Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant archive_postsperpage - assumed 'archive_postsperpage' (this will throw an Error in a future version of PHP) in ..../archive/index.php on line 456
Printing a list of names from the battlelist [Archive] - Forums

PDA

View Full Version : Printing a list of names from the battlelist



Evan
01-18-2013, 05:27 PM
I am very new to this stuff, I have followed ManInTheCave's short tutorial on creating your first program.
First of all, I apologize if this is not the right place to post, I could not find any support board anywhere.

So, I was able to create a program that prints the player's health, mana, and position:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace playerPosition
{
public partial class MainForm : Form
{
/* These two variables are very important to reading memory. You've probably seen the word "BasedAddress" a
* lot if you've been trying to program recently, and the variable "Base" is what will store this address
* as an integer. In order to obtain the BaseAddress we will use a variable to store information on the
* Tibia Client, making it a little easier to do. */
public static UInt32 Base = 0;
public static Process Tibia = null;

/* These are the integer variables which will store our characters information, such as health, mana,
* experience, magic level, level, capacity, coordinates, and exp to level. */
public int hp;
public int mp;
public int xp;
public int ml;
public int lvl;
public int cap;
public int xpos;
public int ypos;
public int zpos;
public int xpup;

/* In these we will store some information in a string format, such as our name, first quest in the quest log. */
public string name;
public string quest;

/* Here comes a list of our addresses which we will read. Note that I posted each address twice, once just an
* address, and once the address + 0x400000. If you're using Windows XP or have ASLR disabled for some miscallanious
* reason, you should use the address with L on the end. For instance for the Exp Address, use XpAdrL, not XpAdr.
* You'll also then need to remove the other ASLR related material from this, we'll get to that in a while though. */

// XOR Address
UInt32 Pxor = 0x3B6EF0;
// EXP Address
UInt32 XpAdr = 0x286F00;
UInt32 XpAdrL = 0x286F00 + 0x400000;
// Mana Address
UInt32 MpAdr = 0x3B6F44;
UInt32 MpAdrL = 0x3B6F44 + 0x400000;
// Health Address
UInt32 HpAdr = 0x54C000;
UInt32 HpAdrL = 0x54C000 + 0x400000;
// Cap Address
UInt32 CapAdr = 0x578E94;
UInt32 CapAdrL = 0x578E94 + 0x400000;
// Level Address
UInt32 LvlAdr = 0x3ABFC8;
UInt32 LvlAdrL = 0x3ABFC8 + 0x400000;
// Magic Address
UInt32 MlAdr = 0x3ABFD0;
UInt32 MlAdrL = 0x3ABFD0 + 0x400000;
// Name Address
UInt32 NameAdr = 0x54C00C;
UInt32 NameAdrL = 0x54C00C + 0x400000;
//XPos Address
UInt32 XAdr = 0x583EA8;
UInt32 XAdrL = 0x583EA8 + 0x400000;
//YPos Address
UInt32 YAdr = 0x583EAC;
UInt32 YAdrL = 0x583EAC + 0x400000;
//ZPos Address
UInt32 ZAdr = 0x583EB0;
UInt32 ZAdrL = 0x583EB0 + 0x400000;
//First Quest Address
UInt32 QstAdr = 0x3AD0D5;
UInt32 QstAdrL = 0x3AD0D5 + 0x400000;

// Import WindowsAPI Function to read process memory without using unmanaged code directly.
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

/* Read bytes from address - This is a function, effectively, which takes X, Y, and Z input, and uses it to get A output.
* It will take an window handle, in form of an IntPtr, an address, in form of a 64 bit Int, and BytesToRead, in form of a tiny int. */
public static byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
{
IntPtr ptrBytesRead;
// Declare a buffer, this is the no mans land in which the information travels to get from the memory address to our programs memory.
byte[] buffer = new byte[BytesToRead];
// Call to the windows function to get the information.
ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);

// The result of this function will be the contents of buffer. Any information which was stored at the memory address passed in, is now in the buffer.
return buffer;
}

// This should convert the contents of "buffer" - or any other byte variable - to a usable Int32.
public static int ReadInt32(IntPtr Handle, long Address)
{
return BitConverter.ToInt32(ReadBytes(Handle, Address, 4), 0);
}

public MainForm()
{
InitializeComponent();
}

private void MainForm_Load(object sender, EventArgs e)
{
Process[] TibiaProcess = Process.GetProcessesByName("Tibia");
Tibia = TibiaProcess[0];
Base = Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32());

DateTime theDate = DateTime.Now;
label8.Text = (theDate.ToString());

label7.Text = ASCIIEncoding.Default.GetString(ReadBytes(Tibia.Ha ndle, (NameAdr + Base) + (1299 * 5), 32));

healthBox.Text = (Convert.ToString(ReadInt32(Tibia.Handle, (HpAdr + Base)) ^ ReadInt32(Tibia.Handle, (Pxor + Base))));
manaBox.Text = (Convert.ToString(ReadInt32(Tibia.Handle, (MpAdr + Base)) ^ ReadInt32(Tibia.Handle, (Pxor + Base))));

posXBox.Text = (Convert.ToString(ReadInt32(Tibia.Handle, (XAdr + Base))));
posYBox.Text = (Convert.ToString(ReadInt32(Tibia.Handle, (YAdr + Base))));
posZBox.Text = (Convert.ToString(ReadInt32(Tibia.Handle, (ZAdr + Base))));

listView1.Items.Clear();
var items = listView1.Items;
items.Add("Bob");
items.Add("Joe");
items.Add("Kim");
}

