diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..74b5b13
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,4 @@
+[*.cs]
+
+# CS0649: Field 'VehicleInfo.Name' is never assigned to, and will always have its default value null
+dotnet_diagnostic.CS0649.severity = silent
diff --git a/Client/DataDumper/Program.cs b/Client/DataDumper/Program.cs
new file mode 100644
index 0000000..2594c3d
--- /dev/null
+++ b/Client/DataDumper/Program.cs
@@ -0,0 +1,27 @@
+using RageCoop.Core;
+using Newtonsoft.Json;
+using System.Data.HashFunction.Jenkins;
+using System;
+
+namespace RageCoop.Client.DataDumper
+{
+ public static class Program
+ {
+
+ static UInt32 Hash(string key)
+ {
+ int i = 0;
+ uint hash = 0;
+ while (i != key.Length)
+ {
+ hash += key[i++];
+ hash += hash << 10;
+ hash ^= hash >> 6;
+ }
+ hash += hash << 3;
+ hash ^= hash >> 11;
+ hash += hash << 15;
+ return hash;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Client/DataDumper/RageCoop.Client.DataDumper.csproj b/Client/DataDumper/RageCoop.Client.DataDumper.csproj
new file mode 100644
index 0000000..c90ff82
--- /dev/null
+++ b/Client/DataDumper/RageCoop.Client.DataDumper.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net6.0
+ enable
+ exe
+ ..\..\bin\Debug\Client.DataDumper
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client/Loader/LoaderContext.cs b/Client/Loader/LoaderContext.cs
index d9404ee..57ea0be 100644
--- a/Client/Loader/LoaderContext.cs
+++ b/Client/Loader/LoaderContext.cs
@@ -189,7 +189,11 @@ namespace RageCoop.Client.Loader
{
CurrentDomain.DoKeyEvent(keys, status);
}
-
+ public override object InitializeLifetimeService()
+ {
+ // Return null to avoid lifetime restriction on the marshaled object.
+ return null;
+ }
public void Dispose()
{
lock (this)
diff --git a/Client/Scripts/DevTools/DevTool.cs b/Client/Scripts/DevTools/DevTool.cs
index 638bdd5..c8c59c9 100644
--- a/Client/Scripts/DevTools/DevTool.cs
+++ b/Client/Scripts/DevTools/DevTool.cs
@@ -1,5 +1,6 @@
using GTA;
using GTA.Math;
+using GTA.Native;
using System;
using System.Drawing;
using System.Threading;
@@ -11,174 +12,80 @@ namespace RageCoop.Client
internal class DevTool : Script
{
public static Vehicle ToMark;
- public static bool UseSecondary = false;
- public static int Current = 0;
- public static int Secondary = 0;
- public static MuzzleDir Direction = MuzzleDir.Forward;
public static Script Instance;
public DevTool()
{
Util.StartUpCheck();
Instance = this;
Tick += OnTick;
- KeyDown += OnKeyDown;
Pause();
}
-
- private void OnKeyDown(object sender, KeyEventArgs e)
- {
- if (ToMark == null || (!ToMark.Exists())) { return; }
- if (DevToolMenu.Menu.SelectedItem == DevToolMenu.boneIndexItem)
- {
-
- switch (e.KeyCode)
- {
- case Keys.Right:
- Current++;
- break;
- case Keys.Left:
- Current--;
- break;
- }
- }
- else if (DevToolMenu.Menu.SelectedItem == DevToolMenu.secondaryBoneIndexItem)
- {
-
- switch (e.KeyCode)
- {
- case Keys.Right:
- Secondary++;
- break;
- case Keys.Left:
- Secondary--;
- break;
- }
- }
- Update();
- }
- private static void Update()
- {
-
- if (Current > ToMark.Bones.Count - 1)
- {
- Current = 0;
- }
- else if (Current < 0)
- {
- Current = ToMark.Bones.Count - 1;
- }
- DevToolMenu.boneIndexItem.AltTitle = Current.ToString();
- if (Secondary > ToMark.Bones.Count - 1)
- {
- Secondary = 0;
- }
- else if (Secondary < 0)
- {
- Secondary = ToMark.Bones.Count - 1;
- }
- DevToolMenu.secondaryBoneIndexItem.AltTitle = Secondary.ToString();
- }
private void OnTick(object sender, EventArgs e)
{
- if (ToMark == null || !ToMark.Exists()) { return; }
- Update();
- Draw(Current);
- if (UseSecondary)
+ var wb = Game.Player.Character?.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
+ if (wb?.IsValid==true)
{
- Draw(Secondary);
+ World.DrawLine(wb.Position, wb.Position + wb.RightVector, Color.Blue);
}
-
- }
- private static void Draw(int boneindex)
- {
- var bone = ToMark.Bones[boneindex];
- World.DrawLine(bone.Position, bone.Position + 2 * bone.ForwardVector, Color.Blue);
- World.DrawLine(bone.Position, bone.Position + 2 * bone.UpVector, Color.Green);
- World.DrawLine(bone.Position, bone.Position + 2 * bone.RightVector, Color.Yellow);
- Vector3 todraw = bone.ForwardVector;
- switch ((byte)Direction)
+ if (ToMark == null) return;
+ if (WeaponUtil.VehicleWeapons.TryGetValue((uint)(int)ToMark.Model, out var info))
{
- case 0:
- todraw = bone.ForwardVector;
- break;
- case 1:
- todraw = bone.RightVector;
- break;
- case 2:
- todraw = bone.UpVector;
- break;
- case 3:
- todraw = bone.ForwardVector * -1;
- break;
- case 4:
- todraw = bone.RightVector * -1;
- break;
- case 5:
- todraw = bone.UpVector * -1;
- break;
- }
- World.DrawLine(bone.Position, bone.Position + 10 * todraw, Color.Red);
- }
- public static void CopyToClipboard(MuzzleDir dir)
- {
-
- if (ToMark != null)
- {
- string s;
- if (UseSecondary)
+ foreach (var ws in info.Weapons)
{
- if ((byte)dir < 3)
+ foreach (var w in ws.Value.Bones)
{
- s = $@"
- // {ToMark.DisplayName}
- case {ToMark.Model.Hash}:
- return BulletsShot%2==0 ? {Current} : {Secondary};
- ";
- }
- else
- {
- s = $@"
- // {ToMark.DisplayName}
- case {ToMark.Model.Hash}:
- return BulletsShot%2==0 ? {Current} : {Secondary};
- ";
+ DrawBone(w.BoneName, ws.Value.Name);
}
}
- else
- {
- if ((byte)dir < 3)
- {
- s = $@"
- // {ToMark.DisplayName}
- case {ToMark.Model.Hash}:
- return {Current};
- ";
- }
- else
- {
- s = $@"
- // {ToMark.DisplayName}
- case {ToMark.Model.Hash}:
- return {Current};
- ";
- }
- }
- Thread thread = new Thread(() => Clipboard.SetText(s));
- thread.SetApartmentState(ApartmentState.STA);
- thread.Start();
- thread.Join();
- GTA.UI.Notification.Show("Copied to clipboard, please paste it on the GitHub issue page!");
+ }
+ }
+ void FindAndDraw()
+ {
+ DrawBone("weapon_1a");
+ DrawBone("weapon_1b");
+ DrawBone("weapon_1c");
+ DrawBone("weapon_1d");
+ DrawBone("weapon_2a");
+ DrawBone("weapon_2b");
+ DrawBone("weapon_2c");
+ DrawBone("weapon_2d");
+ DrawBone("weapon_3a");
+ DrawBone("weapon_3b");
+ DrawBone("weapon_3c");
+ DrawBone("weapon_3d");
+ DrawBone("weapon_4a");
+ DrawBone("weapon_4b");
+ DrawBone("weapon_4c");
+ DrawBone("weapon_4d");
+ DrawBone("weapon_1e");
+ DrawBone("weapon_1f");
+ DrawBone("weapon_1g");
+ DrawBone("weapon_1h");
+ DrawBone("weapon_2e");
+ DrawBone("weapon_2f");
+ DrawBone("weapon_2g");
+ DrawBone("weapon_2h");
+ DrawBone("weapon_3e");
+ DrawBone("weapon_3f");
+ DrawBone("weapon_3g");
+ DrawBone("weapon_3h");
+ DrawBone("weapon_4e");
+ DrawBone("weapon_4f");
+ DrawBone("weapon_4g");
+ DrawBone("weapon_4h");
+ }
+ void DrawBone(string name, string text = null)
+ {
+ text = text ?? name;
+ var b = ToMark.Bones[name];
+ if (b.IsValid)
+ {
+ var start = b.Position;
+ var end = b.Position + b.ForwardVector * 5;
+ World.DrawLine(start, end, Color.AliceBlue);
+ Util.DrawTextFromCoord(end, text, 0.35f);
}
}
}
- internal enum MuzzleDir : byte
- {
- Forward = 0,
- Right = 1,
- Up = 2,
- Backward = 3,
- Left = 4,
- Down = 5,
- }
}
diff --git a/Client/Scripts/Menus/Sub/DevToolMenu.cs b/Client/Scripts/Menus/Sub/DevToolMenu.cs
index a08bdf9..9d441a4 100644
--- a/Client/Scripts/Menus/Sub/DevToolMenu.cs
+++ b/Client/Scripts/Menus/Sub/DevToolMenu.cs
@@ -1,24 +1,37 @@
using GTA;
using LemonUI.Menus;
using System;
+using System.Threading.Tasks;
using System.Drawing;
+using RageCoop.Client.Scripting;
+using Console = GTA.Console;
+using System.IO;
+using Newtonsoft.Json;
+using GTA.Native;
namespace RageCoop.Client
{
+ class AnimDic
+ {
+ public string DictionaryName;
+ public string[] Animations;
+ }
internal static class DevToolMenu
{
- public static NativeMenu Menu = new NativeMenu("RAGECOOP", "DevTool", "Help with the development")
+ const string AnimationsPath = @"RageCoop\Data\animDictsCompact.json";
+ public static NativeMenu Menu = new NativeMenu("RAGECOOP", "DevTool", "Internal testing tools")
{
UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
private static readonly NativeCheckboxItem enableItem = new NativeCheckboxItem("Enable");
+ public static readonly NativeItem dumpItem = new NativeItem("Dump vehicle weapons");
+ public static readonly NativeItem dumpFixItem = new NativeItem("Dump weapon fixes");
+ public static readonly NativeItem dumpWHashItem = new NativeItem("Dump WeaponHash.cs");
+ public static readonly NativeItem getAnimItem = new NativeItem("Get current animation");
+
+ public static readonly NativeItem dumpVWHashItem = new NativeItem("Dump VehicleWeaponHash.cs");
- private static readonly NativeCheckboxItem enableSecondaryItem = new NativeCheckboxItem("Secondary", "Enable if this vehicle have two muzzles");
- public static NativeItem boneIndexItem = new NativeItem("Current bone index");
- public static NativeItem secondaryBoneIndexItem = new NativeItem("Secondary bone index");
- public static NativeItem clipboardItem = new NativeItem("Copy to clipboard");
- public static NativeListItem dirItem = new NativeListItem("Direction");
static DevToolMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
@@ -26,55 +39,70 @@ namespace RageCoop.Client
enableItem.Activated += enableItem_Activated;
enableItem.Checked = false;
- enableSecondaryItem.CheckboxChanged += EnableSecondaryItem_Changed;
- secondaryBoneIndexItem.Enabled = false;
- clipboardItem.Activated += ClipboardItem_Activated;
- dirItem.ItemChanged += DirItem_ItemChanged;
- foreach (var d in Enum.GetValues(typeof(MuzzleDir)))
+ dumpItem.Activated += DumpItem_Activated;
+ dumpVWHashItem.Activated += (s,e)=> WeaponUtil.DumpVehicleWeaponHashes();
+ dumpWHashItem.Activated += (s, e) => WeaponUtil.DumpWeaponHashes();
+ dumpFixItem.Activated += (s, e) => WeaponUtil.DumpWeaponFix();
+ getAnimItem.Activated += (s, e) =>
{
- dirItem.Items.Add((MuzzleDir)d);
- }
- dirItem.SelectedIndex = 0;
+ if (File.Exists(AnimationsPath))
+ {
+ var anims = JsonConvert.DeserializeObject(File.ReadAllText(AnimationsPath));
+ foreach(var anim in anims)
+ {
+ foreach(var a in anim.Animations)
+ {
+ if (Function.Call(Hash.IS_ENTITY_PLAYING_ANIM, Main.P,anim.DictionaryName,a,3))
+ {
+ Console.Info(anim.DictionaryName + " : " + a);
+ GTA.UI.Notification.Show(anim.DictionaryName+" : "+a);
+ }
+ }
+ }
+ }
+ else
+ {
+ GTA.UI.Notification.Show($"~r~{AnimationsPath} not found");
+ }
+ };
Menu.Add(enableItem);
- Menu.Add(boneIndexItem);
- Menu.Add(enableSecondaryItem);
- Menu.Add(secondaryBoneIndexItem);
- Menu.Add(dirItem);
- Menu.Add(clipboardItem);
+ Menu.Add(dumpItem);
+ Menu.Add(dumpVWHashItem);
+ Menu.Add(dumpWHashItem);
+ Menu.Add(dumpFixItem);
+ Menu.Add(getAnimItem);
}
- private static void EnableSecondaryItem_Changed(object sender, EventArgs e)
+ private static void DumpItem_Activated(object sender, EventArgs e)
{
- if (enableSecondaryItem.Checked)
+ dumpItem.Enabled = false;
+ Directory.CreateDirectory(@"RageCoop\Data\tmp");
+ var input = @"RageCoop\Data\tmp\vehicles.json";
+ var dumpLocation = @"RageCoop\Data\VehicleWeapons.json";
+ try
{
- DevTool.UseSecondary = true;
- secondaryBoneIndexItem.Enabled = true;
+
+ VehicleWeaponInfo.Dump(input, dumpLocation);
+ Console.Info($"Weapon info dumped to " + dumpLocation);
}
- else
+ catch (Exception ex)
{
- DevTool.UseSecondary = false;
- secondaryBoneIndexItem.Enabled = false;
+ Console.Error($"~r~" + ex.ToString());
+ }
+ finally
+ {
+ dumpItem.Enabled = true;
}
- }
-
- private static void DirItem_ItemChanged(object sender, ItemChangedEventArgs e)
- {
- DevTool.Direction = dirItem.SelectedItem;
- }
-
- private static void ClipboardItem_Activated(object sender, EventArgs e)
- {
- DevTool.CopyToClipboard(dirItem.SelectedItem);
}
private static void enableItem_Activated(object sender, EventArgs e)
{
if (enableItem.Checked)
{
- DevTool.Instance.Resume();
DevTool.ToMark = Game.Player.Character.CurrentVehicle;
+ DevTool.Instance.Resume();
}
else
{
diff --git a/Client/Scripts/Networking/Receive.cs b/Client/Scripts/Networking/Receive.cs
index 0ff84c9..21343a3 100644
--- a/Client/Scripts/Networking/Receive.cs
+++ b/Client/Scripts/Networking/Receive.cs
@@ -42,11 +42,10 @@ namespace RageCoop.Client
}
};
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
- private static bool _recycle;
public static void ProcessMessage(NetIncomingMessage message)
{
if (message == null) { return; }
- _recycle = true;
+ var _recycle = true;
switch (message.MessageType)
{
case NetIncomingMessageType.StatusChanged:
@@ -293,7 +292,7 @@ namespace RageCoop.Client
{
recycle = false;
// Dispatch to script thread
- API.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; });
+ API.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); return true; });
}
break;
}
diff --git a/Client/Scripts/Properties/AssemblyInfo.cs b/Client/Scripts/Properties/AssemblyInfo.cs
index c803f2e..83ad61a 100644
--- a/Client/Scripts/Properties/AssemblyInfo.cs
+++ b/Client/Scripts/Properties/AssemblyInfo.cs
@@ -16,7 +16,7 @@ using System.Resources;
// Version informationr(
-[assembly: AssemblyVersion("1.5.6.1")]
-[assembly: AssemblyFileVersion("1.5.6.1")]
+[assembly: AssemblyVersion("1.5.6.98")]
+[assembly: AssemblyFileVersion("1.5.6.98")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
diff --git a/Client/Scripts/RageCoop.Client.csproj b/Client/Scripts/RageCoop.Client.csproj
index 4ae9576..c4bed45 100644
--- a/Client/Scripts/RageCoop.Client.csproj
+++ b/Client/Scripts/RageCoop.Client.csproj
@@ -128,6 +128,9 @@
+
+ .editorconfig
+
diff --git a/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs b/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs
index aaad583..f0cac0a 100644
--- a/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs
+++ b/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs
@@ -175,7 +175,7 @@ namespace RageCoop.Client
return;
}
- Vector3 targetPos = MainPed.Bones[Bone.IKHead].Position;
+ Vector3 targetPos = MainPed.Bones[Bone.IKHead].Position + Vector3.WorldUp * 0.5f;
Point toDraw = default;
if (Util.WorldToScreen(targetPos, ref toDraw))
{
@@ -688,7 +688,6 @@ namespace RageCoop.Client
}
if (MainPed.IsOnTurretSeat())
{
- // Function.Call(Hash.SET_VEHICLE_TURRET_SPEED_THIS_FRAME, MainPed.CurrentVehicle, 100);
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z);
}
if (MainPed.VehicleWeapon == VehicleWeaponHash.Invalid)
diff --git a/Client/Scripts/Sync/EntityPool.cs b/Client/Scripts/Sync/EntityPool.cs
index 6bc2022..4d03a1d 100644
--- a/Client/Scripts/Sync/EntityPool.cs
+++ b/Client/Scripts/Sync/EntityPool.cs
@@ -43,7 +43,7 @@ namespace RageCoop.Client
#endregion
public static void Cleanup(bool keepPlayer = true, bool keepMine = true)
{
- foreach (var ped in PedsByID.Values)
+ foreach (var ped in PedsByID.Values.ToArray())
{
if ((keepPlayer && (ped.ID == Main.LocalPlayerID)) || (keepMine && (ped.OwnerID == Main.LocalPlayerID))) { continue; }
RemovePed(ped.ID);
@@ -51,7 +51,7 @@ namespace RageCoop.Client
PedsByID.Clear();
PedsByHandle.Clear();
- foreach (int id in new List(VehiclesByID.Keys))
+ foreach (int id in VehiclesByID.Keys.ToArray())
{
if (keepMine && (VehiclesByID[id].OwnerID == Main.LocalPlayerID)) { continue; }
RemoveVehicle(id);
@@ -59,7 +59,7 @@ namespace RageCoop.Client
VehiclesByID.Clear();
VehiclesByHandle.Clear();
- foreach (var p in ProjectilesByID.Values)
+ foreach (var p in ProjectilesByID.Values.ToArray())
{
if (p.Shooter.ID != Main.LocalPlayerID && p.MainProjectile != null && p.MainProjectile.Exists())
{
diff --git a/Client/Scripts/Sync/SyncEvents.cs b/Client/Scripts/Sync/SyncEvents.cs
index 125c748..d40aa6b 100644
--- a/Client/Scripts/Sync/SyncEvents.cs
+++ b/Client/Scripts/Sync/SyncEvents.cs
@@ -3,6 +3,7 @@ using GTA.Math;
using Lidgren.Network;
using RageCoop.Core;
using System;
+using System.Runtime.InteropServices;
namespace RageCoop.Client
{
@@ -30,9 +31,7 @@ namespace RageCoop.Client
{
// Main.Logger.Trace($"bullet shot:{(WeaponHash)hash}");
-
var start = owner.MainPed.GetMuzzlePosition();
- if (owner.MainPed.IsOnTurretSeat()) { start = owner.MainPed.Bones[Bone.SkelHead].Position; }
if (start.DistanceTo(impactPosition) > 10)
{
// Reduce latency
@@ -43,17 +42,8 @@ namespace RageCoop.Client
public static void TriggerVehBulletShot(uint hash, Vehicle veh, SyncedPed owner)
{
-
int i;
- // ANNIHL
- if (veh.Model.Hash == 837858166)
- {
- Networking.SendVehicleBullet(hash, owner, veh.Bones[35]);
- Networking.SendVehicleBullet(hash, owner, veh.Bones[36]);
- Networking.SendVehicleBullet(hash, owner, veh.Bones[37]);
- Networking.SendVehicleBullet(hash, owner, veh.Bones[38]);
- }
- else if ((i = veh.GetMuzzleIndex()) != -1)
+ if ((i = veh.GetMuzzleIndex(owner.MainPed.VehicleWeapon)) != -1)
{
Networking.SendVehicleBullet(hash, owner, veh.Bones[i]);
}
@@ -72,8 +62,6 @@ namespace RageCoop.Client
#region HANDLE
public static ParticleEffectAsset CorePFXAsset = new ParticleEffectAsset("core");
- private static WeaponAsset _weaponAsset = default;
- private static uint _lastWeaponHash;
private static void HandlePedKilled(Packets.PedKilled p)
{
@@ -94,60 +82,21 @@ namespace RageCoop.Client
}
private static void HandleBulletShot(Vector3 start, Vector3 end, uint weaponHash, int ownerID)
{
- switch (weaponHash)
- {
- // Minigun, not working for some reason
- case (uint)WeaponHash.Minigun:
- weaponHash = 1176362416;
- break;
-
- // Valkyire, not working for some reason
- case 2756787765:
- weaponHash = 1176362416;
- break;
-
- // Tampa3, not working for some reason
- case 3670375085:
- weaponHash = 1176362416;
- break;
-
- // Ruiner2, not working for some reason
- case 50118905:
- weaponHash = 1176362416;
- break;
-
- // SAVAGE
- case 1638077257:
- weaponHash = (uint)VehicleWeaponHash.PlayerLazer;
- break;
-
- case (uint)VehicleWeaponHash.PlayerBuzzard:
- weaponHash = 1176362416;
- break;
- }
-
var p = EntityPool.GetPedByID(ownerID)?.MainPed;
if (p == null) { p = Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); }
+
+ var damage = (int)p.GetWeaponDamage(weaponHash);
+ weaponHash = WeaponUtil.GetWeaponFix(weaponHash);
+
if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); }
- if (_lastWeaponHash != weaponHash)
- {
- _weaponAsset.MarkAsNoLongerNeeded();
- _weaponAsset = new WeaponAsset(weaponHash);
- _lastWeaponHash = weaponHash;
- }
- if (!_weaponAsset.IsLoaded) { _weaponAsset.Request(); }
- World.ShootBullet(start, end, p, _weaponAsset, (int)p.GetWeaponDamage(weaponHash));
+ var asset = new WeaponAsset(weaponHash);
+ if (!asset.IsLoaded) { asset.Request(); }
+ World.ShootBullet(start, end, p, asset, damage);
Prop w;
- if (((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid))
+ var turret = false;
+ if ((((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid)) || (turret = p.IsOnTurretSeat()))
{
- if (p.Weapons.Current.Components.GetSuppressorComponent().Active)
- {
- World.CreateParticleEffectNonLooped(CorePFXAsset, "muz_pistol_silencer", p.GetMuzzlePosition(), w.Rotation, 1);
- }
- else
- {
- World.CreateParticleEffectNonLooped(CorePFXAsset, WeaponUtil.GetFlashFX((WeaponHash)weaponHash), p.GetMuzzlePosition(), w.Rotation, 1);
- }
+ World.CreateParticleEffectNonLooped(CorePFXAsset, p.Weapons.Current.Components.GetSuppressorComponent().Active ? "muz_pistol_silencer" : WeaponUtil.GetFlashFX((WeaponHash)weaponHash, turret), p.GetMuzzlePosition(), turret ? p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).GetRotation() : w.Rotation, 1);
}
}
public static void HandleVehicleBulletShot(Packets.VehicleBulletShot p)
@@ -157,8 +106,8 @@ namespace RageCoop.Client
if (v == null) { return; }
var b = v.Bones[p.Bone];
World.CreateParticleEffectNonLooped(CorePFXAsset,
- WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
- b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1);
+ WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash, true),
+ b.Position, b.GetRotation(), 1);
}
public static void HandleEvent(PacketType type, NetIncomingMessage msg)
{
@@ -166,8 +115,7 @@ namespace RageCoop.Client
{
case PacketType.BulletShot:
{
- Packets.BulletShot p = new Packets.BulletShot();
- p.Deserialize(msg);
+ var p = msg.GetPacket();
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
break;
}
diff --git a/Client/Scripts/Util/PedExtensions.cs b/Client/Scripts/Util/PedExtensions.cs
index fdf5f00..56ad5fa 100644
--- a/Client/Scripts/Util/PedExtensions.cs
+++ b/Client/Scripts/Util/PedExtensions.cs
@@ -335,7 +335,11 @@ namespace RageCoop.Client
{
return v.Bones[35].Position + v.Bones[35].ForwardVector * 100;
}
- if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); }
+ if (p.IsOnTurretSeat())
+ {
+ var b = p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon);
+ return b.Position + b.ForwardVector * 50;
+ }
if (weapon != null)
{
// Not very accurate, but doesn't matter
@@ -459,6 +463,7 @@ namespace RageCoop.Client
public static bool IsTurretSeat(this Vehicle veh, int seat)
{
+ if (Function.Call(Hash.IS_TURRET_SEAT, veh, seat)) { return true; }
if (!Function.Call(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle))
{
return false;
diff --git a/Client/Scripts/Util/Util.cs b/Client/Scripts/Util/Util.cs
index 550497b..088c0b8 100644
--- a/Client/Scripts/Util/Util.cs
+++ b/Client/Scripts/Util/Util.cs
@@ -1,6 +1,7 @@
using GTA;
using GTA.Math;
using GTA.Native;
+using LemonUI.Elements;
using Newtonsoft.Json;
using RageCoop.Core;
using System;
@@ -14,6 +15,10 @@ 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)
@@ -42,6 +47,21 @@ namespace RageCoop.Client
return new SizeF(width, 1080f);
}
}
+ public static void DrawTextFromCoord(Vector3 coord, string text, float scale = 0.5f, Point offset = default)
+ {
+ Point toDraw = default;
+ if (WorldToScreen(coord, ref toDraw))
+ {
+ toDraw.X += offset.X;
+ toDraw.Y += offset.Y;
+ new ScaledText(toDraw, text, scale, GTA.UI.Font.ChaletLondon)
+ {
+ Outline = true,
+ Alignment = GTA.UI.Alignment.Center,
+ Color = Color.White,
+ }.Draw();
+ }
+ }
public static bool WorldToScreen(Vector3 pos, ref Point screenPos)
{
float x, y;
diff --git a/Client/Scripts/Util/WeaponUtil.cs b/Client/Scripts/Util/WeaponUtil.cs
index ca403e5..cb1c5db 100644
--- a/Client/Scripts/Util/WeaponUtil.cs
+++ b/Client/Scripts/Util/WeaponUtil.cs
@@ -1,22 +1,239 @@
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
{
- internal class MuzzleInfo
+ #region DUMP
+
+ class VehicleInfo
{
- public MuzzleInfo(Vector3 pos, Vector3 forward)
- {
- Position = pos;
- ForawardVector = forward;
- }
- public Vector3 Position;
- public Vector3 ForawardVector;
+ public string Name;
+ public string[] Weapons;
+ public uint Hash;
+ public VehicleBone[] Bones;
}
+ class VehicleBone
+ {
+ public uint BoneID;
+ public uint BoneIndex;
+ public string BoneName;
+ }
+ class WeaponBones
+ {
+ public string Name;
+ public VehicleBone[] Bones;
+ }
+ class VehicleWeaponInfo
+ {
+ 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);
+ }
+ Console.Info("Deserialising");
+ var infos = JsonConvert.DeserializeObject(File.ReadAllText(input));
+ Console.Info("Serialising");
+ File.WriteAllText(output,
+ JsonConvert.SerializeObject(
+ 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++)
+ {
+ 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()
+ });
+
+ }
+ return result;
+ }
+ public uint Hash;
+ public string Name;
+ public Dictionary Weapons = new Dictionary();
+ }
+ class WeaponInfo
+ {
+ public string Name;
+ public uint Hash;
+ }
+
+ [StructLayout(LayoutKind.Explicit, Size = 312)]
+ public struct DlcWeaponData
+ {
+ }
+ class WeaponFix
+ {
+ public Dictionary Bullet=new Dictionary();
+ public Dictionary Lazer = new Dictionary();
+ }
+ #endregion
+
internal static class WeaponUtil
{
+ public static Dictionary VehicleWeapons = new Dictionary();
+ public static WeaponFix WeaponFix;
+ public const string VehicleWeaponLocation= @"RageCoop\Data\VehicleWeapons.json";
+ public const string WeaponFixLocation = @"RageCoop\Data\WeaponFixes.json";
+ static WeaponUtil()
+ {
+ if (!File.Exists(VehicleWeaponLocation))
+ {
+ Directory.CreateDirectory(@"RageCoop\Data\tmp");
+ var input = @"RageCoop\Data\tmp\vehicles.json";
+ VehicleWeaponInfo.Dump(input, VehicleWeaponLocation);
+ }
+
+ // Parse and load to memory
+ foreach (var w in JsonConvert.DeserializeObject(File.ReadAllText(VehicleWeaponLocation)))
+ {
+ VehicleWeapons.Add(w.Hash, w);
+ }
+ WeaponFix = JsonConvert.DeserializeObject(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() { 3 };
+ P.IsInvincible = true;
+ var fix = new WeaponFix();
+ foreach (VehicleWeaponHash v in Enum.GetValues(typeof(VehicleWeaponHash)))
+ {
+ Console.Info("Testing: " + v);
+ if (types.Contains(v.GetWeaponDamageType()))
+ {
+ var asset = new WeaponAsset((int)v);
+ asset.Request(1000);
+ World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
+ if (!Function.Call(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
+ !Function.Call(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);
+ var asset = new WeaponAsset((int)w);
+ asset.Request(1000);
+ World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
+ if (!Function.Call(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
+ !Function.Call(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();
+ }
+ 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 hashes = new Dictionary();
+ foreach (var wep in JsonConvert.DeserializeObject(HttpHelper.DownloadString("https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/weapons.json")))
+ {
+ if (!wep.Name.StartsWith("WEAPON")) { continue; }
+ hashes.Add(wep.Hash, wep.Name);
+ }
+ var output = "public enum WeaponHash : uint\r\n{";
+ List lines = new List();
+ 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},";
+ }
+ output += "\r\n}";
+ File.WriteAllText(path, output);
+
+ }
+
+ public static void DumpVehicleWeaponHashes(string path = @"RageCoop\Data\VehicleWeaponHash.cs")
+ {
+ Dictionary hashes = new Dictionary();
+ foreach (var veh in VehicleWeapons.Values)
+ {
+ 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 lines = new List();
+ 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},";
+ }
+ 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;
+ }
+ return hash;
+ }
public static Dictionary GetWeaponComponents(this Weapon weapon)
{
Dictionary result = null;
@@ -36,334 +253,37 @@ namespace RageCoop.Client
public static Vector3 GetMuzzlePosition(this Ped p)
{
- var w = p.Weapons.CurrentWeaponObject;
- if (w != null)
+ if (p.IsOnTurretSeat())
{
- var hash = p.Weapons.Current.Hash;
- if (MuzzleBoneIndexes.ContainsKey(hash)) { return w.Bones[MuzzleBoneIndexes[hash]].Position; }
- return w.Position;
+ return p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).Position;
+ }
+ var wb = p.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
+ if (wb?.IsValid == true)
+ {
+ return wb.Position;
}
return p.Bones[Bone.SkelRightHand].Position;
}
- private static long BulletsShot = 0;
-
public static float GetWeaponDamage(this Ped P, uint hash)
{
var comp = P.Weapons.Current.Components.GetSuppressorComponent();
return Function.Call(Hash.GET_WEAPON_DAMAGE, hash, comp.Active ? comp.ComponentHash : WeaponComponentHash.Invalid);
-
- /*
- if (P.IsInVehicle() && (hash!=(uint)P.Weapons.Current.Hash))
- {
- // This is a vehicle weapon
- P.VehicleWeapon=(VehicleWeaponHash)hash;
- return 100;
- }
- switch (P.Weapons.Current.Group)
- {
- case WeaponGroup.Pistol: return 30;
- case WeaponGroup.AssaultRifle: return 30;
- case WeaponGroup.SMG: return 20;
- case WeaponGroup.MG: return 40;
- case WeaponGroup.Shotgun: return 30;
- case WeaponGroup.Sniper: return 200;
- case WeaponGroup.Heavy: return 30;
- }
- return 0;
- */
}
- public static int GetMuzzleIndex(this Vehicle v)
+ public static int GetMuzzleIndex(this Vehicle v, VehicleWeaponHash hash)
{
- BulletsShot++;
- switch (v.Model.Hash)
+ if (VehicleWeapons.TryGetValue((uint)v.Model.Hash, out var veh) && veh.Weapons.TryGetValue((uint)hash, out var wp))
{
- // cerberus3
- case 1909700336:
- return 53;
-
- // cerberus2
- case 679453769:
- return 54;
-
- // cerberus
- case -801550069:
- return 90;
- /*
- // cerberus (flame)
- case -801550069:
- i=BulletsShot%2==0 ? 89 : 88;
- return new MuzzleInfo(v.Bones[i].Position, v.Bones[i].ForwardVector);
- // cerberus (passenger flame)
- case -801550069:
- i=BulletsShot%2==0 ? 76 : 75;
- return new MuzzleInfo(v.Bones[i].Position, v.Bones[i].ForwardVector);
- */
-
- // ISSI6
- case 1239571361:
- return BulletsShot % 2 == 0 ? 12 : 14;
-
-
- // ISSI5
- case 1537277726:
- return BulletsShot % 2 == 0 ? 30 : 32;
-
-
- // ISSI4
- case 628003514:
- return BulletsShot % 2 == 0 ? 14 : 12;
-
-
- // DOMINATOR6
- case -1293924613:
- return BulletsShot % 2 == 0 ? 51 : 55;
-
-
- // IMPALER4
- case -1744505657:
- return BulletsShot % 2 == 0 ? 64 : 63;
-
-
-
- // IMPERATOR3
- case -755532233:
- return BulletsShot % 2 == 0 ? 86 : 88;
-
-
-
- // SLAMVAN6
- case 1742022738:
- return BulletsShot % 2 == 0 ? 78 : 76;
-
-
- // CHAMPION
- case -915234475:
- return BulletsShot % 2 == 0 ? 60 : 61;
-
-
- // MONSTER4
- case 840387324:
- return BulletsShot % 2 == 0 ? 63 : 65;
-
-
- // BRUTUS2
- case -1890996696:
- return 67;
-
- // BRUISER2
- case -1694081890:
- return BulletsShot % 2 == 0 ? 45 : 51;
-
-
- // TECHNICAL3
- case 1356124575:
- return 67;
-
- // TECHNICAL2
- case 1180875963:
- return 54;
-
- // TECHNICAL
- case -2096818938:
- return 63;
-
- // PATRIOT3
- case -670086588:
- return BulletsShot % 2 == 0 ? 87 : 89;
-
- // NIGHTSHARK
- case 433954513:
- return BulletsShot % 2 == 0 ? 1 : 2;
-
- /*
- // NIGHTSHARK (second)
- case 433954513:
- return BulletsShot%2==0 ? 3 : 4;
- */
-
- // MENACER
- case 2044532910:
- return BulletsShot % 2 == 0 ? 91 : 90;
- /*
- // MENACER
- case 2044532910:
- return new MuzzleInfo(v.Bones[75].Position, v.Bones[75].ForwardVector);
- // MENACER
- case 2044532910:
- return new MuzzleInfo(v.Bones[78].Position, v.Bones[78].ForwardVector);
-
- */
-
- // CARACARA
- case 1254014755:
- return 83;
-
- /*
- // CARACARA
- case 1254014755:
- return BulletsShot%2==0 ? 93 : 94;
- */
-
- // INSURGENT
- case -1860900134:
- return 49;
-
- // INSURGENT3
- case -1924433270:
- return 81;
-
- /*
- // INSURGENT3
- case -1924433270:
- return BulletsShot%2==0 ? 86 : 91;
- */
-
- // BLAZER5
- case -1590337689:
- return BulletsShot % 2 == 0 ? 17 : 18;
-
- // BRUISER
- case 668439077:
- return BulletsShot % 2 == 0 ? 66 : 68;
-
-
- // BRUTUS
- case 2139203625:
- return 84;
-
-
- // MONSTER3
- case 1721676810:
- return BulletsShot % 2 == 0 ? 53 : 55;
-
-
- // BRUISER3
- case -2042350822:
- return BulletsShot % 2 == 0 ? 52 : 50;
-
- // BRUTUS3
- case 2038858402:
- return 84;
-
- // MONSTER5
- case -715746948:
- return BulletsShot % 2 == 0 ? 63 : 65;
-
- // JB7002
- case 394110044:
- return BulletsShot % 2 == 0 ? 54 : 53;
-
- // DOMINATOR5
- case -1375060657:
- return BulletsShot % 2 == 0 ? 35 : 36;
-
- // IMPALER3
- case -1924800695:
- return BulletsShot % 2 == 0 ? 75 : 76;
-
-
- // IMPERATOR2
- case 1637620610:
- return BulletsShot % 2 == 0 ? 97 : 99;
-
-
- // SLAMVAN5
- case 373261600:
- return BulletsShot % 2 == 0 ? 51 : 53;
-
-
- // RUINER2
- case 941494461:
- return BulletsShot % 2 == 0 ? 65 : 66;
-
-
- // TAMPA3
- case -1210451983:
- return 87;
-
- // SCRAMJET
- case -638562243:
- return BulletsShot % 2 == 0 ? 44 : 45;
-
-
- // VIGILANTE
- case -1242608589:
- return BulletsShot % 2 == 0 ? 42 : 43;
-
-
- // ZR380
- case 540101442:
- return BulletsShot % 2 == 0 ? 57 : 63;
-
-
- // ZR3802
- case -1106120762:
- return BulletsShot % 2 == 0 ? 57 : 63;
-
-
- // ZR3803
- case -1478704292:
- return BulletsShot % 2 == 0 ? 53 : 59;
-
-
- // STROMBERG
- case 886810209:
- return BulletsShot % 2 == 0 ? 85 : 84;
-
-
- // SLAMVAN4
- case -2061049099:
- return BulletsShot % 2 == 0 ? 76 : 78;
-
-
- // IMPERATOR
- case 444994115:
- return BulletsShot % 2 == 0 ? 88 : 86;
-
-
- // IMPALER2
- case 1009171724:
- return BulletsShot % 2 == 0 ? 63 : 64;
-
-
- // DOMINATOR4
- case -688189648:
- return BulletsShot % 2 == 0 ? 59 : 60;
-
-
- // SAVAGE
- case -82626025:
- return 30;
-
- // BUZZARD
- case 788747387:
- return BulletsShot % 2 == 0 ? 28 : 23;
-
-
- // ANNIHL
- case 837858166:
- return (int)BulletsShot % 4 + 35;
-
-
- // HYDRA
- case 970385471:
- return BulletsShot % 2 == 0 ? 29 : 28;
-
-
- // STARLING
- case -1700874274:
- return BulletsShot % 2 == 0 ? 24 : 12;
-
-
- // RHINO
- case 782665360:
- return 30;
-
- default:
- return AddOnDataProvider.GetMuzzleIndex(v.Model.Hash);
+ return (int)wp.Bones[CoreUtils.RandInt(0, wp.Bones.Length)].BoneIndex;
}
+ return -1;
+ }
+ public static EntityBone GetMuzzleBone(this Vehicle v, VehicleWeaponHash hash)
+ {
+ var i = v.GetMuzzleIndex(hash);
+ if (i == -1) { return null; }
+ return v.Bones[i];
}
public static bool IsUsingProjectileWeapon(this Ped p)
{
@@ -377,83 +297,16 @@ namespace RageCoop.Client
var w = p.Weapons.Current;
return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash);
}
-
+ public static int GetWeaponDamageType(this T hash) where T : Enum
+ {
+ return Function.Call(Hash.GET_WEAPON_DAMAGE_TYPE, hash);
+ }
public static readonly HashSet ExplosiveBullets = new HashSet
{
(uint)VehicleWeaponHash.PlayerLazer,
(uint)WeaponHash.Railgun,
1638077257
};
-
- public static readonly Dictionary MuzzleBoneIndexes = new Dictionary
- {
- {WeaponHash.HeavySniper,6},
- {WeaponHash.MarksmanRifle,9},
- {WeaponHash.SniperRifle,9},
- {WeaponHash.AdvancedRifle,5},
- {WeaponHash.SpecialCarbine,9},
- {WeaponHash.BullpupRifle,7},
- {WeaponHash.AssaultRifle,9},
- {WeaponHash.CarbineRifle,6},
- {WeaponHash.MachinePistol,5},
- {WeaponHash.SMG,5},
- {WeaponHash.AssaultSMG,6},
- {WeaponHash.CombatPDW,5},
- {WeaponHash.MG,6},
- {WeaponHash.CombatMG,7},
- {WeaponHash.Gusenberg,7},
- {WeaponHash.MicroSMG,10},
- {WeaponHash.APPistol,8},
- {WeaponHash.StunGun,4},
- {WeaponHash.Pistol,8},
- {WeaponHash.CombatPistol,8},
- {WeaponHash.Pistol50,7},
- {WeaponHash.SNSPistol,8},
- {WeaponHash.HeavyPistol,8},
- {WeaponHash.VintagePistol,8},
- {WeaponHash.Railgun,9},
- {WeaponHash.Minigun,5},
- {WeaponHash.Musket,3},
- {WeaponHash.HeavyShotgun,10},
- {WeaponHash.PumpShotgun,11},
- {WeaponHash.SawnOffShotgun,8},
- {WeaponHash.BullpupShotgun,8},
- {WeaponHash.AssaultShotgun,9},
- {WeaponHash.HeavySniperMk2,11},
- {WeaponHash.MarksmanRifleMk2,9},
- {WeaponHash.CarbineRifleMk2,13},
- {WeaponHash.SpecialCarbineMk2,16},
- {WeaponHash.BullpupRifleMk2,8},
- {WeaponHash.CompactRifle,7},
- {WeaponHash.MilitaryRifle,11},
- {WeaponHash.AssaultrifleMk2,17},
- {WeaponHash.MiniSMG,5},
- {WeaponHash.SMGMk2,6},
- {WeaponHash.CombatMGMk2,16},
- {WeaponHash.UnholyHellbringer,4},
- {WeaponHash.PistolMk2,12},
- {WeaponHash.SNSPistolMk2,15},
- {WeaponHash.CeramicPistol,10},
- {WeaponHash.MarksmanPistol,4},
- {WeaponHash.Revolver,7},
- {WeaponHash.RevolverMk2,7},
- {WeaponHash.DoubleActionRevolver,7},
- {WeaponHash.NavyRevolver,7},
- {WeaponHash.PericoPistol,4},
- {WeaponHash.FlareGun,4},
- {WeaponHash.UpNAtomizer,4},
- {WeaponHash.HomingLauncher,5},
- {WeaponHash.CompactGrenadeLauncher,8},
- {WeaponHash.Widowmaker,6},
- {WeaponHash.GrenadeLauncher,3},
- {WeaponHash.RPG,9},
- {WeaponHash.DoubleBarrelShotgun,8},
- {WeaponHash.SweeperShotgun,7},
- {WeaponHash.CombatShotgun,7},
- {WeaponHash.PumpShotgunMk2,7},
-
- };
-
public static readonly HashSet ProjectileWeapons = new HashSet {
WeaponHash.HomingLauncher,
WeaponHash.RPG,
@@ -471,8 +324,18 @@ namespace RageCoop.Client
(VehicleWeaponHash)3565779982, // STROMBERG missiles
(VehicleWeaponHash)3169388763, // SCRAMJET missiles
};
- public static string GetFlashFX(this WeaponHash w)
+ 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:
@@ -510,16 +373,9 @@ namespace RageCoop.Client
case WeaponGroup.FireExtinguisher:
return "weap_extinguisher";
+ default:
+ return "muz_assault_rifle";
}
- switch ((VehicleWeaponHash)w)
- {
- case VehicleWeaponHash.Tank:
- return "muz_tank";
-
- case VehicleWeaponHash.PlayerBuzzard:
- return "muz_buzzard";
- }
- return "muz_assault_rifle";
}
public static WeaponGroup GetWeaponGroup(this WeaponHash hash)
{
diff --git a/Client/Scripts/WorldThread.cs b/Client/Scripts/WorldThread.cs
index 2d44487..ffcb4e3 100644
--- a/Client/Scripts/WorldThread.cs
+++ b/Client/Scripts/WorldThread.cs
@@ -2,6 +2,7 @@
using GTA.Native;
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Core/CoreUtils.cs b/Core/CoreUtils.cs
index 62431eb..2eafd62 100644
--- a/Core/CoreUtils.cs
+++ b/Core/CoreUtils.cs
@@ -19,11 +19,33 @@ using System.Text;
[assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")]
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
+[assembly: InternalsVisibleTo("RageCoop.Client.DataDumper")]
[assembly: InternalsVisibleTo("RageCoop.ResourceBuilder")]
namespace RageCoop.Core
{
internal static class CoreUtils
{
+ private static Random random = new Random();
+ public static string FormatToSharpStyle(string input,int offset=14)
+ {
+ var ss = input.Substring(offset).Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+ // Replace first character with upper case
+ for (int i = 0; i < ss.Length; i++)
+ {
+ var sec = ss[i].ToLower();
+ var head = sec[0];
+ ss[i] = head.ToString().ToUpper() + sec.Remove(0, 1);
+ }
+ return string.Join("", ss);
+ }
+ public static string ToHex(this int value)
+ {
+ return String.Format("0x{0:X}", value);
+ }
+ public static string ToHex(this uint value)
+ {
+ return String.Format("0x{0:X}", value);
+ }
private static readonly HashSet ToIgnore = new HashSet()
{
"RageCoop.Client",
@@ -35,16 +57,37 @@ namespace RageCoop.Core
"ScriptHookVDotNet3",
"ScriptHookVDotNet"
};
+ public static int RandInt(int start,int end)
+ {
+ return random.Next(start, end);
+ }
+ public static string GetTempDirectory(string dir = null)
+ {
+ dir = dir ?? Path.GetTempPath();
+ string path;
+ do
+ {
+ path = Path.Combine(dir, RandomString(10));
+ } while (Directory.Exists(path) || File.Exists(path));
+
+ return path;
+ }
+ public static string RandomString(int length)
+ {
+ const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ return new string(Enumerable.Repeat(chars, length)
+ .Select(s => s[random.Next(s.Length)]).ToArray());
+ }
public static void GetDependencies(Assembly assembly, ref HashSet existing)
{
if (assembly.FullName.StartsWith("System")) { return; }
- foreach(var name in assembly.GetReferencedAssemblies())
+ foreach (var name in assembly.GetReferencedAssemblies())
{
if (name.FullName.StartsWith("System")) { continue; }
try
{
var asm = Assembly.Load(name);
- GetDependencies(asm,ref existing);
+ GetDependencies(asm, ref existing);
}
catch { }
}
diff --git a/Core/Networking/HttpHelper.cs b/Core/Networking/HttpHelper.cs
index 3c7a75e..2b2dd02 100644
--- a/Core/Networking/HttpHelper.cs
+++ b/Core/Networking/HttpHelper.cs
@@ -7,7 +7,7 @@ namespace RageCoop.Core
{
internal static class HttpHelper
{
- public static void DownloadFile(string url, string destination, Action progressCallback)
+ public static void DownloadFile(string url, string destination, Action progressCallback = null)
{
if (File.Exists(destination)) { File.Delete(destination); }
AutoResetEvent ae = new AutoResetEvent(false);
diff --git a/RageCoop-V.sln b/RageCoop-V.sln
index 714563f..ad4a479 100644
--- a/RageCoop-V.sln
+++ b/RageCoop-V.sln
@@ -15,6 +15,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RageCoop.Client.Loader", "C
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{531656CF-7269-488D-B042-741BC96C3941}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{12E29AB7-74C4-4250-8975-C02D7FFC2D7B}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
diff --git a/Server/Properties/AssemblyInfo.cs b/Server/Properties/AssemblyInfo.cs
index d970dca..c3c597b 100644
--- a/Server/Properties/AssemblyInfo.cs
+++ b/Server/Properties/AssemblyInfo.cs
@@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
-[assembly: AssemblyVersion("1.5.6.1")]
-[assembly: AssemblyFileVersion("1.5.6.1")]
+[assembly: AssemblyVersion("1.5.6.12")]
+[assembly: AssemblyFileVersion("1.5.6.12")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
diff --git a/libs/ScriptHookVDotNet.dll b/libs/ScriptHookVDotNet.dll
index 99c840c..a03030f 100644
Binary files a/libs/ScriptHookVDotNet.dll and b/libs/ScriptHookVDotNet.dll differ
diff --git a/libs/ScriptHookVDotNet2.dll b/libs/ScriptHookVDotNet2.dll
index cde7303..554a2fc 100644
Binary files a/libs/ScriptHookVDotNet2.dll and b/libs/ScriptHookVDotNet2.dll differ
diff --git a/libs/ScriptHookVDotNet3.dll b/libs/ScriptHookVDotNet3.dll
index eb132a2..0cf01b8 100644
Binary files a/libs/ScriptHookVDotNet3.dll and b/libs/ScriptHookVDotNet3.dll differ