PWI - Resources/Loot Structure

04/23/2012 23:24 Subzero12#1
Hi all,

Been working on a small project, so far with 2h of coding and reading I'm already able to read all the NPC's info and player info.

But can't seem to be able to read any resources info :/

I think I found the resource count at: baseCall + 0x1C + 0x1C + 0x28 + 0x18 + 0x4 + 0x4

Can anyone give me some insight off the loot struct offsets?

(To see if i can pass to the 2nd stage of my project -> do stuff lol)

Thx :)
04/24/2012 00:24 dumbfck#2
Unfortunately there is no sorted list of resources, so you need to scan all 768 entries in the list:
Code:
[[[[[[[baseCall]+0x1C]+0x1C]+0x28]+0x18]+i*4]+0x4]
where i is 0 to 767.

Here's a little C# demo:
Form1.cs

MemFunctions.cs

Form1.Designer.cs

Good luck :D
04/24/2012 09:41 Subzero12#3
Thx :D I had a mistake in my item base pointer :o

I will try to correct it later and its time to start sending packets :)
04/24/2012 10:15 Interest07#4
Good luck :)

It's nice to see people programming their own stuff :D Your questions will be answered promptly if you have any I'm sure ;)
04/24/2012 20:03 Subzero12#5
The problem was:
uint pointer = MemFunctions.MemReadUInt(p, MemFunctions.resolveNestedPointer(p, baseCall, 0x1C, 0x1C, 0x28, 0x18));
uint itemBase = MemFunctions.MemReadUInt(p, MemFunctions.resolveNestedPointer(p, pointer + (i * 0x4), 0x4));

