|
You last visited: Today at 23:49
Advertisement
PWI - Resources/Loot Structure
Discussion on PWI - Resources/Loot Structure within the Perfect World forum part of the MMORPGs category.
04/24/2012, 00:24
|
#1
|
elite*gold: 0
Join Date: Jun 2010
Posts: 75
Received Thanks: 2
|
PWI - Resources/Loot Structure
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, 01:24
|
#2
|
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
|
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
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace nearbyItems
{
public partial class Form1 : Form
{
public uint baseCall = 0xA521C0;
static Process[] processes = System.Diagnostics.Process.GetProcessesByName("elementclient");
static int pid;
//open process
public static IntPtr pr_processHandle = MemFunctions.OpenProcess(pid);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (processes.Length == 0)
{
MessageBox.Show("No elementclients were found");
Application.Exit();
}
else
{
pid = processes[0].Id;
//open process
pr_processHandle = MemFunctions.OpenProcess(pid);
}
timer1.Start();
}
private void button1_Click(object sender, EventArgs e)
{
}
private void getNearbyItemList()
{
IntPtr p = pr_processHandle; // Just a shorter name
uint bytesRead = 0;
// Pointer is the base of the nearby item list
uint pointer = MemFunctions.MemReadUInt(p, MemFunctions.resolveNestedPointer(p, baseCall, 0x1C, 0x1C, 0x28, 0x18));
for (uint i = 0; i < 768; i++)
{
uint itemBase = MemFunctions.MemReadUInt(p, MemFunctions.resolveNestedPointer(p, pointer + (i * 0x4), 0x4));
if (itemBase != 0)
{
uint itemTypeID = MemFunctions.MemReadUInt(p, itemBase + 0x110);
uint itemUniqueID = MemFunctions.MemReadUInt(p, itemBase + 0x10C);
string itemName = MemFunctions.MemReadUnicode(p, MemFunctions.MemReadUInt(p, itemBase + 0x168), 64, ref bytesRead);
textBox1.AppendText(itemBase.ToString("X8") + "\t" + itemName + "\r\n");
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.Clear();
getNearbyItemList();
}
}
}
MemFunctions.cs
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
public class MemFunctions
{
public delegate int ThreadProc(IntPtr param);
public enum EncodingType
{
ASCII,
Unicode,
UTF7,
UTF8,
GBK
}
[Flags]
public enum FreeType
{
Decommit = 0x4000,
Release = 0x8000,
}
const UInt32 INFINITE = 0xFFFFFFFF;
const UInt32 WAIT_ABANDONED = 0x00000080;
const UInt32 WAIT_OBJECT_0 = 0x00000000;
const UInt32 WAIT_TIMEOUT = 0x00000102;
[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
Int32 bInheritHandle,
UInt32 dwProcessId
);
[DllImport("Kernel32.dll")]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
private static extern Int32 CloseHandle(
IntPtr hObject
);
[DllImport("kernel32.dll")]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
int dwSize, FreeType dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
private static extern IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes, uint dwStackSize, IntPtr
lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
uint dwSize, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32.dll")]
private static extern UInt32 GetLastError();
public static int AllocateMemory(IntPtr processHandle, int memorySize)
{
return (int)VirtualAllocEx(processHandle, (IntPtr)0, (uint)memorySize, 0x1000, 0x40);
}
public static IntPtr CreateRemoteThread(IntPtr processHandle, int address)
{
return CreateRemoteThread(processHandle, (IntPtr)0, 0, (IntPtr)address, (IntPtr)0, 0, (IntPtr)0);
}
public static void WaitForSingleObject(IntPtr threadHandle)
{
if (WaitForSingleObject(threadHandle, INFINITE) != WAIT_OBJECT_0)
{
Debug.WriteLine("Failed waiting for single object");
}
}
public static void FreeMemory(IntPtr processHandle, int address)
{
bool result;
result = VirtualFreeEx(processHandle, (IntPtr)address, 0, FreeType.Release);
}
public static UInt32 GetError()
{
return GetLastError();
}
// constants information can be found in <winnt.h>
[Flags]
public enum ProcessAccessType
{
PROCESS_TERMINATE = (0x0001),
PROCESS_CREATE_THREAD = (0x0002),
PROCESS_SET_SESSIONID = (0x0004),
PROCESS_VM_OPERATION = (0x0008),
PROCESS_VM_READ = (0x0010),
PROCESS_VM_WRITE = (0x0020),
PROCESS_DUP_HANDLE = (0x0040),
PROCESS_CREATE_PROCESS = (0x0080),
PROCESS_SET_QUOTA = (0x0100),
PROCESS_SET_INFORMATION = (0x0200),
PROCESS_QUERY_INFORMATION = (0x0400)
}
public static IntPtr OpenProcess(int pId)
{
ProcessAccessType access;
access = ProcessAccessType.PROCESS_VM_READ
| ProcessAccessType.PROCESS_VM_WRITE
| ProcessAccessType.PROCESS_VM_OPERATION;
return OpenProcess(2035711, 0, (UInt32)pId);
//return OpenProcess((uint)access, 0, (UInt32)pId);
}
public static void CloseProcess(IntPtr handle)
{
Int32 result = CloseHandle(handle);
}
public static void MemWriteBytes(IntPtr processHandle, int address, byte[] value)
{
bool success;
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, value, (uint)value.Length, ref nBytesRead);
}
public static void MemWriteStruct(IntPtr processHandle, int address, object value)
{
bool success;
byte[] buffer = RawSerialize(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, (uint)buffer.Length, ref nBytesRead);
}
public static void MemWriteInt(IntPtr processHandle, int address, int value)
{
bool success;
byte[] buffer = BitConverter.GetBytes(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
}
public static void MemWriteFloat(IntPtr processHandle, int address, float value)
{
bool success;
byte[] buffer = BitConverter.GetBytes(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
}
public static void MemWriteShort(IntPtr processHandle, int address, short value)
{
bool success;
byte[] buffer = BitConverter.GetBytes(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, 2, ref nBytesRead);
}
public static void MemWriteByte(IntPtr processHandle, int address, byte value)
{
bool success;
byte[] buffer = BitConverter.GetBytes(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, 1, ref nBytesRead);
}
public static byte[] MemReadBytes(IntPtr processHandle, int address, int size)
{
bool success;
byte[] buffer = new byte[size];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, (uint)size, ref nBytesRead);
return buffer;
}
public unsafe static bool MemReadBytesToStruct(IntPtr processHandle, uint address, byte* pBytes, int size)
{
bool success;
byte[] buffer = new byte[size];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, (uint)size, ref nBytesRead);
for (int i = 0, j = buffer.Length; i < j; i++)
{
*pBytes++ = buffer[i];
}
return success;
}
public static int MemReadInt(IntPtr processHandle, int address)
{
bool success;
byte[] buffer = new byte[4];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
return BitConverter.ToInt32(buffer, 0);
}
public static uint MemReadUInt(IntPtr processHandle, uint address)
{
bool success;
byte[] buffer = new byte[4];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
return BitConverter.ToUInt32(buffer, 0);
}
// Returns the data referenced by a nested pointer, i.e., [[[[someAddress]+24]+28]+4]
public static uint MemReadUIntNested(IntPtr processHandle, uint firstAddr, params uint[] p)
{
uint val = MemReadUInt(processHandle, firstAddr);
for (int i = 0; i < p.Length; i++)
{
val = MemReadUInt(processHandle, val + p[i]);
}
return val;
}
// Resolves a nested pointer, i.e., [[[[someAddress]+24]+28]+4]
// To return the data referenced by the pointer (uint only) use 0 as the last param.
public static uint resolveNestedPointer(IntPtr processHandle, uint firstAddr, params uint[] p)
{
uint val = MemReadUInt(processHandle, firstAddr);
for (int i = 0; i < p.Length - 1; i++)
{
val = MemReadUInt(processHandle, val + p[i]);
}
return (uint)(val + p[p.Length - 1]);
}
public static float MemReadFloat(IntPtr processHandle, int address)
{
bool success;
byte[] buffer = new byte[4];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
return BitConverter.ToSingle(buffer, 0);
}
public static string MemReadUnicode(IntPtr processHandle, uint address, uint maxSize, ref uint _bytesRead)
{
bool success;
byte[] buffer = new byte[maxSize];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, maxSize, ref nBytesRead);
_bytesRead = nBytesRead;
return ByteArrayToString(buffer, EncodingType.Unicode);
}
// This one will be a bit slower, but will hopefully eliminate returning empty strings where
// the address + size is not in accessible memory, resulting in a failure from ReadProcessMemory.
// Bytes are read in chunks of [chunkSize] size and chunks are scanned for 0x00, 0x00 (i.e.,
// end of string). If this is not found, we read another chunk, repeating until the string
// terminator is found.
// This might also help with reading enormous strings (e.g., complete chat listing) until I find
// a better solution for working around the maximum memory size that can be read
public static string MemReadUnicodeToEnd(IntPtr processHandle, uint address, uint maxSize, uint chunkSize, ref uint _bytesRead, bool doubleTerminator = false)
{
bool success;
byte[] buffer = new byte[chunkSize];
byte[] bigString = new byte[maxSize];
UInt32 nBytesRead = 0;
bool exit = false;
uint i, j, currLength = 0;
do
{
success = ReadProcessMemory(processHandle, (IntPtr)(address + currLength), buffer, chunkSize, ref nBytesRead);
_bytesRead = nBytesRead;
System.Buffer.BlockCopy(buffer, 0, bigString, (int)currLength, (int)chunkSize);
currLength += chunkSize;
if (!doubleTerminator)
{
for (i = 0, j = chunkSize - 2; i < j; i++)
{
if (buffer[i] == 0 && buffer[i + 1] == 0)
{
// We found the string terminator
exit = true;
break;
}
}
}
else // Full chat listing can contain more than two consecutive 0x00 bytes because of item links.
{
for (i = 0, j = chunkSize - 3; i < j; i++)
{
if (buffer[i] == 0 && buffer[i + 1] == 0 && buffer[i + 2] == 0)
{
// We found the string terminator
exit = true;
break;
}
}
}
} while (!exit && currLength < maxSize);
_bytesRead = currLength - chunkSize + i;
return ByteArrayToString(bigString, EncodingType.Unicode);
}
public static object MemReadStruct(IntPtr processHandle, int address, Type anyType)
{
int rawsize = Marshal.SizeOf(anyType);
bool success;
byte[] buffer = new byte[rawsize];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, (UInt32)rawsize, ref nBytesRead);
return RawDeserialize(buffer, 0, anyType);
}
private static object RawDeserialize(byte[] rawData, int position, Type anyType)
{
int rawsize = Marshal.SizeOf(anyType);
if (rawsize > rawData.Length)
return null;
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
object retobj = Marshal.PtrToStructure(buffer, anyType);
Marshal.FreeHGlobal(buffer);
return retobj;
}
private static byte[] RawSerialize(object anything)
{
int rawSize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawDatas = new byte[rawSize];
Marshal.Copy(buffer, rawDatas, 0, rawSize);
Marshal.FreeHGlobal(buffer);
return rawDatas;
}
public unsafe static string fixedByteArrayToString(byte* bytes, uint maxLength)
{
return fixedByteArrayToString(bytes, maxLength, EncodingType.Unicode);
}
public unsafe static string fixedByteArrayToString(byte* bytes, uint maxLength, EncodingType enc)
{
byte[] temp = new byte[maxLength];
for (int i = 0; i < maxLength; i++)
{
temp[i] = *(bytes + i);
}
return ByteArrayToString(temp, enc);
}
public static string ByteArrayToString(byte[] bytes)
{
return ByteArrayToString(bytes, EncodingType.Unicode);
}
public static string ByteArrayToString(byte[] bytes, EncodingType encodingType)
{
int arraySize = bytes.Length;
// Redim array to be 2 bytes bigger and fill the last two bytes with 0x00
Array.Resize(ref bytes, arraySize + 2);
bytes[arraySize - 1] = 0;
bytes[arraySize - 2] = 0;
System.Text.Encoding encoding = null;
string result = "";
switch (encodingType)
{
case EncodingType.ASCII:
encoding = new System.Text.ASCIIEncoding();
break;
case EncodingType.Unicode:
encoding = new System.Text.UnicodeEncoding();
break;
case EncodingType.UTF7:
encoding = new System.Text.UTF7Encoding();
break;
case EncodingType.UTF8:
encoding = new System.Text.UTF8Encoding();
break;
case EncodingType.GBK:
encoding = Encoding.GetEncoding("GBK"); ;
break;
}
for (int i = 0; i < bytes.Length; i += 2)
{
if (bytes[i] == 0 && bytes[i + 1] == 0)
{
result = encoding.GetString(bytes, 0, i);
break;
}
}
return result;
}
public unsafe static string ByteArrayToStringByRef(byte* bytes, int maxSize, EncodingType encodingType)
{
byte[] bArray = new byte[maxSize];
int count = 0;
while (!(*bytes == 0 && *(bytes + 1) == 0) && count < maxSize - 2)
{
byte x = *bytes;
byte y = *(bytes + 1);
bArray[count] = *bytes;
bArray[count + 1] = *(bytes + 1);
bytes += 2;
count += 2;
}
return ByteArrayToString(bArray, encodingType);
}
public static byte[] StringToByteArray(string str, EncodingType encodingType)
{
System.Text.Encoding encoding = null;
switch (encodingType)
{
case EncodingType.ASCII:
encoding = new System.Text.ASCIIEncoding();
break;
case EncodingType.Unicode:
encoding = new System.Text.UnicodeEncoding();
break;
case EncodingType.UTF7:
encoding = new System.Text.UTF7Encoding();
break;
case EncodingType.UTF8:
encoding = new System.Text.UTF8Encoding();
break;
}
return encoding.GetBytes(str);
}
}
Form1.Designer.cs
Code:
namespace nearbyItems
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(236, 309);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(11, 16);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(299, 280);
this.textBox1.TabIndex = 1;
//
// timer1
//
this.timer1.Interval = 300;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(323, 344);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Timer timer1;
}
}
Good luck
|
|
|
04/24/2012, 10:41
|
#3
|
elite*gold: 0
Join Date: Jun 2010
Posts: 75
Received Thanks: 2
|
Thx  I had a mistake in my item base pointer
I will try to correct it later and its time to start sending packets
|
|
|
04/24/2012, 11:15
|
#4
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
Good luck
It's nice to see people programming their own stuff  Your questions will be answered promptly if you have any I'm sure
|
|
|
04/24/2012, 21:03
|
#5
|
elite*gold: 0
Join Date: Jun 2010
Posts: 75
Received Thanks: 2
|
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, 22:16
|
#6
|
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
|
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:
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, 12:08
|
#7
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
Quote:
Originally Posted by dumbfck
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:
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  )
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, 12:42
|
#8
|
elite*gold: 0
Join Date: Jun 2010
Posts: 75
Received Thanks: 2
|
Hmmm I see.
Then if I need the action struct addresses:
PHP Code:
uint addr1 = MemFunctions.MemReadUInt(pr_processHandle, 0x00A521C0); uint addr2 = MemFunctions.MemReadUInt(pr_processHandle, addr1 + 0x1C); uint addr3 = MemFunctions.MemReadUInt(pr_processHandle, addr2 + 0x34); uint actionStruct = MemFunctions.MemReadUInt(pr_processHandle, addr3 + 0x109c); uint actionList = MemFunctions.MemReadUInt(pr_processHandle, actionStruct + 0x30); uint moveAction = MemFunctions.MemReadUInt(pr_processHandle, actionList + 0x8);
And then to move to X,Y,Z I just need:
PHP Code:
MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction + 0x8, 0); MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction + 0x14, 1); MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction + 0x28, X); MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction + 0x2C, Y); MemFunctions.MemWriteFloat(pr_processHandle, (int) moveAction + 0x30, Z); MemFunctions.MemWriteInt(pr_processHandle, (int) moveAction + 0x38, 0); MemFunctions.MemWriteInt(pr_processHandle, (int)actionStruct + 0xC, (int) moveAction); MemFunctions.MemWriteInt(pr_processHandle, (int)actionStruct + 0x18, 1); 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, 12:50
|
#9
|
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
|
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, 12:53
|
#10
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
Quote:
Originally Posted by dumbfck
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
|
|
|
04/25/2012, 12:56
|
#11
|
elite*gold: 20
Join Date: May 2009
Posts: 1,290
Received Thanks: 326
|
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
|
|
|
04/25/2012, 12:56
|
#12
|
elite*gold: 10
Join Date: Sep 2010
Posts: 400
Received Thanks: 234
|
Quote:
Originally Posted by Interest07
>.> 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
|
|
|
04/25/2012, 13:01
|
#13
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
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, 13:07
|
#14
|
elite*gold: 20
Join Date: May 2009
Posts: 1,290
Received Thanks: 326
|
For me :
X = X coordinate, 2D
Y = Y coordinate, 2D
Z = Height
Will always be manifested in my brain  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?
|
|
|
04/25/2012, 13:20
|
#15
|
elite*gold: 0
Join Date: Jun 2010
Posts: 75
Received Thanks: 2
|
Quote:
Originally Posted by Sᴡoosh
For me :
X = X coordinate, 2D
Y = Y coordinate, 2D
Z = Height
|
To me too 
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
|
|
|
 |
