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..92456b8
--- /dev/null
+++ b/NwPluginAPI/Core/Extensions/ItemExtensions.cs
@@ -0,0 +1,296 @@
+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;
+using JetBrains.Annotations;
+
+namespace PluginAPI.Core.Extensions
+{
+ public static class ItemExtensions
+ {
+ ///
+ /// Checks if the current is ammunition.
+ ///
+ /// 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;
+ }
+ }
+
+ ///
+ /// Checks if the current represents 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:
+ case ItemType.GunCom45:
+ case ItemType.GunCrossvec:
+ case ItemType.GunLogicer:
+ 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:
+ return countSpecialWeapons;
+ // Default case: not a firearm
+ default:
+ return false;
+ }
+ }
+
+ ///
+ /// Checks if the current is an 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;
+
+ ///
+ /// Checks if the current is an 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;
+
+ ///
+ /// Checks if the current is an 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 current represents is an throwable item.
+ ///
+ /// The ItemType value to check.
+ ///
+ /// 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;
+
+ ///
+ /// Checks if the current is an keycard.
+ ///
+ /// 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.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;
+ }
+ }
+
+ ///
+ /// Retrieves the associated with the specified .
+ ///
+ /// The value for which to retrieve the .
+ ///
+ /// The associated with the specified if found; otherwise, null.
+ ///
+ public static ItemBase GetItemBase(this ItemType type)
+ {
+ return InventoryItemLoader.TryGetItem(type, out ItemBase itemBase) ? itemBase : null;
+ }
+
+ ///
+ /// Gets a random attachments code for the specified representing a 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())
+ throw new ArgumentException("The provided argument is not a valid firearm.", nameof(firearm));
+
+ return AttachmentsUtils.GetRandomAttachmentsCode(firearm);
+ }
+
+ ///
+ /// Applies attachments to the specified using the provided attachments code.
+ ///
+ /// 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");
+
+ firearm.ApplyAttachmentsCode(attachmentCode, true);
+
+ 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 FirearmStatus(firearm.Status.Ammo, 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 ApplyRandomAttachments(this Firearm firearm)
+ {
+ if (firearm == null)
+ 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));
+ }
+
+ ///
+ /// Try to apply attachment to the specified based on a player's preferences.
+ ///
+ /// 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)
+ return false;
+
+ if(AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out var prefs) && prefs.TryGetValue(firearm.ItemTypeId, out uint attachmentsCode))
+ {
+ 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);
+ }
+ }
+}
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