Skip to content

Instantly share code, notes, and snippets.

@ikt32
Last active June 9, 2017 19:04
Show Gist options
  • Save ikt32/34de76a478b37b8194056df91c37bdab to your computer and use it in GitHub Desktop.
Save ikt32/34de76a478b37b8194056df91c37bdab to your computer and use it in GitHub Desktop.
Accessing wheel data in ScriptHookVDotNet
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
using GTA.Math;
using GTA.Native;
namespace GTA.examples
{
public class WheelData : Script
{
public WheelData()
{
Tick += OnTick;
}
void OnTick(object sender, EventArgs e)
{
Ped player = Game.Player.Character;
if (!player.IsInVehicle())
{
return;
}
Vehicle vehicle = player.CurrentVehicle;
ShowWheelInfo(vehicle);
}
void ShowText(float x, float y, string text, float size = 0.2f)
{
Function.Call(Hash.SET_TEXT_FONT, 0);
Function.Call(Hash.SET_TEXT_SCALE, size, size);
Function.Call(Hash.SET_TEXT_COLOUR, 255, 255, 255, 255);
Function.Call(Hash.SET_TEXT_WRAP, 0.0, 1.0);
Function.Call(Hash.SET_TEXT_CENTRE, 0);
Function.Call(Hash.SET_TEXT_OUTLINE, true);
Function.Call(Hash._SET_TEXT_ENTRY, "STRING");
Function.Call(Hash._ADD_TEXT_COMPONENT_STRING, text);
Function.Call(Hash._DRAW_TEXT, x, y);
}
void ShowText3D(Vector3 location, List<string> textLines)
{
OutputArgument ox = new OutputArgument();
OutputArgument oy = new OutputArgument();
bool success = Function.Call<bool>(Hash._WORLD3D_TO_SCREEN2D, location.X, location.Y, location.Z, ox, oy);
float x = ox.GetResult<float>();
float y = oy.GetResult<float>();
if (success)
{
int i = 0;
foreach (var line in textLines)
{
ShowText(x, y + 0.0125f * i, line);
i++;
}
float szX = 0.060f;
float szY = 0.0125f * i;
Function.Call(Hash.DRAW_RECT, x + 0.027f, y + (0.0125f * i) / 2.0f, szX, szY, 75, 75, 75, 75);
}
}
unsafe ulong GetWheelsPtr(Vehicle handle)
{
var address = (ulong)handle.MemoryAddress;
ulong offset = 0xB10;
return *((ulong*)(address + offset));
}
unsafe int GetNumWheels(Vehicle handle)
{
var address = (ulong)handle.MemoryAddress;
ulong offset = 0xB10;
offset += 8;
return *((int*)(address + offset));
}
unsafe List<ulong> GetWheelPtrs(Vehicle handle)
{
var wheelPtr = GetWheelsPtr(handle); // pointer to wheel pointers
var numWheels = GetNumWheels(handle);
List<ulong> wheelPtrs = new List<ulong>();
for (int i = 0; i < numWheels; i++)
{
var wheelAddr = *((ulong*)(wheelPtr + 0x008 * (ulong)i));
wheelPtrs.Add(wheelAddr);
}
return wheelPtrs;
}
unsafe List<float> GetWheelsSpeed(Vehicle handle)
{
List<ulong> wheelPtrs = GetWheelPtrs(handle);
ulong offset = 0x168;
List<float> speeds = new List<float>();
foreach (var wheel in wheelPtrs)
{
speeds.Add(-*((float*)(wheel + offset)));
}
return speeds;
}
unsafe void ShowWheelInfo(Vehicle vehicle)
{
var wheels = GetWheelPtrs(vehicle);
var wheelsSpeed = GetWheelsSpeed(vehicle);
//var wheelsCompr = GetWheelsCompression(vehicle);
//var wheelsHealt = GetWheelsHealth(vehicle);
int i = 0;
foreach (var wheelAddr in wheels)
{
// 20, 30: offset from body?
// 40, 50: last position on ground?
// 60 - current position? seems to be 0,0,0 when contact is lost
// B0 - world velocity
// C0 - Same, but flipped?
// 168 - rotation speed rad/s
// 16C - slippage y-dir?
// 170 - heating
// materials.dat related
// 190 - surface related: tyre grip
// 194 - surface related: wet grip
// 198 - surface related: tyre drag
// 19C - surface related: top speed mult
// 1C4 - steering angle
// 1C8/1D4 - Brake
// 1CC/1D8 - Throttle/powered
// 1E0/1E4 - Health
// 1EC / (flags?) - Powered states
// ulong offPosX = 0x40;
// ulong offPosY = 0x44;
// ulong offPosZ = 0x48;
ulong offPosX = 0x40;
ulong offPosY = 0x44;
ulong offPosZ = 0x48;
ulong offRadius = 0x110; // offWheelSzX
ulong offWheelSzY = 0x114; // not sure at all!
ulong offWheelSzZ = 0x118;
float radius = *((float*)(wheelAddr + offRadius));
float szY = *((float*)(wheelAddr + offWheelSzY));
float szZ = *((float*)(wheelAddr + offWheelSzZ));
Vector3 wheelPos;
wheelPos.X = *((float*)(wheelAddr + offPosX));
wheelPos.Y = *((float*)(wheelAddr + offPosY));
wheelPos.Z = *((float*)(wheelAddr + offPosZ));
float wheelSpeed = wheelsSpeed[i];
//float wheelCompr = wheelsCompr.at(i);
//float wheelHealt = wheelsHealt.at(i);
List<string> lines = new List<string>
{
"Speed: " + wheelSpeed * radius,
"Rad/s: " + wheelSpeed,
"Radius: " + radius,
//"Dummy0",
//"Dummy1",
};
ShowText3D(wheelPos, lines);
// int j = 0;
// float baseX = 0.45f;
// float baseY = 0.20f;
// float distX = 0.125f;
// float distY = 0.02f;
// float fntSz = 0.40f;
// ShowText(baseX + distX * i, baseY + distY * j, "WhlRot: " + wheelSpeed, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "WhlSpd: " + wheelSpeed * radius, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "PhyVel: " + vehicle.Speed, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "DshSpd: " + vehicle.WheelSpeed, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "Phy/Whl: " + vehicle.Speed/wheelSpeed, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "Dsh/Whl: " + vehicle.WheelSpeed/wheelSpeed, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "TireRad: " + radius, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "RimRad: " + szY, fntSz);
// j++;
// ShowText(baseX + distX * i, baseY + distY * j, "Width: " + szZ, fntSz);
i++;
}
//ShowText(0.4f, 0.4f, "Veh : " + ((ulong)vehicle.MemoryAddress).ToString("x"));
//ShowText(0.4f, 0.4125f, "Whls: " + GetWheelsPtr(vehicle).ToString("x"));
//ShowText(0.4f, 0.4250f, "nWhl: " + wheels.Count);
//ShowText(0.4f, 0.4325f, "nWhl: " + GetNumWheels(vehicle));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment