escape + kill objective changes (#17890)
* 3 space indent at start of line jumpscare * _leftShuttles -> ShuttlesLeft * stuff * RequireDead override for the future * fix 50% logic * rouge * pod 1984 * technically more "difficult" --------- Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -1,10 +1,8 @@
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Systems;
|
||||||
using Content.Server.Station.Components;
|
|
||||||
using Content.Shared.Cuffs.Components;
|
using Content.Shared.Cuffs.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Map.Components;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Conditions
|
namespace Content.Server.Objectives.Conditions
|
||||||
@@ -28,22 +26,6 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|
|
||||||
public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ("Structures/Furniture/chairs.rsi"), "shuttle");
|
public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ("Structures/Furniture/chairs.rsi"), "shuttle");
|
||||||
|
|
||||||
private bool IsAgentOnShuttle(TransformComponent agentXform, EntityUid? shuttle)
|
|
||||||
{
|
|
||||||
if (shuttle == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
|
||||||
|
|
||||||
if (!entMan.TryGetComponent<MapGridComponent>(shuttle, out var shuttleGrid) ||
|
|
||||||
!entMan.TryGetComponent<TransformComponent>(shuttle, out var shuttleXform))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shuttleXform.WorldMatrix.TransformBox(shuttleGrid.LocalAABB).Contains(agentXform.WorldPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float Progress
|
public float Progress
|
||||||
{
|
{
|
||||||
get {
|
get {
|
||||||
@@ -54,25 +36,22 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
|| !entMan.TryGetComponent<TransformComponent>(_mind.OwnedEntity, out var xform))
|
|| !entMan.TryGetComponent<TransformComponent>(_mind.OwnedEntity, out var xform))
|
||||||
return 0f;
|
return 0f;
|
||||||
|
|
||||||
var shuttleContainsAgent = false;
|
if (mindSystem.IsCharacterDeadIc(_mind))
|
||||||
var agentIsAlive = !mindSystem.IsCharacterDeadIc(_mind);
|
return 0f;
|
||||||
var agentIsEscaping = true;
|
|
||||||
|
|
||||||
if (entMan.TryGetComponent<CuffableComponent>(_mind.OwnedEntity, out var cuffed)
|
if (entMan.TryGetComponent<CuffableComponent>(_mind.OwnedEntity, out var cuffed)
|
||||||
&& cuffed.CuffedHandCount > 0)
|
&& cuffed.CuffedHandCount > 0)
|
||||||
// You're not escaping if you're restrained!
|
|
||||||
agentIsEscaping = false;
|
|
||||||
|
|
||||||
// Any emergency shuttle counts for this objective.
|
|
||||||
foreach (var stationData in entMan.EntityQuery<StationEmergencyShuttleComponent>())
|
|
||||||
{
|
{
|
||||||
if (IsAgentOnShuttle(xform, stationData.EmergencyShuttle)) {
|
// You're not escaping if you're restrained!
|
||||||
shuttleContainsAgent = true;
|
return 0f;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (shuttleContainsAgent && agentIsAlive && agentIsEscaping) ? 1f : 0f;
|
// Any emergency shuttle counts for this objective, but not pods.
|
||||||
|
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
|
||||||
|
if (!emergencyShuttle.IsTargetEscaping(_mind.OwnedEntity.Value))
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
return 1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Objectives.Interfaces;
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Objectives.Conditions
|
namespace Content.Server.Objectives.Conditions
|
||||||
@@ -12,6 +15,11 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
protected Mind.Mind? Target;
|
protected Mind.Mind? Target;
|
||||||
public abstract IObjectiveCondition GetAssigned(Mind.Mind mind);
|
public abstract IObjectiveCondition GetAssigned(Mind.Mind mind);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the target must be truly dead, ignores missing evac.
|
||||||
|
/// </summary>
|
||||||
|
protected bool RequireDead = false;
|
||||||
|
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -37,13 +45,37 @@ namespace Content.Server.Objectives.Conditions
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var entityManager = IoCManager.Resolve<EntityManager>();
|
if (Target == null || Target.OwnedEntity == null)
|
||||||
var mindSystem = entityManager.System<MindSystem>();
|
return 1f;
|
||||||
return Target == null || mindSystem.IsCharacterDeadIc(Target) ? 1f : 0f;
|
|
||||||
|
var entMan = IoCManager.Resolve<EntityManager>();
|
||||||
|
var mindSystem = entMan.System<MindSystem>();
|
||||||
|
if (mindSystem.IsCharacterDeadIc(Target))
|
||||||
|
return 1f;
|
||||||
|
|
||||||
|
if (RequireDead)
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
// if evac is disabled then they really do have to be dead
|
||||||
|
var configMan = IoCManager.Resolve<IConfigurationManager>();
|
||||||
|
if (!configMan.GetCVar(CCVars.EmergencyShuttleEnabled))
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
// target is escaping so you fail
|
||||||
|
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
|
||||||
|
if (emergencyShuttle.IsTargetEscaping(Target.OwnedEntity.Value))
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
// evac has left without the target, greentext since the target is afk in space with a full oxygen tank and coordinates off.
|
||||||
|
if (emergencyShuttle.ShuttlesLeft)
|
||||||
|
return 1f;
|
||||||
|
|
||||||
|
// if evac is still here and target hasn't boarded, show 50% to give you an indicator that you are doing good
|
||||||
|
return emergencyShuttle.EmergencyShuttleArrived ? 0f : 0.5f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Difficulty => 2f;
|
public float Difficulty => 1.75f;
|
||||||
|
|
||||||
public bool Equals(IObjectiveCondition? other)
|
public bool Equals(IObjectiveCondition? other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,7 +71,10 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _launchedShuttles;
|
private bool _launchedShuttles;
|
||||||
|
|
||||||
private bool _leftShuttles;
|
/// <summary>
|
||||||
|
/// Have the emergency shuttles left for CentCom?
|
||||||
|
/// </summary>
|
||||||
|
public bool ShuttlesLeft;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Have we announced the launch?
|
/// Have we announced the launch?
|
||||||
@@ -209,9 +212,9 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Departed
|
// Departed
|
||||||
if (!_leftShuttles && _consoleAccumulator <= 0f)
|
if (!ShuttlesLeft && _consoleAccumulator <= 0f)
|
||||||
{
|
{
|
||||||
_leftShuttles = true;
|
ShuttlesLeft = true;
|
||||||
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}")));
|
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}")));
|
||||||
|
|
||||||
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken?.Token ?? default);
|
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken?.Token ?? default);
|
||||||
@@ -309,7 +312,7 @@ public sealed partial class EmergencyShuttleSystem
|
|||||||
{
|
{
|
||||||
_announced = false;
|
_announced = false;
|
||||||
_roundEndCancelToken = null;
|
_roundEndCancelToken = null;
|
||||||
_leftShuttles = false;
|
ShuttlesLeft = false;
|
||||||
_launchedShuttles = false;
|
_launchedShuttles = false;
|
||||||
_consoleAccumulator = float.MinValue;
|
_consoleAccumulator = float.MinValue;
|
||||||
EarlyLaunchAuthorized = false;
|
EarlyLaunchAuthorized = false;
|
||||||
|
|||||||
@@ -31,355 +31,388 @@ namespace Content.Server.Shuttles.Systems;
|
|||||||
|
|
||||||
public sealed partial class EmergencyShuttleSystem : EntitySystem
|
public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Handles the escape shuttle + CentCom.
|
* Handles the escape shuttle + CentCom.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Dependency] private readonly IAdminLogManager _logger = default!;
|
[Dependency] private readonly IAdminLogManager _logger = default!;
|
||||||
[Dependency] private readonly IAdminManager _admin = default!;
|
[Dependency] private readonly IAdminManager _admin = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _reader = default!;
|
[Dependency] private readonly AccessReaderSystem _reader = default!;
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
[Dependency] private readonly CommunicationsConsoleSystem _commsConsole = default!;
|
[Dependency] private readonly CommunicationsConsoleSystem _commsConsole = default!;
|
||||||
[Dependency] private readonly DockingSystem _dock = default!;
|
[Dependency] private readonly DockingSystem _dock = default!;
|
||||||
[Dependency] private readonly IdCardSystem _idSystem = default!;
|
[Dependency] private readonly IdCardSystem _idSystem = default!;
|
||||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
private const float ShuttleSpawnBuffer = 1f;
|
private const float ShuttleSpawnBuffer = 1f;
|
||||||
|
|
||||||
private bool _emergencyShuttleEnabled;
|
private bool _emergencyShuttleEnabled;
|
||||||
|
|
||||||
private const string DockTag = "DockEmergency";
|
private const string DockTag = "DockEmergency";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
_sawmill = Logger.GetSawmill("shuttle.emergency");
|
_sawmill = Logger.GetSawmill("shuttle.emergency");
|
||||||
_emergencyShuttleEnabled = _configManager.GetCVar(CCVars.EmergencyShuttleEnabled);
|
_emergencyShuttleEnabled = _configManager.GetCVar(CCVars.EmergencyShuttleEnabled);
|
||||||
// Don't immediately invoke as roundstart will just handle it.
|
// Don't immediately invoke as roundstart will just handle it.
|
||||||
_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, ComponentShutdown>(OnCentcommShutdown);
|
||||||
SubscribeLocalEvent<StationCentcommComponent, ComponentInit>(OnCentcommInit);
|
SubscribeLocalEvent<StationCentcommComponent, ComponentInit>(OnCentcommInit);
|
||||||
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
||||||
InitializeEmergencyConsole();
|
InitializeEmergencyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoundStart(RoundStartingEvent ev)
|
private void OnRoundStart(RoundStartingEvent ev)
|
||||||
{
|
{
|
||||||
CleanupEmergencyConsole();
|
CleanupEmergencyConsole();
|
||||||
_roundEndCancelToken?.Cancel();
|
_roundEndCancelToken?.Cancel();
|
||||||
_roundEndCancelToken = new CancellationTokenSource();
|
_roundEndCancelToken = new CancellationTokenSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCentcommShutdown(EntityUid uid, StationCentcommComponent component, ComponentShutdown args)
|
private void OnCentcommShutdown(EntityUid uid, StationCentcommComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
QueueDel(component.Entity);
|
QueueDel(component.Entity);
|
||||||
component.Entity = EntityUid.Invalid;
|
component.Entity = EntityUid.Invalid;
|
||||||
|
|
||||||
if (_mapManager.MapExists(component.MapId))
|
if (_mapManager.MapExists(component.MapId))
|
||||||
_mapManager.DeleteMap(component.MapId);
|
_mapManager.DeleteMap(component.MapId);
|
||||||
|
|
||||||
component.MapId = MapId.Nullspace;
|
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)
|
||||||
{
|
{
|
||||||
SetupEmergencyShuttle();
|
SetupEmergencyShuttle();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CleanupEmergencyShuttle();
|
CleanupEmergencyShuttle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CleanupEmergencyShuttle()
|
private void CleanupEmergencyShuttle()
|
||||||
{
|
{
|
||||||
var query = AllEntityQuery<StationCentcommComponent>();
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out _))
|
while (query.MoveNext(out var uid, out _))
|
||||||
{
|
{
|
||||||
RemCompDeferred<StationCentcommComponent>(uid);
|
RemCompDeferred<StationCentcommComponent>(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
UpdateEmergencyConsole(frameTime);
|
UpdateEmergencyConsole(frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
_configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
_configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
||||||
ShutdownEmergencyConsole();
|
ShutdownEmergencyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the client is requesting debug info on where an emergency shuttle would dock.
|
/// If the client is requesting debug info on where an emergency shuttle would dock.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args)
|
private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args)
|
||||||
{
|
{
|
||||||
if (!_admin.IsAdmin((IPlayerSession) args.SenderSession))
|
if (!_admin.IsAdmin((IPlayerSession) args.SenderSession))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var player = args.SenderSession.AttachedEntity;
|
var player = args.SenderSession.AttachedEntity;
|
||||||
if (player is null)
|
if (player is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var station = _station.GetOwningStation(player.Value);
|
var station = _station.GetOwningStation(player.Value);
|
||||||
|
|
||||||
if (!TryComp<StationEmergencyShuttleComponent>(station, out var stationShuttle) ||
|
if (!TryComp<StationEmergencyShuttleComponent>(station, out var stationShuttle) ||
|
||||||
!HasComp<ShuttleComponent>(stationShuttle.EmergencyShuttle))
|
!HasComp<ShuttleComponent>(stationShuttle.EmergencyShuttle))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(station.Value));
|
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(station.Value));
|
||||||
if (targetGrid == null)
|
if (targetGrid == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var config = _dock.GetDockingConfig(stationShuttle.EmergencyShuttle.Value, targetGrid.Value, DockTag);
|
var config = _dock.GetDockingConfig(stationShuttle.EmergencyShuttle.Value, targetGrid.Value, DockTag);
|
||||||
if (config == null)
|
if (config == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
|
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
|
||||||
{
|
{
|
||||||
StationUid = targetGrid,
|
StationUid = targetGrid,
|
||||||
Position = config.Area,
|
Position = config.Area,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls the emergency shuttle for the station.
|
/// Calls the emergency shuttle for the station.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
|
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(stationUid, ref 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));
|
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)} unable to dock with station {ToPrettyString(stationUid)}");
|
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
|
||||||
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
|
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
|
||||||
{
|
{
|
||||||
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, 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)} 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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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, 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)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
|
_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 OnCentcommInit(EntityUid uid, StationCentcommComponent component, ComponentInit args)
|
private void OnCentcommInit(EntityUid uid, StationCentcommComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled)
|
if (!_emergencyShuttleEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Post mapinit? fancy
|
// Post mapinit? fancy
|
||||||
if (TryComp<TransformComponent>(component.Entity, out var xform))
|
if (TryComp<TransformComponent>(component.Entity, out var xform))
|
||||||
{
|
{
|
||||||
component.MapId = xform.MapID;
|
component.MapId = xform.MapID;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddCentcomm(component);
|
AddCentcomm(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
|
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
AddEmergencyShuttle(uid, component);
|
AddEmergencyShuttle(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spawns the emergency shuttle for each station and starts the countdown until controls unlock.
|
/// Spawns the emergency shuttle for each station and starts the countdown until controls unlock.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CallEmergencyShuttle()
|
public void CallEmergencyShuttle()
|
||||||
{
|
{
|
||||||
if (EmergencyShuttleArrived)
|
if (EmergencyShuttleArrived)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_emergencyShuttleEnabled)
|
if (!_emergencyShuttleEnabled)
|
||||||
{
|
{
|
||||||
_roundEnd.EndRound();
|
_roundEnd.EndRound();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime);
|
_consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime);
|
||||||
EmergencyShuttleArrived = true;
|
EmergencyShuttleArrived = true;
|
||||||
|
|
||||||
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
CallEmergencyShuttle(uid, comp);
|
CallEmergencyShuttle(uid, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_commsConsole.UpdateCommsConsoleInterface();
|
_commsConsole.UpdateCommsConsoleInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupEmergencyShuttle()
|
private void SetupEmergencyShuttle()
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled)
|
if (!_emergencyShuttleEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var centcommQuery = AllEntityQuery<StationCentcommComponent>();
|
var centcommQuery = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
while (centcommQuery.MoveNext(out var centcomm))
|
while (centcommQuery.MoveNext(out var centcomm))
|
||||||
{
|
{
|
||||||
AddCentcomm(centcomm);
|
AddCentcomm(centcomm);
|
||||||
}
|
}
|
||||||
|
|
||||||
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
AddEmergencyShuttle(uid, comp);
|
AddEmergencyShuttle(uid, comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCentcomm(StationCentcommComponent component)
|
private void AddCentcomm(StationCentcommComponent component)
|
||||||
{
|
{
|
||||||
// Check for existing centcomms and just point to that
|
// Check for existing centcomms and just point to that
|
||||||
var query = AllEntityQuery<StationCentcommComponent>();
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var otherComp))
|
while (query.MoveNext(out var otherComp))
|
||||||
{
|
{
|
||||||
if (otherComp == component)
|
if (otherComp == component)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
component.MapId = otherComp.MapId;
|
component.MapId = otherComp.MapId;
|
||||||
component.ShuttleIndex = otherComp.ShuttleIndex;
|
component.ShuttleIndex = otherComp.ShuttleIndex;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapId = _mapManager.CreateMap();
|
var mapId = _mapManager.CreateMap();
|
||||||
component.MapId = mapId;
|
component.MapId = mapId;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(component.Map.ToString()))
|
if (!string.IsNullOrEmpty(component.Map.ToString()))
|
||||||
{
|
{
|
||||||
var ent = _map.LoadGrid(mapId, component.Map.ToString());
|
var ent = _map.LoadGrid(mapId, component.Map.ToString());
|
||||||
|
|
||||||
if (ent != null)
|
if (ent != null)
|
||||||
{
|
{
|
||||||
component.Entity = ent.Value;
|
component.Entity = ent.Value;
|
||||||
_shuttle.AddFTLDestination(ent.Value, false);
|
_shuttle.AddFTLDestination(ent.Value, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_sawmill.Warning("No CentComm map found, skipping setup.");
|
_sawmill.Warning("No CentComm map found, skipping setup.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashSet<MapId> GetCentcommMaps()
|
public HashSet<MapId> GetCentcommMaps()
|
||||||
{
|
{
|
||||||
var query = AllEntityQuery<StationCentcommComponent>();
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
var maps = new HashSet<MapId>(Count<StationCentcommComponent>());
|
var maps = new HashSet<MapId>(Count<StationCentcommComponent>());
|
||||||
|
|
||||||
while (query.MoveNext(out var comp))
|
while (query.MoveNext(out var comp))
|
||||||
{
|
{
|
||||||
maps.Add(comp.MapId);
|
maps.Add(comp.MapId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component)
|
private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component)
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled
|
if (!_emergencyShuttleEnabled
|
||||||
|| component.EmergencyShuttle != null ||
|
|| component.EmergencyShuttle != null ||
|
||||||
!TryComp<StationCentcommComponent>(uid, out var centcomm))
|
!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(centcomm.MapId, 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 + centcomm.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(uid)}");
|
_sawmill.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(uid)}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
centcomm.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
|
// Update indices for all centcomm comps pointing to same map
|
||||||
var query = AllEntityQuery<StationCentcommComponent>();
|
var query = AllEntityQuery<StationCentcommComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var comp))
|
while (query.MoveNext(out var comp))
|
||||||
{
|
{
|
||||||
if (comp == centcomm || comp.MapId != centcomm.MapId)
|
if (comp == centcomm || comp.MapId != centcomm.MapId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
comp.ShuttleIndex = centcomm.ShuttleIndex;
|
comp.ShuttleIndex = centcomm.ShuttleIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
component.EmergencyShuttle = shuttle;
|
component.EmergencyShuttle = shuttle;
|
||||||
EnsureComp<ProtectedGridComponent>(shuttle.Value);
|
EnsureComp<ProtectedGridComponent>(shuttle.Value);
|
||||||
EnsureComp<PreventPilotComponent>(shuttle.Value);
|
EnsureComp<PreventPilotComponent>(shuttle.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)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.LaunchTime = component.LaunchTime.Value + args.PausedTime;
|
component.LaunchTime = component.LaunchTime.Value + args.PausedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether a target is escaping on the emergency shuttle, but only if evac has arrived.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTargetEscaping(EntityUid target)
|
||||||
|
{
|
||||||
|
// if evac isn't here then sitting in a pod doesn't return true
|
||||||
|
if (!EmergencyShuttleArrived)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check each emergency shuttle
|
||||||
|
var xform = Transform(target);
|
||||||
|
foreach (var stationData in EntityQuery<StationEmergencyShuttleComponent>())
|
||||||
|
{
|
||||||
|
if (stationData.EmergencyShuttle == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (IsOnGrid(xform, stationData.EmergencyShuttle.Value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsOnGrid(TransformComponent xform, EntityUid shuttle, MapGridComponent? grid = null, TransformComponent? shuttleXform = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(shuttle, ref grid, ref shuttleXform))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return shuttleXform.WorldMatrix.TransformBox(grid.LocalAABB).Contains(xform.WorldPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
objective-condition-escape-shuttle-title = Escape on the emergency shuttle alive and unrestrained.
|
objective-condition-escape-shuttle-title = Escape to centcom alive and unrestrained.
|
||||||
objective-condition-escape-shuttle-description = One of our undercover agents will debrief you when you arrive. Don't show up in cuffs.
|
objective-condition-escape-shuttle-description = One of our undercover agents will debrief you when you arrive. Don't show up in cuffs.
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
objective-condition-kill-person-title = Kill {$targetName}, {CAPITALIZE($job)}
|
objective-condition-kill-person-title = Kill or maroon {$targetName}, {CAPITALIZE($job)}
|
||||||
objective-condition-kill-person-description = Do it however you like, just make sure they don't last the shift.
|
objective-condition-kill-person-description = Do it however you like, just make sure they don't make it to centcom.
|
||||||
|
|||||||
Reference in New Issue
Block a user