diff --git a/EXILED/Exiled.API/Enums/LockerType.cs b/EXILED/Exiled.API/Enums/LockerType.cs index b38b592c0a..af62a06cb3 100644 --- a/EXILED/Exiled.API/Enums/LockerType.cs +++ b/EXILED/Exiled.API/Enums/LockerType.cs @@ -46,9 +46,15 @@ public enum LockerType Adrenaline, /// - /// Unknow type of locker. + /// Unknown type of locker. /// - Unknow, + Unknown, + + /// + /// Unknown type of locker. + /// + [Obsolete("Use LockerType.Unknown", true)] + Unknow = Unknown, /// /// MircoHid pedestal. diff --git a/EXILED/Exiled.API/Extensions/LockerExtensions.cs b/EXILED/Exiled.API/Extensions/LockerExtensions.cs index bdf3689bbc..4a6466f636 100644 --- a/EXILED/Exiled.API/Extensions/LockerExtensions.cs +++ b/EXILED/Exiled.API/Extensions/LockerExtensions.cs @@ -48,7 +48,7 @@ public static class LockerExtensions "RegularMedkitStructure" => LockerType.Medkit, "AdrenalineMedkitStructure" => LockerType.Adrenaline, "MicroHIDpedestal" => LockerType.MicroHid, - _ => LockerType.Unknow, + _ => LockerType.Unknown, }; } } diff --git a/EXILED/Exiled.API/Features/Lockers/Chamber.cs b/EXILED/Exiled.API/Features/Lockers/Chamber.cs index 1b499294ae..af4fba905d 100644 --- a/EXILED/Exiled.API/Features/Lockers/Chamber.cs +++ b/EXILED/Exiled.API/Features/Lockers/Chamber.cs @@ -16,6 +16,7 @@ namespace Exiled.API.Features.Lockers using Exiled.API.Extensions; using Exiled.API.Features.Pickups; using Exiled.API.Interfaces; + using InventorySystem.Items.Pickups; using MapGeneration.Distributors; using UnityEngine; @@ -188,6 +189,56 @@ public bool IsOpen /// public bool CanInteract => Base.CanInteract; + /// + /// Adds an item to the current chamber. + /// + /// The pickup to add. + public void AddItem(Pickup item) + { + Transform parent = UseMultipleSpawnpoints && Spawnpoints.Any() + ? Spawnpoints.GetRandomValue() + : Spawnpoint; + + if (IsOpen) + { + item.Transform.SetParent(parent); + + if (!item.IsSpawned) + item.Spawn(); + + return; + } + + // If the item is already spawned on the network, unspawn it before proceeding. + if (item.IsSpawned) + item.UnSpawn(); + + // Set the item's parent transform. + item.Transform.SetParent(parent); + + // Lock the item in place. + item.IsLocked = true; + + // Notify any pickup distributor triggers. + (item.Base as IPickupDistributorTrigger)?.OnDistributed(); + + // If the item has a Rigidbody component, make it kinematic and reset its position and rotation. + if (item.Rigidbody != null) + { + item.Rigidbody.isKinematic = true; + item.Rigidbody.transform.localPosition = Vector3.zero; + item.Rigidbody.transform.localRotation = Quaternion.identity; + + // Add the Rigidbody to the list of bodies to be unfrozen later. + SpawnablesDistributorBase.BodiesToUnfreeze.Add(item.Rigidbody); + } + + Base.Content.Add(item.Base); + item.Spawn(); + if (Base._wasEverOpened) + item.IsLocked = false; + } + /// /// Spawns a specified item from . /// diff --git a/EXILED/Exiled.API/Features/Lockers/Locker.cs b/EXILED/Exiled.API/Features/Lockers/Locker.cs index 653e432d2f..8c7f801d25 100644 --- a/EXILED/Exiled.API/Features/Lockers/Locker.cs +++ b/EXILED/Exiled.API/Features/Lockers/Locker.cs @@ -156,11 +156,11 @@ public Vector3 RandomChamberPosition /// The to filter by. If unspecified, all zones are considered. /// The to filter by. If unspecified, all locker types are considered. /// A random object, or if no matching locker is found. - public static Locker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknow) + public static Locker? Random(ZoneType zone = ZoneType.Unspecified, LockerType lockerType = LockerType.Unknown) { IEnumerable filteredLockers = List; - if (lockerType != LockerType.Unknow) + if (lockerType != LockerType.Unknown) filteredLockers = filteredLockers.Where(l => l.Type == lockerType); if (zone != ZoneType.Unspecified) @@ -173,58 +173,7 @@ public Vector3 RandomChamberPosition /// Adds an item to a randomly selected locker chamber. /// /// The to be added to the locker chamber. - public void AddItem(Pickup item) - { - // Select a random chamber from the available locker chambers. - Chamber chamber = Chambers.GetRandomValue(); - - // Determine the parent transform where the item will be placed. - Transform parentTransform = chamber.UseMultipleSpawnpoints && chamber.Spawnpoints.Any() - ? chamber.Spawnpoints.GetRandomValue() - : chamber.Spawnpoint; - - // If the chamber is open, immediately set the item's parent and spawn it. - if (chamber.IsOpen) - { - item.Transform.SetParent(parentTransform); - - if(!item.IsSpawned) - item.Spawn(); - } - else - { - // If the item is already spawned on the network, unspawn it before proceeding. - if (item.IsSpawned) - item.UnSpawn(); - - // Set the item's parent transform. - item.Transform.SetParent(parentTransform); - - // Lock the item in place. - item.IsLocked = true; - - // Notify any pickup distributor triggers. - (item.Base as IPickupDistributorTrigger)?.OnDistributed(); - - // If the item has a Rigidbody component, make it kinematic and reset its position and rotation. - if (item.Rigidbody != null) - { - item.Rigidbody.isKinematic = true; - item.Rigidbody.transform.localPosition = Vector3.zero; - item.Rigidbody.transform.localRotation = Quaternion.identity; - - // Add the Rigidbody to the list of bodies to be unfrozen later. - SpawnablesDistributorBase.BodiesToUnfreeze.Add(item.Rigidbody); - } - - // If the chamber is configured to spawn items on the first opening, add the item to the list of items to be spawned. - // Otherwise, spawn the item immediately. - if (chamber.InitiallySpawn) - chamber.Base._toBeSpawned.Add(item.Base); - else - ItemDistributor.SpawnPickup(item.Base); - } - } + public void AddItem(Pickup item) => Chambers.GetRandomValue().AddItem(item); /// /// Spawns an item of the specified to the locker by creating a new . diff --git a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs index ad0019ce48..41ff71695e 100644 --- a/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs +++ b/EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs @@ -4,12 +4,13 @@ // Licensed under the CC BY-SA 3.0 license. // // ----------------------------------------------------------------------- + namespace Exiled.API.Features.Spawn { using System; - using System.Linq; using Exiled.API.Enums; + using Exiled.API.Extensions; using Exiled.API.Features.Lockers; using UnityEngine; using YamlDotNet.Serialization; @@ -38,7 +39,7 @@ public class LockerSpawnPoint : SpawnPoint /// /// Gets or sets the type of the . /// - public LockerType Type { get; set; } = LockerType.Unknow; + public LockerType Type { get; set; } = LockerType.Unknown; /// public override float Chance { get; set; } @@ -57,16 +58,25 @@ public override Vector3 Position { get { - Locker foundLocker = Locker.Random(Zone, Type) ?? throw new NullReferenceException("No locker found in the specified zone."); - - // If UseChamber is true, use a random chamber's position. - if (UseChamber) - return foundLocker.RandomChamberPosition; - - // Otherwise, use the Offset if provided, or the locker's position. - return Offset != Vector3.zero ? foundLocker.Transform.TransformPoint(Offset) : foundLocker.Position; + GetSpawningInfo(out _, out _, out Vector3 position); + return position; } set => throw new InvalidOperationException("The position of this type of SpawnPoint cannot be changed."); } + + /// + /// Gets the spawn info. + /// + /// The locker to spawn in. + /// The chamber to spawn in. Null when is false. + /// The position to spawn in. + /// No locker was found. + #nullable enable + public void GetSpawningInfo(out Locker locker, out Chamber? chamber, out Vector3 position) + { + locker = Locker.Random(Zone, Type) ?? throw new NullReferenceException($"No locker found of type {Type} in {Zone}."); + chamber = UseChamber ? locker.Chambers.GetRandomValue() : null; + position = chamber?.GetRandomSpawnPoint() ?? (Offset == Vector3.zero ? locker.Position : locker.Transform.TransformPoint(Offset)); + } } } diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 8aff47f913..356f701c0a 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -17,6 +17,7 @@ namespace Exiled.CustomItems.API.Features using Exiled.API.Extensions; using Exiled.API.Features; using Exiled.API.Features.Attributes; + using Exiled.API.Features.Lockers; using Exiled.API.Features.Pickups; using Exiled.API.Features.Pools; using Exiled.API.Features.Spawn; @@ -25,15 +26,10 @@ namespace Exiled.CustomItems.API.Features using Exiled.Events.EventArgs.Player; using Exiled.Events.EventArgs.Scp914; using Exiled.Loader; - using InventorySystem.Items.Pickups; - using MEC; - using PlayerRoles; - using UnityEngine; - using YamlDotNet.Serialization; using static CustomItems; @@ -578,86 +574,35 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit) if (Loader.Random.NextDouble() * 100 >= spawnPoint.Chance || (limit > 0 && spawned >= limit)) continue; - spawned++; - - /*if (spawnPoint is DynamicSpawnPoint dynamicSpawnPoint && dynamicSpawnPoint.Location == SpawnLocationType.InsideLocker) + Pickup? pickup; + if (spawnPoint is LockerSpawnPoint { UseChamber: true } lockerSpawnPoint) { - for (int i = 0; i < 50; i++) + try { - if (Exiled.API.Features.Lockers.Locker.List is null) - { - Log.Debug($"{nameof(Spawn)}: Locker list is null."); - continue; - } - - Locker locker = Exiled.API.Features.Lockers.Locker.Random(); - - if (locker is null) - { - Log.Debug($"{nameof(Spawn)}: Selected locker is null."); - continue; - } - - if (locker.Loot is null) - { - Log.Debug($"{nameof(Spawn)}: Invalid locker location. Attempting to find a new one.."); - continue; - } - - if (locker.Chambers is null) - { - Log.Debug($"{nameof(Spawn)}: Locker chambers is null"); - continue; - } - - LockerChamber chamber = locker.Chambers[Loader.Random.Next(Mathf.Max(0, locker.Chambers.Length - 1))]; - - if (chamber is null) - { - Log.Debug($"{nameof(Spawn)}: chamber is null"); - continue; - } - - Vector3 position = chamber._spawnpoint.transform.position; - - Pickup? pickup = Spawn(position, null); - if (pickup?.Base is BaseFirearmPickup firearmPickup && this is CustomWeapon customWeapon) - { - firearmPickup.Status = new FirearmStatus(customWeapon.ClipSize, firearmPickup.Status.Flags, firearmPickup.Status.Attachments); - firearmPickup.NetworkStatus = firearmPickup.Status; - } - - Log.Debug($"Spawned {Name} at {position} ({spawnPoint.Name})"); - break; + lockerSpawnPoint.GetSpawningInfo(out _, out Chamber? chamber, out Vector3 position); + pickup = Spawn(position); + chamber?.AddItem(pickup); + } + catch (Exception e) + { + Log.Error($"CustomItem {Name}({Id} failed to spawn: {e.Message})"); + continue; } } else { - Pickup? pickup = Spawn(spawnPoint.Position, null); - if (pickup?.Base is BaseFirearmPickup firearmPickup && this is CustomWeapon customWeapon) - { - firearmPickup.Status = new FirearmStatus(customWeapon.ClipSize, firearmPickup.Status.Flags, firearmPickup.Status.Attachments); - firearmPickup.NetworkStatus = firearmPickup.Status; - } - - Log.Debug($"Spawned {Name} at {spawnPoint.Position} ({spawnPoint.Name})"); - }*/ - - Pickup? pickup = Spawn(spawnPoint.Position); + pickup = Spawn(spawnPoint.Position); + } if (pickup == null) continue; - if (spawnPoint is LockerSpawnPoint { UseChamber: true } lockerSpawnPoint) - { - Exiled.API.Features.Lockers.Locker? foundLocker = Exiled.API.Features.Lockers.Locker.Random(lockerSpawnPoint.Zone, lockerSpawnPoint.Type); - foundLocker?.AddItem(pickup); - } + spawned++; - if (pickup.Is(out Exiled.API.Features.Pickups.FirearmPickup firearmPickup) && this is CustomWeapon customWeapon) + /*if (pickup.Is(out FirearmPickup firearmPickup) && this is CustomWeapon customWeapon) { - // set MaxAmmo if synced TODO - } + // TODO: Set MaxAmmo (if synced) + }*/ } return spawned;