diff --git a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs index eb1f9796b2..47ccc3c3c4 100644 --- a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs +++ b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs @@ -15,6 +15,7 @@ using Content.Server.Station.Events; using Content.Server.Station.Systems; using Content.Shared.Administration; using Content.Shared.CCVar; +using Content.Shared.Damage.Components; using Content.Shared.DeviceNetwork; using Content.Shared.Mobs.Components; using Content.Shared.Movement.Components; @@ -63,6 +64,16 @@ public sealed class ArrivalsSystem : EntitySystem /// public bool Enabled { get; private set; } + /// + /// Flags if all players must arrive via the Arrivals system, or if they can spawn in other ways. + /// + public bool Forced { get; private set; } + + /// + /// Flags if all players spawning at the departure terminal have godmode until they leave the terminal. + /// + public bool ArrivalsGodmode { get; private set; } + /// /// The first arrival is a little early, to save everyone 10s /// @@ -94,7 +105,12 @@ public sealed class ArrivalsSystem : EntitySystem // Don't invoke immediately as it will get set in the natural course of things. Enabled = _cfgManager.GetCVar(CCVars.ArrivalsShuttles); - Subs.CVar(_cfgManager, CCVars.ArrivalsShuttles, SetArrivals); + Forced = _cfgManager.GetCVar(CCVars.ForceArrivals); + ArrivalsGodmode = _cfgManager.GetCVar(CCVars.GodmodeArrivals); + + _cfgManager.OnValueChanged(CCVars.ArrivalsShuttles, SetArrivals); + _cfgManager.OnValueChanged(CCVars.ForceArrivals, b => Forced = b); + _cfgManager.OnValueChanged(CCVars.GodmodeArrivals, b => ArrivalsGodmode = b); // Command so admins can set these for funsies _console.RegisterCommand("arrivals", ArrivalsCommand, ArrivalsCompletion); @@ -250,6 +266,9 @@ public sealed class ArrivalsSystem : EntitySystem // The player has successfully left arrivals and is also not on the shuttle. Remove their warp coupon. RemCompDeferred(pUid); RemCompDeferred(pUid); + + if (ArrivalsGodmode) + RemCompDeferred(pUid); } } @@ -309,7 +328,7 @@ public sealed class ArrivalsSystem : EntitySystem return; // Only works on latejoin even if enabled. - if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound) + if (!Enabled || !Forced && _ticker.RunLevel != GameRunLevel.InRound) return; if (!HasComp(ev.Station)) @@ -317,33 +336,37 @@ public sealed class ArrivalsSystem : EntitySystem TryGetArrivals(out var arrivals); - if (TryComp(arrivals, out TransformComponent? arrivalsXform)) + if (!TryComp(arrivals, out TransformComponent? arrivalsXform)) + return; + + var mapId = arrivalsXform.MapID; + + var points = EntityQueryEnumerator(); + var possiblePositions = new List(); + while (points.MoveNext(out var uid, out var spawnPoint, out var xform)) { - var mapId = arrivalsXform.MapID; + if (spawnPoint.SpawnType != SpawnPointType.LateJoin || xform.MapID != mapId) + continue; - var points = EntityQueryEnumerator(); - var possiblePositions = new List(); - while (points.MoveNext(out var uid, out var spawnPoint, out var xform)) - { - if (spawnPoint.SpawnType != SpawnPointType.LateJoin || xform.MapID != mapId) - continue; - - possiblePositions.Add(xform.Coordinates); - } - - if (possiblePositions.Count > 0) - { - var spawnLoc = _random.Pick(possiblePositions); - ev.SpawnResult = _stationSpawning.SpawnPlayerMob( - spawnLoc, - ev.Job, - ev.HumanoidCharacterProfile, - ev.Station); - - EnsureComp(ev.SpawnResult.Value); - EnsureComp(ev.SpawnResult.Value); - } + possiblePositions.Add(xform.Coordinates); } + + if (possiblePositions.Count <= 0) + return; + + var spawnLoc = _random.Pick(possiblePositions); + ev.SpawnResult = _stationSpawning.SpawnPlayerMob( + spawnLoc, + ev.Job, + ev.HumanoidCharacterProfile, + ev.Station); + + EnsureComp(ev.SpawnResult.Value); + EnsureComp(ev.SpawnResult.Value); + + // If you're forced to spawn, you're invincible until you leave wherever you were forced to spawn. + if (ArrivalsGodmode) + EnsureComp(ev.SpawnResult.Value); } private bool TryTeleportToMapSpawn(EntityUid player, EntityUid stationId, TransformComponent? transform = null) diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index b91082ff26..d30c9fc111 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -65,7 +65,15 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem _spawnerCallbacks = new Dictionary>() { { SpawnPriorityPreference.Arrivals, _arrivalsSystem.HandlePlayerSpawning }, - { SpawnPriorityPreference.Cryosleep, _containerSpawnPointSystem.HandlePlayerSpawning } + { + SpawnPriorityPreference.Cryosleep, ev => + { + if (_arrivalsSystem.Forced) + _arrivalsSystem.HandlePlayerSpawning(ev); + else + _containerSpawnPointSystem.HandlePlayerSpawning(ev); + } + } }; } @@ -308,4 +316,4 @@ public sealed class PlayerSpawningEvent : EntityEventArgs HumanoidCharacterProfile = humanoidCharacterProfile; Station = station; } -} \ No newline at end of file +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index f3025f326a..e3f0f65438 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1425,6 +1425,18 @@ namespace Content.Shared.CCVar public static readonly CVarDef ArrivalsReturns = CVarDef.Create("shuttle.arrivals_returns", false, CVar.SERVERONLY); + /// + /// Should all players be forced to spawn at departures, even on roundstart, even if their loadout says they spawn in cryo? + /// + public static readonly CVarDef ForceArrivals = + CVarDef.Create("shuttle.force_arrivals", false, CVar.SERVERONLY); + + /// + /// Should all players who spawn at arrivals have godmode until they leave the map? + /// + public static readonly CVarDef GodmodeArrivals = + CVarDef.Create("shuttle.godmode_arrivals", false, CVar.SERVERONLY); + /// /// Whether to automatically spawn escape shuttles. ///