This commit is contained in:
sardelka9515
2022-10-23 19:02:39 +08:00
parent 6b34ab6e36
commit 2828b9b74f
114 changed files with 7374 additions and 7205 deletions

View File

@ -3,7 +3,7 @@
namespace RageCoop.Client
{
/// <summary>
/// Class providing support for addon mods
/// Class providing support for addon mods
/// </summary>
internal class AddOnDataProvider
{
@ -56,4 +56,4 @@ namespace RageCoop.Client
}
}
}
}
}

View File

@ -1,19 +1,19 @@

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using GTA;
using GTA.Math;
using RageCoop.Core;
using SHVDN;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace RageCoop.Client
{
internal unsafe class MemPatch
{
private readonly IntPtr _address;
private readonly byte[] _data;
private readonly byte[] _orginal;
private readonly IntPtr _address;
public MemPatch(byte* address, byte[] data)
{
_data = data;
@ -21,10 +21,12 @@ namespace RageCoop.Client
_address = (IntPtr)address;
Marshal.Copy((IntPtr)address, _orginal, 0, data.Length);
}
public void Install()
{
Marshal.Copy(_data, 0, _address, _data.Length);
}
public void Uninstall()
{
Marshal.Copy(_orginal, 0, _address, _orginal.Length);
@ -36,68 +38,95 @@ namespace RageCoop.Client
public static MemPatch VignettingPatch;
public static MemPatch VignettingCallPatch;
public static MemPatch TimeScalePatch;
static Memory()
{
// Weapon/radio wheel slow-mo patch
// Thanks @CamxxCore, https://github.com/CamxxCore/GTAVWeaponWheelMod
var result = NativeMemory.FindPattern("\x38\x51\x64\x74\x19", "xxxxx");
if (result == null) { throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slow-mo"); }
if (result == null)
throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slow-mo");
var address = result + 26;
address = address + *(int*)address + 4u;
VignettingPatch = new MemPatch(address, new byte[] { RET, 0x90, 0x90, 0x90, 0x90 });
VignettingCallPatch = new MemPatch(result + 8, new byte[] { 0x90, 0x90, 0x90, 0x90, 0x90 });
TimeScalePatch = new MemPatch(result + 34, new byte[] { XOR_32_64, 0xD2 });
}
public static void ApplyPatches()
{
VignettingPatch.Install();
VignettingCallPatch.Install();
TimeScalePatch.Install();
}
public static void RestorePatches()
{
VignettingPatch.Uninstall();
VignettingCallPatch.Uninstall();
TimeScalePatch.Uninstall();
}
#region PATCHES
#endregion
#region OFFSET-CONST
public const int PositionOffset = 144;
public const int VelocityOffset = 800;
public const int MatrixOffset = 96;
#endregion
#region OPCODE
private const byte XOR_32_64 = 0x31;
private const byte RET = 0xC3;
#endregion
public static Vector3 ReadPosition(this Entity e) => ReadVector3(e.MemoryAddress + PositionOffset);
public static Quaternion ReadQuaternion(this Entity e) => Quaternion.RotationMatrix(e.Matrix);
public static Vector3 ReadRotation(this Entity e) => e.ReadQuaternion().ToEulerDegrees();
public static Vector3 ReadVelocity(this Ped e) => ReadVector3(e.MemoryAddress + VelocityOffset);
public static Vector3 ReadPosition(this Entity e)
{
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 static Vector3 ReadVelocity(this Ped e)
{
return ReadVector3(e.MemoryAddress + VelocityOffset);
}
public static Vector3 ReadVector3(IntPtr address)
{
float* ptr = (float*)address.ToPointer();
return new Vector3()
var ptr = (float*)address.ToPointer();
return new Vector3
{
X = *ptr,
Y = ptr[1],
Z = ptr[2]
};
}
public static List<int> FindOffset(float toSearch, IntPtr start, int range = 1000, float tolerance = 0.01f)
{
var foundOffsets = new List<int>(100);
for (int i = 0; i <= range; i++)
for (var i = 0; i <= range; i++)
{
var val = NativeMemory.ReadFloat(start + i);
if (Math.Abs(val - toSearch) < tolerance)
{
foundOffsets.Add(i);
}
if (Math.Abs(val - toSearch) < tolerance) foundOffsets.Add(i);
}
return foundOffsets;
}
#region PATCHES
#endregion
#region OFFSET-CONST
public const int PositionOffset = 144;
public const int VelocityOffset = 800;
public const int MatrixOffset = 96;
#endregion
#region OPCODE
private const byte XOR_32_64 = 0x31;
private const byte RET = 0xC3;
#endregion
}
}
}

View File

@ -1,62 +1,52 @@
using GTA.Math;
using GTA.Native;
using System;
using System;
using System.Runtime.InteropServices;
using GTA.Math;
using GTA.Native;
namespace RageCoop.Client
{
[StructLayout(LayoutKind.Explicit, Size = 80)]
public struct HeadBlendData
{
[FieldOffset(0)]
public int ShapeFirst;
[FieldOffset(0)] public int ShapeFirst;
[FieldOffset(8)]
public int ShapeSecond;
[FieldOffset(8)] public int ShapeSecond;
[FieldOffset(16)]
public int ShapeThird;
[FieldOffset(16)] public int ShapeThird;
[FieldOffset(24)]
public int SkinFirst;
[FieldOffset(24)] public int SkinFirst;
[FieldOffset(32)]
public int SkinSecond;
[FieldOffset(32)] public int SkinSecond;
[FieldOffset(40)]
public int SkinThird;
[FieldOffset(40)] public int SkinThird;
[FieldOffset(48)]
public float ShapeMix;
[FieldOffset(48)] public float ShapeMix;
[FieldOffset(56)]
public float SkinMix;
[FieldOffset(56)] public float SkinMix;
[FieldOffset(64)]
public float ThirdMix;
[FieldOffset(64)] public float ThirdMix;
}
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct NativeVector3
{
[FieldOffset(0)]
public float X;
[FieldOffset(0)] public float X;
[FieldOffset(8)]
public float Y;
[FieldOffset(8)] public float Y;
[FieldOffset(16)]
public float Z;
[FieldOffset(16)] public float Z;
public static implicit operator Vector3(NativeVector3 vec)
{
return new Vector3() { X = vec.X, Y = vec.Y, Z = vec.Z };
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 };
return new NativeVector3 { X = vec.X, Y = vec.Y, Z = vec.Z };
}
}
public static class NativeCaller
{
// These are borrowed from ScriptHookVDotNet's
@ -80,8 +70,9 @@ namespace RageCoop.Client
public static unsafe R Invoke<R>(ulong hash) where R : unmanaged
{
NativeInit(hash);
return *(R*)(NativeCall());
return *(R*)NativeCall();
}
public static unsafe R Invoke<R>(Hash hash, params object[] args)
where R : unmanaged
{
@ -90,45 +81,50 @@ namespace RageCoop.Client
foreach (var arg in arguments)
NativePush(arg);
return *(R*)(NativeCall());
return *(R*)NativeCall();
}
/// <summary>
/// Helper function that converts an array of primitive values to a native stack.
/// Helper function that converts an array of primitive values to a native stack.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static unsafe ulong[] ConvertPrimitiveArguments(object[] args)
{
var result = new ulong[args.Length];
for (int i = 0; i < args.Length; ++i)
for (var 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] = 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();
@ -141,5 +137,4 @@ namespace RageCoop.Client
return result;
}
}
}
}

View File

@ -460,6 +460,6 @@
_0x1D19C622 = 454,
_0xB68D3EAB = 455,
CPED_CONFIG_FLAG_CanBeIncapacitated = 456,
_0x4BD5EBAD = 457,
_0x4BD5EBAD = 457
}
}
}

View File

