include(".../addresses.lua"); include(".../functions.lua"); local tablePointer; local endTablePointer; local itemSize = 32; local proc = getProc(); local tables = {}; -- Internal debuging use only... local debugTableIndexes = false; local debugTableRanges = true; CTRange = class( function(self, _start, _end, startAddress) self.Start = _start; self.End = _end; self.StartAddress = startAddress; end ); CTDef = class( function (self, ptr) self.Address = ptr; self.EnAddress = 0; self.StartId = 0; self.EndId = 0; self.Name = ""; self.Ranges = {}; if( self.Address ~= nil and self.Address ~= 0 ) then self:Update(); end; end ); function CTDef:Update() self.StartId = memoryReadInt(proc, self.Address + addresses.idOffset ); self.EndId = 0; local lastId = self.StartId; local currId; local lastStartId = self.StartId; local lastStartDir = self.Address; local currItemDir = self.Address; local lastItemDir = self.Address; if ( debugTableIndexes ) then printf("Table starts with id: %d\t\t Dir: %X\n", self.StartId, self.Address); end; while ( lastId ~= nil and lastId ~= 0 ) do currItemDir = currItemDir - itemSize; -- We move itemSize bytes up to go to next one currId = memoryReadInt(proc, currItemDir + addresses.idOffset ); -- 12 bytes offset id object if ( currId == nil or currId == 0 or ( ( currId > (lastId + 2) ) or ( currId < (lastId - 2) ) ) ) then -- Primero que nada agregamos el rango encontrado, si hace falta... local found = false; for _, _table in ipairs(tables) do if ( lastStartId >= _table.StartId and lastId <= _table.EndId ) then found = true; break; end; end; for _, _range in ipairs(self.Ranges) do if ( lastStartId >= _range.Start and lastId <= _range.End ) then found = true; break; end; end; if ( (lastId and not self.EndId) or self.EndId < lastId ) then self.EndId = lastId; end; if ( found == false ) then -- We dind't find any more ids in range, add this one to the table table.insert(self.Ranges, CTRange(lastStartId, lastId, lastStartDir)); if ( debugTableRanges ) then cprintf( cli.yellow, "Adding range. Start: %d\tEnd: %d\tAddress: %X\tTable#: %d\n", lastStartId, lastId, lastStartDir, #tables ); end; end; currItemDir = GetNextTableAddress( lastItemDir ); if ( currItemDir ~= nil ) then currId = memoryReadInt(proc, currItemDir + addresses.idOffset ); -- 12 bytes offset object id if ( currId == nil or currId == 0 or ( ( currId > (lastId + 2) ) or ( currId < (lastId - 2) ) ) ) then -- no more ids for current table break; else self.EndId = currId; lastStartId = currId; lastStartDir = currItemDir; end; else break; end; end; if ( currId and currItemDir and self.StartId > currId ) then lastStartId = currId; lastStartDir = currItemDir; self.StartId = currId; self.Address = currItemDir; end; lastId = currId; lastItemDir = currItemDir; end; end; function GetTablesPointers() local tablePointerDir = memoryReadIntPtr( proc, addresses.tablesBase, addresses.tablesBaseOffset ); tablePointer = tablePointerDir; endTablePointer = memoryReadInt(proc, tablePointerDir + 0x4); -- cprintf(cli.yellow, "Tables dir: %x \t Final: %X\n\n\n", tablePointer, endTablePointer); end; function GetNextTableAddress( ptr, try ) local _address; local lastId = memoryReadInt( proc, ptr + addresses.idOffset ); -- 12 bytes offset id local found = true; local tmpID; -- Here offsets seem to vary, in some tables you get the next dir in 0x4 and in others in 0x8, should be a pattern but didn't find it yet... _address = memoryReadInt( proc, ptr + 0x4 ); tmpID = memoryReadInt( proc, _address + addresses.idOffset ); -- 12 bytes offset id if _address == nil or ( memoryReadInt( proc, _address + 0x4 ) ~= ptr and memoryReadInt( proc, _address ) ~= ptr ) then _address = memoryReadInt( proc, ptr + 0x8 ); if _address == nil or ( memoryReadInt( proc, _address + 0x4 ) ~= ptr and memoryReadInt( proc, _address ) ~= ptr ) then if debugTableIndexes then print("Fail 1\n"); end; found = false; for i = 1, 10 do -- 10 lines should be enough... _address = memoryReadInt( proc, ( ptr + ( i * itemSize ) ) + 0x4 ); -- we go back one item to see if it fits the id we are looking for tmpID = memoryReadInt( proc, _address + addresses.idOffset ); if debugTableIndexes then printf("Readed 1: %d\n", tmpID or 0); end if ( tmpID == lastId + 1 and _address ~= ptr ) then -- We found it, we can exit and return the address. found = true; if debugTableIndexes then print("Found by brute force.\n"); end; break; end; end; if not found and debugTableIndexes then print("Fail 2\n"); end; end; end tmpID = memoryReadInt( proc, _address + addresses.idOffset ); -- 12 bytes id offset if ( tmpID ~= lastId + 1 ) then if debugTableIndexes then print("Falla 3\n"); printf("\rTenemos ID: %d\En dir: %X\n", tmpID or 0, _address ); end; found = false; for i = 1, 10 do -- 10 lines should be enough... _address = _address + ( i * itemSize ); -- we go back one item to see if it fits the id we are looking for tmpID = memoryReadInt( proc, _address + addresses.idOffset ); -- 12 bytes offset del id if debugTableIndexes then printf("\rReaded 2: %d\n", tmpID or 0 ); end; if ( tmpID == lastId + 1 ) then -- We found it, we can exit and return the address. found = true; if debugTableIndexes then print("Found by brute force 2\n"); end; break; end; end; end; if not found then _address = nil; end; if debugTableIndexes then cprintf( cli.red, "Received: %X\tReturning: %X\n" ,ptr, _address or 0 ); end; return _address; end; function GetTableForID( id ) for _, _table in ipairs( tables ) do if ( id >= _table.StartId and id <= _table.EndId ) then return _table; end; end; printf( "Table not found for ID: %d\n", id ); return nil; end; function GetItemAddress( id ) local _table = GetTableForID( id ); local _address; if _table ~= nil then for _, _range in ipairs( _table.Ranges ) do if ( id >= _range.Start and id <= _range.End ) then tmp = id - _range.Start; -- We substract 32 bytes (itemSize) multiplied by the the number that is the difference between the id we get and the range start _address = _range.StartAddress - ( tmp * 32 ); -- We check if this is the right one, there are mixed ids, don't know why i think is just instantiation of tables problem... local tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8); if ( id ~= memoryReadInt( proc, tmpAddress ) ) then -- We search one after... _address = _range.StartAddress - ( ( tmp - 1 ) * 32 ); tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8); if ( id ~= memoryReadInt( proc, tmpAddress ) ) then -- We search one before... _address = _range.StartAddress - ( ( tmp + 1 ) * 32 ); tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8); if ( id ~= memoryReadInt( proc, tmpAddress ) ) then -- Couldn't find it, we give up... _address = nil; end; end; end; end; end; end; if ( _address ~= nil ) then _address = memoryReadIntPtr( proc, _address + 0x10, 0x8 ); end return _address; end; function LoadTables() GetTablesPointers(); local realTablePointer = memoryReadInt(proc, tablePointer); local punteroTablaDatos; local i = 0; while ( i < 28 ) do local name = memoryReadString(proc, realTablePointer + 38); -- This isn't really necessary but is here for debuging purposes... if debugTableIndexes then printf("Name: %s\n", name); end; local dataPointerTemporal = memoryReadIntPtr(proc, realTablePointer, addresses.tableStartPtrOffset); if dataPointerTemporal ~= nil then local dataPointer = memoryReadInt(proc, dataPointerTemporal + addresses.tableDataStartPtrOffset); -- We move up 32 bytes from the name line dataPointer = dataPointer - itemSize; local primerId = memoryReadInt(proc, dataPointer + addresses.idOffset ); -- 12 bytes offset del id de objeto local _table = CTDef(dataPointer); _table.Name = name; table.insert( tables, _table); end; i = i + 1; realTablePointer = memoryReadInt(proc, tablePointer + ( i * 4 ) ); end; end;