Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Perfect World > PW Hacks, Bots, Cheats, Exploits
You last visited: Today at 14:30

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



guide: debug pwi, find function addresses and offsets, write a bot(c++ code included)

Discussion on guide: debug pwi, find function addresses and offsets, write a bot(c++ code included) within the PW Hacks, Bots, Cheats, Exploits forum part of the Perfect World category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Mar 2007
Posts: 26
Received Thanks: 38
guide: debug pwi, find function addresses and offsets, write a bot(c++ code included)

hi,
let's start right away.


what you can learn:

- trace and call ingame-functions like attack, cast spell, pick up, moveto, ...
- traverse object lists like items, mobs, players
- read ingame structures (class objects) and how they play together
- write your own fully client-side bot that doesnt need to simulate mouse/keyboard input and doesnt need to read pixels


tools needed:

- debugger (ollydbg, although i prefer softice but its kinda broken since xp)
- disassembler (ida pro and w32dasm)
- mem searcher (cheat engine)
- basic asm knowledge
- a brain


i have attached some pics which show some commented disassemblies, etc. you should download them and check them out when i reference them in the text (sry, i was too lazy to upload and link each of them, its just too many).



Theory:
----------
there are, more or less, 2 types of functions:

type 1:
these functions call a function that i named "PerformAction". all these functions perform some checks, and if everything seems alright, they setup the parameters for the "PerformAction" function and then call it, to create an action. most functions are this type and they will be extremely easy to find

type 2:
these function dont call "PerformAction" directly. i didnt investigate them any further, but i think they setup some stuff (like put something into a queue) and "PerformAction" may or may not be called some time later.

i will explain how to find each type of function in a little bit.


Calling Chain:
---------------
the general internal calling chain of most functions looks like this:

1) ... -> FinalDispatchHandler -> Function [ -> PerformAction ]
2) ... -> FinalDispatchHandler -> LeftClickHandler [ -> Function ] [ -> PerformAction ] (for actions that are executed via left mouse clicks)


FinalDispatchHandler:
-------------------------------
i wasnt sure how to name this one, i just left it with this name. this is the final handler for most events, actions and inputs. this function is passed an action code or something and then it calls the corresponding final function to execute the action. for example, if you press spacebar, it will call the jump function and if you left click (outside a gui element) it will call the LeftClickHandler and so on. so it forwards action to its final handlers. this handler is also called, whenever your hp/mana changes.


LeftClickHandler:
-----------------------------------------
i gave it this name because it is the final handler for a left mouse click if the mouse click doesnt resolve to a gui element. both SetTarget and MoveTo will be found inside this handler. however, both these "functions" are not seperate functions, their full code is inside this handler, so theres no actual function call to do a SetTarget or MoveTo.


Strategy:
------------
1) find a function that calls PerformAction (e.g. CastSpell)
2) get the address of this function
3) forwardtrace this function to get the PerformAction address
4) find the LeftClickHandler via bp on PerformAction when setting target or moving somewhere (both are left click functions)
5) backtrace the LeftClickHandler to get the address of FinalDispatchHandler

when we have done all this, we have all the functions we need to trace the other functions.


so, now let's find these functions via debugging



Debugging:
-------------
before you do anything, open up elementclient.exe in ida pro and w32dasm and once finished disassembling, save the disassembly outputs.



1) DrawStatusText:
-----------------------
we will need this one for some functions. this prints some text in the status window.
open your w32dasm disassembly of elementclient.exe. click the StrnRef button. search for the string "^^C8FF64". double click the string in the list. w32dasm will now jump to the code address that references this string. it should be 5946cf (see pic00 for the whole process if you need to).
now open up your ida pro disassembly. go to the address we just found (5946cf). to do this, press g and enter the address in the field like shown in pic01 and press the OK button. ida should now jump to the address and it should look similar to pic02. if your not in graph view, right click somewhere on the disassembly and select Graph View from the drop down menu. now scroll up to the start of the function. it should look similar to pic03. as you can see, the function address is 5941a0. lets rename the function to make the disassembly more readable. left click on sub_5941a0 and press n. a dialog should pop up. enter the fields like shown in pic04 and press the OK button. your disassembly should now look like shown in pic5.

DrawStatusText: 5941a0

--- beware: this function is also called for chat messages! ---



2) CastSpell #1 (pref. method, but needs venomancer lvl9 or above):
------------------------------------------------------------------------
try to cast Ironwood Scarab with insufficient chi and you will get an error message.
so what we do is, set a bp on DrawStatusText, cast ironwood scarab with insufficient chi, and then we trace from DrawStatusText to CastSpell in olly.
this one time im gonna show you how to do it in depth. after that, i will refer to this one.
so open up olly and attach it to elementclient.exe as shown in pic06. once attached, press f9 to resume the process.
now we set a bp on DrawStatusText (5941a0). to do this, we have to go to the function address of DrawStatusText. press ctrl+g. a dialog as shown in pic07 will show up. enter the address (5941a0) in the field as shown in pic07 and press the OK button. olly should now look as shown in pic08. press f2 to set a bp on the address. olly should now look as shown in pic09 (notice the red background of the address indicates a bp).
now our bp is set and we can finally cast ironwood scarab with insufficient chi. the bp will be hit and you will be right back in olly. now trace to the function that called DrawStatusText. to do this, first press ctrl+f9, this will "jump" to the end of the current function (DrawStatusText) as shown in pic10 (you should be at address 594b0b now). now press f8 and you will be inside the function that called DrawStatusText. you should now be at 4373cb as shown in pic11, which is inside one of the DrawStatusError functions, which loads a "predefined" error string by its id and then calls DrawStatusText accordingly. so press f8 3 more times to trace over the RETN at 4373d2 as shown in pic12. you should now be at address 45cd70 as shown in pic13, which is inside the function that called DrawStatusError. in other words, your now inside the CastSpell function. so now open ida and go to the address we just found (45cd70). to do this, press g and enter the address in the field and press OK as shown in pic13. your ida should now look similar to pic14.
go on at 4) CastSpell #3 after you read 3) CastSpell #2



3) CastSpell #2 (no requirements, just a class that can cast a damage spell):
--------------------------------------------------------------------------
CastSpell tries to use the current target, if no target is passed as a param. so if we dont have a target and try to cast a damage spell, CastSpell will read out the current target id. so what we do is, add the address of the current target id to our cheat engine address list and then find out what accesses this address and then we cast a damage spell with no current target.
pic21 and pic22 will show you how to add this address to your ce address list if you dont know how to do it. in fact, the address is resolved as following:
[[9b4594] + 0x20] + 0xaf0
there are also tuts on these forums on how to find the "base" address.
alright, now go ingame, and deselect any current target if you have one. now add the address to your ce list and find out what accesses this address. now go back ingame, wait a little, move around a little. ce should now show some addresses in the list. it should look similar to pic23. now cast a damage spell with no current target, ce should show 2 new addresses as shown in pic24. the address 45ccbb as shown in pic24 is the one we are looking for. this address is inside the CastSpell function. so now open ida and go to the address we just found (45ccbb). to do this, press g and enter the address in the field and press OK as shown in pic25. your ida should now look similar to pic26.
go on at 4) CastSpell #3



