Fix Centcomm (#16772)
This commit is contained in:
@@ -207,13 +207,16 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
if (component.WinType == WinType.OpsMajor || component.WinType == WinType.CrewMajor)
|
if (component.WinType == WinType.OpsMajor || component.WinType == WinType.CrewMajor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var (nuke, nukeTransform) in EntityQuery<NukeComponent, TransformComponent>(true))
|
var nukeQuery = AllEntityQuery<NukeComponent, TransformComponent>();
|
||||||
|
var centcomms = _emergency.GetCentcommMaps();
|
||||||
|
|
||||||
|
while (nukeQuery.MoveNext(out var nuke, out var nukeTransform))
|
||||||
{
|
{
|
||||||
if (nuke.Status != NukeStatus.ARMED)
|
if (nuke.Status != NukeStatus.ARMED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// UH OH
|
// UH OH
|
||||||
if (nukeTransform.MapID == _emergency.CentComMap)
|
if (centcomms.Contains(nukeTransform.MapID))
|
||||||
{
|
{
|
||||||
component.WinConditions.Add(WinCondition.NukeActiveAtCentCom);
|
component.WinConditions.Add(WinCondition.NukeActiveAtCentCom);
|
||||||
SetWinType(uid, WinType.OpsMajor, component);
|
SetWinType(uid, WinType.OpsMajor, component);
|
||||||
@@ -259,10 +262,12 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
|||||||
component.WinConditions.Add(WinCondition.SomeNukiesAlive);
|
component.WinConditions.Add(WinCondition.SomeNukiesAlive);
|
||||||
|
|
||||||
var diskAtCentCom = false;
|
var diskAtCentCom = false;
|
||||||
foreach (var (_, transform) in EntityManager.EntityQuery<NukeDiskComponent, TransformComponent>())
|
var diskQuery = AllEntityQuery<NukeDiskComponent, TransformComponent>();
|
||||||
|
|
||||||
|
while (diskQuery.MoveNext(out _, out var transform))
|
||||||
{
|
{
|
||||||
var diskMapId = transform.MapID;
|
var diskMapId = transform.MapID;
|
||||||
diskAtCentCom = _emergency.CentComMap == diskMapId;
|
diskAtCentCom = centcomms.Contains(diskMapId);
|
||||||
|
|
||||||
// TODO: The target station should be stored, and the nuke disk should store its original station.
|
// TODO: The target station should be stored, and the nuke disk should store its original station.
|
||||||
// This is fine for now, because we can assume a single station in base SS14.
|
// This is fine for now, because we can assume a single station in base SS14.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spawns Central Command (emergency destination) for a station.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class StationCentcommComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Crude shuttle offset spawning.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("shuttleIndex")]
|
||||||
|
public float ShuttleIndex;
|
||||||
|
|
||||||
|
[DataField("map")]
|
||||||
|
public ResPath Map = new("/Maps/centcomm.yml");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Centcomm entity that was loaded.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("entity")]
|
||||||
|
public EntityUid Entity = EntityUid.Invalid;
|
||||||
|
|
||||||
|
public MapId MapId = MapId.Nullspace;
|
||||||
|
}
|
||||||
@@ -154,39 +154,39 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
{
|
{
|
||||||
_launchedShuttles = true;
|
_launchedShuttles = true;
|
||||||
|
|
||||||
if (CentComMap != null)
|
var dataQuery = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||||
|
|
||||||
|
while (dataQuery.MoveNext(out var stationUid, out var comp))
|
||||||
{
|
{
|
||||||
var dataQuery = AllEntityQuery<StationEmergencyShuttleComponent>();
|
if (!TryComp<ShuttleComponent>(comp.EmergencyShuttle, out var shuttle) ||
|
||||||
|
!TryComp<StationCentcommComponent>(stationUid, out var centcomm))
|
||||||
while (dataQuery.MoveNext(out var comp))
|
|
||||||
{
|
{
|
||||||
if (!TryComp<ShuttleComponent>(comp.EmergencyShuttle, out var shuttle))
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Deleted(CentComGrid))
|
|
||||||
{
|
|
||||||
// TODO: Need to get non-overlapping positions.
|
|
||||||
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
|
||||||
new EntityCoordinates(
|
|
||||||
_mapManager.GetMapEntityId(CentComMap.Value),
|
|
||||||
_random.NextVector2(1000f)), _consoleAccumulator, TransitTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
|
||||||
CentComGrid.Value, _consoleAccumulator, TransitTime, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var podQuery = AllEntityQuery<EscapePodComponent>();
|
if (Deleted(centcomm.Entity))
|
||||||
var podLaunchOffset = 0.5f;
|
|
||||||
|
|
||||||
// Stagger launches coz funny
|
|
||||||
while (podQuery.MoveNext(out _, out var pod))
|
|
||||||
{
|
{
|
||||||
pod.LaunchTime = _timing.CurTime + TimeSpan.FromSeconds(podLaunchOffset);
|
// TODO: Need to get non-overlapping positions.
|
||||||
podLaunchOffset += _random.NextFloat(0.5f, 2.5f);
|
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
||||||
|
new EntityCoordinates(
|
||||||
|
_mapManager.GetMapEntityId(centcomm.MapId),
|
||||||
|
_random.NextVector2(1000f)), _consoleAccumulator, TransitTime);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
||||||
|
centcomm.Entity, _consoleAccumulator, TransitTime, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var podQuery = AllEntityQuery<EscapePodComponent>();
|
||||||
|
var podLaunchOffset = 0.5f;
|
||||||
|
|
||||||
|
// Stagger launches coz funny
|
||||||
|
while (podQuery.MoveNext(out _, out var pod))
|
||||||
|
{
|
||||||
|
pod.LaunchTime = _timing.CurTime + TimeSpan.FromSeconds(podLaunchOffset);
|
||||||
|
podLaunchOffset += _random.NextFloat(0.5f, 2.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,13 +194,16 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
|
|
||||||
while (podLaunchQuery.MoveNext(out var uid, out var pod, out var shuttle))
|
while (podLaunchQuery.MoveNext(out var uid, out var pod, out var shuttle))
|
||||||
{
|
{
|
||||||
if (CentComGrid == null || pod.LaunchTime == null || pod.LaunchTime < _timing.CurTime)
|
var stationUid = _station.GetOwningStation(uid);
|
||||||
|
|
||||||
|
if (!TryComp<StationCentcommComponent>(stationUid, out var centcomm) ||
|
||||||
|
Deleted(centcomm.Entity) || pod.LaunchTime == null || pod.LaunchTime < _timing.CurTime)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't dock them. If you do end up doing this then stagger launch.
|
// Don't dock them. If you do end up doing this then stagger launch.
|
||||||
_shuttle.FTLTravel(uid, shuttle,
|
_shuttle.FTLTravel(uid, shuttle, centcomm.Entity, hyperspaceTime: TransitTime);
|
||||||
CentComGrid.Value, hyperspaceTime: TransitTime);
|
|
||||||
|
|
||||||
RemCompDeferred<EscapePodComponent>(uid);
|
RemCompDeferred<EscapePodComponent>(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,16 +213,22 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
_leftShuttles = true;
|
_leftShuttles = true;
|
||||||
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}")));
|
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}")));
|
||||||
|
|
||||||
_roundEndCancelToken = new CancellationTokenSource();
|
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken?.Token ?? default);
|
||||||
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken.Token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All the others.
|
// All the others.
|
||||||
if (_consoleAccumulator < minTime)
|
if (_consoleAccumulator < minTime)
|
||||||
{
|
{
|
||||||
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
// Guarantees that emergency shuttle arrives first before anyone else can FTL.
|
// Guarantees that emergency shuttle arrives first before anyone else can FTL.
|
||||||
if (CentComGrid != null)
|
while (query.MoveNext(out var comp))
|
||||||
_shuttle.AddFTLDestination(CentComGrid.Value, true);
|
{
|
||||||
|
if (Deleted(comp.Entity))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_shuttle.AddFTLDestination(comp.Entity, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +380,9 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
|
|
||||||
public bool DelayEmergencyRoundEnd()
|
public bool DelayEmergencyRoundEnd()
|
||||||
{
|
{
|
||||||
if (_roundEndCancelToken == null) return false;
|
if (_roundEndCancelToken == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
_roundEndCancelToken?.Cancel();
|
_roundEndCancelToken?.Cancel();
|
||||||
_roundEndCancelToken = null;
|
_roundEndCancelToken = null;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Threading;
|
||||||
using Content.Server.Access.Systems;
|
using Content.Server.Access.Systems;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
@@ -23,7 +23,6 @@ using Robust.Shared.Map;
|
|||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems;
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
@@ -54,14 +53,6 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
public MapId? CentComMap { get; private set; }
|
|
||||||
public EntityUid? CentComGrid { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used for multiple shuttle spawn offsets.
|
|
||||||
/// </summary>
|
|
||||||
private float _shuttleIndex;
|
|
||||||
|
|
||||||
private const float ShuttleSpawnBuffer = 1f;
|
private const float ShuttleSpawnBuffer = 1f;
|
||||||
|
|
||||||
private bool _emergencyShuttleEnabled;
|
private bool _emergencyShuttleEnabled;
|
||||||
@@ -76,14 +67,35 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
_configManager.OnValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
_configManager.OnValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
||||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
|
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
|
||||||
SubscribeLocalEvent<StationEmergencyShuttleComponent, ComponentStartup>(OnStationStartup);
|
SubscribeLocalEvent<StationEmergencyShuttleComponent, ComponentStartup>(OnStationStartup);
|
||||||
|
SubscribeLocalEvent<StationCentcommComponent, ComponentShutdown>(OnCentcommShutdown);
|
||||||
|
SubscribeLocalEvent<StationCentcommComponent, ComponentInit>(OnCentcommInit);
|
||||||
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
||||||
InitializeEmergencyConsole();
|
InitializeEmergencyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRoundStart(RoundStartingEvent ev)
|
||||||
|
{
|
||||||
|
CleanupEmergencyConsole();
|
||||||
|
_roundEndCancelToken?.Cancel();
|
||||||
|
_roundEndCancelToken = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCentcommShutdown(EntityUid uid, StationCentcommComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
QueueDel(component.Entity);
|
||||||
|
component.Entity = EntityUid.Invalid;
|
||||||
|
|
||||||
|
if (_mapManager.MapExists(component.MapId))
|
||||||
|
_mapManager.DeleteMap(component.MapId);
|
||||||
|
|
||||||
|
component.MapId = MapId.Nullspace;
|
||||||
|
}
|
||||||
|
|
||||||
private void SetEmergencyShuttleEnabled(bool value)
|
private void SetEmergencyShuttleEnabled(bool value)
|
||||||
{
|
{
|
||||||
if (_emergencyShuttleEnabled == value)
|
if (_emergencyShuttleEnabled == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_emergencyShuttleEnabled = value;
|
_emergencyShuttleEnabled = value;
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
@@ -96,6 +108,16 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CleanupEmergencyShuttle()
|
||||||
|
{
|
||||||
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out _))
|
||||||
|
{
|
||||||
|
RemCompDeferred<StationCentcommComponent>(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
@@ -146,22 +168,22 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls the emergency shuttle for the station.
|
/// Calls the emergency shuttle for the station.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CallEmergencyShuttle(EntityUid? stationUid)
|
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
|
||||||
{
|
{
|
||||||
if (!TryComp<StationEmergencyShuttleComponent>(stationUid, out var stationShuttle) ||
|
if (!Resolve(stationUid, ref stationShuttle) ||
|
||||||
!TryComp<TransformComponent>(stationShuttle.EmergencyShuttle, out var xform) ||
|
!TryComp<TransformComponent>(stationShuttle.EmergencyShuttle, out var xform) ||
|
||||||
!TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle))
|
!TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid.Value));
|
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid));
|
||||||
|
|
||||||
// UHH GOOD LUCK
|
// UHH GOOD LUCK
|
||||||
if (targetGrid == null)
|
if (targetGrid == null)
|
||||||
{
|
{
|
||||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} unable to dock with station {ToPrettyString(stationUid.Value)}");
|
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
|
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
|
||||||
// TODO: Need filter extensions or something don't blame me.
|
// TODO: Need filter extensions or something don't blame me.
|
||||||
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||||
return;
|
return;
|
||||||
@@ -174,10 +196,10 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||||
{
|
{
|
||||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false);
|
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} docked with stations");
|
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
|
||||||
// TODO: Need filter extensions or something don't blame me.
|
// TODO: Need filter extensions or something don't blame me.
|
||||||
_audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true);
|
_audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true);
|
||||||
}
|
}
|
||||||
@@ -186,35 +208,33 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||||
{
|
{
|
||||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} unable to find a valid docking port for {ToPrettyString(stationUid.Value)}");
|
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
|
||||||
// TODO: Need filter extensions or something don't blame me.
|
// TODO: Need filter extensions or something don't blame me.
|
||||||
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
|
private void OnCentcommInit(EntityUid uid, StationCentcommComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
AddEmergencyShuttle(component);
|
if (!_emergencyShuttleEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Post mapinit? fancy
|
||||||
|
if (TryComp<TransformComponent>(component.Entity, out var xform))
|
||||||
|
{
|
||||||
|
component.MapId = xform.MapID;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCentcomm(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoundStart(RoundStartingEvent ev)
|
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
if (CentComMap != null)
|
AddEmergencyShuttle(uid, component);
|
||||||
_mapManager.DeleteMap(CentComMap.Value);
|
|
||||||
|
|
||||||
// Just in case the grid isn't on the map.
|
|
||||||
DebugTools.Assert(Deleted(CentComGrid));
|
|
||||||
if (CentComGrid != null)
|
|
||||||
Del(CentComGrid.Value);
|
|
||||||
|
|
||||||
CentComGrid = null;
|
|
||||||
CentComMap = null;
|
|
||||||
|
|
||||||
CleanupEmergencyConsole();
|
|
||||||
SetupEmergencyShuttle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -234,14 +254,11 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
_consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime);
|
_consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime);
|
||||||
EmergencyShuttleArrived = true;
|
EmergencyShuttleArrived = true;
|
||||||
|
|
||||||
if (CentComMap != null)
|
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||||
_mapManager.SetMapPaused(CentComMap.Value, false);
|
|
||||||
|
|
||||||
var query = AllEntityQuery<StationDataComponent>();
|
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
CallEmergencyShuttle(uid);
|
CallEmergencyShuttle(uid, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_commsConsole.UpdateCommsConsoleInterface();
|
_commsConsole.UpdateCommsConsoleInterface();
|
||||||
@@ -249,80 +266,111 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
|||||||
|
|
||||||
private void SetupEmergencyShuttle()
|
private void SetupEmergencyShuttle()
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled || CentComMap != null && _mapManager.MapExists(CentComMap.Value)) return;
|
if (!_emergencyShuttleEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
CentComMap = _mapManager.CreateMap();
|
var centcommQuery = AllEntityQuery<StationCentcommComponent>();
|
||||||
_mapManager.SetMapPaused(CentComMap.Value, true);
|
|
||||||
|
|
||||||
// Load CentCom
|
while (centcommQuery.MoveNext(out var centcomm))
|
||||||
var centComPath = _configManager.GetCVar(CCVars.CentcommMap);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(centComPath))
|
|
||||||
{
|
{
|
||||||
var centcomm = _map.LoadGrid(CentComMap.Value, "/Maps/centcomm.yml");
|
AddCentcomm(centcomm);
|
||||||
CentComGrid = centcomm;
|
|
||||||
|
|
||||||
if (CentComGrid != null)
|
|
||||||
_shuttle.AddFTLDestination(CentComGrid.Value, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_sawmill.Info("No CentCom map found, skipping setup.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var comp in EntityQuery<StationEmergencyShuttleComponent>(true))
|
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
AddEmergencyShuttle(comp);
|
AddEmergencyShuttle(uid, comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddEmergencyShuttle(StationEmergencyShuttleComponent component)
|
private void AddCentcomm(StationCentcommComponent component)
|
||||||
|
{
|
||||||
|
// Check for existing centcomms and just point to that
|
||||||
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var otherComp))
|
||||||
|
{
|
||||||
|
if (otherComp == component)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
component.MapId = otherComp.MapId;
|
||||||
|
component.ShuttleIndex = otherComp.ShuttleIndex;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapId = _mapManager.CreateMap();
|
||||||
|
component.MapId = mapId;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(component.Map.ToString()))
|
||||||
|
{
|
||||||
|
var ent = _map.LoadGrid(mapId, component.Map.ToString());
|
||||||
|
|
||||||
|
if (ent != null)
|
||||||
|
{
|
||||||
|
component.Entity = ent.Value;
|
||||||
|
_shuttle.AddFTLDestination(ent.Value, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sawmill.Warning("No CentComm map found, skipping setup.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<MapId> GetCentcommMaps()
|
||||||
|
{
|
||||||
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
var maps = new HashSet<MapId>(Count<StationCentcommComponent>());
|
||||||
|
|
||||||
|
while (query.MoveNext(out var comp))
|
||||||
|
{
|
||||||
|
maps.Add(comp.MapId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component)
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled
|
if (!_emergencyShuttleEnabled
|
||||||
|| CentComMap == null
|
|| component.EmergencyShuttle != null ||
|
||||||
|| component.EmergencyShuttle != null)
|
!TryComp<StationCentcommComponent>(uid, out var centcomm))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load escape shuttle
|
// Load escape shuttle
|
||||||
var shuttlePath = component.EmergencyShuttlePath;
|
var shuttlePath = component.EmergencyShuttlePath;
|
||||||
var shuttle = _map.LoadGrid(CentComMap.Value, shuttlePath.ToString(), new MapLoadOptions()
|
var shuttle = _map.LoadGrid(centcomm.MapId, shuttlePath.ToString(), new MapLoadOptions()
|
||||||
{
|
{
|
||||||
// Should be far enough... right? I'm too lazy to bounds check CentCom rn.
|
// Should be far enough... right? I'm too lazy to bounds check CentCom rn.
|
||||||
Offset = new Vector2(500f + _shuttleIndex, 0f)
|
Offset = new Vector2(500f + centcomm.ShuttleIndex, 0f)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shuttle == null)
|
if (shuttle == null)
|
||||||
{
|
{
|
||||||
_sawmill.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(component.Owner)}");
|
_sawmill.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(uid)}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_shuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
|
centcomm.ShuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
|
||||||
|
|
||||||
|
// Update indices for all centcomm comps pointing to same map
|
||||||
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var comp))
|
||||||
|
{
|
||||||
|
if (comp == centcomm || comp.MapId != centcomm.MapId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comp.ShuttleIndex = comp.ShuttleIndex;
|
||||||
|
}
|
||||||
|
|
||||||
component.EmergencyShuttle = shuttle;
|
component.EmergencyShuttle = shuttle;
|
||||||
EnsureComp<ProtectedGridComponent>(shuttle.Value);
|
EnsureComp<ProtectedGridComponent>(shuttle.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CleanupEmergencyShuttle()
|
|
||||||
{
|
|
||||||
// If we get cleaned up mid roundend just end it.
|
|
||||||
if (_launchedShuttles)
|
|
||||||
{
|
|
||||||
_roundEnd.EndRound();
|
|
||||||
}
|
|
||||||
|
|
||||||
_shuttleIndex = 0f;
|
|
||||||
|
|
||||||
if (CentComMap == null || !_mapManager.MapExists(CentComMap.Value))
|
|
||||||
{
|
|
||||||
CentComMap = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mapManager.DeleteMap(CentComMap.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEscapeUnpaused(EntityUid uid, EscapePodComponent component, ref EntityUnpausedEvent args)
|
private void OnEscapeUnpaused(EntityUid uid, EscapePodComponent component, ref EntityUnpausedEvent args)
|
||||||
{
|
{
|
||||||
if (component.LaunchTime == null)
|
if (component.LaunchTime == null)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
|
using Content.Server.Station.Components;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems;
|
namespace Content.Server.Shuttles.Systems;
|
||||||
@@ -39,6 +40,12 @@ public sealed partial class ShuttleSystem
|
|||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
FTLDock(config, shuttleXform);
|
FTLDock(config, shuttleXform);
|
||||||
|
|
||||||
|
if (TryComp<StationMemberComponent>(xform.GridUid, out var stationMember))
|
||||||
|
{
|
||||||
|
_station.AddGridToStation(stationMember.Station, ent[0]);
|
||||||
|
}
|
||||||
|
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
using Content.Server.Doors.Systems;
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
@@ -33,6 +34,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
|
|||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
||||||
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly StunSystem _stuns = default!;
|
[Dependency] private readonly StunSystem _stuns = default!;
|
||||||
[Dependency] private readonly ThrusterSystem _thruster = default!;
|
[Dependency] private readonly ThrusterSystem _thruster = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|||||||
@@ -1171,12 +1171,6 @@ namespace Content.Shared.CCVar
|
|||||||
public static readonly CVarDef<int> EmergencyShuttleAutoCallExtensionTime =
|
public static readonly CVarDef<int> EmergencyShuttleAutoCallExtensionTime =
|
||||||
CVarDef.Create("shuttle.auto_call_extension_time", 45, CVar.SERVERONLY);
|
CVarDef.Create("shuttle.auto_call_extension_time", 45, CVar.SERVERONLY);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The map to load for CentCom for the emergency shuttle to dock to.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly CVarDef<string> CentcommMap =
|
|
||||||
CVarDef.Create("shuttle.centcomm_map", "/Maps/centcomm.yml", CVar.SERVERONLY);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Crew Manifests
|
* Crew Manifests
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,6 +31,12 @@
|
|||||||
components:
|
components:
|
||||||
- type: StationArrivals
|
- type: StationArrivals
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: BaseStationCentcomm
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: StationCentcomm
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BaseStationEvacuation
|
id: BaseStationEvacuation
|
||||||
abstract: true
|
abstract: true
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
- BaseStationJobsSpawning
|
- BaseStationJobsSpawning
|
||||||
- BaseStationRecords
|
- BaseStationRecords
|
||||||
- BaseStationArrivals
|
- BaseStationArrivals
|
||||||
|
- BaseStationCentcomm
|
||||||
- BaseStationEvacuation
|
- BaseStationEvacuation
|
||||||
- BaseStationAlertLevels
|
- BaseStationAlertLevels
|
||||||
- BaseStationExpeditions
|
- BaseStationExpeditions
|
||||||
|
|||||||
Reference in New Issue
Block a user