From 8a89371d54d1d1824610bfc0f676ceeb721c4182 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 26 Jul 2023 19:04:18 -0300 Subject: [PATCH 1/6] I thought it would be shorter # Player - Added `IEnumerable GetPlayers(RoleTypeId roleType)`: Gets a filtered collection of players based on their role type. - Added `IEnumerable GetPlayers(Team team)`: Gets a filtered collection of players based on their team. - Added `Player Get(Collider collider)` and `TryGet(Collider collider, out Player player)`: Methods to get or try getting the player associated with a collider. - Added `Player Get(Footprint footprint)` and `TryGet(Footprint footprint, out Player player)`: Methods to get or try getting the player associated with a footprint. - Added `Footprint Footprint`: Property to get the player's footprint. - Modified `DropAmmo(ItemType item, ushort amount, bool checkMinimals = false)`: Un-commented the method to allow the player to drop ammo. - Modified `SetRole(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin)`: Added an optional parameter to specify the role spawn flags for the role change. # Facility doors - Added a method to try getting a `FacilityDoor` from a `DoorVariant`. - `TryGet(DoorVariant baseDoor, out FacilityDoor facilityDoor)`: Tries to get the `FacilityDoor` associated with the provided `DoorVariant`. If found, the `facilityDoor` parameter will be set; otherwise, it will be `null`. # ItemExtensions - Created an `ItemExtensions` class with various extension methods for `ItemType` and `Firearm`. - Added methods to check if an `ItemType` is of a specific category: `IsAmmo`, `IsFirearm`, `IsMedical`, `IsUtility`, `IsArmor`, `IsKeycard`, `IsThrowable`. - Implemented a method to get a `Firearm`'s `ItemBase` using `InventoryItemLoader`. - Added a method to get a random attachments code for a given `ItemType`. - Introduced a method to apply attachments to a `Firearm`. - Provided a method to apply a set of random attachments directly to a `Firearm`. - Implemented a method to attempt applying a player's attachments preferences to a `Firearm`. --- .../Core/Doors/FacilityBreakableDoor.cs | 18 ++ NwPluginAPI/Core/Doors/FacilityDoor.cs | 19 ++ NwPluginAPI/Core/Doors/FacilityGate.cs | 19 ++ NwPluginAPI/Core/Extensions/ItemExtensions.cs | 215 ++++++++++++++++++ NwPluginAPI/Core/Player.cs | 59 ++++- NwPluginAPI/Core/Zones/FacilityRoom.cs | 4 +- 6 files changed, 329 insertions(+), 5 deletions(-) create mode 100644 NwPluginAPI/Core/Extensions/ItemExtensions.cs diff --git a/NwPluginAPI/Core/Doors/FacilityBreakableDoor.cs b/NwPluginAPI/Core/Doors/FacilityBreakableDoor.cs index 47f9293..5954017 100644 --- a/NwPluginAPI/Core/Doors/FacilityBreakableDoor.cs +++ b/NwPluginAPI/Core/Doors/FacilityBreakableDoor.cs @@ -71,6 +71,24 @@ public void Destroy() DoorEvents.TriggerAction(OriginalObject, DoorAction.Destroyed, null); } + /// + /// Try-get a from a + /// + /// The + /// The if its found otherwise will be + /// A boolean indicating if the was found. + public static bool TryGet(DoorVariant baseDoor, out FacilityBreakableDoor facilityDoor) + { + if (List == null) + { + facilityDoor = null; + return false; + } + + facilityDoor = List.FirstOrDefault(door => door.GameObject == baseDoor.gameObject); + return facilityDoor != null; + } + /// /// Initializes a new instance of the class. /// diff --git a/NwPluginAPI/Core/Doors/FacilityDoor.cs b/NwPluginAPI/Core/Doors/FacilityDoor.cs index dec084f..c1ed554 100644 --- a/NwPluginAPI/Core/Doors/FacilityDoor.cs +++ b/NwPluginAPI/Core/Doors/FacilityDoor.cs @@ -124,6 +124,25 @@ public static IEnumerable Get(Zones.FacilityZone facilityZone) => /// Whether or not the door lock reason is new. public void Lock(DoorLockReason reason, bool enabled) => OriginalObject.ServerChangeLock(reason, enabled); + + /// + /// Try-get a from a + /// + /// The + /// The if its found otherwise will be + /// A boolean indicating if the was found. + public static bool TryGet(DoorVariant baseDoor, out FacilityDoor facilityDoor) + { + if (Facility.Doors == null) + { + facilityDoor = null; + return false; + } + + facilityDoor = Facility.Doors.FirstOrDefault(door => door.GameObject == baseDoor.gameObject); + return facilityDoor != null; + } + /// /// Initializes a new instance of the class. /// diff --git a/NwPluginAPI/Core/Doors/FacilityGate.cs b/NwPluginAPI/Core/Doors/FacilityGate.cs index 2e5919b..3fa379d 100644 --- a/NwPluginAPI/Core/Doors/FacilityGate.cs +++ b/NwPluginAPI/Core/Doors/FacilityGate.cs @@ -6,6 +6,7 @@ namespace PluginAPI.Core.Doors using System.Collections.Generic; using System.Linq; using UnityEngine; + using Interactables.Interobjects.DoorUtils; /// /// Represents a gate. @@ -32,6 +33,24 @@ public class FacilityGate : FacilityDoor /// public Transform[] PryPositions => OriginalObject.PryPositions; + /// + /// Try-get a from a + /// + /// The + /// The if its found otherwise will be + /// A boolean indicating if the was found. + public static bool TryGet(DoorVariant baseDoor, out FacilityGate facilityDoor) + { + if (List == null) + { + facilityDoor = null; + return false; + } + + facilityDoor = List.FirstOrDefault(door => door.GameObject == baseDoor.gameObject); + return facilityDoor != null; + } + /// /// Initializes a new instance of the class. /// diff --git a/NwPluginAPI/Core/Extensions/ItemExtensions.cs b/NwPluginAPI/Core/Extensions/ItemExtensions.cs new file mode 100644 index 0000000..4c23ee0 --- /dev/null +++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs @@ -0,0 +1,215 @@ +using InventorySystem; +using InventorySystem.Items; +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Attachments; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PluginAPI.Core.Extensions +{ + public static class ItemExtensions + { + public static bool IsAmmo(this ItemType type) + { + switch (type) + { + case ItemType.Ammo12gauge: + case ItemType.Ammo44cal: + case ItemType.Ammo556x45: + case ItemType.Ammo762x39: + case ItemType.Ammo9x19: + return true; + } + return false; + } + + /// + /// Gets if the is a fire Firearm. + /// + /// The to check + /// if is , jailbird and microhid count as firearms + /// Returns whether or not the is a firearm. + public static bool IsFirearm(this ItemType type, bool countSpecialWeapons = false) + { + switch (type) + { + case ItemType.GunAK: + case ItemType.GunCOM15: + case ItemType.GunCOM18: + case ItemType.GunCom45: + case ItemType.GunCrossvec: + case ItemType.GunLogicer: + case ItemType.GunRevolver: + case ItemType.GunShotgun: + case ItemType.GunE11SR: + case ItemType.GunFSP9: + return true; + case ItemType.Jailbird: + case ItemType.MicroHID: + { + if (countSpecialWeapons) + return true; + return false; + } + } + return false; + } + + /// + /// Gets if the is a medical item. + /// + /// + /// Returns whether or not the is a medical item. + public static bool IsMedical(this ItemType type) => type is ItemType.Medkit or ItemType.Adrenaline or ItemType.Painkillers or ItemType.SCP500; + + /// + /// Gets if the is a utility item. + /// + /// + /// Returns whether or not the is a utility item. + public static bool IsUtility(this ItemType type) => type is ItemType.Radio or ItemType.Flashlight; + + /// + /// Gets if the is a armor item. + /// + /// + /// Returns whether or not the is a armor item. + public static bool IsArmor(this ItemType type) => type is ItemType.ArmorCombat or ItemType.ArmorHeavy or ItemType.ArmorLight; + + /// + /// Checks if the specified is a throwable item. + /// + /// The to be checked. + /// + /// Returns whether or not the is a throwable item. + /// + public static bool IsThrowable(this ItemType type) => type is ItemType.SCP018 or ItemType.GrenadeFlash or ItemType.GrenadeHE or ItemType.SCP2176; + + /// + /// Gets if the is a keycard item. + /// + /// + /// Returns whether or not the is a keycard item. + public static bool IsKeycard(this ItemType type) + { + switch (type) + { + case ItemType.KeycardChaosInsurgency: + case ItemType.KeycardContainmentEngineer: + case ItemType.KeycardFacilityManager: + case ItemType.KeycardGuard: + case ItemType.KeycardJanitor: + case ItemType.KeycardNTFCommander: + case ItemType.KeycardNTFLieutenant: + case ItemType.KeycardNTFOfficer: + case ItemType.KeycardO5: + case ItemType.KeycardResearchCoordinator: + case ItemType.KeycardScientist: + case ItemType.KeycardZoneManager: + return true; + } + return false; + } + + /// + /// Gets a of a . + /// + /// + /// The or if not found. + public static ItemBase GetItemBase(this ItemType type) + { + if(InventoryItemLoader.TryGetItem(type, out ItemBase itembase)) + return itembase; + + return null; + } + + /// + /// Gets a random attachments code for the specified representing a set of random attachments for a firearm. + /// + /// The of the firearm to be searched for random attachments. + /// The attachments code, a value representing a random set of attachments for the firearm. + public static uint GetRandomAttachments(this ItemType firearm) + { + if (!firearm.IsFirearm()) + throw new ArgumentException("The provided argument is not a valid firearm.", nameof(firearm)); + + return AttachmentsUtils.GetRandomAttachmentsCode(firearm); + } + + /// + /// Applies the specified attachments to the given . + /// + /// The to which the attachments will be applied. + /// The attachments code representing the set of attachments to apply. + public static void ApllyAttachments(this Firearm firearm, uint attachmentCode) + { + if (firearm == null) + throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); + + firearm.ApplyAttachmentsCode(attachmentCode, true); + + FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; + if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) + { + firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; + } + firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + } + + /// + /// Applies a set of random attachments to the specified . + /// + /// The to which random attachments will be applied. + /// Thrown if the is null. + public static void ApllyRandomAttachments(this Firearm firearm) + { + if (firearm == null) + throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); + + firearm.ApplyAttachmentsCode(AttachmentsUtils.GetRandomAttachmentsCode(firearm.ItemTypeId), true); + + FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; + if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) + { + firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; + } + firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + } + + /// + /// Applies the preferences of a 's attachments to a given . + /// + /// The to modify. + /// The whose attachments preferences are to be applied. + /// If this value is true, the weapon will be fully reloaded with ammunition when the attachment is applied. + /// Returns true if the weapon was modified with the attachments; otherwise, false. + public static bool TryApplyAttachmentsPreferences(this Firearm firearm, Player player, bool reloadWeapon = false) + { + if(firearm == null) + throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); + + if(AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out var prefs) && prefs.TryGetValue(firearm.ItemTypeId, out uint attachmentsCode)) + { + firearm.ApplyAttachmentsCode(attachmentsCode, true); + + FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; + if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) + { + firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; + } + + if(reloadWeapon) + firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + else + firearm.Status = new(0, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + return true; + } + return false; + } + + } +} diff --git a/NwPluginAPI/Core/Player.cs b/NwPluginAPI/Core/Player.cs index 47475e0..b3dfcc9 100644 --- a/NwPluginAPI/Core/Player.cs +++ b/NwPluginAPI/Core/Player.cs @@ -118,6 +118,54 @@ public static bool TryGet(IGameComponent component, out T player) where T : P return true; } + /// + /// Gets a filtred by . + /// Can be empty. + /// + /// The player's team + /// The filtered . + public static IEnumerable GetPlayers(Team team) => GetPlayers().Where(p => p.Team == team); + + /// + /// Gets a filtred by . + /// Can be empty. + /// + /// The player's team + /// The filtered . + public static IEnumerable GetPlayers(RoleTypeId roleType) => GetPlayers().Where(p => p.Role == roleType); + + #region Get player from collider + + /// + /// Gets the associated with the , if any. + /// + public static Player Get(Collider collider) => Get(collider.gameObject); + + /// + /// Try-get a associated with the . + /// + /// The + /// The found by the , if there is none it will return . + /// A boolean indicating whether or not a player was found. + public static bool TryGet(Collider collider, out Player player) => TryGet(collider.gameObject, out player); + #endregion + + #region Get player from footprint + + /// + /// Gets the associated with the , if any. + /// + public static Player Get(Footprint footprint) => Get(footprint.Hub); + + /// + /// Try-get a associated with the . + /// + /// The + /// The found by the , if there is none it will return . + /// A boolean indicating whether or not a player was found. + public static bool TryGet(Footprint footprint, out Player player) => TryGet(footprint.Hub, out player); + #endregion + #region Get player from gameobject. /// @@ -581,6 +629,11 @@ public RoleTypeId Role set => ReferenceHub.roleManager.ServerSetRole(value, RoleChangeReason.RemoteAdmin); } + /// + /// Gets the player's . + /// + public Footprint Footprint => new(ReferenceHub); + /// /// Gets player . /// @@ -1200,7 +1253,7 @@ public void RemoveItems(ItemType itemType, int number = 1) /// The amount of ammo which will be dropped. /// Will prevent dropping small amounts of ammo. /// Whether or not the player dropped the ammo successfully. - public List DropAmmo(ItemType item, ushort amount, bool checkMinimals = false) => null;// ReferenceHub.inventory.ServerDropAmmo(item, amount, checkMinimals); + public List DropAmmo(ItemType item, ushort amount, bool checkMinimals = false) => ReferenceHub.inventory.ServerDropAmmo(item, amount, checkMinimals); /// /// Drops all items including ammo. @@ -1248,7 +1301,8 @@ public void SetGroup(UserGroup group) /// /// The which will be set. /// The of role change. - public void SetRole(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin) => ReferenceHub.roleManager.ServerSetRole(newRole, reason); + /// The of role change. + public void SetRole(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin, RoleSpawnFlags spawnFlags = RoleSpawnFlags.All) => ReferenceHub.roleManager.ServerSetRole(newRole, reason, spawnFlags); /// /// Disconnects the player from the server. @@ -1387,6 +1441,5 @@ public bool TryGetComponent(out T component, bool globalSearch = false) where #endregion #endregion - } } \ No newline at end of file diff --git a/NwPluginAPI/Core/Zones/FacilityRoom.cs b/NwPluginAPI/Core/Zones/FacilityRoom.cs index e11538f..29d06ee 100644 --- a/NwPluginAPI/Core/Zones/FacilityRoom.cs +++ b/NwPluginAPI/Core/Zones/FacilityRoom.cs @@ -51,7 +51,7 @@ public class FacilityRoom /// public Quaternion Rotation => Transform.rotation; -#region Get Components + #region Get Components /// public T GetComponent(bool globalSearch = false, bool childSearch = false) where T : MonoBehaviour @@ -119,7 +119,7 @@ public bool TryGetComponent(out T component, bool globalSearch = false, bool return true; } -#endregion + #endregion internal void RegisterDoor(DoorVariant door) { From fe1ba46fd150fd2fa593a12a6d36b3a4c13c66a7 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Wed, 26 Jul 2023 19:16:04 -0300 Subject: [PATCH 2/6] Ups * Added summary to `IsAmmo(this ItemType type)` --- NwPluginAPI/Core/Extensions/ItemExtensions.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NwPluginAPI/Core/Extensions/ItemExtensions.cs b/NwPluginAPI/Core/Extensions/ItemExtensions.cs index 4c23ee0..40d7d3c 100644 --- a/NwPluginAPI/Core/Extensions/ItemExtensions.cs +++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs @@ -12,6 +12,11 @@ namespace PluginAPI.Core.Extensions { public static class ItemExtensions { + /// + /// Gets if the is ammo for a firearm. + /// + /// The to check + /// Returns whether or not the is ammo. public static bool IsAmmo(this ItemType type) { switch (type) From 095be6e7835c90d9f4e6117c6cda1ae58ac6ffba Mon Sep 17 00:00:00 2001 From: SrLicht Date: Fri, 28 Jul 2023 18:52:53 -0300 Subject: [PATCH 3/6] Reverting Changes in FacilityRoom * Visual studio doing things --- NwPluginAPI/Core/Zones/FacilityRoom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NwPluginAPI/Core/Zones/FacilityRoom.cs b/NwPluginAPI/Core/Zones/FacilityRoom.cs index 29d06ee..e11538f 100644 --- a/NwPluginAPI/Core/Zones/FacilityRoom.cs +++ b/NwPluginAPI/Core/Zones/FacilityRoom.cs @@ -51,7 +51,7 @@ public class FacilityRoom /// public Quaternion Rotation => Transform.rotation; - #region Get Components +#region Get Components /// public T GetComponent(bool globalSearch = false, bool childSearch = false) where T : MonoBehaviour @@ -119,7 +119,7 @@ public bool TryGetComponent(out T component, bool globalSearch = false, bool return true; } - #endregion +#endregion internal void RegisterDoor(DoorVariant door) { From a9a296222b9198b5ca164278acaec58079ee43fc Mon Sep 17 00:00:00 2001 From: SrLicht Date: Fri, 28 Jul 2023 18:54:33 -0300 Subject: [PATCH 4/6] Github... please --- NwPluginAPI/Core/Extensions/ItemExtensions.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/NwPluginAPI/Core/Extensions/ItemExtensions.cs b/NwPluginAPI/Core/Extensions/ItemExtensions.cs index 40d7d3c..56e0b75 100644 --- a/NwPluginAPI/Core/Extensions/ItemExtensions.cs +++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs @@ -12,11 +12,7 @@ namespace PluginAPI.Core.Extensions { public static class ItemExtensions { - /// - /// Gets if the is ammo for a firearm. - /// - /// The to check - /// Returns whether or not the is ammo. + public static bool IsAmmo(this ItemType type) { switch (type) From 792570c30a1dc8887276ffa70e4bc8cd85901510 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Fri, 28 Jul 2023 18:55:19 -0300 Subject: [PATCH 5/6] Update my summary github --- NwPluginAPI/Core/Extensions/ItemExtensions.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NwPluginAPI/Core/Extensions/ItemExtensions.cs b/NwPluginAPI/Core/Extensions/ItemExtensions.cs index 56e0b75..40d7d3c 100644 --- a/NwPluginAPI/Core/Extensions/ItemExtensions.cs +++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs @@ -12,7 +12,11 @@ namespace PluginAPI.Core.Extensions { public static class ItemExtensions { - + /// + /// Gets if the is ammo for a firearm. + /// + /// The to check + /// Returns whether or not the is ammo. public static bool IsAmmo(this ItemType type) { switch (type) From fd766706794b87002c969b786d466d99d8b054a0 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Tue, 26 Sep 2023 18:44:18 -0300 Subject: [PATCH 6/6] Update ItemExtensions.cs --- NwPluginAPI/Core/Extensions/ItemExtensions.cs | 248 ++++++++++++------ 1 file changed, 162 insertions(+), 86 deletions(-) diff --git a/NwPluginAPI/Core/Extensions/ItemExtensions.cs b/NwPluginAPI/Core/Extensions/ItemExtensions.cs index 40d7d3c..92456b8 100644 --- a/NwPluginAPI/Core/Extensions/ItemExtensions.cs +++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs @@ -7,40 +7,52 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using JetBrains.Annotations; namespace PluginAPI.Core.Extensions { public static class ItemExtensions { /// - /// Gets if the is ammo for a firearm. + /// Checks if the current is ammunition. /// - /// The to check - /// Returns whether or not the is ammo. + /// The ItemType value to check. + /// + /// true if the specified is an ammunition; otherwise, false. + /// public static bool IsAmmo(this ItemType type) { switch (type) { + // List of ammunition case ItemType.Ammo12gauge: case ItemType.Ammo44cal: case ItemType.Ammo556x45: case ItemType.Ammo762x39: case ItemType.Ammo9x19: return true; + // Default case: not an ammunition + default: + return false; } - return false; } - + /// - /// Gets if the is a fire Firearm. + /// Checks if the current represents a firearm. /// - /// The to check - /// if is , jailbird and microhid count as firearms - /// Returns whether or not the is a firearm. + /// The ItemType value to check. + /// + /// A boolean parameter indicating whether to count special weapons (default is false). + /// If set to true, special weapons like Jailbird and MicroHID are considered firearms; otherwise, they are not. + /// + /// + /// true if the specified is a firearm; otherwise, false. + /// public static bool IsFirearm(this ItemType type, bool countSpecialWeapons = false) { switch (type) { + // List of firearm case ItemType.GunAK: case ItemType.GunCOM15: case ItemType.GunCOM18: @@ -50,93 +62,110 @@ public static bool IsFirearm(this ItemType type, bool countSpecialWeapons = fals case ItemType.GunRevolver: case ItemType.GunShotgun: case ItemType.GunE11SR: + case ItemType.GunFRMG0: + case ItemType.GunA7: case ItemType.GunFSP9: return true; + // Special cases (Jailbird and MicroHID) depend on the value of countSpecialWeapons case ItemType.Jailbird: case ItemType.MicroHID: - { - if (countSpecialWeapons) - return true; - return false; - } + return countSpecialWeapons; + // Default case: not a firearm + default: + return false; } - return false; } - + /// - /// Gets if the is a medical item. + /// Checks if the current is an medical item. /// - /// - /// Returns whether or not the is a medical item. + /// The ItemType value to check. + /// + /// true if the specified is a medical item; otherwise, false. + /// public static bool IsMedical(this ItemType type) => type is ItemType.Medkit or ItemType.Adrenaline or ItemType.Painkillers or ItemType.SCP500; /// - /// Gets if the is a utility item. + /// Checks if the current is an utility item. /// - /// - /// Returns whether or not the is a utility item. + /// The ItemType value to check. + /// + /// true if the specified is a utility item; otherwise, false. + /// public static bool IsUtility(this ItemType type) => type is ItemType.Radio or ItemType.Flashlight; /// - /// Gets if the is a armor item. + /// Checks if the current is an armor item. /// - /// - /// Returns whether or not the is a armor item. + /// The value to check. + /// + /// true if the specified is an armor item; otherwise, false. + /// public static bool IsArmor(this ItemType type) => type is ItemType.ArmorCombat or ItemType.ArmorHeavy or ItemType.ArmorLight; /// - /// Checks if the specified is a throwable item. + /// Checks if the current represents is an throwable item. /// - /// The to be checked. + /// The ItemType value to check. /// - /// Returns whether or not the is a throwable item. + /// true if the specified is a throwable item; otherwise, false. /// public static bool IsThrowable(this ItemType type) => type is ItemType.SCP018 or ItemType.GrenadeFlash or ItemType.GrenadeHE or ItemType.SCP2176; - + /// - /// Gets if the is a keycard item. + /// Checks if the current is an keycard. /// - /// - /// Returns whether or not the is a keycard item. + /// The ItemType value to check. + /// + /// true if the specified is a keycard; otherwise, false. + /// public static bool IsKeycard(this ItemType type) { switch (type) { + // List of keycard case ItemType.KeycardChaosInsurgency: case ItemType.KeycardContainmentEngineer: case ItemType.KeycardFacilityManager: case ItemType.KeycardGuard: case ItemType.KeycardJanitor: - case ItemType.KeycardNTFCommander: - case ItemType.KeycardNTFLieutenant: - case ItemType.KeycardNTFOfficer: + case ItemType.KeycardMTFCaptain: + case ItemType.KeycardMTFOperative: + case ItemType.KeycardMTFPrivate: case ItemType.KeycardO5: case ItemType.KeycardResearchCoordinator: case ItemType.KeycardScientist: case ItemType.KeycardZoneManager: return true; + // Default case: not a keycard + default: + return false; } - return false; } /// - /// Gets a of a . + /// Retrieves the associated with the specified . /// - /// - /// The or if not found. + /// The value for which to retrieve the . + /// + /// The associated with the specified if found; otherwise, null. + /// public static ItemBase GetItemBase(this ItemType type) { - if(InventoryItemLoader.TryGetItem(type, out ItemBase itembase)) - return itembase; - - return null; + return InventoryItemLoader.TryGetItem(type, out ItemBase itemBase) ? itemBase : null; } /// - /// Gets a random attachments code for the specified representing a set of random attachments for a firearm. + /// Gets a random attachments code for the specified representing a firearm. /// - /// The of the firearm to be searched for random attachments. - /// The attachments code, a value representing a random set of attachments for the firearm. + /// The value representing the firearm. + /// + /// A random attachments code for the specified firearm, or an exception if the provided + /// argument is not a valid firearm. + /// + /// + /// Thrown when the provided argument is not a valid firearm. + /// public static uint GetRandomAttachments(this ItemType firearm) { if (!firearm.IsFirearm()) @@ -146,23 +175,32 @@ public static uint GetRandomAttachments(this ItemType firearm) } /// - /// Applies the specified attachments to the given . + /// Applies attachments to the specified using the provided attachments code. /// - /// The to which the attachments will be applied. - /// The attachments code representing the set of attachments to apply. - public static void ApllyAttachments(this Firearm firearm, uint attachmentCode) + /// The to which to apply the attachments. + /// The attachments code to apply to the firearm. + /// If the weapon when applying attachments has a flashlight, do you want to turn it on; default is true + /// + /// Thrown when the provided is null. + /// + public static void ApplyAttachments(this Firearm firearm, uint attachmentCode, bool enableFlashLight = true) { if (firearm == null) - throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); + throw new ArgumentNullException(nameof(firearm), "Firearm is null"); firearm.ApplyAttachmentsCode(attachmentCode, true); - FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; - if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) + var firearmStatusFlags = firearm.Status.Flags; + + if(!firearmStatusFlags.HasFlag(FirearmStatusFlags.MagazineInserted)) + firearmStatusFlags |= FirearmStatusFlags.MagazineInserted; + + if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight) && enableFlashLight) { firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; } - firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + + firearm.Status = new FirearmStatus(firearm.Status.Ammo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); } /// @@ -170,51 +208,89 @@ public static void ApllyAttachments(this Firearm firearm, uint attachmentCode) /// /// The to which random attachments will be applied. /// Thrown if the is null. - public static void ApllyRandomAttachments(this Firearm firearm) + public static void ApplyRandomAttachments(this Firearm firearm) { if (firearm == null) - throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); - - firearm.ApplyAttachmentsCode(AttachmentsUtils.GetRandomAttachmentsCode(firearm.ItemTypeId), true); - - FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; - if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) - { - firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; - } - firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + throw new ArgumentNullException(nameof(firearm), "Firearm is null"); + // Get a random attachments code + var randomAttachments = GetRandomAttachments(firearm.ItemTypeId); + + // Apply the random attachments, preserving the flashlight status if it's enabled + ApplyAttachments(firearm, randomAttachments, firearm.Status.Flags.HasFlag(FirearmStatusFlags.FlashlightEnabled)); } - + /// - /// Applies the preferences of a 's attachments to a given . + /// Try to apply attachment to the specified based on a player's preferences. /// - /// The to modify. - /// The whose attachments preferences are to be applied. - /// If this value is true, the weapon will be fully reloaded with ammunition when the attachment is applied. - /// Returns true if the weapon was modified with the attachments; otherwise, false. - public static bool TryApplyAttachmentsPreferences(this Firearm firearm, Player player, bool reloadWeapon = false) + /// The to which attachments preferences will be applied. + /// The whose preferences are used for attachments. + /// Optional. Indicates whether to preserve the current ammo when applying preferences (default is true). + /// + /// true if attachment preferences were successfully applied; otherwise, false. + /// + public static bool TryApplyAttachmentsPreferences(this Firearm firearm, Player player, bool preserveAmmo = true) { - if(firearm == null) - throw new ArgumentNullException(nameof(Firearm), "Firearm is null"); + if (firearm == null) + return false; if(AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out var prefs) && prefs.TryGetValue(firearm.ItemTypeId, out uint attachmentsCode)) { - firearm.ApplyAttachmentsCode(attachmentsCode, true); - - FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted; - if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight)) - { - firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled; - } - - if(reloadWeapon) - firearm.Status = new(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); - else - firearm.Status = new(0, firearmStatusFlags, firearm.GetCurrentAttachmentsCode()); + firearm.Status = preserveAmmo ? new FirearmStatus(firearm.Status.Ammo, firearm.Status.Flags, firearm.GetCurrentAttachmentsCode()) : new FirearmStatus(0, firearm.Status.Flags, firearm.GetCurrentAttachmentsCode()); + + ApplyAttachments(firearm, attachmentsCode, firearm.Status.Flags.HasFlag(FirearmStatusFlags.FlashlightEnabled)); return true; } return false; } + /// + /// Gets the maximum ammo capacity for the specified . + /// + /// The for which to retrieve the maximum ammo capacity. + /// The maximum ammo capacity for the specified . + public static byte GetMaxAmmo(this Firearm firearm) + { + return firearm == null ? (byte)0 : firearm.AmmoManagerModule.MaxAmmo; + } + + /// + /// Gets the maximum ammo capacity for the specified . + /// + /// The for which to retrieve the maximum ammo capacity. + /// The maximum ammo capacity for the specified . Returns 0 if the item is not a firearm. + public static byte GetMaxAmmo(this ItemType type) + { + var baseItem = GetItemBase(type); + + return baseItem is not Firearm firearm ? (byte)0 : firearm.AmmoManagerModule.MaxAmmo; + } + + /// + /// Reloads the specified to its maximum ammo capacity while preserving attachments and status flags. + /// + /// The to be reloaded. + /// Thrown if the is null. + public static void ReloadFirearm(this Firearm firearm) + { + if (firearm == null) + throw new ArgumentNullException(nameof(firearm), "Firearm is null"); + + // Create a new FirearmStatus with maximum ammo capacity while preserving attachments and status flags + firearm.Status = new FirearmStatus(firearm.AmmoManagerModule.MaxAmmo, firearm.Status.Flags, firearm.Status.Attachments); + } + + /// + /// Removes all ammunition from the specified . + /// + /// The from which to remove all ammunition. + /// Thrown if the is null. + public static void RemoveAmmo(this Firearm firearm) + { + if (firearm == null) + throw new ArgumentNullException(nameof(firearm), "Firearm is null"); + + // Set the ammo count to zero + firearm.Status = new FirearmStatus(0, firearm.Status.Flags, firearm.Status.Attachments); + } } }