4) CastSpell #3 (function address and prototype):
-----------------------------------------------------
alright, now you got that address inside the CastSpell function. now scroll up to the function start in ida graph view. it should look similar to pic15. as you can see, the CastSpell function address is 45cc50. but before we go on, lets make the disassembly more readable. lets rename the function first. to do this, left click on sub_45cc50 and press n. a dialog should pop up. enter the fields as shown in pic16 and press OK. now lets set the function prototype. again, left click on the function name and press y. a dialog should pop up. enter the field as shown in pic17 and press OK. the function should now look as shown in pic18 (CastSpell prototype). as you can see, there are 2 params (dw0, dw1) that i didnt investigate further. setting both to 0 worked for me everytime, so i just left them like that. they have something to do with the action objects that i will cover later. if you want to know what these params are for, you can investigate further if you want to. pic19 and pic20 show some parameter stuff and how the function is called, check them out if you want to.

here are some spell ids that you can pass as a param.
i hope they are still up to date, i didnt test them in the latest version.
you can find out more yourself by setting a bp on CastSpell and checking the params for each spell.

#define SPELLID_VENOMOUS_SCARAB 0x12b
#define SPELLID_IRONWOOD_SCARAB 0x12c
#define SPELLID_BLAZING_SCARAB 0x12d
#define SPELLID_FROST_SCARAB 0x12e
#define SPELLID_NATURES_GRACE 0x134
#define SPELLID_METABOLIC_BOOST 0x133
#define SPELLID_SOUL_TRANSFUSION 0x137
#define SPELLID_HEAL_PET 0x14a
#define SPELLID_REVIVE_PET 0x149
#define SPELLID_TAME_BEAST 0x148
#define SPELLID_SUMMER_SPRINT 0x2fa
#define SPELLID_BRAMBLE_GUARD 0x132
#define SPELLID_FOX_FORM 0x138
#define SPELLID_TOWN_PORTAL 0xa7

CastSpell: 45cc50 (pic18)



5) PerformAction, CreateActionObj, PrepareActionObj:
----------------------------------------------------------
as already said, PerformAction is called inside the CastSpell function. in fact, its the very last call on a successfull spell cast inside the CastSpell function. from now on, all pics will show already processed disassemblies (which means that i already renamed the functions and set the prototypes). so from now on, you will have to rename the functions and set the prototypes yourself as we did it before. the pics will show you how i named the functions and declared the prototypes. you can, of course, choose other names.
so, open up the CastSpell function in ida and scroll down to the end of the function. pic27 will show you the 3 function calls and pic28-pic30 will show you the prototype of each function. as you can see, i didnt investigate too much into these functions, since i dont really need to call them (only to emulate a MoveTo(x,y,z)). you can of course investigate further if you want to know more about action objects and the like.

CreateActionObj: 466c70 (pic28)
PrepareActionObj: 46e300 (pic29)
PerformAction: 467070 (pic30)



for the following stuff, make sure you have no pet out and your at full hp/mp because pets and hp/mp changes might trigger FinalDispatchHandler.



8) LeftClickHandler / FinalDispatchHandler
-------------------------------------------
bp on PerformAction (467070). move somewhere via left mouse click. trace to the function that called PerformAction (in olly press ctrl+f9 and then f8). write down the addr (it should be 45f1a2, which is inside LeftClickHandler). now further trace via f8 in olly over the next RETN and find out what called the LeftClickHandler. also write down this addr (it should be 44fdda, which is inside the FinalDispatchHandler). open up both addresses in ida graph view and scroll up to the function starts. these are your LeftClickHandler / FinalDispatchHandler addresses.

LeftClickHandler: 45eaf0 (pic31)
FinalDispatchHandler: 44fd40 (pic32)


once we have all that, the rest isnt very hard.



9) Methods to find the other functions:
--------------------------------------
always make sure, no pet is out and be at full hp/mana


a) type 1 functions:
- CastSpell (already got that)
- Pickup / Gather (same function)
- Attack
bp on PerformAction. execute the corresponding action ingame. trace back to the function that called PerformAction (in olly press ctrl+f9 and then f8). write down the addr. open up this addr in ida graph view. scroll up to function start. thats your function addr.

Attack 462740 (pic33)
Pickup/Gather: 462800 (pic34)


b) type 2 functions:
- Jump
- CancelAction
- DoAction
bp on FinalDispatchHandler. execute the corresponding action ingame. forwardtrace to the very first call (in olly press f8 until you come across a call instruction). write down the addr that is being called. this is your function addr.

Jump: 455430 (pic35)
CancelAction: 4551f0 (pic36)
DoAction(Fly, Meditate, ...): 4576d0 (pic53) check 15) DoAction for more info



10) MoveTo:
------------------
bp on CreateActionObj. move somewhere ingame via left mouse click. trace to the function that called CreateActionObj (in olly press ctrl+f9 and then f8). write down the addr (it should be 45f033, which is inside the LeftClickHandler). open this addr in ida. you will see, that first CreateActionObj is called, then 2 more functions are called (sub_46a890 and sub_46a9e0). they probably convert mouse coords to game coords and store them in the actionobj. we have to find out, how these functions exactly alter the actionobj before PerformAction is called. if you want to, you can inspect these functions deeper, but i have some pseudo code, that alters the actionobj "enough" that it works. it doesnt do everything these 2 functions do, but it worked. hope it still works:


Code:
typedef struct __tagACTIONOBJMOVETO
{
	char         uk0[0x20];                    // 0x00
	float        x;                            // 0x20
	float        z;                            // 0x24
	float        y;                            // 0x28
	DWORD        dwAction;                     // 0x2c      0: move
} ACTIONOBJMOVETO, *LPACTIONOBJMOVETO;

ACTIONOBJMOVETO *p;
p = CreateActionObj(p_localplayer->p_actionbase0, 1);
p->x = x;
p->y = y;
p->z = z;
p->dwAction = 0;
PerformAction(p_localplayer->actionbase0, 1, p, 1, 0);


11) SetTarget:
--------------------
as already stated, this one is also inside the LeftClickHandler. either bp on LeftClickHandler and forwardtrace it yourself or do this:

