As a word of introduction I'd like to thank the person here at TPForums (I can't remember thy name unfortunately ) that made me realize this is possible with Delphi.
The battlelist (and other static structures) can be read into your program in one memory read given that you prepare for it accordingly.
This tutorial is to show how it's done (one of two ways I know).
Our example prog will read battlelist in one memory read.
The example is based on 7.7 client as I'm coding things for RealOTS currently.
This can be easily adapted to any other client with a small bit of work though.
Let's get started.
First off we have to declare our structure that will hold the single battlelist entry.
I did it this way:
[code=delphi]type
TBattleListEntry = record
ID: cardinal;
name: array[0..31] of byte;
posX, posY, posZ: cardinal;
offsetX, offsetY: cardinal;
unknown1: array[0..4] of cardinal;
isWalking, direction: cardinal;
unknown2: array[0..2] of cardinal;
outfit: array[0..4] of cardinal;
//outfit[0] // Looktype
//outfit[1] // Head
//outfit[2] // Body
//outfit[3] // Legs
//outfit[4] // Feet
lightRange, lightColor: cardinal;
blackSquare: array[0..1] of cardinal;
HP, Speed, Visible: cardinal;
Skull, Shield, unknown3: cardinal;
end;[/code]BEWARE! Types and order of variables in the structure is CRUCIAL! It must preserve the data format in the client memory!
After that we also have to declare an array that will hold all of the battlelist entries:
[code=delphi]type
TBattleList = record
list: array[0..149] of TBattleListEntry;
end;[/code]
Then we can declare some constant values, like memory addresses and offsets we use:
[code=delphi]const
stBL = $0056C8B0;[/code]
Now we are ready for memory reading.
First thing of'course is to open process for memory reading, which is quite a common thing to do and I'll skip it here.
It's in the example in attachment though.
Now... any time we need to get some actuall info from battle list we read it like this:
[code=delphi]ReadProcessMemory(tProcess, ptr(stBL), @mBL, $5B68, nobr);[/code]Where:
- stBL is the battle list start address (ID of first creature entry) we declared as a constant;
- mBL is local variable for whole battle list declared like this:
[code=delphi]mBL: TBattleList; // your structure to hold BattleList[/code]- $5B68 is the size of battle list (in HEX) - basicly it's one creature entry size * number of entries ($9C * 150 in this case);
- nobr is an integer for Number Of Bytes Read.
This line reads whole battlelist contents into our structure directly. (Thanks Stiju for pointing this out ^^)
Voila!
You now have a copy of the battlelist in your structure, with a very comfortable access to it.
For instance:
To get the HP bar of first creature in battle list you have to do this:
[code=delphi]HP := mBL.list[0].HP;[/code]Where:
- HP is an integer;
- 0 - first entry in our battlelist structure.
Example sources in the attachment.
Have fun & Good luck ^^
[attachment=993]
[edit]
PS.
To get the creature name from byte array into a string you just do:
Code:
name := PChar(@mBL.list[i].name); // copy creature name into string var
Where name is a variable of type string.