private void updateBtn_Click(object sender, EventArgs e)
{
this.MainForm_Load(this, null);
}
}
}

I apologize if this is not the right tag, if not, someone point me to the right tags for this code.
Note, the listview items are just there to show that I have a working table, I can certainly loop the names into the table.


Anyways, let's say I want to loop all the names from the battle list into the table, how do I do that?
What I am specifically confused about is reading the memory for the names.

I am getting all of the addresses from BlackD's collection: http://www.blackdtools.com/forum/showthread.php?59833-9-81-Blackd-Tibia-addresses-9-81
I assume adrNameStart=&H94C008 is the start address (battleListAddress).

Now what I don't understand is the rest of DarkstaR's formula:
battleListAddress + (battleListSize * index) + nameOffset

Can someone point me to the right direction?

Xavious
01-18-2013, 06:13 PM
There are many different ways to scan your battlelist, here is one way that is fairly simple. You do however need to know the correct start address and its distances.


for (uint i = Addresses.Battlelist.Start; i < Addresses.Battlelist.End; i += Addresses.Battlelist.StepCreatures)
{
if (Memory.ReadByte(i + Addresses.Creature.DistanceIsVisible) == 1)
{
list.Add(Memory.ReadString(i + Addresses.Creature.Name));
}
}


And this is how you can get the battlelist end address


Battlelist.End = Battlelist.Start + (Battlelist.StepCreatures * Battlelist.MaxCreatures);



However it would be better to store creatures addresses when scanning through your battlelist and use a Creature class with battlelist distances to get its different values

Evan
01-18-2013, 07:00 PM
Yeah, I was able to speak with Blaster_89, he was kind enough to help me out and give me a lecture.
I appreciate your help too Xavious, thanks. Hopefully this may help others who may ask for a similar question.

Blequi
01-18-2013, 08:06 PM
I made a simple creature names reader (in Lua) and tried to explain each step as easy as I could.


Open Cheat Engine
Attach to Tibia
Ctrl+Alt+L
Paste the code (read it carefully, each step is explained)






tibiaExe = getAddress("Tibia.exe") -- It's "Tibia.exe" in static addresses
-- so-called "Base Address"

blStart = 0x54C008 + tibiaExe -- where creatures array begins
blStep = 0xB0 -- (or 176 decimal) amount of bytes each creature contains
blMax = 1300 -- max count of creatures availables

