Log in

View Full Version : Charlist reader for Tibia 9.71 - made with Delphi 7 + update 10.11



blackd
11-16-2012, 17:25
Many people is asking me about the new char list of Tibia 9.71, so I have decide to share here the code of a simple function to read the new charlist in Tibia.
Code is Delphi 7, and it should be easy to port to any other language.

7598

The important parts:



// This Delphi 7 procedure can read the new charlist in Tibia 9.71
// -Made by Blackd-
procedure TForm3.charlist();
var
i,address,address_end ,lastchar:Cardinal;
Nick, World : string;
Base_Address, remoteadr: Cardinal;
nametype: Cardinal;
begin
// in this simplified function we will think that there is
// a single Tibia client running.
// (Other way every function should have a ProcessId paramater to
// handle multiclient correctly)
ProcessID := func.ProcessIDFromAppname32('Tibia.exe');
// get base address. One time is enough.
Base_Address := Integer(func.GetModuleBaseAddress(ProcessID, 'Tibia.exe'));
// get index of selected char
ClientSelectedCharId := MemReadInteger(charlist_selected - $400000 + Base_Address);

StringList.Clear;

// we must do some maths to know how many chars are loaded
address := func.ReadMemInteger(charlist_start - $400000 + Base_Address);
address_end := func.ReadMemInteger(charlist_end - $400000 + Base_Address);
lastchar := ((address_end - address) div charlist_dist) - 1 ;

for i:=0 to lastchar do
begin
// union type: string can be stored here or in other place.
// depends on the value of nametype
nametype := func.ReadMemInteger(address + dist_name_type);
if nametype = 15 then
// nametype = hex 0F => Read name here directly
Nick := func.MemReadString(address+dist_name )
else
begin
// nametype = other value => Read address here
remoteadr := func.ReadMemInteger(address+dist_name );
// then read name in that address
Nick := func.MemReadString(remoteadr);
end;
// world is always there directly
World := func.MemReadString(address+dist_world );

// check if this char was the current char:
if (i=ClientSelectedCharId) then
begin
ClientSelectedCharName:=Nick;
ClientSelectedCharServer:=World;
end;
// add item to our list
StringList.Add(Nick+'|'+World);
address := address + charlist_dist;
end;
end;




StringList := TStringList.Create;
charlist_start:=$946CB0;
charlist_selected:=$946CFC;
charlist_end:=$946CB4;
charlist_dist:=72;
dist_name:=4;
dist_world:=32;
dist_name_size:=20;
dist_name_type:=24;
ClientSelectedCharId:=0;
ClientSelectedCharName:='';
ClientSelectedCharServer:='';


7598

blackd
08-24-2013, 11:58
For people who is asking me for updated addreses for Tibia 10.11 :



charlist_start:=$951A48;
charlist_selected:=$951AB4;
charlist_end:=$951A4C;
charlist_dist:=120;
dist_name:=4;
dist_world:=32;
dist_name_size:=20;
dist_name_type:=24;


new function:



procedure TTibiaMainThread.ClientGetCharList;
var
i,address,address_end:Cardinal;
Nick, World : string;
entry_type: Cardinal;
remoteadr: Cardinal;
namesize,nametype: Cardinal;

begin
ClientSelectedCharId := func.ReadMemInt(TibiaWndHandle, TibiaAddr.OFFSET_SELECTED_CHAR);
PlayerCharList.Clear;
address := func.ReadMemInt(TibiaWndHandle, TibiaAddr.POINTER_CHARLIST);
address_end := func.ReadMemInt(TibiaWndHandle, TibiaAddr.charlist_end);
for i:=0 to address_end do
begin
entry_type:= func.ReadMemInt(TibiaWndHandle, address);
namesize:= func.ReadMemInt(TibiaWndHandle, address+ TibiaAddr.dist_name_size);
if (namesize=0) or (entry_type=0) then
break
else
begin
nametype := func.ReadMemInt(TibiaWndHandle, address + TibiaAddr.dist_name_type);
if nametype = 15 then
Nick := func.ReadMemStr(TibiaWndHandle, address+TibiaAddr.dist_name)
else
begin
remoteadr := func.ReadMemInt(TibiaWndHandle, address+TibiaAddr.dist_name);
Nick := func.ReadMemStr(TibiaWndHandle, remoteadr);
end;
World := func.ReadMemStr(TibiaWndHandle, address+TibiaAddr.dist_world);
if (i=ClientSelectedCharId) then
ClientSelectedCharName:=Nick;
PlayerCharList.Add(Nick+'|'+World);
address := address + TibiaAddr.charlist_dist;
end;
end;
end;

blackd
08-27-2013, 02:03
char reader function in Visual Basic 6 , for tibia 10.11:



Public Function UpdateCharListFromMemory3(idConnection As Integer, maxr As Integer) As Long
Dim i As Long
Dim address As Long
Dim address_end As Long
Dim nick As String
Dim world As String
Dim entry_type As Long
Dim remoteadr As Long
Dim namesize As Long
Dim nametype As Long
Dim dist_name_size As Long
Dim dist_name_type As Long
Dim dist_name As Long
Dim dist_world As Long
Dim selectedNick As String
Dim charlist_dist As Long
Dim tibiaclient As Long
Dim ClientSelectedCharId As Long
Dim currentID As Long
Dim rememberPort As Long
dist_name_size = 20
dist_name_type = 24
dist_name = 4
dist_world = 32
charlist_dist = 120
tibiaclient = ProcessID(idConnection)
ClientSelectedCharId = Memory_ReadLong(adrSelectedCharIndex, tibiaclient)

address = Memory_ReadLong(adrCharListPtr, tibiaclient)
address_end = Memory_ReadLong(adrCharListPtrEND, tibiaclient)
currentID = 0
i = address
ResetCharList2 idConnection
Do
'Debug.Print "current Address=&H" & Hex(i)
entry_type = Memory_ReadLong(i, tibiaclient, True)
namesize = Memory_ReadLong(i + dist_name_size, tibiaclient, True)
If ((namesize = 0) Or (entry_type = 0)) Then
Exit Do
Else
nametype = Memory_ReadLong(i + dist_name_type, tibiaclient, True)
If nametype = 15 Then
nick = readMemoryString(tibiaclient, i + dist_name, , True)
Else
remoteadr = Memory_ReadLong(i + dist_name, tibiaclient, True)
nick = readMemoryString(tibiaclient, remoteadr, , True)
End If
world = readMemoryString(tibiaclient, i + dist_world, , True)
If (currentID = ClientSelectedCharId) Then
selectedNick = nick
' Debug.Print "Nick=" & nick & " ; Server=" & world & " * SELECTED"
Else
' Debug.Print "Nick=" & nick & " ; Server=" & world
End If
rememberPort = GetGameServerPort(world)
AddCharServer2 idConnection, nick, world, "127", "0", "0", "1", rememberPort
End If
i = i + charlist_dist
currentID = currentID + 1
Loop Until i >= address_end
'Debug.Print "Read completed"
UpdateCharListFromMemory3 = 0
End Function