using GTA; using GTA.Math; using GTA.Native; using RageCoop.Core; using System.Collections.Generic; namespace RageCoop.Client { internal static partial class PedExtensions { public static bool IsBetween(this T item, T start, T end) { return Comparer.Default.Compare(item, start) >= 0 && Comparer.Default.Compare(item, end) <= 0; } public static bool Compare(this Dictionary item, Dictionary item2) { if (item == null || item2 == null || item.Count != item2.Count) { return false; } foreach (KeyValuePair pair in item) { if (item2.TryGetValue(pair.Key, out Y value) && Equals(value, pair.Value)) { continue; } // TryGetValue() or Equals failed return false; } // No difference between item and item2 return true; } #region PED public static byte GetPedSpeed(this Ped ped) { if (ped.IsSprinting) { return 3; } if (ped.IsRunning) { return 2; } if (ped.IsWalking) { return 1; } return 0; } // Not sure whether component will always be lesser than 255, whatever... public static byte[] GetPedClothes(this Ped ped) { var result = new byte[36]; for (byte i = 0; i < 12; i++) { result[i]=(byte)Function.Call(Hash.GET_PED_DRAWABLE_VARIATION, ped.Handle, i); result[i+12]=(byte)Function.Call(Hash.GET_PED_TEXTURE_VARIATION, ped.Handle, i); result[i+24]=(byte)Function.Call(Hash.GET_PED_PALETTE_VARIATION, ped.Handle, i); } return result; } public static PedDataFlags GetPedFlags(this Ped ped) { PedDataFlags flags = PedDataFlags.None; if (ped.IsAiming || ped.IsOnTurretSeat()) { flags |= PedDataFlags.IsAiming; } if (ped.IsReloading) { flags |= PedDataFlags.IsReloading; } if (ped.IsJumping) { flags |= PedDataFlags.IsJumping; } // Fake death if (ped.IsRagdoll || (ped.Health==1 && ped.IsPlayer)) { flags |= PedDataFlags.IsRagdoll; } if (ped.IsOnFire) { flags |= PedDataFlags.IsOnFire; } if (ped.IsInParachuteFreeFall) { flags |= PedDataFlags.IsInParachuteFreeFall; } if (ped.ParachuteState == ParachuteState.Gliding) { flags |= PedDataFlags.IsParachuteOpen; } bool climbingLadder = ped.IsTaskActive(TaskType.CTaskGoToAndClimbLadder); if (climbingLadder) { flags |= PedDataFlags.IsOnLadder; } if (ped.IsVaulting && !climbingLadder) { flags |= PedDataFlags.IsVaulting; } if (ped.IsInCover || ped.IsGoingIntoCover) { flags |=PedDataFlags.IsInCover; } if (Function.Call(Hash.GET_PED_STEALTH_MOVEMENT, ped)) { flags |= PedDataFlags.IsInStealthMode; } return flags; } public static string[] GetReloadingAnimation(this Ped ped) { switch (ped.Weapons.Current.Hash) { case WeaponHash.Revolver: case WeaponHash.RevolverMk2: case WeaponHash.DoubleActionRevolver: case WeaponHash.NavyRevolver: return new string[2] { "anim@weapons@pistol@revolver_str", "reload_aim" }; case WeaponHash.APPistol: return new string[2] { "weapons@pistol@ap_pistol_str", "reload_aim" }; case WeaponHash.Pistol50: return new string[2] { "weapons@pistol@pistol_50_str", "reload_aim" }; case WeaponHash.Pistol: case WeaponHash.PistolMk2: case WeaponHash.PericoPistol: case WeaponHash.SNSPistol: case WeaponHash.SNSPistolMk2: case WeaponHash.HeavyPistol: case WeaponHash.VintagePistol: case WeaponHash.CeramicPistol: case WeaponHash.MachinePistol: return new string[2] { "weapons@pistol@pistol_str", "reload_aim" }; case WeaponHash.AssaultRifle: case WeaponHash.AssaultrifleMk2: return new string[2] { "weapons@rifle@hi@assault_rifle_str", "reload_aim" }; case WeaponHash.SniperRifle: return new string[2] { "weapons@rifle@hi@sniper_rifle_str", "reload_aim" }; case WeaponHash.HeavySniper: case WeaponHash.HeavySniperMk2: return new string[2] { "weapons@rifle@lo@sniper_heavy_str", "reload_aim" }; case WeaponHash.PumpShotgun: case WeaponHash.PumpShotgunMk2: return new string[2] { "weapons@rifle@pump_str", "reload_aim" }; case WeaponHash.Railgun: return new string[2] { "weapons@rifle@lo@rail_gun_str", "reload_aim" }; case WeaponHash.SawnOffShotgun: return new string[2] { "weapons@rifle@lo@sawnoff_str", "reload_aim" }; case WeaponHash.AssaultShotgun: return new string[2] { "weapons@rifle@lo@shotgun_assault_str", "reload_aim" }; case WeaponHash.BullpupShotgun: return new string[2] { "weapons@rifle@lo@shotgun_bullpup_str", "reload_aim" }; case WeaponHash.AdvancedRifle: return new string[2] { "weapons@submg@advanced_rifle_str", "reload_aim" }; case WeaponHash.CarbineRifle: case WeaponHash.CarbineRifleMk2: case WeaponHash.CompactRifle: return new string[2] { "weapons@rifle@lo@carbine_str", "reload_aim" }; case WeaponHash.Gusenberg: return new string[2] { "anim@weapons@machinegun@gusenberg_str", "reload_aim" }; case WeaponHash.Musket: return new string[2] { "anim@weapons@musket@musket_str", "reload_aim" }; case WeaponHash.FlareGun: return new string[2] { "anim@weapons@pistol@flare_str", "reload_aim" }; case WeaponHash.SpecialCarbine: case WeaponHash.SpecialCarbineMk2: return new string[2] { "anim@weapons@rifle@lo@spcarbine_str", "reload_aim" }; case WeaponHash.CombatPDW: return new string[2] { "anim@weapons@rifle@lo@pdw_str", "reload_aim" }; case WeaponHash.BullpupRifle: case WeaponHash.BullpupRifleMk2: return new string[2] { "anim@weapons@submg@bullpup_rifle_str", "reload_aim" }; case WeaponHash.AssaultSMG: return new string[2] { "weapons@submg@assault_smg_str", "reload_aim" }; case WeaponHash.MicroSMG: case WeaponHash.MiniSMG: return new string[2] { "weapons@submg@lo@micro_smg_str", "reload_aim" }; case WeaponHash.SMG: case WeaponHash.SMGMk2: return new string[2] { "weapons@rifle@smg_str", "reload_aim" }; case WeaponHash.GrenadeLauncher: case WeaponHash.GrenadeLauncherSmoke: case WeaponHash.CompactGrenadeLauncher: return new string[2] { "weapons@heavy@grenade_launcher_str", "reload_aim" }; case WeaponHash.RPG: case WeaponHash.Firework: return new string[2] { "weapons@heavy@rpg_str", "reload_aim" }; case WeaponHash.CombatMG: case WeaponHash.CombatMGMk2: return new string[2] { "weapons@machinegun@combat_mg_str", "reload_aim" }; 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!"); return null; } } public static VehicleSeat GetNearestSeat(this Ped ped, Vehicle veh, float distanceToignoreDoors = 50f) { float num = 99f; int result = -2; Dictionary dictionary = new Dictionary(); 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) { bool flag = veh.Bones[text].Position != Vector3.Zero; if (flag) { float num2 = ped.Position.DistanceTo(Function.Call(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]); if (flag2) { num = num2; result = dictionary[text]; } } } 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); if (flag) { result = true; } else { bool isDead = veh.GetPedOnSeat(seat).IsDead; if (isDead) { result = true; } else { int num = Function.Call(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[] { ped, veh.GetPedOnSeat(seat) }); bool flag2 = num > 2; if (flag2) { result = true; } } } return result; } public static bool IsTaskActive(this Ped p, TaskType task) { return Function.Call(Hash.GET_IS_TASK_ACTIVE, p.Handle, task); } public static Vector3 GetAimCoord(this Ped p) { var weapon = p.Weapons.CurrentWeaponObject; var v = p.CurrentVehicle; // Rhino if (v!=null && v.Model.Hash==782665360) { return v.Bones[35].Position+v.Bones[35].ForwardVector*100; } if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); } if (weapon!=null) { // Not very accurate, but doesn't matter Vector3 dir = weapon.RightVector; return weapon.Position+dir*20; } return GetLookingCoord(p); } public static Vector3 GetLookingCoord(this Ped p) { EntityBone b = p.Bones[Bone.FacialForehead]; Vector3 v = b.UpVector.Normalized; return b.Position+200*v; } public static void StayInCover(this Ped p) { Function.Call(Hash.TASK_STAY_IN_COVER, p); } public static VehicleSeat GetSeatTryingToEnter(this Ped p) { return (VehicleSeat)Function.Call(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p); } #endregion public static bool IsTurretSeat(this Vehicle veh, int seat) { if (!Function.Call(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); } } }