|
Similar Threads
|
Xml Database Structure
02/28/2012 - CO2 PServer Guides & Releases - 11 Replies
Alright, this is still unfinished, At the moment it only supports MYSQL, but I will finish rest later, if I get time. It's untested so far and so, but looks like it would work.
Anyways, when I get home I will test it and fix whatever I find of bugs etc.
It also still contains the xml converter as it's under solution.
The XmlLib is a DLL, which you just add as reference to your project, however there is some major things you need to do, before you actually use it.
First of all you...
|
SQL-DB structure
05/29/2010 - Silkroad Online - 0 Replies
Hey folks,
does anyone happen to have the structure of the official SRO SQL-DB? I need no more than the column names and their associated table names (usually located in the DB "INFORMATION_SCHEMA").
|
[C] Player Structure [PW-MS]
03/16/2010 - PW Hacks, Bots, Cheats, Exploits - 5 Replies
Hi everyone. Just wanna share the stuff i found out when reversing the game.
Assuming you are using dll injectiong and you have the base pointer to all player stats, you can simply access all the data from a nice and userfriendly structure.
Here how to read from memory:
VARBASE *Stats = 0xBASEPOINTER;
printf("Player HP: %d/%d", Stats->p_Player->Current_HP, Stats->p_Player->Maximum_HP);
And here the structure you need to make this available:
typedef unsinged char BYTE;
|
packet structure
03/09/2008 - Conquer Online 2 - 16 Replies
For what I'd like to do, I think packets are the place to start. After that, probably java then C and VB. This is a question for the people here who are self-taught... what resources would you recommend for...
1. understanding packet structure
2. learning some programming language without enrolling at the local university
I'm mainly interested in packet structure and how to capture/decipher/edit/send them, and eventually I'd like to "automate" these functions by writing some programs. ...
|
Drop-Loot bug (Loot sichtbar vor dem kill)
03/28/2006 - WoW Exploits, Hacks, Tools & Macros - 1 Replies
So hi
und zwar für alle die gerne mal etwas farmen aber kaum zeit haben ein kleiner Tipp der immo noch auch allen EU realms (ja auch auf Blizz-Servern) ghet. und zwar gibt es in den Blasted Lands den Altar of the Storms dort laufen mobs der LVL ca. 54 rum.
Das geniale kommt est noch man sihet an den mobs bevor man sie killt, angreift was auch immer ob und welche Waffe sie droppe.
Das system ist ganz einfach: es laufen dort z.B. Walocks rum diese habven immer so nen schwarzen staff in...
|
All times are GMT +1. The time now is 23:50.
|
|