before SetTarget is called inside the LeftClickHandler, the new target id will be stored in a variable i named dwTmpNewTargetId. the address of this variable is the address of the current target id + 4. see pic37 on how to get the address if you dont know what i mean.
so, now via cheat engine, find out what writes to this address. now go ingame and set a new target. 2 addresses will pop up. use the first one, it should be 45eef7, which is inside the LeftClickHandler. open this addr in ida pro and check pic38. here you will see how SetTarget is called and how to resolve the class object that is being used (p_objdbbase4).

SetTarget: 5cc0c0 (pic39)



12) Equip/Use
------------------
bp on DrawStatusText. try to equip something you cannot equip or try to use something in your inventory that is on cooldown (-> an error message will be printed). trace to the function that called DrawStatusText (in olly pres ctrl+f9 and then f8). your now inside a DrawStatusError function. so further trace with f8 over the net RETN. you should now be at address 45c95e, which is inside the Equip/Use function. so open this address in ida pro. scroll up to the function start. thats your Equip/Use function.

Equip/Use: 45c280 (pic40)

but how do we get the class object (p_invobjdb)? look at the xrefs of this function as shwon in pic40. check the xref with the red circle in pic40. you will see that a function (i named it GetInvObjDB) is called which returns p_invobjdb in eax (check pic41). so check out this function now (compare pic42). its actually very easy, it starts out with a static pointer.



13) Mob/Player/NPC/Item/Resource Lists:
------------------------------------------
open the Attack function in ida pro and check pic43. as you can see, a function is being called which returns the object with the dwTargetId id. i named this function GetObjById. pic43 shows how to resolve the class object (p_worldobjdb) for the function.

GetObjById: 42c820 (pic44)

if you analyze this function a bit, you will see, that the id is checked with some flags to determine whether the id is a mob/npc, a player, or an item/resource. (there are 3 lists, 1 for mobs/npcs, 1 for players, 1 for items/resources).
pic45 and pic46 show the calls for the 3 types of ids. (different list pointers for each id type).

GetObjByIdFromObjList: 5ad4f0 (pic47)
this function shows you, how the lists are built up and how to traverse it (sort of). offset 0x18 into the list class is a pointer to a sequential list of pointers to listentries which store the id of the obj and the pointer to the obj. offset 0x04 into the listentry stores a pointer to the obj and offset 0x08 into the listentry stores the id of the obj.

GetPlayerByIdFromPlayerList: 5b66e0 (pic48)
this function actually calls GetObjByIdFromObjList, but before it checks whether the id belongs to the localplayer. it does this because the localplayer is not in the playerlist.



14) Inventory lists:
-------------------------
open the Equip/Use function in ida pro and check pic49. there are 7 lists for different inventory items. 1 list (id 0) is the list for items in your inventory (backpack), 1 list (id 1) is for items that are currently equipped ("normal" items), the other lists should be for quest items, costumes etc., but i didnt check them because i dont care.

GetInvItemListById: 45c1e0 (pic50)
this function returns the address of the list class object for the list with the id passed as param. actually this one is pretty easy. pic51 shows the offsets into the p_invobjdb for the pointers to the inventory items and normal equipped items lists.

once we have the list the item we want to use is in, we can finally call GetInvItemBySlotFromList

GetInvItemBySlotFromList: 48baa0 (pic52)
the class object for this member function is of course the corresponding list, the parameter is the item slot of the item we want to use (e.g. item slot 0 and the list with id 0 would be the very first item in your inventory backpack). this function shows you how the inventory lists are built and how to traverse them. offset 0x10 into the list class object stores the number of total item slots (any slot index >= this value is a bad slot index). offset 0x0c into the list class object stores a pointer to a sequential list of pointers to inventory item objects.



15) DoAction (Fly, Meditate, ...):
--------------------------------------
DoAction is called for Fly and Meditate, probably for all other actions like Nod, Salute, Provoke, etc. as well. this function is passed a pointer to a structure i named DOACTIONPARAM. i didnt fully "decrypt" the structure, only the fields i needed, here it is:

Code:
typedef struct __tagDOACTIONPARAM              // param passed to DoAction
{
	DWORD        uk0;                          // 0x00
	DWORD        uk1;                          // 0x04
	DWORD        uk2;                          // 0x08
	void         *p_data;                      // 0x0c        might be a pointer to some data
	DWORD        dwAction;                     // 0x10        check DA_ constants
} DOACTIONPARAM, *LPDOACTIONPARAM;


#define DA_MEDITATE               0x6f
#define DA_STOPMEDITATE           0x70
#define DA_FLY                    0x60
#define DA_STOPFLY                0x61
it was enough to just set dwAction to the action you want to execute. maybe this has changed, try it out. here is some pseudocode to Fly:

Code:
DOACTIONPARAM dap;
dap.dwAction = (bFly) ? DA_FLY : DA_STOPFLY;
DoAction(p_localplayer, &dap);

i will provide some structure definitions written in c++. i dont play this game anymore, i just wrote this and debugged pw again just for fun. so some of the structures are not up to date and need some (minor?) updating. but i updated all the structures i was referring to above. structures like MOBOBJ, WORLDITEMOBJ and pet stuff, which i didnt cover, i didnt update because i really hate mem dumping and checking offset over offset. you can of course update them yourself if you havent already done so. maybe i will go over pet commands and the like later, but i dont know if i wanna do this now. the structures might give you a better idea on how to traverse lists so that you can find whatever you want. a small tip on traversing lists: go through all pointers from start to end, check for null pointers, check for valid ids, use exception handling. i hope theres no errors in the code because i updated some offsets and names to match the disassemblies i provided and havent tested it, but it should be fine.

note on the code:
i decided not to include any real function code. i included most important ingame structures which will enable you to write your own functions to traverse lists. you also have most important ingame function addresses which you can call if you want to. the code is best used from within the target process, since you can obtain objects very easily starting from p_base0 or p_objdbbase0 via structure pointers.

note on calling functions:
most ingame functions are member functions (__thiscall calling convention). this means, the first param is always the this pointer (passed in ecx), the other params are passed like in __stdcall (pushed onto stack right to left, called functions cleans stack).


Code:
#define MAKEPTR(base, offset)      ((DWORD) base + (DWORD) offset)



///////////////////////////////////////////////////////
// *** (class) object pointers ***
///////////////////////////////////////////////////////
#define VA_BASE0                0x9b4594       // address of pointer to p_base1
#define VA_OBJDBBASE0           0x9b3eec       // address of pointer to p_objdbbase1
#define OBJDBBASE4OFFSET        0xec           // p_objdbbase4 = p_objdbbase0->p_objdbbase1->p_objdbbase3 + OBJDBBASE4OFFSET





//////////////////////////////////////////////////////
// *** (class) object structures ***
//////////////////////////////////////////////////////
#pragma pack(push,1)
typedef struct __tagPOINT3D
{
	float        x;                            // 0x00
	float        z;                            // 0x04
	float        y;                            // 0x08
} POINT3D, *LPPOINT3D;


