Customizable key binding and passenger fix.

This commit is contained in:
sausage 2022-05-23 11:10:11 +08:00
parent 74d9e69fe4
commit 6bacaad1ce
10 changed files with 453 additions and 485 deletions

View File

@ -9,16 +9,15 @@ namespace RageCoop.Client
internal enum TimeStamp
{
AddPeds,
PedTotal,
AddVehicles,
VehicleTotal,
SendPed,
SendPedState,
PedTotal,
UpdatePed,
AddVehicles,
SendVehicle,
SendVehicleState,
UpdatePed,
UpdateVehicle,
CheckPersistent,
VehicleTotal,
CheckProjectiles,
GetAllEntities,
Receive,

View File

@ -17,7 +17,7 @@ namespace RageCoop.Client
/// <summary>
/// Don't use it!
/// </summary>
public class Main : Script
internal class Main : Script
{
private bool _gameLoaded = false;
@ -28,13 +28,13 @@ namespace RageCoop.Client
public static int MyPlayerID=0;
public static bool DisableTraffic = true;
public static bool NPCsAllowed = false;
internal static RelationshipGroup SyncedPedsGroup;
internal static RelationshipGroup SyncedPedsGroup;
public static Settings Settings = null;
public static new Settings Settings = null;
public static Networking MainNetworking = null;
#if !NON_INTERACTIVE
public static MenusMain MainMenu = null;
public static RageCoopMenu MainMenu = null;
#endif
public static Chat MainChat = null;
public static PlayerList MainPlayerList = new PlayerList();
@ -75,7 +75,7 @@ namespace RageCoop.Client
MainNetworking = new Networking();
MainNetworking.Start();
#if !NON_INTERACTIVE
MainMenu = new MenusMain();
MainMenu = new RageCoopMenu();
#endif
MainChat = new Chat();
#if DEBUG
@ -106,7 +106,7 @@ namespace RageCoop.Client
else if (!_gameLoaded && (_gameLoaded = true))
{
#if !NON_INTERACTIVE
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", "Press ~g~F9~s~ to open the menu.");
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP","Welcome!", $"Press ~g~{Main.Settings.MenuKey}~s~ to open the menu.");
#endif
}
@ -176,7 +176,6 @@ namespace RageCoop.Client
}
#if !NON_INTERACTIVE
bool _lastEnteringVeh=false;
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (MainChat.Focused)
@ -189,80 +188,52 @@ namespace RageCoop.Client
Function.Call(Hash.ACTIVATE_FRONTEND_MENU, Function.Call<int>(Hash.GET_HASH_KEY, "FE_MENU_VERSION_SP_PAUSE"), false, 0);
return;
}
switch (e.KeyCode)
if(e.KeyCode == Settings.MenuKey)
{
case Keys.F9:
if (MainMenu.MenuPool.AreAnyVisible)
{
MainMenu.MainMenu.Visible = false;
MainMenu.SubSettings.MainMenu.Visible = false;
}
else
{
MainMenu.MainMenu.Visible = true;
}
break;
case Keys.J:
Game.Player.Character.CurrentVehicle.ApplyForce(new Vector3(0, 0, 100));
Script.Yield();
GTA.UI.Notification.Show(Game.Player.Character.CurrentVehicle.Speed.ToString());
break;
default:
if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo))
{
if (MainNetworking.IsOnServer())
{
ulong currentTimestamp = Util.GetTickCount64();
MainPlayerList.Pressed = (currentTimestamp - MainPlayerList.Pressed) < 5000 ? (currentTimestamp - 6000) : currentTimestamp;
}
}
else if (Game.IsControlJustPressed(GTA.Control.MpTextChatAll))
{
if (MainNetworking.IsOnServer())
{
MainChat.Focused = true;
}
}
break;
}
if (e.KeyCode==Keys.L)
{
GTA.UI.Notification.Show(DumpCharacters());
}
if (e.KeyCode==Keys.I)
{
GTA.UI.Notification.Show(DumpPlayers());
}
if (e.KeyCode==Keys.U)
{
Debug.ShowTimeStamps();
}
if (e.KeyCode==Keys.G)
{
var P = Game.Player.Character;
if (P.IsInVehicle())
if (MainMenu.MenuPool.AreAnyVisible)
{
_lastEnteringVeh=false;
P.Task.LeaveVehicle();
MainMenu.MainMenu.Visible = false;
MainMenu.SubSettings.MainMenu.Visible = false;
}
else
{
var V = World.GetClosestVehicle(P.Position, 50);
if (_lastEnteringVeh)
MainMenu.MainMenu.Visible = true;
}
}
else if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo))
{
if (MainNetworking.IsOnServer())
{
ulong currentTimestamp = Util.GetTickCount64();
MainPlayerList.Pressed = (currentTimestamp - MainPlayerList.Pressed) < 5000 ? (currentTimestamp - 6000) : currentTimestamp;
}
}
else if (Game.IsControlJustPressed(GTA.Control.MpTextChatAll))
{
if (MainNetworking.IsOnServer())
{
MainChat.Focused = true;
}
}
else if (e.KeyCode==Settings.PassengerKey)
{
var P = Game.Player.Character;
if (!P.IsInVehicle())
{
if (P.IsTaskActive(ETasks.EnterVehicle))
{
P.Task.ClearAllImmediately();
_lastEnteringVeh = false;
P.Task.ClearAll();
}
else if (V!=null)
else
{
var seat = Util.getNearestSeat(P, V);
P.Task.EnterVehicle(V, seat);
_lastEnteringVeh=true;
var V = World.GetClosestVehicle(P.Position, 50);
if (V!=null)
{
var seat = Util.GetNearestSeat(P, V);
P.Task.EnterVehicle(V, seat);
}
}
}
}

