1208 lines
48 KiB
Plaintext
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(); |