typedef struct __tagACTIONBASE1                // *** up to date ***
{
	DWORD        uk0;                          // 0x00
	DWORD        dwActionState;                // 0x04 +     check AS_ constants
	char         uk1[0x10];                    // 0x08
	//void         *p_actionbase2;               // 0x18       not used and probably outdated
} ACTIONBASE1, *LPACTIONBASE1;


typedef struct __tagACTIONBASE0                // *** up to date ***
{
	DWORD        uk0;                          // 0x00
	void         *obj;                         // 0x04 +     pointer to player object (if mobs have this too, it would probably be pointer to mob object ;) )
	char         uk1[0x0c];                    // 0x08
	ACTIONBASE1  *p_actionbase1;               // 0x14 +     dynamically changed for every action (=> current action base)
	BOOL         bPerformingAction;            // 0x18 +     careful with this one, if you cast a spell and are out of range
	                                           // it will be set to 1 when walking, set to 0 when stop walking, then
	                                           // the attack command is sent to the server and when confirmation is
	                                           // received, it will be set back to 1 for casting (same for attacking)
} ACTIONBASE0, *LPACTIONBASE0;


typedef struct __tagPETOBJ                     // *** up to date ***
{
	char         uk0[0x04];                    // 0x00
	DWORD        dwLoyalty;                    // 0x04 +
	DWORD        dwHunger;                     // 0x08 +    check PH_ constants
	char         uk1[0x14];                    // 0x0c
	DWORD        dwLevel;                      // 0x20 +
	char         uk2[0x04];                    // 0x24
	DWORD        dwXP;                         // 0x28 +
	char         uk3[0x08];                    // 0x2c
	WCHAR        *lpName;                      // 0x34 +
	DWORD        dwHP;                         // 0x38 +
	// dwMaxHP can be found by finding the MOBOBJ of your pet in the moblist (your pet: dwOwnerId == p_localplayer->dwId)
} PETOBJ, *LPPETOBJ;


typedef struct __tagPETLISTHEADER              // *** up to date ***
{
	char         uk0[0x08];                    // 0x00
	DWORD        dwCurrentPet;                 // 0x08 +        0, 1, 2, ... 9     NOPET: no pet
	DWORD        dwPetBagSize;                 // 0x0c +        1, 2, ... a        size of pet bag (number of pet slots)
	PETOBJ       *pet[0x0a];                   // 0x10 +        list of pointers to pet objects
	DWORD        dwCurrentPetId;               // 0x38 +
	char         uk1[0x04];                    // 0x3c
	DWORD        dwPetMode;                    // 0x40 +        check PM_ constants
} PETLISTHEADER, *LPPETLISTHEADER;


typedef struct __tagPLAYEROBJ                  // local player is not in the player list *** mostly up to date (+ indicates up to date) ***
{
	char            uk0[0x0c];                 // 0x00
	float           player_angle0;             // 0x0c  ?      orientation
	float           uk1;                       // 0x10
	float           player_angle1;             // 0x14  ?      orientation
	char            uk2[0x24];                 // 0x18
	POINT3D         pos;                       // 0x3c  +
	char            uk3[0x410];                // 0x48
	DWORD           dwId;                      // 0x458 +
	DWORD           uk4;                       // 0x45c
	DWORD           uk5;                       // 0x460
	DWORD           dwLevel;                   // 0x464 +
	DWORD           uk6;                       // 0x468
	DWORD           dwHP;                      // 0x46c +
	DWORD           dwMP;                      // 0x470 +
	DWORD           dwXP;                      // 0x474 +
	DWORD           dwSpirit;                  // 0x478 +
	DWORD           dwAvailableAP;             // 0x47c +      available attribute points
	DWORD           dwChi;                     // 0x480
	char            uk7[0x10];                 // 0x484
	DWORD           dwCon;                     // 0x494 +
	DWORD           dwInt;                     // 0x498 +
	DWORD           dwStr;                     // 0x49c +
	DWORD           dwAgi;                     // 0x4a0 +
	DWORD           dwMaxHP;                   // 0x4a4 +
	DWORD           dwMaxMP;                   // 0x4a8 +
	char            uk8[0x0c];                 // 0x4ac
	float           ground_speed;              // 0x4b8 +
	char            uk9[0x08];                 // 0x4bc
	DWORD           dwAccuracy;                // 0x4c4 +
	DWORD           dwMinPhysAtk;              // 0x4c8 +
	DWORD           dwMaxPhysAtk;              // 0x4cc +
	char            uk10[0x38];                // 0x4d0
	DWORD           dwMetalRes;                // 0x508 +
	DWORD           dwWoodRes;                 // 0x50c +
	DWORD           dwWaterRes;                // 0x510 +
	DWORD           dwFireRes;                 // 0x514 +
	DWORD           dwEarthRes;                // 0x518 +
	DWORD           dwPhysDef;                 // 0x51c +
	DWORD           dwEva;                     // 0x520 +     evasion
	char            uk11[0x04];                // 0x524
	DWORD           dwMoney;                   // 0x528 +
	char            uk12[0x64];                // 0x52c
	DWORD           dwReputation;              // 0x590
	DWORD           dwTransformState;          // 0x594       0: human; 1: fox
	char            uk13[0x70];                // 0x598
	WCHAR           *lpName;                   // 0x608 +     unicode string
	char            uk14[0x04];                // 0x60c
	DWORD           dwClassId;                 // 0x610
	DWORD           dwGender;                  // 0x614
	char            uk15[0x04];                // 0x618
	DWORD           dwTransportMode;           // 0x61c +     0: ground; 1: swim; 2: fly
	char            uk16[0x5c];                // 0x620
	BOOL            bAggro;                    // 0x67c
	char            uk17[0x470];               // 0x680
	DWORD           dwTargetId;                // 0xaf0 +
	DWORD           dwTmpTargetId;             // 0xaf4 +
	char            uk18[0xf4];                // 0xaf8
	DWORD           dwJumpState;               // 0xbec +     0, 1, 2
	char            uk19[0x258];               // 0xbf0
	ACTIONBASE0     *p_actionbase0;            // 0xe48 +
	char            uk22[0x14];                // 0xe4c
	PETLISTHEADER   *p_petlist;                // 0xe60 +
} PLAYEROBJ, *LPPLAYEROBJ;