View File

@ -10,7 +10,7 @@ namespace RageCoop.Client.Menus
/// <summary>
/// Don't use it!
/// </summary>
public class MenusMain
public class RageCoopMenu
{
public ObjectPool MenuPool = new ObjectPool();
@ -20,7 +20,7 @@ namespace RageCoop.Client.Menus
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
#region SUB
public Sub.Settings SubSettings = new Sub.Settings();
public Sub.SettingsMenu SubSettings = new Sub.SettingsMenu();
public Sub.Servers ServerList = new Sub.Servers();
#endregion
@ -39,7 +39,7 @@ namespace RageCoop.Client.Menus
/// <summary>
/// Don't use it!
/// </summary>
public MenusMain()
public RageCoopMenu()
{
MainMenu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
MainMenu.Title.Color = Color.FromArgb(255, 165, 0);
@ -55,13 +55,14 @@ namespace RageCoop.Client.Menus
MainMenu.Add(_serverConnectItem);
MainMenu.AddSubMenu(SubSettings.MainMenu);
MainMenu.AddSubMenu(DebugMenu.Menu);
MainMenu.AddSubMenu(DebugMenu.MainMenu);
MainMenu.Add(_aboutItem);
MenuPool.Add(ServerList.MainMenu);
MenuPool.Add(MainMenu);
MenuPool.Add(SubSettings.MainMenu);
MenuPool.Add(DebugMenu.Menu);
MenuPool.Add(DebugMenu.MainMenu);
MenuPool.Add(DebugMenu.DiagnosticMenu);
}
public void UsernameActivated(object a, System.EventArgs b)

View File

@ -11,7 +11,12 @@ namespace RageCoop.Client
{
internal static class DebugMenu
{
public static NativeMenu Menu = new NativeMenu("RAGECOOP", "Debug", "Debug settings") {
public static NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Debug", "Debug settings") {
UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
public static NativeMenu DiagnosticMenu = new NativeMenu("RAGECOOP", "Diagnostic", "Performence and Diagnostic")
{
UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
@ -24,15 +29,24 @@ namespace RageCoop.Client
catch { }
Update();
};
Menu.Add(d1);
Menu.Opening+=(sender, e) =>Update();
MainMenu.Add(d1);
MainMenu.AddSubMenu(DiagnosticMenu);
MainMenu.Opening+=(sender, e) =>Update();
DiagnosticMenu.Opening+=(sender, e) =>
{
DiagnosticMenu.Clear();
foreach (var pair in Debug.TimeStamps)
{
DiagnosticMenu.Add(new NativeItem(pair.Key.ToString(), pair.Value.ToString(), pair.Value.ToString()));
}
};
Update();
}
private static void Update()
{
d1.AltTitle = SyncParameters.PositioinPrediction.ToString();
}
}

View File

@ -1,6 +1,7 @@
#undef DEBUG
using System.Drawing;
using System.Drawing;
using System;
using System.Windows.Forms;
using GTA;
using LemonUI.Menus;
namespace RageCoop.Client.Menus.Sub
@ -8,7 +9,7 @@ namespace RageCoop.Client.Menus.Sub
/// <summary>
/// Don't use it!
/// </summary>
public class Settings
public class SettingsMenu
{
public NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Settings", "Go to the settings")
{
@ -18,32 +19,55 @@ namespace RageCoop.Client.Menus.Sub
private readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.DisableTraffic);
private readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu);
#if DEBUG
private readonly NativeCheckboxItem _useDebugItem = new NativeCheckboxItem("Debug", Main.UseDebug);
private readonly NativeCheckboxItem _showNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Main.MainNetworking.ShowNetworkInfo);
#endif
private static NativeItem _menuKey = new NativeItem("Menu Key","The key to open menu", Main.Settings.MenuKey.ToString());
private static NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.ToString());
/// <summary>
/// Don't use it!
/// </summary>
public Settings()
public SettingsMenu()
{
MainMenu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
MainMenu.Title.Color = Color.FromArgb(255, 165, 0);
_disableTrafficItem.CheckboxChanged += DisableTrafficCheckboxChanged;
_flipMenuItem.CheckboxChanged += FlipMenuCheckboxChanged;
#if DEBUG
_useDebugItem.CheckboxChanged += UseDebugCheckboxChanged;
_showNetworkInfoItem.CheckboxChanged += ShowNetworkInfoCheckboxChanged;
#endif
_menuKey.Activated+=ChaneMenuKey;
_passengerKey.Activated+=ChangePassengerKey;
MainMenu.Add(_disableTrafficItem);
MainMenu.Add(_flipMenuItem);
#if DEBUG
MainMenu.Add(_useDebugItem);
MainMenu.Add(_showNetworkInfoItem);
#endif
MainMenu.Add(_menuKey);
MainMenu.Add(_passengerKey);
}
private void ChaneMenuKey(object sender, EventArgs e)
{
try
{
Main.Settings.MenuKey =(Keys)Enum.Parse(
typeof(Keys),
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.MenuKey.ToString(), 20));
_menuKey.AltTitle=Main.Settings.MenuKey.ToString();
}
catch { }
}
private void ChangePassengerKey(object sender, EventArgs e)
{
try
{
Main.Settings.PassengerKey =(Keys)Enum.Parse(
typeof(Keys),
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.PassengerKey.ToString(), 20));
_passengerKey.AltTitle=Main.Settings.PassengerKey.ToString();
}
catch { }
}
public void DisableTrafficCheckboxChanged(object a, System.EventArgs b)
@ -53,9 +77,8 @@ namespace RageCoop.Client.Menus.Sub
public void FlipMenuCheckboxChanged(object a, System.EventArgs b)
{
#if !NON_INTERACTIVE
Main.MainMenu.MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
#endif
MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
Main.MainMenu.ServerList.MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
@ -63,25 +86,6 @@ namespace RageCoop.Client.Menus.Sub
Util.SaveSettings();
}
#if DEBUG
public void UseDebugCheckboxChanged(object a, System.EventArgs b)
{
Main.UseDebug = _useDebugItem.Checked;
if (!_useDebugItem.Checked && Main.DebugSyncPed != null)
{
if (Main.DebugSyncPed.Character.Exists())
{
Main.DebugSyncPed.Character.Kill();
Main.DebugSyncPed.Character.Delete();
}
Main.DebugSyncPed = null;
Main.LastFullDebugSync = 0;
Main.Players.Remove(0);
}
}
public void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b)
{
Main.MainNetworking.ShowNetworkInfo = _showNetworkInfoItem.Checked;
@ -92,6 +96,5 @@ namespace RageCoop.Client.Menus.Sub
Main.MainNetworking.BytesSend = 0;
}
}
#endif
}
}