@ -1,15 +1,14 @@
using GTA;
using System;
using System.Collections.Generic;
using GTA;
using GTA.Math;
using GTA.Native;
using RageCoop.Core;
using System;
using System.Collections.Generic;
namespace RageCoop.Client
{
internal static partial class PedExtensions
internal static class PedExtensions
{
public static bool IsBetween<T>(this T item, T start, T end)
{
return Comparer<T>.Default.Compare(item, start) >= 0 && Comparer<T>.Default.Compare(item, end) <= 0;
@ -17,17 +16,11 @@ namespace RageCoop.Client
public static bool Compare<T, Y>(this Dictionary<T, Y> item, Dictionary<T, Y> item2)
{
if (item == null || item2 == null || item.Count != item2.Count)
{
return false;
}
if (item == null || item2 == null || item.Count != item2.Count) return false;
foreach (KeyValuePair<T, Y> pair in item)
foreach (var pair in item)
{
if (item2.TryGetValue(pair.Key, out Y value) && Equals(value, pair.Value))
{
continue;
}
if (item2.TryGetValue(pair.Key, out var value) && Equals(value, pair.Value)) continue;
// TryGetValue() or Equals failed
return false;
@ -38,37 +31,141 @@ namespace RageCoop.Client
}
public static Vector3 RaycastEverything(Vector2 screenCoord)
{
var camPos = GameplayCamera.Position;
var camRot = GameplayCamera.Rotation;
const float raycastToDist = 100.0f;
const float raycastFromDist = 1f;
var target3D = ScreenRelToWorld(camPos, camRot, screenCoord);
var source3D = camPos;
Entity ignoreEntity = Game.Player.Character;
if (Game.Player.Character.IsInVehicle()) ignoreEntity = Game.Player.Character.CurrentVehicle;
var dir = target3D - source3D;
dir.Normalize();
var raycastResults = World.Raycast(source3D + dir * raycastFromDist,
source3D + dir * raycastToDist,
IntersectFlags.Everything,
ignoreEntity);
if (raycastResults.DidHit) return raycastResults.HitPosition;
return camPos + dir * raycastToDist;
}
public static Vector3 ScreenRelToWorld(Vector3 camPos, Vector3 camRot, Vector2 coord)
{
var camForward = camRot.ToDirection();
var rotUp = camRot + new Vector3(10, 0, 0);
var rotDown = camRot + new Vector3(-10, 0, 0);
var rotLeft = camRot + new Vector3(0, 0, -10);
var rotRight = camRot + new Vector3(0, 0, 10);
var camRight = rotRight.ToDirection() - rotLeft.ToDirection();
var camUp = rotUp.ToDirection() - rotDown.ToDirection();
double rollRad = -camRot.Y.ToRadians();
var camRightRoll = camRight * (float)Math.Cos(rollRad) - camUp * (float)Math.Sin(rollRad);
var camUpRoll = camRight * (float)Math.Sin(rollRad) + camUp * (float)Math.Cos(rollRad);
var point3D = camPos + camForward * 10.0f + camRightRoll + camUpRoll;
if (!WorldToScreenRel(point3D, out var point2D)) return camPos + camForward * 10.0f;
var point3DZero = camPos + camForward * 10.0f;
if (!WorldToScreenRel(point3DZero, out var point2DZero)) return camPos + camForward * 10.0f;
const double eps = 0.001;
if (Math.Abs(point2D.X - point2DZero.X) < eps || Math.Abs(point2D.Y - point2DZero.Y) < eps)
return camPos + camForward * 10.0f;
var scaleX = (coord.X - point2DZero.X) / (point2D.X - point2DZero.X);
var scaleY = (coord.Y - point2DZero.Y) / (point2D.Y - point2DZero.Y);
return camPos + camForward * 10.0f + camRightRoll * scaleX + camUpRoll * scaleY;
}
public static bool WorldToScreenRel(Vector3 worldCoords, out Vector2 screenCoords)
{
var num1 = new OutputArgument();
var num2 = new OutputArgument();
if (!Function.Call<bool>(Hash.GET_SCREEN_COORD_FROM_WORLD_COORD, worldCoords.X, worldCoords.Y,
worldCoords.Z, num1, num2))
{
screenCoords = new Vector2();
return false;
}
screenCoords = new Vector2((num1.GetResult<float>() - 0.5f) * 2, (num2.GetResult<float>() - 0.5f) * 2);
return true;
}
public static void StayInCover(this Ped p)
{
Function.Call(Hash.TASK_STAY_IN_COVER, p);
}
public static bool IsTurretSeat(this Vehicle veh, int seat)
{
if (Function.Call<bool>(Hash.IS_TURRET_SEAT, veh, seat)) return true;
if (!Function.Call<bool>(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle)) return false;
switch (seat)
{
case -1:
return (VehicleHash)veh.Model.Hash == VehicleHash.Rhino
|| (VehicleHash)veh.Model.Hash == VehicleHash.Khanjari
|| (VehicleHash)veh.Model.Hash == VehicleHash.FireTruck
|| (VehicleHash)veh.Model.Hash == VehicleHash.Riot2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus3;
case 0:
return (VehicleHash)veh.Model.Hash == VehicleHash.Apc
|| (VehicleHash)veh.Model.Hash == VehicleHash.Dune3;
case 1:
return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie
|| (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical3
|| (VehicleHash)veh.Model.Hash == VehicleHash.HalfTrack
|| (VehicleHash)veh.Model.Hash == VehicleHash.Barrage;
case 2:
return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie
|| (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Barrage;
case 3:
return (VehicleHash)veh.Model.Hash == VehicleHash.Limo2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Dinghy5;
case 7:
return (VehicleHash)veh.Model.Hash == VehicleHash.Insurgent;
}
return false;
}
public static bool IsOnTurretSeat(this Ped P)
{
if (P.CurrentVehicle == null) return false;
return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex);
}
#region PED
public static byte GetPedSpeed(this Ped ped)
{
if (ped.IsSittingInVehicle())
{
return 4;
}
if (ped.IsTaskActive(TaskType.CTaskEnterVehicle))
{
return 5;
}
if (ped.IsTaskActive(TaskType.CTaskExitVehicle))
{
return 6;
}
if (ped.IsWalking)
{
return 1;
}
if (ped.IsRunning)
{
return 2;
}
if (ped.IsSprinting)
{
return 3;
}
if (ped.IsSittingInVehicle()) return 4;
if (ped.IsTaskActive(TaskType.CTaskEnterVehicle)) return 5;
if (ped.IsTaskActive(TaskType.CTaskExitVehicle)) return 6;
if (ped.IsWalking) return 1;
if (ped.IsRunning) return 2;
if (ped.IsSprinting) return 3;
return 0;
@ -84,87 +181,46 @@ namespace RageCoop.Client
result[i + 12] = (byte)Function.Call<short>(Hash.GET_PED_TEXTURE_VARIATION, ped.Handle, i);
result[i + 24] = (byte)Function.Call<short>(Hash.GET_PED_PALETTE_VARIATION, ped.Handle, i);
}
return result;
}
public static PedDataFlags GetPedFlags(this Ped ped)
{
PedDataFlags flags = PedDataFlags.None;
var flags = PedDataFlags.None;
if (ped.IsAiming || ped.IsOnTurretSeat())
{
flags |= PedDataFlags.IsAiming;
}
if (ped.IsAiming || ped.IsOnTurretSeat()) flags |= PedDataFlags.IsAiming;
if (ped.IsReloading)
{
flags |= PedDataFlags.IsReloading;
}
if (ped.IsReloading) flags |= PedDataFlags.IsReloading;
if (ped.IsJumping)
{
flags |= PedDataFlags.IsJumping;
}
if (ped.IsJumping) flags |= PedDataFlags.IsJumping;
// Fake death
if (ped.IsRagdoll || (ped.Health == 1 && ped.IsPlayer))
{
flags |= PedDataFlags.IsRagdoll;
}
if (ped.IsRagdoll || (ped.Health == 1 && ped.IsPlayer)) flags |= PedDataFlags.IsRagdoll;
if (ped.IsOnFire)
{
flags |= PedDataFlags.IsOnFire;
}
if (ped.IsOnFire) flags |= PedDataFlags.IsOnFire;
if (ped.IsInParachuteFreeFall)
{
flags |= PedDataFlags.IsInParachuteFreeFall;
}
if (ped.IsInParachuteFreeFall) flags |= PedDataFlags.IsInParachuteFreeFall;
if (ped.ParachuteState == ParachuteState.Gliding)
{
flags |= PedDataFlags.IsParachuteOpen;
}
if (ped.ParachuteState == ParachuteState.Gliding) flags |= PedDataFlags.IsParachuteOpen;
bool climbingLadder = ped.IsTaskActive(TaskType.CTaskGoToAndClimbLadder);
if (climbingLadder)
{
flags |= PedDataFlags.IsOnLadder;
}
var climbingLadder = ped.IsTaskActive(TaskType.CTaskGoToAndClimbLadder);
if (climbingLadder) flags |= PedDataFlags.IsOnLadder;
if (ped.IsVaulting && !climbingLadder)
{
flags |= PedDataFlags.IsVaulting;
}
if (ped.IsVaulting && !climbingLadder) flags |= PedDataFlags.IsVaulting;
if (ped.IsInCover || ped.IsGoingIntoCover)
{
flags |= PedDataFlags.IsInCover;
if (ped.IsInCoverFacingLeft)
{
flags |= PedDataFlags.IsInCover;
}
if (!Function.Call<bool>(Hash.IS_PED_IN_HIGH_COVER, ped))
{
flags |= PedDataFlags.IsInLowCover;
}
if (ped.IsTaskActive(TaskType.CTaskAimGunBlindFire))
{
flags |= PedDataFlags.IsBlindFiring;
}
if (ped.IsInCoverFacingLeft) flags |= PedDataFlags.IsInCover;
if (!Function.Call<bool>(Hash.IS_PED_IN_HIGH_COVER, ped)) flags |= PedDataFlags.IsInLowCover;
if (ped.IsTaskActive(TaskType.CTaskAimGunBlindFire)) flags |= PedDataFlags.IsBlindFiring;
}
if (ped.IsInvincible)
{
flags |= PedDataFlags.IsInvincible;
}
if (ped.IsInvincible) flags |= PedDataFlags.IsInvincible;
if (Function.Call<bool>(Hash.GET_PED_STEALTH_MOVEMENT, ped))
{
flags |= PedDataFlags.IsInStealthMode;
}
if (Function.Call<bool>(Hash.GET_PED_STEALTH_MOVEMENT, ped)) flags |= PedDataFlags.IsInStealthMode;
return flags;
@ -253,31 +309,34 @@ namespace RageCoop.Client
case WeaponHash.MG:
return new string[2] { "weapons@machinegun@mg_str", "reload_aim" };
default:
Main.Logger.Warning($"~r~Reloading failed! Weapon ~g~[{ped.Weapons.Current.Hash}]~r~ could not be found!");
Main.Logger.Warning(
$"~r~Reloading failed! Weapon ~g~[{ped.Weapons.Current.Hash}]~r~ could not be found!");
return null;
}
}
public static VehicleSeat GetNearestSeat(this Ped ped, Vehicle veh, float distanceToignoreDoors = 50f)
{
float num = 99f;
int result = -2;
Dictionary<string, int> dictionary = new Dictionary<string, int>();
var num = 99f;
var result = -2;
var dictionary = new Dictionary<string, int>();
dictionary.Add("door_dside_f", -1);
dictionary.Add("door_pside_f", 0);
dictionary.Add("door_dside_r", 1);
dictionary.Add("door_pside_r", 2);
foreach (string text in dictionary.Keys)
foreach (var text in dictionary.Keys)
{
bool flag = veh.Bones[text].Position != Vector3.Zero;
var flag = veh.Bones[text].Position != Vector3.Zero;
if (flag)
{
float num2 = ped.Position.DistanceTo(Function.Call<Vector3>(Hash.GET_WORLD_POSITION_OF_ENTITY_BONE, new InputArgument[]
{
veh,
veh.Bones[text].Index
}));
bool flag2 = (num2 < distanceToignoreDoors) && (num2 < num) && IsSeatUsableByPed(ped, veh, dictionary[text]);
var num2 = ped.Position.DistanceTo(Function.Call<Vector3>(Hash.GET_WORLD_POSITION_OF_ENTITY_BONE,
new InputArgument[]
{
veh,
veh.Bones[text].Index
}));
var flag2 = num2 < distanceToignoreDoors && num2 < num &&
IsSeatUsableByPed(ped, veh, dictionary[text]);
if (flag2)
{
num = num2;
@ -285,46 +344,46 @@ namespace RageCoop.Client
}
}
}
return (VehicleSeat)result;
}
public static bool IsSeatUsableByPed(Ped ped, Vehicle veh, int _seat)
{
VehicleSeat seat = (VehicleSeat)_seat;
bool result = false;
bool flag = veh.IsSeatFree(seat);
var seat = (VehicleSeat)_seat;
var result = false;
var flag = veh.IsSeatFree(seat);
if (flag)
{
result = true;
}
else
{
bool isDead = veh.GetPedOnSeat(seat).IsDead;
var isDead = veh.GetPedOnSeat(seat).IsDead;
if (isDead)
{
result = true;
}
else
{
int num = Function.Call<int>(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[]
var num = Function.Call<int>(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[]
{
ped,
veh.GetPedOnSeat(seat)
});
bool flag2 = num > 2;
if (flag2)
{
result = true;
}
var flag2 = num > 2;
if (flag2) result = true;
}
}
return result;
}
public static bool IsTaskActive(this Ped p, TaskType task)
{
return Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, p.Handle, task);
}
public static Vector3 GetAimCoord(this Ped p)
{
Prop weapon;
@ -332,183 +391,35 @@ namespace RageCoop.Client
EntityBone b;
if (p.IsOnTurretSeat())
{
if((b = p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon)) != null)
{
if ((b = p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon)) != null)
return b.Position + b.ForwardVector * 50;
}
return GetLookingCoord(p);
}
if ((weapon= p.Weapons.CurrentWeaponObject) != null)
if ((weapon = p.Weapons.CurrentWeaponObject) != null)
{
// Not very accurate, but doesn't matter
Vector3 dir = weapon.RightVector;
var dir = weapon.RightVector;
return weapon.Position + dir * 20;
}
return GetLookingCoord(p);
}
public static Vector3 GetLookingCoord(this Ped p)
{
if (p == Main.P && Function.Call<int>(Hash.GET_FOLLOW_PED_CAM_VIEW_MODE) == 4)
{
return RaycastEverything(default);
}
EntityBone b = p.Bones[Bone.FacialForehead];
Vector3 v = b.UpVector.Normalized;
var v = b.UpVector.Normalized;
return b.Position + 200 * v;
}
public static VehicleSeat GetSeatTryingToEnter(this Ped p)
{
return (VehicleSeat)Function.Call<int>(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p);
}
#endregion
public static Vector3 RaycastEverything(Vector2 screenCoord)
{
Vector3 camPos = GameplayCamera.Position;
Vector3 camRot = GameplayCamera.Rotation;
const float raycastToDist = 100.0f;
const float raycastFromDist = 1f;
Vector3 target3D = ScreenRelToWorld(camPos, camRot, screenCoord);
Vector3 source3D = camPos;
Entity ignoreEntity = Game.Player.Character;
if (Game.Player.Character.IsInVehicle())
{
ignoreEntity = Game.Player.Character.CurrentVehicle;
}
Vector3 dir = target3D - source3D;
dir.Normalize();
RaycastResult raycastResults = World.Raycast(source3D + dir * raycastFromDist,
source3D + dir * raycastToDist,
IntersectFlags.Everything,
ignoreEntity);
if (raycastResults.DidHit)
{
return raycastResults.HitPosition;
}
return camPos + dir * raycastToDist;
}
public static Vector3 ScreenRelToWorld(Vector3 camPos, Vector3 camRot, Vector2 coord)
{
Vector3 camForward = camRot.ToDirection();
Vector3 rotUp = camRot + new Vector3(10, 0, 0);
Vector3 rotDown = camRot + new Vector3(-10, 0, 0);
Vector3 rotLeft = camRot + new Vector3(0, 0, -10);
Vector3 rotRight = camRot + new Vector3(0, 0, 10);
Vector3 camRight = rotRight.ToDirection() - rotLeft.ToDirection();
Vector3 camUp = rotUp.ToDirection() - rotDown.ToDirection();
double rollRad = -camRot.Y.ToRadians();
Vector3 camRightRoll = camRight * (float)Math.Cos(rollRad) - camUp * (float)Math.Sin(rollRad);
Vector3 camUpRoll = camRight * (float)Math.Sin(rollRad) + camUp * (float)Math.Cos(rollRad);
Vector3 point3D = camPos + camForward * 10.0f + camRightRoll + camUpRoll;
if (!WorldToScreenRel(point3D, out Vector2 point2D))
{
return camPos + camForward * 10.0f;
}
Vector3 point3DZero = camPos + camForward * 10.0f;
if (!WorldToScreenRel(point3DZero, out Vector2 point2DZero))
{
return camPos + camForward * 10.0f;
}
const double eps = 0.001;
if (Math.Abs(point2D.X - point2DZero.X) < eps || Math.Abs(point2D.Y - point2DZero.Y) < eps)
{
return camPos + camForward * 10.0f;
}
float scaleX = (coord.X - point2DZero.X) / (point2D.X - point2DZero.X);
float scaleY = (coord.Y - point2DZero.Y) / (point2D.Y - point2DZero.Y);
return camPos + camForward * 10.0f + camRightRoll * scaleX + camUpRoll * scaleY;
}
public static bool WorldToScreenRel(Vector3 worldCoords, out Vector2 screenCoords)
{
OutputArgument num1 = new OutputArgument();
OutputArgument num2 = new OutputArgument();
if (!Function.Call<bool>(Hash.GET_SCREEN_COORD_FROM_WORLD_COORD, worldCoords.X, worldCoords.Y, worldCoords.Z, num1, num2))
{
screenCoords = new Vector2();
return false;
}
screenCoords = new Vector2((num1.GetResult<float>() - 0.5f) * 2, (num2.GetResult<float>() - 0.5f) * 2);
return true;
}
public static void StayInCover(this Ped p)
{
Function.Call(Hash.TASK_STAY_IN_COVER, p);
}
public static bool IsTurretSeat(this Vehicle veh, int seat)
{
if (Function.Call<bool>(Hash.IS_TURRET_SEAT, veh, seat)) { return true; }
if (!Function.Call<bool>(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle))
{
return false;
}
switch (seat)
{
case -1:
return (VehicleHash)veh.Model.Hash == VehicleHash.Rhino
|| (VehicleHash)veh.Model.Hash == VehicleHash.Khanjari
|| (VehicleHash)veh.Model.Hash == VehicleHash.FireTruck
|| (VehicleHash)veh.Model.Hash == VehicleHash.Riot2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus3;
case 0:
return (VehicleHash)veh.Model.Hash == VehicleHash.Apc
|| (VehicleHash)veh.Model.Hash == VehicleHash.Dune3;
case 1:
return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie
|| (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Technical3
|| (VehicleHash)veh.Model.Hash == VehicleHash.HalfTrack
|| (VehicleHash)veh.Model.Hash == VehicleHash.Barrage;
case 2:
return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie
|| (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Barrage;
case 3:
return (VehicleHash)veh.Model.Hash == VehicleHash.Limo2
|| (VehicleHash)veh.Model.Hash == VehicleHash.Dinghy5;
case 7:
return (VehicleHash)veh.Model.Hash == VehicleHash.Insurgent;
}
return false;
}
public static bool IsOnTurretSeat(this Ped P)
{
if (P.CurrentVehicle == null) { return false; }
return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex);
}
}
}
}

