Reading CPed pool

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
Hello, i need some help ;)
I'am trying to read memory pool from CPed,
need to get every CPed pointer on every peds,
but seems my code doesn't work correctly, where i'am failed?

Code:
DWORD CNULL = 0x1; 
  DWORD *POOL = &CNULL; 
  ReadProcessMemory(hProc, (LPVOID)0xB74490, POOL, 4, 0); 
  for (int i = 0; i < 65535; i++) 
  { 
   DWORD *PlayerPtr = &CNULL; 
   *PlayerPtr = *POOL + (i * 0x7C4); 
 
   DWORD *player = &CNULL; 
   ReadProcessMemory(hProc, (LPVOID)*PlayerPtr, player, 4, 0); 
 
   DWORD IsObjectCreated = 0; 
   DWORD *isElementAddr = &CNULL; 
   *isElementAddr = (*player) + 0x18; 
   ReadProcessMemory(hProc, (LPVOID)*isElementAddr, &IsObjectCreated, 4, 0); 
   if (IsObjectCreated == 0) continue; 
 
   float health = 0.00; 
   DWORD *HealthAddr = &CNULL; 
   *HealthAddr = (*player) + (0x540); 
 
   ReadProcessMemory(hProc, (LPVOID)*HealthAddr, &health, 4, 0); 
 
   printf("[i: %i] OFFSET: %i | HEALTH: %f\n",i,*player,health); 
  } 
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
user88 said:
Cnull 0x1???

It's just pointer initiallization cuz i have exception on executing like i use pointers wich was not been initiated. Doesn't matter, question in another, why my reading example doesn't work correctly - i get not valid pointers. And i need to do it only from ReadProcessMemory cuz i make a trainer.
 
Joined
Dec 31, 2015
Messages
712
Reaction score
27
Took a quick peek on this, the problem may be in the pointer arithmetic, uint_ptr + 0x01 means your pointer will be incremented by sizeof(uint_ptr), mostly by 4 bytes on x86 and by 8 on x64
Try cast it to char*
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
supahdupahnubah said:
Took a quick peek on this, the problem may be in the pointer arithmetic, uint_ptr + 0x01 means your pointer will be incremented by sizeof(uint_ptr), mostly by 4 bytes on x86 and by 8 on x64
Try cast it to char*

But i'am initiate pointer before i set a new value. How it's can increment my next values?


So if u right suppa, next code must works i think.
Anyway here is not important to use pointers.
Code:
  DWORD POOL; 
  ReadProcessMemory(hProc, (LPVOID)0xB74490, &POOL, 4, 0); 
  for (int i = 0; i < 65535; i++) 
  { 
   DWORD PlayerPtr;
   PlayerPtr = POOL + (i * 0x7C4); 
 
   DWORD player; 
   ReadProcessMemory(hProc, (LPVOID)PlayerPtr, &player, 4, 0); 
 
   DWORD CPedOffset= 0; 
   DWORD isPedCreated; 
   CPedOffset = player + 0x18; 
   ReadProcessMemory(hProc, (LPVOID)CPedOffset, &IsPedCreated, 4, 0); 
   if (IsPedCreated == 0) continue; 
 
   float health = 0.00; 
   DWORD HealthAddr; 
   HealthAddr = player + 0x540; 
 
   ReadProcessMemory(hProc, (LPVOID)HealthAddr, &health, 4, 0); 
 
   printf("[i: %i] OFFSET: %i | HEALTH: %f\n",i,player,health); 
  } 
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
Nope( It's doesn't parsing pool correctly, only in 0x0 offset my local player was been valid but others offset - not.
 

monday

Expert
Joined
Jun 23, 2014
Messages
1,125
Reaction score
149
I guess you could complete this task using:
http://ugbase.eu/Thread-SNIPPET-For-All-Peds
+
https://www.gtamodding.com/wiki/Memory_Addresses_(SA)#Pedestrians


Just keep in mind that "0xB74490" is not an address to the begining of ped pool. It's pointing to "ped pool usage information, which contains:"

   
+0 = Pointer to the first ped in the pool
   +4 = Pointer to a byte map indicating which peds are in use
   +8 = [dword] Maximum number of peds in the pool
   +12 = [dword] Current number of peds in the pool

That's why in the snippet "ForAllPeds" +0x4 is added after initial reading of the address. To reach "byte map" indicating which peds are in use. That byte map is 140 bytes long, each byte representing 1 actor. If the byte is higher than 0 and lower than 128 then the actor is streamed and his information corresponding to that byte could be read from the main ped pool (which starts at the address that you get by reading 0xB7CD98 edit: possibly it does but i'm paranoically not sure about it now, anyway it definately starts when you read 0xB74490 "twice" just like it says in the quote above, "[value at 0xB74490]+0 is a pointer to the first ped in the pool").

If you look at that snippet it reads the byte map 1 by 1 (29@ increases by 1 with each loop). But in the end that snippet provides actor handle (31@) which isn't the begining of CPed I think. So don't just fully copy that snippet, copy the part that reads the byte map and what you'd have to do is:
-read all the bytes from the byte map and if any of them is between 0 and 128 then:
   -multiply the index of that byte by length of each CPed (1988) and add it to the value found at 0xB7CD98

This way you should get to the begining of that structure for specific ped (if I didn't make any mistake)


Edit:
I forgot that I used something like this before... It's not the clearest or most efficient example but it worked fine
[shcode=cpp]    gtaActorBase = *(DWORD*)0xB74490;
    byteMap = *(DWORD*)(gtaActorBase+4);
    DWORD numberOfActiveActors = *(DWORD*)(gtaActorBase+12);
    for(DWORD i = 0; i < 35584; i = i + 0x100)
    {
        BYTE inUse = *(BYTE*)byteMap;
        byteMap += 0x1;
        if(inUse > 0x00 && 0x80 > inUse)
        {                       

            DWORD offset = i / 256 * 1988;                         
            DWORD pActorStruct = *(DWORD*)*(DWORD*)0xB74490; //pointer to the first element in the pool
            pActorStruct += offset; //add our offset for the active actor
                              
            if((*(unsigned short*)(pActorStruct + 0x530))!=1){continue;}//55 = wasted

            pActorStruct += 0x14;                       
            DWORD pActorCoords = *(DWORD*)pActorStruct; //coords  
            [/shcode]
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
monday said:
I guess you could complete this task using:
http://ugbase.eu/Thread-SNIPPET-For-All-Peds
+
https://www.gtamodding.com/wiki/Memory_Addresses_(SA)#Pedestrians


Just keep in mind that "0xB74490" is not an address to the begining of ped pool. It's pointing to "ped pool usage information, which contains:"

   
+0 = Pointer to the first ped in the pool
   +4 = Pointer to a byte map indicating which peds are in use
   +8 = [dword] Maximum number of peds in the pool
   +12 = [dword] Current number of peds in the pool

That's why in the snippet "ForAllPeds" +0x4 is added after initial reading of the address. To reach "byte map" indicating which peds are in use. That byte map is 140 bytes long, each byte representing 1 actor. If the byte is higher than 0 and lower than 128 then the actor is streamed and his information corresponding to that byte could be read from the main ped pool (which starts at the address that you get by reading 0xB7CD98 edit: possibly it does but i'm paranoically not sure about it now, anyway it definately starts when you read 0xB74490 "twice" just like it says in the quote above, "[value at 0xB74490]+0 is a pointer to the first ped in the pool").

If you look at that snippet it reads the byte map 1 by 1 (29@ increases by 1 with each loop). But in the end that snippet provides actor handle (31@) which isn't the begining of CPed I think. So don't just fully copy that snippet, copy the part that reads the byte map and what you'd have to do is:
-read all the bytes from the byte map and if any of them is between 0 and 128 then:
   -multiply the index of that byte by length of each CPed (1988) and add it to the value found at 0xB7CD98

This way you should get to the begining of that structure for specific ped (if I didn't make any mistake)


Edit:
I forgot that I used something like this before... It's not the clearest or most efficient example but it worked fine
[shcode=cpp]    gtaActorBase = *(DWORD*)0xB74490;
    byteMap = *(DWORD*)(gtaActorBase+4);
    DWORD numberOfActiveActors = *(DWORD*)(gtaActorBase+12);
    for(DWORD i = 0; i < 35584; i = i + 0x100)
    {
        BYTE inUse = *(BYTE*)byteMap;
        byteMap += 0x1;
        if(inUse > 0x00 && 0x80 > inUse)
        {                       

            DWORD offset = i / 256 * 1988;                         
            DWORD pActorStruct = *(DWORD*)*(DWORD*)0xB74490; //pointer to the first element in the pool
            pActorStruct += offset; //add our offset for the active actor
                              
            if((*(unsigned short*)(pActorStruct + 0x530))!=1){continue;}//55 = wasted

            pActorStruct += 0x14;                       
            DWORD pActorCoords = *(DWORD*)pActorStruct; //coords  
            [/shcode]
i
i hope that i'am correctly understood u, trying to rewrite my reading and all will be nothing if i've used just pointers from dll, cuz from trainer i'am dissapointed with anonoying use of ReadProcessMemory on reading pointers(


Doesn't works(
DWORD CPed, CMap;
ReadProcessMemory(hProc, (LPVOID)0xB74490, &CPed, 4, 0);
CMap = (CPed + 0x4);
ReadProcessMemory(hProc, (LPVOID)CMap, &CMap, 4, 0);
for (DWORD i = 0; i < 35584; i = i + 0x100)
{
BYTE valide;
ReadProcessMemory(hProc, (LPVOID)CMap, &valide, 4, 0);
CPed += 0x1;
if(valide > 0x00 && 0x80 > valide)
{
float health = 0;
DWORD pActorStruct;
DWORD offset = i / 256 * 1988;
ReadProcessMemory(hProc, (LPVOID)0xB74490, &pActorStruct, 4, 0);
pActorStruct += offset; //add our offset for the active actor
ReadProcessMemory(hProc, (LPVOID)pActorStruct, &pActorStruct, 4, 0);
DWORD AddrHp = pActorStruct + 0x540;
ReadProcessMemory(hProc, (LPVOID)AddrHp, &health, 4, 0);
if (health > 0) {
printf("[id: %i]: health: %f\n",i,health);
}
}
}
 

user88

Well-known member
Joined
Jun 29, 2017
Messages
426
Reaction score
165
Location
LINK CLEO DICE HACK HERE!
This is the problem if cleo coders goto c++
No prepared functions?
(Oh, fuck no functions to cp)

Its really that simple to read out that shit
Gtamodding is self explained

Btw why use the pedpool instead of patternscan of samp structures?
And forget the playing with pointers, u can cut yourself into Ya foot
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
user88 said:
This is the problem if cleo coders goto c++
No prepared functions?
(Oh, fuck no functions to cp)

Its really that simple to read out that shit
Gtamodding is self explained

Btw why use the pedpool instead of patternscan of samp structures?
And forget the playing with pointers, u can cut yourself into Ya foot

It's not for sa:mp
 

monday

Expert
Joined
Jun 23, 2014
Messages
1,125
Reaction score
149
waiting for window + opening process + the base for it I took from Opcode.eXe code
http://ugbase.eu/Thread-Memory-Addresses--16382?pid=96416#pid96416

actor_struct was copied from s0beit if I remember but idk, just slightly changed (I deleted bits that had incompatible types from what I remember)
Code:
// GTA_mod.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

using namespace std;


struct actor_info
{
#pragma pack( 1 )
    BYTE deleted[34];
    unsigned short modelID;
    BYTE deleted11[30];
    uint8_t                flags;                /* 66 immunities */
    uint8_t                __unknown_67[1];    /* 67 */
    BYTE deleted2[12];    /* 68 */

    float                spin[3];            /* 80 */
    float                speed_rammed[3];    /* 92 */
    float                spin_rammed[3];        /* 104 */
    uint8_t                __unknown_116[60];    /* 116 */
    void                *__unknown_176;        /* 176 - pointer to a "entry node info" pool item */
    void                *__unknown_180;        /* 180 - pointer to a "ptr node Double" pool item */

                                            //collision data
    DWORD                collision_flags;    /* 184 - 2nd byte = currently colliding 1/0, or actively
                                            running against (0x2), 3rd byte = type colliding with
                                            (1 = road, 4=pavement, 35 = object, 3f=car).. unsure about 3rd byte

                                            nuck notes: 186 is used to tell if a surface is "steep" too,
                                            actually any slight angle at all
                                            */
    void                *last_touched_object;    /* 188 - You can touch roads - those are considered buildings */
    void                *last_collided_object;    /* 192 - pointer to object last collided with (on foot, not jetpack) */
    uint8_t                __unknown_196[16];        /* 196 */
    float                speed;            /* 212 */
    float                collision_time_216; /* 216 - collision timer? */
    void                *collision_current_obj;        /* 220 - pointer to current thing colliding with */
    uint8_t                collision_something[12];    /* 224 - related to collision */
    float                collision_last_coord[3];    /* 236 - coordination of last collision */

                                                    //end of collision data
    uint8_t                __unknown_248[100];            /* 248 */
                                                    // 252 - animation related
    uint8_t                animation_state;            /* 348 */
    uint8_t                __unknown_349[7];            /* 349 */
    float                step_pos[3];        /* 356 - coordinates, last foot step */
    float                step_pos_before[3]; /* 368 - coordinates, foot step before last one */
    uint8_t                __unknown_380[752]; /* 380 */

    BYTE deleted3[16];            /* 1132 */
                                //1148 - animations base
    struct animation_base *animBase;
    BYTE deleted10[4];

    uint8_t                __unknown_1156[8]; /* 1156 */

                                           // relative body-part-positions
    void                *pNeck;                /* 1164 - void* pNeck
                                            (pChest?)
                                            - 4 unknown
                                            - float height
                                            - float front/back
                                            - float left/right
                                            - void* pObject
                                            (same struct for the following body-part-pointers [except pLeft/RightArm])
                                            */
    void                *pHead;                /* 1168 */
    void                *pLeftArm;            /* 1172 */
    void                *pRightArm;            /* 1176 */
    void                *pLeftLowArm;        /* 1180 */
    void                *pRightLowArm;        /* 1184 */
    void                *pLeftLeg;            /* 1188 */
    void                *pRightLeg;            /* 1192 */
    void                *pLeftLowLeg;        /* 1196 */
    void                *pRightLowLeg;        /* 1200 */
    void                *pRightMidLeg;        /* 1204 */
    void                *pLeftMidLeg;        /* 1208 */
    void                *pLeftMidArm;        /* 1212 */
    void                *pRightMidArm;        /* 1216 */
    void                *pLeftShoulder;        /* 1220 */
    void                *pRightShoulder;    /* 1224 */
    void                *pChest;            /* 1228 */
    void                *pMouth;            /* 1232 */
                                            // end of body-part-positions

    uint8_t                runningStyle;        /* 1236 - 0x36 = cj, 0x8A = rollerskate,
                                            0x7F = woozie, 0x75 = crash.. etc. */
    uint8_t                __unknown_1237[7];    /* 1237 */
    float                runspeed;            /* 1244 */
    uint8_t                __unknown_1248[36]; /* 1248 */
    uint16_t            muzzle_flash;        /* 1284 */
    uint8_t                __unknown_1286[6];    /* 1286 */

    BYTE deleted4[32];    /* 1292 - Inverse Kinematics */
    uint8_t                __unknown_1324[4];    /* 1324 */

    uint32_t            actorState;    /* 1328 - ACTOR_STATE_* */
    uint32_t            runState; /* 1332 - ACTOR_MSTATE_* */
    uint8_t                __unknown_1336[8];    /* 1336 */
    float                hitpoints;            /* 1344 */
    float                hitpoints_max;        /* 1348 - hmm, does not seem to be right.. it's set to "100.1318519" or something like that */
    float                armor;    /* 1352 */
    uint8_t                __unknown_1356[12];        /* 1356 */

                                                // 1360 and 1364 are using in resetting on-foot position when re-standing up

    float                fCurrentRotation;        /* 1368 */
    float                fTargetRotation;        /* 1372 */
    float                fRotationSpeed;            /* 1376 */
    float                fRotationCalculation;    /* 1380 - is 0.1 when target rotation reached */

    union
    {
        BYTE deleted5[4];    /* 1384 - touching a CEntitySAInterface */
        struct vehicle_info *vehicle_contact;    /* 1384 - standing on top of vehicle */
    };

    float    vehicle_contact_dist[3];            /* 1388 - distance to the middle of the car standing on */
    float    fPlaneAnglesContactEntity[3];        /* 1400 - Angles of the plane of the contact entity the actor is
                                                standing on (?) */
    void    *item_contact;                        /* 1412 - standing on top of vehicle/object/building/...*/
    float    fUnknown_1416;                        /* 1416 - only changing when slightly under map */

    union
    {
        //CEntitySAInterface    *CurrentObjective;    /* 1420 - usually current vehicle's entity */
        DWORD vehicleDw;
        struct vehicle_info *vehicle;
    };

    uint8_t                __unknown_1424[8];    /* 1424 */
    uint8_t                actor_lock;            /* 1432 */
    uint8_t                __unknown_1433[7];    /* 1433 */
    BYTE deleted6[364];            /* 1440 */
    uint8_t                __unknown_1804[12]; /* 1804 */
    uint8_t                weapon_slot;        /* 1816 */
    uint8_t                __unknown_1817[3];    /* 1817 */
    void                *ptr_autoAimTarget;    /* 1820 - weapon target */
    float                fImpactPos_close[3];/* 1824 - last impact point of close range weapon [fist/knife/csaw/etc.] */
    uint8_t                __unknown_1836[20]; /* 1836 */
    uint32_t            weapon_model;        /* 1856 */
    uint8_t                __unknown_1860[28]; /* 1860 */
    uint32_t            weapon_hit_type;    /* 1888 - last hit by this weapon */
    struct actor_info    *weapon_hit_by;        /* 1892 - last hit by this object (usually an actor) */
    uint8_t                __unknown_1889[92]; /* 1896 */
};    /* 1988 */


int main()
{
    cout << "Looking for GTA:SA:MP window." << endl;
    // MA VARIABLES
    DWORD pId;
    DWORD dwOldProtect = 0;
    HANDLE pHandle;
    HWND hWnd = 0;

    float zero = 0.0;
    while (hWnd == 0) {
        hWnd = FindWindow(0, "GTA:SA:MP");
        Sleep(100);
    }
    cout << "Just found the window." << endl;

    GetWindowThreadProcessId(hWnd, &pId);
    pHandle = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION, TRUE, pId);

    
    DWORD pedPoolUsageInfo;
    DWORD pedPoolBegining;
    DWORD byteMapAddr;
    BYTE activityStatus; //bytemap check
    actor_info actor; // a.k.a "CPed" or ClassPedestrian?
    float hp;
    float armor;
    while (true) 
    {
        ReadProcessMemory(pHandle, (LPCVOID)0xB74490, &pedPoolUsageInfo, 4, 0);
        ReadProcessMemory(pHandle, (LPCVOID)(pedPoolUsageInfo), &pedPoolBegining, 4, 0);
        ReadProcessMemory(pHandle, (LPCVOID)(pedPoolUsageInfo +4), &byteMapAddr, 4, 0);
        
        for (BYTE i = 0; i < 140; i++)
        {
            ReadProcessMemory(pHandle, (LPCVOID)(byteMapAddr + i), &activityStatus, 1, 0);
            if (activityStatus > 0 && activityStatus < 128)
            {
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988), &actor, 1988, 0);
                cout << "ID(memory): " << (int)i << ", Speed: " << actor.speed << ", HP: " << actor.hitpoints << ", Armor: " << actor.armor << endl;

                //or instead of reading the whole 1988 bytes at once (which is slow) ignore the actor_struct and "manually" read all the data like:
                /*
                
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988 + 1344), &hp, 4, 0); //1344 is offset for hp
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988 + 1352), &armor, 4, 0); //1352 is offset for armor
                cout << "ID(memory): " << (int)i << ", HP: " << hp << ", Armor: " << armor << endl;
                
                */

                Sleep(500); // just to check whether the example works without spamming too much
            }
        }        
    }
    CloseHandle(pHandle);
    return 0;
}

Just tested it and it worked, with samp in windowed mode so the output is visible. The whole actor_struct allows to use a simple:
actor.armor
But it reads the whole 1988 which is slow, idk if there's a way to efficiently and easily access memory without injecting the mod to the process.
So there's also commented out part in the main function which simply reads the required 4 bytes, takes more hassle to write but works faster. If you use the commented out part then you could just delete the big actor_info struct.
 

0pc0d3R

Active member
Joined
Feb 11, 2016
Messages
96
Reaction score
2
Location
Ukraine
monday said:
waiting for window + opening process + the base for it I took from Opcode.eXe code
http://ugbase.eu/Thread-Memory-Addresses--16382?pid=96416#pid96416

actor_struct was copied from s0beit if I remember but idk, just slightly changed (I deleted bits that had incompatible types from what I remember)
Code:
// GTA_mod.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

using namespace std;


struct actor_info
{
#pragma pack( 1 )
    BYTE deleted[34];
    unsigned short modelID;
    BYTE deleted11[30];
    uint8_t                flags;                /* 66 immunities */
    uint8_t                __unknown_67[1];    /* 67 */
    BYTE deleted2[12];    /* 68 */

    float                spin[3];            /* 80 */
    float                speed_rammed[3];    /* 92 */
    float                spin_rammed[3];        /* 104 */
    uint8_t                __unknown_116[60];    /* 116 */
    void                *__unknown_176;        /* 176 - pointer to a "entry node info" pool item */
    void                *__unknown_180;        /* 180 - pointer to a "ptr node Double" pool item */

                                            //collision data
    DWORD                collision_flags;    /* 184 - 2nd byte = currently colliding 1/0, or actively
                                            running against (0x2), 3rd byte = type colliding with
                                            (1 = road, 4=pavement, 35 = object, 3f=car).. unsure about 3rd byte

                                            nuck notes: 186 is used to tell if a surface is "steep" too,
                                            actually any slight angle at all
                                            */
    void                *last_touched_object;    /* 188 - You can touch roads - those are considered buildings */
    void                *last_collided_object;    /* 192 - pointer to object last collided with (on foot, not jetpack) */
    uint8_t                __unknown_196[16];        /* 196 */
    float                speed;            /* 212 */
    float                collision_time_216; /* 216 - collision timer? */
    void                *collision_current_obj;        /* 220 - pointer to current thing colliding with */
    uint8_t                collision_something[12];    /* 224 - related to collision */
    float                collision_last_coord[3];    /* 236 - coordination of last collision */

                                                    //end of collision data
    uint8_t                __unknown_248[100];            /* 248 */
                                                    // 252 - animation related
    uint8_t                animation_state;            /* 348 */
    uint8_t                __unknown_349[7];            /* 349 */
    float                step_pos[3];        /* 356 - coordinates, last foot step */
    float                step_pos_before[3]; /* 368 - coordinates, foot step before last one */
    uint8_t                __unknown_380[752]; /* 380 */

    BYTE deleted3[16];            /* 1132 */
                                //1148 - animations base
    struct animation_base *animBase;
    BYTE deleted10[4];

    uint8_t                __unknown_1156[8]; /* 1156 */

                                           // relative body-part-positions
    void                *pNeck;                /* 1164 - void* pNeck
                                            (pChest?)
                                            - 4 unknown
                                            - float height
                                            - float front/back
                                            - float left/right
                                            - void* pObject
                                            (same struct for the following body-part-pointers [except pLeft/RightArm])
                                            */
    void                *pHead;                /* 1168 */
    void                *pLeftArm;            /* 1172 */
    void                *pRightArm;            /* 1176 */
    void                *pLeftLowArm;        /* 1180 */
    void                *pRightLowArm;        /* 1184 */
    void                *pLeftLeg;            /* 1188 */
    void                *pRightLeg;            /* 1192 */
    void                *pLeftLowLeg;        /* 1196 */
    void                *pRightLowLeg;        /* 1200 */
    void                *pRightMidLeg;        /* 1204 */
    void                *pLeftMidLeg;        /* 1208 */
    void                *pLeftMidArm;        /* 1212 */
    void                *pRightMidArm;        /* 1216 */
    void                *pLeftShoulder;        /* 1220 */
    void                *pRightShoulder;    /* 1224 */
    void                *pChest;            /* 1228 */
    void                *pMouth;            /* 1232 */
                                            // end of body-part-positions

    uint8_t                runningStyle;        /* 1236 - 0x36 = cj, 0x8A = rollerskate,
                                            0x7F = woozie, 0x75 = crash.. etc. */
    uint8_t                __unknown_1237[7];    /* 1237 */
    float                runspeed;            /* 1244 */
    uint8_t                __unknown_1248[36]; /* 1248 */
    uint16_t            muzzle_flash;        /* 1284 */
    uint8_t                __unknown_1286[6];    /* 1286 */

    BYTE deleted4[32];    /* 1292 - Inverse Kinematics */
    uint8_t                __unknown_1324[4];    /* 1324 */

    uint32_t            actorState;    /* 1328 - ACTOR_STATE_* */
    uint32_t            runState; /* 1332 - ACTOR_MSTATE_* */
    uint8_t                __unknown_1336[8];    /* 1336 */
    float                hitpoints;            /* 1344 */
    float                hitpoints_max;        /* 1348 - hmm, does not seem to be right.. it's set to "100.1318519" or something like that */
    float                armor;    /* 1352 */
    uint8_t                __unknown_1356[12];        /* 1356 */

                                                // 1360 and 1364 are using in resetting on-foot position when re-standing up

    float                fCurrentRotation;        /* 1368 */
    float                fTargetRotation;        /* 1372 */
    float                fRotationSpeed;            /* 1376 */
    float                fRotationCalculation;    /* 1380 - is 0.1 when target rotation reached */

    union
    {
        BYTE deleted5[4];    /* 1384 - touching a CEntitySAInterface */
        struct vehicle_info *vehicle_contact;    /* 1384 - standing on top of vehicle */
    };

    float    vehicle_contact_dist[3];            /* 1388 - distance to the middle of the car standing on */
    float    fPlaneAnglesContactEntity[3];        /* 1400 - Angles of the plane of the contact entity the actor is
                                                standing on (?) */
    void    *item_contact;                        /* 1412 - standing on top of vehicle/object/building/...*/
    float    fUnknown_1416;                        /* 1416 - only changing when slightly under map */

    union
    {
        //CEntitySAInterface    *CurrentObjective;    /* 1420 - usually current vehicle's entity */
        DWORD vehicleDw;
        struct vehicle_info *vehicle;
    };

    uint8_t                __unknown_1424[8];    /* 1424 */
    uint8_t                actor_lock;            /* 1432 */
    uint8_t                __unknown_1433[7];    /* 1433 */
    BYTE deleted6[364];            /* 1440 */
    uint8_t                __unknown_1804[12]; /* 1804 */
    uint8_t                weapon_slot;        /* 1816 */
    uint8_t                __unknown_1817[3];    /* 1817 */
    void                *ptr_autoAimTarget;    /* 1820 - weapon target */
    float                fImpactPos_close[3];/* 1824 - last impact point of close range weapon [fist/knife/csaw/etc.] */
    uint8_t                __unknown_1836[20]; /* 1836 */
    uint32_t            weapon_model;        /* 1856 */
    uint8_t                __unknown_1860[28]; /* 1860 */
    uint32_t            weapon_hit_type;    /* 1888 - last hit by this weapon */
    struct actor_info    *weapon_hit_by;        /* 1892 - last hit by this object (usually an actor) */
    uint8_t                __unknown_1889[92]; /* 1896 */
};    /* 1988 */


int main()
{
    cout << "Looking for GTA:SA:MP window." << endl;
    // MA VARIABLES
    DWORD pId;
    DWORD dwOldProtect = 0;
    HANDLE pHandle;
    HWND hWnd = 0;

    float zero = 0.0;
    while (hWnd == 0) {
        hWnd = FindWindow(0, "GTA:SA:MP");
        Sleep(100);
    }
    cout << "Just found the window." << endl;

    GetWindowThreadProcessId(hWnd, &pId);
    pHandle = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION, TRUE, pId);

    
    DWORD pedPoolUsageInfo;
    DWORD pedPoolBegining;
    DWORD byteMapAddr;
    BYTE activityStatus; //bytemap check
    actor_info actor; // a.k.a "CPed" or ClassPedestrian?
    float hp;
    float armor;
    while (true) 
    {
        ReadProcessMemory(pHandle, (LPCVOID)0xB74490, &pedPoolUsageInfo, 4, 0);
        ReadProcessMemory(pHandle, (LPCVOID)(pedPoolUsageInfo), &pedPoolBegining, 4, 0);
        ReadProcessMemory(pHandle, (LPCVOID)(pedPoolUsageInfo +4), &byteMapAddr, 4, 0);
        
        for (BYTE i = 0; i < 140; i++)
        {
            ReadProcessMemory(pHandle, (LPCVOID)(byteMapAddr + i), &activityStatus, 1, 0);
            if (activityStatus > 0 && activityStatus < 128)
            {
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988), &actor, 1988, 0);
                cout << "ID(memory): " << (int)i << ", Speed: " << actor.speed << ", HP: " << actor.hitpoints << ", Armor: " << actor.armor << endl;

                //or instead of reading the whole 1988 bytes at once (which is slow) ignore the actor_struct and "manually" read all the data like:
                /*
                
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988 + 1344), &hp, 4, 0); //1344 is offset for hp
                ReadProcessMemory(pHandle, (LPCVOID)(pedPoolBegining + i * 1988 + 1352), &armor, 4, 0); //1352 is offset for armor
                cout << "ID(memory): " << (int)i << ", HP: " << hp << ", Armor: " << armor << endl;
                
                */

                Sleep(500); // just to check whether the example works without spamming too much
            }
        }        
    }
    CloseHandle(pHandle);
    return 0;
}

Just tested it and it worked, with samp in windowed mode so the output is visible. The whole actor_struct allows to use a simple:
actor.armor
But it reads the whole 1988 which is slow, idk if there's a way to efficiently and easily access memory without injecting the mod to the process.
So there's also commented out part in the main function which simply reads the required 4 bytes, takes more hassle to write but works faster. If you use the commented out part then you could just delete the big actor_info struct
Thx, it's work.
 

AR3S

Active member
Joined
Apr 7, 2016
Messages
41
Reaction score
0
user88 said:
This is the problem if cleo coders goto c++
No prepared functions?
(Oh, fuck no functions to cp)

Its really that simple to read out that shit
Gtamodding is self explained

Btw why use the pedpool instead of patternscan of samp structures?
And forget the playing with pointers, u can cut yourself into Ya foot

(way way better to read cped pool structure instead of samps one tho)
 
Top