It’s the same thing depending on what you’re trying to use it for.
void flWheelTransform = *(void *)((uint64_t)instance + 0x18);
And use 0x1490744 (the update you have)
#include <iostream> // for debugging
#include <Windows.h>
#include "MinHook.h" // Assuming you're using MinHook
// Function pointer to the original Update method
typedef void(__thiscall* UpdateFunc)(void* instance);
UpdateFunc OriginalUpdate;
// Typedef for Vector3, if you don't have a Vector3 struct/class elsewhere
struct Vector3
{
float x, y, z;
};
// Custom structure for the CutsceneVehicleRig class
struct CutsceneVehicleRig
{
// ... Other members ...
Transform* wheelFL; //0x18
Transform* wheelRL; // 0x20
Transform* wheelFR; // 0x28
Transform* wheelRR; // 0x30
Transform* carBody; // 0x38
float weight; // 0x40
float groundHeight; // 0x44
bool AnimateWheelRotation; // 0x48
int PivotPos; // 0x4C
Quaternion oldDirection; // 0x50
Vector3 oldPosition; // 0x60
float wheelSpin; // 0x6C
float rotates; // 0x70
float speed; // 0x84
bool stopped; // 0x88
Vector3 oldBodyPos; // 0x8C
Vector3 oldWheelFLPos; // 0x98
Vector3 oldWheelFRPos; // 0xA4
Vector3 oldWheelRLPos; // 0xB0
Vector3 oldWheelRRPos; // 0xBC
};
// Our custom Transform class
class Transform {
public:
float x, y, z; // Position
float rx, ry, rz, rw; // rotation
Vector3 GetPosition() { return {x,y,z}; }
Quaternion GetRotation() { return {rx,ry,rz,rw}; }
void SetPosition(float x1, float y1, float z1) {x=x1; y=y1; z=z1;}
};
// Hook function
void __fastcall MyUpdateHook(CutsceneVehicleRig* instance)
{
if (instance) {
Transform* flTransform = instance->wheelFL;
Transform* frTransform = instance->wheelFR;
// Read the old positions
Vector3 oldFlPos = instance->oldWheelFLPos;
Vector3 oldFrPos = instance->oldWheelFRPos;
// Do what you wish here
if (flTransform) {
float x = flTransform->GetPosition().x;
float y = flTransform->GetPosition().y;
float z = flTransform->GetPosition().z;
flTransform->SetPosition(x + 1.0f, y, z);
std::cout << "Old FL Position: x: " << oldFlPos.x << ", y: " << oldFlPos.y << ", z: " << oldFlPos.z << std::endl;
std::cout << "New FL Position: x: " << x + 1.0f << ", y: " << y << ", z: " << z << std::endl;
}
if (frTransform) {
float x = frTransform->GetPosition().x;
float y = frTransform->GetPosition().y;
float z = frTransform->GetPosition().z;
frTransform->SetPosition(x, y, z + 1.0f);
std::cout << "Old FR Position: x: " << oldFrPos.x << ", y: " << oldFrPos.y << ", z: " << oldFrPos.z << std::endl;
std::cout << "New FR Position: x: " << x << ", y: " << y << ", z: " << z + 1.0f << std::endl;
}
}
// Call the original method to make sure the game logic continues
OriginalUpdate(instance);
}
bool HookFunction(uintptr_t target, void* detour, void** original) {
if (MH_CreateHook((LPVOID)target, detour, original) != MH_OK) {
return false;
}
return MH_EnableHook((LPVOID)target) == MH_OK;
}
bool UnhookFunction(uintptr_t target) {
return MH_DisableHook((LPVOID)target) == MH_OK;
}
// In your DLL main or similar initialization code:
bool InitializeHook()
{
if (MH_Initialize() != MH_OK)
{
// Failed to initialize minhook.
return false;
}
// Replace with the actual address of the Update method. From your
// question you have the RVA which is relative to the base image of the module
// you're looking at. So convert this to a virtual address.
uintptr_t updateFunctionAddress = (uintptr_t)GetModuleHandle(NULL) + 0x1490744; // Get the base address of the program and add the RVA of the function.
if (!HookFunction(updateFunctionAddress, &MyUpdateHook, (void**)&OriginalUpdate)) {
std::cerr << "Failed to create hook.\n";
MH_Uninitialize();
return false;
}
// Successfully hooked.
return true;
}
void UninitializeHook() {
// Unhook
uintptr_t updateFunctionAddress = (uintptr_t)GetModuleHandle(NULL) + 0x1490744;
if (UnhookFunction(updateFunctionAddress) == MH_OK) {
std::cout << "Unhooked successfully.\n";
}
else {
std::cerr << "Failed to unhook.\n";
}
MH_Uninitialize();
}