typedef struct __tagMOBOBJ                     // also for npcs and pets (npcs and pets are in the mob list too) *** outdated ***
{
	char            uk0[0x0c];                 // 0x00
	float           angle0;                    // 0x0c
	float           uk1;                       // 0x10
	float           angle1;                    // 0x14
	char            uk2[0x24];                 // 0x18
	POINT3D         pos;                       // 0x3c
	char            uk3[0x6c];                 // 0x48
	DWORD           dwType;                    // 0xb4       9: pet; 7: npc; 6: monster (check MOBTYPE_ constants)
	char            uk4[0x64];                 // 0xb8
	DWORD           dwId;                      // 0x11c
	char            uk5[0x04];                 // 0x120
	DWORD           dwLevel;                   // 0x124
	char            uk6[0x04];                 // 0x128
	DWORD           dwHP;                      // 0x12c
	char            uk7[0x2c];                 // 0x130
	DWORD           dwMaxHP;                   // 0x15c
	char            uk8[0xd8];                 // 0x160
	DWORD           dwOwnerId;                 // 0x238      0: no owner; else pet owner id
	WCHAR           *lpName;                   // 0x23c      unicode string
} MOBOBJ, *LPMOBOBJ;


typedef struct __tagWORLDITEMOBJ               // also for resources (resources on the ground are also in the item list) *** probably outdated ***
{
	char            uk0[0x14];                 // 0x00
	DWORD           dwAmount;                  // 0x14
	DWORD           dwMaxAmount;               // 0x18
	DWORD           dwPrice;                   // 0x1c
	char            uk1[0xec];                 // 0x20
	DWORD           dwId;                      // 0x10c
	char            uk2[0x54];                 // 0x110
	WCHAR           *lpName;                   // 0x164
} WORLDITEMOBJ, *LPWORLDITEMOBJ;


typedef struct __tagGUIBASE1                     // *** up to date ***
{
	char         uk0[0x18];                      // 0x00
	void         *p_lastcmdsent;                 // 0x18         the gui obj that was sent the last cmd
	char         uk1[0xb8];                      // 0x1c
	void         *p_focus;                       // 0xd4         the gui obj that the mouse is over (has the mouse focus)
	char         uk2[0x1a4];                     // 0xd8
	void         *p_petbag;                      // 0x27c
	char         uk3[0x38];                      // 0x280
	void         *p_petbar;                      // 0x2b8
	char         uk4[0x8c];                      // 0x2bc
	void         *p_mainbar;                     // 0x348
	void         *p_prbar;                       // 0x34c        public relations bar
} GUIBASE1, *LPGUIBASE1;


typedef struct __tagGUIBASE0                     // *** up to date ***
{
	char         uk0[0x08];                      // 0x00
	GUIBASE1     *p_guibase1;                    // 0x08
} GUIBASE0, *LPGUIBASE0;


typedef struct __tagBASE1                        // *** up to date ***
{
	DWORD        uk0;                            // 0x00
	GUIBASE0     *p_guibase0;                    // 0x04 +       pointer to guibase0
	char         uk1[0x18];                      // 0x08
	PLAYEROBJ    *p_localplayer;                 // 0x20 +       pointer to local player obj
} BASE1, *LPBASE1;


typedef struct __tagBASE0
{
	BASE1        *p_base1;                       // 0x00 (this whole struct is actually just a pointer)
} BASE0, *LPBASE0;


typedef struct __tagWORLDOBJLISTENTRY                     // check GetObjByIdFromObjList    *** up to date ***
{
	__tagWORLDOBJLISTENTRY     *next;                     // 0x00
	void                       *p_obj;                    // 0x04       pointer to OBJ (player, mob/npc/pet, item/resource)
	DWORD                      dwId;                      // 0x08
} WORLDOBJLISTENTRY, *LPWORLDOBJLISTENTRY;


typedef struct __tagWORLDOBJLISTHEADER              // check GetObjByIdFromObjList     *** up to date ***
{
	char                 uk0[0x14];                 // 0x00
	DWORD                dwObjects;                 // 0x14       number of (valid) list entries (they are scattered over the entire list); invalid list entries == 0
	WORLDOBJLISTENTRY    **p_listentry;             // 0x18       pointer to sequential list of WORLDOBJLISTENTRYs
	void                 *lpEndOfList;              // 0x1c       either end of list or pointer to another structure
	DWORD                dwListEntries;             // 0x20       the size of the list in number of entries
	DWORD                dwIdEntryConversion;       // 0x24       Id / dwIdEntryConversion = List Entry to start
} WORLDOBJLISTHEADER, *LPWORLDOBJLISTHEADER;


typedef struct __tagWORLDOBJDB                 // world object database (check GetObjById)       *** up to date ***
{
	char                 uk0[0x20];              // 0x00
	WORLDOBJLISTHEADER   *p_playerlist;          // 0x20       players only (localplayer is not in this list)
	WORLDOBJLISTHEADER   *p_moblist;             // 0x24       mobs, npcs, pets
	WORLDOBJLISTHEADER   *p_itemlist;            // 0x28       items (on ground), resources (on ground)
} WORLDOBJDB, *LPWORLDOBJDB;


typedef struct __tagINVITEMOBJ                 // *** probably outdated ***
{
	char            uk0[0x14];                 // 0x00
	DWORD           dwAmount;                  // 0x14
	DWORD           dwMaxAmount;               // 0x18
	DWORD           dwPrice;                   // 0x1c
	char            uk1[0xec];                 // 0x20
	WCHAR           *lpName;                   // 0x50
	DWORD           dwId;                      // 0x10c
	char            uk2[0x54];                 // 0x110
} INVITEMOBJ, *LPINVITEMOBJ;


typedef struct __tagINVOBJLISTHEADER           // check GetInvItemBySlotFromList        *** up to date ***
{
	char            uk0[0x0c];                 // 0x00
	INVITEMOBJ      **p_item;                  // 0x0c       pointer to sequential list of pointers to inv item objects
	DWORD           dwTotalSlots;              // 0x10
} INVOBJLISTHEADER, *LPINVOBJLISTHEADER;


typedef struct __tagINVOBJDB                   // check GetInvItemListById       *** up to date ***
{
	char                 uk0[0xc34];                  // 0x00
	INVOBJLISTHEADER     *p_invitemlist;              // 0xc34      list id: 0    inventory items
	INVOBJLISTHEADER     *p_normalequipitemlist;      // 0xc38      id: 1         normal equipped items
	INVOBJLISTHEADER     *p_list2;                    // 0xc3c      id: 2
	char                 uk1[0x30];                   // 0xc40
	INVOBJLISTHEADER     *p_list3;                    // 0xc70      id: 3
	INVOBJLISTHEADER     *p_list4;                    // 0xc74      id: 4
	INVOBJLISTHEADER     *p_list5;                    // 0xc78      id: 5
	INVOBJLISTHEADER     *p_list6;                    // 0xc7c      id: 6
} INVOBJDB, *LPINVOBJDB;


typedef struct __tagOBJDBBASE2                 // *** up to date ***
{
	char         uk0[0x08];                    // 0x00
	WORLDOBJDB   *p_worldobjdb;                // 0x08       world object database
	char         uk1[0x14];                    // 0x0c
	INVOBJDB     *p_invobjdb;                  // 0x20       inventory item database
} OBJDBBASE2, *LPOBJDBBASE2;


typedef struct __tagOBJDBBASE1                   // *** up to date ***
{
	char         uk0[0x1c];                      // 0x00
	OBJDBBASE1   *p_objdbbase2;                  // 0x1c
	void         *p_objdbbase3;                  // 0x20       (includes p_objdbbase4)
} OBJDBBASE1, *LPOBJDBBASE1;

typedef struct __tagOBJDBBASE0
{
	OBJDBBASE1   *p_objdbbase1;                  // 0x00 (this struct is actually just a pointer)
} OBJDBBASE0, *LPOBJDBBASE0;
#pragma pack(pop)









/////////////////////////////////////////////////////
// *** constants and macros ***
/////////////////////////////////////////////////////
#define NOTARGET               0x00000000
#define INVALIDTARGET          NOTARGET

#define NOCURRENTPET           0xffffffff         // dwCurrentPet


// player action states
#define AS_NONE                           0     // standing still, doing nothing (also when flying and standing still)
#define AS_MOVE                           1     // either walking, jumping or flying somewhere
#define AS_MOVEINTORANGE                  2     // moving somewhere to execute an action (cast, atk, gather, talk to, ...)
#define AS_ATTACK                         3     // attacking
#define AS_CAST                           4     // casting (channeling) a spell
#define AS_MEDITATE                       0x0a  // meditating
#define AS_GATHER                         0x0b  // gathering resources


// pet hunger states
#define PH_FULL                  0
#define PH_SATISFIED             1
#define PH_PECKISH               2
#define PH_HUNGRY0               3
#define PH_HUNGRY1               4
#define PH_STARVING              5


// pet modes
#define PM_DEFEND                0
#define PM_AUTO                  1
#define PM_MANUAL                2
// the pet mode must be set via ingame function to tell the server (modifying in mem doesnt work)
// pet attack when casting a spell is totally server side
// if you change pet mode in mem from auto to manual and dont tell the server, the pet will still attack when
// you cast a spell


// pet gui commands
#define PETBAR_ATTACK                     "attack"
#define PETBAR_FOLLOW                     "follow"
#define PETBAR_STOP                       "stop"
#define PETBAR_MANUALMODE                 "combat"
#define PETBAR_DEFENDMODE                 "defensive"
#define PETBAR_AUTOMODE                   "offensive"

#define PETBAG_CALLX                      "summon%d"         // X: 1 based pet index (not zero based)
#define PETBAG_STOWX                      "recall%d"
#define PETBAG_STATSX                     "detail%d"


// mob stuff (these are only valid for MOBOBJ objects)
#define MOBTYPE_MOB        6
#define MOBTYPE_NPC        7
#define MOBTYPE_PET        9

#define ISMOB(obj) ((BOOL) (obj->dwType == MOBTYPE_MOB))
#define ISNPC(obj) ((BOOL) (obj->dwType == MOBTYPE_NPC))
#define ISPET(obj) ((BOOL) (obj->dwType == MOBTYPE_PET))



/////////////////////////////////////////////////
// *** class object pointers ***
/////////////////////////////////////////////////
BASE0          *p_base0 = (BASE0 *) VA_BASE0;
OBJDBBASE0     *p_objdbbase0 = (OBJDBBASE0 *) VA_OBJDBBASE0;


// class object macros
#define LOCALPLAYER()                 p_base0->p_base1->p_localplayer

#define OBJDBBASE1()                  p_objdbbase0->p_objdbbase1
#define OBJDBBASE4()                  ((void *) MAKEPTR(p_objdbbase0->p_objdbbase1->p_objdbbase3, OBJDBBASE4OFFSET))   // p_objdbbase4

#define MOBLISTHEADER()               p_objdbbase0->p_objdbbase1->p_objdbbase2->p_worldobjdb->p_moblist
#define PLAYERLISTHEADER()            p_objdbbase0->p_objdbbase1->p_objdbbase2->p_worldobjdb->p_playerlist
#define WORLDITEMLISTHEADER()         p_objdbbase0->p_objdbbase1->p_objdbbase2->p_worldobjdb->p_itemlist

#define INVITEMLISTHEADER()           p_objdbbase0->p_objdbbase1->p_objdbbase2->p_invobjdb->p_invitemlist;
#define EQUIPITEMLISTHEADER()         p_objdbbase0->p_objdbbase1->p_objdbbase2->p_invobjdb->p_equipitemlist;

hope it helped a bit.



*** update ***
i checked some structures, the following structures are still up to date:
ACTIONBASE0
ACTIONBASE1
PETOBJ
PETLISTHEADER

i also updated the offset of the pointer to the petlistheader into the PLAYEROBJ.




*** update ***
BASE1, GUIBASE0, GUIBASE1 updated


Pet Functions / GUI Commands:
-----------------------------------
in pw, theres a function that sends gui commands to gui elements. its similar to the SendMessage api, but it tells the gui element what to do, instead of what has happened.
all gui element objects are stored inside p_base0->p_base1->p_guibase0->p_guibase1 (i will update these structures in the attached code). once you found the GuiCommand function and the gui object, you can send commands to this object. so lets start to find some stuff.



GuiCommand:
----------------
open elementclient.exe in w32dasm. search for the string "Dlg_Building". double click it. there should be one reference to it at address 5928a0. this address is inside the GuiCommand function. so open ida pro graph view, jump to this address and scroll up to the function start.
GuiCommand looks like this:






the first param is a string (not unicode) which contains the command to execute. the second param is a pointer to the gui object to send the command to.



Gui Command and Objects:
--------------------------------
now we need to get some commands and objects so that we can use GuiCommand. i will explain how to send the "stow pet x" command to the petbag gui object (this principle applies to all other commands as well, so dont worry if you dont have a pet).

first of all, we need a good bp inside GuiCommand. 59271a is a good one, since the pointer to the gui command string will be stored in ebx and the pointer to the gui object will be stored in esi.

so, first open up your petbag. now set a bp on 59271a. now stow your pet (in the following pic i stowed my first pet). your bp will hit. dont resume the process for the following actions. now check the following pic:






as you can see, ebx points to the string "recall1". so the command to stow pet x is "recallx". esi holds the petbag gui object.

