diff --git a/managed/src/SwiftlyS2.Shared/Misc/BitFieldHelper.cs b/managed/src/SwiftlyS2.Shared/Misc/BitFieldHelper.cs index 502e8a0c8..f7962bedd 100644 --- a/managed/src/SwiftlyS2.Shared/Misc/BitFieldHelper.cs +++ b/managed/src/SwiftlyS2.Shared/Misc/BitFieldHelper.cs @@ -1,55 +1,55 @@ -namespace SwiftlyS2.Shared.Misc; +namespace SwiftlyS2.Shared.Misc; -static class BitFieldHelper +internal static class BitFieldHelper { - public static int GetBits(ref byte data, int index, int bitCount) + public static int GetBits( ref byte data, int index, int bitCount ) { if (index < 0 || index + bitCount > 8) throw new ArgumentOutOfRangeException(); - int mask = (1 << bitCount) - 1; + var mask = (1 << bitCount) - 1; return (data >> index) & mask; } - public static void SetBits(ref byte data, int index, int bitCount, int value) + public static void SetBits( ref byte data, int index, int bitCount, int value ) { if (index < 0 || index + bitCount > 8) throw new ArgumentOutOfRangeException(); - int mask = ((1 << bitCount) - 1) << index; + var mask = ((1 << bitCount) - 1) << index; data = (byte)((data & ~mask) | ((value << index) & mask)); } - public static int GetBits(ref int data, int index, int bitCount) + public static int GetBits( ref int data, int index, int bitCount ) { if (index < 0 || index + bitCount > 32) throw new ArgumentOutOfRangeException(); - int mask = (1 << bitCount) - 1; + var mask = (1 << bitCount) - 1; return (data >> index) & mask; } - public static void SetBits(ref int data, int index, int bitCount, int value) + public static void SetBits( ref int data, int index, int bitCount, int value ) { if (index < 0 || index + bitCount > 32) throw new ArgumentOutOfRangeException(); - int mask = ((1 << bitCount) - 1) << index; + var mask = ((1 << bitCount) - 1) << index; data = (data & ~mask) | ((value << index) & mask); } - public static long GetBits(ref long data, int index, int bitCount) + public static long GetBits( ref long data, int index, int bitCount ) { if (index < 0 || index + bitCount > 64) throw new ArgumentOutOfRangeException(); - long mask = (1L << bitCount) - 1; + var mask = (1L << bitCount) - 1; return (data >> index) & mask; } - public static void SetBits(ref long data, int index, int bitCount, long value) + public static void SetBits( ref long data, int index, int bitCount, long value ) { if (index < 0 || index + bitCount > 64) throw new ArgumentOutOfRangeException(); - long mask = ((1L << bitCount) - 1) << index; + var mask = ((1L << bitCount) - 1) << index; data = (data & ~mask) | ((value << index) & mask); } - public static bool GetBit(ref byte data, int index) => GetBits(ref data, index, 1) != 0; - public static void SetBit(ref byte data, int index, bool value) => SetBits(ref data, index, 1, value ? 1 : 0); + public static bool GetBit( ref byte data, int index ) => GetBits(ref data, index, 1) != 0; + public static void SetBit( ref byte data, int index, bool value ) => SetBits(ref data, index, 1, value ? 1 : 0); - public static bool GetBit(ref int data, int index) => GetBits(ref data, index, 1) != 0; - public static void SetBit(ref int data, int index, bool value) => SetBits(ref data, index, 1, value ? 1 : 0); + public static bool GetBit( ref int data, int index ) => GetBits(ref data, index, 1) != 0; + public static void SetBit( ref int data, int index, bool value ) => SetBits(ref data, index, 1, value ? 1 : 0); - public static bool GetBit(ref long data, int index) => GetBits(ref data, index, 1) != 0; - public static void SetBit(ref long data, int index, bool value) => SetBits(ref data, index, 1, value ? 1 : 0); + public static bool GetBit( ref long data, int index ) => GetBits(ref data, index, 1) != 0; + public static void SetBit( ref long data, int index, bool value ) => SetBits(ref data, index, 1, value ? 1 : 0); } \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveData.cs b/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveData.cs new file mode 100644 index 000000000..3b81c4c9b --- /dev/null +++ b/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveData.cs @@ -0,0 +1,36 @@ +// Reference: https://github.com/KZGlobalTeam/cs2kz-metamod/blob/8d4038394173f1c10d763346d45cd3ccbc0091aa/src/sdk/datatypes.h#L252-L278 + +using System.Runtime.InteropServices; + +namespace SwiftlyS2.Shared.Natives; + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct CMoveData +{ + public CMoveDataBase Base; // class CMoveData : public CMoveDataBase + + public Vector OutWishVel; + public QAngle OldAngles; + + /// + /// World space input vector. Used to compare against the movement services' previous rotation for ground movement stuff. + /// + public Vector InputRotated; + + /// + /// Continuous acceleration in units per second squared (u/s²). + /// + public Vector ContinuousAcceleration; + + /// + /// Immediate delta in u/s. Air acceleration bypasses per second acceleration, + /// applies up to half of its impulse to the velocity and the rest goes straight into this. + /// + public Vector FrameVelocityDelta; + + public float MaxSpeed; + public float ClientMaxSpeed; + public float FrictionDecel; + public bool InAir; + public bool GameCodeMovedPlayer; // true if usercmd cmd number == (m_nGameCodeHasMovedPlayerAfterCommand + 1) +} \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveDataBase.cs b/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveDataBase.cs new file mode 100644 index 000000000..93a5a0e02 --- /dev/null +++ b/managed/src/SwiftlyS2.Shared/Natives/Structs/CMoveDataBase.cs @@ -0,0 +1,46 @@ +// Reference: https://github.com/KZGlobalTeam/cs2kz-metamod/blob/8d4038394173f1c10d763346d45cd3ccbc0091aa/src/sdk/datatypes.h#L165-L250 + +using System.Runtime.InteropServices; +using SwiftlyS2.Shared.Misc; +using SwiftlyS2.Shared.SchemaDefinitions; + +namespace SwiftlyS2.Shared.Natives; + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct CMoveDataBase +{ + private byte _bitfield0; // Bitfield members + + public bool HasZeroFrametime { + get => BitFieldHelper.GetBit(ref _bitfield0, 0); + set => BitFieldHelper.SetBit(ref _bitfield0, 0, value); + } + + public bool IsLateCommand { + get => BitFieldHelper.GetBit(ref _bitfield0, 1); + set => BitFieldHelper.SetBit(ref _bitfield0, 1, value); + } + + public CHandle PlayerHandle; + public QAngle AbsViewAngles; + public QAngle ViewAngles; + public Vector LastMovementImpulses; + public float ForwardMove; + public float SideMove; // Warning! Flipped compared to CS:GO, moving right gives negative value + public float UpMove; + public Vector Velocity; + public QAngle Angles; + public Vector Unknown; // Unused. Probably pulled from engine upstream. + public CUtlVector SubtickMoves; + public CUtlVector AttackSubtickMoves; + public bool HasSubtickInputs; + public float UnknownFloat; // Set to 1.0 during SetupMove, never change during gameplay. Is apparently used for weapon services stuff. + public CUtlVector TouchList; + public Vector CollisionNormal; + public Vector GroundNormal; + public Vector AbsOrigin; + public int TickCount; + public int TargetTick; + public float SubtickStartFraction; + public float SubtickEndFraction; +} \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Natives/Structs/SubtickMove.cs b/managed/src/SwiftlyS2.Shared/Natives/Structs/SubtickMove.cs new file mode 100644 index 000000000..0df6e5088 --- /dev/null +++ b/managed/src/SwiftlyS2.Shared/Natives/Structs/SubtickMove.cs @@ -0,0 +1,39 @@ +// Reference: https://github.com/KZGlobalTeam/cs2kz-metamod/blob/8d4038394173f1c10d763346d45cd3ccbc0091aa/src/sdk/datatypes.h#L141-L163 + +using System.Runtime.InteropServices; + +namespace SwiftlyS2.Shared.Natives; + +[StructLayout(LayoutKind.Explicit, Size = 0x20, Pack = 1)] +public struct SubtickMove +{ + [FieldOffset(0x00)] + public float When; + + [FieldOffset(0x04)] + private readonly int Padding0; + + [FieldOffset(0x08)] + public ulong Button; + + // Union: pressed (bool) or analogMove struct + [FieldOffset(0x10)] + public bool Pressed; + + [FieldOffset(0x10)] + public float AnalogForwardDelta; + + [FieldOffset(0x14)] + public float AnalogLeftDelta; + + [FieldOffset(0x18)] + public float PitchDelta; + + [FieldOffset(0x1C)] + public float YawDelta; + + public readonly bool IsAnalogInput() + { + return Button == 0; + } +} \ No newline at end of file diff --git a/managed/src/SwiftlyS2.Shared/Natives/Structs/TouchListT.cs b/managed/src/SwiftlyS2.Shared/Natives/Structs/TouchListT.cs new file mode 100644 index 000000000..29086221c --- /dev/null +++ b/managed/src/SwiftlyS2.Shared/Natives/Structs/TouchListT.cs @@ -0,0 +1,12 @@ +// Reference: https://github.com/KZGlobalTeam/cs2kz-metamod/blob/8d4038394173f1c10d763346d45cd3ccbc0091aa/src/sdk/datatypes.h#L135-L139 + +using System.Runtime.InteropServices; + +namespace SwiftlyS2.Shared.Natives; + +[StructLayout(LayoutKind.Sequential)] +public struct TouchListT +{ + public Vector DeltaVelocity; + public CGameTrace Trace; +} \ No newline at end of file diff --git a/managed/src/TestPlugin/TestPlugin.cs b/managed/src/TestPlugin/TestPlugin.cs index 9342ee300..6ef31563b 100644 --- a/managed/src/TestPlugin/TestPlugin.cs +++ b/managed/src/TestPlugin/TestPlugin.cs @@ -637,6 +637,7 @@ public void GetIpCommand( ICommandContext context ) // Core.Menus.OpenMenu(player, settingsMenu); // } + [Command("ed")] public void EndRoundCommand( ICommandContext _ ) { @@ -644,6 +645,23 @@ public void EndRoundCommand( ICommandContext _ ) gameRules.TerminateRound(RoundEndReason.CTsWin, 10.0f); } + [Command("sizecheck")] + public void SizeCheckCommand( ICommandContext _ ) + { + unsafe + { + var moveDataSize = sizeof(CMoveData); + var moveDataBaseSize = sizeof(CMoveDataBase); + var subtickMoveSize = sizeof(SubtickMove); + var touchListSize = sizeof(TouchListT); + + Console.WriteLine($"CMoveData size: {moveDataSize} bytes"); + Console.WriteLine($"CMoveDataBase size: {moveDataBaseSize} bytes"); + Console.WriteLine($"SubtickMove size: {subtickMoveSize} bytes"); + Console.WriteLine($"TouchListT size: {touchListSize} bytes"); + } + } + [Command("tm")] public void TestMenuCommand( ICommandContext context ) {