View File

@ -1,6 +1,7 @@
// WARNING: values can change after a game update
// if R* adds in the middle!
// This is up-to-date for b2372
internal enum TaskType
{
CTaskHandsUp = 0,
@ -435,4 +436,4 @@ internal enum TaskType
CTaskVehiclePullAlongside = 528,
CTaskVehicleTransformToSubmarine = 529,
CTaskAnimatedFallback = 530
};
}

View File

@ -1,52 +1,63 @@
using GTA;
using GTA.Math;
using GTA.Native;
using LemonUI.Elements;
using Newtonsoft.Json;
using RageCoop.Core;
using System;
using System;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using GTA;
using GTA.Math;
using GTA.Native;
using GTA.UI;
using LemonUI.Elements;
using Newtonsoft.Json;
using RageCoop.Core;
using Font = GTA.UI.Font;
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
namespace RageCoop.Client
{
internal static class Util
{
public static Vector3 GetRotation(this EntityBone b)
{
return b.ForwardVector.ToEulerRotation(b.UpVector);
}
public static void StartUpCheck()
{
if (AppDomain.CurrentDomain.GetData("RageCoop.Client.LoaderContext") == null)
{
var error = $"Client not loaded with loader, please re-install using the installer to fix this issue";
try
{
GTA.UI.Notification.Show("~r~" + error);
}
catch { }
throw new Exception(error);
}
}
public static string SettingsPath = "RageCoop\\Settings.json";
public static SizeF ResolutionMaintainRatio
{
get
{
// Get the game width and height
int screenw = GTA.UI.Screen.Resolution.Width;
int screenh = GTA.UI.Screen.Resolution.Height;
var screenw = Screen.Resolution.Width;
var screenh = Screen.Resolution.Height;
// Calculate the ratio
float ratio = (float)screenw / screenh;
var ratio = (float)screenw / screenh;
// And the width with that ratio
float width = 1080f * ratio;
var width = 1080f * ratio;
// Finally, return a SizeF
return new SizeF(width, 1080f);
}
}
public static Vector3 GetRotation(this EntityBone b)
{
return b.ForwardVector.ToEulerRotation(b.UpVector);
}
public static void StartUpCheck()
{
if (AppDomain.CurrentDomain.GetData("RageCoop.Client.LoaderContext") == null)
{
var error = "Client not loaded with loader, please re-install using the installer to fix this issue";
try
{
Notification.Show("~r~" + error);
}
catch
{
}
throw new Exception(error);
}
}
public static void DrawTextFromCoord(Vector3 coord, string text, float scale = 0.5f, Point offset = default)
{
Point toDraw = default;
@ -54,14 +65,15 @@ namespace RageCoop.Client
{
toDraw.X += offset.X;
toDraw.Y += offset.Y;
new ScaledText(toDraw, text, scale, GTA.UI.Font.ChaletLondon)
new ScaledText(toDraw, text, scale, Font.ChaletLondon)
{
Outline = true,
Alignment = GTA.UI.Alignment.Center,
Color = Color.White,
Alignment = Alignment.Center,
Color = Color.White
}.Draw();
}
}
public static bool WorldToScreen(Vector3 pos, ref Point screenPos)
{
float x, y;
@ -74,74 +86,10 @@ namespace RageCoop.Client
return true;
}
}
return false;
}
#region -- POINTER --
private static int _steeringAngleOffset { get; set; }
public static unsafe void NativeMemory()
{
IntPtr address;
address = Game.FindPattern("\x74\x0A\xF3\x0F\x11\xB3\x1C\x09\x00\x00\xEB\x25", "xxxxxx????xx");
if (address != IntPtr.Zero)
{
_steeringAngleOffset = *(int*)(address + 6) + 8;
}
}
public static unsafe void CustomSteeringAngle(this Vehicle veh, float value)
{
IntPtr address = new IntPtr((long)veh.MemoryAddress);
if (address == IntPtr.Zero || _steeringAngleOffset == 0)
{
return;
}
*(float*)(address + _steeringAngleOffset).ToPointer() = value;
}
#endregion
#region MATH
public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, ulong currentTime, int duration)
{
return new Vector3()
{
X = LinearFloatLerp(start.X, end.X, currentTime, duration),
Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration),
Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration),
};
}
public static float LinearFloatLerp(float start, float end, ulong currentTime, int duration)
{
return (end - start) * currentTime / duration + start;
}
public static float Lerp(float from, float to, float fAlpha)
{
return (from * (1.0f - fAlpha)) + (to * fAlpha); //from + (to - from) * fAlpha
}
public static Vector3 RotationToDirection(Vector3 rotation)
{
double z = MathExtensions.DegToRad(rotation.Z);
double x = MathExtensions.DegToRad(rotation.X);
double num = Math.Abs(Math.Cos(x));
return new Vector3
{
X = (float)(-Math.Sin(z) * num),
Y = (float)(Math.Cos(z) * num),
Z = (float)Math.Sin(x)
};
}
#endregion
public static string SettingsPath = "RageCoop\\Settings.json";
public static Settings ReadSettings(string path = null)
{
path = path ?? SettingsPath;
@ -160,6 +108,7 @@ namespace RageCoop.Client
return settings;
}
public static bool SaveSettings(string path = null, Settings settings = null)
{
try
@ -181,25 +130,26 @@ namespace RageCoop.Client
public static Vehicle CreateVehicle(Model model, Vector3 position, float heading = 0f)
{
if (!model.IsLoaded) { return null; }
return (Vehicle)Entity.FromHandle(Function.Call<int>(Hash.CREATE_VEHICLE, model.Hash, position.X, position.Y, position.Z, heading, false, false));
if (!model.IsLoaded) return null;
return (Vehicle)Entity.FromHandle(Function.Call<int>(Hash.CREATE_VEHICLE, model.Hash, position.X,
position.Y, position.Z, heading, false, false));
}
public static Ped CreatePed(Model model, Vector3 position, float heading = 0f)
{
if (!model.IsLoaded) { return null; }
return (Ped)Entity.FromHandle(Function.Call<int>(Hash.CREATE_PED, 26, model.Hash, position.X, position.Y, position.Z, heading, false, false));
if (!model.IsLoaded) return null;
return (Ped)Entity.FromHandle(Function.Call<int>(Hash.CREATE_PED, 26, model.Hash, position.X, position.Y,
position.Z, heading, false, false));
}
public static void SetOnFire(this Entity e, bool toggle)
{
if (toggle)
{
Function.Call(Hash.START_ENTITY_FIRE, e.Handle);
}
else
{
Function.Call(Hash.STOP_ENTITY_FIRE, e.Handle);
}
}
public static void SetFrozen(this Entity e, bool toggle)
{
Function.Call(Hash.FREEZE_ENTITY_POSITION, e, toggle);
@ -207,28 +157,32 @@ namespace RageCoop.Client
public static SyncedPed GetSyncEntity(this Ped p)
{
if (p == null) { return null; }
if (p == null) return null;
var c = EntityPool.GetPedByHandle(p.Handle);
if (c == null) { EntityPool.Add(c = new SyncedPed(p)); }
if (c == null) EntityPool.Add(c = new SyncedPed(p));
return c;
}
public static SyncedVehicle GetSyncEntity(this Vehicle veh)
{
if (veh == null) { return null; }
if (veh == null) return null;
var v = EntityPool.GetVehicleByHandle(veh.Handle);
if (v == null) { EntityPool.Add(v = new SyncedVehicle(veh)); }
if (v == null) EntityPool.Add(v = new SyncedVehicle(veh));
return v;
}
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default(Vector3), ForceType forceType = ForceType.MaxForceRot2)
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default,
ForceType forceType = ForceType.MaxForceRot2)
{
Function.Call(Hash.APPLY_FORCE_TO_ENTITY, e.Handle, forceType, direction.X, direction.Y, direction.Z, rotation.X, rotation.Y, rotation.Z, boneIndex, false, true, true, false, true);
Function.Call(Hash.APPLY_FORCE_TO_ENTITY, e.Handle, forceType, direction.X, direction.Y, direction.Z,
rotation.X, rotation.Y, rotation.Z, boneIndex, false, true, true, false, true);
}
public static byte GetPlayerRadioIndex()
{
return (byte)Function.Call<int>(Hash.GET_PLAYER_RADIO_STATION_INDEX);
}
public static void SetPlayerRadioIndex(int index)
{
Function.Call(Hash.SET_RADIO_TO_STATION_INDEX, index);
@ -237,5 +191,66 @@ namespace RageCoop.Client
[DllImport("kernel32.dll")]
public static extern ulong GetTickCount64();
#region -- POINTER --
private static int _steeringAngleOffset { get; set; }
public static unsafe void NativeMemory()
{
IntPtr address;
address = Game.FindPattern("\x74\x0A\xF3\x0F\x11\xB3\x1C\x09\x00\x00\xEB\x25", "xxxxxx????xx");
if (address != IntPtr.Zero) _steeringAngleOffset = *(int*)(address + 6) + 8;
}
public static unsafe void CustomSteeringAngle(this Vehicle veh, float value)
{
var address = new IntPtr((long)veh.MemoryAddress);
if (address == IntPtr.Zero || _steeringAngleOffset == 0) return;
*(float*)(address + _steeringAngleOffset).ToPointer() = value;
}
#endregion
#region MATH
public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, ulong currentTime, int duration)
{
return new Vector3
{
X = LinearFloatLerp(start.X, end.X, currentTime, duration),
Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration),
Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration)
};
}
public static float LinearFloatLerp(float start, float end, ulong currentTime, int duration)
{
return (end - start) * currentTime / duration + start;
}
public static float Lerp(float from, float to, float fAlpha)
{
return from * (1.0f - fAlpha) + to * fAlpha; //from + (to - from) * fAlpha
}
public static Vector3 RotationToDirection(Vector3 rotation)
{
var z = MathExtensions.DegToRad(rotation.Z);
var x = MathExtensions.DegToRad(rotation.X);
var num = Math.Abs(Math.Cos(x));
return new Vector3
{
X = (float)(-Math.Sin(z) * num),
Y = (float)(Math.Cos(z) * num),
Z = (float)Math.Sin(x)
};
}
#endregion
}
}
}