now lets find out how to get the petbag gui object.
as already said, all gui objects are stored inside p_base0->p_base1->p_guibase0->p_guibase1. so all we need to do, is search this area for the pointer to the petbag gui object. the pic shows you how to do it. (1) shows you how to get the address of p_guibase1. enter this address into the search range start. search range end should be search range start + whatever, i chose + 0x3000, dont make it too small. enter the value stored in esi (the petbag object) into the value to search field (tab hex). now start the search. you will most likely find 3 addresses if you havent resumed the process, which you shouldnt. now resume the process and play around a bit with your mouse and click some gui elements etc. you will see, that 2 addresses will change whenever you do something. in fact it's like this: the first address we found is the address of a pointer to the gui object that received the last command. the second address we found is the address of a pointer to the gui object that the mouse is hovering (that gui object has the mouse "focus"). the third address is the address of the pointer to our petbag gui object. now to get the offset into the p_guibase1 structure, simply substract the address of p_guibase1 from the addresses you found (in my pic, the first address (the address of the pointer to the gui object that recieved the last gui command) would have the offset 14583018 - 14583000 = 0x18). the second address (focus) offset would be 0xd4 and the third (petbag) would be 0x27c.


Pet Functions:
------------------
so to find out how to do pet functions, summon a pet, set the bp like above, click the attack button, and do the same as above (ebx holds the command string "attack", esi is the gui obj (petbar)). filter out the gui object (eliminate the addresses with the offsets 0x18 and 0x4d, which i explained above). the pet command strings are included in the attached source.

so, finally to make your pet attack, do this (pseudo code):
GuiCommand("attack", p_base0->p_base1->p_guibase0->p_guibase1->p_petbar)

p_petbar: [[[[9baad4] + 4] + 8] + 2b8]
p_petbag: [[[[9baad4] + 4] + 8] + 27c]
Attached Files
File Type: rar pics.rar (9.55 MB, 1658 views)
toxic6666 is offline  
Thanks
31 Users
Old 12/31/2009, 09:53   #2
 
elite*gold: 0
Join Date: Nov 2009
Posts: 12
Received Thanks: 1
Very nice! This may help alot for many people.
And now get the pointers to local client and objects struct automatically!
muchenberg is offline  
Thanks
1 User
Old 01/03/2010, 19:44   #3
 
louco89's Avatar
 
elite*gold: 0
Join Date: May 2009
Posts: 32
Received Thanks: 4
Thank you.
louco89 is offline  
Old 01/05/2010, 01:44   #4
 
elite*gold: 0
Join Date: Apr 2008
Posts: 84
Received Thanks: 5
thank you, why not also include the bot heheheh
wongfei888 is offline  
Old 01/06/2010, 13:15   #5
 
elite*gold: 0
Join Date: Mar 2007
Posts: 26
Received Thanks: 38
Quote:
Originally Posted by wongfei888 View Post
thank you, why not also include the bot heheheh

the bot i wrote was specially designed for my venomancer. the bot logic was hardcoded into the source code, there was no real gui to edit the bot logic and select the spells to cast etc. i really hate gui programming, so i just updated the bot logic to my preferred spell cycle everytime i got new spells. so this wouldnt be an all round bot. it would only work on venomancer lvl 5x+ that has all my spells. but with a little work, you should be able to write your own bot now. this is actually just a guide on where and how to start if you want to write your own bot
toxic6666 is offline  
Old 01/21/2010, 09:17   #6
 
elite*gold: 0
Join Date: Nov 2009
Posts: 8
Received Thanks: 0
Thank you for this guide!!

And i have a little question))) How I can get Name of current Location, such as "City of Dragons"? I'm trying search pointers with Cheat Engine, but can't find Base Adress.
Alexhomp is offline  
Old 01/21/2010, 18:59   #7
 
elite*gold: 0
Join Date: Mar 2007
Posts: 26
Received Thanks: 38
on the current pwi version, the pointer to the name of the current location would be:

[[[[[9ba42c] + 1c] + 8] + 60] + 4]


it looks like your using rus version, so this wont work for you. so here is a little very simplified tut on how to find it:


i tried to simply mem search for it, but i got kinda lost too
so i started to trace it, here is how i did it:

search for the name of the current location via ce (tab unicode and case sensitive). you should find about 6 or maybe more addresses. now change the location and search (next scan) for the new location name. about 3 addresses should be left. now find the "real" one: change the first letter of each address to something else and see what happens. if the letter will be reset to the original letter or if the location name in game will be updated with the changed letter, then you found the "real" one. in pwi, the location name will be constantly updated, so the letter will be reset to the original letter. now find out what writes to this address. you should find one address. it should be something like

mov word ptr [eax], bx

now open your preferred debugger and set a conditional bp on this address. lets say that the address of the "real" location name was 0x7d0302c, then your condition would look like this (in case the instruction is the same as above):

eax == 0x7d0302c

now trace back over 3 RETs via step-over (e.g. F8 in olly). write down the address your at now. open this address in ida pro. it should look similar to this:






as you can see, a virtual function is being called. the param (edi) is a pointer to the current location name. so we need to scroll up a bit, to see how to retrieve edi. so scroll up a bit until your screen looks similar to this:






as you can see, the last offset for our pointer is 0x04
now scroll up some more until your screen looks similar to this:






as you can see, the second last offset for our pointer is 0x60. all we need to do now, is check the function sub_4c9c80 to see how to get eax. so double click the function, and your screen should look similar to this:






here you have the static base address and 2 more offsets.


so in pwi, it would be (as already said):

[[[[[9ba42c] + 1c] + 8] + 60] + 4]
toxic6666 is offline  
Thanks
2 Users
Old 01/22/2010, 00:14   #8
 
elite*gold: 0
Join Date: Feb 2009
Posts: 46
Received Thanks: 30
Hey,

@toxic6666: it would be fine, if u also can help me with a little problem ^^

As i didnt want to loop 768 objects, i searched for alternatives and found the following ones:

9ba42c, 1C, 8, 20, A0, i*4, 3C <--3D position of player with index i
9ba42c, 1C, 8, 24, 50, i*4, 3C <--3D position of mob/npc/pet with index i

U can see i have A0/50 instead of 18 and i dont need the additional object in between (u called it WORLDOBJLISTENTRY).
The good thing on the pointer lists i found is, that all valid objects are at the beginning. So i just do a for-loop from 0 to Count-1.
My question is if there is also such a nice list for herbs/mats/items?

thx in advance,
Megamorph
Megamorph is offline  
Old 01/22/2010, 01:19   #9
 
elite*gold: 0
Join Date: Jan 2009
Posts: 137
Received Thanks: 19
Good manual, man. Thank you. I found some new info.

