feat(core): CheatEngine item container coprse loaders

This commit is contained in:
gromchek 2026-01-17 15:25:16 +03:00
parent 52bd97bc47
commit 89a8691959
14 changed files with 2787 additions and 106 deletions

View file

@ -716,55 +716,45 @@ function GetCGObjectAddr(guidValue)
return nil
end
local CGUNIT_C_VTABLE = 0xa34d90
local CGPLAYER_C_VTABLE = 0xa326c8
local VTABLE_TYPES = {
[0xA34D90] = "unit",
[0xA326C8] = "player",
[0xA33428] = "item",
[0xA332D0] = "container",
[0xA331C8] = "corpse",
}
local memScan = createMemScan()
local foundList = createFoundList(memScan)
local function cleanup()
foundList.destroy()
memScan.destroy()
end
memScan.firstScan(
soExactValue,
vtQword,
rtRounded,
soExactValue, vtQword, rtRounded,
string.format("%016X", guidValue),
nil,
0x0,
0x7FFFFFFFFFFFFFFF,
"",
fsmNotAligned,
nil,
true,
false,
false,
false
nil, 0x0, 0x7FFFFFFFFFFFFFFF,
"", fsmNotAligned, nil,
true, false, false, false
)
memScan.waitTillDone()
foundList.initialize()
local resultAddr, resultType = nil, nil
for i = 0, foundList.Count - 1 do
local addrGUIDvalue = tonumber(foundList.Address[i], 16)
if addrGUIDvalue then
local base = addrGUIDvalue - 0x30
local vtbl = readInteger(base)
if vtbl == CGPLAYER_C_VTABLE then
resultAddr, resultType = base, "player"
break
elseif vtbl == CGUNIT_C_VTABLE then
resultAddr, resultType = base, "unit"
break
local addr = tonumber(foundList.Address[i], 16)
if addr then
local base = addr - 0x30
local objType = VTABLE_TYPES[readInteger(base)]
if objType then
cleanup()
return base, objType
end
end
end
foundList.destroy()
memScan.destroy()
if resultAddr then
return resultAddr, resultType
end
cleanup()
return nil
end

View file

@ -0,0 +1,48 @@
-- #include "cgobject.lua"
local ObjectFields = Struct("ObjectFields")
:hex("GUID", "uint64")
:field("type", "uint32")
:field("unk", "uint32")
:field("scale", "float")
:field("pad", "uint32")
local ContainerSlot = Struct("ContainerSlot")
:hex("guid", "uint64")
local ContainerFields = Struct("ContainerFields")
:field("NumSlots", "int32")
:field("Pad", "int32")
:structArray("Slot", ContainerSlot, 36)
local ItemEnchantment = Struct("ItemEnchantment")
:array("id", "uint32", 3)
local ItemFields = Struct("ItemFields")
:hex("Owner", "uint64")
:hex("Contained", "uint64")
:hex("Creator", "uint64")
:hex("GiftCreator", "uint64")
:field("StackCount", "int32")
:field("Duration", "int32")
:array("SpellCharges", "int32", 5)
:hex("Flags", "uint32")
:structArray("Enchantment", ItemEnchantment, 12)
:field("PropertySeed", "int32")
:field("RandomPropertiesID", "int32")
:field("Durability", "int32")
:field("MaxDurability", "int32")
:field("CreatePlayedTime", "int32")
:field("Pad", "int32")
local CGContainer = Struct("CGContainer", CGObject)
:paddingTo(0x778)
:embed("ObjectFields", ObjectFields) -- 0x778
:embed("ItemFields", ItemFields) -- 0x790
:embed("ContainerFields", ContainerFields) -- 0x878
:field("itemId", "int32") -- 0x9A0
:field("scale", "float") -- 0x9A4
:paddingTo(0xB88)
-- #include "load_player_container.lua"

39
cheatengine/cgcorpse.lua Normal file
View file

@ -0,0 +1,39 @@
-- #include "cgobject.lua"
local Vector3 = Struct("Vector3")
:field("x", "float")
:field("y", "float")
:field("z", "float")
local ObjectFields = Struct("ObjectFields")
:hex("GUID", "uint64")
:field("type", "uint32")
:field("unk", "uint32")
:field("scale", "float")
:field("pad", "uint32")
local CorpseFields = Struct("CorpseFields")
:hex("Owner", "uint64")
:hex("Party", "uint64")
:field("DisplayId", "int32")
:array("Item", "int32", 19)
:hex("Bytes1", "uint32")
:hex("Bytes2", "uint32")
:field("Guild", "int32")
:field("Flags", "int32")
:field("DynamicFlags", "int32")
:field("Pad", "int32")
local CGCorpse = Struct("CGCorpse", CGObject)
:paddingTo(0xE8)
:embed("Position", Vector3) -- 0x0E8
:paddingTo(0xF8)
:field("FacingAngle", "float") -- 0x0F8
:paddingTo(0x274)
:embed("Scale", Vector3) -- 0x274
:paddingTo(0x290)
:embed("ObjectFields", ObjectFields) -- 0x290
:embed("CorpseFields", CorpseFields) -- 0x2A8
:paddingTo(0x338)
-- #include "load_mouseover_corpse.lua"

