Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Exiled::CustomItems] [Exiled::API] [Exiled::CustomRoles] Adding news Spawnpoints, Wrapper for Locker and added LockerType #77

Merged
merged 24 commits into from
Sep 2, 2024
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
50 changes: 50 additions & 0 deletions EXILED/Exiled.API/Enums/LockerType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// -----------------------------------------------------------------------
// <copyright file="LockerType.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Enums
{
/// <summary>
/// Unique identifier for different types of <see cref="Features.Lockers.Locker"/>s.
/// </summary>
public enum LockerType
{
/// <summary>
/// The pedestal used by SCP items.
/// </summary>
Pedestal,

/// <summary>
/// Large weapon locker.
/// </summary>
LargeGun,

/// <summary>
/// Locker for rifles, known as a rifle rack.
/// </summary>
RifleRack,

/// <summary>
/// Miscellaneous locker for various items.
/// </summary>
Misc,

/// <summary>
/// Locker that contains medkits.
/// </summary>
Medkit,

/// <summary>
/// Locker that contains adrenaline.
/// </summary>
Adrenaline,

/// <summary>
/// Unknow type of locker.
/// </summary>
Unknow,
}
}
4 changes: 3 additions & 1 deletion EXILED/Exiled.API/Enums/SpawnLocationType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Enums
{
using System;

/// <summary>
/// All of the valid spawn location types.
/// </summary>
Expand Down Expand Up @@ -150,6 +151,7 @@ public enum SpawnLocationType
/// <summary>
/// Inside a random locker on the map.
/// </summary>
[Obsolete("Use LockerSpawnPoint instead")]
InsideLocker,
}
}
43 changes: 43 additions & 0 deletions EXILED/Exiled.API/Extensions/LockerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// -----------------------------------------------------------------------
// <copyright file="LockerExtensions.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Extensions
{
using System;

using Exiled.API.Enums;
using MapGeneration.Distributors;

/// <summary>
/// A set of extensions for <see cref="Enums.LockerType"/>.
/// </summary>
public static class LockerExtensions
{
/// <summary>
/// Gets the <see cref="LockerType"/> from the given <see cref="Locker"/> object.
/// </summary>
/// <param name="locker">The <see cref="Locker"/> to check.</param>
/// <returns>The corresponding <see cref="LockerType"/>.</returns>
public static LockerType GetLockerType(this Locker locker) => locker.name.GetLockerTypeByName();

/// <summary>
/// Gets the <see cref="LockerType"/> by name.
/// </summary>
/// <param name="name">The name to check.</param>
/// <returns>The corresponding <see cref="LockerType"/>.</returns>
public static LockerType GetLockerTypeByName(this string name) => name.Replace("(Clone)", string.Empty) switch
{
"Scp500PedestalStructure Variant" => LockerType.Pedestal,
"LargeGunLockerStructure" => LockerType.LargeGun,
"RifleRackStructure" => LockerType.RifleRack,
"MiscLocker" => LockerType.Misc,
"RegularMedkitStructure" => LockerType.Medkit,
"AdrenalineMedkitStructure" => LockerType.Adrenaline,
_ => LockerType.Unknow,
};
}
}
224 changes: 224 additions & 0 deletions EXILED/Exiled.API/Features/Lockers/Chamber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// -----------------------------------------------------------------------
// <copyright file="Chamber.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------
namespace Exiled.API.Features.Lockers
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features.Pickups;
using Exiled.API.Interfaces;
using MapGeneration.Distributors;
using UnityEngine;

