- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 805
- Reaction score
- 457
Bypassing the headache of CR3 fixes for external projects is always a win, especially when dealing with the mess that is modern Frostbite titles. This method focuses on iterating through soldier and vehicle entities without the usual performance overhead or complex memory mapping usually required for external reads in these environments.
The Logic
Working with the GlobalNativeTypeRegistry allows you to pull the first entity by its Class ID directly. From there, you just walk the list using the NextEntity offset. This approach is versatile—while I originally mapped this out for explosives ESP (claymores/mines), it scales perfectly for bullets, grenades, and even rare loot entities.
Technical Meat (Offsets & Signatures)
These targets were pulled from the Steam build. If the game updates, you'll need to re-sig the class constructors to find the updated vftables.
Implementation
The core routine iterates through the ClientGameWorld. It checks the ClassId and runs a subclass check if you're looking for derived entities. It's a clean way to populate your local entity cache for an ESP or a triggerbot without having to brute-force memory or rely on fragile pointers.
Operational Notes
This logic is reminiscent of the classic BF4 iteration techniques but adapted for the modern engine quirks found in recent Battlefield releases. If you're building a loot or vehicle-specific radar, this is the most stable path forward.
Curious if anyone has attempted to port this for the latest build's Hazard Zone entities specifically.
The Logic
Working with the GlobalNativeTypeRegistry allows you to pull the first entity by its Class ID directly. From there, you just walk the list using the NextEntity offset. This approach is versatile—while I originally mapped this out for explosives ESP (claymores/mines), it scales perfectly for bullets, grenades, and even rare loot entities.
Technical Meat (Offsets & Signatures)
These targets were pulled from the Steam build. If the game updates, you'll need to re-sig the class constructors to find the updated vftables.
Code:
// Virtual function 0 of almost every entity is GetTypeInfo()
#define OFFSET_ClientSoldierEntity__TypeInfo 0x149CB8D60
#define OFFSET_ClientVehicleEntity__TypeInfo 0x149B204F0
#define OFFSET_ClientLootItemEntity__TypeInfo 0x149B45740
#define OFFSET_ClientExplosionPackEntity__TypeInfo 0x149C3B9E0
// Member offsets
#define OFFSET_ClientSoldierEntity_NextEntity 0x98
#define OFFSET_ClientVehicleEntity_NextEntity 0x98
// Registry & World Offsets
#define OFFSET_GlobalNativeTypeRegistry 0x149409A88
#define OFFSET_GlobalNativeTypeRegistry_Array 0x68
#define OFFSET_UnknownIndex 0x149552958
#define OFFSET_ClientGameWorld 0x149A3FD90
#define OFFSET_ClassId 0x38
#define OFFSET_LastSubClassId 0x3A
Implementation
The core routine iterates through the ClientGameWorld. It checks the ClassId and runs a subclass check if you're looking for derived entities. It's a clean way to populate your local entity cache for an ESP or a triggerbot without having to brute-force memory or rely on fragile pointers.
Code:
__int64 GetFirstEntityByClassId(__int16 _ClassId, __int64 _ClientGameWorld_field_10)
{
__int64 pGlobalNativeTypeRegistry = ReadT<__int64>(OFFSET_GlobalNativeTypeRegistry);
__int64 v1 = ReadT<__int64>(ReadT<__int64>(pGlobalNativeTypeRegistry + OFFSET_GlobalNativeTypeRegistry_Array) + 8LL * ((__int64)_ClassId - 1));
unsigned int UnknownIndex = ReadT<unsigned int>(OFFSET_UnknownIndex);
__int64 v2 = 16LL * ReadT<unsigned int>(UnknownIndex + ReadT<__int64>(_ClientGameWorld_field_10 + OFFSET_ClientGameWorld_field_10_Index));
return ReadT<__int64>(v1 + v2 + 0x78);
}
void TestClientGameWorld(__int64 _TypeInfo, __int64 _Offset, void(*_Callback)(__int64 _Entity), bool _CheckSubClass)
{
__int64 pClientGameWorld = ReadT<__int64>(OFFSET_ClientGameWorld);
if (!pClientGameWorld) return;
__int16 Entity__ClassId = ReadT<__int16>(_TypeInfo + OFFSET_ClassId);
__int16 Entity__LastSubClassId = ReadT<__int16>(_TypeInfo + OFFSET_LastSubClassId);
__int64 AddressOf_NextEntity = GetFirstEntityByClassId(Entity__ClassId, pClientGameWorld + 0x10);
while (AddressOf_NextEntity)
{
__int64 pEntity = AddressOf_NextEntity - _Offset;
_Callback(pEntity);
AddressOf_NextEntity = ReadT<__int64>(AddressOf_NextEntity);
}
}
Operational Notes
- External read performance: Ensure you are using a fast RPM method (kernel driver or specialized DMA) to avoid stuttering when the entity count spikes in full servers.
- Subclass Checking: For Soldiers, keeping _CheckSubClass as true ensures you don't miss specialized classes, though it slightly increases the iteration time.
- Detection: Standard external rules apply. Hide your overlay and ensure your handle/driver isn't flagged. This method doesn't touch the game code, making it safer than internal shells.
Code:
[+] _Entity->0x2F1F27E90 | ClientSoldierEntity
[+] _Entity->0x27D606270 | ClientSoldierEntity
[+] _Entity->0x2D343D490 | ClientVehicleEntity
[+] _Entity->0x359683BA0 | ClientVehicleEntity
This logic is reminiscent of the classic BF4 iteration techniques but adapted for the modern engine quirks found in recent Battlefield releases. If you're building a loot or vehicle-specific radar, this is the most stable path forward.
Curious if anyone has attempted to port this for the latest build's Hazard Zone entities specifically.