View File

@ -1,8 +1,8 @@
using GTA;
using System;
using System.Collections.Generic;
using GTA;
using GTA.Native;
using RageCoop.Core;
using System;
using System.Collections.Generic;
namespace RageCoop.Client
{
@ -15,101 +15,62 @@ namespace RageCoop.Client
var veh = v.MainVehicle;
VehicleDataFlags flags = 0;
if (veh.IsEngineRunning)
{
flags |= VehicleDataFlags.IsEngineRunning;
}
if (veh.IsEngineRunning) flags |= VehicleDataFlags.IsEngineRunning;
if (veh.AreLightsOn)
{
flags |= VehicleDataFlags.AreLightsOn;
}
if (veh.AreLightsOn) flags |= VehicleDataFlags.AreLightsOn;
if (veh.BrakePower >= 0.01f)
{
flags |= VehicleDataFlags.AreBrakeLightsOn;
}
if (veh.BrakePower >= 0.01f) flags |= VehicleDataFlags.AreBrakeLightsOn;
if (veh.AreHighBeamsOn)
{
flags |= VehicleDataFlags.AreHighBeamsOn;
}
if (veh.AreHighBeamsOn) flags |= VehicleDataFlags.AreHighBeamsOn;
if (veh.IsSirenActive)
{
flags |= VehicleDataFlags.IsSirenActive;
}
if (veh.IsSirenActive) flags |= VehicleDataFlags.IsSirenActive;
if (veh.IsDead)
{
flags |= VehicleDataFlags.IsDead;
}
if (veh.IsDead) flags |= VehicleDataFlags.IsDead;
if (Function.Call<bool>(Hash.IS_HORN_ACTIVE, veh.Handle))
{
flags |= VehicleDataFlags.IsHornActive;
}
if (Function.Call<bool>(Hash.IS_HORN_ACTIVE, veh.Handle)) flags |= VehicleDataFlags.IsHornActive;
if (v.IsSubmarineCar && Function.Call<bool>(Hash._GET_IS_SUBMARINE_VEHICLE_TRANSFORMED, veh.Handle))
{
flags |= VehicleDataFlags.IsTransformed;
}
if (v.IsAircraft)
{
flags |= VehicleDataFlags.IsAircraft;
}
if (v.IsAircraft) flags |= VehicleDataFlags.IsAircraft;
if (v.IsDeluxo && veh.IsDeluxoHovering())
{
flags |= VehicleDataFlags.IsDeluxoHovering;
}
if (v.IsDeluxo && veh.IsDeluxoHovering()) flags |= VehicleDataFlags.IsDeluxoHovering;
if (v.HasRoof)
{
flags |= VehicleDataFlags.HasRoof;
}
if (v.HasRoof) flags |= VehicleDataFlags.HasRoof;
if (v.HasRocketBoost && veh.IsRocketBoostActive())
{
flags |= VehicleDataFlags.IsRocketBoostActive;
}
if (v.HasRocketBoost && veh.IsRocketBoostActive()) flags |= VehicleDataFlags.IsRocketBoostActive;
if (v.HasParachute && veh.IsParachuteActive())
{
flags |= VehicleDataFlags.IsParachuteActive;
}
if (v.HasParachute && veh.IsParachuteActive()) flags |= VehicleDataFlags.IsParachuteActive;
if (veh.IsOnFire)
{
flags |= VehicleDataFlags.IsOnFire;
}
if (veh.IsOnFire) flags |= VehicleDataFlags.IsOnFire;
return flags;
}
public static bool IsRocketBoostActive(this Vehicle veh)
{
return Function.Call<bool>(Hash._IS_VEHICLE_ROCKET_BOOST_ACTIVE, veh);
}
public static bool IsParachuteActive(this Vehicle veh)
{
return Function.Call<bool>((Hash)0x3DE51E9C80B116CF, veh);
}
public static void SetRocketBoostActive(this Vehicle veh, bool toggle)
{
Function.Call(Hash._SET_VEHICLE_ROCKET_BOOST_ACTIVE, veh, toggle);
}
public static void SetParachuteActive(this Vehicle veh, bool toggle)
{
Function.Call((Hash)0x0BFFB028B3DD0A97, veh, toggle);
}
public static Dictionary<int, int> GetVehicleMods(this VehicleModCollection mods)
{
Dictionary<int, int> result = new Dictionary<int, int>();
foreach (VehicleMod mod in mods.ToArray())
{
result.Add((int)mod.Type, mod.Index);
}
var result = new Dictionary<int, int>();
foreach (var mod in mods.ToArray()) result.Add((int)mod.Type, mod.Index);
return result;
}
@ -117,40 +78,25 @@ namespace RageCoop.Client
{
// Broken windows
byte brokenWindows = 0;
for (int i = 0; i < 8; i++)
{
for (var i = 0; i < 8; i++)
if (!veh.Windows[(VehicleWindowIndex)i].IsIntact)
{
brokenWindows |= (byte)(1 << i);
}
}
// Broken doors
byte brokenDoors = 0;
byte openedDoors = 0;
foreach (VehicleDoor door in veh.Doors)
{
foreach (var door in veh.Doors)
if (door.IsBroken)
{
brokenDoors |= (byte)(1 << (byte)door.Index);
}
else if (door.IsOpen)
{
openedDoors |= (byte)(1 << (byte)door.Index);
}
}
else if (door.IsOpen) openedDoors |= (byte)(1 << (byte)door.Index);
// Bursted tires
short burstedTires = 0;
foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels())
{
foreach (var wheel in veh.Wheels.GetAllWheels())
if (wheel.IsBursted)
{
burstedTires |= (short)(1 << (int)wheel.BoneId);
}
}
return new VehicleDamageModel()
return new VehicleDamageModel
{
BrokenDoors = brokenDoors,
OpenedDoors = openedDoors,
@ -163,47 +109,37 @@ namespace RageCoop.Client
public static void SetDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true)
{
for (int i = 0; i < 8; i++)
for (var i = 0; i < 8; i++)
{
var door = veh.Doors[(VehicleDoorIndex)i];
if ((model.BrokenDoors & (byte)(1 << i)) != 0)
{
if (!door.IsBroken)
{
door.Break(leavedoors);
}
if (!door.IsBroken) door.Break(leavedoors);
continue;
}
else if (door.IsBroken)
if (door.IsBroken)
{
// The vehicle can only fix a door if the vehicle was completely fixed
veh.Repair();
return;
}
if ((model.OpenedDoors & (byte)(1 << i)) != 0)
{
if ((!door.IsOpen) && (!door.IsBroken))
{
door.Open();
}
if (!door.IsOpen && !door.IsBroken) door.Open();
}
else if (door.IsOpen)
{
if (!door.IsBroken) { door.Close(); }
if (!door.IsBroken) door.Close();
}
if ((model.BrokenWindows & (byte)(1 << i)) != 0)
{
veh.Windows[(VehicleWindowIndex)i].Smash();
}
else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact)
{
veh.Windows[(VehicleWindowIndex)i].Repair();
}
else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) veh.Windows[(VehicleWindowIndex)i].Repair();
}
foreach (VehicleWheel wheel in veh.Wheels)
{
foreach (var wheel in veh.Wheels)
if ((model.BurstedTires & (short)(1 << (int)wheel.BoneId)) != 0)
{
if (!wheel.IsBursted)
@ -216,7 +152,6 @@ namespace RageCoop.Client
{
wheel.Fix();
}
}
veh.IsLeftHeadLightBroken = model.LeftHeadLightBroken > 0;
veh.IsRightHeadLightBroken = model.RightHeadLightBroken > 0;
@ -224,19 +159,12 @@ namespace RageCoop.Client
public static Dictionary<int, int> GetPassengers(this Vehicle veh)
{
Dictionary<int, int> ps = new Dictionary<int, int>();
var ps = new Dictionary<int, int>();
var d = veh.Driver;
if (d != null && d.IsSittingInVehicle())
{
ps.Add(-1, d.GetSyncEntity().ID);
}
foreach (Ped p in veh.Passengers)
{
if (d != null && d.IsSittingInVehicle()) ps.Add(-1, d.GetSyncEntity().ID);
foreach (var p in veh.Passengers)
if (p.IsSittingInVehicle())
{
ps.Add((int)p.SeatIndex, p.GetSyncEntity().ID);
}
}
return ps;
}
@ -244,25 +172,29 @@ namespace RageCoop.Client
{
Function.Call(Hash._SET_VEHICLE_HOVER_TRANSFORM_PERCENTAGE, deluxo, hover ? 1f : 0f);
}
public static bool IsDeluxoHovering(this Vehicle deluxo)
{
return Math.Abs(deluxo.Bones[27].ForwardVector.GetCosTheta(deluxo.ForwardVector) - 1) > 0.05;
}
public static void SetDeluxoWingRatio(this Vehicle v, float ratio)
{
Function.Call(Hash._SET_SPECIALFLIGHT_WING_RATIO, v, ratio);
}
public static float GetDeluxoWingRatio(this Vehicle v)
{
return v.Bones[99].Position.DistanceTo(v.Bones[92].Position) - 1.43f;
}
public static float GetNozzleAngel(this Vehicle plane)
{
return Function.Call<float>(Hash._GET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane);
}
public static bool HasNozzle(this Vehicle v)
{
switch (v.Model.Hash)
{
// Hydra
@ -280,14 +212,16 @@ namespace RageCoop.Client
// Avenger
case 408970549:
return true;
}
return false;
}
public static void SetNozzleAngel(this Vehicle plane, float ratio)
{
Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio);
}
#endregion
}
}
}

