Ok, here goes some quick and dirty test to make, here takes 1.5s to index the tables (only doing that once of course) and then 16ms to update inventory, of course we need more data than the scarse info i'm getting but i hope you will see the point...
Still working on a better way to index tables, tables are not lineal those bitches are fragmentated into blocks (yes the tables are huge) i managed to connect all blocks but i'm using some "brute force" to get pointers to the next part when is not in the last item (in most cases it is) well i'll let the code speak for itself, i see alot of potential here...
P.S.: Some strings and some function names in spanish, old habit of writing in english will be, i hope, good for you to read because most of it is in english...
Code: Select all
include("addresses.lua");
include("functions.lua");
local inventarioBase = 0x9B8948;
local tablasBase = 0x9CC224;
local tablasBaseOffset = 0x28;
local idOffset = 0;
local cantidadOffset = 0x10;
local itemInfoOffset = 0x10;
local skillsBase = 0x9C58E0;
local punteroTabla;
local punteroTablaFinal;
local proc = getProc();
local tablas = {};
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 = "<UNKNOWN>";
self.Ranges = {};
if( self.Address ~= nil and self.Address ~= 0 ) then self:Update(); end;
end
);
function CTDef:Update()
self.StartId = memoryReadInt(proc, self.Address + 0xC );
-- self.Name = memoryReadString(proc, self.Address + 36);
local lastId = self.StartId;
local currId;
local lastStartId = self.StartId;
local lastStartDir = self.Address;
local currItemDir = self.Address;
local lastItemDir = self.Address;
local tryNumber = 1;
-- printf("Tabla comienza con id: %d\t\t Dir: %X\n", self.StartId, self.Address);
while ( lastId ~= nil and lastId ~= 0 ) do
currItemDir = currItemDir - 32; -- Descontamos 32 bytes para pasar al siguiente.
currId = debugAssert(memoryReadInt(proc, currItemDir + 0xC ), "[GetInfoItem] No se pudo leer el id"); -- 12 bytes offset del id de objeto
self.EndId = currId;
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(tablas) 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 ( found == false ) then
table.insert(self.Ranges, CTRange(lastStartId, lastId, lastStartDir));
cprintf( cli.yellow, "Agregando rango. Inicio: %d\tFin: %d\tDir: %X\tTabla: %d\n", lastStartId, lastId, lastStartDir, #tablas );
end;
self.EndId = lastId;
currItemDir = GetNextTableAddress( lastItemDir, tryNumber );
if ( currItemDir ~= nil ) then
currId = debugAssert(memoryReadInt(proc, currItemDir + 0xC ), "No se pudo leer el id en la tabla continuada"); -- 12 bytes offset del id de objeto
if ( currId == nil or currId == 0 or ( ( currId > (lastId + 2) ) or ( currId < (lastId - 2) ) ) ) then
-- currItemDir = lastItemDir;
break;
else
tryNumber = 1;
self.EndId = currId;
lastStartId = currId;
lastStartDir = currItemDir;
end;
else
break;
end;
end;
lastId = currId;
lastItemDir = currItemDir;
end;
end;
CItem = class(
function (self, ptr)
self.Address = ptr;
self.Id = 0;
self.Name = "<UNKNOWN>";
if( self.Address ~= nil and self.Address ~= 0 ) then self:Update(); end;
end
);
function CItem:Update()
local _oldAddress = self.Address;
self.Address = memoryReadIntPtr(proc, self.Address + 0x10, 0x8);
self.Id = debugAssert(memoryReadInt(proc, self.Address ), "No se pudo leer el id");
-- Caso especial para las cartas
if ( self.Id >= 770000 and self.Id <= 771000 ) then
self.Name = "<CARD>";
else
local nameAddress = debugAssert(memoryReadInt(proc, self.Address + 0xC), "No se pudo leer puntero de nombre"); -- 12 bytes offset del nombre
if( nameAddress == nil or nameAddress == 0 ) then
tmp = nil;
else
tmp = debugAssert(memoryReadString(proc, nameAddress), "No se pudo leer el nombre");
end;
if tmp ~= nil then
self.Name = tmp;
else
self.Name = "<UNKNOWN>";
end;
end;
end;
function ObtenerPunterosTablas()
local dirPunteroTabla = memoryReadIntPtr(proc, tablasBase, tablasBaseOffset);
punteroTabla = dirPunteroTabla;
punteroTablaFinal = memoryReadInt(proc, dirPunteroTabla + 0x4);
cprintf(cli.yellow, "Dir tablas: %x \t Final: %x\n\n\n", punteroTabla, punteroTablaFinal);
end;
function GetNextTableAddress( ptr, try )
local _address;
_address = memoryReadInt( proc, ptr + 0x4 );
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
local lastId = memoryReadInt( proc, ptr + 0xC ); -- 12 bytes offset del id
local found = false;
for i = 1, 10 do -- 10 lineas deberían ser suficientes...
_address = memoryReadInt( proc, ( ptr + ( i * 32 ) ) + 0x4 ); -- Retrocedemos de a una línea para ver si encontramos la dir que buscamos
tmpID = memoryReadInt( proc, _address + 0xC ); -- 12 bytes offset del id
-- printf("Leimos: %d\n", tmpID);
if ( tmpID == lastId + 1 and _address ~= ptr ) then
-- Lo encontramos, podemos salir del bucle y devolver la dir.
found = true;
print("Encontrado por fuerza bruta\n");
break;
end;
end;
if not found then
_address = nil;
end;
end;
end;
-- cprintf( cli.red, "Recibido: %X\tDevolviendo: %X\n" ,ptr, _address or 0 );
return _address;
end;
-- Guardar las tablas
function GuardarTablas()
local punteroTablaReal = memoryReadInt(proc, punteroTabla);
local punteroTablaDatos;
local i = 0;
while ( i < 28 ) do
local nombre = memoryReadString(proc, punteroTablaReal + 38);
-- printf("Nombre: %s\n", nombre);
local punteroDatosTemporal = memoryReadIntPtr(proc, punteroTablaReal, 0x124);
if punteroDatosTemporal ~= nil then
local punteroDatos = memoryReadInt(proc, punteroDatosTemporal + 0x28);
-- Descontamos los 32 bytes de la línea del nombre
punteroDatos = punteroDatos - 32;
local primerId = memoryReadInt(proc, punteroDatos + 0xC ); -- 12 bytes offset del id de objeto
local tabla = CTDef(punteroDatos);
tabla.Name = nombre;
table.insert( tablas, tabla);
end;
i = i + 1;
punteroTablaReal = memoryReadInt(proc, punteroTabla + ( i * 4 ) );
end;
end;
function RecorrerInventario()
local intemOffset = 0;
local id, cantidad;
local itemDir = inventarioBase;
local itemInfo;
-- local timeStart = getTime();
for i = 0, 60 do
itemDir = inventarioBase + (68 * i); -- 68 bytes tamaño de estructura por item en el inventario
id = memoryReadInt(proc, itemDir + idOffset );
if id ~= nil and id ~= 0 then
cantidad = memoryReadInt(proc, itemDir + cantidadOffset );
itemInfo = GetInfoItem(id);
if itemInfo then
printf( "ID: %d\tNombre: %s\t\t\tCantidad: %d\n", id, itemInfo.Name , cantidad );
end;
end;
end;
-- printf( "Tardamos en recorrer el inventario: %d\n", deltaTime( getTime(), timeStart ) );
end;
function GetInfoItem( id )
local _address = GetItemAddress( id );
if _address ~= nil and _address ~= 0 then
return CItem( _address );
end;
printf( "Devolviendo nulo para ID: %d\n", id );
return nil;
end;
function GetTableForID( id )
for _, _table in ipairs( tablas ) do
if ( id >= _table.StartId and id <= _table.EndId ) then
return _table;
end;
end;
printf( "Tabla no encontrada para 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
-- _address = _rango.StartAddress;
tmp = id - _range.Start;
-- Restamos 32 bytes por el número de items de diferencia que hay entre el primer id del rango y el id que nos pasaron
_address = _range.StartAddress - ( tmp * 32 );
-- Comprobamos que sea esta, hay items cruzados, no tengo muy claro porqué pero es asi...
local tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8);
if ( id ~= memoryReadInt( proc, tmpAddress ) ) then
-- Lo buscamos uno después...
_address = _range.StartAddress - ( ( tmp - 1 ) * 32 );
tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8);
if ( id ~= memoryReadInt( proc, tmpAddress ) ) then
-- Lo buscamos uno antes...
_address = _range.StartAddress - ( ( tmp + 1 ) * 32 );
tmpAddress = memoryReadIntPtr(proc, _address + 0x10, 0x8);
if ( id ~= memoryReadInt( proc, tmpAddress ) ) then
-- No pudimos encontrarlo, nos damos por vencidos...
_address = nil;
end;
end;
end;
end;
end;
end;
return _address;
end;
function EnumerarSkills()
local currSkillId = memoryReadInt( proc, skillsBase );
local i = 0;
local skillInfo;
while currSkillId ~= -1 do
if ( currSkillId ~= 0 ) then
skillInfo = GetInfoItem( currSkillId );
if skillInfo ~= nil then
printf("ID: %d\tDir: %X\tNombre: %s\n", skillInfo.Id, skillInfo.Address, skillInfo.Name);
else
printf("Error al obtener el skill con ID: %d\n", currSkillId);
end;
end;
i = i + 1;
currSkillId = memoryReadInt( proc, skillsBase + ( i * 4 ) );
end;
end;
-- 491587 Esencia de Magia
function main()
local timeStart = getTime();
ObtenerPunterosTablas();
-- printf("Una: %X\n", memoryReadIntPtr(proc, 0x1854920, 0x124));
GuardarTablas();
printf( "Tardamos en enumerar las tablas: %d\n", deltaTime( getTime(), timeStart ) );
timeStart = getTime();
RecorrerInventario();
printf( "Tardamos en enumerar el inventario: %d\n", deltaTime( getTime(), timeStart ) );
timeStart = getTime();
EnumerarSkills();
printf( "Tardamos en enumerar los skills: %d\n", deltaTime( getTime(), timeStart ) );
end;
startMacro(main, true);