Last active
August 16, 2022 09:40
-
-
Save ikt32/466c59df7aff69d2ac788fa38e669300 to your computer and use it in GitHub Desktop.
Get unsafe struct from GTA Native function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using GTA; | |
using GTA.Native; | |
// shvdn2 | |
public static class SHVNative | |
{ | |
// These are borrowed from ScriptHookVDotNet's | |
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeInit@@YAX_K@Z")] | |
static extern void NativeInit(ulong hash); | |
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativePush64@@YAX_K@Z")] | |
static extern void NativePush64(ulong val); | |
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeCall@@YAPEA_KXZ")] | |
static extern unsafe ulong* NativeCall(); | |
// These are from ScriptHookV's nativeCaller.h | |
static unsafe void nativePush<T>(T val) where T: unmanaged | |
{ | |
ulong val64 = 0; | |
*(T*)(&val64) = val; | |
NativePush64(val64); | |
} | |
public static unsafe R invoke<R>(ulong hash) where R : unmanaged | |
{ | |
NativeInit(hash); | |
return *(R*)(NativeCall()); | |
} | |
// Apparently this works, but might be less efficient than C++'s variadic things | |
public static unsafe R invoke<R>(ulong hash, params dynamic[] args) | |
where R : unmanaged | |
{ | |
NativeInit(hash); | |
foreach(var arg in args) | |
nativePush(arg); | |
return *(R*)(NativeCall()); | |
} | |
} | |
public class HeadBlendDataTest : Script | |
{ | |
[StructLayout(LayoutKind.Explicit, Size = 80)] | |
public struct HeadBlendData | |
{ | |
[FieldOffset(0)] | |
public int ShapeFirst; | |
[FieldOffset(8)] | |
public int ShapeSecond; | |
[FieldOffset(16)] | |
public int ShapeThird; | |
[FieldOffset(24)] | |
public int SkinFirst; | |
[FieldOffset(32)] | |
public int SkinSecond; | |
[FieldOffset(40)] | |
public int SkinThird; | |
[FieldOffset(48)] | |
public float ShapeMix; | |
[FieldOffset(56)] | |
public float SkinMix; | |
[FieldOffset(64)] | |
public float ThirdMix; | |
} | |
public HeadBlendDataTest() | |
{ | |
Tick += OnTick; | |
lastPed = Game.Player.Character; | |
} | |
private Ped lastPed; | |
void OnTick(object sender, EventArgs e) | |
{ | |
// just a sanity check for invoke | |
ShowText(0.5f, 0.00f, SHVNative.invoke<int>((ulong)Hash.GET_GAME_TIMER).ToString()); | |
Ped playerPed = Game.Player.Character; | |
if (playerPed != lastPed) | |
{ | |
Function.Call(Hash.SET_PED_HEAD_BLEND_DATA, playerPed, 1, 2, 3, 4, 5, 6, 1.0f, 2.0f, 3.0f); | |
} | |
var hbd = GetHeadBlendData(playerPed); | |
ShowText(0.5f, 0.250f, hbd.ShapeFirst.ToString()); | |
ShowText(0.5f, 0.275f, hbd.ShapeSecond.ToString()); | |
ShowText(0.5f, 0.300f, hbd.ShapeThird.ToString()); | |
ShowText(0.5f, 0.325f, hbd.SkinFirst.ToString()); | |
ShowText(0.5f, 0.350f, hbd.SkinSecond.ToString()); | |
ShowText(0.5f, 0.375f, hbd.SkinThird.ToString()); | |
ShowText(0.5f, 0.400f, hbd.ShapeMix.ToString()); | |
ShowText(0.5f, 0.425f, hbd.SkinMix.ToString()); | |
ShowText(0.5f, 0.450f, hbd.ThirdMix.ToString()); | |
} | |
public unsafe HeadBlendData GetHeadBlendData(Ped ped) | |
{ | |
HeadBlendData hbd = new HeadBlendData() {ShapeFirst = -1}; | |
HeadBlendData* pHbd = &hbd; | |
bool result = SHVNative.invoke<bool>((ulong)Hash._GET_PED_HEAD_BLEND_DATA, ped.Handle, (IntPtr)pHbd); | |
// result handling might be useful | |
return *pHbd; | |
} | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment