HenryEx Advanced Cheater
Reputation: 2
Joined: 18 Dec 2011 Posts: 97
|
Posted: Thu Jan 30, 2025 12:01 pm Post subject: Update CE structures with new fields/offsets from Mono |
|
|
function updateStructFromMonoClass( idx_struct, className, doDelete, verbose )
Tried of deleting and recreating your dissect structures after game updates, when offsets have shifted? Don't want to assign all your structure pointers anew and recreate all the local structures you've made?
Well, i was and wrote a simple function to automatically compare a current structure to a certain mono class and update the structure entries with new offsets, or add any entirely new fields into the structure.
This assumes that your structure entry name is identical to the class' field. If a field name changes between updates or you changed the structure entry name, a new entry will be created. You have the option to automatically delete any 'orphaned' structure entries upon update.
idx_struct is the integer index of the structure you want to update.
className is a string of the mono class to compare against.
doDelete == true will delete any entries that don't match the class fields
verbose is an integer, set to 1 or 2 for console output on what the function does
Put this into your autorun folder or paste it into your table's LUA script:
Code: | --- Update existing CE structure with with new offset / fields from a Mono class
-- Allows you to update structure offsets wtihout losing changes to existing fields
-- like structure pointers and local structures
-- @param idx_struct: integer index of CE Structure you want updated
-- @param className: string containing the mono class you want to take fields from
-- @param doDelete: Optional bool, deletes struct entries that don't correspond to current class fields
-- @param verbose: Optional integer; >0 prints info on structure changes, >1 prints all actions
-- @return true if structure was changed, false if not
function updateStructFromMonoClass( idx_struct, className, doDelete, verbose )
if not idx_struct or not className then error('ERROR updateStructFromMonoClass: arguments malformed or missing!') end
if idx_struct + 1 > getStructureCount() then error('ERROR updateStructFromMonoClass: structure index out of bounds!') end
local classId = mono_findClass('', className)
if not classId then error('ERROR updateStructFromMonoClass: no class ID found for given class name!') end
verbose = type(verbose) == 'number' and verbose or 0
local ver1 = verbose > 0 and true or false
local ver2 = verbose > 1 and true or false
local changed = false
local st = getStructure(idx_struct)
local st_name = st.getName()
if ver1 then print( string.format('== Updating structure %s with mono class %s ==',st_name, className) ) end
local st_count = st.Count
local st_entry = {}
for i = 1, st_count do st_entry[i] = st.getElement(i-1) end
local st2 = monoform_exportStructInternal(createStructure(''), classId, true --[[recursive]], false --[[not static]], {'some struct map thing'}, false --[[not global]])
local st2_count = st2.Count
local st2_entry = {}
for i = 1, st2_count do st2_entry[i] = st2.getElement(i-1) end
local st2_tName = {}
local st2_tOffset = {}
for i = 1, st2_count do st2_tName[ st2_entry[i].Name ] = st2_entry[i].Offset end
for i = 1, st2_count do st2_tOffset[ st2_entry[i].Offset ] = st2_entry[i].Name end
-- simple offset adjust for existing fields
st.beginUpdate()
for i = 1, st_count do
local ename = st_entry[i].Name
if st2_tName[ename] then
local newoff = st2_tName[ename]
if st_entry[i].Offset ~= newoff then
if ver1 then print( string.format('Updated offset of %s from %X to %X',ename,st_entry[i].Offset,newoff) ) end
st_entry[i].Offset = newoff
changed = true
else
if ver2 then print( string.format('Offset of %s unchanged from %X',ename,newoff) ) end
end
elseif doDelete then
if ver1 then print( string.format( 'Entry %s not found, removed from structure', ename ) ) end
st_entry[i].destroy()
else
if ver1 then print( string.format( 'Entry %s not found in new field list', ename ) ) end
end
end
st.endUpdate()
if st.Count ~= st_count then -- refresh if struct changed
if ver2 then print('> Structure size changed, updating tables') end
st_entry = {}
st_count = st.Count
for i = 1, st_count do st_entry[i] = st.getElement(i-1) end
changed = true
end
local st_tName = {}
for i = 1, st_count do st_tName[ st_entry[i].Name ] = st_entry[i].Offset end
st.beginUpdate()
for _,v in ipairs(st2_entry) do
if not st_tName[v.Name] then -- check if new entry is in old struct
if ver1 then print( string.format('Field %s not found, adding as new entry',v.Name) ) end
local e = st.addElement()
e.setName( v.getName() )
e.setOffset( v.getOffset() )
e.setVartype( v.getVartype() )
e.setBytesize( v.getBytesize() )
changed = true
end
end
st.endUpdate()
return changed
end |
As a bonus, a small function to automatically update all table structures with the same name as a mono class, using the above function. The "doDelete" and "verbose" parameters get passed on to the above function.
Intentionally skips the "String" structure that gets auto-created by CE's mono features.
Code: | function updateAllMonoStructs( doDelete, verbose )
verbose = type(verbose) == 'number' and verbose or 0
local numStructs = getStructureCount()
local numMonos = 0
local numChanged = 0
for i=0, numStructs-1 do
repeat -- workaround to continue for loop on break
local stName = getStructure(i).Name
local classId = mono_findClass('', stName)
if not classId or stName == 'String' then break end
numMonos = numMonos + 1
local changed = updateStructFromMonoClass(i, stName, doDelete, verbose)
if changed then
numChanged = numChanged + 1
if verbose > 0 then print(string.format('CHANGED: %s\n',stName)) end
else
if verbose > 0 then print(string.format('UNCHANGED: %s\n',stName)) end
end
until true
end
if verbose > 0 then print('Number of Mono Structures found:', numMonos) end
if verbose > 0 then print('Number of Structures updated:', numChanged) end
end
|
edit: changed calling syntax from ':' to '.', since the former breaks the script in newer versions of CE. Hmmm.
|
|