/// <summary>
/// A wrapper for <see cref="LockerChamber"/>.
/// </summary>
public class Chamber : IWrapper<LockerChamber>, IWorldSpace
{
/// <summary>
/// <see cref="Dictionary{TKey,TValue}"/> with <see cref="LockerChamber"/> and <see cref="Chamber"/>.
/// </summary>
internal static readonly Dictionary<LockerChamber, Chamber> Chambers = new();

/// <summary>
/// Initializes a new instance of the <see cref="Chamber"/> class.
/// </summary>
/// <param name="chamber"><see cref="LockerChamber"/> instance.</param>
/// <param name="locker"><see cref="Lockers.Locker"/> where this chamber is located.</param>
public Chamber(LockerChamber chamber, Locker locker)
{
Base = chamber;
Locker = locker;

Chambers.Add(chamber, this);
}

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Chamber"/> which contains all the <see cref="Chamber"/> instances.
/// </summary>
public static IReadOnlyCollection<Chamber> List => Chambers.Values;

/// <inheritdoc/>
public LockerChamber Base { get; }

/// <summary>
/// Gets the <see cref="Lockers.Locker"/> where this chamber is located at.
/// </summary>
public Locker Locker { get; }

/// <inheritdoc/>
public Vector3 Position => Base.transform.position;

/// <inheritdoc/>
public Quaternion Rotation => Base.transform.rotation;

/// <summary>
/// Gets or sets all pickups that should be spawned when the door is initially opened.
/// </summary>
public IEnumerable<Pickup> ToBeSpawned
{
get => Base._toBeSpawned.Select(Pickup.Get);
set
{
Base._toBeSpawned.Clear();

foreach (Pickup pickup in value)
Base._toBeSpawned.Add(pickup.Base);
}
}

/// <summary>
/// Gets or sets all spawn points.
/// </summary>
/// <remarks>
/// Used if <see cref="UseMultipleSpawnpoints"/> is set to <see langword="true"/>.
/// </remarks>
public IEnumerable<Transform> Spawnpoints
{
get => Base._spawnpoints;
set => Base._spawnpoints = value.ToArray();
}

/// <summary>
/// Gets or sets all the acceptable items which can be spawned in this chamber.
/// </summary>
public IEnumerable<ItemType> AcceptableTypes
{
get => Base.AcceptableItems;
set => Base.AcceptableItems = value.ToArray();
}

/// <summary>
/// Gets or sets required permissions to open this chamber.
/// </summary>
public KeycardPermissions RequiredPermissions
{
get => (KeycardPermissions)Base.RequiredPermissions;
set => Base.RequiredPermissions = (Interactables.Interobjects.DoorUtils.KeycardPermissions)value;
}

/// <summary>
/// Gets or sets a value indicating whether multiple spawn points should be used.
/// </summary>
/// <remarks>
/// If <see langword="true"/>, <see cref="Spawnpoints"/> will be used over <see cref="Spawnpoint"/>.
/// </remarks>
public bool UseMultipleSpawnpoints
{
get => Base._useMultipleSpawnpoints;
set => Base._useMultipleSpawnpoints = value;
}

/// <summary>
/// Gets or sets a spawn point for the items in the chamber.
/// </summary>
/// <remarks>
/// Used if <see cref="UseMultipleSpawnpoints"/> is set to <see langword="false"/>.
/// </remarks>
public Transform Spawnpoint
{
get => Base._spawnpoint;
set => Base._spawnpoint = value;
}

/// <summary>
/// Gets or sets a value indicating whether or not items should be spawned as soon as they one chamber is opened.
/// </summary>
public bool InitiallySpawn
{
get => Base._spawnOnFirstChamberOpening;
set => Base._spawnOnFirstChamberOpening = value;
}

/// <summary>
/// Gets or sets the amount of time before a player can interact with the chamber again.
/// </summary>
public float Cooldown
{
get => Base._targetCooldown;
set => Base._targetCooldown = value;
}

/// <summary>
/// Gets a value indicating whether the chamber is currently open.
/// </summary>
public bool IsOpen => Base.IsOpen;

/// <summary>
/// Gets the <see cref="Stopwatch"/> of current cooldown.
/// </summary>
/// <remarks>Used in <see cref="CanInteract"/> check.</remarks>
public Stopwatch CurrentCooldown => Base._stopwatch;

/// <summary>
/// Gets a value indicating whether the chamber is interactable.
/// </summary>
public bool CanInteract => Base.CanInteract;

/// <summary>
/// Spawns a specified item from <see cref="AcceptableTypes"/>.
/// </summary>
/// <param name="type"><see cref="ItemType"/> from <see cref="AcceptableTypes"/>.</param>
/// <param name="amount">Amount of items that should be spawned.</param>
public void SpawnItem(ItemType type, int amount) => Base.SpawnItem(type, amount);

/// <summary>
/// Adds an item of the specified type to the chamber's spawn list.
/// If the chamber is open and <paramref name="spawnIfIsOpen"/> is set to <see langword="true"/>,
/// the item is spawned immediately at a random spawn point within the chamber.
/// </summary>
/// <param name="itemType">The type of item to add to the spawn list.</param>
/// <param name="quantity">The number of items to add. Defaults to 1.</param>
/// <param name="spawnIfIsOpen">
/// If <see langword="true"/> and the chamber is open, the item is immediately spawned at a random spawn point.
/// Otherwise, the item is added to the spawn list and will spawn when the chamber is opened.
/// </param>
public void AddItemToSpawn(ItemType itemType, int quantity = 1, bool spawnIfIsOpen = false)
{
for (int i = 0; i < quantity; i++)
{
Pickup pickup = Pickup.Create(itemType);

if (spawnIfIsOpen && IsOpen)
{
pickup.Position = GetRandomSpawnPoint();
pickup.Spawn();
continue;
}

Base._toBeSpawned.Add(pickup.Base);
}
}

/// <summary>
/// Gets a random spawn point within the chamber.
/// If multiple spawn points are available and <see cref="UseMultipleSpawnpoints"/> is <see langword="true"/>,
/// a random spawn point is selected from the available points.
/// Otherwise, the default spawn point is used.
/// </summary>
/// <returns>A <see cref="Vector3"/> representing the position of the selected spawn point.</returns>
public Vector3 GetRandomSpawnPoint()
{
if (UseMultipleSpawnpoints && Spawnpoints.Any())
{
return Spawnpoints.GetRandomValue().position;
}

return Spawnpoint.position;
}

/// <summary>
/// Gets the chamber by its <see cref="LockerChamber"/>.
/// </summary>
/// <param name="chamber"><see cref="LockerChamber"/>.</param>
/// <returns><see cref="Chamber"/>.</returns>
internal static Chamber Get(LockerChamber chamber) => Chambers.TryGetValue(chamber, out Chamber chmb) ? chmb : new(chamber, Locker.Get(x => x.Chambers.Any(x => x.Base == chamber)).FirstOrDefault());
}
}
Loading
Loading