creatureIdOffset = 0x0 -- (or 0 decimal) creature id isn't offset'd, so leave it 0.

creatureNameOffset = 0x4 -- (or 4 decimal) creature name is offset'd 4 bytes
-- from beginning

creatureIsValidOffset = 0xAC -- (or 172 decimal) creature is valid is offset'd by 172 bytes

-- we will loop through a simple array, so we need an index like i and our 0-based loop as follows, from 0 to blMax - 1
for i = 0, blMax - 1 do

-- now, we are placed at beginning of the i-th creature data
creatureAddress = blStart + i * blStep

-- Address of creature's id
creatureIdAddress = creatureAddress + creatureIdOffset

-- Read value contained in creatureIdAddress (creature id)
creatureId = readInteger(creatureIdAddress)

-- most likely, we only need creatures with id other than 0
-- so we will check it.
if (creatureId ~= 0) then

-- we want know if the creature is still valid,
-- because dead creatures, so far creatures or not available at all
-- won't be included in the search

-- Address of creature is valid
creatureIsValidAddress = creatureAddress + creatureIsValidOffset

-- Read value contained in creatureIsValidAddress (creature is valid)
-- 0 -> invalid, 1 -> valid
creatureIsValid = readInteger(creatureIsValidAddress) == 1

-- we will display only valid creatures
if (creatureIsValid) then

-- Address of creature's name
creatureNameAddress = creatureAddress + creatureNameOffset

-- Read value contained in creatureNameAddress (creature name)
creatureName = readString(creatureNameAddress)

-- printing creature name
print(creatureName)
end
else
-- when we face a creature with id == 0, we won't find creatures anymore
break
end
end

XtrmJash
01-18-2013, 10:58 PM
I'll explain to you the system for reading the BattleList:

The battle list looks a little like this:

Name
HealthPercent
PosX
PosY
PosZ

Let's just take Name and HealthPercent. The actual battle list contains a LOT more information, so bare that in mind when eventually reading it.

We can know that the "Name" is a certain length. I'm not sure exactly what it is, but let's say it is 32 bytes, for arguments sake. We also can know that the HealthPercent is a certain length, probably 4 bytes or so, since that's plenty of bytes for this example. Let's also pretend that the only information that exists are the name, and health percent.

As we know already, a variable is stored at a memory address. The battle list is literally just a list of variables stored in a certain order. Let's say there are 10 creatures in our battle list (the example I'm talking through). So now we know that there are 10 instances of a creature, each with a Name of 32 bytes, and a HealthPercent of 4 bytes. That means that each creature will use a total of 36 bytes. This means our battle list step (the distance between the start of each creatures information) is 36 bytes.

So, in order to read it we need to do something like this:

Calculate the maximum battle list length (we do this by calculating the total amount of creatures (10) multiplied by the length of each creature (36 bytes). We get 360 bytes, in total.
Read each of the creatures information, and store it in a variable, then step to the next creature. Do this until we've reached our maximum length.

In this pseudo code i will represent a counter, so we know where we are currently in the battle list.

So we do:
i = 0 - This would be i = BattleListStart, the start address of the battle list.
while i < 360 - While we are less than the total length of the battle list
read string at address i - read the Name, which is stored at 0 in our 2 part array containing Name and HealthPercent
read int at address i + 32 - read the HealthPercent which is after the name which is 32 bytes long, so our "offset" is +32
i = i + 36 - Add 36 to the battle list step, so that we step to the next creature before continuing to cycle
end - end the loop, so we can start it again if we need to or continue our code.

There is also a high probability here that you will find a creature with no name or HealthPercent, since we won't always have 10 creatures on our screen. To find this out we can work out if the Name is an empty string, by doing something like this to add the creature to our data structure, assuming our data structure is a list box named listBox1.


if (Name != "")
{
listBox1.Items.Add(Name);
listBox1.Items.Add(Convert.ToString(HealthPercent) );
}

That's the basics of it, I will write a proper tutorial for this one day.

I hope you've learned from my tutorial, it's nice to see someone has used it at least! Massive thanks for that :)

