diff --git a/Dps_A/BaseClass/BlobExClass/BlobExClass.nut b/Dps_A/BaseClass/BlobExClass/BlobExClass.nut new file mode 100644 index 0000000..778ac15 --- /dev/null +++ b/Dps_A/BaseClass/BlobExClass/BlobExClass.nut @@ -0,0 +1,58 @@ +/* +文件名:BlobExClass.nut +路径:BaseClass/BaseTool/BlobExClass.nut +创建日期:2024-05-07 17:34 +文件用途:拓展的Blob类 +*/ +class BlobEx extends blob { + + constructor(BaseBlob) { + base.constructor(BaseBlob.len()); + writeblob(BaseBlob); + } + + function writeblob(B) { + base.writeblob(B); + seek(0); + } + + function GetUShort() { + return readn('s'); + } + + function GetShort() { + return readn('w'); + } + + function charPtrToInt(arr) { + local value = ((arr[0]) << 0) | + ((arr[1]) << 8) | + ((arr[2]) << 16) | + ((arr[3]) << 24); + return value; + } + + // function GetInt() { + // local CurTPos = tell(); + // local Ret = charPtrToInt([this[CurTPos], this[CurTPos + 1], this[CurTPos + 2], this[CurTPos + 3]]); + // seek(4, 'c'); + // return Ret; + // } + + function GetInt() { + return readn('i'); + } + + function Get256() { + local Buf = readn('c'); + return (256.0 + Buf.tofloat()) % 256.0; + } + + function GetFloat() { + return readn('f'); + } + + function GetString(count) { + return stream_myreadstring(count); + } +} \ No newline at end of file diff --git a/Dps_A/BaseClass/GameManagerClass/GameManagerClass.nut b/Dps_A/BaseClass/GameManagerClass/GameManagerClass.nut index 0e3c56c..31f0d95 100644 --- a/Dps_A/BaseClass/GameManagerClass/GameManagerClass.nut +++ b/Dps_A/BaseClass/GameManagerClass/GameManagerClass.nut @@ -87,6 +87,51 @@ class GameManager extends Base_C_Object { print("请注意如果你不处于DP-S开发环境,请关闭此功能,以免对性能造成影响"); Sq_AutoReload(Path); } + + //开启时装镶嵌 + function FixAvatarUseJewel() { + //时装镶嵌修复 + _AvatarUseJewel_Object <- AvatarUseJewel(); + } + + //修复下线卡城镇 + function FixSaveTown() { + Cb_Set_Charac_Info_Detail_Enter_Func._FixSaveTown_ <- function(arg) { + local curArea = NativePointer(arg[3]).add(34).readS8(); + if (curArea == 12 || curArea == 13) { + NativePointer(arg[3]).add(34).writeS8(11); + } + } + } + + //修复绝望金币异常 + function FixDespairGold() { + getroottable()._FixDespairGold_Data_ <- {}; + Cb_UseAncientDungeonItems_Enter_Func._FixDespairGold_ <- function(arg) { + local DgnObj = Dungeon(arg[1]); + local DgnIndex = DgnObj.GetId(); + if ((DgnIndex >= 11008) && (DgnIndex <= 11107)) { + getroottable()._FixDespairGold_Data_[arg[1]] <- NativePointer(arg[1]).add(2044).readS8(); + NativePointer(arg[1]).add(2044).writeS8(0); + } + } + Cb_UseAncientDungeonItems_Leave_Func._FixDespairGold_ <- function(arg) { + local DgnObj = Dungeon(arg[1]); + local DgnIndex = DgnObj.GetId(); + if ((DgnIndex >= 11008) && (DgnIndex <= 11107)) { + //绝望之塔 不再扣除金币 + NativePointer(arg[1]).add(2044).writeS8(getroottable()._FixDespairGold_Data_[arg[1]]); + getroottable()._FixDespairGold_Data_.rawdelete(arg[1]); + } + } + } + + //修复绝望之塔通关后可以用门票继续进入 + function FixDespairDungeon() { + Cb_User_GetLastClearTime_Leave_Func._FixDespairDungeon_ <- function(arg) { + return 0; + } + } } //热重载 function _Reload_List_Write_(Path) { diff --git a/Dps_A/BaseClass/IOClass/IOClass.nut b/Dps_A/BaseClass/IOClass/IOClass.nut index 5512347..721a2e5 100644 --- a/Dps_A/BaseClass/IOClass/IOClass.nut +++ b/Dps_A/BaseClass/IOClass/IOClass.nut @@ -16,6 +16,7 @@ class IO extends Base_C_Object { _Fseek_Address = Module.getExportByName(null, "fseek"); _Ftell_Address = Module.getExportByName(null, "ftell"); _Rewind_Address = Module.getExportByName(null, "rewind"); + _Flush_Address = Module.getExportByName(null, "fflush"); @@ -25,7 +26,7 @@ class IO extends Base_C_Object { local FileObj = Sq_CallFunc(_Fopen_Address, "pointer", ["pointer", "pointer"], Str_Ptr(FileName), Str_Ptr(Modes)); if (FileObj) { base.constructor(FileObj); - } else error("文件打开错误! FileName: " + FileName); + } else throw("文件打开错误! FileName: " + FileName); } //读取一行 @@ -68,6 +69,9 @@ class IO extends Base_C_Object { Sq_CallFunc(_Fputs_Address, "int", ["pointer", "pointer"], Buffer.C_Object, this.C_Object); } + function Flush() { + Sq_CallFunc(_Flush_Address, "pointer", ["pointer"], this.C_Object); + } //关闭文件 function Close() { diff --git a/Dps_A/BaseClass/InvenClass/InvenClass.nut b/Dps_A/BaseClass/InvenClass/InvenClass.nut index fc6f2fd..d9867e2 100644 --- a/Dps_A/BaseClass/InvenClass/InvenClass.nut +++ b/Dps_A/BaseClass/InvenClass/InvenClass.nut @@ -72,4 +72,9 @@ class Inven extends Base_C_Object { SUser.SendUpdateItemList(1, 0, Slot); return Ret; } + + //获取时装管理器 + function GetAvatarItemMgr() { + return Sq_CallFunc(S_Ptr("0x80DD576"), "pointer", ["pointer"], this.C_Object); + } } \ No newline at end of file diff --git a/Dps_A/BaseClass/ItemClass/ItemClass.nut b/Dps_A/BaseClass/ItemClass/ItemClass.nut index d0f2af9..2701971 100644 --- a/Dps_A/BaseClass/ItemClass/ItemClass.nut +++ b/Dps_A/BaseClass/ItemClass/ItemClass.nut @@ -125,6 +125,11 @@ class Item extends Base_C_Object { Sq_WriteBlobToAddress(C_Object, Attribute); } + //检查是否为空 + // function IsEmpty() { + // return Sq_CallFunc(S_Ptr("0x811ED66"), "int", ["pointer"], this.C_Object); + // } + //删除道具 function Delete() { Sq_Inven_RemoveItem(C_Object); diff --git a/Dps_A/BaseClass/LogClass/LogClass.nut b/Dps_A/BaseClass/LogClass/LogClass.nut new file mode 100644 index 0000000..23b7eea --- /dev/null +++ b/Dps_A/BaseClass/LogClass/LogClass.nut @@ -0,0 +1,90 @@ +/* +文件名:LogClass.nut +路径:Dps_A/BaseClass/LogClass/LogClass.nut +创建日期:2024-10-10 11:35 +文件用途:日志类 +*/ +class Log { + + //linux创建文件夹 + // function api_mkdir(path) { + // var path_ptr = Memory.allocUtf8String(path); + // if (opendir(path_ptr)) + // return true; + // return mkdir(path_ptr, 0x1FF); + // } + _opendir_Address = Module.getExportByName(null, "opendir"); + _mkdir_Address = Module.getExportByName(null, "mkdir"); + + + Logger = null; + LoggerBuffer = null; + + Coro = null; + + constructor(Info) { + Logger = {}; + LoggerBuffer = {}; + + local DirPath = Str_Ptr("/dp_s/log"); + if (!(Sq_CallFunc(_opendir_Address, "int", ["pointer"], DirPath))) { + Sq_CallFunc(_mkdir_Address, "int", ["pointer", "int"], DirPath, 0x1FF); + } + + //打开文件输出句柄 + foreach(Level, Path in Info) { + + try { + local Io = IO(Path, "a"); + Logger[Level] <- Io; + LoggerBuffer[Level] <- []; + } catch (exception) { + error("日志器初始化失败"); + } + } + + getroottable()._Logger_Object_ <- this; + Cb_timer_dispatch_Func.rawset("__System__Logger__Event", Update.bindenv(this)); + + Coro = newthread(__Write__.bindenv(this)); + } + + + function Put(Type, Message) { + if (getroottable().rawin("_Logger_Object_")) { + if (getroottable()._Logger_Object_.Logger.rawin(Type)) { + getroottable()._Logger_Object_.LoggerBuffer[Type].push(Message); + // getroottable()._Logger_Object_.Logger[Type].Write(Message); + // getroottable()._Logger_Object_.Logger[Type].Flush(); + } else { + error("未知的日志类型"); + } + } else { + error("未初始化日志器"); + } + } + + function __Write__() { + local ret = suspend("no"); + foreach(Type, MessageArr in LoggerBuffer) { + for (local i = 0; i< MessageArr.len(); i++) { + Logger[Type].Write(MessageArr[i]); + Logger[Type].Flush(); + MessageArr.remove(i); + i--; + suspend("no"); + } + } + return "yes"; + } + + function Update() { + local susparam = "noq"; + if (Coro.getstatus() == "idle") susparam = Coro.call(); + else if (Coro.getstatus() == "suspended") susparam = Coro.wakeup(); + + if (susparam == "yes") { + Coro = newthread(__Write__.bindenv(this)); + } + } +} diff --git a/Dps_A/BaseClass/MemoryClass/MemoryClass.nut b/Dps_A/BaseClass/MemoryClass/MemoryClass.nut index e1a2c1e..cfcc8c2 100644 --- a/Dps_A/BaseClass/MemoryClass/MemoryClass.nut +++ b/Dps_A/BaseClass/MemoryClass/MemoryClass.nut @@ -29,6 +29,17 @@ class NativePointer extends Base_C_Object { } } + function Output(Size) { + local Buf = Sq_Point2Blob(this.C_Object, Size); + local Str = "["; + foreach(Value in Buf) { + Str = format("%s%02X", Str, Value); + Str += ","; + } + Str += "]"; + print(Str); + } + function add(intoffset) { this.C_Object = Sq_PointerOperation(this.C_Object, intoffset, "+"); return this; diff --git a/Dps_A/BaseClass/PacketClass/PacketClass.nut b/Dps_A/BaseClass/PacketClass/PacketClass.nut index c97cebb..a7aeafa 100644 --- a/Dps_A/BaseClass/PacketClass/PacketClass.nut +++ b/Dps_A/BaseClass/PacketClass/PacketClass.nut @@ -65,6 +65,40 @@ class Packet extends Base_C_Object { Sq_Packet_Send(SUser.C_Object, this.C_Object); } + + + function GetByte() { + local data = Memory.alloc(1); + if (Sq_CallFunc(S_Ptr("0x858CF22"), "int", ["pointer", "pointer"], this.C_Object, data.C_Object)) { + return data.readS8(); + } + return null; + } + + function GetShort() { + local data = Memory.alloc(2); + if (Sq_CallFunc(S_Ptr("0x858CFC0"), "int", ["pointer", "pointer"], this.C_Object, data.C_Object)) { + return data.readS16(); + } + return null; + } + + function GetInt() { + local data = Memory.alloc(4); + if (Sq_CallFunc(S_Ptr("0x858D27E"), "int", ["pointer", "pointer"], this.C_Object, data.C_Object)) { + return data.readS32(); + } + return null; + } + + function GetBinary(len) { + local data = Memory.alloc(len); + if (Sq_CallFunc(S_Ptr("0x858D3B2"), "int", ["pointer", "pointer"], this.C_Object, data.C_Object)) { + return data; + } + return null; + } + function Delete() { Sq_CallFunc(S_Ptr("0x858DE80"), "void", ["pointer"], this.C_Object); Sq_Delete_Point(this.C_Object); diff --git a/Dps_A/BaseClass/PvfClass/PvfItemClass.nut b/Dps_A/BaseClass/PvfClass/PvfItemClass.nut index ac157b4..57728e6 100644 --- a/Dps_A/BaseClass/PvfClass/PvfItemClass.nut +++ b/Dps_A/BaseClass/PvfClass/PvfItemClass.nut @@ -70,4 +70,9 @@ function PvfItem::GetUsableLevel() { //是否为消耗品 function PvfItem::IsStackable() { return Sq_CallFunc(S_Ptr("0x80f12fa"), "int", ["pointer"], this.C_Object); +} + +//获取消耗品类型 +function PvfItem::GetItemType() { + return Sq_CallFunc(S_Ptr("0x8514A84"), "int", ["pointer"], this.C_Object); } \ No newline at end of file diff --git a/Dps_A/BaseClass/ScriptManager/ScriptManager.nut b/Dps_A/BaseClass/ScriptManager/ScriptManager.nut new file mode 100644 index 0000000..bfe401a --- /dev/null +++ b/Dps_A/BaseClass/ScriptManager/ScriptManager.nut @@ -0,0 +1,1228 @@ +/* +文件名: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); + + // local AllFileStartPos = ScriptData.StartPos; + // foreach(FilePath, Info in ScriptData.PvfFileInfo) { + + // //Ani太多了 加载的时候解密 其他文件 现在解密 + // //构建AniMap + // if (endswith(FilePath, ".ani") && !endswith(FilePath, ".als")) { + // // ScriptData.Ani[FilePath] <- InitPvfAni(FileRo); + // ScriptData.AniPathTable[FilePath] <- { + // Pos = (AllFileStartPos + Info.ROffset), + // Length = Info.Length, + // Cr32 = Info.Cr32 + // } + // } else { + // FileRo.seek(AllFileStartPos + Info.ROffset); + // CrcDecode(FileRo, Info.Length, Info.Cr32); + // // 解密完需要重新调整指针位置 + // FileRo.seek(AllFileStartPos + Info.ROffset); + // } + // } + + 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]") { + 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(); \ No newline at end of file diff --git a/Dps_A/BaseClass/TimerClass/TimerClass.nut b/Dps_A/BaseClass/TimerClass/TimerClass.nut index cf6df6d..957c5e1 100644 --- a/Dps_A/BaseClass/TimerClass/TimerClass.nut +++ b/Dps_A/BaseClass/TimerClass/TimerClass.nut @@ -79,31 +79,31 @@ class Timer { local func = Info[0]; //参数 local func_args = Info[1]; - //下次任务叠加时间 + //Cron字符串 local NextTimestep = Info[2]; //执行函数 func.acall(func_args); //继续构建下一次任务 - Date_Exec_Tree.insert(time() + NextTimestep, Info); + Date_Exec_Tree.insert(Sq_Cron_Next(NextTimestep, time()), Info); } function SetCronTask(target_func, CronString, ...) { - local parts = split(CronString, "/"); - local minute = parts[0].tointeger(); - local hour = parts[1].tointeger(); - local day = parts[2].tointeger(); - local weekday = parts[3].tointeger(); + // local parts = split(CronString, "/"); + // local minute = parts[0].tointeger(); + // local hour = parts[1].tointeger(); + // local day = parts[2].tointeger(); + // local weekday = parts[3].tointeger(); - local S_minute = minute * 60; - local S_hour = hour * 60 * 60; - local S_day = day * 24 * 60 * 60; - local S_weekday = weekday * 7 * 24 * 60 * 60; + // local S_minute = minute * 60; + // local S_hour = hour * 60 * 60; + // local S_day = day * 24 * 60 * 60; + // local S_weekday = weekday * 7 * 24 * 60 * 60; - local AddTimestep = S_minute + S_hour + S_day + S_weekday; + // local AddTimestep = S_minute + S_hour + S_day + S_weekday; local NowTimestep = time(); //下一次执行的时间 - local NextTimestep = AddTimestep + NowTimestep; + local NextTimestep = Sq_Cron_Next(CronString, NowTimestep); local target_arg_list = []; target_arg_list.push(getroottable()); @@ -119,7 +119,7 @@ class Timer { //参数列表 func_info.push(target_arg_list); //间隔时间戳时间 - func_info.push(AddTimestep); + func_info.push(CronString); _Timer_Object.Date_Exec_Tree.insert(NextTimestep, func_info); } diff --git a/Dps_A/BaseClass/UserClass/UserClass.nut b/Dps_A/BaseClass/UserClass/UserClass.nut index 8157753..0b36f88 100644 --- a/Dps_A/BaseClass/UserClass/UserClass.nut +++ b/Dps_A/BaseClass/UserClass/UserClass.nut @@ -599,4 +599,9 @@ function User::SendItemMail(UID, CID, ItemList, title, content) { SUser.Send(Pack); Pack.Delete(); } +} + +//道具是否被锁 +function User::CheckItemLock(Type, Slot) { + return Sq_CallFunc(S_Ptr("0x8646942"), "int", ["pointer", "int", "int"], this.C_Object, Type, Slot); } \ No newline at end of file diff --git a/Dps_A/CallBack/Gm_Input.nut b/Dps_A/CallBack/Gm_Input.nut index 67751fb..5be9038 100644 --- a/Dps_A/CallBack/Gm_Input.nut +++ b/Dps_A/CallBack/Gm_Input.nut @@ -253,8 +253,51 @@ function TestCronTask(str) { } - Gm_InputFunc_Handle.TTT <- function(SUser, CmdString) { + print("初始化开始时间: " + time()); + local PvfObject = Script(); + print("初始化结束时间: " + time()); + local Data = ScriptData.GetEquipment(305014); + printT(Data); + // //修复金币异常 + // //CParty::UseAncientDungeonItems + // var CParty_UseAncientDungeonItems_ptr = ptr(0x859EAC2); + // var CParty_UseAncientDungeonItems = new NativeFunction(CParty_UseAncientDungeonItems_ptr, 'int', ['pointer', 'pointer', 'pointer', 'pointer'], { + // "abi": "sysv" + // }); + // Interceptor.replace(CParty_UseAncientDungeonItems_ptr, new NativeCallback(function(party, dungeon, inven_item, a4) { + // //当前进入的地下城id + // var dungeon_index = CDungeon_get_index(dungeon); + // //根据地下城id判断是否为绝望之塔 + // if ((dungeon_index >= 11008) && (dungeon_index <= 11107)) { + // //绝望之塔 不再扣除金币 + // return 1; + // } + // //其他副本执行原始扣除道具逻辑 + // return CParty_UseAncientDungeonItems(party, dungeon, inven_item, a4); + // }, 'int', ['pointer', 'pointer', 'pointer', 'pointer'])); + // } + + // local exp_bonus = Memory.alloc(4); + // local gold_bonus = Memory.alloc(4); + // local quest_point_bonus = Memory.alloc(4); + // local quest_piece_bonus = Memory.alloc(4); + + // //计算任务基础奖励(不包含道具奖励) + // Sq_CallFunc(S_Ptr(0x866E7A8), "int", ["pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "int"], SUser, pvfQuest, exp_bonus, gold_bonus, quest_point_bonus, quest_piece_bonus, 1); + + // local mitems = {}; + // mitems[3037] <- 500; + // SUser.SendMail(mitems, { + // Title = "标题", + // Text = "内容" + // }); + + // Timer.SetCronTask(function() { + + // }, "1/0/0/0"); //计划任务格式为 1/0/0/0 这样格式的字符串 代表 分 时 天 周 如例子标识的 为每分钟执行1次 + + // local MoveSUser = World.GetUserByUidCid(2, 2); // local Pack = Packet(); // Pack.Put_Header(0, 22); @@ -266,14 +309,45 @@ Gm_InputFunc_Handle.TTT <- function(SUser, CmdString) { // Pack.Finalize(true); // SUser.Send(Pack); // Pack.Delete(); + // local MoveSUser = World.GetUserByUidCid(2, 2); - local Pack = Packet(); - Pack.Put_Header(0, 23); - Pack.Put_Short(SUser.GetUniqueId()); //唯一id - Pack.Put_Byte(SUser.GetLocation().Town); //城镇 - Pack.Delete(); + // local Pack = Packet(); + // Pack.Put_Header(0, 23); + // Pack.Put_Short(MoveSUser.GetUniqueId()); //唯一id + // Pack.Put_Byte(MoveSUser.GetLocation().Town); //城镇 + + // Pack.Put_Byte(7); //区域 + // Pack.Put_Short(MoveSUser.GetAreaPos().X); + + // Pack.Put_Short(MoveSUser.GetAreaPos().Y); + // Pack.Put_Byte(MoveSUser.GetDirections()); //朝向 + // Pack.Put_Byte(MoveSUser.GetVisibleValues()); //是否可见 + // Pack.Finalize(true); + // print(111); + // SUser.Send(Pack); + // Pack.Delete(); + + // local PartyObj = SUser.GetParty(); + + // Sq_CallFunc(S_Ptr("0x85A73A6"), "int", ["pointer", "pointer", "int"], PartyObj.C_Object, SUser.C_Object, 3037); + + // Haker.LoadHook(S_Ptr("0x859D14E"), + // ["pointer", "pointer"], + // function(args) { + // local PartyObj = Party(args[0]); + // local Ssuser = PartyObj.GetUser(0); + // if (Ssuser) { + // local pack = Packet(args[1]); + // Ssuser.Send(pack); + // } + // return null; + // }, + // function(args) { + + // return null; + // }); // local RealList = [World.GetUserByUidCid(2, 2), World.GetUserByUidCid(1, 1)]; // foreach(_Index, Value in RealList) { diff --git a/Dps_A/ProjectClass/AvatarUseJewel/AvatarUseJewel.nut b/Dps_A/ProjectClass/AvatarUseJewel/AvatarUseJewel.nut new file mode 100644 index 0000000..a53541c --- /dev/null +++ b/Dps_A/ProjectClass/AvatarUseJewel/AvatarUseJewel.nut @@ -0,0 +1,146 @@ +/* +文件名:AvatarUseJewel.nut +路径:Dps_A/ProjectClass/AvatarUseJewel/AvatarUseJewel.nut +创建日期:2024-10-09 19:52 +文件用途:时装镶嵌 +*/ +class AvatarUseJewel { + + function WongWork_CAvatarItemMgr_getJewelSocketData(a, b) { + return Sq_CallFunc(S_Ptr("0x82F98F8"), "pointer", ["pointer", "int"], a, b); + } + + function CStackableItem_getJewelTargetSocket(C_Object) { + return Sq_CallFunc(S_Ptr("0x0822CA28"), "int", ["pointer"], C_Object); + } + + function CInventory_delete_item(C_Object, Type, Slot, Count, Ps, Log) { + return Sq_CallFunc(S_Ptr("0x850400C"), "int", ["pointer", "int", "int", "int", "int", "int"], C_Object, Type, Slot, Count, Ps, Log); + } + + function api_set_JewelSocketData(jewelSocketData, slot, emblem_item_id) { + if (jewelSocketData) { + NativePointer(jewelSocketData).add(slot * 6 + 2).writeInt(emblem_item_id); + } + } + + function DB_UpdateAvatarJewelSlot_makeRequest(a, b, c) { + return Sq_CallFunc(S_Ptr("0x843081C"), "pointer", ["int", "int", "pointer"], a, b, c); + } + + //获取时装在数据库中的uid + function api_get_avartar_ui_id(avartar) { + return NativePointer(avartar).add(7).readInt(); + } + + function FixFunction() { + Haker.LoadHook("0x8217BD6", ["int", "pointer", "pointer", "int"], + function(args) { + //角色 + local SUser = User(args[1]); + //包数据 + local Pack = Packet(args[2]); + + //校验角色状态是否允许镶嵌 + if (!SUser || SUser.GetState() != 3) { + return; + } + //时装所在的背包槽 + local Inven_Slot = Pack.GetShort(); + //时装item_id + local Item_Id = Pack.GetInt(); + //本次镶嵌徽章数量 + local Emblem_Count = Pack.GetByte(); + + //获取时装道具 + local InvemObj = SUser.GetInven(); + local AvatarObj = InvemObj.GetSlot(2, Inven_Slot); + + //校验时装 数据是否合法 + if (!AvatarObj || AvatarObj.IsEmpty() || (AvatarObj.GetIndex() != Item_Id) || SUser.CheckItemLock(2, Inven_Slot)) return; + + + local Avartar_AddInfo = AvatarObj.GetAdd_Info(); + //获取时装管理器 + local Inven_AvartarMgr = InvemObj.GetAvatarItemMgr(); + + //获取时装插槽数据 + local Jewel_Socket_Data = AvatarUseJewel.WongWork_CAvatarItemMgr_getJewelSocketData(Inven_AvartarMgr, Avartar_AddInfo); + + if (!Jewel_Socket_Data) return; + + //最多只支持3个插槽 + if (Emblem_Count <= 3) { + local emblems = {}; + + for (local i = 0; i< Emblem_Count; i++) { + //徽章所在的背包槽 + local emblem_inven_slot = Pack.GetShort(); + //徽章item_id + local emblem_item_id = Pack.GetInt(); + //该徽章镶嵌的时装插槽id + local avartar_socket_slot = Pack.GetByte(); + + //获取徽章道具 + local EmblemObje = InvemObj.GetSlot(1, emblem_inven_slot); + + //校验徽章及插槽数据是否合法 + if (!EmblemObje || EmblemObje.IsEmpty() || (EmblemObje.GetIndex() != emblem_item_id) || (avartar_socket_slot >= 3)) return; + + //校验徽章是否满足时装插槽颜色要求 + //获取徽章pvf数据 + local citem = PvfItem.GetPvfItemById(emblem_item_id); + if (!citem) return; + + //校验徽章类型 + if (!citem.IsStackable() || citem.GetItemType() != 20) return; + + //获取徽章支持的插槽 + local emblem_socket_type = AvatarUseJewel.CStackableItem_getJewelTargetSocket(citem.C_Object); + + //获取要镶嵌的时装插槽类型 + local avartar_socket_type = NativePointer(Jewel_Socket_Data).add(avartar_socket_slot * 6).readShort(); + + if (!(emblem_socket_type & avartar_socket_type)) return; + + emblems[avartar_socket_slot] <- [emblem_inven_slot, emblem_item_id]; + } + + //开始镶嵌 + foreach(avartar_socket_slot, emblemObject in emblems) { + //删除徽章 + local emblem_inven_slot = emblemObject[0]; + AvatarUseJewel.CInventory_delete_item(InvemObj.C_Object, 1, emblem_inven_slot, 1, 8, 1); + //设置时装插槽数据 + local emblem_item_id = emblemObject[1]; + AvatarUseJewel.api_set_JewelSocketData(Jewel_Socket_Data, avartar_socket_slot, emblem_item_id); + } + + //时装插槽数据存档 + AvatarUseJewel.DB_UpdateAvatarJewelSlot_makeRequest(SUser.GetCID(), AvatarUseJewel.api_get_avartar_ui_id(AvatarObj.C_Object), Jewel_Socket_Data); + + //通知客户端时装数据已更新 + SUser.SendUpdateItemList(1, 1, Inven_Slot); + + //回包给客户端 + local Pack = Packet(); + Pack.Put_Header(1, 204); + Pack.Put_Int(1); + Pack.Finalize(true); + SUser.Send(Pack); + Pack.Delete(); + } + + return null; + }, + + function(args) { + return 0; + } + ); + } + + constructor() { + FixFunction(); + } +} \ No newline at end of file diff --git a/Dps_A/ProjectClass/MarrySystem/MarrySystem.nut b/Dps_A/ProjectClass/MarrySystem/MarrySystem.nut index a62946c..e22c67d 100644 --- a/Dps_A/ProjectClass/MarrySystem/MarrySystem.nut +++ b/Dps_A/ProjectClass/MarrySystem/MarrySystem.nut @@ -4,6 +4,12 @@ 创建日期:2024-10-01 10:02 文件用途:结婚系统 */ + + + + + + class Marry { //当前频道 Channel = null; @@ -16,8 +22,10 @@ class Marry { //进入礼堂前的位置信息 EnterAuditoriumPosList = {}; - //礼堂id 对应的用户信息 + //礼堂id 对应的用户信息 结构为Map> AuditoriumUserInfo = {}; + //角色时装信息 + UserAvaList = {}; //数据库操作集 @@ -339,6 +347,8 @@ class Marry { Flag = 2 } + + local WorldMap = World.GetOnlinePlayer(); foreach(W_User in WorldMap) { if (W_User.GetCID() == Target_CId) { @@ -351,6 +361,40 @@ class Marry { } } + //开启婚礼 参数为礼堂编号 也就是其中一个人的cid + function OpenAuditorium(index) { + //通知所有在这个礼堂里的人 婚礼开始了 + local userlist = AuditoriumUserInfo[RoomId]; + + local dxcid = Mysql_Operate_Func.CheckMarryTarget(index); + foreach(uid in userlist) { + local user = World.GetUserByUid(uid); + + //发包通知 如果是2个结婚的人的cid 下发另外的包 + if (user.GetCID() == index || user.GetCID() == dxcid) { + local T = { + op = OP + 32, + userlist = userlist + } + } else { + //发包通知 普通宾客的包 + local T = { + op = OP + 34, + userlist = userlist + } + } + user.SendJso(T); + } + + + + + //删除礼堂信息 + AuditoriumUserInfo.rawdelete(RoomId); + //删除数据库信息 + Mysql_Operate_Func.DeleteMarryInfo(index); + Mysql_Operate_Func.DeleteMarryInfo(dxcid); + } //进入礼堂 @@ -389,7 +433,7 @@ class Marry { - AuditoriumUserInfo[RoomId].rawset(SUser.GetCID(), 1); + AuditoriumUserInfo[RoomId].rawset(SUser.GetUID(), GetAva(SUser)); local UserCanSee = []; foreach(cid in AuditoriumUserInfo[RoomId]) { @@ -412,11 +456,12 @@ class Marry { World.MoveArea(SUser, Info.Town, Info.Area, Info.Pos.X, Info.Pos.Y); - AuditoriumUserInfo[Info["所在礼堂编号"]].rawdelete(SUser.GetCID()); + AuditoriumUserInfo[Info["所在礼堂编号"]].rawdelete(SUser.GetUID()); } - } + } + //获得礼堂列表 @@ -498,12 +543,14 @@ class Marry { Pack.Put_Byte(MUser.GetLocation().Town); //城镇 - Pack.Put_Byte(MUser.GetArea(1)); //区域 + Pack.Put_Byte(99); //区域 Pack.Put_Short(MUser.GetAreaPos().X); + Pack.Put_Short(MUser.GetAreaPos().Y); Pack.Put_Byte(MUser.GetDirections()); //朝向 Pack.Put_Byte(MUser.GetVisibleValues()); //是否可见 Pack.Finalize(true); + print(111); SUser.Send(Pack); Pack.Delete(); } @@ -511,6 +558,7 @@ class Marry { + constructor() { Config = dofile("/root/娱心插件配置/结婚系统配置.dat"); local ConfigPath = Sq_Game_GetConfig(); @@ -531,14 +579,48 @@ class Marry { //每次加载的时候都注册礼堂信息 AuditoriumUserInfo.rawset(1, {}); - local RealList = []; - RealList.push(World.GetUserByUid(1)); - RealList.push(World.GetUserByUid(2)); + + //玩家重新上线的时候自动给他退出礼堂 + Cb_reach_game_world_Func.Auditorium <- function(SUser) { + if (EnterAuditoriumPosList.rawin(SUser.GetUID())) { + local Info = EnterAuditoriumPosList[SUser.GetCID()]; + AuditoriumUserInfo[Info["所在礼堂编号"]].rawdelete(SUser.GetUID()); + } + }.bindenv(this); + + + // local RealList = []; + + // RealList.push(World.GetUserByUid(1)); + // RealList.push(World.GetUserByUid(2)); + + + + // Timer.SetTimeOut(function() { + // // Sq_CallFunc(S_Ptr("0x850d374"), "int", ["pointer", "int"], S_Ptr("0x1"), "sss") + // // local S = Memory.alloc(100); + // // Sq_Delete_Point(S.C_Object); + // Sq_CallFunc(S_Ptr("0x08692af6"), "int", ["pointer", "int", "int"], 1, 1, 1); + // }, 3000); + + + // local Suser = World.GetUserByUid(2); + // //获取背包对象 + // local InvenObj = Suser.GetInven(); + // //遍历身上的每一件装备 + // for (local u = 0; u <= 10; u++) { + // //如果装备存在 并且存在于 加成表中 就给提升率加上对应的值 + // local EquObj = InvenObj.GetSlot(Inven.INVENTORY_TYPE_BODY, u); + // if (EquObj && !EquObj.IsEmpty) { + // local EquObjId = EquObj.GetIndex(); + // print(EquObj.Output()); + // } + // } + - Timer.SetTimeOut(MarryUserDeleteCallBack, 3000, RealList, World.GetUserByUid(1)); //从池子拿连接 local SqlObj = MysqlPool.GetInstance().GetConnect(); @@ -553,7 +635,124 @@ class Marry { } //把连接还池子 MysqlPool.GetInstance().PutConnect(SqlObj); + + defaultJobItemIdMap.rawset(0, defaultJobItemId(39278, 39400, 0, 0, 40600, 41000, 41800, 42200)); + defaultJobItemIdMap.rawset(1, defaultJobItemId(0, 43400, 0, 0, 44600, 45000, 45800, 46200)); + defaultJobItemIdMap.rawset(2, defaultJobItemId(0, 47400, 0, 48426, 48600, 49000, 49800, 50200)); + defaultJobItemIdMap.rawset(3, defaultJobItemId(51265, 51400, 0, 0, 52600, 53000, 53800, 54200)); + defaultJobItemIdMap.rawset(4, defaultJobItemId(0, 55400, 55820, 0, 56600, 57000, 57800, 58200)); + + defaultJobItemIdMap.rawset(5, defaultJobItemId(1600000, 1610000, 0, 0, 1640000, 1650000, 1670000, 1680000)); + defaultJobItemIdMap.rawset(6, defaultJobItemId(1720000, 1730000, 0, 1750000, 1760000, 1770000, 1790000, 1800000)); + defaultJobItemIdMap.rawset(7, defaultJobItemId(0, 29201, 0, 0, 29202, 29203, 29204, 29205)); + defaultJobItemIdMap.rawset(8, defaultJobItemId(0, 2090000, 0, 0, 2120000, 2130000, 2140000, 2150000)); + defaultJobItemIdMap.rawset(9, defaultJobItemId(39278, 39400, 0, 0, 40600, 41000, 41800, 42200)); + defaultJobItemIdMap.rawset(10, defaultJobItemId(51265, 51400, 0, 0, 52600, 53000, 53800, 54200)); + } + +} + + + +//获取角色身上的显示时装 +function GetAva(SUser) { + //获取背包对象 + local InvenObj = SUser.GetInven(); + + local re = []; + + + local job = SUser.GetCharacJob(); + //遍历身上的每一件装备 + for (local u = 0; u <= 2; u++) { + local EquObj = InvenObj.GetSlot(Inven.INVENTORY_TYPE_BODY, u); + if (EquObj && !EquObj.IsEmpty) { + //先拿克隆id 如果这个值有 那说明带的克隆 直接用这个 + local clearId = Sq_CallFunc(S_Ptr("0x850d374"), "int", ["pointer", "int"], 1, u) + // print(clearId); + local EquObjId = EquObj.GetIndex(); + // print(EquObjId); + //如果这个是克隆 + if (clearId > 0) { + re.push(clearId); + } else { //不是克隆 直接把id放上去 + + re.push(EquObjId); + + } + } else { //如果这个部位没东西 直接放默认时装上去 + re.push(defaultJobItemIdMap[job].index[u]); + } + + } + return re; +} +//默认时装 +defaultJobItemIdMap <- {}; + + +class defaultJobItemId { + + /** + * 头发 + */ + hat = 0; + + /** + * 帽子 + */ + hair = 0; + + /** + *脸 + */ + face = 0; + /** + * 披风 + */ + breast = 0; + /** + * 上衣 + */ + coat = 0; + + /** + * 下装 + */ + pants = 0; + + /** + * 鞋子 + */ + shoes = 0; + + /** + * 皮肤 + */ + skin = 0; + + index = []; + + constructor(hat, hair, face, breast, coat, pants, shoes, skin) { + this.hat = hat; + this.hair = hair; + this.face = face; + this.breast = breast; + this.coat = coat; + this.pants = pants; + this.shoes = shoes; + this.skin = skin; + index.push(hat); + index.push(hair); + index.push(face); + + index.push(breast); + index.push(coat); + index.push(pants); + index.push(shoes); + index.push(skin); } } + ProjectInitFuncMap.P_Marry <- Marry(); \ No newline at end of file diff --git a/Dps_A/main.nut b/Dps_A/main.nut index d40c5ed..becd9dc 100644 --- a/Dps_A/main.nut +++ b/Dps_A/main.nut @@ -5,6 +5,7 @@ function InitPluginInfo() { _Timer_Object <- Timer(); + //初始化自动重载 只在15线开启 local ConfigPath = Sq_Game_GetConfig(); local Channel = ConfigPath.slice(ConfigPath.find("cfg/") + 4, ConfigPath.len()); @@ -18,12 +19,21 @@ function InitPluginInfo() { PoolObj.Init(); - - // Sq_CreatCConnectPool(2, 4, "127.0.0.1", 3306, "game", "uu5!^%jg"); - Sq_CreatSocketConnect("192.168.200.24", "65109"); + // Sq_CreatSocketConnect("192.168.200.24", "65109"); //初始化结婚 ProjectInitFuncMap.P_Marry <- Marry(); + + + //初始化日志器 + Log({ + "normal": "/dp_s/log/normal.log", + "error": "/dp_s/log/error.log" + }); + //调用方式 + //Log.Put("normal", "测试日志"); + //Log.Put("error", "测试错误日志"); + } @@ -39,7 +49,13 @@ function main() { PrintTag(); GameManager.SetGameMaxLevel(95); + GameManager.FixAvatarUseJewel(); + GameManager.FixSaveTown(); + GameManager.FixDespairGold(); + local PvfObject = Script(); + local Data = ScriptData.GetEquipment(305014); + printT(Data); } diff --git a/Dps_C/B-TW_UseItem.nut b/Dps_C/B-TW_UseItem.nut index 9ea75fa..3bb7642 100644 --- a/Dps_C/B-TW_UseItem.nut +++ b/Dps_C/B-TW_UseItem.nut @@ -361,7 +361,7 @@ foreach(_ItemId, baseInfo in TW_StkUpJTable) { if (SlotItem.GetType() != "装备") { local SlotCount = SlotItem.GetAdd_Info(); local GiveRate = floor(SlotCount.tofloat() / Info.Stk.Count.tofloat()); - if(GiveRate < 1){ + if (GiveRate< 1) { SUser.SendNotiPacketMessage(format(TW_STR_00084), 8); return false; } @@ -1563,7 +1563,7 @@ Cb_timer_dispatch_Func["TW_Cb_timer_dispatch_Func"] <- function() { if (mitems.len() > 0) { SUser.SendMail(mitems, { Title = TW_STR_00001, - Text = TW_STR_00002 + Text = TW_STR_0000 }) } diff --git a/Dps_C/New_Hook.nut b/Dps_C/New_Hook.nut index f96c8c7..9f6bea0 100644 --- a/Dps_C/New_Hook.nut +++ b/Dps_C/New_Hook.nut @@ -106,4 +106,64 @@ _Hook_Register_Currency_Func_("0x84FC37E", ["pointer", "int", "pointer", "int"], //获取通关时间回调 Cb_CParty_SetBestClearTime_Enter_Func <- {}; Cb_CParty_SetBestClearTime_Leave_Func <- {}; -_Hook_Register_Currency_Func_("0x85BE178", ["pointer", "char", "int", "int", "bool"], Cb_CParty_SetBestClearTime_Enter_Func, Cb_CParty_SetBestClearTime_Leave_Func); \ No newline at end of file +_Hook_Register_Currency_Func_("0x85BE178", ["pointer", "char", "int", "int", "bool"], Cb_CParty_SetBestClearTime_Enter_Func, Cb_CParty_SetBestClearTime_Leave_Func); + +//使用称号回收箱时检查使用条件 +Cb_UseLimitCube_Check_Error_Enter_Func <- {}; +Cb_UseLimitCube_Check_Error_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x081D3BBC", ["pointer", "int", "int", "int", "pointer", "pointer", "pointer", "int"], Cb_UseLimitCube_Check_Error_Enter_Func, Cb_UseLimitCube_Check_Error_Leave_Func); + +//使用称号回收箱过程 +Cb_UseLimitCube_Process_Enter_Func <- {}; +Cb_UseLimitCube_Process_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x081D3D38", ["pointer", "pointer", "pointer", "pointer", "int"], Cb_UseLimitCube_Process_Enter_Func, Cb_UseLimitCube_Process_Leave_Func); + +//购买商城物品时日志 +Cb_Log_BuyCashShopItem_Enter_Func <- {}; +Cb_Log_BuyCashShopItem_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x08686EA0", ["pointer", "int", "int", "int", "int", "char", "int", "int", "int"], Cb_Log_BuyCashShopItem_Enter_Func, Cb_Log_BuyCashShopItem_Leave_Func); + +//购买道具获取信息 +Cb_BuyItem_Get_Data_Enter_Func <- {}; +Cb_BuyItem_Get_Data_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x81BE658", ["pointer", "pointer", "int", "pointer", "int"], Cb_BuyItem_Get_Data_Enter_Func, Cb_BuyItem_Get_Data_Leave_Func); + +//设置角色详细信息 +Cb_Set_Charac_Info_Detail_Enter_Func <- {}; +Cb_Set_Charac_Info_Detail_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x0864AC1A", ["pointer", "int", "int", "pointer", "int"], Cb_Set_Charac_Info_Detail_Enter_Func, Cb_Set_Charac_Info_Detail_Leave_Func); + +//使用远古地下城道具 +Cb_UseAncientDungeonItems_Enter_Func <- {}; +Cb_UseAncientDungeonItems_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x859EAC2", ["pointer", "pointer", "pointer", "pointer", "int"], Cb_UseAncientDungeonItems_Enter_Func, Cb_UseAncientDungeonItems_Leave_Func); + +//购买限时商品 +Cb_BuyCeraShopLimitItem_Enter_Func <- {}; +Cb_BuyCeraShopLimitItem_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x821F9BA", ["pointer", "pointer", "pointer", "int"], Cb_BuyCeraShopLimitItem_Enter_Func, Cb_BuyCeraShopLimitItem_Leave_Func); + +//获取下次清除时间 +Cb_User_GetLastClearTime_Enter_Func <- {}; +Cb_User_GetLastClearTime_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x0864387E", ["pointer", "int"], Cb_User_GetLastClearTime_Enter_Func, Cb_User_GetLastClearTime_Leave_Func); + +//每日可交易金币上限 +Cb_User_CharacInfo_IsAvailableCurCharacTradeGoldDaily_Enter_Func <- {}; +Cb_User_CharacInfo_IsAvailableCurCharacTradeGoldDaily_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x08646496", ["pointer", "int", "int"], Cb_User_CharacInfo_IsAvailableCurCharacTradeGoldDaily_Enter_Func, Cb_User_CharacInfo_IsAvailableCurCharacTradeGoldDaily_Leave_Func); + +//进入副本加载完毕时 +Cb_Party_OnStartMapFinishLoading_Enter_Func <- {}; +Cb_Party_OnStartMapFinishLoading_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x085B170A", ["pointer", "int", "int"], Cb_Party_OnStartMapFinishLoading_Enter_Func, Cb_Party_OnStartMapFinishLoading_Leave_Func); + +//房间清理完毕 +Cb_Battle_Field_onClearMap_Enter_Func <- {}; +Cb_Battle_Field_onClearMap_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x0830DD2C", ["pointer", "bool", "char"], Cb_Battle_Field_onClearMap_Enter_Func, Cb_Battle_Field_onClearMap_Leave_Func); + +//放弃副本 +Cb_Party_giveup_game_Enter_Func <- {}; +Cb_Party_giveup_game_Leave_Func <- {}; +_Hook_Register_Currency_Func_("0x085B2BAA", ["pointer", "bool", "bool", "bool", "void"], Cb_Party_giveup_game_Enter_Func, Cb_Party_giveup_game_Leave_Func); \ No newline at end of file diff --git a/folder-alias.json b/folder-alias.json index be58cbe..54e5a32 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -133,5 +133,17 @@ }, "Dps_A/BaseClass/HotFixClass": { "description": "热更新" + }, + "Dps_A/ProjectClass/AvatarUseJewel": { + "description": "时装镶嵌" + }, + "Dps_A/BaseClass/LogClass": { + "description": "日志类" + }, + "Dps_A/BaseClass/BlobExClass": { + "description": "高级blob" + }, + "Dps_A/BaseClass/ScriptManager": { + "description": "pvf管理器" } } \ No newline at end of file diff --git a/lib/libAurora.so b/lib/libAurora.so index e695848..6b8829c 100755 Binary files a/lib/libAurora.so and b/lib/libAurora.so differ diff --git a/lib/libAurora.soAAA b/lib/libAurora.soAAA new file mode 100644 index 0000000..4f03ac2 Binary files /dev/null and b/lib/libAurora.soAAA differ diff --git a/lib/libAurora.soAAACC b/lib/libAurora.soAAACC new file mode 100755 index 0000000..e695848 Binary files /dev/null and b/lib/libAurora.soAAACC differ diff --git a/log/error.log b/log/error.log new file mode 100644 index 0000000..e69de29 diff --git a/log/normal.log b/log/normal.log new file mode 100644 index 0000000..e69de29