Purpose of this article is to describe in deep, low-level details how to read contents of the Tibia map in memory. After reading the article you will know and understand all the algorithms that are needed to implement the map reading feature in your own bot.

Part 1. Locating the map in memory.

The map is stored in memory in a dynamic way - this means that its location might vary every time you start your Tibia client (although in practice it varies from one windows type to the other only). In such case to know the exact location you have to look into the value of some pointer in the memory - in Tibia 7.6 its address is 0x4AF478. After rereferencing this pointer, you obtain a pointer to the map structure itself.
The map is stored as an array of 2016 tiles. Each tile consumes 168 bytes, which gives space for 168/4=42 integers. Those 42 integers are:
  • number of items stacked/displayed on the tile (at most 13)
  • 13 item definitions, each of them consists of
    • item id
    • item extra data 1
    • item extra data 2
  • 2 not-used integers for padding
In C++ the above map description could look like:

struct objectData { int objectId; int data1; int data2; } struct tileDef { int stackedObjectCount; struct objectData[13]; int padding1; int padding2; }; struct tileDef map[2016]; // with tileDef address 0x4AF478

Part 2. Decrypting the 'extra data' tile parts

The 'extra data' of tile depends on the object type. I know about two usages of it:
  • for creatures (object id 99 (0x63)) data1 is Tibia ID of the creature
  • for multiplicable objects (e.g. fish, meat, gold, worms, etc.) data1 is amount of items in the tile

Part 3. Locating yourself on the map

Having the current knowledge, locating yourself on the map in the memory is pretty simple: it is just a tile with creature id 99 (0x63) and data1 (Tibia ID) equal to your own Tibia ID. Position (between 0 and 2015) of the 'yourself tile' is esential for further computations.

Part 4. Map structure in memory

As I mentioned in the very beginning of this article, a map in memory contains description of exactly 2016 tiles. It appears that this array of tiles is not flat, but is rather a tri-dimension array of size 8*14*18 (see that 8*14*18 equals to 2016)! In the memory it is written like

struct tileDef map[8][14][18];

So having any 'tile position' it is possible to compute an exact location of the tile in the tri-dimension array using the following equations:

z = cellNr/(14*18); y=(cellNr-z*14*18)/18; x=(cellNr-z*14*18-y*18);

Now assuming that we know 'yourself tile' position (see part 3) we can compute an exact location of 'yourself tile' in the memory array. For example if 'yourself tile' is 1066, then we can compute that this equals to position [4][3][7]. Unfortunetally doing a few experiments with a running Tibia client lead to two surprising conclusions:
  • 'yourself tile' can be any tile in the array (we might have expected that it always is a center, [0][0][0] or a similar thing)
  • walking north/south/east/west causes move of our position in the array by '1' most of the time on either x (third dimension) or y (second dimension)

Part 5. Solving the map puzzle

Further experiments with walking east/west closed us to the final solution of the map puzzle:
  • assume that you are on [anything][anything][x] with x>0; moving left causes transition to [anything][anything][x-1]
  • assume that you are on [anything][anything][0]; moving left causes transition to [anything][anything][17]
  • assume that you are on [anything][anything][x] with x<17; moving right causes transition to [anything][anything][x+1]
  • assume that you are on [anything][anything][17]; moving right causes transition to [anything][anything][0]
Similarily with up/down moving
  • from [][y][] with y>0; moving up transits you to [][y-1][]
  • from [][0][]; moving up transits you to [][13][]
  • from [][y][] with y>0; moving down transits you to [][y-1][]
  • from [][13][]; moving down transits you to [][0][]
Knowing the above we can try to proceed with reading what is written on a tile different than your own, which is obviously our goal. Let's assume that you stand on [][x][y] and want to know what is one-up/one-left tile of you. It works in a very similar way as walking left/up, which means that unless x>0 and y>0 it's enough to read [][x-1][y-1] from the memory to get what we need! If you want to "cross" the array boundary, things become more complex a little bit, but equations from the above remain unchanged. For example if you stand on [][0][0] and want to read one-up/one-left tile you need to look in [][13][17].

Part 6. Map reading in Tibia Auto

The map reading/writting technique is used in Tibia Auto to solve a few problems:
Auto fish
Thanks to the map reading, auto fisher knows fields which have fish (are "fishy") and witch have no fish and so should not be fished.
Ammo restack
Thanks to the map reading, ammo restack knows whether to pickup a spear or other throwable.
Looting in cavebot
Thanks to the map reading, cavebot knows id of corpse of the just killed monster, for looting purposes.
Map hacks
Thanks to the map writting, map hacks can mark fields which have no fish in a special way.



Discuss and rate this article on the forum!


Back to the homesite

Copyright to vanitas. This article is written for http://tibiaauto.tenet.pro24.pl/. Its publishing without a written permission is a violation of law.