diff --git a/EXILED/Exiled.API/Enums/SpawnableFaction.cs b/EXILED/Exiled.API/Enums/SpawnableFaction.cs index 131a7a4ff4..0903253fca 100644 --- a/EXILED/Exiled.API/Enums/SpawnableFaction.cs +++ b/EXILED/Exiled.API/Enums/SpawnableFaction.cs @@ -12,6 +12,11 @@ namespace Exiled.API.Enums /// public enum SpawnableFaction { + /// + /// Represents no wave. + /// + None, + /// /// Normal NTF wave. /// diff --git a/EXILED/Exiled.API/Extensions/RoleExtensions.cs b/EXILED/Exiled.API/Extensions/RoleExtensions.cs index 407e26565c..445edb88c4 100644 --- a/EXILED/Exiled.API/Extensions/RoleExtensions.cs +++ b/EXILED/Exiled.API/Extensions/RoleExtensions.cs @@ -12,12 +12,13 @@ namespace Exiled.API.Extensions using System.Linq; using Enums; - using Exiled.API.Features.Spawn; + using Features.Spawn; using Footprinting; using InventorySystem; using InventorySystem.Configs; using PlayerRoles; using PlayerRoles.FirstPersonControl; + using Respawning; using Respawning.Waves; using UnityEngine; @@ -233,12 +234,62 @@ public static Dictionary GetStartingAmmo(this RoleTypeId roleT /// /// A instance. /// associated with the wave. - public static SpawnableFaction GetFaction(this SpawnableWaveBase waveBase) => waveBase switch + public static SpawnableFaction GetSpawnableFaction(this SpawnableWaveBase waveBase) => waveBase switch { NtfSpawnWave => SpawnableFaction.NtfWave, NtfMiniWave => SpawnableFaction.NtfMiniWave, ChaosSpawnWave => SpawnableFaction.ChaosWave, - _ => SpawnableFaction.ChaosMiniWave + ChaosMiniWave => SpawnableFaction.ChaosMiniWave, + _ => SpawnableFaction.None }; + + /// + /// Gets the associated with the provided . + /// + /// A member of the enum. + /// associated with the provided . + public static Faction GetFaction(this SpawnableFaction spawnableFaction) => spawnableFaction switch + { + SpawnableFaction.ChaosWave or SpawnableFaction.ChaosMiniWave => Faction.FoundationEnemy, + SpawnableFaction.NtfWave or SpawnableFaction.NtfMiniWave => Faction.FoundationStaff, + _ => Faction.Unclassified, + }; + + /// + /// Gets the associated with the provided . + /// + /// A member of the enum. + /// associated with the provided . + public static Faction GetFaction(this SpawnableTeamType spawnableTeamType) => spawnableTeamType switch + { + SpawnableTeamType.ChaosInsurgency => Faction.FoundationEnemy, + SpawnableTeamType.NineTailedFox => Faction.FoundationStaff, + _ => Faction.Unclassified, + }; + + /// + /// Tries to get the associated with the provided and . + /// + /// A member of the enum. + /// The to return. + /// A determining whether to get a normal spawn wave or a mini one. + /// associated with the provided influenced by . + public static bool TryGetSpawnableFaction(this Faction faction, out SpawnableFaction spawnableFaction, bool mini = false) + { + switch (faction) + { + case Faction.FoundationStaff: + spawnableFaction = mini ? SpawnableFaction.NtfMiniWave : SpawnableFaction.NtfWave; + break; + case Faction.FoundationEnemy: + spawnableFaction = mini ? SpawnableFaction.ChaosMiniWave : SpawnableFaction.ChaosWave; + break; + default: + spawnableFaction = SpawnableFaction.None; + return false; + } + + return true; + } } } diff --git a/EXILED/Exiled.API/Features/Respawn.cs b/EXILED/Exiled.API/Features/Respawn.cs index fbbfd9ce5b..a7590dfd2d 100644 --- a/EXILED/Exiled.API/Features/Respawn.cs +++ b/EXILED/Exiled.API/Features/Respawn.cs @@ -9,9 +9,11 @@ namespace Exiled.API.Features { using System; using System.Collections.Generic; + using System.Linq; using CustomPlayerEffects; using Enums; + using Extensions; using PlayerRoles; using Respawning; using Respawning.Waves; @@ -26,6 +28,16 @@ public static class Respawn private static GameObject ntfHelicopterGameObject; private static GameObject chaosCarGameObject; + /// + /// Gets the of paused 's. + /// + public static List PausedWaves { get; } = new(); + + /// + /// Gets the containing faction influence. + /// + public static Dictionary FactionInfluence => FactionInfluenceManager.Influence; + /// /// Gets the NTF Helicopter's . /// @@ -55,18 +67,16 @@ public static GameObject ChaosVan } /// - /// Gets or sets the next known that will spawn. + /// Gets the next known that will spawn. /// - public static Faction NextKnownFaction - { - get => WaveManager._nextWave.TargetFaction; - set => WaveManager._nextWave = WaveManager.Waves.Find(x => x.TargetFaction == value); - } + /// This returns SpawnableFaction.None unless a respawn has already started. + public static SpawnableFaction NextKnownSpawnableFaction => WaveManager._nextWave is not null ? WaveManager._nextWave.GetSpawnableFaction() : SpawnableFaction.None; /// /// Gets the next known that will spawn. /// - public static SpawnableTeamType NextKnownTeam => NextKnownFaction.GetSpawnableTeam(); + /// This returns SpawnableFaction.None unless a respawn has already started. + public static SpawnableTeamType NextKnownTeam => NextKnownSpawnableFaction.GetFaction().GetSpawnableTeam(); /// /// Gets the current state of the . @@ -74,7 +84,7 @@ public static Faction NextKnownFaction public static WaveManager.WaveQueueState CurrentState => WaveManager.State; /// - /// Gets a value indicating whether a team is currently being spawned or the animations are playing for a team. + /// Gets a value indicating whether the respawn process for a is currently in progress.. /// public static bool IsSpawning => WaveManager.State == WaveManager.WaveQueueState.WaveSpawning; @@ -106,177 +116,335 @@ public static bool ProtectedCanShoot } /// - /// Gets a of that have spawn protection. + /// Gets a of s that have spawn protection. /// public static List ProtectedTeams => SpawnProtected.ProtectedTeams; /// /// Tries to get a . /// - /// Found . + /// The found . /// Type of . - /// true if was successfully found. Otherwise, false. - public static bool TryGetWaveBase(out T spawnWave) - where T : SpawnableWaveBase => WaveManager.TryGet(out spawnWave); + /// true if was successfully found. Otherwise, false. + /// + public static bool TryGetWaveBase(out T spawnableWaveBase) + where T : SpawnableWaveBase => WaveManager.TryGet(out spawnableWaveBase); /// - /// Tries to get a from a . + /// Tries to get a . /// - /// Team's . - /// Found . - /// true if was successfully found. Otherwise, false. - public static bool TryGetWaveBase(Faction faction, out SpawnableWaveBase spawnWave) - => WaveManager.TryGet(faction, out spawnWave); + /// A determining which wave to search for. + /// The found . + /// true if was successfully found. Otherwise, false. + /// + public static bool TryGetWaveBase(SpawnableFaction spawnableFaction, out SpawnableWaveBase spawnableWaveBase) + { + spawnableWaveBase = WaveManager.Waves.Find(x => x.GetSpawnableFaction() == spawnableFaction); + return spawnableWaveBase is not null; + } /// - /// Tries to get a from a . + /// Tries to get an of . /// - /// Team's . - /// Found . - /// true if was successfully found. Otherwise, false. - public static bool TryGetWaveBase(SpawnableFaction faction, out SpawnableWaveBase spawnWave) + /// A determining which waves to search for. + /// The containing found 's if there are any, otherwise null. + /// true if was successfully found. Otherwise, false. + /// + public static bool TryGetWaveBases(Faction faction, out IEnumerable spawnableWaveBases) { - switch (faction) + List spawnableWaves = new(); + spawnableWaves.AddRange(WaveManager.Waves.Where(x => x.TargetFaction == faction)); + + if (spawnableWaves.IsEmpty()) { - case SpawnableFaction.NtfWave: - bool result = TryGetWaveBase(out NtfSpawnWave ntfSpawnWave); - spawnWave = ntfSpawnWave; - return result; - case SpawnableFaction.NtfMiniWave: - result = TryGetWaveBase(out NtfMiniWave ntfMiniWave); - spawnWave = ntfMiniWave; - return result; - case SpawnableFaction.ChaosWave: - result = TryGetWaveBase(out ChaosSpawnWave chaosSpawnWave); - spawnWave = chaosSpawnWave; - return result; - case SpawnableFaction.ChaosMiniWave: - result = TryGetWaveBase(out ChaosMiniWave chaosMiniWave); - spawnWave = chaosMiniWave; - return result; + spawnableWaveBases = null; + return false; } - spawnWave = null; - return false; + spawnableWaveBases = spawnableWaves; + return true; } /// - /// Docs. + /// Tries to get an of . + /// + /// A determining which waves to search for. + /// The containing found 's if there are any, otherwise null. + /// true if was successfully found. Otherwise, false. + /// + public static bool TryGetWaveBases(SpawnableTeamType spawnableTeamType, out IEnumerable spawnableWaveBases) + { + return TryGetWaveBases(spawnableTeamType.GetFaction(), out spawnableWaveBases); + } + + /// + /// Advances the respawn timer for s. + /// + /// The whose 's timers are to be advanced. + /// Number of seconds to advance the timers by. + /// This advances the timer for both the normal and mini wave. + public static void AdvanceTimer(Faction faction, float seconds) => WaveManager.AdvanceTimer(faction, seconds); + + /// + /// Advances the respawn timer for s. + /// + /// The whose 's timers are to be advanced. + /// A representing the amount of time to advance the timers by. + /// This advances the timer for both the normal and mini wave. + public static void AdvanceTimer(Faction faction, TimeSpan time) => AdvanceTimer(faction, (float)time.TotalSeconds); + + /// + /// Advances the respawn timer for s. /// - /// Docs1. - /// Docs2. - public static void AdvanceTime(Faction faction, float time) => WaveManager.AdvanceTimer(faction, time); + /// The whose 's timers are to be advanced. + /// Number of seconds to advance the timers by. + /// This advances the timer for both the normal and mini wave. + public static void AdvanceTimer(SpawnableTeamType spawnableTeamType, float seconds) => AdvanceTimer(spawnableTeamType.GetFaction(), seconds); /// - /// Docs. + /// Advances the respawn timer for s. /// - /// Docs1. - public static void SpawnWave(SpawnableWaveBase wave) => WaveManager.Spawn(wave); + /// The whose 's timers are to be advanced. + /// A representing the amount of time to advance the timers by. + /// This advances the timer for both the normal and mini wave. + public static void AdvanceTimer(SpawnableTeamType spawnableTeamType, TimeSpan time) => AdvanceTimer(spawnableTeamType.GetFaction(), time); /// - /// Docs. + /// Advances the respawn timer for s. /// - /// Docs1. - /// Docs2. - /// Docs3. - public static void SpawnWave(Faction faction, bool mini) - where T : SpawnableWaveBase + /// The whose 's timer is to be advanced. + /// Number of seconds to advance the timers by. + public static void AdvanceTimer(SpawnableFaction spawnableFaction, float seconds) { - if (TryGetWaveBase(out T wave)) - SpawnWave(wave); + foreach (SpawnableWaveBase spawnableWaveBase in WaveManager.Waves) + { + TimeBasedWave timeBasedWave = (TimeBasedWave)spawnableWaveBase; + if (timeBasedWave.GetSpawnableFaction() == spawnableFaction) + { + timeBasedWave.Timer.AddTime(Mathf.Abs(seconds)); + } + } } /// - /// Play effects when a certain class spawns. + /// Advances the respawn timer for s. /// - /// The for which effects should be played. + /// The whose 's timer is to be advanced. + /// A representing the amount of time to advance the timers by. + public static void AdvanceTimer(SpawnableFaction spawnableFaction, TimeSpan time) => AdvanceTimer(spawnableFaction, (float)time.TotalSeconds); + + /// + /// Play the spawn effect of a . + /// + /// The whose effect should be played. public static void PlayEffect(SpawnableWaveBase wave) { WaveUpdateMessage.ServerSendUpdate(wave, UpdateMessageFlags.Trigger); } /// - /// Summons the NTF chopper. + /// Summons the chopper. /// public static void SummonNtfChopper() { - if (TryGetWaveBase(Faction.FoundationStaff, out SpawnableWaveBase wave)) + if (TryGetWaveBase(SpawnableFaction.NtfWave, out SpawnableWaveBase wave)) PlayEffect(wave); } /// - /// Summons the van. + /// Summons the van. /// /// This will also trigger Music effect. + /// public static void SummonChaosInsurgencyVan() { - if (TryGetWaveBase(Faction.FoundationEnemy, out SpawnableWaveBase wave)) + if (TryGetWaveBase(SpawnableFaction.ChaosWave, out SpawnableWaveBase wave)) PlayEffect(wave); } /// - /// Grants tickets to a . + /// Grants tokens to a given 's s. + /// + /// The to whose s to grant tokens. + /// The amount of tokens to grant. + /// true if tokens were successfully granted to an , otherwise false. + public static bool GrantTokens(Faction faction, int amount) + { + if (TryGetWaveBases(faction, out IEnumerable waveBases)) + { + foreach (ILimitedWave limitedWave in waveBases.OfType()) + { + limitedWave.RespawnTokens += amount; + } + + return true; + } + + return false; + } + + /// + /// Removes tokens from a given 's s. + /// + /// The from whose s to remove tokens. + /// The amount of tokens to remove. + /// true if tokens were successfully removed from an , otherwise false. + public static bool RemoveTokens(Faction faction, int amount) + { + if (TryGetWaveBases(faction, out IEnumerable waveBases)) + { + foreach (ILimitedWave limitedWave in waveBases.OfType()) + { + limitedWave.RespawnTokens = Math.Max(0, limitedWave.RespawnTokens - amount); + } + + return true; + } + + return false; + } + + /// + /// Modifies tokens of a given 's s by a given amount. /// - /// The to grant tickets to. - /// The amount of tickets to grant. - public static void GrantTickets(Faction team, int amount) + /// The whose s' tokens are to be modified. + /// The amount of tokens to add/remove. + /// true if tokens were successfully modified for an , otherwise false. + public static bool ModifyTokens(Faction faction, int amount) { - if (TryGetWaveBase(team, out SpawnableWaveBase wave) && wave is ILimitedWave limitedWave) - limitedWave.RespawnTokens += amount; + if (TryGetWaveBases(faction, out IEnumerable waveBases)) + { + foreach (ILimitedWave limitedWave in waveBases.OfType()) + { + limitedWave.RespawnTokens = amount; + } + + return true; + } + + return false; } /// - /// Removes tickets from a . + /// Tries to get the tokens of a given 's . /// - /// The to remove tickets from. - /// The amount of tickets to remove. - public static void RemoveTickets(Faction team, int amount) + /// The from whose to get the tokens. + /// The amount of tokens an has, if one was found, otherwise 0. + /// true if an was successfully found, otherwise false. + public static bool TryGetTokens(SpawnableFaction spawnableFaction, out int tokens) { - if (TryGetWaveBase(team, out SpawnableWaveBase wave) && wave is ILimitedWave limitedWave) - limitedWave.RespawnTokens = Math.Max(0, limitedWave.RespawnTokens - amount); + if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase waveBase) && waveBase is ILimitedWave limitedWave) + { + tokens = limitedWave.RespawnTokens; + return true; + } + + tokens = 0; + return false; } /// - /// Modify tickets from a . + /// Sets the amount of tokens of an of the given . /// - /// The to modify tickets from. - /// The amount of tickets to modify. - public static void ModifyTickets(Faction team, int amount) + /// The whose 's tokens to set. + /// The amount of tokens to set. + /// true if tokens were successfully set for an , otherwise false. + public static bool SetTokens(SpawnableFaction spawnableFaction, int amount) { - if (TryGetWaveBase(team, out SpawnableWaveBase wave) && wave is ILimitedWave limitedWave) + if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase waveBase) && waveBase is ILimitedWave limitedWave) + { limitedWave.RespawnTokens = amount; + return true; + } + + return false; + } + + /// + /// Starts the spawn sequence of the given . + /// + /// The whose wave to spawn. + /// Whether the wave should be a mini wave or not. + public static void ForceWave(SpawnableTeamType spawnableTeamType, bool isMini = false) + { + ForceWave(spawnableTeamType.GetFaction(), isMini); + } + + /// + /// Starts the spawn sequence of the given . + /// + /// The whose wave to spawn. + /// Whether the wave should be a mini wave or not. + public static void ForceWave(Faction faction, bool isMini = false) + { + if (faction.TryGetSpawnableFaction(out SpawnableFaction spawnableFaction, isMini)) + { + ForceWave(spawnableFaction); + } + } + + /// + /// Starts the spawn sequence of the given . + /// + /// The whose wave to spawn. + public static void ForceWave(SpawnableFaction spawnableFaction) + { + if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase spawnableWaveBase)) + { + ForceWave(spawnableWaveBase); + } } /// - /// Gets the amount of tickets from a . + /// Starts the spawn sequence of the given . /// - /// 's faction. - /// Tickets of team or -1 if team doesn't depend on tickets. - public static int GetTickets(SpawnableFaction faction) + /// The to spawn. + public static void ForceWave(SpawnableWaveBase spawnableWaveBase) { - if (TryGetWaveBase(faction, out SpawnableWaveBase wave) && wave is ILimitedWave limitedWave) - return limitedWave.RespawnTokens; + WaveManager.Spawn(spawnableWaveBase); + } - return -1; + /// + /// Pauses respawn waves by removing them from WaveManager.Waves and storing them in . + /// + /// + public static void PauseWaves() + { + PausedWaves.Clear(); + PausedWaves.AddRange(WaveManager.Waves); + WaveManager.Waves.Clear(); } /// - /// Forces a spawn of the given . + /// Resumes respawn waves by filling WaveManager.Waves with values stored in . /// - /// The to spawn. - public static void ForceWave(Faction team) + /// + /// This also clears . + public static void ResumeWaves() { - if (TryGetWaveBase(team, out SpawnableWaveBase wave)) - ForceWave(wave); + WaveManager.Waves.Clear(); + WaveManager.Waves.AddRange(PausedWaves); + PausedWaves.Clear(); } /// - /// Docs. + /// Restarts respawn waves by clearing WaveManager.Waves and filling it with new values.. /// - /// Docs1. - public static void ForceWave(SpawnableWaveBase wave) + /// + /// This also clears . + public static void RestartWaves() { - WaveManager.Spawn(wave); + WaveManager.Waves.Clear(); + WaveManager.Waves.AddRange(new List { new ChaosMiniWave(), new ChaosSpawnWave(), new NtfMiniWave(), new NtfSpawnWave() }); + PausedWaves.Clear(); } + + /// + /// Tries to get the influence value of a given . + /// + /// The whose influence to get. + /// The amount of influence a faction has. + /// Whether an entry was successfully found. + public static bool TryGetFactionInfluence(Faction faction, out float influence) => FactionInfluence.TryGetValue(faction, out influence); } } \ No newline at end of file