XtrmJash
01-20-2013, 12:37 PM
I've written some shit on reading battle list, which may be of use to you.

I declared these at the start of my Reader class:


public static UInt32 BLStart = 0x54C008;
public static UInt32 BLStep = 0xB0;
public static int BLMax = 1300;

Then I added a couple of classes to my program, to give it some more shape, this one contains all the data offsets for the battle list:


class BListAdresses
{
public static UInt32 IdOffset = 0x0;
public static UInt32 TypeOffset = 0x3;
public static UInt32 NameOffset = 0x4;
public static UInt32 ZOffset = 0x24;
public static UInt32 YOffset = 0x28;
public static UInt32 XOffset = 0x2C;
public static UInt32 TimeLastMovedOffset = 0x3C;
public static UInt32 WalkingOffset = 0x50;
public static UInt32 DirectionOffset = 0x38;
public static UInt32 PreviousOffset = 0x58;
public static UInt32 NextOffset = 0x5C;
public static UInt32 OutfitOffset = 0x60;
public static UInt32 MountIdOffset = 0x78;
public static UInt32 BlackSquareOffset = 0x88;
public static UInt32 HppcOffset = 0x8C;
public static UInt32 SpeedOffset = 0x90;
public static UInt32 SkullOffset = 0x98;
public static UInt32 PartyOffset = 0x9C;
public static UInt32 WarOffset = 0xA8;
public static UInt32 VisibleOffset = 0xAC;

}

I also added an objects class, with an struct for the battle list:


class Objects
{
public struct BList
{
public int Addr;

public int Id;
public int Type;
public string Name;
public int Z;
public int Y;
public int X;
public int TimeLastMoved;
public int Walking;
public int Direction;
public int Previous;
public int Next;
public int Outfit;
public int MountId;

public int BlackSquare;
public int Hppc;
public int Speed;

public int SkullType;
public int Party;
public int WarIcon;
public int Visible;
}
}

I then added a perhaps slightly more complex than required function to read the battle list:


public Objects.BList[] BlGet()
{
int max = Convert.ToInt32(BLStep) * BLMax;
Objects.BList[] bat = new Objects.BList[BLMax];
for (int i = 0; i < BLMax; i++)
{
UInt32 CreatureOffset = Convert.ToUInt32(i) * BLStep;
Objects.BList batt = new Objects.BList();
batt.Addr = i;
batt.Id = ReadInt32(BLStart + BListAdresses.IdOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
if (batt.Id != 0)
{
batt.Type = ReadByte(BLStart + BListAdresses.TypeOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Name = ReadString(BLStart + BListAdresses.NameOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Z = ReadInt32(BLStart + BListAdresses.ZOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Y = ReadInt32(BLStart + BListAdresses.YOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.X = ReadInt32(BLStart + BListAdresses.XOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.TimeLastMoved = ReadInt32(BLStart + BListAdresses.TimeLastMovedOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Walking = ReadInt32(BLStart + BListAdresses.WalkingOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Direction = ReadInt32(BLStart + BListAdresses.DirectionOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Previous = ReadInt32(BLStart + BListAdresses.PreviousOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Next = ReadInt32(BLStart + BListAdresses.NextOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Outfit = ReadInt32(BLStart + BListAdresses.OutfitOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.MountId = ReadInt32(BLStart + BListAdresses.MountIdOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));

batt.BlackSquare = ReadInt32(BLStart + BListAdresses.BlackSquareOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Hppc = ReadInt32(BLStart + BListAdresses.HppcOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Speed = ReadInt32(BLStart + BListAdresses.SpeedOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));

batt.SkullType = ReadInt32(BLStart + BListAdresses.SkullOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Party = ReadInt32(BLStart + BListAdresses.PartyOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.WarIcon = ReadInt32(BLStart + BListAdresses.WarOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
batt.Visible = ReadByte(BLStart + BListAdresses.VisibleOffset + CreatureOffset + Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32()));
bat[i] = batt;
}
}

return bat;
}

It should be noted that I also declared Tibia at the start of all of this, as a process... E.g:


Process Tibia = Process.GetProcessesByName("Tibia")[0];

I'm also using a function not listed in my tutorial, called ReadByte to read the Visible status of the battle list entry and the Type of the creature:


public byte ReadByte(Int64 Address)
{
return ReadBytes(Tibia.Handle, Address, 1)[0];
}


Note that there are probably some mistakes in this, due to the fact that I haven't worked out exactly what the length is of each element of the battle list array, so if you get something where for instance you're expecting the number 10, and you get 10383057830 or something stupid, just change the ReadInt32 or whatever to ReadByte or add a ReadShort function. If you don't know how, just ask.

If you basically add these components then call something like this:


Objects.BList[] myBlist = Read.BlGet();

Then you can do, for example:


foreach (Objects.BList creature in myBlist)
{
listBox1.Items.Add("creature.Name");
}

This will create a list of names of the creatures in your battle list.

Note that in this I am not checking to see if each creature is visible at the level where I read the memory, so it will return some unexpected results (players who left your screen hours ago in some cases). The alternative would be something like this:


Objects.BList[] myBlist = Read.BlGet();
foreach (Objects.BList creature in myBlist)
{
if (creature.Id != 0 && creature.Visible == 1)
{
blview.Rows.Add(creature.Name, Convert.ToString(creature.Visible), Convert.ToString(creature.Id), Convert.ToString(creature.X), Convert.ToString(creature.Y), Convert.ToString(creature.Z), Convert.ToString(creature.Type));
}
}

If any of this is too confusing and you can't work it out, check this out on google code, just committed the entire code of my latest "project":

http://code.google.com/p/japi/source/browse/#svn%2Ftrunk%2FJBot

Good luck!

stryku
01-31-2013, 12:46 AM
hey. i have a little problem with reading bl. my function read it right but it return also a place where moster was killed. why? what should i do to avoid that?

______

it return place with dead monster which only was killed by my. idk why

___
ok my problem is solved.

______
now i have another problem. why it's not working?
string ReadString(DWORD Point)
{
char value[32] = {0};
SIZE_T numBytesRead;

if (ReadProcessMemory(tibia.uchwytProcesu, (LPCVOID)Point, &value, 32, &numBytesRead) == 0)
{
DWORD lastError = GetLastError();
return "";
// error - return an empty string
}

return value;
}

void skanBl()
{

int mojeX, mojeZ, mojeY, jegoX, jegoY, jegoZ, jegoTyp;
WORD jegoId;
DWORD step = 0x0;
string nazwa;
for(int i = 0; i < 100; i++)
{

mojeX = czytajBezXor(adresy.adrPozX);
mojeY = czytajBezXor(adresy.adrPozY);
mojeZ = czytajBezXor(adresy.adrPozZ);
jegoX = czytajBezXor(adresy.adrBlStart + adrBlOf.X + adresy.adrBase + step);
jegoY = czytajBezXor(adresy.adrBlStart + adrBlOf.Y + adresy.adrBase + step);
jegoZ = czytajBezXor(adresy.adrBlStart + adrBlOf.Z + adresy.adrBase + step);
ReadProcessMemory(tibia.uchwytProcesu, (LPCVOID)(adresy.adrBlStart + adrBlOf.Id + adresy.adrBase + step), &jegoId, sizeof(int), NULL);
jegoTyp = czytajBezXor(adresy.adrBlStart + adrBlOf.Typ + adresy.adrBase + step);


//this one wont work. it return always empty string
nazwa = ReadString(adresy.adrBlStart + 0x4 + adresy.adrBase + step);

string r="Rat";
if(nazwa==r)//(czyNaEkranie(mojeX, mojeY, mojeZ, jegoX, jegoY, jegoZ, jegoTyp, nazwa, jegoId) == true)
{
//some code
}
else
{
//some other code
}



step += adrBlOf.Step;
}

or can anyone post his readString function?