44
cheatengine/cgitem.lua Normal file
View file

@ -0,0 +1,44 @@
-- #include "cgobject.lua"
local ObjectFields = Struct("ObjectFields")
:hex("GUID", "uint64")
:field("type", "uint32")
:field("unk", "uint32")
:field("scale", "float")
:field("pad", "uint32")
local ItemEnchantment = Struct("ItemEnchantment")
:array("id", "uint32", 3)
local ItemFields = Struct("ItemFields")
:hex("Owner", "uint64")
:hex("Contained", "uint64")
:hex("Creator", "uint64")
:hex("GiftCreator", "uint64")
:field("StackCount", "int32")
:field("Duration", "int32")
:array("SpellCharges", "int32", 5)
:hex("Flags", "uint32")
:structArray("Enchantment", ItemEnchantment, 12)
:field("PropertySeed", "int32")
:field("RandomPropertiesID", "int32")
:field("Durability", "int32")
:field("MaxDurability", "int32")
:field("CreatePlayedTime", "int32")
:field("Pad", "int32")
local CGItem = Struct("CGItem", CGObject)
:paddingTo(0x3E0)
:embed("ObjectFields", ObjectFields) -- 0x3E0
:embed("ItemFields", ItemFields) -- 0x3F8
:field("itemId", "int32") -- 0x4E0
:field("scale", "float") -- 0x4E4
:paddingTo(0x4F4)
:field("StackCount", "int32") -- 0x4F4
:array("SpellCharges", "int32", 5) -- 0x4F8
:hex("Flags", "uint32") -- 0x50C
:structArray("Enchantment", ItemEnchantment, 12) -- 0x510
:field("Durability", "int32") -- 0x5A0
:paddingTo(0x5A8)
-- #include "load_bagpack_item.lua"

View file

@ -18,7 +18,7 @@ CGObject:field("m_objectScalingEndMS", "int32") -- 0x00A0
CGObject:field("m_objectLastScale", "float") -- 0x00A4
CGObject:ptr("specialEffectPtr") -- 0x00A8
CGObject:field("objectHeight", "float") -- 0x00AC
CGObject:ptr("unkPlayerNamePtr", "int32") -- 0x00B0
CGObject:ptr("unkPlayerNamePtr") -- 0x00B0
CGObject:ptr("CM2Model", "m_model") -- 0x00B4
CGObject:ptr("cmapEntityPtr") -- 0x00B8
CGObject:hex("unkMovementFlags", "int32") -- 0x00BC

View file

@ -0,0 +1,12 @@
local addr, typ = GetCGObjectAddr(readQword(0xC79D10)) -- local player GUID from game connection class
if addr then
if typ == "player" then
local bagpackOffset = 0x1F20
for i = 0, 15, 1 do
local addr, typ = GetCGObjectAddr(readQword(addr + bagpackOffset + i * 8))
if addr ~= 0 and typ == "item" then
loadStructToTable(CGItem, addr)
end
end
end
end

View file

@ -0,0 +1,17 @@
local address = 0x51f838 -- at CGGameUI__HandleObjectTrackChange
debugger_onBreakpoint = nil
function onBreakpoint()
local addr, typ = GetCGObjectAddr(readQword(0x00bd07a0)) -- mouseover guid
if addr then
if typ == "corpse" then
loadStructToTable(CGCorpse, addr)
end
end
debugger_onBreakpoint = nil
debug_removeBreakpoint(address)
debug_continueFromBreakpoint(co_run)
return 1
end
debug_setBreakpoint(address)
debugger_onBreakpoint = onBreakpoint

View file

@ -0,0 +1,12 @@
local addr, typ = GetCGObjectAddr(readQword(0xC79D10)) -- local player GUID from game connection class
if addr then
if typ == "player" then
local bagsOffset = 0x1F00
for i = 0, 4, 1 do
local addr, typ = GetCGObjectAddr(readQword(addr + bagsOffset + i * 8))
if addr ~= 0 and typ == "container" then
loadStructToTable(CGContainer, addr)
end
end
end
end