View File

@ -1,48 +1,56 @@
using GTA;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using GTA;
using GTA.Math;
using GTA.Native;
using Newtonsoft.Json;
using RageCoop.Core;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System;
using Console = GTA.Console;
using System.Drawing;
using System.Runtime.InteropServices;
namespace RageCoop.Client
{
#region DUMP
class VehicleInfo
internal class VehicleInfo
{
public VehicleBone[] Bones;
public uint Hash;
public string Name;
public string[] Weapons;
public uint Hash;
public VehicleBone[] Bones;
}
class VehicleBone
internal class VehicleBone
{
public uint BoneID;
public uint BoneIndex;
public string BoneName;
}
class WeaponBones
internal class WeaponBones
{
public string Name;
public VehicleBone[] Bones;
public string Name;
}
class VehicleWeaponInfo
internal class VehicleWeaponInfo
{
public uint Hash;
public string Name;
public Dictionary<uint, WeaponBones> Weapons = new Dictionary<uint, WeaponBones>();
public static void Dump(string input, string output)
{
Console.Info("Generating " + output);
if (!File.Exists(input))
{
Console.Info("Downloading");
HttpHelper.DownloadFile("https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/vehicles.json", input);
HttpHelper.DownloadFile(
"https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/vehicles.json", input);
}
Console.Info("Deserialising");
var infos = JsonConvert.DeserializeObject<VehicleInfo[]>(File.ReadAllText(input));
Console.Info("Serialising");
@ -51,52 +59,77 @@ namespace RageCoop.Client
infos.Select(x => FromVehicle(x)).Where(x => x != null),
Formatting.Indented));
}
public static VehicleWeaponInfo FromVehicle(VehicleInfo info)
{
if (info.Weapons.Length == 0)
{
return null;
}
var result = new VehicleWeaponInfo() { Hash = info.Hash, Name = info.Name };
for (int i = 0; i < info.Weapons.Length; i++)
{
if (info.Weapons.Length == 0) return null;
var result = new VehicleWeaponInfo { Hash = info.Hash, Name = info.Name };
for (var i = 0; i < info.Weapons.Length; i++)
result.Weapons.Add((uint)Game.GenerateHash(info.Weapons[i])
, new WeaponBones
{
Name = info.Weapons[i],
Bones = info.Bones.Where(x => x.BoneName.StartsWith($"weapon_{i + 1}") && !x.BoneName.EndsWith("rot")).ToArray()
Bones = info.Bones.Where(x =>
x.BoneName.StartsWith($"weapon_{i + 1}") && !x.BoneName.EndsWith("rot")).ToArray()
});
}
return result;
}
public uint Hash;
public string Name;
public Dictionary<uint, WeaponBones> Weapons = new Dictionary<uint, WeaponBones>();
}
class WeaponInfo
internal class WeaponInfo
{
public string Name;
public uint Hash;
public string Name;
}
[StructLayout(LayoutKind.Explicit, Size = 312)]
public struct DlcWeaponData
{
}
class WeaponFix
internal class WeaponFix
{
public Dictionary<uint,string> Bullet=new Dictionary<uint, string>();
public Dictionary<uint, string> Bullet = new Dictionary<uint, string>();
public Dictionary<uint, string> Lazer = new Dictionary<uint, string>();
}
#endregion
internal static class WeaponUtil
{
public const string VehicleWeaponLocation = @"RageCoop\Data\VehicleWeapons.json";
public const string WeaponFixLocation = @"RageCoop\Data\WeaponFixes.json";
public static Dictionary<uint, VehicleWeaponInfo> VehicleWeapons = new Dictionary<uint, VehicleWeaponInfo>();
public static WeaponFix WeaponFix;
public const string VehicleWeaponLocation= @"RageCoop\Data\VehicleWeapons.json";
public const string WeaponFixLocation = @"RageCoop\Data\WeaponFixes.json";
public static readonly HashSet<uint> ExplosiveBullets = new HashSet<uint>
{
(uint)VehicleWeaponHash.PlayerLazer,
(uint)WeaponHash.Railgun,
1638077257
};
public static readonly HashSet<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash>
{
WeaponHash.HomingLauncher,
WeaponHash.RPG,
WeaponHash.Firework,
WeaponHash.UpNAtomizer,
WeaponHash.GrenadeLauncher,
WeaponHash.GrenadeLauncherSmoke,
WeaponHash.CompactGrenadeLauncher,
WeaponHash.FlareGun
};
public static readonly HashSet<VehicleWeaponHash> VehicleProjectileWeapons = new HashSet<VehicleWeaponHash>
{
VehicleWeaponHash.PlaneRocket,
VehicleWeaponHash.SpaceRocket,
VehicleWeaponHash.Tank,
(VehicleWeaponHash)3565779982, // STROMBERG missiles
(VehicleWeaponHash)3169388763 // SCRAMJET missiles
};
static WeaponUtil()
{
if (!File.Exists(VehicleWeaponLocation))
@ -107,17 +140,16 @@ namespace RageCoop.Client
}
// Parse and load to memory
foreach (var w in JsonConvert.DeserializeObject<VehicleWeaponInfo[]>(File.ReadAllText(VehicleWeaponLocation)))
{
VehicleWeapons.Add(w.Hash, w);
}
foreach (var w in JsonConvert.DeserializeObject<VehicleWeaponInfo[]>(
File.ReadAllText(VehicleWeaponLocation))) VehicleWeapons.Add(w.Hash, w);
WeaponFix = JsonConvert.DeserializeObject<WeaponFix>(File.ReadAllText(WeaponFixLocation));
}
public static void DumpWeaponFix(string path = WeaponFixLocation)
{
var P = Game.Player.Character;
var pos = P.Position + Vector3.WorldUp * 3;
var types = new HashSet<int>() { 3 };
var types = new HashSet<int> { 3 };
P.IsInvincible = true;
var fix = new WeaponFix();
foreach (VehicleWeaponHash v in Enum.GetValues(typeof(VehicleWeaponHash)))
@ -129,19 +161,15 @@ namespace RageCoop.Client
asset.Request(1000);
World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
if (!Function.Call<bool>(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10, pos.Y + 10, pos.Z + 10, true))
{
fix.Bullet.Add((uint)v,$"{nameof(VehicleWeaponHash)}.{v}");
}
foreach (var p in World.GetAllProjectiles())
{
p.Delete();
}
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10,
pos.Y + 10, pos.Z + 10, true))
fix.Bullet.Add((uint)v, $"{nameof(VehicleWeaponHash)}.{v}");
foreach (var p in World.GetAllProjectiles()) p.Delete();
Script.Wait(50);
}
}
foreach (WeaponHash w in Enum.GetValues(typeof(WeaponHash)))
{
if (types.Contains(w.GetWeaponDamageType()))
{
Console.Info("Testing: " + w);
@ -149,91 +177,70 @@ namespace RageCoop.Client
asset.Request(1000);
World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
if (!Function.Call<bool>(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10, pos.Y + 10, pos.Z + 10, true))
{
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10,
pos.Y + 10, pos.Z + 10, true))
fix.Bullet.Add((uint)w, $"{nameof(WeaponHash)}.{w}");
}
foreach (var p in World.GetAllProjectiles())
{
p.Delete();
}
foreach (var p in World.GetAllProjectiles()) p.Delete();
Script.Wait(50);
}
}
AddLazer(VehicleWeaponHash.PlayerSavage);
AddLazer(VehicleWeaponHash.StrikeforceCannon);
void AddLazer(dynamic hash)
{
fix.Lazer.Add((uint)hash, $"{hash.GetType().Name}.{hash.ToString()}");
}
File.WriteAllText(path, JsonConvert.SerializeObject(fix, Formatting.Indented));
P.IsInvincible = false;
}
public static void DumpWeaponHashes(string path = VehicleWeaponLocation)
{
Dictionary<uint, string> hashes = new Dictionary<uint, string>();
foreach (var wep in JsonConvert.DeserializeObject<WeaponInfo[]>(HttpHelper.DownloadString("https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/weapons.json")))
var hashes = new Dictionary<uint, string>();
foreach (var wep in JsonConvert.DeserializeObject<WeaponInfo[]>(
HttpHelper.DownloadString(
"https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/weapons.json")))
{
if (!wep.Name.StartsWith("WEAPON")) { continue; }
if (!wep.Name.StartsWith("WEAPON")) continue;
hashes.Add(wep.Hash, wep.Name);
}
var output = "public enum WeaponHash : uint\r\n{";
List<string> lines = new List<string>();
var lines = new List<string>();
foreach (var hash in hashes)
{
lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value, 7)} = {hash.Key.ToHex()}");
}
lines.Sort();
foreach (var l in lines)
{
output += $"\r\n\t{l},";
}
foreach (var l in lines) output += $"\r\n\t{l},";
output += "\r\n}";
File.WriteAllText(path, output);
}
public static void DumpVehicleWeaponHashes(string path = @"RageCoop\Data\VehicleWeaponHash.cs")
{
Dictionary<uint, string> hashes = new Dictionary<uint, string>();
var hashes = new Dictionary<uint, string>();
foreach (var veh in VehicleWeapons.Values)
{
foreach (var hash in veh.Weapons)
{
if (!hashes.ContainsKey(hash.Key))
{
hashes.Add(hash.Key, hash.Value.Name);
}
}
}
foreach (var hash in veh.Weapons)
if (!hashes.ContainsKey(hash.Key))
hashes.Add(hash.Key, hash.Value.Name);
var output = "public enum VehicleWeaponHash : uint\r\n{\r\n\tInvalid = 0xFFFFFFFF,";
List<string> lines = new List<string>();
foreach (var hash in hashes)
{
lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value)} = {hash.Key.ToHex()}");
}
var lines = new List<string>();
foreach (var hash in hashes) lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value)} = {hash.Key.ToHex()}");
lines.Sort();
foreach (var l in lines)
{
output += $"\r\n\t{l},";
}
foreach (var l in lines) output += $"\r\n\t{l},";
output += "\r\n}";
File.WriteAllText(path, output);
}
public static uint GetWeaponFix(uint hash)
{
if(WeaponFix.Bullet.TryGetValue(hash,out var _))
{
return (uint)VehicleWeaponHash.SubcarMg;
}
if (WeaponFix.Lazer.TryGetValue(hash, out var _))
{
return (uint)VehicleWeaponHash.PlayerLazer;
}
if (WeaponFix.Bullet.TryGetValue(hash, out var _)) return (uint)VehicleWeaponHash.SubcarMg;
if (WeaponFix.Lazer.TryGetValue(hash, out var _)) return (uint)VehicleWeaponHash.PlayerLazer;
return hash;
}
public static Dictionary<uint, bool> GetWeaponComponents(this Weapon weapon)
{
Dictionary<uint, bool> result = null;
@ -242,10 +249,7 @@ namespace RageCoop.Client
{
result = new Dictionary<uint, bool>();
foreach (var comp in weapon.Components)
{
result.Add((uint)comp.ComponentHash, comp.Active);
}
foreach (var comp in weapon.Components) result.Add((uint)comp.ComponentHash, comp.Active);
}
return result;
@ -253,90 +257,63 @@ namespace RageCoop.Client
public static Vector3 GetMuzzlePosition(this Ped p)
{
if (p.IsOnTurretSeat())
{
return p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).Position;
}
if (p.IsOnTurretSeat()) return p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).Position;
var wb = p.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
if (wb?.IsValid == true)
{
return wb.Position;
}
if (wb?.IsValid == true) return wb.Position;
return p.Bones[Bone.SkelRightHand].Position;
}
public static float GetWeaponDamage(this Ped P, uint hash)
{
var comp = P.Weapons.Current.Components.GetSuppressorComponent();
return Function.Call<float>(Hash.GET_WEAPON_DAMAGE, hash, comp.Active ? comp.ComponentHash : WeaponComponentHash.Invalid);
return Function.Call<float>(Hash.GET_WEAPON_DAMAGE, hash,
comp.Active ? comp.ComponentHash : WeaponComponentHash.Invalid);
}
public static int GetMuzzleIndex(this Vehicle v, VehicleWeaponHash hash)
{
if (VehicleWeapons.TryGetValue((uint)v.Model.Hash, out var veh) && veh.Weapons.TryGetValue((uint)hash, out var wp))
{
if (VehicleWeapons.TryGetValue((uint)v.Model.Hash, out var veh) &&
veh.Weapons.TryGetValue((uint)hash, out var wp))
return (int)wp.Bones[CoreUtils.RandInt(0, wp.Bones.Length)].BoneIndex;
}
return -1;
}
public static EntityBone GetMuzzleBone(this Vehicle v, VehicleWeaponHash hash)
{
if ((uint)hash == 1422046295) { hash = VehicleWeaponHash.WaterCannon; } // Weird...
if ((uint)hash == 1422046295) hash = VehicleWeaponHash.WaterCannon;
var i = v.GetMuzzleIndex(hash);
if (i == -1) { return null; }
if (i == -1) return null;
return v.Bones[i];
}
public static bool IsUsingProjectileWeapon(this Ped p)
{
var vp = p.VehicleWeapon;
var type = Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, vp);
if (vp != VehicleWeaponHash.Invalid)
{
return type == 3 ? false : VehicleProjectileWeapons.Contains(vp) || (type == 5 && !ExplosiveBullets.Contains((uint)vp));
}
return type == 3
? false
: VehicleProjectileWeapons.Contains(vp) || (type == 5 && !ExplosiveBullets.Contains((uint)vp));
var w = p.Weapons.Current;
return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash);
}
public static int GetWeaponDamageType<T>(this T hash) where T : Enum
{
return Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, hash);
}
public static readonly HashSet<uint> ExplosiveBullets = new HashSet<uint>
{
(uint)VehicleWeaponHash.PlayerLazer,
(uint)WeaponHash.Railgun,
1638077257
};
public static readonly HashSet<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash> {
WeaponHash.HomingLauncher,
WeaponHash.RPG,
WeaponHash.Firework,
WeaponHash.UpNAtomizer,
WeaponHash.GrenadeLauncher,
WeaponHash.GrenadeLauncherSmoke,
WeaponHash.CompactGrenadeLauncher,
WeaponHash.FlareGun,
};
public static readonly HashSet<VehicleWeaponHash> VehicleProjectileWeapons = new HashSet<VehicleWeaponHash> {
VehicleWeaponHash.PlaneRocket,
VehicleWeaponHash.SpaceRocket,
VehicleWeaponHash.Tank,
(VehicleWeaponHash)3565779982, // STROMBERG missiles
(VehicleWeaponHash)3169388763, // SCRAMJET missiles
};
public static string GetFlashFX(this WeaponHash w,bool veh)
public static string GetFlashFX(this WeaponHash w, bool veh)
{
if (veh)
{
switch ((VehicleWeaponHash)w)
{
case VehicleWeaponHash.Tank:
return "muz_tank";
default: return "muz_buzzard";
}
}
switch (w.GetWeaponGroup())
{
case WeaponGroup.SMG:
@ -378,6 +355,7 @@ namespace RageCoop.Client
return "muz_assault_rifle";
}
}
public static WeaponGroup GetWeaponGroup(this WeaponHash hash)
{
return Function.Call<WeaponGroup>(Hash.GET_WEAPONTYPE_GROUP, hash);
@ -397,4 +375,4 @@ namespace RageCoop.Client
public float SweepPitchMax;
}
*/
}
}