Read quaternion and rotation directly from memory

This commit is contained in:
Sardelka
2022-07-25 19:07:58 +08:00
parent e072c2aee8
commit cc52f66f5d
7 changed files with 173 additions and 5 deletions

View File

@ -32,7 +32,7 @@ namespace RageCoop.Client
ID =c.ID,
OwnerID=c.OwnerID,
Health = p.Health,
Rotation = p.Rotation,
Rotation = p.ReadRotation(),
Velocity = p.Velocity,
Speed = p.GetPedSpeed(),
CurrentWeaponHash = (uint)p.Weapons.Current.Hash,
@ -91,7 +91,7 @@ namespace RageCoop.Client
Flags = veh.GetVehicleFlags(),
SteeringAngle = veh.SteeringAngle,
Position = veh.PredictPosition(),
Quaternion=veh.Quaternion,
Quaternion=veh.ReadQuaternion(),
Velocity = veh.Velocity,
RotationVelocity=veh.RotationVelocity,
ThrottlePower = veh.ThrottlePower,

View File

@ -57,6 +57,7 @@
<Compile Include="Sync\SyncEvents.cs" />
<Compile Include="Sync\SyncParameters.cs" />
<Compile Include="Util\Memory.cs" />
<Compile Include="Util\NativeCaller.cs" />
<Compile Include="Util\PedConfigFlags.cs" />
<Compile Include="Util\PedExtensions.cs" />
<Compile Include="Util\TaskType.cs" />
@ -83,6 +84,7 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\libs\Lidgren.Network.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>

View File

@ -361,7 +361,7 @@ namespace RageCoop.Client
model.Request(1000);
if (model != null)
{
ParachuteProp = World.CreateProp(model, MainPed.ReadPosition(), MainPed.Rotation, false, false);
ParachuteProp = World.CreateProp(model, MainPed.ReadPosition(), MainPed.ReadRotation(), false, false);
model.MarkAsNoLongerNeeded();
ParachuteProp.IsPositionFrozen = true;
ParachuteProp.IsCollisionEnabled = false;

View File

@ -356,7 +356,7 @@ namespace RageCoop.Client
MainVehicle.Velocity = Velocity+5*(predicted - current);
if (IsFlipped)
{
MainVehicle.Quaternion=Quaternion.Slerp(MainVehicle.Quaternion, Quaternion, 0.5f);
MainVehicle.Quaternion=Quaternion.Slerp(MainVehicle.ReadQuaternion(), Quaternion, 0.5f);
MainVehicle.RotationVelocity=RotationVelocity;
}
else
@ -383,7 +383,7 @@ namespace RageCoop.Client
private Vector3 GetCalibrationRotation()
{
var rot = Quaternion.LookRotation(Quaternion*Vector3.RelativeFront, Quaternion*Vector3.RelativeTop).ToEulerAngles();
var curRot = Quaternion.LookRotation(MainVehicle.Quaternion*Vector3.RelativeFront, MainVehicle.Quaternion*Vector3.RelativeTop).ToEulerAngles();
var curRot = Quaternion.LookRotation(MainVehicle.ReadQuaternion()*Vector3.RelativeFront, MainVehicle.ReadQuaternion()*Vector3.RelativeTop).ToEulerAngles();
var r = (rot-curRot).ToDegree();
if (r.X>180) { r.X=r.X-360; }

View File

@ -5,6 +5,8 @@ using System.Text;
using System.Threading.Tasks;
using GTA.Math;
using GTA;
using SHVDN;
using RageCoop.Core;
namespace RageCoop.Client
{
@ -17,6 +19,14 @@ namespace RageCoop.Client
{
return ReadVector3(e.MemoryAddress+PositionOffset);
}
public static Quaternion ReadQuaternion(this Entity e)
{
return Quaternion.RotationMatrix(e.Matrix);
}
public static Vector3 ReadRotation(this Entity e)
{
return e.ReadQuaternion().ToEulerDegrees();
}
public unsafe static Vector3 ReadVector3(IntPtr address)
{
float* ptr = (float*)address.ToPointer();

View File

@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
using GTA.Native;
using GTA.Math;
using System.Runtime.InteropServices;
using LemonUI.Elements;
using System.Drawing;
namespace RageCoop.Client
{
[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;
}
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct NativeVector3
{
[FieldOffset(0)]
public float X;
[FieldOffset(8)]
public float Y;
[FieldOffset(16)]
public float Z;
public static implicit operator Vector3(NativeVector3 vec)
{
return new Vector3() { X=vec.X, Y=vec.Y, Z=vec.Z };
}
public static implicit operator NativeVector3(Vector3 vec)
{
return new NativeVector3() { X=vec.X, Y=vec.Y, Z=vec.Z };
}
}
public static class NativeCaller
{
// 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());
}
public static unsafe R Invoke<R>(Hash hash, params object[] args)
where R : unmanaged
{
NativeInit((ulong)hash);
var arguments=ConvertPrimitiveArguments(args);
foreach (var arg in arguments)
NativePush(arg);
return *(R*)(NativeCall());
}
/// <summary>
/// Helper function that converts an array of primitive values to a native stack.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static unsafe ulong[] ConvertPrimitiveArguments(object[] args)
{
var result = new ulong[args.Length];
for (int i = 0; i < args.Length; ++i)
{
if (args[i] is bool valueBool)
{
result[i] = valueBool ? 1ul : 0ul;
continue;
}
if (args[i] is byte valueByte)
{
result[i] = (ulong)valueByte;
continue;
}
if (args[i] is int valueInt32)
{
result[i] = (ulong)valueInt32;
continue;
}
if (args[i] is ulong valueUInt64)
{
result[i] = valueUInt64;
continue;
}
if (args[i] is float valueFloat)
{
result[i] = *(ulong*)&valueFloat;
continue;
}
if (args[i] is IntPtr valueIntPtr)
{
result[i] = (ulong)valueIntPtr.ToInt64();
continue;
}
throw new ArgumentException("Unknown primitive type in native argument list", nameof(args));
}
return result;
}
}
}

View File

@ -98,6 +98,10 @@ namespace RageCoop.Core
{
return radian*(float)(180/Math.PI);
}
public static Vector3 ToEulerDegrees(this Quaternion q)
{
return q.ToEulerAngles().ToDegree();
}
public static Vector3 ToEulerAngles(this Quaternion q)
{
Vector3 angles = new Vector3();