DP-S-Script/Dps_A/BaseClass/ScriptManager/ScriptManager.nut

1208 lines
48 KiB
Plaintext

/*
文件名:ScriptManager.nut
路径:Dps_A/BaseClass/ScriptManager/ScriptManager.nut
创建日期:2024-10-11 12:24
文件用途:pvf 管理器
*/
class Script {
constructor(Path = "/home/neople/game/Script.pvf") {
print("正在初始化PVF...");
local StartTime = time();
//文件
local FileIo = null;
try {
FileIo = file(Path, "rb");
} catch (exception) {
error("打不开Script文件!");
}
if (!FileIo) return;
local FileRo = BlobEx(FileIo.readblob(FileIo.len()));
InitPvfTreeHeader(FileRo);
FileIo.close();
InitStringBin(FileRo);
InitLoadString(FileRo);
ScriptData.IO = FileRo;
ScriptData.Init();
print("PVF初始化完毕!!!");
print("用时: " + (time() - StartTime) + "秒");
}
function charPtrToInt(arr) {
local value = ((arr[0]) << 0) | ((arr[1]) << 8) | ((arr[2]) << 16) | ((arr[3]) << 24);
return value;
}
function CrcDecode(Ro, Length, crc32) {
local num = 0x81A79011;
for (local i = 0; i< Length; i += 4) {
local Pos = Ro.tell();
local anInt = charPtrToInt([Ro[Pos], Ro[Pos + 1], Ro[Pos + 2], Ro[Pos + 3]]);
local val = (anInt ^ num ^ crc32);
local jiemi = (val >>> 6) | ((val << (32 - 6)) & 0xFFFFFFFF);
Ro[Pos] = ((jiemi >>> 0) & 0xFF);
Ro[Pos + 1] = ((jiemi >>> 8) & 0xFF);
Ro[Pos + 2] = ((jiemi >>> 16) & 0xFF);
Ro[Pos + 3] = ((jiemi >>> 24) & 0xFF);
Ro.seek(4, 'c');
}
}
//初始化PVF文件树
function InitPvfTreeHeader(HeaderRo) {
//读取UUID的长度
local UUID_LENGTH = HeaderRo.GetInt();
//UUID 读 1 - 36位 构造 UTF8 string
local UUID = HeaderRo.GetString(UUID_LENGTH);
//版本号
local Version = HeaderRo.GetInt();
// 文件路径数据的大小
local AlignedIndexHeaderSize = HeaderRo.GetInt();
// 解密密钥
local IndexHeaderCrc = HeaderRo.GetInt();
// 文件数量
local IndexSize = HeaderRo.GetInt();
local FristPos = HeaderRo.tell();
CrcDecode(HeaderRo, AlignedIndexHeaderSize, IndexHeaderCrc)
// HeaderRo.CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc);
local CurrPos = 0;
ScriptData.StartPos = AlignedIndexHeaderSize + 56;
for (local i = 0; i< IndexSize; i++) {
HeaderRo.seek(FristPos + CurrPos);
local FileNumber = HeaderRo.GetInt();
local FilePathLength = HeaderRo.GetInt();
local FileName = HeaderRo.GetString(FilePathLength);
local FileLength = HeaderRo.GetInt();
local Cre32 = HeaderRo.GetInt();
local RelativeOffset = HeaderRo.GetInt();
if (FileLength > 0) {
local RealFileLength = (FileLength + 3) & 4294967292;
ScriptData.PvfFileInfo[FileName] <- {
ROffset = RelativeOffset,
Cr32 = Cre32,
Length = RealFileLength,
DecodeFlag = 0
}
}
CurrPos += 20;
CurrPos += FilePathLength;
}
}
function InitStringBin(Ro) {
local Info = ScriptData.GetFileInfo("stringtable.bin");
if (!Info) return;
Ro.seek(ScriptData.StartPos + Info.ROffset);
CrcDecode(Ro, Info.Length, Info.Cr32);
//解密完需要重新调整指针位置
Ro.seek(ScriptData.StartPos + Info.ROffset);
local FileHPos = Ro.tell();
local Count = Ro.GetInt();
local CurrentIndex = 0;
for (local i = 0; i< Count; i++) {
Ro.seek(FileHPos + CurrentIndex * 4 + 4);
local StartPos = Ro.GetInt();
local EndPos = Ro.GetInt();
local Len = EndPos - StartPos;
Ro.seek(FileHPos + StartPos + 4);
local Str = Ro.GetString(Len);
ScriptData.BinString[CurrentIndex] <- Str;
CurrentIndex++;
}
ScriptData.RemoveFileInfo("stringtable.bin");
// print("初始化StringTable完成,数量: " + ScriptData.BinString.len());
}
function InitLoadString(Ro) {
local Info = ScriptData.GetFileInfo("n_string.lst");
if (!Info) return;
Ro.seek(ScriptData.StartPos + Info.ROffset);
CrcDecode(Ro, Info.Length, Info.Cr32);
//解密完需要重新调整指针位置
Ro.seek(ScriptData.StartPos + Info.ROffset);
local FileHPos = Ro.tell();
local Flag = Ro.GetUShort();
// print("Flag :" + Flag);
local i = 2;
while (i< Info.Length) {
if ((Info.Length - i) >= 10) {
Ro.seek(FileHPos + i + 6);
local FindKey = Ro.GetInt();
local Key = ScriptData.GetBinString(FindKey);
if (Key) {
local FileInfo = ScriptData.GetFileInfo(Key.tolower());
Ro.seek(ScriptData.StartPos + FileInfo.ROffset);
CrcDecode(Ro, FileInfo.Length, FileInfo.Cr32);
//解密完需要重新调整指针位置
Ro.seek(ScriptData.StartPos + FileInfo.ROffset);
local Str = Ro.GetString(FileInfo.Length);
local StrArr = split(Str, "\r\n");
foreach(index, strobj in StrArr) {
if (strobj.find(">") != null) {
local strobjarr = split(strobj, ">");
if (strobjarr.len() > 1)
ScriptData.LoadString[strobjarr[0]] <- strobjarr[1];
}
}
ScriptData.RemoveFileInfo(Key.tolower());
}
} else break;
i += 10;
}
ScriptData.RemoveFileInfo("n_string.lst");
// print("初始化LoadString完成,数量: " + ScriptData.LoadString.len());
}
}
class GlobaData {
//加载完成的Flag
InitFlag = false;
//PVF的文件解析集合
PvfFileInfo = null;
//PVF文件的开始下标
StartPos = null;
//PVF文件的IO
IO = null;
AniPathTable = null;
Ani = null;
LoadString = null;
BinString = null;
//怪物List
MonsterLst = null;
MonsterConfigLst = null;
//地图List
MapLst = null;
MapConfigLst = null;
//地板List
TileConfigLst = null;
//被动对象List
PassiveObjectLst = null;
PassiveObjectConfigLst = null;
//角色配置信息路径List
CharacterLst = null;
CharacterConfigLst = null;
//装备List
EquipmentLst = null;
EquipmentConfigLst = null;
//APC List
AICharacterLst = null;
AICharacterConfigLst = null;
//Atk List
AttackinfoConfigLst = null;
constructor() {
PvfFileInfo = {};
Ani = {};
AniPathTable = {};
LoadString = {};
BinString = {};
MonsterConfigLst = {};
MapConfigLst = {};
TileConfigLst = {};
PassiveObjectConfigLst = {};
CharacterConfigLst = {};
EquipmentConfigLst = {};
AICharacterConfigLst = {};
AttackinfoConfigLst = {};
}
function InitList(Path, ErrorStr, TableName) {
this[TableName] = {};
local HeaderPath = Path + "/";
local Info = ScriptData.GetFileInfo(HeaderPath + Path + ".lst");
if (!Info) return error(ErrorStr + "列表不存在。加载失败!");
IO.seek(ScriptData.StartPos + Info.ROffset);
local FileHPos = IO.tell();
local Flag = IO.GetUShort();
local i = 2;
while (i< Info.Length) {
if ((Info.Length - i) >= 10) {
IO.seek(FileHPos + i + 1);
local Id;
if (Path == "equipment") {
Id = IO.GetInt();
IO.seek(1, 'c');
} else {
Id = IO.GetShort();
IO.seek(3, 'c');
}
local FindKey = IO.readn('i');
local Key = ScriptData.GetBinString(FindKey);
Key = HeaderPath + Key.tolower();
this[TableName][Id] <- Key;
} else break;
i += 10;
}
}
function Init() {
//初始化怪物列表
InitList("monster", "怪物", "MonsterLst");
//初始化地图列表
InitList("map", "地图", "MapLst");
//初始化被动对象列表
InitList("passiveobject", "被动对象", "PassiveObjectLst");
//初始化角色配置信息列表
InitList("character", "角色配置", "CharacterLst");
//初始化角色配置信息列表
InitList("equipment", "装备", "EquipmentLst");
// Util.PrintTable(EquipmentLst);
//初始化APC列表
InitList("aicharacter", "APC", "AICharacterLst");
ScriptData.InitFlag = true;
}
function RegRealPath(Path) {
if (Path.find("../") != null) {
while (true) {
local rbuf = regexp("[^/]+/../");
local Ret = rbuf.capture(Path);
if (Ret) {
Path = Path.slice(0, Ret[0].begin) + Path.slice(Ret[0].end);
} else {
return Path;
}
}
}
return Path;
}
function GetFileInfo(Path) {
Path = RegRealPath(Path);
if (!PvfFileInfo.rawin(Path)) return null;
else {
//如果是未解密的需要先解密
if (Path != "stringtable.bin" && Path != "n_string.lst" && !(endswith(Path, ".str")) && PvfFileInfo[Path].DecodeFlag == 0) {
local Info = PvfFileInfo[Path];
IO.seek(StartPos + Info.ROffset);
Script.CrcDecode(IO, Info.Length, Info.Cr32);
// 解密完需要重新调整指针位置
// FileRo.seek(StartPos + Info.ROffset);
}
return PvfFileInfo[Path];
}
}
function RemoveFileInfo(Path) {
if (PvfFileInfo.rawin(Path)) {
delete PvfFileInfo[Path]
}
}
function GetAni(Path) {
Path = RegRealPath(Path);
if (Path in Ani)
return Ani[Path];
else {
try {
IO.seek(AniPathTable[Path].Pos);
CrcDecode(IO, AniPathTable[Path].Length, AniPathTable[Path].Cr32);
IO.seek(AniPathTable[Path].Pos);
Ani[Path] <- InitPvfAni(IO);
return Ani[Path];
} catch (exception) {
print(Path + "找不到文件!");
error(exception);
}
// print(Path + "找不到文件!");
return null;
}
}
function GetBinString(Path) {
if (Path in BinString)
return BinString[Path];
else {
print(Path + "找不到文件!");
return null;
}
}
function GetLoadString(Path) {
if (Path in LoadString)
return LoadString[Path];
else {
print(Path + "找不到文件!");
return null;
}
}
function UnpackData(FilePos, i) {
local out = "";
IO.seek(FilePos + i); //内容指示位
local currentByte = IO.readn('c'); //内容指示位
local after = IO.GetInt();
switch (currentByte) {
case 10: {
IO.seek(FilePos + i - 4);
local Before = IO.GetInt();
local Buf = GetBinString(after);
if (!Buf) {
Buf = "";
} else {
Buf = "<" + Before + "::" + Buf + "`" + GetLoadString(Buf) + "`>";
}
Buf = Buf + "\r\n";
out += Buf;
break;
}
case 2: {
out += after + '\t';
break;
}
case 4: {
local Bbuf = blob(4);
Bbuf.writen(after, 'i');
Bbuf.seek(0);
local Buf = Bbuf.readn('f');
out += after + '\t';
break;
}
case 6:
case 8:
case 7:
case 5: {
local Buf = GetBinString(after);
if (!Buf) Buf = "";
return Buf;
}
default:
out += "";
break;
}
return out;
}
function Decompile_attackinfo(DirPath, FileRealName, Info) {
local AttackinfoAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//攻击类型 攻击属性类型 损伤反应
if (str == "[attack type]" || str == "[elemental property]" || str == "[damage reaction]") {
local Ret = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt[str.slice(1, -1)] <- Ret.slice(1, -1);
}
//武器伤害应用 推力 抬起
else if (str == "[weapon damage apply]" || str == "[push aside]" || str == "[lift up]") {
local Ret = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt[str.slice(1, -1)] <- ((Ret.tointeger() - 9).tofloat());
}
//打击音效
else if (str == "[hit wav]") {
local Ret = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt[str.slice(1, -1)] <- Ret;
}
//打击效果
else if (str == "[hit info]") {
AttackinfoAtt["hit_info"] <- {};
local HitType = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt["hit_info"].Type <- HitType;
local Ret = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt["hit_info"].BloodType <- Ret.slice(1, -1);
local Value0 = UnpackData(FilePos, i);
i += 5;
local Value1 = UnpackData(FilePos, i);
i += 5;
AttackinfoAtt["hit_info"].Value <- [Value0, Value1];
}
} else break;
}
}
return AttackinfoAtt;
}
//获取ATK
function GetAtk(Path) {
Path = RegRealPath(Path);
if (AttackinfoConfigLst.rawin(Path)) return AttackinfoConfigLst[Path];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
if (Info) {
local InfoObj = Decompile_attackinfo(DirPath, FileRealName, Info);
AttackinfoConfigLst[Path] <- InfoObj;
return InfoObj;
} else error(Path + " AttackInfo不存在!");
}
function Decompile_monster(DirPath, FileRealName, Info) {
local MonsterAtt = {};
//属性表
MonsterAtt.Attributes <- {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//大小
if (str == "[size]") {
local gx = UnpackData(FilePos, i);
i += 5;
local gy = UnpackData(FilePos, i);
i += 5;
MonsterAtt.size <- {
x = gx.tointeger(),
y = gy.tointeger()
};
}
//属性
else if (str == "[HpMax]" || str == "[Attack]" || str == "[Speed]" || str == "[Defense]" || str == "[DeployCost]" || str == "[Resilience]" || str == "[FirePower]" || str == "[IcePower]" || str == "[LightningPower]" || str == "[DarkPower]" || str == "[FireResistance]" || str == "[IceResistance]" || str == "[LightningResistance]" || str == "[DarkResistance]") {
local RealKey = str.slice(1, str.len() - 1);
MonsterAtt.Attributes[RealKey] <- UnpackData(FilePos, i).tointeger() - 9;
i += 5;
}
// //属性
// else if (str == "[ability]") {
// MonsterAtt.ability <- {};
// while (true) {
// local Ret = UnpackData(FilePos, i);
// i += 5;
// if (Ret == "[/ability]") break;
// if (endswith(Ret, "]")) {
// local Value = UnpackData(FilePos, i);
// i += 5;
// MonsterAtt.ability[Ret.slice(1, Ret.len() - 1)] <- Value.tointeger();
// }
// }
// }
//标签
else if (str == "[category]") {
MonsterAtt.category <- {};
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/category]") break;
if (endswith(Ret, "]")) {
MonsterAtt.category[Ret.slice(1, Ret.len() - 1)] <- true;
}
}
}
//等级 移动速度 攻击速度 释放速度 硬直 重量
else if (str == "[level]" || str == "[move speed]" || str == "[attack speed]" || str == "[cast speed]" || str == "[hit recovery]" || str == "[weight]") {
local RealKey = str.slice(1, str.len() - 1);
MonsterAtt[RealKey] <- {};
MonsterAtt[RealKey].min <- UnpackData(FilePos, i).tointeger();
i += 5;
MonsterAtt[RealKey].max <- UnpackData(FilePos, i).tointeger();
i += 5;
}
//视力 针对最近 好战 攻击延迟(僵值) 名字
else if (str == "[sight]" || str == "[targeting nearest]" || str == "[warlike]" || str == "[attack delay]") {
local RealKey = str.slice(1, str.len() - 1);
MonsterAtt[RealKey] <- UnpackData(FilePos, i).tointeger();
i += 5;
}
//名字
else if (str == "[name]") {
local RealKey = str.slice(1, str.len() - 1);
MonsterAtt[RealKey] <- UnpackData(FilePos, i);
i += 5;
}
//头像
else if (str == "[face image]") {
local buf1 = UnpackData(FilePos, i);
i += 5;
local buf2 = UnpackData(FilePos, i);
i += 5;
MonsterAtt.face <- {
path = buf1,
index = buf2
};
}
//Ani
else if (str == "[animotion]") {
MonsterAtt.animotion <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/animotion]") break;
MonsterAtt.animotion.append(DirPath + Ret.tolower());
}
}
//Atk
else if (str == "[attack info]") {
MonsterAtt.attackinfo <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/attack info]") break;
MonsterAtt.attackinfo.append(DirPath + Ret.tolower());
}
}
} else break;
}
}
return MonsterAtt;
}
function GetMonster(Idx) {
if (MonsterLst.rawin(Idx)) {
local Path = MonsterLst[Idx];
if (MonsterConfigLst.rawin(Path)) return MonsterConfigLst[Path];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_monster(DirPath, FileRealName, Info);
MonsterConfigLst[Path] <- InfoObj;
return InfoObj;
} else error(Idx + " 号怪物不存在!");
}
function Decompile_map(DirPath, FileRealName, Info) {
local MapAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//远景速度 中景速度 近景速度
if (str == "[far sight scroll]" || str == "[middle sight scroll]" || str == "[near sight scroll]") {
local RealKey = str.slice(1, str.len() - 1);
MapAtt[RealKey] <- UnpackData(FilePos, i).tointeger();
i += 5;
}
//名字
else if (str == "[map name]" || str == "[map type]") {
local RealKey = str.slice(1, str.len() - 1);
MapAtt[RealKey] <- UnpackData(FilePos, i);
i += 5;
}
//地板
else if (str == "[tile]") {
MapAtt.tile <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/tile]") break;
MapAtt.tile.append(DirPath + Ret.tolower());
}
}
//音乐
else if (str == "[sound]") {
MapAtt.sound <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/sound]") break;
MapAtt.sound.append(Ret);
}
}
//对象
else if (str == "[passive object]") {
MapAtt.passiveobject <- [];
while (true) {
local Id = UnpackData(FilePos, i);
i += 5;
if (Id == "[/passive object]") break;
local XPos = UnpackData(FilePos, i);
i += 5;
local YPos = UnpackData(FilePos, i);
i += 5;
local ZPos = UnpackData(FilePos, i);
i += 5;
local Tbuf = {
id = Id.tointeger() - 9,
x = XPos.tointeger() - 9,
y = YPos.tointeger() - 9,
z = ZPos.tointeger() - 9,
}
MapAtt.passiveobject.append(Tbuf);
}
}
//Ani
else if (str == "[animation]") {
MapAtt.animation <- [];
while (true) {
local Path = UnpackData(FilePos, i);
i += 5;
if (Path == "[/animation]") break;
local Layer = UnpackData(FilePos, i);
i += 5;
local XPos = UnpackData(FilePos, i).tointeger();
i += 5;
local YPos = UnpackData(FilePos, i).tointeger();
i += 5;
local ZPos = UnpackData(FilePos, i).tointeger();
i += 5;
local Tbuf = {
path = DirPath + Path.tolower(),
layer = Layer,
x = XPos - 9,
y = YPos - 9,
z = ZPos - 9
}
MapAtt.animation.append(Tbuf);
}
}
//背景动画
else if (str == "[background animation]") {
MapAtt.backgroundani <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/background animation]") break;
if (Ret == "[ani info]") {
local AniBuf = {};
while (true) {
local Key = UnpackData(FilePos, i);
i += 5;
if (Key == "[/ani info]") break;
local Value = UnpackData(FilePos, i);
i += 5;
if (Key == "[filename]") Value = DirPath + Value.tolower();
AniBuf[Key] <- Value;
}
MapAtt.backgroundani.append(AniBuf);
}
}
}
} else break;
}
}
return MapAtt;
}
function GetMap(Idx) {
if (MapLst.rawin(Idx)) {
local Path = MapLst[Idx];
if (MapConfigLst.rawin(Path)) return MapConfigLst[Path];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_map(DirPath, FileRealName, Info);
MapConfigLst[Path] <- InfoObj;
return InfoObj;
} else error(Idx + " 号地图不存在!");
}
function Decompile_tile(Info) {
local TileAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
if (str == "[IMAGE]") {
local gpath = "sprite/" + UnpackData(FilePos, i).tolower();
i += 5;
local gidx = UnpackData(FilePos, i).tointeger() - 9;
i += 5;
TileAtt.image <- {
path = gpath,
idx = gidx
}
}
//偏移
else if (str == "[img pos]") {
TileAtt.pos <- UnpackData(FilePos, i).tointeger();
i += 5;
}
} else break;
}
}
return TileAtt;
}
//读取地板
function GetTile(Path) {
if (TileConfigLst.rawin(Path)) return TileConfigLst[Path];
local Info = GetFileInfo(Path);
local InfoObj = Decompile_tile(Info);
TileConfigLst[Path] <- InfoObj;
return InfoObj;
}
function Decompile_passiveobject(DirPath, FileRealName, Info) {
local PassiveobjectAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//大小
if (str == "[size]") {
local gx = UnpackData(FilePos, i);
i += 5;
local gy = UnpackData(FilePos, i);
i += 5;
PassiveobjectAtt.size <- {
x = gx.tointeger(),
y = gy.tointeger()
};
}
//浮动高度 图层 通过类型 名字
else if (str == "[floating height]" || str == "[layer]" || str == "[pass type]" || str == "[name]") {
local RealKey = str.slice(1, str.len() - 1);
PassiveobjectAtt[RealKey] <- UnpackData(FilePos, i);
i += 5;
}
//Ani
else if (str == "[animotion]") {
PassiveobjectAtt.animotion <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/animotion]") break;
PassiveobjectAtt.animotion.append(DirPath + Ret.tolower());
}
}
//Atk
else if (str == "[attack info]") {
PassiveobjectAtt.attackinfo <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/attack info]") break;
PassiveobjectAtt.attackinfo.append(DirPath + Ret.tolower());
}
}
//回调函数
else if (str == "[create function]" || str == "[proc function]" || str == "[destroy function]" || str == "[attack function]") {
local RealKey = str.slice(1, str.len() - 1);
local Path = UnpackData(FilePos, i);
i += 5;
// Path = "sqr/PassiveObjectFunc/" + Path + ".nut";
// PassiveobjectAtt[RealKey] <- dofile(Path);
Path = "PassiveObject_" + Path;
if (getroottable().PassiveObjectFunction.rawin(Path))
PassiveobjectAtt[RealKey] <- getroottable().PassiveObjectFunction[Path];
}
} else break;
}
}
return PassiveobjectAtt;
}
//获取被动对象
function GetPassiveObject(Idx) {
if (PassiveObjectLst.rawin(Idx)) {
local Path = PassiveObjectLst[Idx];
if (PassiveObjectConfigLst.rawin(Path)) return PassiveObjectConfigLst[Path];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_passiveobject(DirPath, FileRealName, Info);
PassiveObjectConfigLst[Path] <- InfoObj;
return InfoObj;
} else error(Idx + " 号被动对象不存在!");
}
function Decompile_character(DirPath, FileRealName, Info) {
local CharacterAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//职业
if (str == "[job]") {
local RealKey = str.slice(1, -1);
CharacterAtt[RealKey] <- UnpackData(FilePos, i).slice(1, -1);
i += 5;
}
//基础属性
else if (str == "[HP MAX]]" || str == "[MP MAX]]" || str == "[physical attack]]" || str == "[physical defense]]" || str == "[magical attack]]" || str == "[magical defense]]" || str == "[inventory limit]]" || str == "[MP regen speed]]" || str == "[move speed]]" || str == "[attack speed]]" || str == "[cast speed]]" || str == "[hit recovery]]" || str == "[jump power]]" || str == "[weight]]" || str == "[jump speed]]") {
local RealKey = str.slice(1, str.len() - 1);
CharacterAtt[RealKey] <- UnpackData(FilePos, i).tofloat();
i += 5;
}
//基础Ani
else if (str == "[waiting motion]" || str == "[move motion]" || str == "[sit motion]" || str == "[damage motion 1]" || str == "[damage motion 2]" || str == "[down motion]" || str == "[overturn motion]" || str == "[jump motion]" || str == "[jumpattack motion]" || str == "[rest motion]" || str == "[throw motion 1-1]" || str == "[throw motion 1-2]" || str == "[throw motion 2-1]" || str == "[throw motion 2-2]" || str == "[throw motion 3-1]" || str == "[throw motion 3-2]" || str == "[throw motion 4-1]" || str == "[throw motion 4-2]" || str == "[dash motion]" || str == "[dashattack motion]" || str == "[getitem motion]" || str == "[buff motion]" || str == "[simple rest motion]" || str == "[simple move motion]" || str == "[back motion]") {
local RealKey = str.slice(1, str.len() - 1);
CharacterAtt[RealKey] <- (UnpackData(FilePos, i).tolower());
i += 5;
}
//普攻Ani
else if (str == "[attack motion]") {
CharacterAtt.attack_motion <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/attack motion]") break;
CharacterAtt.attack_motion.append(Ret.tolower());
}
}
//进阶Ani
else if (str == "[etc motion]") {
CharacterAtt.etc_motion <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/etc motion]") break;
CharacterAtt.etc_motion.append(Ret.tolower());
}
}
//基础Atk
else if (str == "[jumpattack info]" || str == "[dashattack info]") {
local RealKey = str.slice(1, str.len() - 1);
CharacterAtt[RealKey] <- (DirPath + UnpackData(FilePos, i).tolower());
i += 5;
}
//普攻Atk
else if (str == "[attack info]") {
CharacterAtt.attack_info <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/attack info]") break;
CharacterAtt.attack_info.append(DirPath + Ret.tolower());
}
}
//进阶Atk
else if (str == "[etc attack info]") {
CharacterAtt.etc_attack_info <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/etc attack info]") break;
CharacterAtt.etc_attack_info.append(DirPath + Ret.tolower());
}
}
} else break;
}
}
return CharacterAtt;
}
//获取角色配置
function GetCharacter(Idx) {
//如果已经读取过配置 直接返回配置
if (CharacterConfigLst.rawin(Idx)) return CharacterConfigLst[Idx];
if (CharacterLst.rawin(Idx)) {
local Path = CharacterLst[Idx];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_character(DirPath, FileRealName, Info);
InfoObj.DirPath <- DirPath;
CharacterConfigLst[Idx] <- InfoObj;
// Util.PrintTable(InfoObj);
return InfoObj;
} else error(Idx + " 号角色配置不存在!");
}
function Decompile_equipment(DirPath, FileRealName, Info) {
local EquipmentAtt = {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//名称
if (str == "[name]") {
local RealKey = str.slice(1, str.len() - 1);
EquipmentAtt[RealKey] <- UnpackData(FilePos, i);
i += 5;
}
//grade 套装Id
else if (str == "[grade]" || str == "[part set index]" || str == "[anti evil]" || str == "[sb dongcai]") {
local RealKey = str.slice(1, str.len() - 1);
EquipmentAtt[RealKey] <- UnpackData(FilePos, i).tointeger() - 9;
i += 5;
}
//适用角色
else if (str == "[usable job]") {
EquipmentAtt.usable_job <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/usable job]") break;
EquipmentAtt.usable_job.append(Ret.slice(1, -1).tolower());
}
}
//图标
else if (str == "[icon]") {
EquipmentAtt.icon <- {};
local Ret = UnpackData(FilePos, i);
i += 5;
EquipmentAtt.icon.path <- Ret.tolower();
Ret = UnpackData(FilePos, i);
i += 5;
EquipmentAtt.icon.index <- Ret.tointeger();
}
//装备类型
else if (str == "[equipment type]") {
EquipmentAtt.type <- {};
local Ret = UnpackData(FilePos, i);
i += 5;
EquipmentAtt.type.path <- Ret.tolower().slice(1, -1);
Ret = UnpackData(FilePos, i);
i += 5;
EquipmentAtt.type.index <- Ret.tointeger();
}
//Ani
else if (str == "[animation job]") {
local Job = UnpackData(FilePos, i).slice(1, -1);
i += 5;
EquipmentAtt["Ani_" + Job] <- {};
i += 5;
local Index1 = UnpackData(FilePos, i).tointeger() - 9;
i += 5;
local Index2 = UnpackData(FilePos, i).tointeger() - 9;
i += 5;
EquipmentAtt["Ani_" + Job].variation <- [Index1, Index2];
EquipmentAtt["Ani_" + Job].layer_variation <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[animation job]" || (endswith(Ret, "]") && Ret != "[equipment ani script]" && Ret != "[layer variation]")) {
i -= 5;
break;
} else if (Ret == "[layer variation]") {
local InfoBuf = {};
InfoBuf.Zorder <- UnpackData(FilePos, i).tointeger() - 9;
i += 5;
InfoBuf.Path <- UnpackData(FilePos, i);
i += 5;
EquipmentAtt["Ani_" + Job].layer_variation.append(InfoBuf);
}
}
}
} else break;
}
}
return EquipmentAtt;
}
//获取装备配置
function GetEquipment(Idx) {
//如果已经读取过配置 直接返回配置
if (EquipmentConfigLst.rawin(Idx)) return EquipmentConfigLst[Idx];
if (EquipmentLst.rawin(Idx)) {
local Path = EquipmentLst[Idx];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_equipment(DirPath, FileRealName, Info);
InfoObj.DirPath <- DirPath;
EquipmentConfigLst[Idx] <- InfoObj;
// Util.PrintTable(InfoObj);
return InfoObj;
} else error(Idx + " 号装备配置不存在!");
}
function Decompile_aicharacter(DirPath, FileRealName, Info) {
local AICharacterAtt = {};
//属性表
AICharacterAtt.Attributes <- {};
IO.seek(StartPos + Info.ROffset);
local FilePos = IO.tell();
local out = "";
if (Info.Length >= 7) {
//以5为单步从第二位开始遍历字节
local i = 2;
while (true) {
//到最后了就不处理了防止内存越界
if (i< Info.Length && Info.Length - i >= 5) {
local str = UnpackData(FilePos, i);
i += 5;
//名称
if (str == "[name]") {
local RealKey = str.slice(1, str.len() - 1);
AICharacterAtt[RealKey] <- UnpackData(FilePos, i);
i += 5;
}
//属性
else if (str == "[HpMax]" || str == "[Attack]" || str == "[Speed]" || str == "[Defense]" || str == "[DeployCost]" || str == "[Resilience]" || str == "[FirePower]" || str == "[IcePower]" || str == "[LightningPower]" || str == "[DarkPower]" || str == "[FireResistance]" || str == "[IceResistance]" || str == "[LightningResistance]" || str == "[DarkResistance]") {
local RealKey = str.slice(1, str.len() - 1);
AICharacterAtt.Attributes[RealKey] <- UnpackData(FilePos, i).tointeger() - 9;
i += 5;
}
//装备
else if (str == "[equipment]") {
AICharacterAtt.equipment <- [];
while (true) {
local Ret = UnpackData(FilePos, i);
i += 5;
if (Ret == "[/equipment]") break;
AICharacterAtt.equipment.append(Ret.tointeger() - 9);
}
}
//基础信息
else if (str == "[minimum info]") {
AICharacterAtt["minimum info"] <- [];
for (local o = 0; o< 16; o++) {
local Buf = UnpackData(FilePos, i);
i += 5;
if (o == 0 || o == 12) {
AICharacterAtt["minimum info"].append(Buf);
} else {
AICharacterAtt["minimum info"].append(Buf.tointeger() - 9);
}
}
}
} else break;
}
}
return AICharacterAtt;
}
//获取APC配置
function GetAICharacter(Idx) {
//如果已经读取过配置 直接返回配置
if (AICharacterConfigLst.rawin(Idx)) return AICharacterConfigLst[Idx];
if (AICharacterLst.rawin(Idx)) {
local Path = AICharacterLst[Idx];
local Pos = 0;
while (true) {
local Buf = Path.find("/", Pos + 1);
if (Buf != null)
Pos = Buf;
else break;
}
local DirPath = Path.slice(0, Pos + 1);
local FileRealName = Path.slice(Pos + 1);
local Info = GetFileInfo(Path);
local InfoObj = Decompile_aicharacter(DirPath, FileRealName, Info);
InfoObj.DirPath <- DirPath;
AICharacterConfigLst[Idx] <- InfoObj;
// Util.PrintTable(InfoObj);
return InfoObj;
} else error(Idx + " 号APC配置不存在!");
}
}
getroottable().ScriptData <- GlobaData();