diff --git a/Base/_Tool/Item_Class.nut b/Base/_Tool/Item_Class.nut index 5d67c17..ab33cfd 100644 --- a/Base/_Tool/Item_Class.nut +++ b/Base/_Tool/Item_Class.nut @@ -1,6 +1,8 @@ - class Rindro_Item { + //C指针 C_Object = null; + //绘制信息结构体 + DrawInfo = null; constructor() { @@ -24,6 +26,15 @@ class Rindro_Item { function SetIndex(Index) { NativePointer(C_Object).add(0x1C).writeInt(Index); } + //获取名字 + function GetName() { + local NamePointer = NativePointer(C_Object).add(0x20).readInt(); + return NativePointer(L_sq_I2P(NamePointer)).readUnicodeString(); + } + //获取品级 + function GetRarity() { + return NativePointer(C_Object).add(0xF4).readInt(); + } //获取强化值 function GetUpgrade() { return MemoryTool.DecodeMemoryData(C_Object + 0x1054); @@ -64,4 +75,172 @@ class Rindro_Item { function SetEnchanting(Enchanting) { MemoryTool.EncodeMemoryData(C_Object + 0x1084, Enchanting); } -} \ No newline at end of file + //读取Uuid + function GetUuid() { + return NativePointer(C_Object).add(0x206).readInt(); + } + + + + //是否为装备 + function IsEquip() { + return NativePointer(C_Object).add(0x4).readInt() == 2; + } + + //是否为消耗品 + function IsStack() { + return NativePointer(C_Object).add(0x4).readInt() == 1; + } + + + function ConstructDrawingInformation(...) { + if (!DrawInfo) { + DrawInfo = Rindro_Item_DrawInfo(this); + if (vargc > 0) { + DrawInfo.AddGuidanceInformation(vargv[0]); + } + DrawInfo.Init(); + } + } + + function Show(X, Y) { + //背景框 + Rindro_BaseToolClass.DrawNineBox(X, Y, 214, DrawInfo.Height + 30, "interface2/common/mypopup/popup.img", 0); + // local C_Object = Rindro_Image_GlobalMap["popup"].GetPng(134); + // print(C_Object); + // L_Sq_CallFunc(0x11DF050, "void", FFI_FASTCALL, ["pointer", "int", "int", "int", "int", "int"], C_Object, 0, 10, 10, 10, 10); + + foreach(info in DrawInfo.InfoList) { + //文字 + if (info.Type == 0) { + L_sq_DrawCode(info.Content, X + info.X, Y + info.Y, info.Color, 0, 1); + } else if (info.Type == 1) { + Rindro_Image_GlobalMap["popup"].DrawPng(270, X + info.X, Y + info.Y); + } else if (info.Type == 2) { + info.Func(X + info.X, Y + info.Y, this); + } + } + } +} + + +class Rindro_Item_DrawInfo { + //Item对象 + Item = null; + //指导信息 (原装备生成的信息) + GuidanceInformation = null; + //指导信息标志位 + GuidanceInformationFlag = 0; + //信息 + InfoList = null; + + Height = 0; + + Padding = 8; + + constructor(gItem) { + Item = gItem; + InfoList = []; + } + + //添加指导信息 + function AddGuidanceInformation(info) { + GuidanceInformation = info; + } + + function Init() { + + //读取强化等级 + local UpgradeLevel = Item.GetUpgrade(); + //读取名字 + local Name = Item.GetName(); + local UpgradeStr = UpgradeLevel > 0 ? (UpgradeLevel + " ") : ""; + local NameStr = Name.len() > 0 ? (Name + " ") : "未定名"; + + AddContent((UpgradeStr + Name), Padding, Padding, Rindro_BaseToolClass.GetRarityColor(Item.GetRarity())); + + if (isGm()) { + //读取编号 + local Index = Item.GetIndex(); + //读取uuid + local Uuid = Item.GetUuid(); + local IndexStr = Index > 0 ? ("编号: [" + Index + "] ") : ""; + local UuidStr = Uuid > 10000 ? ("uid: [" + Uuid + "] ") : ""; + AddContent((IndexStr + UuidStr), Padding, 15, 0xffffffff); + } + + for (local i = 1; i< GuidanceInformation.len(); i++) { + local info = GuidanceInformation[i]; + if (info.Str && info.Str.len() > 0) { + local RealStr = format(info.Str); + if (info.Flag != GuidanceInformationFlag) { + AddContent(RealStr, Padding, 15, info.Color); + } + //说明要绘制在右侧这个左侧信息已经绘制过了 + else { + local StrLength = LenheartTextClass.GetStringLength(RealStr); + AddContent(RealStr, 215 - StrLength - Padding, 0, info.Color); + } + } else { + AddDividing(26, 15); + //第二道分割线下面 + if (GuidanceInformationFlag > 4) { + //有自定义的代理内容则添加 + if (getroottable()["NewItemInfoWindow_Obj"].CustomDrawDelegate.len() > 0) { + //真正达成条件需要代理的Item + local RealCustomDrawDelegate = []; + //先遍历一遍检查条件是否成立 + foreach(Name, Info in getroottable()["NewItemInfoWindow_Obj"].CustomDrawDelegate) { + if (Info.CheckFunc(Item) == true) RealCustomDrawDelegate.append(Info); + } + //需要代理的项 + if (RealCustomDrawDelegate.len() > 0) { + foreach(Info in RealCustomDrawDelegate) { + AddDelegate(Info.Height, Info.Func); + } + AddDividing(26, 15); + } + } + } + } + GuidanceInformationFlag = info.Flag; + } + } + + //增加内容 + function AddContent(Content, X, Y, Color) { + InfoList.append({ + Type = 0, + Content = Content, + X = X, + Y = Y + Height, + Color = Color + }); + + Height += Y; + } + + //增加分割线 + function AddDividing(X, Y) { + InfoList.append({ + Type = 1, + X = X, + Y = Y + Height + 3, + }); + + Height += 8; + } + + //增加自定义代理 + function AddDelegate(Y, Func) { + InfoList.append({ + Type = 2, + X = 0, + Y = Height, + Func = Func + }); + Height += Y; + } +} + +getroottable().rawdelete("NewItemInfoWindow_Obj"); \ No newline at end of file diff --git a/Project/NewItemInfoWindow/NewItemInfoWindow.nut b/Project/NewItemInfoWindow/NewItemInfoWindow.nut new file mode 100644 index 0000000..b034896 --- /dev/null +++ b/Project/NewItemInfoWindow/NewItemInfoWindow.nut @@ -0,0 +1,166 @@ +/* +文件名:NewItemInfoWindow.nut +路径:Project/NewItemInfoWindow/NewItemInfoWindow.nut +创建日期:2026-01-18 11:22 +文件用途: +*/ +class NewItemInfoWindowC extends Rindro_BaseToolClass { + + + + //绘制信息Map + DrawInfoMap = null; + //Script信息 + ScriptInfoMap = null; + + //自定义绘制代理 + CustomDrawDelegate = null; + + Img = Rindro_Image("soulweapon/main.img"); + + constructor() { + DrawInfoMap = {}; + ScriptInfoMap = {}; + CustomDrawDelegate = {}; + Fix(); + + AddDelegate("测试代理", 28, function(X, Y, Item) { + L_sq_DrawCode("灵魂救赎阶段: 1 / 3", X + 6, Y + 15, sq_RGBA(255, 0, 240, 255), 0, 1); + L_sq_DrawCode("封印灵魂数: ", X + 6, Y + 30, sq_RGBA(104, 213, 237, 255), 0, 1); + L_sq_DrawCode("100%", X + 180, Y + 30, sq_RGBA(255, 119, 0, 255), 0, 1); + Img.DrawPng(0, X + 70, Y + 34); + Img.DrawPng(1, X + 72, Y + 36); + }.bindenv(this), function(Item) { + if (Item.GetIndex() == 104000046) return true; + return false; + }) + } + + + //绘制Info + function Show(InfoList, EquipAddress, XPos, YPos) { + if (!DrawInfoMap.rawin(EquipAddress)) { + local ItemObject = Rindro_Item(); + ItemObject.LoadByAddress(EquipAddress); + ItemObject.ConstructDrawingInformation(InfoList); + DrawInfoMap.rawset(EquipAddress, ItemObject); + } + DrawInfoMap[EquipAddress].Show(XPos, YPos); + } + + function AddDelegate(Name, Height, Func, CheckFunc) { + CustomDrawDelegate.rawset(Name, { + //代理区域高度 + Height = Height, + //代理回调函数 + Func = Func, + //代理条件 + CheckFunc = CheckFunc + }) + } + + function RemoveDelegate(Name) { + CustomDrawDelegate.rawdelete(Name); + } + + function Fix() { + NativePointer(0xF363D9).writeByteArray(array(16, 0x90)) + Rindro_Haker.LoadHook(0xF363D0, ["int", "int", "int", "void"], + function(args) { + //先获取到 DrawItemContent_F36110 的 a3参数 + local a3 = L_sq_P2I(Rindro_Haker.CpuContext.ecx) + 0x17c; + + //计算 + //数据头尾指针 一个元素 72字节 + local Start = NativePointer(a3).add(0x4).readInt(); + local End = NativePointer(a3).add(0x8).readInt(); + //数据数组长度 + local Length = ((End - Start) / 72); + + //原数据 + local InfoList = []; + //获取装备编号 (遍历所有数据块 找到标志位 读取装备指针) + local EquipAddress = 0; + for (local i = 1; i< Length; i++) { + local Info = {}; + + local Str = null; + if (NativePointer(Start).add(72 * i + 0x24).readInt()< 8) { + local StrPointer = NativePointer(Start).add(72 * i + 0x10); + if (L_sq_P2I(StrPointer.C_Object) > 0x400000) { + Str = StrPointer.readUnicodeString(); + } + } else { + local StrPointer = NativePointer(Start).add(72 * i + 0x10).readInt(); + if (StrPointer > 0x400000) { + Str = NativePointer(StrPointer).readUnicodeString(); + } + } + Info.Str <- Str; + Info.Flag <- NativePointer(Start).add(72 * i).readInt(); + + local Pos = NativePointer(Start).add(72 * i + 0x4).readInt(); + local Color = NativePointer(Start).add(72 * i + 0x8).readInt(); + + //特殊的位置信息 作为标志位的时候 颜色是装备指针 + if (Pos == 947330670) { + EquipAddress = Color; + } + + Info.Color <- Color; + InfoList.append(Info); + } + + if (EquipAddress != 0) { + // printf("装备编号: " + NativePointer(EquipAddress).add(0x1c).readInt()); + local XPos = NativePointer(L_sq_P2I(Rindro_Haker.CpuContext.esi) + 0x14).readInt(); + local YPos = NativePointer(L_sq_P2I(Rindro_Haker.CpuContext.esi) + 0x18).readInt(); + Show(InfoList, EquipAddress, XPos, YPos); + //HOOK原逻辑不执行 + NativePointer(0xF363D9).writeByteArray(array(16, 0x90)) + } + + return null; + }.bindenv(this), + function(args) { + //还原原逻辑 + NativePointer(0xF363D9).writeByteArray([0x80, 0xBE, 0x90, 0x01, 0x00, 0x00, 0x00, 0x74, 0x0E, 0xC6, 0x86, 0x90, 0x01, 0x00, 0x00, 0x00]); + return null; + }.bindenv(this)); + + //构造信息时 + Rindro_Haker.LoadHook(0xF542F0, ["int", "int", "int", "int", "int"], + function(args) { + //找到新增分割线的构造时机 将标志位写入位置参数 将Item地址写入颜色参数 + if (args[0] > 0) { + if (NativePointer(args[1]).readUnicodeString().len() <= 0) { + local EquipmentAddress = NativePointer(Rindro_Haker.CpuContext.ecx).add(0x178).readInt(); + //是装备才做这个事 + if (NativePointer(EquipmentAddress).add(0x4).readInt() == 2) { + args[2] = 947330670; + args[3] = EquipmentAddress; + return args; + } + } + } + }.bindenv(this), + function(args) { + + return null; + }.bindenv(this)); + + } +} + + +getroottable().rawdelete("NewItemInfoWindow_Obj"); + + +function Lenheart_NewItemInfoWindow_Fun(obj) { + local RootTab = getroottable(); + if (!RootTab.rawin("NewItemInfoWindow_Obj")) { + RootTab.rawset("NewItemInfoWindow_Obj", NewItemInfoWindowC()); + } +} + +getroottable()["LenheartFuncTab"].rawset("NewItemInfoWindowFuncN", Lenheart_NewItemInfoWindow_Fun); \ No newline at end of file