Skip to content

Commit

Permalink
[Exiled::CustomItems] [Exiled::API] [Exiled::CustomRoles]
Browse files Browse the repository at this point in the history
… Adding news Spawnpoints, Wrapper for Locker and added LockerType (#77)

* QoL

* Added ``RoomSpawnPoint`` for spawning things in a room with a offset property.

* Now Items will be spawned in the MapGenerated event instead of RoundStart avoiding the micro-log for spawning to many pickups in one frame.

* YES YAMATO I USE NULLEABLE

* Shut

* Done

* Created a Wrapper for Locker

* Created LockerSpawnPoint

* I NEED HELP FOR IMPLEMENTING SUPPLYLOCKER I DONT FUCKING KNOW HOW MAKE A TRANSPILER

* I hate you Yamato :D

* Boop

* Why Exiled use MONO.POSIX

* And dont use the nuget for it 💀

* Now it will compile in the page

* Removing Else if (spawnPoint is RoleSpawnPoint roleSpawnPoint) since its not necessary spawnpoint.Position does the same.

* Supressing CS0618  due the obsolet in SpawnLocationType.InsideLocker.
   * Note: SpawnLocationType.InsideLocker its only used in CustomItem.SpawnAll() so it will be fine to deleted this in futures releases.

* Fixing compile action due the warnings

* Adding support for Offset

Almost forget about this :P

* Sorry

I cant resist adding more things

* Adding support for CustomRoles

* Implementing SupplyLocker

* I literally copy the generator transpiler

* Its works i test it.

* Give me my exiled contributor role.

* LockerType enum

* Code part of the code has been taken from MER (https://github.com/Michal78900/MapEditorReborn/blob/dev/MapEditorReborn/API/Extensions/LockerExtensions.cs) - Credits to Michal, i ask him i can use it, not answer yet but if the say no i will use another way.

* SupplyLocker now have a LockerType Property to know what type of Locker is

* LockerSpawnPoint can now chose what locker want to use

* Mimimi warnings

* Re-implementing Locker API

* Re-implementing locker api of Exiled-Team/EXILED#2026

* Update EXILED/Exiled.API/Enums/LockerType.cs

Co-authored-by: Nameless <85962933+Misfiy@users.noreply.github.com>

* I dont like the name of ExiledLockers but

* Resolving #77 (comment)

* Resolving #77 (comment)

* Cleaning Chambers List.

* Fixing CustomWeapon

* Fixing a Bug with custom items with spawning in old SpawnLocationType.InsideLocker

* Update Map.cs

Removing blank line.

* MORE

* Added GetRandomSpawnPoint() in Chamber

* Added AddItemToSpawn((ItemType itemType, int quantity = 1, bool spawnIfIsOpen = false)) in Chamber

* Added IsOpen in chamber.

* Fixing obsolet use

* Sorry @VALERA771

* Resolve #77 (review)

* Update Exiled.Loader.csproj

* Resolving #77 (comment)

* Update MapHandler.cs

Reduce the delay on spawning items, its not necessary to be to long

* Ups

Ups

---------

Co-authored-by: Nameless <85962933+Misfiy@users.noreply.github.com>
  • Loading branch information
SrLicht and Misfiy authored Sep 2, 2024
1 parent d08b002 commit 96ccf32
Show file tree
Hide file tree
Showing 17 changed files with 761 additions and 42 deletions.
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

0 comments on commit 96ccf32

Please sign in to comment.