Replacing CHandlingData of a helicopter with scripts
-
Hi people, I'm having a problem with a little project I'm working on. Many of you probably saw me spamming the Discord with weird stuff, but I wanted to make a thread here to ask for help and post what I got so far.
Basically, I want to remove the autocentering for helicopters, but only affecting the player's vehicle, because AI acts weirdly without that centering. To accomplish that, I need to set "fAttackLiftMult" and "fAttackDiveMult" to zero. Since there's only one instance of CHandlingData in memory for each vehicle model, If I modify one, it will affect the others, so I have to copy it and replace the pointer from the vehicle to the new data block. In theory, that should work.
To get the address of the CHandlingData used by my current vehicle, I use this code snippet I took from "Driving Modes", by Stillhere (I hope he doesn't mind ):
public Class() { MemoryAccess.Pattern pattern = new MemoryAccess.Pattern("<\u0003\u000f\u0085\0\0\0\0H\u008bA H\u008b\u0088", "xxxx????xxxxxxx"); pattern.Init(); unsafe { _hOffset = *(int*)(pattern.Get(0).ToInt64() + 22L); } } private unsafe static float GetHandlingValue(int exactOffset) { float* ptr = (float*) (((long*)Game.Player.Character.CurrentVehicle.MemoryAddress)[(ulong)_hOffset / 8UL] + (long)((ulong)exactOffset)); return *ptr; } private unsafe static void SetHandlingValue(int exactOffset, float currentValue) { Process[] processesByName = Process.GetProcessesByName("GTA5"); if (processesByName.Length != 0) { using (Memory memory = new Memory(processesByName[0])) { IntPtr address = (IntPtr)(((long*)Game.Player.Character.CurrentVehicle.MemoryAddress)[(ulong)_hOffset / 8UL] + (long)((ulong)exactOffset)); memory.WriteFloat(address, currentValue); } } }
I'm not really sure how that works, but it works. It allows me to get and set handling values directly from memory.
The CHandlingData structure seems to have a size of 816 bytes for ground vehicles. However, helicopters have an extra "CFlyingHandlingData", so it's handling block is bigger. After some debugging I found the last byte before the next CHandlingData entry is 2443.
The values I need are stored at offset 888 and 892. If I do "SetHandlingValue" with those two offsets to 0, my helicopter stops centering itself, but it also affects all the other helis of the same type. I need to copy the handling data, so I do this:byte* target = (byte*)Marshal.AllocHGlobal(2444).ToPointer(); byte* source = (byte*)((long*)Game.Player.Character.CurrentVehicle.MemoryAddress)[(ulong)_hOffset / 8UL]; for (int i = 0; i < 2444; i++) { target[i] = source[i]; }
After that, target and source point to identical blocks of data, now I change the pointer from my current vehicle to the new CHandlingData:
((long*)Game.Player.Character.CurrentVehicle.MemoryAddress)[(ulong)_hOffset / 8UL] = (long)target;
Everything should be working fine, but it isn't.
I tried doing this with a BANSHEE, changing it's brake force to 0. After that, the vehicle I was driving lost it's ability to brake, but if I got in another Banshee, it could brake normally, so it was working correctly.
However, if I try to do this with a Helicopter, and I modify a value from CFlyingHandlingData, the helicopter still uses the variables from the OLD CHandlingData, not my copy.My guess is that something, somewhere, is still pointing to the old CFlyingHandlingData, and I need to replace that pointer too. However, I couldn't find any address that could fit inside the CHandlingData block, and I searched for it in CurrentVehicle, the old CHandlingData and also the vehicle model addresses. Nothing works, I don't know what's going on. Any ideas?