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.
///