View File

@ -26,8 +26,9 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<DocumentationFile>bin\Debug\CoopClient.xml</DocumentationFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -135,9 +136,9 @@
<Compile Include="Sync\Entities\SyncedVehicle.cs" />
<Compile Include="Main.cs" />
<Compile Include="MapLoader.cs" />
<Compile Include="Menus\MenusMain.cs" />
<Compile Include="Menus\RageCoopMenu.cs" />
<Compile Include="Menus\Sub\Servers.cs" />
<Compile Include="Menus\Sub\Settings.cs" />
<Compile Include="Menus\Sub\SettingsMenu.cs" />
<Compile Include="Networking\Networking.cs" />
<Compile Include="PlayerList.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -1,4 +1,5 @@
#undef DEBUG
using System.Windows.Forms;
namespace RageCoop.Client
{
/// <summary>
@ -29,6 +30,15 @@ namespace RageCoop.Client
/// </summary>
public int LogLevel = 2;
/// <summary>
/// The key to open menu
/// </summary>
public Keys MenuKey { get; set; } = Keys.F9;
/// <summary>
/// The key to enter a vehicle as passenger.
/// </summary>
public Keys PassengerKey { get; set; }=Keys.G;
}
}

View File

@ -71,7 +71,6 @@ namespace RageCoop.Client
private bool _lastRagdoll=false;
private ulong _lastRagdollTime=0;
private bool _lastInCover = false;
private bool _isEnteringVehicle = false;
/// <summary>
/// The latest character model hash (may not have been applied yet)
/// </summary>
@ -334,7 +333,6 @@ namespace RageCoop.Client
private bool _isPlayingAnimation = false;
private string[] _currentAnimation = new string[2] { "", "" };
private float _animationStopTime = 0;
private void DisplayOnFoot()
{
@ -693,8 +691,6 @@ namespace RageCoop.Client
SmoothTransition();
}
private bool StuckDetection = false;
private ulong LastStuckTime;
private void UpdateOnFootPosition(bool updatePosition = true, bool updateRotation = true, bool updateVelocity = true)
{
/*
@ -767,19 +763,6 @@ namespace RageCoop.Client
}
MainPed.ApplyForce(f);
}
private Vector3 GetCalibrationRotation()
{
var r = Rotation-MainPed.Rotation;
if (r.X>180) { r.X=(180-r.X); }
else if (r.X<-180) { r.X=360+r.X; }
if (r.Y>180||r.Y<-180) { r.Y=(180-r.Y); }
else if (r.Y<-180) { r.Y=360+r.Y; }
if (r.Z>180||r.Z<-180) { r.Z=(180-r.Z); }
else if (r.Z<-180) { r.Z=360+r.Z; }
return r;
}
private string LoadAnim(string anim)
{
ulong startTime = Util.GetTickCount64();
@ -797,41 +780,5 @@ namespace RageCoop.Client
return anim;
}
#endregion
#region QUEUED ACTIONS
#region ENTER-VEHICLE
/// <summary>
/// Tell this character to enter a vehicle and do callback when the task is finished.
/// </summary>
/// <param name="veh"></param>
/// <param name="seat"></param>
/// <param name="callback"> callback function to be invoked when done, accepting first argument that indicates whether the operation is successful.</param>
public void EnterVehicle(SyncedVehicle veh,VehicleSeat seat, Action<bool> callback)
{
Main.QueueAction(new Func<bool>(() =>
{
MainPed.Task.EnterVehicle(veh.MainVehicle, seat,-1,2,EnterVehicleFlags.AllowJacking|EnterVehicleFlags.WarpToDoor);
return true;
}));
int i = 0;
float maxwait = Game.FPS*5;
Main.QueueAction(new Func<bool>(() =>
{
i++;
if ((_lastEnteringVehicle && !MainPed.IsGettingIntoVehicle)||i>maxwait)
{
callback(MainPed.IsInVehicle());
_isEnteringVehicle=false;
return true;
}
_lastEnteringVehicle = MainPed.IsGettingIntoVehicle;
return false;
}));
}
#endregion
#endregion
}
}

View File

@ -338,7 +338,7 @@ namespace RageCoop.Client
}
Function.Call(Hash.SET_VEHICLE_BRAKE_LIGHTS, MainVehicle.Handle, BrakeLightsOn);
MainVehicle.SetVehicleDamageModel(DamageModel);
MainVehicle.SetDamageModel(DamageModel);
}
MainVehicle.LockStatus=LockStatus;

View File

@ -12,9 +12,13 @@ using System.Diagnostics;
namespace RageCoop.Client
{
public enum ETasks
/// <summary>
///
/// </summary>
internal enum ETasks
{
CLIMB_LADDER = 47
CLIMB_LADDER = 47,
EnterVehicle = 160,
}
internal static partial class Util
@ -105,6 +109,180 @@ namespace RageCoop.Client
}
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;
}
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;
}
foreach (KeyValuePair<T, Y> 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 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 = DegToRad(rotation.Z);
double x = 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 Model ModelRequest(this int hash)
{
Model model = new Model(hash);
if (!model.IsValid)
{
//GTA.UI.Notification.Show("~y~Not valid!");
return null;
}
if (!model.IsLoaded)
{
return model.Request(1000) ? model : null;
}
return model;
}
#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;
}
public static Dictionary<byte, short> GetPedClothes(this Ped ped)
{
Dictionary<byte, short> result = new Dictionary<byte, short>();
for (byte i = 0; i < 11; i++)
{
short mod = Function.Call<short>(Hash.GET_PED_DRAWABLE_VARIATION, ped.Handle, i);
result.Add(i, mod);
}
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;
}
if (ped.IsRagdoll)
{
flags |= PedDataFlags.IsRagdoll;
}
if (ped.IsOnFire)
{
flags |= PedDataFlags.IsOnFire;
}
if (ped.IsInParachuteFreeFall)
{
flags |= PedDataFlags.IsInParachuteFreeFall;
}
if (ped.ParachuteState == ParachuteState.Gliding)
{
flags |= PedDataFlags.IsParachuteOpen;
}
if (Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER)) // USING_LADDER
{
flags |= PedDataFlags.IsOnLadder;
}
if (ped.IsVaulting && !Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER))
{
flags |= PedDataFlags.IsVaulting;
}
if (ped.IsInCover || ped.IsGoingIntoCover)
{
flags |=PedDataFlags.IsInCover;
}
return flags;
}
public static string[] GetReloadingAnimation(this Ped ped)
{
switch (ped.Weapons.Current.Hash)
@ -188,94 +366,134 @@ namespace RageCoop.Client
case WeaponHash.MG:
return new string[2] { "weapons@machinegun@mg_str", "reload_aim" };
default:
GTA.UI.Notification.Show($"~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 Model ModelRequest(this int hash)
public static VehicleSeat GetNearestSeat(Ped ped, Vehicle veh, float distanceToignoreDoors = 50f)
{
Model model = new Model(hash);
if (!model.IsValid)
float num = 99f;
int result = -2;
Dictionary<string, int> 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)
{
//GTA.UI.Notification.Show("~y~Not valid!");
return null;
}
if (!model.IsLoaded)
{
return model.Request(1000) ? model : null;
}
return model;
}
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;
}
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;
}
foreach (KeyValuePair<T, Y> pair in item)
{
if (item2.TryGetValue(pair.Key, out Y value) && Equals(value, pair.Value))
bool flag = veh.Bones[text].Position != Vector3.Zero;
if (flag)
{
continue;
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]);
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<int>(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[]
{
ped,
veh.GetPedOnSeat(seat)
});
bool flag2 = num > 2;
if (flag2)
{
result = true;
}
}
// TryGetValue() or Equals failed
return false;
}
// No difference between item and item2
return true;
return result;
}
public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, ulong currentTime, int duration)
public static bool IsTaskActive(this Ped p,ETasks task)
{
return new Vector3()
return Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, p.Handle, task);
}
public static Vector3 GetAimCoord(this Ped p)
{
var weapon = p.Weapons.CurrentWeaponObject;
if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); }
if (weapon!=null)
{
X = LinearFloatLerp(start.X, end.X, currentTime, duration),
Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration),
Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration),
};
}
// Not very accurate, but doesn't matter
Vector3 dir = weapon.RightVector;
return weapon.Position+dir*20;
public static float LinearFloatLerp(float start, float end, ulong currentTime, int duration)
{
return (end - start) * currentTime / duration + start;
}
/*
RaycastResult result = World.Raycast(weapon.Position+dir, weapon.Position+dir*10000, IntersectFlags.Everything, p.IsInVehicle() ? (Entity)p : p.CurrentVehicle);
public static float Lerp(float from, float to, float fAlpha)
{
return (from * (1.0f - fAlpha)) + (to * fAlpha); //from + (to - from) * fAlpha
}
public static byte GetPedSpeed(this Ped ped)
{
if (ped.IsSprinting)
{
return 3;
if (result.DidHit)
{
return result.HitPosition;
}
else
{
return weapon.Position+dir*20;
}
*/
}
if (ped.IsRunning)
{
return 2;
}
if (ped.IsWalking)
{
return 1;
}
return 0;
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<int>(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p);
}
public static Vector3 GetMuzzlePosition(this Ped p)
{
var w = p.Weapons.CurrentWeaponObject;
if (w!=null)
{
var hash = p.Weapons.Current.Hash;
if (MuzzleBoneIndexes.ContainsKey(hash)) { return w.Bones[MuzzleBoneIndexes[hash]].Position; }
return w.Position;
}
return p.Bones[Bone.SkelRightHand].Position;
}
#endregion
#region VEHICLE
public static VehicleDataFlags GetVehicleFlags(this Vehicle veh)
{
@ -336,63 +554,6 @@ namespace RageCoop.Client
return flags;
}
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;
}
if (ped.IsRagdoll)
{
flags |= PedDataFlags.IsRagdoll;
}
if (ped.IsOnFire)
{
flags |= PedDataFlags.IsOnFire;
}
if (ped.IsInParachuteFreeFall)
{
flags |= PedDataFlags.IsInParachuteFreeFall;
}
if (ped.ParachuteState == ParachuteState.Gliding)
{
flags |= PedDataFlags.IsParachuteOpen;
}
if (Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER)) // USING_LADDER
{
flags |= PedDataFlags.IsOnLadder;
}
if (ped.IsVaulting && !Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER))
{
flags |= PedDataFlags.IsVaulting;
}
if (ped.IsInCover || ped.IsGoingIntoCover)
{
flags |=PedDataFlags.IsInCover;
}
return flags;
}
public static bool HasFlag(this PedDataFlags flagToCheck,PedDataFlags flag)
{
@ -404,16 +565,6 @@ namespace RageCoop.Client
return (flagToCheck & flag)!=0;
}
public static Dictionary<byte, short> GetPedClothes(this Ped ped)
{
Dictionary<byte, short> result = new Dictionary<byte, short>();
for (byte i = 0; i < 11; i++)
{
short mod = Function.Call<short>(Hash.GET_PED_DRAWABLE_VARIATION, ped.Handle, i);
result.Add(i, mod);
}
return result;
}
public static Dictionary<uint, bool> GetWeaponComponents(this Weapon weapon)
{
@ -508,32 +659,8 @@ namespace RageCoop.Client
}
return ps;
}
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 SyncedPed GetSyncEntity(this Ped p)
{
if(p == null) { return null; }
var c = EntityPool.GetPedByHandle(p.Handle);
if(c==null) { EntityPool.Add(c=new SyncedPed(p)); }
return c;
}
public static SyncedVehicle GetSyncEntity(this Vehicle veh)
{
if(veh == null) { return null; }
var v=EntityPool.GetVehicleByHandle(veh.Handle);
if (v==null) { EntityPool.Add(v=new SyncedVehicle(veh)); }
return v;
}
public static void SetVehicleDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true)
public static void SetDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true)
{
for (int i = 0; i < 8; i++)
{
@ -590,132 +717,46 @@ namespace RageCoop.Client
veh.IsRightHeadLightBroken = model.RightHeadLightBroken > 0;
}
#endregion
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 SyncedPed GetSyncEntity(this Ped p)
{
if(p == null) { return null; }
var c = EntityPool.GetPedByHandle(p.Handle);
if(c==null) { EntityPool.Add(c=new SyncedPed(p)); }
return c;
}
public static SyncedVehicle GetSyncEntity(this Vehicle veh)
{
if(veh == null) { return null; }
var v=EntityPool.GetVehicleByHandle(veh.Handle);
if (v==null) { EntityPool.Add(v=new SyncedVehicle(veh)); }
return v;
}
public static double DegToRad(double deg)
{
return deg * Math.PI / 180.0;
}
public static Vector3 RotationToDirection(Vector3 rotation)
{
double z = DegToRad(rotation.Z);
double x = 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)
};
}
public static VehicleSeat getNearestSeat(Ped ped, Vehicle veh, float distanceToignoreDoors=50f)
{
float num = 99f;
int result = -2;
Dictionary<string, int> 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)
{
bool 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]);
if (flag2)
{
num = num2;
result = dictionary[text];
}
}
}
return (VehicleSeat)result;
}
public static bool IsSeatUsableByPed(Ped ped, Vehicle veh, int _seat, bool allowJacking=false)
{
/*
*/
if (!allowJacking)
{
return veh.IsSeatFree((VehicleSeat)_seat);
}
else
{
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<int>(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[]
{
ped,
veh.GetPedOnSeat(seat)
});
bool flag2 = num > 2;
if (flag2)
{
result = true;
}
}
}
return result;
}
}
public static Vector3 GetAimCoord(this Ped p)
{
var weapon = p.Weapons.CurrentWeaponObject;
if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); }
if (weapon!=null)
{
Vector3 dir = weapon.RightVector;
return weapon.Position+dir*20;
RaycastResult result = World.Raycast(weapon.Position+dir, weapon.Position+dir*10000, IntersectFlags.Everything, p.IsInVehicle() ? (Entity)p : p.CurrentVehicle);
if (result.DidHit)
{
return result.HitPosition;
}
else
{
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 bool IsWeapon(this Entity e)
{
return WeaponModels.Contains(e.Model);
}
public static bool IsTurretSeat(this Vehicle veh, int seat)
{
if (!Function.Call<bool>(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle))
@ -761,14 +802,6 @@ namespace RageCoop.Client
if (P.CurrentVehicle == null) { return false; }
return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex);
}
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<int>(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p);
}
public static readonly Model[] WeaponModels = Weapon.GetAllModels();
@ -793,17 +826,6 @@ namespace RageCoop.Client
}
return damage;
}
public static Vector3 GetMuzzlePosition(this Ped p)
{
var w = p.Weapons.CurrentWeaponObject;
if (w!=null)
{
var hash = p.Weapons.Current.Hash;
if (MuzzleBoneIndexes.ContainsKey(hash)) { return w.Bones[MuzzleBoneIndexes[hash]].Position; }
return w.Position;
}
return p.Bones[Bone.SkelRightHand].Position;
}
public static readonly Dictionary<WeaponHash, int> MuzzleBoneIndexes = new Dictionary<WeaponHash, int>
{
{WeaponHash.HeavySniper,6},