From 3d1b219c8f429d8370e75bb0a2768c695244a785 Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:46:56 +0300 Subject: [PATCH 1/6] Update Player.cs --- EXILED/Exiled.API/Features/Player.cs | 66 ++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index 0f189f1e28..761025e59e 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -64,6 +64,7 @@ namespace Exiled.API.Features using VoiceChat.Playbacks; using static DamageHandlers.DamageHandlerBase; + using static InventorySystem.Items.Firearms.Modules.AnimatorReloaderModuleBase; using DamageHandlerBase = PlayerStatsSystem.DamageHandlerBase; using Firearm = Items.Firearm; @@ -1803,23 +1804,70 @@ public void TrySetCustomRoleFriendlyFire(string roleTypeId, Dictionary Whether the item was able to be added. public bool TryRemoveCustomeRoleFriendlyFire(string role) => CustomRoleFriendlyFireMultiplier.Remove(role); + /// + /// Forces the player's client to play the weapon reload animation, bypassing server-side checks. + /// + /// if the command to start reloading was sent. Otherwise, . + /// + /// This method does not check if the weapon can actually be reloaded. It only forces the animation and is not guaranteed to result in a successful reload. + /// + public bool ForceReloadWeapon() + { + if (CurrentItem is not Firearm firearm) + { + return false; + } + + firearm.AnimatorReloaderModule.IsReloading = true; + firearm.AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Reload); + return true; + } + /// /// Forces the player to reload their current weapon. /// - /// if firearm was successfully reloaded. Otherwise, . + /// if the firearm was successfully reloaded. Otherwise, . public bool ReloadWeapon() { - if (CurrentItem is Firearm firearm) + if (CurrentItem is not Firearm firearm) { - // TODO not finish - /* - bool result = firearm.Base.Ammo.ServerTryReload(); - Connection.Send(new RequestMessage(firearm.Serial, RequestType.Reload)); - return result; - */ + return false; } - return false; + return firearm.AnimatorReloaderModule.ServerTryReload(); + } + + /// + /// Forces the player's client to play the weapon unload animation, bypassing server-side checks. + /// + /// if the command to start unloading was sent. Otherwise, . + /// + /// This method does not check if the weapon can actually be unloaded. It only forces the animation and is not guaranteed to result in a successful unload. + /// + public bool ForceUnloadWeapon() + { + if (CurrentItem is not Firearm firearm) + { + return false; + } + + firearm.AnimatorReloaderModule.IsUnloading = true; + firearm.AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Unload); + return true; + } + + /// + /// Forces the player to unload their current weapon. + /// + /// if the firearm was successfully unloaded. Otherwise, . + public bool UnloadWeapon() + { + if (CurrentItem is not Firearm firearm) + { + return false; + } + + return firearm.AnimatorReloaderModule.ServerTryUnload(); } /// From f17fe5e4e28330657dce441eddc17411ec5f2585 Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:49:32 +0300 Subject: [PATCH 2/6] Update Firearm.cs --- EXILED/Exiled.API/Features/Items/Firearm.cs | 77 +++++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index eeee66adcd..e717a513e1 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -21,21 +21,15 @@ namespace Exiled.API.Features.Items using Exiled.API.Interfaces; using Exiled.API.Structs; using Extensions; - using InventorySystem; - using InventorySystem.Items; using InventorySystem.Items.Autosync; - using InventorySystem.Items.Firearms; using InventorySystem.Items.Firearms.Attachments; using InventorySystem.Items.Firearms.Attachments.Components; - using InventorySystem.Items.Firearms.BasicMessages; using InventorySystem.Items.Firearms.Modules; - using InventorySystem.Items.Pickups; - using MEC; - using UnityEngine; + + using static InventorySystem.Items.Firearms.Modules.AnimatorReloaderModuleBase; using BaseFirearm = InventorySystem.Items.Firearms.Firearm; using FirearmPickup = Pickups.FirearmPickup; - using Object = UnityEngine.Object; /// /// A wrapper class for . @@ -63,20 +57,26 @@ public Firearm(BaseFirearm itemBase) foreach (ModuleBase module in Base.Modules) { - if (module is IPrimaryAmmoContainerModule primaryAmmoModule) + switch (module) { - PrimaryMagazine ??= (PrimaryMagazine)Magazine.Get(primaryAmmoModule); - continue; - } + case IPrimaryAmmoContainerModule primaryAmmoModule: + PrimaryMagazine ??= (PrimaryMagazine)Magazine.Get(primaryAmmoModule); + break; - if (module is IAmmoContainerModule ammoModule) - { - BarrelMagazine ??= (BarrelMagazine)Magazine.Get(ammoModule); - } + case IAmmoContainerModule ammoModule: + BarrelMagazine ??= (BarrelMagazine)Magazine.Get(ammoModule); + break; - if (module is HitscanHitregModuleBase hitregModule) - { - HitscanHitregModule = hitregModule; + case HitscanHitregModuleBase hitregModule: + HitscanHitregModule = hitregModule; + break; + + case AnimatorReloaderModuleBase animatorReloaderModule: + AnimatorReloaderModule = animatorReloaderModule; + break; + + default: + break; } } } @@ -146,6 +146,11 @@ public static IReadOnlyDictionary public HitscanHitregModuleBase HitscanHitregModule { get; } + /// + /// Gets an animator reloader module for the current firearm. + /// + public AnimatorReloaderModuleBase AnimatorReloaderModule { get; } + /// /// Gets or sets the amount of ammo in the firearm magazine. /// @@ -713,12 +718,38 @@ public void ClearPreferences() /// /// For specific reloading logic you also can use for avaible weapons. /// + public void ForceReload() + { + AnimatorReloaderModule.IsReloading = true; + AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Reload); + } + + /// + /// Attempts to reload the firearm with server-side validation. + /// public void Reload() { - if (Base.TryGetModule(out AnimatorReloaderModuleBase module)) - { - module.StartReloading(); - } + AnimatorReloaderModule.ServerTryReload(); + } + + /// + /// Attempts to unload the firearm with server-side validation. + /// + public void Unload() + { + AnimatorReloaderModule.ServerTryUnload(); + } + + /// + /// Forces the firearm's client-side unload animation, bypassing server-side checks. + /// + /// + /// This only plays the animation and is not guaranteed to result in a successful unload. For server-validated unloading, use . + /// + public void ForceUnload() + { + AnimatorReloaderModule.IsUnloading = true; + AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Unload); } /// From 3c0316f6036cd6d1f9de891901870139b96703ca Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:58:20 +0300 Subject: [PATCH 3/6] validation for nre --- EXILED/Exiled.API/Features/Player.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index 761025e59e..09d591e594 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -1813,7 +1813,7 @@ public void TrySetCustomRoleFriendlyFire(string roleTypeId, Dictionary public bool ForceReloadWeapon() { - if (CurrentItem is not Firearm firearm) + if (CurrentItem is not Firearm firearm || firearm.AnimatorReloaderModule == null) { return false; } @@ -1829,7 +1829,7 @@ public bool ForceReloadWeapon() /// if the firearm was successfully reloaded. Otherwise, . public bool ReloadWeapon() { - if (CurrentItem is not Firearm firearm) + if (CurrentItem is not Firearm firearm || firearm.AnimatorReloaderModule == null) { return false; } @@ -1846,7 +1846,7 @@ public bool ReloadWeapon() /// public bool ForceUnloadWeapon() { - if (CurrentItem is not Firearm firearm) + if (CurrentItem is not Firearm firearm || firearm.AnimatorReloaderModule == null) { return false; } @@ -1862,7 +1862,7 @@ public bool ForceUnloadWeapon() /// if the firearm was successfully unloaded. Otherwise, . public bool UnloadWeapon() { - if (CurrentItem is not Firearm firearm) + if (CurrentItem is not Firearm firearm || firearm.AnimatorReloaderModule == null) { return false; } From b93df51b5bddc1e61f54c84c424f72a1b6f85b89 Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:59:42 +0300 Subject: [PATCH 4/6] Add validation for nre --- EXILED/Exiled.API/Features/Items/Firearm.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index e717a513e1..7f7fbb6973 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -720,6 +720,9 @@ public void ClearPreferences() /// public void ForceReload() { + if (AnimatorReloaderModule == null) + return; + AnimatorReloaderModule.IsReloading = true; AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Reload); } @@ -729,6 +732,9 @@ public void ForceReload() /// public void Reload() { + if (AnimatorReloaderModule == null) + return; + AnimatorReloaderModule.ServerTryReload(); } @@ -737,6 +743,9 @@ public void Reload() /// public void Unload() { + if (AnimatorReloaderModule == null) + return; + AnimatorReloaderModule.ServerTryUnload(); } @@ -748,6 +757,9 @@ public void Unload() /// public void ForceUnload() { + if (AnimatorReloaderModule == null) + return; + AnimatorReloaderModule.IsUnloading = true; AnimatorReloaderModule.SendRpcHeaderWithRandomByte(ReloaderMessageHeader.Unload); } From 150ed36624d0145ef72145ca20a427ad59104b80 Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 22:04:39 +0300 Subject: [PATCH 5/6] Update Firearm.cs --- EXILED/Exiled.API/Features/Items/Firearm.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 7f7fbb6973..400ebac98c 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -757,7 +757,7 @@ public void Unload() /// public void ForceUnload() { - if (AnimatorReloaderModule == null) + if (AnimatorReloaderModule == null) return; AnimatorReloaderModule.IsUnloading = true; From 2ddddf41b0a84e84c125bc0d8a1561072343252b Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Sun, 10 Aug 2025 22:15:45 +0300 Subject: [PATCH 6/6] Update Firearm.cs --- EXILED/Exiled.API/Features/Items/Firearm.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 400ebac98c..46d544eed7 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -730,23 +730,25 @@ public void ForceReload() /// /// Attempts to reload the firearm with server-side validation. /// - public void Reload() + /// if the firearm was successfully reloaded. Otherwise, . + public bool Reload() { if (AnimatorReloaderModule == null) - return; + return false; - AnimatorReloaderModule.ServerTryReload(); + return AnimatorReloaderModule.ServerTryReload(); } /// /// Attempts to unload the firearm with server-side validation. /// - public void Unload() + /// if the firearm was successfully unload. Otherwise, . + public bool Unload() { if (AnimatorReloaderModule == null) - return; + return false; - AnimatorReloaderModule.ServerTryUnload(); + return AnimatorReloaderModule.ServerTryUnload(); } ///