It continues to be in the move action, because I'm having an hard time figuring out when to use a MemRead or a resolveNestedPointer, any guide/tutorial that i can read in order to better understand this?
Or this knowledge comes from using CE and browsing the memory for the game?
04/24/2012 21:16 dumbfck#6
You would use a MemRead to just read a single memory location, e.g.,
Code:
MemRead(processHandle, 0x123456);
resolveNestedPointer is a little function I made up to make searching for nested pointers a bit easier. You literally just feed it a base and any number of offsets and it automagically recurses through a bunch of MemReads.
Say for example, you had (in the notation you'll see around these forums)
Code:
[[[[[[baseCall]+0x1C]+0x1C]+0x28]+0x4]0x4]
You'd simple call it like:
Code:
uint baseCall = 0xA521C0;
MemFunctions.resolveNestedPointer(processHandle, baseCall, 0x1C, 0x1C, 0x28, 0x4, 0x4);
To get the address of that last pointer. If you wanted to read data in that last pointer, as long as you want it in uint form, you can just add a 0 to the end of that list.
If what you want to eventually read is not a uint, you'll need one of the other read functions to read the final address you get from resolveNestedPointer.
So, say for example, that pointer chain pointed to a float, you could do something like:
Code:
MemFunctions.MemReadFloat(p, MemFunctions.resolveNestedPointer(p, baseCall, , 0x1C, 0x1C, 0x28, 0x4, 0x4));
Which would be the equivalent of this if you broke it into two steps with an intermediate variable:
Code:
uint pointerToFloat = MemFunctions.resolveNestedPointer(p, baseCall, , 0x1C, 0x1C, 0x28, 0x4, 0x4);
float derp = MemFunctions.MemReadFloat(p, pointerToFloat);
If you were to look at that offset chain in CE, it would look like:
[Only registered and activated users can see links. Click Here To Register...][Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
What language are you actualy using anyway? C#?
If you're using C#, you could try fiddling with it and setting breakpoints after your reads, then seeing if they match up with the values in CE. If your value matches one of the intermediate memory values shown in the CE window (see above) then you need another offset at the end of the chain.
Hope I'm making sense lol
04/25/2012 11:08 Interest07#7
Quote:
Originally Posted by dumbfck View Post
You would use a MemRead to just read a single memory location, e.g.,
Code:
MemRead(processHandle, 0x123456);
resolveNestedPointer is a little function I made up to make searching for nested pointers a bit easier. You literally just feed it a base and any number of offsets and it automagically recurses through a bunch of MemReads.
Say for example, you had (in the notation you'll see around these forums)
Code:
[[[[[[baseCall]+0x1C]+0x1C]+0x28]+0x4]0x4]
You'd simple call it like:
Code:
uint baseCall = 0xA521C0;
MemFunctions.resolveNestedPointer(processHandle, baseCall, 0x1C, 0x1C, 0x28, 0x4, 0x4);
To get the address of that last pointer. If you wanted to read data in that last pointer, as long as you want it in uint form, you can just add a 0 to the end of that list.
If what you want to eventually read is not a uint, you'll need one of the other read functions to read the final address you get from resolveNestedPointer.
So, say for example, that pointer chain pointed to a float, you could do something like:
Code:
MemFunctions.MemReadFloat(p, MemFunctions.resolveNestedPointer(p, baseCall, , 0x1C, 0x1C, 0x28, 0x4, 0x4));
Which would be the equivalent of this if you broke it into two steps with an intermediate variable:
Code:
uint pointerToFloat = MemFunctions.resolveNestedPointer(p, baseCall, , 0x1C, 0x1C, 0x28, 0x4, 0x4);
float derp = MemFunctions.MemReadFloat(p, pointerToFloat);
If you were to look at that offset chain in CE, it would look like:
[Only registered and activated users can see links. Click Here To Register...][Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
What language are you actualy using anyway? C#?
If you're using C#, you could try fiddling with it and setting breakpoints after your reads, then seeing if they match up with the values in CE. If your value matches one of the intermediate memory values shown in the CE window (see above) then you need another offset at the end of the chain.
Hope I'm making sense lol
In the end, if the nested pointer stuff confuses you, you don't have to use it.
using a pattern of:
Code:
uint basePointer = readMem(realBaseAddress);
uint pStructures = readMem(basePointer + 0x1C);
uint pPlayer = readMem(pStructures + 0x34);
uint hp = readMem(pPlayer+ 0xXXX);
works just as well, as that's what the resolve nested pointer does internally anyway (as far as i know :p)

It's the way I personally do it, as I have my classes structured in the same way as PW does, so it ends up doing one or two mem read calls in each class.
04/25/2012 11:42 Subzero12#8
Hmmm I see.

Then if I need the action struct addresses:
PHP Code:
uint addr1 MemFunctions.MemReadUInt(pr_processHandle0x00A521C0);
uint addr2 MemFunctions.MemReadUInt(pr_processHandleaddr1 0x1C);
uint addr3 MemFunctions.MemReadUInt(pr_processHandleaddr2 0x34);
uint actionStruct MemFunctions.MemReadUInt(pr_processHandleaddr3 0x109c);
uint actionList MemFunctions.MemReadUInt(pr_processHandleactionStruct 0x30);
uint moveAction MemFunctions.MemReadUInt(pr_processHandleactionList 0x8); 
And then to move to X,Y,Z I just need:
PHP Code:
MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction 0x80); 
MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction 0x141);
MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction 0x28X);
MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction 0x2CY);
MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction 0x30Z);
MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction 0x380);
MemFunctions.MemWriteInt(pr_processHandle, (int)actionStruct 0xC, (int) moveAction);
MemFunctions.MemWriteInt(pr_processHandle, (int)actionStruct 0x181);
MemFunctions.MemWriteInt(pr_processHandle, (int)actionStruct 0x14, (int) moveAction); 
Or I need to write any other value? (My char won't move xD)

Btw, Yes I'm using C# :) Trying to learn something more about it (so far seems very similar to C++/Java).
04/25/2012 11:50 dumbfck#9
I've never actually used action structs for moving, so I'm not sure about the process of doing so... However, check you don't have your Z and Y co-ordinates swapped. They're stored in X,Z,Y order, not X,Y,Z.
04/25/2012 11:53 Interest07#10
Quote:
Originally Posted by dumbfck View Post
I've never actually used action structs for moving, so I'm not sure about the process of doing so... However, check you don't have your Z and Y co-ordinates swapped. They're stored in X,Z,Y order, not X,Y,Z.
>.> They ARE stored in X, Y, Z order. It's a good idea to check you are using the CORRECT order though :p
04/25/2012 11:56 Sᴡoosh#11
Everybody seems to have a knack with not accepting that Z is the "real" Y here, and Y is height. This is usual in d3d coordinate systems - even though I , for some reason, hate Y being height. No clue why. In my code internals, Y is always Z, and Z is height :D
04/25/2012 11:56 dumbfck#12
Quote:
Originally Posted by Interest07 View Post
>.> They ARE stored in X, Y, Z order.
Ok, they're not stored how normal people think of X,Y,Z lol. Your brain works in mysterious ways... Brilliant... but mysterious :p
04/25/2012 12:01 Interest07#13
You people are hopeless :(

I'll have to send for the people with the nice white jackets that lets you hug yourself. Maybe they can teach you the error of your ways. The smart ones are always the craziest. Looking to see if the OP put the X Y Z values in the correct order was a good tip though, I'll give you that. Shame you're all so misguided in what correct means though.
04/25/2012 12:07 Sᴡoosh#14
For me :
X = X coordinate, 2D
Y = Y coordinate, 2D
Z = Height

Will always be manifested in my brain :D Probably from when I still played pw, people refered to it as X/Y to.

Interest, do pass me one of those fluffy, white jackets though, will you? :D
04/25/2012 12:20 Subzero12#15
Quote:
Originally Posted by Sᴡoosh View Post
For me :
X = X coordinate, 2D
Y = Y coordinate, 2D
Z = Height
To me too :D
Almost had forgotten about the time I used OpenGl and used the Y and Z switched.

But even switching Y and Z the small test char won't move :S