diff --git a/SillySCP/Handlers/AntiSurface.cs b/SillySCP/Handlers/AntiSurface.cs index fcdb730..6b9165f 100644 --- a/SillySCP/Handlers/AntiSurface.cs +++ b/SillySCP/Handlers/AntiSurface.cs @@ -1,16 +1,9 @@ -using System.Collections; -using System.Text.RegularExpressions; -using Exiled.API.Enums; +using Exiled.API.Enums; using Exiled.API.Features; -using Exiled.API.Features.Doors; -using Exiled.Events.EventArgs.Map; -using Exiled.Events.EventArgs.Player; +using Exiled.API.Features.Waves; using Exiled.Events.EventArgs.Server; -using Interactables.Interobjects; using MEC; -using PlayerRoles; using SillySCP.API.Interfaces; -using UnityEngine; namespace SillySCP.Handlers; @@ -18,100 +11,88 @@ public class AntiSurface : IRegisterable { public void Init() { - Exiled.Events.Handlers.Map.ElevatorSequencesUpdated += OnElevatorSequencesUpdated; - Exiled.Events.Handlers.Server.RespawnedTeam += OnRespawned; - Exiled.Events.Handlers.Player.Died += OnPlayerDied; + Exiled.Events.Handlers.Server.RespawnedTeam += OnRespawnedTeam; + Exiled.Events.Handlers.Server.CompletingObjective += OnObjectiveComplete; } public void Unregister() { - Exiled.Events.Handlers.Map.ElevatorSequencesUpdated -= OnElevatorSequencesUpdated; - Exiled.Events.Handlers.Server.RespawnedTeam -= OnRespawned; - Exiled.Events.Handlers.Player.Died -= OnPlayerDied; + Exiled.Events.Handlers.Server.RespawnedTeam -= OnRespawnedTeam; + Exiled.Events.Handlers.Server.CompletingObjective += OnObjectiveComplete; } - private void OnPlayerDied(DiedEventArgs ev) + private void OnObjectiveComplete(CompletingObjectiveEventArgs ev) { - if (Exiled.API.Features.Player.List.Count(p => p.IsAlive && !p.IsScp) > 3) return; - TryStartCoroutine(); + _wave = GetWave(); } - private void OnElevatorSequencesUpdated(ElevatorSequencesUpdatedEventArgs ev) + private void OnRespawnedTeam(RespawnedTeamEventArgs ev) { - if (ev.Sequence != ElevatorChamber.ElevatorSequence.DoorOpening) return; - if (ev.Lift.Type is not ElevatorType.GateA and not ElevatorType.GateB) return; - if (ev.Lift.CurrentLevel != 1) return; - TryStartCoroutine(); + Timing.KillCoroutines(_handle); + _wave = GetWave(); + _handle = Timing.RunCoroutine(SurfaceChecker()); } - private void OnRespawned(RespawnedTeamEventArgs ev) + private static TimedWave GetWave() { - _handle = null; - - Door ezA = Door.Get(DoorType.GateA); - Door ezB = Door.Get(DoorType.GateB); - ezA.Unlock(); - ezB.Unlock(); - - TryStartCoroutine(); + if (Respawn.NextKnownSpawnableFaction == SpawnableFaction.None) return null; + TimedWave wave = TimedWave.GetTimedWaves() + .FirstOrDefault(wave => wave.SpawnableFaction == Respawn.NextKnownSpawnableFaction && !wave.Timer.IsPaused); + return wave; } - - private CoroutineHandle? _handle; - private void TryStartCoroutine() - { - if (_handle != null) return; - _handle = Timing.RunCoroutine(SurfaceChecker()); - } + private static TimedWave _wave; + private CoroutineHandle _handle; - private IEnumerator SurfaceChecker() + private static IEnumerator SurfaceChecker() { - yield return Timing.WaitForSeconds(120); - - if (Exiled.API.Features.Player.List.Count(player => player.IsAlive && !player.IsScp) > 3) - yield break; + HashSet lastKnownPlayers = new (GetSurfacePlayers()); + DateTime firstCalled = DateTime.Now; + bool isFirstRun = true; - List surfacePlayers = Room.Get(RoomType.Surface).Players.ToList(); - - if (surfacePlayers.Count == 0 || - surfacePlayers.Count(p => p.IsScp) > 1 || - surfacePlayers.Select(p => p.Role.Team).Distinct().Count() > 1) - yield break; - - Team team = surfacePlayers[0].Role.Team; - int playerCount = surfacePlayers.Count; - - Door gateA = Door.Get(DoorType.ElevatorGateA); - Door gateB = Door.Get(DoorType.ElevatorGateB); - Door ezA = Door.Get(DoorType.GateA); - Door ezB = Door.Get(DoorType.GateB); - - int closerToACount = surfacePlayers.Count(player => - Vector3.Distance(player.Position, gateA.Position) <= Vector3.Distance(player.Position, gateB.Position)); - - ezA.IsOpen = ezB.IsOpen = true; - ezA.Lock(DoorLockType.Warhead); - ezB.Lock(DoorLockType.Warhead); - - string message; - string translation; - - if (playerCount != closerToACount) - { - message = $"{playerCount} {Spaceify(team.ToString())} personnel located on surface"; - translation = $"{playerCount} {Spaceify(team.ToString())} personnel located on Surface"; - } - else + foreach (int seconds in Seconds) { - string nearGate = closerToACount > 0 ? "a" : "b"; - string nearGateTranslation = closerToACount > 0 ? "A" : "B"; - message = $"{playerCount} {Spaceify(team.ToString())} personnel located near gate {nearGate}"; - translation = $"{playerCount} {Spaceify(team.ToString())} personnel located near Gate {nearGateTranslation}"; + if (TotalSeconds(_wave) < seconds) + continue; + + yield return Timing.WaitUntilTrue(() => TotalSeconds(_wave) <= seconds); + + if (isFirstRun && (DateTime.Now - firstCalled).TotalSeconds < 29) + { + lastKnownPlayers = new (GetSurfacePlayers()); + isFirstRun = false; + continue; + } + + IEnumerable currentPlayers = GetSurfacePlayers(); + + foreach (Exiled.API.Features.Player player in currentPlayers) + { + if (lastKnownPlayers.Contains(player)) + { + player.Kick("Holding up the round on surface."); + } + } + + lastKnownPlayers = new (currentPlayers); } - - Cassie.MessageTranslated(message, translation); - _handle = null; } - private string Spaceify(string input) => Regex.Replace(input, "([A-Z])", " $1").Trim(); + private static IEnumerable GetSurfacePlayers() + { + return Exiled.API.Features.Player.List.Where(player => player.Zone == ZoneType.Surface && player.IsHuman); + } + + private static readonly int[] Seconds = new[] + { + 180, + 120, + 60, + 30 + }; + + private static int TotalSeconds(TimedWave wave) + { + return Convert.ToInt32(wave.Timer.TimeLeft.TotalSeconds); + } } \ No newline at end of file diff --git a/SillySCP/SillySCP.csproj b/SillySCP/SillySCP.csproj index 362eb74..54a8a99 100644 --- a/SillySCP/SillySCP.csproj +++ b/SillySCP/SillySCP.csproj @@ -18,7 +18,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive