/* 文件名: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();