[-]
Shout:
Click Refresh to load shouts.

Post Reply 
 
Thread Rating:
  • 1 Votes - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tibia GUI structure
05-30-2009, 08:20 AM (This post was last modified: 07-02-2009 10:33 AM by Snowak. Edit Reason: )
Post: #1
Tibia GUI structure
[SIZE="4"][FONT="Georgia"]
Hello!
[/FONT][/SIZE]
Long time ago, somewhere around 8.21 I've managed to work out whole GUI structure in Tibia client. I've just found below notes on my computer and though that someone maybe will find it useful. Luckily they're written like tutorial, as I've shared it with few people. When connected with hooking, this knowledge makes it possible to modify absolutely everything related to GUI and even to add own items! After writing simple API you will be able to make things such as world view which correctly accept mouse clicks, world view with margins to keep the correct width/height ratio and also eq panel on the left (which looks quite funny Tongue). Here you go.


Quote:I. Window structure
GUI pointer points to main Tibia window structure containing it's size etc. All other windows are it's child windows
therefore to access it you need to add 0x24 to that address. Later, I'll talk about those childs as first level windows, but remember that in fact they're not!

- Child pointers
0x30, 4b - points to game window child
0x34, 4b - points to player window child
0x38, 4b - points to containers window child
0x3C, 4b - points to first child of player window child
0x40, 4b - points to chat window child
0x44, 4b - points to resize bar child


II. Basics
To move between items it's required to use values like nextChild, nextItem etc. First variables are used for the same
purpose in all structures, then there are helper variables used to store additional informations. They depends on the
structure and don't have direct influence on drawing. It may happen that they're used to recalculate some values after
resizing.

First level child, are as follows in order:
a) Containers window: space for containers, vip list, battle list, trade window etc
b) Player window: space for eq, minimap, buttons, health, mana
c) Chat window
d) Resize bar (the one above chat window)
e) Game window


III. GUI Structure (in order: containers window, player window, chat window, resize bar, game window [with margins!])

- GUI pointers
0x00, 4b - points to callbacks structure
0x04, 4b - points to gui background structure

0x0C, 4b - points to parent window, in this case it's whole window structure containing resolution
0x10, 4b - points to next item
0x24, 4b - points to firstChild
0x28, 4b - points to child window where we clicked by mouse, it's equal to 0 if mouse button isn't pressed

- Following values have direct influence on drawing
- however they will be restored after Tibia recalculates the value (after minimizing window, resizing game window etc)
0x14, 4b - left offset
0x18, 4b - top offset
0x1C, 4b - width
0x20, 4b - height

- Those values contain different things, they depend on item which we are accessing
a) Part with containers, vips, bl etc
- Following values store the original size, they don't have influence on drawing but they're
- used when recalculating the values so modyfing them have constant effect
0x2C, 4b - relative left offset (to it's original position x.x)
0x30, 4b - relative top offset (to it's original position x.x)
0x34, 4b - width
0x38, 4b - height

- Others
0x3C, 4b - points to child window which we are moving, it's equal to 0 if we're not moving it
0x44, 4b - it contain height in pixels which isn't used by child windows
0x08, 4b - 0 - no background, 3 - used in resize bar, 8 - used in game window, 9 - has background

b) Part with eq, buttons, minimap
0x30, 4b - image id of top-left margin
0x34, 4b - image id of top margin
0x38, 4b - image id of top-right margin
0x3C, 4b - image id of left margin
0x40, 4b - image id of right margin
0x44, 4b - image id of bottom-left margin
0x48, 4b - image id of bottom margin
0x4C, 4b - image id of bottom-right margin

0x5c, 4b - width, doesn't have ANY influence, it's a helper-variable
0x60, 4b - height, doesn't have ANY influence, it's a helper-variable

0x3C, 4b - points to child window which we are moving, it's equal to 0 if we're not moving it

c) Part containing game window and margins
0x2C, 4b - points to world window, but instead of it it's recommended to use firstChild
0x30, 4b - top margin size } those values are used
0x34, 4b - left margin size } to calculate position
0x38, 4b - game window width } of world's window
0x3C, 4b - game window height } frame border

a) World window
Helper variables are used to store positions of names that are drawed on screen. When updating them fast enough
name will be drawed in different place. Anyway, there's no use for it.

IV. GUI callbacks structure (memory have read-only flag, unlock it with VirtualProtectEx)
Note: Mouse positions are relative to top & left offset of item

- Functions I am sure of
0x04, 4b - points to onGUIItemCreate procedure
start address of created gui item, 4b
0x34, 4b - points to onWindowResize procedure (also called when was minimized and then opened from taskbar)
width, 4b
height, 4b
0x44, 4b - points to onDraw procedure
val: 1, ?b
val: 0, ?b
val: 0, ?b
0x48, 4b - points to onGUIResize procedure which is called everytime when Tibia is recounting values
*No parameters expected*
0x4C, 4b - points to onMouseMove procedure (even in different window!)
mouseX, 4b
mouseY, 4b
0x50, 4b - points to onLeftMouseDown procedure
mouseX, 4b
mouseY, 4b
val: 0, ?b
0x54, 4b - points to onLeftMouseUp procedure
mouseX, 4b
mouseY, 4b
val: 0, ?b
0x58, 4b - points to onLeftMouseDblClick procedure
mouseX, 4b
mouseY, 4b
val: 0, ?b
0x5C, 4b - points to onRightMouseUp procedure
mouseX, 4b
mouseY, 4b
val: 0, ?b
0x6c, 4b - points to onKeyDown procedure
Note: Screen window doesn't get this event when any dialog window is opened (like Options, Quests)
charID, ?b
0x70, 4b - points to procedure which is called when we click on player window

