Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions EXILED/Exiled.API/Enums/LockerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,15 @@ public enum LockerType
Adrenaline,

/// <summary>
/// Unknow type of locker.
/// Unknown type of locker.
/// </summary>
Unknow,
Unknown,

/// <summary>
/// Unknown type of locker.
/// </summary>
[Obsolete("Use LockerType.Unknown", true)]
Unknow = Unknown,

/// <summary>
/// MircoHid pedestal.
Expand Down
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Extensions/LockerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static class LockerExtensions
"RegularMedkitStructure" => LockerType.Medkit,
"AdrenalineMedkitStructure" => LockerType.Adrenaline,
"MicroHIDpedestal" => LockerType.MicroHid,
_ => LockerType.Unknow,
_ => LockerType.Unknown,
};
}
}
51 changes: 51 additions & 0 deletions EXILED/Exiled.API/Features/Lockers/Chamber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -188,6 +189,56 @@ public bool IsOpen
/// </summary>
public bool CanInteract => Base.CanInteract;

/// <summary>
/// Adds an item to the current chamber.
/// </summary>
/// <param name="item">The pickup to add.</param>
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;
}

/// <summary>
/// Spawns a specified item from <see cref="AcceptableTypes"/>.
/// </summary>
Expand Down
57 changes: 3 additions & 54 deletions EXILED/Exiled.API/Features/Lockers/Locker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ public Vector3 RandomChamberPosition
/// <param name="zone">The <see cref="ZoneType"/> to filter by. If unspecified, all zones are considered.</param>
/// <param name="lockerType">The <see cref="LockerType"/> to filter by. If unspecified, all locker types are considered.</param>
/// <returns>A random <see cref="Locker"/> object, or <see langword="null"/> if no matching locker is found.</returns>
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<Locker> filteredLockers = List;

if (lockerType != LockerType.Unknow)
if (lockerType != LockerType.Unknown)
filteredLockers = filteredLockers.Where(l => l.Type == lockerType);

if (zone != ZoneType.Unspecified)
Expand All @@ -173,58 +173,7 @@ public Vector3 RandomChamberPosition
/// Adds an item to a randomly selected locker chamber.
/// </summary>
/// <param name="item">The <see cref="Pickup"/> to be added to the locker chamber.</param>
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);

/// <summary>
/// Spawns an item of the specified <see cref="ItemType"/> to the locker by creating a new <see cref="Pickup"/>.
Expand Down
30 changes: 20 additions & 10 deletions EXILED/Exiled.API/Features/Spawn/LockerSpawnPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

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;
Expand Down Expand Up @@ -38,7 +39,7 @@ public class LockerSpawnPoint : SpawnPoint
/// <summary>
/// Gets or sets the type of the <see cref="Locker"/>.
/// </summary>
public LockerType Type { get; set; } = LockerType.Unknow;
public LockerType Type { get; set; } = LockerType.Unknown;

/// <inheritdoc/>
public override float Chance { get; set; }
Expand All @@ -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.");
}

/// <summary>
/// Gets the spawn info.
/// </summary>
/// <param name="locker">The locker to spawn in.</param>
/// <param name="chamber">The chamber to spawn in. Null when <see cref="UseChamber"/> is false.</param>
/// <param name="position">The position to spawn in.</param>
/// <exception cref="NullReferenceException">No locker was found.</exception>
#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));
}
}
}
91 changes: 18 additions & 73 deletions EXILED/Exiled.CustomItems/API/Features/CustomItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -578,86 +574,35 @@ public virtual uint Spawn(IEnumerable<SpawnPoint> 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;
Expand Down