Toxic, I spent already 2 weeks for one task... I can inject NPC talk. I can close this window. I can directly by/sell items. But how can I select/open "Quests" in this window? It seems so difficult for me ((( Do you know how to do it?
AlexGD is offline  
Old 01/22/2010, 01:22   #10
 
elite*gold: 0
Join Date: Jan 2009
Posts: 69
Received Thanks: 13
Can someone help me write the injection code, which calls the pet "attack" function? Thanks. =)
FunkU is offline  
Old 01/22/2010, 07:34   #11
 
elite*gold: 0
Join Date: Nov 2009
Posts: 8
Received Thanks: 0
toxic6666, Thank you very much!!!
Alexhomp is offline  
Old 01/22/2010, 14:06   #12
 
elite*gold: 0
Join Date: Mar 2007
Posts: 26
Received Thanks: 38
@Megamorph:
your absolutely right. the lists you found are way better to use if you want to go through the whole list very quickly. the lists i used only seem to be used to get an object by its id very quickly.
but i have to disappoint you. i couldnt find such a list for items/resources either. im quite sure, it doesnt exist (but maybe im wrong). i scanned the whole process for pointers to item/resource objects i got from the "spread" list, but didnt get any other results except the ones from the spread list itself. maybe pw doesnt maintain such a list for items/resources because they are static objects that cant move, so they wont have to be updated that often. i might start another search attempt later this day or tomorrow, if i should find something i will post it, but i doubt it, sry

@AlexGD:
if i understood right, you wanna know how to accept quests from quest npcs? if so, i think you already found the function that sends gui commands to gui elements, but you have the problem that this function isnt called to accept a quest? at least thats what i found out right now. i might take a look at it in the next few days, i havent messed around with gui commands too much, except for pet functions.

@FunkU:
i will update the first post with some information about pet functions and gui commands in a little bit. it should help you solve your problem.

@Alexhomp:
your welcome




first post has beend updated with pet functions and gui commands at the end.
toxic6666 is offline  
Old 01/23/2010, 01:33   #13
 
elite*gold: 0
Join Date: Jan 2009
Posts: 137
Received Thanks: 19
Toxic, I really thank you for guide. Finally I understand disassembling! Yeap, I know, that I just tried to bad, but really your tut clear my eyes )))

But... But... ****! I try hard to link your gui functions to quest strings - i have not found any relations...

Don't get offended, please, I'm really tired to search this (((
AlexGD is offline  
Old 01/23/2010, 12:19   #14
 
elite*gold: 0
Join Date: Jan 2009
Posts: 69
Received Thanks: 13
Thank you. ) But I'm still bad at disassembling and other things you use. I'll try to follow your guide carefully and cautiously when I have time. "Pet attack" is not my primary goal for now. )

But maybe you can help me find a quick solution? I have an injection code which calls function "go back to town when player character is dead". It looks like that:

pushad
mov eax, dword ptr [$0098ADDC] // base address
mov edx [$005DA8F0] // back to town function
call edx
popad
ret

And also I have address of "pet attack" function, I think it's right for my client version - $005B7ED0. So how should look the injection code for "pet attack" function?
FunkU is offline  
Old 01/23/2010, 15:50   #15
 
elite*gold: 0
Join Date: Jan 2009
Posts: 137
Received Thanks: 19
@Megamorph

Do you talk about this?

Code:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~ unifyied getLoot function
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function TaPWT.getLoot(aProcessID: Cardinal; aPointer: DWORD): TaLoot;
var
  NamePointer: DWORD;
  aPlayer: TaPlayer;
begin
  aPlayer := getSelfInfo(aProcessID);

  Result.ID := getDWORD(aProcessID, aPointer + $11C);
  if (Result.ID <> 0) and (Result.ID <> 220) then
  begin
    NamePointer := getDWORD(aProcessID, aPointer + $164);
    Result.Name := getSTRING(aProcessID, NamePointer, 64);

    Result.Location.X := (getSINGLE(aProcessID, aPointer + $3C) / 10) + 400;
    Result.Location.Y := (getSINGLE(aProcessID, aPointer + $44) / 10) + 550;
    Result.Location.Z := (getSINGLE(aProcessID, aPointer + $40) / 10);
    Result.Location.HDelta := SQRT(ABS(Result.Location.X - aPlayer.Location.X)
        * ABS(Result.Location.X - aPlayer.Location.X) + ABS
        (Result.Location.Y - aPlayer.Location.Y) * ABS
        (Result.Location.Y - aPlayer.Location.Y));
    Result.Location.VDelta := ABS(Result.Location.Z - aPlayer.Location.Z);
    Result.Location.Distance := SQRT
      (Result.Location.HDelta * Result.Location.HDelta +
        Result.Location.VDelta * Result.Location.VDelta);
  end;
end;


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~ function to get Loot list in location
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function TaPWT.GetLocationLoot(aProcessID: Cardinal): TaLootArray;
var
  aLoot: TaLoot;
  p1, p2, p3, p4, p5: DWORD;
  I, n: integer;
begin
  SetLength(Result, 768);
  n := 0;
  p1 := getDWORD(aProcessID, getDWORD(aProcessID, getDWORD(aProcessID, aBaseAddress) + $1C) + $8);
  p2 := getDWORD(aProcessID, p1 + $28);
  p3 := getDWORD(aProcessID, p2 + $18);
  for I := 0 to 767 do
  begin
    p4 := getDWORD(aProcessID, p3 + (I * 4));
    p5 := getDWORD(aProcessID, p4 + $4);
    if getDWORD(aProcessID, p5 + $11C) <> 0 then
    begin
      aLoot := getLoot(aProcessID, p5);
      if (aLoot.ID <> 0) and (aLoot.ID <> 220) then
      begin
        Result[n] := aLoot;
        Inc(n);
      end;
    end;
  end;
end;
AlexGD is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
Anyone tried find addresses for a....
08/21/2009 - 12Sky2 - 2 Replies
hey for now we have speed hack taken from phurba, atack speed hack phurba as well, but did anyone tried to take atack damage from dmg weapon ? and def from def weapon ?. As well did anyone tried to hack the time from buffs like let say max is 180 second and did anyone try change it to 999 second ?
Cant find addresses
07/24/2009 - Grand Chase - 9 Replies
Hey im new here and im trying to get the 1 hit kill hack to work on MLE 1348 but for some reason when i scan 16256 in practice mode no addresses appear on the side. Any1 have a solution to this problem?
Why my UCE cannot find the addresses?
06/02/2009 - Grand Chase Philippines - 5 Replies
This is how the problem goes. One scenario: I have tried following the procedures on how to do the damage hack. And so in practice mode. I have tried using MK Ronan and scan the value 16256 in exact value on 4 bytes. The time I scan it, I see 3 addresses and one of those 3 has the exact value of what I input. the second one, I casted Holy Bless. And find the value of 16281. The next scan doesn't prompted any address. So I thought the first address I scan from 16256 is the one. I rescan...
Warrock Addresses/Offsets
10/20/2008 - WarRock - 11 Replies
Scope: B76DC6 Fast Ammo: B76DD0 Fast Health: B76DD4 Fast Repair: B76DD8 Fast Flag: B76DDC Crosshair: B76DF4 Circles: FFFFFFFF Boxes: 0 Nospread: B76E1C Nearfog: B91E64



All times are GMT +2. The time now is 14:30.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.