- Predicted callbacks
0x0C, 4b
It's probably called when whole GUI is being removed, on logout
100, 4b
Probably some timer


[SIZE="4"][FONT="Georgia"]
Finding the pointer
[/FONT][/SIZE]
Okay, the above notes explains the structure, but our main goal is to find the pointer Wink The simpliest aproach is to use Cheat Engine to look for increased/decreased variables while resizing world window to find where it's stored, and then according to above notes just move using parentChild to reach the main window structure. Then just start a scan for this address to get the pointer.

As I'm quite lazy I've noticed that the pointer's address is very close to the player XYZ position. If you substract 0x3C from the Z position address, in 8.21 you would get the pointer too. I don't know whether it changed since that time, but even if it did the pointer is still somewhere nearby.

To save you some time I've made a quick scan and our most wanted pointer is stored at address 0x640B00. So compared to above, it's currently 0x38 before Z coordinate Smile


[SIZE="4"][FONT="Georgia"]
Bonus pointer
[/FONT][/SIZE]
As some of you probably have guessed, dialogs in Tibia are stored using the same structure, however they're not connected with the GUI structure. They have their own pointer in Tibia memory which directly points to opened dialog. Another quick scan, and you will be able to play with it Smile
Added: Thanks to Cameri, the pointer's address is 0x640AFC


[SIZE="4"][FONT="Georgia"]
Preventing and forcing data restore
[/FONT][/SIZE]
There's a little but important thing we need to remember about. When Tibia window is resized/minimized all of our changes will be removed. There are also some values which won't affect the window instantly but after next redraw, however we already know that original values will be restored, thus modyfying them is quite tricky (but of course possible and not that hard with a bit of hooking).

The easiest thing to do is forcing Tibia to redraw GUI. It is necessary for example when we are resizing containers. Here's the WinAPI trick:

Quote:procedure forceGUIResraw;
var
A : array[0..3] of byte;
C : DWORD absolute a;
begin
A[0] := Lo(TibiaWindowWidth);
A[1] := Hi(TibiaWindowWidth);
A[2] := Lo(TibiaWindowHeight);
A[3] := Hi(TibiaWindowHeight);
PostMessage(TibiaHandle, WM_SIZE, SIZE_MAXIMIZED, C);
end;

For those of you who are not familiar with Delphi, the C variable is an unsigned integer where younger bytes (first two) contain tibia window width and older bytes (last two) contain tibia window height. Of course this data can be retrieved using another WinAPI calls, but as we have pointer to Tibia main window's structure which already contain the size, why would we waste time ;>


Now about making the changes constant. The only reliable way to do it, is to hook onGUIResize callback of main window structure. You can safely set up your own settings from there without having to worry that they will be changed. Unfortunetely, it's not that simple. You have to insert your hook AFTER original function. My aproach was to use disassembler and insert a code cave in runtime somewhere before retn op-code. Luckily there's also other method which also requires some ASM coding. We can create a plain helper function which we will put in callback structure. It should call the original function and then our. I haven't tested it, but it would look like:
Quote:call onGUIResize
pushad
call ourCallback
popad
retn


[SIZE="4"][FONT="Georgia"]
Good luck!
[/FONT][/SIZE]
I haven't programmed anything for tibia client since 8.21 so there could be some little changes in the structure, however I didn't noticed any while looking for the pointer. All I currently can do is wish you good luck and hope you'll make good use of it Smile

[SIZE="1"]btw. Please do not re-post it on other forums.[/SIZE]

/edit
There's a better way to force Tibia to redraw itself. Simply use:
Quote:InvalidateRect(TibiaHandle, 0, true);
If the screen flickers, use false instead of true - it won't erase the window.
Find all posts by this user
Quote this message in a reply
05-30-2009, 10:16 AM
Post: #2
Tibia GUI structure
I love you :o!!

Find all posts by this user
Quote this message in a reply
05-30-2009, 11:21 AM
Post: #3
Tibia GUI structure
Excellent! Now I'll try to digest everything you did here!

Cameri

TibiaTek+TibiaAPI Development Team
Taking programming into a whole new level. [Image: 514832412.329.1164300914.png]
Visit this user's website Find all posts by this user
Quote this message in a reply
05-30-2009, 12:20 PM
Post: #4
Tibia GUI structure
1 word:

Awesome!
Find all posts by this user
Quote this message in a reply
07-04-2009, 08:26 AM
Post: #5
Tibia GUI structure
Hey. It's a great spot to start working with Tibia GUI. Very helpful.
Thank you.

.:: Tibia 2 ::.
Find all posts by this user
Quote this message in a reply
02-05-2010, 06:37 AM
Post: #6
RE: Tibia GUI structure
Thank you for this!

I have a question, for the 8.54 the player Z is 0x645530, so I can find the GUI pointer 0x6454f8. Now I would like to use the containers pointer, which I must add 0x38 to the value found in the GUI pointer, lets suppose the result is 0x1C552c8, now I need just to add those values to mix things Smile
It worked here! But, is there any way to know the position of the containers? Size?

Thank you again!
Find all posts by this user
Quote this message in a reply
02-08-2010, 01:24 PM
Post: #7
RE: Tibia GUI structure
It'd be cool to find a way to make a bot that interacts only through Tibia. Such as using the quest window as a listbox, etc
Find all posts by this user
Quote this message in a reply
02-08-2010, 07:50 PM
Post: #8
RE: Tibia GUI structure
I've tried this, its harder then it sounds but entirely possible.

Find all posts by this user
Quote this message in a reply
Post Reply 



Contact UsTProgrammingReturn to TopReturn to ContentLite (Archive) ModeRSS Syndication