Escape pods (#14809)
* Namespace adjustments for days * pod * thanks rider * Fix the oop launch * Fixes * Fix stuff * eeeeeeeee * Fix * access * map * forgor * thing * Genericise escape pod fill
This commit is contained in:
@@ -225,7 +225,7 @@ namespace Content.IntegrationTests.Tests
|
|||||||
Assert.IsNotNull(stationConfig, $"{entManager.ToPrettyString(station)} had null StationConfig.");
|
Assert.IsNotNull(stationConfig, $"{entManager.ToPrettyString(station)} had null StationConfig.");
|
||||||
var shuttlePath = stationConfig.EmergencyShuttlePath.ToString();
|
var shuttlePath = stationConfig.EmergencyShuttlePath.ToString();
|
||||||
var shuttle = mapLoader.LoadGrid(shuttleMap, shuttlePath);
|
var shuttle = mapLoader.LoadGrid(shuttleMap, shuttlePath);
|
||||||
Assert.That(shuttle != null && shuttleSystem.TryFTLDock(entManager.GetComponent<ShuttleComponent>(shuttle.Value), targetGrid.Value), $"Unable to dock {shuttlePath} to {mapProto}");
|
Assert.That(shuttle != null && shuttleSystem.TryFTLDock(shuttle.Value, entManager.GetComponent<ShuttleComponent>(shuttle.Value), targetGrid.Value), $"Unable to dock {shuttlePath} to {mapProto}");
|
||||||
|
|
||||||
mapManager.DeleteMap(shuttleMap);
|
mapManager.DeleteMap(shuttleMap);
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ namespace Content.Server.Communications
|
|||||||
[Dependency] private readonly InteractionSystem _interaction = default!;
|
[Dependency] private readonly InteractionSystem _interaction = default!;
|
||||||
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
|
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
|
[Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
|
||||||
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
|
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
|
||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
@@ -186,7 +186,7 @@ namespace Content.Server.Communications
|
|||||||
private bool CanCallOrRecall(CommunicationsConsoleComponent comp)
|
private bool CanCallOrRecall(CommunicationsConsoleComponent comp)
|
||||||
{
|
{
|
||||||
// Defer to what the round end system thinks we should be able to do.
|
// Defer to what the round end system thinks we should be able to do.
|
||||||
if (_shuttle.EmergencyShuttleArrived || !_roundEndSystem.CanCallOrRecall())
|
if (_emergency.EmergencyShuttleArrived || !_roundEndSystem.CanCallOrRecall())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Calling shuttle checks
|
// Calling shuttle checks
|
||||||
|
|||||||
@@ -43,15 +43,16 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
|
|||||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerSystem = default!;
|
[Dependency] private readonly IPlayerManager _playerSystem = default!;
|
||||||
|
[Dependency] private readonly EmergencyShuttleSystem _emergency = default!;
|
||||||
[Dependency] private readonly FactionSystem _faction = default!;
|
[Dependency] private readonly FactionSystem _faction = default!;
|
||||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
||||||
[Dependency] private readonly StationSpawningSystem _stationSpawningSystem = default!;
|
[Dependency] private readonly StationSpawningSystem _stationSpawningSystem = default!;
|
||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
[Dependency] private readonly ShuttleSystem _shuttleSystem = default!;
|
|
||||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||||
[Dependency] private readonly GameTicker _ticker = default!;
|
[Dependency] private readonly GameTicker _ticker = default!;
|
||||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||||
|
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
||||||
|
|
||||||
|
|
||||||
private enum WinType
|
private enum WinType
|
||||||
@@ -277,7 +278,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UH OH
|
// UH OH
|
||||||
if (nukeTransform.MapID == _shuttleSystem.CentComMap)
|
if (nukeTransform.MapID == _emergency.CentComMap)
|
||||||
{
|
{
|
||||||
_winConditions.Add(WinCondition.NukeActiveAtCentCom);
|
_winConditions.Add(WinCondition.NukeActiveAtCentCom);
|
||||||
RuleWinType = WinType.OpsMajor;
|
RuleWinType = WinType.OpsMajor;
|
||||||
@@ -334,7 +335,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
|
|||||||
foreach (var (_, transform) in EntityManager.EntityQuery<NukeDiskComponent, TransformComponent>())
|
foreach (var (_, transform) in EntityManager.EntityQuery<NukeDiskComponent, TransformComponent>())
|
||||||
{
|
{
|
||||||
var diskMapId = transform.MapID;
|
var diskMapId = transform.MapID;
|
||||||
diskAtCentCom = _shuttleSystem.CentComMap == diskMapId;
|
diskAtCentCom = _emergency.CentComMap == 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.
|
||||||
@@ -655,7 +656,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
|
|||||||
|
|
||||||
if (TryComp<ShuttleComponent>(shuttleId, out var shuttle))
|
if (TryComp<ShuttleComponent>(shuttleId, out var shuttle))
|
||||||
{
|
{
|
||||||
_shuttleSystem.TryFTLDock(shuttle, _nukieOutpost.Value);
|
_shuttle.TryFTLDock(shuttleId, shuttle, _nukieOutpost.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_nukiePlanet = mapId;
|
_nukiePlanet = mapId;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Content.Server.RoundEnd
|
|||||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
[Dependency] private readonly EmergencyShuttleSystem _shuttle = default!;
|
||||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
|
|
||||||
public TimeSpan DefaultCooldownDuration { get; set; } = TimeSpan.FromSeconds(30);
|
public TimeSpan DefaultCooldownDuration { get; set; } = TimeSpan.FromSeconds(30);
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ namespace Content.Server.Shuttles.Commands;
|
|||||||
[AdminCommand(AdminFlags.Fun)]
|
[AdminCommand(AdminFlags.Fun)]
|
||||||
public sealed class DelayRoundEndCommand : IConsoleCommand
|
public sealed class DelayRoundEndCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntitySystemManager _sysManager = default!;
|
||||||
|
|
||||||
public string Command => "delayroundend";
|
public string Command => "delayroundend";
|
||||||
public string Description => Loc.GetString("emergency-shuttle-command-round-desc");
|
public string Description => Loc.GetString("emergency-shuttle-command-round-desc");
|
||||||
public string Help => $"{Command}";
|
public string Help => $"{Command}";
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ShuttleSystem>();
|
var system = _sysManager.GetEntitySystem<EmergencyShuttleSystem>();
|
||||||
|
|
||||||
if (system.DelayEmergencyRoundEnd())
|
if (system.DelayEmergencyRoundEnd())
|
||||||
{
|
{
|
||||||
shell.WriteLine(Loc.GetString("emergency-shuttle-command-round-yes"));
|
shell.WriteLine(Loc.GetString("emergency-shuttle-command-round-yes"));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Content.Server.Shuttles.Systems;
|
|||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles;
|
namespace Content.Server.Shuttles.Commands;
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Mapping)]
|
[AdminCommand(AdminFlags.Mapping)]
|
||||||
public sealed class DockCommand : IConsoleCommand
|
public sealed class DockCommand : IConsoleCommand
|
||||||
@@ -11,12 +11,14 @@ namespace Content.Server.Shuttles.Commands;
|
|||||||
[AdminCommand(AdminFlags.Fun)]
|
[AdminCommand(AdminFlags.Fun)]
|
||||||
public sealed class DockEmergencyShuttleCommand : IConsoleCommand
|
public sealed class DockEmergencyShuttleCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntitySystemManager _sysManager = default!;
|
||||||
|
|
||||||
public string Command => "dockemergencyshuttle";
|
public string Command => "dockemergencyshuttle";
|
||||||
public string Description => Loc.GetString("emergency-shuttle-command-dock-desc");
|
public string Description => Loc.GetString("emergency-shuttle-command-dock-desc");
|
||||||
public string Help => $"{Command}";
|
public string Help => $"{Command}";
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ShuttleSystem>();
|
var system = _sysManager.GetEntitySystem<EmergencyShuttleSystem>();
|
||||||
system.CallEmergencyShuttle();
|
system.CallEmergencyShuttle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ namespace Content.Server.Shuttles.Commands;
|
|||||||
[AdminCommand(AdminFlags.Fun)]
|
[AdminCommand(AdminFlags.Fun)]
|
||||||
public sealed class LaunchEmergencyShuttleCommand : IConsoleCommand
|
public sealed class LaunchEmergencyShuttleCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntitySystemManager _sysManager = default!;
|
||||||
|
|
||||||
public string Command => "launchemergencyshuttle";
|
public string Command => "launchemergencyshuttle";
|
||||||
public string Description => Loc.GetString("emergency-shuttle-command-launch-desc");
|
public string Description => Loc.GetString("emergency-shuttle-command-launch-desc");
|
||||||
public string Help => $"{Command}";
|
public string Help => $"{Command}";
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var system = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ShuttleSystem>();
|
var system = _sysManager.GetEntitySystem<EmergencyShuttleSystem>();
|
||||||
system.EarlyLaunch();
|
system.EarlyLaunch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Components;
|
namespace Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent, Access(typeof(ArrivalsSystem))]
|
||||||
public sealed class ArrivalsShuttleComponent : Component
|
public sealed class ArrivalsShuttleComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("station")]
|
[DataField("station")]
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Components;
|
namespace Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Added to a designated arrivals station for players to spawn at, if enabled.
|
/// Added to a designated arrivals station for players to spawn at, if enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent, Access(typeof(ArrivalsSystem))]
|
||||||
public sealed class ArrivalsSourceComponent : Component
|
public sealed class ArrivalsSourceComponent : Component
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
14
Content.Server/Shuttles/Components/EscapePodComponent.cs
Normal file
14
Content.Server/Shuttles/Components/EscapePodComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If added to a grid gets launched when the emergency shuttle launches.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, Access(typeof(EmergencyShuttleSystem))]
|
||||||
|
public sealed class EscapePodComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("launchTime", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan? LaunchTime;
|
||||||
|
}
|
||||||
13
Content.Server/Shuttles/Components/GridFillComponent.cs
Normal file
13
Content.Server/Shuttles/Components/GridFillComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If added to an airlock will try to autofill a grid onto it on MapInit
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, Access(typeof(ShuttleSystem))]
|
||||||
|
public sealed class GridFillComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("path")] public ResourcePath Path = new("/Maps/Shuttles/escape_pod_small.yml");
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Components;
|
namespace Content.Server.Shuttles.Components;
|
||||||
@@ -5,7 +6,7 @@ namespace Content.Server.Shuttles.Components;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Added to a station that is available for arrivals shuttles.
|
/// Added to a station that is available for arrivals shuttles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent, Access(typeof(ArrivalsSystem))]
|
||||||
public sealed class StationArrivalsComponent : Component
|
public sealed class StationArrivalsComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("shuttle")]
|
[DataField("shuttle")]
|
||||||
|
|||||||
28
Content.Server/Shuttles/DockingConfig.cs
Normal file
28
Content.Server/Shuttles/DockingConfig.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Content.Server.Shuttles.Components;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the data for a valid docking configuration for the emergency shuttle
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DockingConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The pairs of docks that can connect.
|
||||||
|
/// </summary>
|
||||||
|
public List<(EntityUid DockAUid, EntityUid DockBUid, DockingComponent DockA, DockingComponent DockB)> Docks = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Area relative to the target grid the emergency shuttle will spawn in on.
|
||||||
|
/// </summary>
|
||||||
|
public Box2 Area;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Target grid for docking.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid TargetGrid;
|
||||||
|
|
||||||
|
public EntityCoordinates Coordinates;
|
||||||
|
public Angle Angle;
|
||||||
|
}
|
||||||
@@ -280,7 +280,7 @@ public sealed class ArrivalsSystem : EntitySystem
|
|||||||
// TODO: Need some kind of comp to shunt people off if they try to get on?
|
// TODO: Need some kind of comp to shunt people off if they try to get on?
|
||||||
if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
|
if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
|
||||||
{
|
{
|
||||||
while (query.MoveNext(out var comp, out var shuttle, out var xform))
|
while (query.MoveNext(out var uid, out var comp, out var shuttle, out var xform))
|
||||||
{
|
{
|
||||||
if (comp.NextTransfer > curTime || !TryComp<StationDataComponent>(comp.Station, out var data))
|
if (comp.NextTransfer > curTime || !TryComp<StationDataComponent>(comp.Station, out var data))
|
||||||
continue;
|
continue;
|
||||||
@@ -289,7 +289,7 @@ public sealed class ArrivalsSystem : EntitySystem
|
|||||||
if (xform.MapUid != arrivalsXform.MapUid)
|
if (xform.MapUid != arrivalsXform.MapUid)
|
||||||
{
|
{
|
||||||
if (arrivals.IsValid())
|
if (arrivals.IsValid())
|
||||||
_shuttles.FTLTravel(shuttle, arrivals, dock: true);
|
_shuttles.FTLTravel(uid, shuttle, arrivals, dock: true);
|
||||||
}
|
}
|
||||||
// Go to station
|
// Go to station
|
||||||
else
|
else
|
||||||
@@ -297,7 +297,7 @@ public sealed class ArrivalsSystem : EntitySystem
|
|||||||
var targetGrid = _station.GetLargestGrid(data);
|
var targetGrid = _station.GetLargestGrid(data);
|
||||||
|
|
||||||
if (targetGrid != null)
|
if (targetGrid != null)
|
||||||
_shuttles.FTLTravel(shuttle, targetGrid.Value, dock: true);
|
_shuttles.FTLTravel(uid, shuttle, targetGrid.Value, dock: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.NextTransfer += TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
comp.NextTransfer += TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
||||||
@@ -395,7 +395,7 @@ public sealed class ArrivalsSystem : EntitySystem
|
|||||||
var arrivalsComp = EnsureComp<ArrivalsShuttleComponent>(component.Shuttle);
|
var arrivalsComp = EnsureComp<ArrivalsShuttleComponent>(component.Shuttle);
|
||||||
arrivalsComp.Station = uid;
|
arrivalsComp.Station = uid;
|
||||||
EnsureComp<ProtectedGridComponent>(uid);
|
EnsureComp<ProtectedGridComponent>(uid);
|
||||||
_shuttles.FTLTravel(shuttleComp, arrivals, hyperspaceTime: 10f, dock: true);
|
_shuttles.FTLTravel(component.Shuttle, shuttleComp, arrivals, hyperspaceTime: 10f, dock: true);
|
||||||
arrivalsComp.NextTransfer = _timing.CurTime + TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
arrivalsComp.NextTransfer = _timing.CurTime + TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public sealed partial class DockingSystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var worldPos = _transformSystem.GetWorldPosition(xform, xformQuery);
|
var worldPos = _transform.GetWorldPosition(xform, xformQuery);
|
||||||
var otherWorldPos = _transformSystem.GetWorldPosition(otherXform, xformQuery);
|
var otherWorldPos = _transform.GetWorldPosition(otherXform, xformQuery);
|
||||||
|
|
||||||
if ((worldPos - otherWorldPos).Length < comp.Radius) continue;
|
if ((worldPos - otherWorldPos).Length < comp.Radius) continue;
|
||||||
|
|
||||||
|
|||||||
267
Content.Server/Shuttles/Systems/DockingSystem.Shuttle.cs
Normal file
267
Content.Server/Shuttles/Systems/DockingSystem.Shuttle.cs
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Shuttles.Components;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Map.Components;
|
||||||
|
using Robust.Shared.Physics;
|
||||||
|
using Robust.Shared.Physics.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
|
public sealed partial class DockingSystem
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Handles the shuttle side of FTL docking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Angle GetAngle(EntityUid uid, TransformComponent xform, EntityUid targetUid, TransformComponent targetXform, EntityQuery<TransformComponent> xformQuery)
|
||||||
|
{
|
||||||
|
var (shuttlePos, shuttleRot) = _transform.GetWorldPositionRotation(xform, xformQuery);
|
||||||
|
var (targetPos, targetRot) = _transform.GetWorldPositionRotation(targetXform, xformQuery);
|
||||||
|
|
||||||
|
var shuttleCOM = Robust.Shared.Physics.Transform.Mul(new Transform(shuttlePos, shuttleRot),
|
||||||
|
Comp<PhysicsComponent>(uid).LocalCenter);
|
||||||
|
var targetCOM = Robust.Shared.Physics.Transform.Mul(new Transform(targetPos, targetRot),
|
||||||
|
Comp<PhysicsComponent>(targetUid).LocalCenter);
|
||||||
|
|
||||||
|
var mapDiff = shuttleCOM - targetCOM;
|
||||||
|
var angle = mapDiff.ToWorldAngle();
|
||||||
|
angle -= targetRot;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if 2 docks can be connected by moving the shuttle directly onto docks.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanDock(
|
||||||
|
DockingComponent shuttleDock,
|
||||||
|
TransformComponent shuttleDockXform,
|
||||||
|
DockingComponent gridDock,
|
||||||
|
TransformComponent gridDockXform,
|
||||||
|
Angle targetGridRotation,
|
||||||
|
Box2 shuttleAABB,
|
||||||
|
MapGridComponent grid,
|
||||||
|
[NotNullWhen(true)] out Box2? shuttleDockedAABB,
|
||||||
|
out Matrix3 matty,
|
||||||
|
out Angle gridRotation)
|
||||||
|
{
|
||||||
|
gridRotation = Angle.Zero;
|
||||||
|
matty = Matrix3.Identity;
|
||||||
|
shuttleDockedAABB = null;
|
||||||
|
|
||||||
|
if (shuttleDock.Docked ||
|
||||||
|
gridDock.Docked ||
|
||||||
|
!shuttleDockXform.Anchored ||
|
||||||
|
!gridDockXform.Anchored)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, get the station dock's position relative to the shuttle, this is where we rotate it around
|
||||||
|
var stationDockPos = shuttleDockXform.LocalPosition +
|
||||||
|
shuttleDockXform.LocalRotation.RotateVec(new Vector2(0f, -1f));
|
||||||
|
|
||||||
|
// Need to invert the grid's angle.
|
||||||
|
var shuttleDockAngle = shuttleDockXform.LocalRotation;
|
||||||
|
var gridDockAngle = gridDockXform.LocalRotation.Opposite();
|
||||||
|
|
||||||
|
var stationDockMatrix = Matrix3.CreateInverseTransform(stationDockPos, shuttleDockAngle);
|
||||||
|
var gridXformMatrix = Matrix3.CreateTransform(gridDockXform.LocalPosition, gridDockAngle);
|
||||||
|
Matrix3.Multiply(in stationDockMatrix, in gridXformMatrix, out matty);
|
||||||
|
shuttleDockedAABB = matty.TransformBox(shuttleAABB);
|
||||||
|
// Rounding moment
|
||||||
|
shuttleDockedAABB = shuttleDockedAABB.Value.Enlarged(-0.01f);
|
||||||
|
|
||||||
|
if (!ValidSpawn(grid, shuttleDockedAABB.Value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
gridRotation = targetGridRotation + gridDockAngle - shuttleDockAngle;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets docking config between 2 specific docks.
|
||||||
|
/// </summary>
|
||||||
|
public DockingConfig? GetDockingConfig(
|
||||||
|
EntityUid shuttleUid,
|
||||||
|
EntityUid targetGrid,
|
||||||
|
EntityUid shuttleDockUid,
|
||||||
|
DockingComponent shuttleDock,
|
||||||
|
EntityUid gridDockUid,
|
||||||
|
DockingComponent gridDock)
|
||||||
|
{
|
||||||
|
var shuttleDocks = new List<(EntityUid, DockingComponent)>(1)
|
||||||
|
{
|
||||||
|
(shuttleDockUid, shuttleDock)
|
||||||
|
};
|
||||||
|
|
||||||
|
var gridDocks = new List<(EntityUid, DockingComponent)>(1)
|
||||||
|
{
|
||||||
|
(gridDockUid, gridDock)
|
||||||
|
};
|
||||||
|
|
||||||
|
return GetDockingConfigPrivate(shuttleUid, targetGrid, shuttleDocks, gridDocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get a valid docking configuration for the shuttle to the target grid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="priorityTag">Priority docking tag to prefer, e.g. for emergency shuttle</param>
|
||||||
|
public DockingConfig? GetDockingConfig(EntityUid shuttleUid, EntityUid targetGrid, string? priorityTag = null)
|
||||||
|
{
|
||||||
|
var gridDocks = GetDocks(targetGrid);
|
||||||
|
var shuttleDocks = GetDocks(shuttleUid);
|
||||||
|
|
||||||
|
return GetDockingConfigPrivate(shuttleUid, targetGrid, shuttleDocks, gridDocks, priorityTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DockingConfig? GetDockingConfigPrivate(
|
||||||
|
EntityUid shuttleUid,
|
||||||
|
EntityUid targetGrid,
|
||||||
|
List<(EntityUid, DockingComponent)> shuttleDocks,
|
||||||
|
List<(EntityUid, DockingComponent)> gridDocks,
|
||||||
|
string? priorityTag = null)
|
||||||
|
{
|
||||||
|
if (gridDocks.Count <= 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
var targetGridGrid = Comp<MapGridComponent>(targetGrid);
|
||||||
|
var targetGridXform = xformQuery.GetComponent(targetGrid);
|
||||||
|
var targetGridAngle = _transform.GetWorldRotation(targetGridXform).Reduced();
|
||||||
|
|
||||||
|
var shuttleAABB = Comp<MapGridComponent>(shuttleUid).LocalAABB;
|
||||||
|
|
||||||
|
var validDockConfigs = new List<DockingConfig>();
|
||||||
|
|
||||||
|
if (shuttleDocks.Count > 0)
|
||||||
|
{
|
||||||
|
// We'll try all combinations of shuttle docks and see which one is most suitable
|
||||||
|
foreach (var (dockUid, shuttleDock) in shuttleDocks)
|
||||||
|
{
|
||||||
|
var shuttleDockXform = xformQuery.GetComponent(dockUid);
|
||||||
|
|
||||||
|
foreach (var (gridDockUid, gridDock) in gridDocks)
|
||||||
|
{
|
||||||
|
var gridXform = xformQuery.GetComponent(gridDockUid);
|
||||||
|
|
||||||
|
if (!CanDock(
|
||||||
|
shuttleDock, shuttleDockXform,
|
||||||
|
gridDock, gridXform,
|
||||||
|
targetGridAngle,
|
||||||
|
shuttleAABB,
|
||||||
|
targetGridGrid,
|
||||||
|
out var dockedAABB,
|
||||||
|
out var matty,
|
||||||
|
out var targetAngle))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't just use the AABB as we want to get bounds as tight as possible.
|
||||||
|
var spawnPosition = new EntityCoordinates(targetGrid, matty.Transform(Vector2.Zero));
|
||||||
|
spawnPosition = new EntityCoordinates(targetGridXform.MapUid!.Value, spawnPosition.ToMapPos(EntityManager, _transform));
|
||||||
|
|
||||||
|
var dockedBounds = new Box2Rotated(shuttleAABB.Translated(spawnPosition.Position), targetGridAngle, spawnPosition.Position);
|
||||||
|
|
||||||
|
// Check if there's no intersecting grids (AKA oh god it's docking at cargo).
|
||||||
|
if (_mapManager.FindGridsIntersecting(targetGridXform.MapID,
|
||||||
|
dockedBounds).Any(o => o.Owner != targetGrid))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alright well the spawn is valid now to check how many we can connect
|
||||||
|
// Get the matrix for each shuttle dock and test it against the grid docks to see
|
||||||
|
// if the connected position / direction matches.
|
||||||
|
|
||||||
|
var dockedPorts = new List<(EntityUid DockAUid, EntityUid DockBUid, DockingComponent DockA, DockingComponent DockB)>()
|
||||||
|
{
|
||||||
|
(dockUid, gridDockUid, shuttleDock, gridDock),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Check shuttle orientation as the tiebreaker.
|
||||||
|
|
||||||
|
foreach (var (otherUid, other) in shuttleDocks)
|
||||||
|
{
|
||||||
|
if (other == shuttleDock)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var (otherGridUid, otherGrid) in gridDocks)
|
||||||
|
{
|
||||||
|
if (otherGrid == gridDock)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!CanDock(
|
||||||
|
other,
|
||||||
|
xformQuery.GetComponent(otherUid),
|
||||||
|
otherGrid,
|
||||||
|
xformQuery.GetComponent(otherGridUid),
|
||||||
|
targetGridAngle,
|
||||||
|
shuttleAABB, targetGridGrid,
|
||||||
|
out var otherDockedAABB,
|
||||||
|
out _,
|
||||||
|
out var otherTargetAngle) ||
|
||||||
|
!otherDockedAABB.Equals(dockedAABB) ||
|
||||||
|
!targetAngle.Equals(otherTargetAngle))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dockedPorts.Add((otherUid, otherGridUid, other, otherGrid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validDockConfigs.Add(new DockingConfig()
|
||||||
|
{
|
||||||
|
Docks = dockedPorts,
|
||||||
|
Area = dockedAABB.Value,
|
||||||
|
Coordinates = spawnPosition,
|
||||||
|
Angle = targetAngle,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validDockConfigs.Count <= 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Prioritise by priority docks, then by maximum connected ports, then by most similar angle.
|
||||||
|
validDockConfigs = validDockConfigs
|
||||||
|
.OrderByDescending(x => x.Docks.Any(docks =>
|
||||||
|
TryComp<PriorityDockComponent>(docks.DockB.Owner, out var priority) &&
|
||||||
|
priority.Tag?.Equals(priorityTag) == true))
|
||||||
|
.ThenByDescending(x => x.Docks.Count)
|
||||||
|
.ThenBy(x => Math.Abs(Angle.ShortestDistance(x.Angle.Reduced(), targetGridAngle).Theta)).ToList();
|
||||||
|
|
||||||
|
var location = validDockConfigs.First();
|
||||||
|
location.TargetGrid = targetGrid;
|
||||||
|
// TODO: Ideally do a hyperspace warpin, just have it run on like a 10 second timer.
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the emergency shuttle can warp to the specified position.
|
||||||
|
/// </summary>
|
||||||
|
private bool ValidSpawn(MapGridComponent grid, Box2 area)
|
||||||
|
{
|
||||||
|
return !grid.GetLocalTilesIntersecting(area).Any();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<(EntityUid Uid, DockingComponent Component)> GetDocks(EntityUid uid)
|
||||||
|
{
|
||||||
|
var result = new List<(EntityUid Uid, DockingComponent Component)>();
|
||||||
|
var query = AllEntityQuery<DockingComponent, TransformComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var dockUid, out var dock, out var xform))
|
||||||
|
{
|
||||||
|
if (xform.ParentUid != uid || !dock.Enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.Add((dockUid, dock));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
||||||
[Dependency] private readonly SharedJointSystem _jointSystem = default!;
|
[Dependency] private readonly SharedJointSystem _jointSystem = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
private const string DockingFixture = "docking";
|
private const string DockingFixture = "docking";
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Server.Access.Systems;
|
|
||||||
using Content.Server.Popups;
|
|
||||||
using Content.Server.RoundEnd;
|
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Server.Shuttles.Events;
|
using Content.Server.Shuttles.Events;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
using Content.Shared.Access.Systems;
|
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Shuttles.BUIStates;
|
using Content.Shared.Shuttles.BUIStates;
|
||||||
using Content.Shared.Shuttles.Events;
|
using Content.Shared.Shuttles.Events;
|
||||||
@@ -16,23 +13,16 @@ using Content.Shared.Shuttles.Systems;
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Timing;
|
|
||||||
using Timer = Robust.Shared.Timing.Timer;
|
using Timer = Robust.Shared.Timing.Timer;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems;
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
public sealed partial class ShuttleSystem
|
public sealed partial class EmergencyShuttleSystem
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Handles the emergency shuttle's console and early launching.
|
* Handles the emergency shuttle's console and early launching.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
|
||||||
[Dependency] private readonly IdCardSystem _idSystem = default!;
|
|
||||||
[Dependency] private readonly AccessReaderSystem _reader = default!;
|
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
|
||||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Has the emergency shuttle arrived?
|
/// Has the emergency shuttle arrived?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -43,7 +33,7 @@ public sealed partial class ShuttleSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// How much time remaining until the shuttle consoles for emergency shuttles are unlocked?
|
/// How much time remaining until the shuttle consoles for emergency shuttles are unlocked?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private float _consoleAccumulator;
|
private float _consoleAccumulator = float.MinValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long after the transit is over to end the round.
|
/// How long after the transit is over to end the round.
|
||||||
@@ -70,6 +60,8 @@ public sealed partial class ShuttleSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _launchedShuttles;
|
private bool _launchedShuttles;
|
||||||
|
|
||||||
|
private bool _leftShuttles;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Have we announced the launch?
|
/// Have we announced the launch?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -84,6 +76,8 @@ public sealed partial class ShuttleSystem
|
|||||||
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, EmergencyShuttleRepealMessage>(OnEmergencyRepeal);
|
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, EmergencyShuttleRepealMessage>(OnEmergencyRepeal);
|
||||||
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, EmergencyShuttleRepealAllMessage>(OnEmergencyRepealAll);
|
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, EmergencyShuttleRepealAllMessage>(OnEmergencyRepealAll);
|
||||||
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, ActivatableUIOpenAttemptEvent>(OnEmergencyOpenAttempt);
|
SubscribeLocalEvent<EmergencyShuttleConsoleComponent, ActivatableUIOpenAttemptEvent>(OnEmergencyOpenAttempt);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<EscapePodComponent, EntityUnpausedEvent>(OnEscapeUnpaused);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEmergencyOpenAttempt(EntityUid uid, EmergencyShuttleConsoleComponent component, ActivatableUIOpenAttemptEvent args)
|
private void OnEmergencyOpenAttempt(EntityUid uid, EmergencyShuttleConsoleComponent component, ActivatableUIOpenAttemptEvent args)
|
||||||
@@ -119,7 +113,14 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
private void UpdateEmergencyConsole(float frameTime)
|
private void UpdateEmergencyConsole(float frameTime)
|
||||||
{
|
{
|
||||||
if (_consoleAccumulator <= 0f) return;
|
// Add some buffer time so eshuttle always first.
|
||||||
|
var minTime = -(TransitTime - (ShuttleSystem.DefaultStartupTime + ShuttleSystem.DefaultTravelTime + 1f));
|
||||||
|
|
||||||
|
// TODO: I know this is shit but I already just cleaned up a billion things.
|
||||||
|
if (_consoleAccumulator < minTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_consoleAccumulator -= frameTime;
|
_consoleAccumulator -= frameTime;
|
||||||
|
|
||||||
@@ -131,46 +132,76 @@ public sealed partial class ShuttleSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Imminent departure
|
// Imminent departure
|
||||||
if (!_launchedShuttles && _consoleAccumulator <= DefaultStartupTime)
|
if (!_launchedShuttles && _consoleAccumulator <= ShuttleSystem.DefaultStartupTime)
|
||||||
{
|
{
|
||||||
_launchedShuttles = true;
|
_launchedShuttles = true;
|
||||||
|
|
||||||
if (CentComMap != null)
|
if (CentComMap != null)
|
||||||
{
|
{
|
||||||
foreach (var comp in EntityQuery<StationDataComponent>(true))
|
var dataQuery = AllEntityQuery<StationDataComponent>();
|
||||||
|
|
||||||
|
while (dataQuery.MoveNext(out var comp))
|
||||||
{
|
{
|
||||||
if (!TryComp<ShuttleComponent>(comp.EmergencyShuttle, out var shuttle)) continue;
|
if (!TryComp<ShuttleComponent>(comp.EmergencyShuttle, out var shuttle))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (Deleted(CentCom))
|
if (Deleted(CentCom))
|
||||||
{
|
{
|
||||||
// TODO: Need to get non-overlapping positions.
|
// TODO: Need to get non-overlapping positions.
|
||||||
FTLTravel(shuttle,
|
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
||||||
new EntityCoordinates(
|
new EntityCoordinates(
|
||||||
_mapManager.GetMapEntityId(CentComMap.Value),
|
_mapManager.GetMapEntityId(CentComMap.Value),
|
||||||
Vector2.One * 1000f), _consoleAccumulator, TransitTime);
|
_random.NextVector2(1000f)), _consoleAccumulator, TransitTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTLTravel(shuttle,
|
_shuttle.FTLTravel(comp.EmergencyShuttle.Value, shuttle,
|
||||||
CentCom.Value, _consoleAccumulator, TransitTime, true);
|
CentCom.Value, _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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Departed
|
var podLaunchQuery = EntityQueryEnumerator<EscapePodComponent, ShuttleComponent>();
|
||||||
if (_consoleAccumulator <= 0f)
|
|
||||||
|
while (podLaunchQuery.MoveNext(out var uid, out var pod, out var shuttle))
|
||||||
{
|
{
|
||||||
_launchedShuttles = true;
|
if (CentCom == null || pod.LaunchTime == null || pod.LaunchTime < _timing.CurTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Don't dock them. If you do end up doing this then stagger launch.
|
||||||
|
_shuttle.FTLTravel(uid, shuttle,
|
||||||
|
CentCom.Value, hyperspaceTime: TransitTime);
|
||||||
|
|
||||||
|
RemCompDeferred<EscapePodComponent>(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Departed
|
||||||
|
if (!_leftShuttles && _consoleAccumulator <= 0f)
|
||||||
|
{
|
||||||
|
_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();
|
_roundEndCancelToken = new CancellationTokenSource();
|
||||||
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken.Token);
|
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the others.
|
||||||
|
if (_consoleAccumulator < minTime)
|
||||||
|
{
|
||||||
// Guarantees that emergency shuttle arrives first before anyone else can FTL.
|
// Guarantees that emergency shuttle arrives first before anyone else can FTL.
|
||||||
if (CentCom != null)
|
if (CentCom != null)
|
||||||
AddFTLDestination(CentCom.Value, true);
|
_shuttle.AddFTLDestination(CentCom.Value, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +216,8 @@ public sealed partial class ShuttleSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.AuthorizedEntities.Count == 0) return;
|
if (component.AuthorizedEntities.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle early launch REPEAL ALL by {args.Session:user}");
|
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle early launch REPEAL ALL by {args.Session:user}");
|
||||||
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-console-auth-revoked", ("remaining", component.AuthorizationsRequired)));
|
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-console-auth-revoked", ("remaining", component.AuthorizationsRequired)));
|
||||||
@@ -246,8 +278,9 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
_announced = false;
|
_announced = false;
|
||||||
_roundEndCancelToken = null;
|
_roundEndCancelToken = null;
|
||||||
|
_leftShuttles = false;
|
||||||
_launchedShuttles = false;
|
_launchedShuttles = false;
|
||||||
_consoleAccumulator = 0f;
|
_consoleAccumulator = float.MinValue;
|
||||||
EarlyLaunchAuthorized = false;
|
EarlyLaunchAuthorized = false;
|
||||||
EmergencyShuttleArrived = false;
|
EmergencyShuttleArrived = false;
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,30 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using Content.Server.Access.Systems;
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Communications;
|
using Content.Server.Communications;
|
||||||
using Content.Server.GameTicking.Events;
|
using Content.Server.GameTicking.Events;
|
||||||
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.RoundEnd;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Shared.Access.Systems;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Shuttles.Events;
|
using Content.Shared.Shuttles.Events;
|
||||||
using Content.Shared.Tiles;
|
|
||||||
using Content.Shared.Tag;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Maps;
|
using Robust.Server.Maps;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
|
||||||
using Robust.Shared.Physics;
|
|
||||||
using Robust.Shared.Physics.Components;
|
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems;
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
public sealed partial class ShuttleSystem
|
public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Handles the escape shuttle + CentCom.
|
* Handles the escape shuttle + CentCom.
|
||||||
@@ -36,12 +33,23 @@ public sealed partial class ShuttleSystem
|
|||||||
[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 IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = 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 _dockSystem = default!;
|
[Dependency] private readonly DockingSystem _dock = 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 RoundEndSystem _roundEnd = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = 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!;
|
||||||
|
|
||||||
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
public MapId? CentComMap { get; private set; }
|
public MapId? CentComMap { get; private set; }
|
||||||
public EntityUid? CentCom { get; private set; }
|
public EntityUid? CentCom { get; private set; }
|
||||||
@@ -55,19 +63,22 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
private bool _emergencyShuttleEnabled;
|
private bool _emergencyShuttleEnabled;
|
||||||
|
|
||||||
private void InitializeEscape()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
_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<StationDataComponent, ComponentStartup>(OnStationStartup);
|
SubscribeLocalEvent<StationDataComponent, ComponentStartup>(OnStationStartup);
|
||||||
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
|
||||||
|
InitializeEmergencyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEmergencyShuttleEnabled(bool value)
|
private void SetEmergencyShuttleEnabled(bool value)
|
||||||
{
|
{
|
||||||
if (_emergencyShuttleEnabled == value) return;
|
if (_emergencyShuttleEnabled == value)
|
||||||
|
return;
|
||||||
_emergencyShuttleEnabled = value;
|
_emergencyShuttleEnabled = value;
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
@@ -80,9 +91,16 @@ public sealed partial class ShuttleSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShutdownEscape()
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
UpdateEmergencyConsole(frameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
_configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
_configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
|
||||||
|
ShutdownEmergencyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -90,18 +108,25 @@ public sealed partial class ShuttleSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args)
|
private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args)
|
||||||
{
|
{
|
||||||
if (!_admin.IsAdmin((IPlayerSession) args.SenderSession)) return;
|
if (!_admin.IsAdmin((IPlayerSession) args.SenderSession))
|
||||||
|
return;
|
||||||
|
|
||||||
var player = args.SenderSession.AttachedEntity;
|
var player = args.SenderSession.AttachedEntity;
|
||||||
|
|
||||||
if (player == null ||
|
if (player == null ||
|
||||||
!TryComp<StationDataComponent>(_station.GetOwningStation(player.Value), out var stationData) ||
|
!TryComp<StationDataComponent>(_station.GetOwningStation(player.Value), out var stationData) ||
|
||||||
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle)) return;
|
!HasComp<ShuttleComponent>(stationData.EmergencyShuttle))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var targetGrid = _station.GetLargestGrid(stationData);
|
var targetGrid = _station.GetLargestGrid(stationData);
|
||||||
if (targetGrid == null) return;
|
if (targetGrid == null)
|
||||||
var config = GetDockingConfig(shuttle, targetGrid.Value);
|
return;
|
||||||
if (config == null) return;
|
|
||||||
|
var config = _dock.GetDockingConfig(stationData.EmergencyShuttle.Value, targetGrid.Value);
|
||||||
|
if (config == null)
|
||||||
|
return;
|
||||||
|
|
||||||
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
|
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
|
||||||
{
|
{
|
||||||
@@ -117,7 +142,10 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
if (!TryComp<StationDataComponent>(stationUid, out var stationData) ||
|
if (!TryComp<StationDataComponent>(stationUid, out var stationData) ||
|
||||||
!TryComp<TransformComponent>(stationData.EmergencyShuttle, out var xform) ||
|
!TryComp<TransformComponent>(stationData.EmergencyShuttle, out var xform) ||
|
||||||
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle)) return;
|
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var targetGrid = _station.GetLargestGrid(stationData);
|
var targetGrid = _station.GetLargestGrid(stationData);
|
||||||
|
|
||||||
@@ -127,105 +155,38 @@ public sealed partial class ShuttleSystem
|
|||||||
_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.Value)} unable to dock with station {ToPrettyString(stationUid.Value)}");
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
|
_chatSystem.DispatchStationAnnouncement(stationUid.Value, 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.
|
||||||
SoundSystem.Play("/Audio/Misc/notice1.ogg", Filter.Broadcast());
|
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
|
||||||
if (TryFTLDock(shuttle, targetGrid.Value))
|
if (_shuttle.TryFTLDock(stationData.EmergencyShuttle.Value, shuttle, targetGrid.Value))
|
||||||
{
|
{
|
||||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||||
{
|
{
|
||||||
var angle = GetAngle(xform, targetXform, xformQuery);
|
var angle = _dock.GetAngle(stationData.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.Value, 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.Value)} docked with stations");
|
||||||
// TODO: Need filter extensions or something don't blame me.
|
// TODO: Need filter extensions or something don't blame me.
|
||||||
SoundSystem.Play("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast());
|
_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 = GetAngle(xform, targetXform, xformQuery);
|
var angle = _dock.GetAngle(stationData.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||||
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
_chatSystem.DispatchStationAnnouncement(stationUid.Value, 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.Value)} unable to find a valid docking port for {ToPrettyString(stationUid.Value)}");
|
||||||
// TODO: Need filter extensions or something don't blame me.
|
// TODO: Need filter extensions or something don't blame me.
|
||||||
SoundSystem.Play("/Audio/Misc/notice1.ogg", Filter.Broadcast());
|
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Angle GetAngle(TransformComponent xform, TransformComponent targetXform, EntityQuery<TransformComponent> xformQuery)
|
|
||||||
{
|
|
||||||
var (shuttlePos, shuttleRot) = xform.GetWorldPositionRotation(xformQuery);
|
|
||||||
var (targetPos, targetRot) = targetXform.GetWorldPositionRotation(xformQuery);
|
|
||||||
|
|
||||||
var shuttleCOM = Robust.Shared.Physics.Transform.Mul(new Transform(shuttlePos, shuttleRot),
|
|
||||||
Comp<PhysicsComponent>(xform.Owner).LocalCenter);
|
|
||||||
var targetCOM = Robust.Shared.Physics.Transform.Mul(new Transform(targetPos, targetRot),
|
|
||||||
Comp<PhysicsComponent>(targetXform.Owner).LocalCenter);
|
|
||||||
|
|
||||||
var mapDiff = shuttleCOM - targetCOM;
|
|
||||||
var targetRotation = targetRot;
|
|
||||||
var angle = mapDiff.ToWorldAngle();
|
|
||||||
angle -= targetRotation;
|
|
||||||
return angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if 2 docks can be connected by moving the shuttle directly onto docks.
|
|
||||||
/// </summary>
|
|
||||||
private bool CanDock(
|
|
||||||
DockingComponent shuttleDock,
|
|
||||||
TransformComponent shuttleDockXform,
|
|
||||||
DockingComponent gridDock,
|
|
||||||
TransformComponent gridDockXform,
|
|
||||||
Angle targetGridRotation,
|
|
||||||
Box2 shuttleAABB,
|
|
||||||
EntityUid gridUid,
|
|
||||||
MapGridComponent grid,
|
|
||||||
[NotNullWhen(true)] out Box2? shuttleDockedAABB,
|
|
||||||
out Matrix3 matty,
|
|
||||||
out Angle gridRotation)
|
|
||||||
{
|
|
||||||
gridRotation = Angle.Zero;
|
|
||||||
matty = Matrix3.Identity;
|
|
||||||
shuttleDockedAABB = null;
|
|
||||||
|
|
||||||
if (shuttleDock.Docked ||
|
|
||||||
gridDock.Docked ||
|
|
||||||
!shuttleDockXform.Anchored ||
|
|
||||||
!gridDockXform.Anchored)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, get the station dock's position relative to the shuttle, this is where we rotate it around
|
|
||||||
var stationDockPos = shuttleDockXform.LocalPosition +
|
|
||||||
shuttleDockXform.LocalRotation.RotateVec(new Vector2(0f, -1f));
|
|
||||||
|
|
||||||
// Need to invert the grid's angle.
|
|
||||||
var shuttleDockAngle = shuttleDockXform.LocalRotation;
|
|
||||||
var gridDockAngle = gridDockXform.LocalRotation.Opposite();
|
|
||||||
|
|
||||||
var stationDockMatrix = Matrix3.CreateInverseTransform(stationDockPos, shuttleDockAngle);
|
|
||||||
var gridXformMatrix = Matrix3.CreateTransform(gridDockXform.LocalPosition, gridDockAngle);
|
|
||||||
Matrix3.Multiply(in stationDockMatrix, in gridXformMatrix, out matty);
|
|
||||||
shuttleDockedAABB = matty.TransformBox(shuttleAABB);
|
|
||||||
// Rounding moment
|
|
||||||
shuttleDockedAABB = shuttleDockedAABB.Value.Enlarged(-0.01f);
|
|
||||||
|
|
||||||
if (!ValidSpawn(gridUid, grid, shuttleDockedAABB.Value))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
gridRotation = targetGridRotation + gridDockAngle - shuttleDockAngle;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnStationStartup(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
private void OnStationStartup(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
AddEmergencyShuttle(component);
|
AddEmergencyShuttle(component);
|
||||||
@@ -233,6 +194,7 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
private void OnRoundStart(RoundStartingEvent ev)
|
private void OnRoundStart(RoundStartingEvent ev)
|
||||||
{
|
{
|
||||||
|
CleanupEmergencyConsole();
|
||||||
SetupEmergencyShuttle();
|
SetupEmergencyShuttle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +203,8 @@ public sealed partial class ShuttleSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void CallEmergencyShuttle()
|
public void CallEmergencyShuttle()
|
||||||
{
|
{
|
||||||
if (EmergencyShuttleArrived) return;
|
if (EmergencyShuttleArrived)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!_emergencyShuttleEnabled)
|
if (!_emergencyShuttleEnabled)
|
||||||
{
|
{
|
||||||
@@ -255,28 +218,16 @@ public sealed partial class ShuttleSystem
|
|||||||
if (CentComMap != null)
|
if (CentComMap != null)
|
||||||
_mapManager.SetMapPaused(CentComMap.Value, false);
|
_mapManager.SetMapPaused(CentComMap.Value, false);
|
||||||
|
|
||||||
foreach (var comp in EntityQuery<StationDataComponent>(true))
|
var query = AllEntityQuery<StationDataComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
CallEmergencyShuttle(comp.Owner);
|
CallEmergencyShuttle(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
_commsConsole.UpdateCommsConsoleInterface();
|
_commsConsole.UpdateCommsConsoleInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DockingComponent> GetDocks(EntityUid uid)
|
|
||||||
{
|
|
||||||
var result = new List<DockingComponent>();
|
|
||||||
|
|
||||||
foreach (var (dock, xform) in EntityQuery<DockingComponent, TransformComponent>(true))
|
|
||||||
{
|
|
||||||
if (xform.ParentUid != uid || !dock.Enabled) continue;
|
|
||||||
|
|
||||||
result.Add(dock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupEmergencyShuttle()
|
private void SetupEmergencyShuttle()
|
||||||
{
|
{
|
||||||
if (!_emergencyShuttleEnabled || CentComMap != null && _mapManager.MapExists(CentComMap.Value)) return;
|
if (!_emergencyShuttleEnabled || CentComMap != null && _mapManager.MapExists(CentComMap.Value)) return;
|
||||||
@@ -293,7 +244,7 @@ public sealed partial class ShuttleSystem
|
|||||||
CentCom = centcomm;
|
CentCom = centcomm;
|
||||||
|
|
||||||
if (CentCom != null)
|
if (CentCom != null)
|
||||||
AddFTLDestination(CentCom.Value, false);
|
_shuttle.AddFTLDestination(CentCom.Value, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -332,7 +283,6 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
_shuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
|
_shuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
|
||||||
component.EmergencyShuttle = shuttle;
|
component.EmergencyShuttle = shuttle;
|
||||||
EnsureComp<ProtectedGridComponent>(shuttle.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CleanupEmergencyShuttle()
|
private void CleanupEmergencyShuttle()
|
||||||
@@ -354,27 +304,11 @@ public sealed partial class ShuttleSystem
|
|||||||
_mapManager.DeleteMap(CentComMap.Value);
|
_mapManager.DeleteMap(CentComMap.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void OnEscapeUnpaused(EntityUid uid, EscapePodComponent component, ref EntityUnpausedEvent args)
|
||||||
/// Stores the data for a valid docking configuration for the emergency shuttle
|
|
||||||
/// </summary>
|
|
||||||
private sealed class DockingConfig
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
if (component.LaunchTime == null)
|
||||||
/// The pairs of docks that can connect.
|
return;
|
||||||
/// </summary>
|
|
||||||
public List<(DockingComponent DockA, DockingComponent DockB)> Docks = new();
|
|
||||||
|
|
||||||
/// <summary>
|
component.LaunchTime = component.LaunchTime.Value + args.PausedTime;
|
||||||
/// Area relative to the target grid the emergency shuttle will spawn in on.
|
|
||||||
/// </summary>
|
|
||||||
public Box2 Area;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Target grid for docking.
|
|
||||||
/// </summary>
|
|
||||||
public EntityUid TargetGrid;
|
|
||||||
|
|
||||||
public EntityCoordinates Coordinates;
|
|
||||||
public Angle Angle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,14 +12,15 @@ using Content.Shared.Shuttles.Events;
|
|||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Collections;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems
|
namespace Content.Server.Shuttles.Systems;
|
||||||
{
|
|
||||||
public sealed class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
public sealed class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
@@ -93,7 +94,9 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasComp<FTLComponent>(xform.GridUid))
|
var shuttleUid = xform.GridUid.Value;
|
||||||
|
|
||||||
|
if (HasComp<FTLComponent>(shuttleUid))
|
||||||
{
|
{
|
||||||
_popup.PopupCursor(Loc.GetString("shuttle-console-in-ftl"), args.Session);
|
_popup.PopupCursor(Loc.GetString("shuttle-console-in-ftl"), args.Session);
|
||||||
return;
|
return;
|
||||||
@@ -109,7 +112,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
var tagEv = new FTLTagEvent();
|
var tagEv = new FTLTagEvent();
|
||||||
RaiseLocalEvent(xform.GridUid.Value, ref tagEv);
|
RaiseLocalEvent(xform.GridUid.Value, ref tagEv);
|
||||||
|
|
||||||
_shuttle.FTLTravel(shuttle, args.Destination, dock: dock, priorityTag: tagEv.Tag);
|
_shuttle.FTLTravel(xform.GridUid.Value, shuttle, args.Destination, dock: dock, priorityTag: tagEv.Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDock(DockEvent ev)
|
private void OnDock(DockEvent ev)
|
||||||
@@ -138,7 +141,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
UpdateState(uid, comp, docks);
|
UpdateState(uid, docks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,12 +173,12 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
private void OnConsoleAnchorChange(EntityUid uid, ShuttleConsoleComponent component, ref AnchorStateChangedEvent args)
|
private void OnConsoleAnchorChange(EntityUid uid, ShuttleConsoleComponent component, ref AnchorStateChangedEvent args)
|
||||||
{
|
{
|
||||||
UpdateState(uid, component);
|
UpdateState(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnConsolePowerChange(EntityUid uid, ShuttleConsoleComponent component, ref PowerChangedEvent args)
|
private void OnConsolePowerChange(EntityUid uid, ShuttleConsoleComponent component, ref PowerChangedEvent args)
|
||||||
{
|
{
|
||||||
UpdateState(uid, component);
|
UpdateState(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryPilot(EntityUid user, EntityUid uid)
|
private bool TryPilot(EntityUid user, EntityUid uid)
|
||||||
@@ -189,7 +192,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pilotComponent = EntityManager.EnsureComponent<PilotComponent>(user);
|
var pilotComponent = EnsureComp<PilotComponent>(user);
|
||||||
var console = pilotComponent.Console;
|
var console = pilotComponent.Console;
|
||||||
|
|
||||||
if (console != null)
|
if (console != null)
|
||||||
@@ -240,7 +243,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateState(EntityUid consoleUid, ShuttleConsoleComponent component, List<DockingInterfaceState>? docks = null)
|
private void UpdateState(EntityUid consoleUid, List<DockingInterfaceState>? docks = null)
|
||||||
{
|
{
|
||||||
EntityUid? entity = consoleUid;
|
EntityUid? entity = consoleUid;
|
||||||
|
|
||||||
@@ -299,7 +302,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
var canTravel = !locked &&
|
var canTravel = !locked &&
|
||||||
comp.Enabled &&
|
comp.Enabled &&
|
||||||
(!TryComp<FTLComponent>(comp.Owner, out var ftl) || ftl.State == FTLState.Cooldown);
|
(!TryComp<FTLComponent>(destUid, out var ftl) || ftl.State == FTLState.Cooldown);
|
||||||
|
|
||||||
// Can't travel to same map (yet)
|
// Can't travel to same map (yet)
|
||||||
if (canTravel && consoleXform?.MapUid == Transform(destUid).MapUid)
|
if (canTravel && consoleXform?.MapUid == Transform(destUid).MapUid)
|
||||||
@@ -328,7 +331,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
var toRemove = new RemQueue<PilotComponent>();
|
var toRemove = new ValueList<(EntityUid, PilotComponent)>();
|
||||||
var query = EntityQueryEnumerator<PilotComponent>();
|
var query = EntityQueryEnumerator<PilotComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
@@ -338,13 +341,13 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
if (!_blocker.CanInteract(uid, comp.Console.Owner))
|
if (!_blocker.CanInteract(uid, comp.Console.Owner))
|
||||||
{
|
{
|
||||||
toRemove.Add(comp);
|
toRemove.Add((uid, comp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var comp in toRemove)
|
foreach (var (uid, comp) in toRemove)
|
||||||
{
|
{
|
||||||
RemovePilot(comp.Owner, comp);
|
RemovePilot(uid, comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,11 +421,12 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
eye.Zoom = new(1.0f, 1.0f);
|
eye.Zoom = new(1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!helmsman.SubscribedPilots.Remove(pilotComponent)) return;
|
if (!helmsman.SubscribedPilots.Remove(pilotComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
_alertsSystem.ClearAlert(pilotUid, AlertType.PilotingShuttle);
|
_alertsSystem.ClearAlert(pilotUid, AlertType.PilotingShuttle);
|
||||||
|
|
||||||
pilotComponent.Owner.PopupMessage(Loc.GetString("shuttle-pilot-end"));
|
_popup.PopupEntity(Loc.GetString("shuttle-pilot-end"), pilotUid, pilotUid);
|
||||||
|
|
||||||
if (pilotComponent.LifeStage < ComponentLifeStage.Stopping)
|
if (pilotComponent.LifeStage < ComponentLifeStage.Stopping)
|
||||||
EntityManager.RemoveComponent<PilotComponent>(pilotUid);
|
EntityManager.RemoveComponent<PilotComponent>(pilotUid);
|
||||||
@@ -430,7 +434,8 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
public void RemovePilot(EntityUid entity)
|
public void RemovePilot(EntityUid entity)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent)) return;
|
if (!EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
RemovePilot(entity, pilotComponent);
|
RemovePilot(entity, pilotComponent);
|
||||||
}
|
}
|
||||||
@@ -443,4 +448,3 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
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.Station.Systems;
|
||||||
using Content.Server.Stunnable;
|
|
||||||
using Content.Shared.Parallax;
|
using Content.Shared.Parallax;
|
||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffect;
|
||||||
@@ -29,18 +28,11 @@ public sealed partial class ShuttleSystem
|
|||||||
* This is a way to move a shuttle from one location to another, via an intermediate map for fanciness.
|
* This is a way to move a shuttle from one location to another, via an intermediate map for fanciness.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Dependency] private readonly AirlockSystem _airlock = default!;
|
|
||||||
[Dependency] private readonly DoorSystem _doors = default!;
|
|
||||||
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
|
||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
|
||||||
[Dependency] private readonly StunSystem _stuns = default!;
|
|
||||||
[Dependency] private readonly ThrusterSystem _thruster = default!;
|
|
||||||
|
|
||||||
private MapId? _hyperSpaceMap;
|
private MapId? _hyperSpaceMap;
|
||||||
|
|
||||||
private const float DefaultStartupTime = 5.5f;
|
public const float DefaultStartupTime = 5.5f;
|
||||||
private const float DefaultTravelTime = 30f;
|
public const float DefaultTravelTime = 30f;
|
||||||
private const float DefaultArrivalTime = 5f;
|
public const float DefaultArrivalTime = 5f;
|
||||||
private const float FTLCooldown = 30f;
|
private const float FTLCooldown = 30f;
|
||||||
private const float ShuttleFTLRange = 100f;
|
private const float ShuttleFTLRange = 100f;
|
||||||
|
|
||||||
@@ -106,14 +98,17 @@ public sealed partial class ShuttleSystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounds = xform.WorldMatrix.TransformBox(grid.LocalAABB).Enlarged(ShuttleFTLRange);
|
var bounds = _transform.GetWorldMatrix(xform).TransformBox(grid.LocalAABB).Enlarged(ShuttleFTLRange);
|
||||||
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
||||||
|
|
||||||
foreach (var other in _mapManager.FindGridsIntersecting(xform.MapID, bounds))
|
foreach (var other in _mapManager.FindGridsIntersecting(xform.MapID, bounds))
|
||||||
{
|
{
|
||||||
if (grid.Owner == other.Owner ||
|
if (uid == other.Owner ||
|
||||||
!bodyQuery.TryGetComponent(other.Owner, out var body) ||
|
!bodyQuery.TryGetComponent(other.Owner, out var body) ||
|
||||||
body.Mass < ShuttleFTLMassThreshold) continue;
|
body.Mass < ShuttleFTLMassThreshold)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
reason = Loc.GetString("shuttle-console-proximity");
|
reason = Loc.GetString("shuttle-console-proximity");
|
||||||
return false;
|
return false;
|
||||||
@@ -127,7 +122,8 @@ public sealed partial class ShuttleSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public FTLDestinationComponent AddFTLDestination(EntityUid uid, bool enabled)
|
public FTLDestinationComponent AddFTLDestination(EntityUid uid, bool enabled)
|
||||||
{
|
{
|
||||||
if (TryComp<FTLDestinationComponent>(uid, out var destination) && destination.Enabled == enabled) return destination;
|
if (TryComp<FTLDestinationComponent>(uid, out var destination) && destination.Enabled == enabled)
|
||||||
|
return destination;
|
||||||
|
|
||||||
destination = EnsureComp<FTLDestinationComponent>(uid);
|
destination = EnsureComp<FTLDestinationComponent>(uid);
|
||||||
|
|
||||||
@@ -146,19 +142,22 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
if (!RemComp<FTLDestinationComponent>(uid))
|
if (!RemComp<FTLDestinationComponent>(uid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_console.RefreshShuttleConsoles();
|
_console.RefreshShuttleConsoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves a shuttle from its current position to the target one. Goes through the hyperspace map while the timer is running.
|
/// Moves a shuttle from its current position to the target one. Goes through the hyperspace map while the timer is running.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void FTLTravel(ShuttleComponent component,
|
public void FTLTravel(
|
||||||
|
EntityUid shuttleUid,
|
||||||
|
ShuttleComponent component,
|
||||||
EntityCoordinates coordinates,
|
EntityCoordinates coordinates,
|
||||||
float startupTime = DefaultStartupTime,
|
float startupTime = DefaultStartupTime,
|
||||||
float hyperspaceTime = DefaultTravelTime,
|
float hyperspaceTime = DefaultTravelTime,
|
||||||
string? priorityTag = null)
|
string? priorityTag = null)
|
||||||
{
|
{
|
||||||
if (!TrySetupFTL(component, out var hyperspace))
|
if (!TrySetupFTL(shuttleUid, component, out var hyperspace))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hyperspace.StartupTime = startupTime;
|
hyperspace.StartupTime = startupTime;
|
||||||
@@ -173,14 +172,16 @@ public sealed partial class ShuttleSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves a shuttle from its current position to docked on the target one. Goes through the hyperspace map while the timer is running.
|
/// Moves a shuttle from its current position to docked on the target one. Goes through the hyperspace map while the timer is running.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void FTLTravel(ShuttleComponent component,
|
public void FTLTravel(
|
||||||
|
EntityUid shuttleUid,
|
||||||
|
ShuttleComponent component,
|
||||||
EntityUid target,
|
EntityUid target,
|
||||||
float startupTime = DefaultStartupTime,
|
float startupTime = DefaultStartupTime,
|
||||||
float hyperspaceTime = DefaultTravelTime,
|
float hyperspaceTime = DefaultTravelTime,
|
||||||
bool dock = false,
|
bool dock = false,
|
||||||
string? priorityTag = null)
|
string? priorityTag = null)
|
||||||
{
|
{
|
||||||
if (!TrySetupFTL(component, out var hyperspace))
|
if (!TrySetupFTL(shuttleUid, component, out var hyperspace))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hyperspace.StartupTime = startupTime;
|
hyperspace.StartupTime = startupTime;
|
||||||
@@ -192,9 +193,8 @@ public sealed partial class ShuttleSystem
|
|||||||
_console.RefreshShuttleConsoles();
|
_console.RefreshShuttleConsoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TrySetupFTL(ShuttleComponent shuttle, [NotNullWhen(true)] out FTLComponent? component)
|
private bool TrySetupFTL(EntityUid uid, ShuttleComponent shuttle, [NotNullWhen(true)] out FTLComponent? component)
|
||||||
{
|
{
|
||||||
var uid = shuttle.Owner;
|
|
||||||
component = null;
|
component = null;
|
||||||
|
|
||||||
if (HasComp<FTLComponent>(uid))
|
if (HasComp<FTLComponent>(uid))
|
||||||
@@ -310,9 +310,9 @@ public sealed partial class ShuttleSystem
|
|||||||
if (comp.TargetUid != null && shuttle != null)
|
if (comp.TargetUid != null && shuttle != null)
|
||||||
{
|
{
|
||||||
if (comp.Dock)
|
if (comp.Dock)
|
||||||
TryFTLDock(shuttle, comp.TargetUid.Value, comp.PriorityTag);
|
TryFTLDock(uid, shuttle, comp.TargetUid.Value, comp.PriorityTag);
|
||||||
else
|
else
|
||||||
TryFTLProximity(shuttle, comp.TargetUid.Value);
|
TryFTLProximity(uid, shuttle, comp.TargetUid.Value);
|
||||||
|
|
||||||
mapId = Transform(comp.TargetUid.Value).MapID;
|
mapId = Transform(comp.TargetUid.Value).MapID;
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ public sealed partial class ShuttleSystem
|
|||||||
comp.TravelStream = null;
|
comp.TravelStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundSystem.Play(_arrivalSound.GetSound(), Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(uid)), _arrivalSound.Params);
|
_audio.PlayGlobal(_arrivalSound, Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(uid)), true);
|
||||||
|
|
||||||
if (TryComp<FTLDestinationComponent>(uid, out var dest))
|
if (TryComp<FTLDestinationComponent>(uid, out var dest))
|
||||||
{
|
{
|
||||||
@@ -380,7 +380,9 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
foreach (var (dock, xform) in EntityQuery<DockingComponent, TransformComponent>(true))
|
foreach (var (dock, xform) in EntityQuery<DockingComponent, TransformComponent>(true))
|
||||||
{
|
{
|
||||||
if (xform.ParentUid != uid || dock.Enabled == enabled) continue;
|
if (xform.ParentUid != uid || dock.Enabled == enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
_dockSystem.Undock(dock);
|
_dockSystem.Undock(dock);
|
||||||
dock.Enabled = enabled;
|
dock.Enabled = enabled;
|
||||||
}
|
}
|
||||||
@@ -388,25 +390,30 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
private void SetDockBolts(EntityUid uid, bool enabled)
|
private void SetDockBolts(EntityUid uid, bool enabled)
|
||||||
{
|
{
|
||||||
foreach (var (_, door, xform) in EntityQuery<DockingComponent, AirlockComponent, TransformComponent>(true))
|
var query = AllEntityQuery<DockingComponent, AirlockComponent, TransformComponent>();
|
||||||
{
|
|
||||||
if (xform.ParentUid != uid) continue;
|
|
||||||
|
|
||||||
_doors.TryClose(door.Owner);
|
while (query.MoveNext(out var doorUid, out _, out var door, out var xform))
|
||||||
_airlock.SetBoltsWithAudio(door.Owner, door, enabled);
|
{
|
||||||
|
if (xform.ParentUid != uid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_doors.TryClose(doorUid);
|
||||||
|
_airlock.SetBoltsWithAudio(doorUid, door, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float GetSoundRange(EntityUid uid)
|
private float GetSoundRange(EntityUid uid)
|
||||||
{
|
{
|
||||||
if (!_mapManager.TryGetGrid(uid, out var grid)) return 4f;
|
if (!_mapManager.TryGetGrid(uid, out var grid))
|
||||||
|
return 4f;
|
||||||
|
|
||||||
return MathF.Max(grid.LocalAABB.Width, grid.LocalAABB.Height) + 12.5f;
|
return MathF.Max(grid.LocalAABB.Width, grid.LocalAABB.Height) + 12.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupHyperspace()
|
private void SetupHyperspace()
|
||||||
{
|
{
|
||||||
if (_hyperSpaceMap != null) return;
|
if (_hyperSpaceMap != null)
|
||||||
|
return;
|
||||||
|
|
||||||
_hyperSpaceMap = _mapManager.CreateMap();
|
_hyperSpaceMap = _mapManager.CreateMap();
|
||||||
_sawmill.Info($"Setup hyperspace map at {_hyperSpaceMap.Value}");
|
_sawmill.Info($"Setup hyperspace map at {_hyperSpaceMap.Value}");
|
||||||
@@ -453,7 +460,8 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
while (childEnumerator.MoveNext(out var child))
|
while (childEnumerator.MoveNext(out var child))
|
||||||
{
|
{
|
||||||
if (!buckleQuery.TryGetComponent(child.Value, out var buckle) || buckle.Buckled) continue;
|
if (!buckleQuery.TryGetComponent(child.Value, out var buckle) || buckle.Buckled)
|
||||||
|
continue;
|
||||||
|
|
||||||
toKnock.Add(child.Value);
|
toKnock.Add(child.Value);
|
||||||
}
|
}
|
||||||
@@ -462,10 +470,9 @@ public sealed partial class ShuttleSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to dock with the target grid, otherwise falls back to proximity.
|
/// Tries to dock with the target grid, otherwise falls back to proximity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="priorityTag">Priority docking tag to prefer, e.g. for emergency shuttle</param>
|
public bool TryFTLDock(EntityUid shuttleUid, ShuttleComponent component, EntityUid targetUid, string? priorityTag = null)
|
||||||
public bool TryFTLDock(ShuttleComponent component, EntityUid targetUid, string? priorityTag = null)
|
|
||||||
{
|
{
|
||||||
if (!TryComp<TransformComponent>(component.Owner, out var xform) ||
|
if (!TryComp<TransformComponent>(shuttleUid, out var shuttleXform) ||
|
||||||
!TryComp<TransformComponent>(targetUid, out var targetXform) ||
|
!TryComp<TransformComponent>(targetUid, out var targetXform) ||
|
||||||
targetXform.MapUid == null ||
|
targetXform.MapUid == null ||
|
||||||
!targetXform.MapUid.Value.IsValid())
|
!targetXform.MapUid.Value.IsValid())
|
||||||
@@ -473,42 +480,49 @@ public sealed partial class ShuttleSystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = GetDockingConfig(component, targetUid, priorityTag);
|
var config = _dockSystem.GetDockingConfig(shuttleUid, targetUid, priorityTag);
|
||||||
|
|
||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
// Set position
|
FTLDock(config, shuttleXform);
|
||||||
xform.Coordinates = config.Coordinates;
|
|
||||||
xform.WorldRotation = config.Angle;
|
|
||||||
|
|
||||||
// Connect everything
|
|
||||||
foreach (var (dockA, dockB) in config.Docks)
|
|
||||||
{
|
|
||||||
_dockSystem.Dock(dockA.Owner, dockA, dockB.Owner, dockB);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TryFTLProximity(component, targetUid, xform, targetXform);
|
TryFTLProximity(shuttleUid, component, targetUid, shuttleXform, targetXform);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Forces an FTL dock.
|
||||||
|
/// </summary>
|
||||||
|
public void FTLDock(DockingConfig config, TransformComponent shuttleXform)
|
||||||
|
{
|
||||||
|
// Set position
|
||||||
|
shuttleXform.Coordinates = config.Coordinates;
|
||||||
|
_transform.SetWorldRotation(shuttleXform, config.Angle);
|
||||||
|
|
||||||
|
// Connect everything
|
||||||
|
foreach (var (dockAUid, dockBUid, dockA, dockB) in config.Docks)
|
||||||
|
{
|
||||||
|
_dockSystem.Dock(dockAUid, dockA, dockBUid, dockB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to arrive nearby without overlapping with other grids.
|
/// Tries to arrive nearby without overlapping with other grids.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryFTLProximity(ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null)
|
public bool TryFTLProximity(EntityUid shuttleUid, ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(targetUid, ref targetXform) ||
|
if (!Resolve(targetUid, ref targetXform) ||
|
||||||
targetXform.MapUid == null ||
|
targetXform.MapUid == null ||
|
||||||
!targetXform.MapUid.Value.IsValid() ||
|
!targetXform.MapUid.Value.IsValid() ||
|
||||||
!Resolve(component.Owner, ref xform))
|
!Resolve(shuttleUid, ref xform))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
var shuttleAABB = Comp<MapGridComponent>(component.Owner).LocalAABB;
|
var shuttleAABB = Comp<MapGridComponent>(shuttleUid).LocalAABB;
|
||||||
Box2 targetLocalAABB;
|
Box2 targetLocalAABB;
|
||||||
|
|
||||||
// Spawn nearby.
|
// Spawn nearby.
|
||||||
@@ -534,7 +548,8 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
foreach (var grid in _mapManager.FindGridsIntersecting(mapId, targetAABB))
|
foreach (var grid in _mapManager.FindGridsIntersecting(mapId, targetAABB))
|
||||||
{
|
{
|
||||||
if (!nearbyGrids.Add(grid.Owner)) continue;
|
if (!nearbyGrids.Add(grid.Owner))
|
||||||
|
continue;
|
||||||
|
|
||||||
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
||||||
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
||||||
@@ -557,7 +572,8 @@ public sealed partial class ShuttleSystem
|
|||||||
foreach (var grid in _mapManager.GetAllGrids())
|
foreach (var grid in _mapManager.GetAllGrids())
|
||||||
{
|
{
|
||||||
// Don't add anymore as it is irrelevant, but that doesn't mean we need to re-do existing work.
|
// Don't add anymore as it is irrelevant, but that doesn't mean we need to re-do existing work.
|
||||||
if (nearbyGrids.Contains(grid.Owner)) continue;
|
if (nearbyGrids.Contains(grid.Owner))
|
||||||
|
continue;
|
||||||
|
|
||||||
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
||||||
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
||||||
@@ -568,10 +584,10 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
Vector2 spawnPos;
|
Vector2 spawnPos;
|
||||||
|
|
||||||
if (TryComp<PhysicsComponent>(component.Owner, out var shuttleBody))
|
if (TryComp<PhysicsComponent>(shuttleUid, out var shuttleBody))
|
||||||
{
|
{
|
||||||
_physics.SetLinearVelocity(component.Owner, Vector2.Zero, body: shuttleBody);
|
_physics.SetLinearVelocity(shuttleUid, Vector2.Zero, body: shuttleBody);
|
||||||
_physics.SetAngularVelocity(component.Owner, 0f, body: shuttleBody);
|
_physics.SetAngularVelocity(shuttleUid, 0f, body: shuttleBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is pretty crude for multiple landings.
|
// TODO: This is pretty crude for multiple landings.
|
||||||
@@ -604,138 +620,4 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether the emergency shuttle can warp to the specified position.
|
|
||||||
/// </summary>
|
|
||||||
private bool ValidSpawn(EntityUid gridUid, MapGridComponent grid, Box2 area)
|
|
||||||
{
|
|
||||||
// If the target is a map then any tile is valid.
|
|
||||||
// TODO: We already need the entities-under check
|
|
||||||
if (HasComp<MapComponent>(gridUid))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return !grid.GetLocalTilesIntersecting(area).Any();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to get a valid docking configuration for the shuttle to the target grid.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="priorityTag">Priority docking tag to prefer, e.g. for emergency shuttle</param>
|
|
||||||
private DockingConfig? GetDockingConfig(ShuttleComponent component, EntityUid targetGrid, string? priorityTag = null)
|
|
||||||
{
|
|
||||||
var gridDocks = GetDocks(targetGrid);
|
|
||||||
|
|
||||||
if (gridDocks.Count <= 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
|
||||||
var targetGridGrid = Comp<MapGridComponent>(targetGrid);
|
|
||||||
var targetGridXform = xformQuery.GetComponent(targetGrid);
|
|
||||||
var targetGridAngle = targetGridXform.WorldRotation.Reduced();
|
|
||||||
|
|
||||||
var shuttleDocks = GetDocks(component.Owner);
|
|
||||||
var shuttleAABB = Comp<MapGridComponent>(component.Owner).LocalAABB;
|
|
||||||
|
|
||||||
var validDockConfigs = new List<DockingConfig>();
|
|
||||||
|
|
||||||
if (shuttleDocks.Count > 0)
|
|
||||||
{
|
|
||||||
// We'll try all combinations of shuttle docks and see which one is most suitable
|
|
||||||
foreach (var shuttleDock in shuttleDocks)
|
|
||||||
{
|
|
||||||
var shuttleDockXform = xformQuery.GetComponent(shuttleDock.Owner);
|
|
||||||
|
|
||||||
foreach (var gridDock in gridDocks)
|
|
||||||
{
|
|
||||||
var gridXform = xformQuery.GetComponent(gridDock.Owner);
|
|
||||||
|
|
||||||
if (!CanDock(
|
|
||||||
shuttleDock, shuttleDockXform,
|
|
||||||
gridDock, gridXform,
|
|
||||||
targetGridAngle,
|
|
||||||
shuttleAABB,
|
|
||||||
targetGrid,
|
|
||||||
targetGridGrid,
|
|
||||||
out var dockedAABB,
|
|
||||||
out var matty,
|
|
||||||
out var targetAngle)) continue;
|
|
||||||
|
|
||||||
// Can't just use the AABB as we want to get bounds as tight as possible.
|
|
||||||
var spawnPosition = new EntityCoordinates(targetGrid, matty.Transform(Vector2.Zero));
|
|
||||||
spawnPosition = new EntityCoordinates(targetGridXform.MapUid!.Value, spawnPosition.ToMapPos(EntityManager));
|
|
||||||
|
|
||||||
var dockedBounds = new Box2Rotated(shuttleAABB.Translated(spawnPosition.Position), targetGridAngle, spawnPosition.Position);
|
|
||||||
|
|
||||||
// Check if there's no intersecting grids (AKA oh god it's docking at cargo).
|
|
||||||
if (_mapManager.FindGridsIntersecting(targetGridXform.MapID,
|
|
||||||
dockedBounds).Any(o => o.Owner != targetGrid))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alright well the spawn is valid now to check how many we can connect
|
|
||||||
// Get the matrix for each shuttle dock and test it against the grid docks to see
|
|
||||||
// if the connected position / direction matches.
|
|
||||||
|
|
||||||
var dockedPorts = new List<(DockingComponent DockA, DockingComponent DockB)>()
|
|
||||||
{
|
|
||||||
(shuttleDock, gridDock),
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var other in shuttleDocks)
|
|
||||||
{
|
|
||||||
if (other == shuttleDock) continue;
|
|
||||||
|
|
||||||
foreach (var otherGrid in gridDocks)
|
|
||||||
{
|
|
||||||
if (otherGrid == gridDock) continue;
|
|
||||||
|
|
||||||
if (!CanDock(
|
|
||||||
other,
|
|
||||||
xformQuery.GetComponent(other.Owner),
|
|
||||||
otherGrid,
|
|
||||||
xformQuery.GetComponent(otherGrid.Owner),
|
|
||||||
targetGridAngle,
|
|
||||||
shuttleAABB,
|
|
||||||
targetGrid,
|
|
||||||
targetGridGrid,
|
|
||||||
out var otherDockedAABB,
|
|
||||||
out _,
|
|
||||||
out var otherTargetAngle) ||
|
|
||||||
!otherDockedAABB.Equals(dockedAABB) ||
|
|
||||||
!targetAngle.Equals(otherTargetAngle)) continue;
|
|
||||||
|
|
||||||
dockedPorts.Add((other, otherGrid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validDockConfigs.Add(new DockingConfig()
|
|
||||||
{
|
|
||||||
Docks = dockedPorts,
|
|
||||||
Area = dockedAABB.Value,
|
|
||||||
Coordinates = spawnPosition,
|
|
||||||
Angle = targetAngle,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validDockConfigs.Count <= 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Prioritise by priority docks, then by maximum connected ports, then by most similar angle.
|
|
||||||
validDockConfigs = validDockConfigs
|
|
||||||
.OrderByDescending(x => x.Docks.Any(docks =>
|
|
||||||
TryComp<PriorityDockComponent>(docks.DockB.Owner, out var priority) &&
|
|
||||||
priority.Tag?.Equals(priorityTag) == true))
|
|
||||||
.ThenByDescending(x => x.Docks.Count)
|
|
||||||
.ThenBy(x => Math.Abs(Angle.ShortestDistance(x.Angle.Reduced(), targetGridAngle).Theta)).ToList();
|
|
||||||
|
|
||||||
var location = validDockConfigs.First();
|
|
||||||
location.TargetGrid = targetGrid;
|
|
||||||
// TODO: Ideally do a hyperspace warpin, just have it run on like a 10 second timer.
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
69
Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs
Normal file
69
Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using Content.Server.Shuttles.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
|
public sealed partial class ShuttleSystem
|
||||||
|
{
|
||||||
|
private void InitializeGridFills()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<GridFillComponent, MapInitEvent>(OnGridFillMapInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridFillMapInit(EntityUid uid, GridFillComponent component, MapInitEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<DockingComponent>(uid, out var dock) ||
|
||||||
|
!TryComp<TransformComponent>(uid, out var xform) ||
|
||||||
|
xform.GridUid == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn on a dummy map and try to dock if possible, otherwise dump it.
|
||||||
|
var mapId = _mapManager.CreateMap();
|
||||||
|
var valid = false;
|
||||||
|
|
||||||
|
if (_loader.TryLoad(mapId, component.Path.ToString(), out var ent) &&
|
||||||
|
ent.Count == 1 &&
|
||||||
|
TryComp<TransformComponent>(ent[0], out var shuttleXform))
|
||||||
|
{
|
||||||
|
var escape = GetSingleDock(ent[0]);
|
||||||
|
|
||||||
|
if (escape != null)
|
||||||
|
{
|
||||||
|
var config = _dockSystem.GetDockingConfig(ent[0], xform.GridUid.Value, escape.Value.Entity, escape.Value.Component, uid, dock);
|
||||||
|
|
||||||
|
if (config != null)
|
||||||
|
{
|
||||||
|
FTLDock(config, shuttleXform);
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
_sawmill.Error($"Error loading gridfill dock for {ToPrettyString(uid)} / {component.Path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
_mapManager.DeleteMap(mapId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private (EntityUid Entity, DockingComponent Component)? GetSingleDock(EntityUid uid)
|
||||||
|
{
|
||||||
|
var dockQuery = GetEntityQuery<DockingComponent>();
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
var xform = xformQuery.GetComponent(uid);
|
||||||
|
|
||||||
|
var rator = xform.ChildEnumerator;
|
||||||
|
|
||||||
|
while (rator.MoveNext(out var child))
|
||||||
|
{
|
||||||
|
if (!dockQuery.TryGetComponent(child, out var dock))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return (child.Value, dock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Server.Shuttles.Components;
|
using Content.Server.Shuttles.Components;
|
||||||
using Content.Shared.CCVar;
|
using Content.Server.Stunnable;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Configuration;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems
|
namespace Content.Server.Shuttles.Systems
|
||||||
{
|
{
|
||||||
@@ -17,9 +18,18 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
public sealed partial class ShuttleSystem : SharedShuttleSystem
|
public sealed partial class ShuttleSystem : SharedShuttleSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||||
|
[Dependency] private readonly DockingSystem _dockSystem = default!;
|
||||||
|
[Dependency] private readonly DoorSystem _doors = default!;
|
||||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
||||||
|
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
||||||
|
[Dependency] private readonly StunSystem _stuns = default!;
|
||||||
|
[Dependency] private readonly ThrusterSystem _thruster = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
@@ -34,9 +44,8 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
_sawmill = Logger.GetSawmill("shuttles");
|
_sawmill = Logger.GetSawmill("shuttles");
|
||||||
|
|
||||||
InitializeEmergencyConsole();
|
|
||||||
InitializeEscape();
|
|
||||||
InitializeFTL();
|
InitializeFTL();
|
||||||
|
InitializeGridFills();
|
||||||
InitializeIFF();
|
InitializeIFF();
|
||||||
InitializeImpact();
|
InitializeImpact();
|
||||||
|
|
||||||
@@ -53,24 +62,14 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
UpdateEmergencyConsole(frameTime);
|
|
||||||
UpdateHyperspace(frameTime);
|
UpdateHyperspace(frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||||
{
|
{
|
||||||
CleanupEmergencyConsole();
|
|
||||||
CleanupEmergencyShuttle();
|
|
||||||
CleanupHyperspace();
|
CleanupHyperspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
|
||||||
{
|
|
||||||
base.Shutdown();
|
|
||||||
ShutdownEscape();
|
|
||||||
ShutdownEmergencyConsole();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnShuttleAdd(EntityUid uid, ShuttleComponent component, ComponentAdd args)
|
private void OnShuttleAdd(EntityUid uid, ShuttleComponent component, ComponentAdd args)
|
||||||
{
|
{
|
||||||
// Easier than doing it in the comp and they don't have constructors.
|
// Easier than doing it in the comp and they don't have constructors.
|
||||||
@@ -83,7 +82,8 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
private void OnGridFixtureChange(GridFixtureChangeEvent args)
|
private void OnGridFixtureChange(GridFixtureChangeEvent args)
|
||||||
{
|
{
|
||||||
// Look this is jank but it's a placeholder until we design it.
|
// Look this is jank but it's a placeholder until we design it.
|
||||||
if (args.NewFixtures.Count == 0) return;
|
if (args.NewFixtures.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
var uid = args.NewFixtures[0].Body.Owner;
|
var uid = args.NewFixtures[0].Body.Owner;
|
||||||
var manager = Comp<FixturesComponent>(uid);
|
var manager = Comp<FixturesComponent>(uid);
|
||||||
@@ -107,12 +107,12 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
private void OnShuttleStartup(EntityUid uid, ShuttleComponent component, ComponentStartup args)
|
private void OnShuttleStartup(EntityUid uid, ShuttleComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
if (!EntityManager.HasComponent<MapGridComponent>(component.Owner))
|
if (!EntityManager.HasComponent<MapGridComponent>(uid))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? physicsComponent))
|
if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,8 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
|
|
||||||
public void Toggle(EntityUid uid, ShuttleComponent component)
|
public void Toggle(EntityUid uid, ShuttleComponent component)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? physicsComponent)) return;
|
if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
component.Enabled = !component.Enabled;
|
component.Enabled = !component.Enabled;
|
||||||
|
|
||||||
@@ -164,7 +165,7 @@ namespace Content.Server.Shuttles.Systems
|
|||||||
// None of the below is necessary for any cleanup if we're just deleting.
|
// None of the below is necessary for any cleanup if we're just deleting.
|
||||||
if (EntityManager.GetComponent<MetaDataComponent>(uid).EntityLifeStage >= EntityLifeStage.Terminating) return;
|
if (EntityManager.GetComponent<MetaDataComponent>(uid).EntityLifeStage >= EntityLifeStage.Terminating) return;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? physicsComponent))
|
if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ public sealed class StationDataComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The emergency shuttle assigned to this station.
|
/// The emergency shuttle assigned to this station.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables, Access(typeof(ShuttleSystem), Friend = AccessPermissions.ReadWrite)]
|
[ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)]
|
||||||
public EntityUid? EmergencyShuttle;
|
public EntityUid? EmergencyShuttle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,12 +68,12 @@ namespace Content.Shared.Popups
|
|||||||
public abstract void PopupEntity(string message, EntityUid uid, PopupType type=PopupType.Small);
|
public abstract void PopupEntity(string message, EntityUid uid, PopupType type=PopupType.Small);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Variant of <see cref="PopupEntity(string, EntityUid, PopupType)"/> that shoes the popup only to some specific client.
|
/// Variant of <see cref="PopupEntity(string, EntityUid, PopupType)"/> that shows the popup only to some specific client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void PopupEntity(string message, EntityUid uid, EntityUid recipient, PopupType type = PopupType.Small);
|
public abstract void PopupEntity(string message, EntityUid uid, EntityUid recipient, PopupType type = PopupType.Small);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Variant of <see cref="PopupEntity(string, EntityUid, PopupType)"/> that shoes the popup only to some specific client.
|
/// Variant of <see cref="PopupEntity(string, EntityUid, PopupType)"/> that shows the popup only to some specific client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void PopupEntity(string message, EntityUid uid, ICommonSession recipient, PopupType type = PopupType.Small);
|
public abstract void PopupEntity(string message, EntityUid uid, ICommonSession recipient, PopupType type = PopupType.Small);
|
||||||
|
|
||||||
|
|||||||
406
Resources/Maps/Shuttles/escape_pod_small.yml
Normal file
406
Resources/Maps/Shuttles/escape_pod_small.yml
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
meta:
|
||||||
|
format: 3
|
||||||
|
name: DemoStation
|
||||||
|
author: Space-Wizards
|
||||||
|
postmapinit: false
|
||||||
|
tilemap:
|
||||||
|
0: Space
|
||||||
|
1: FloorArcadeBlue
|
||||||
|
2: FloorArcadeBlue2
|
||||||
|
3: FloorArcadeRed
|
||||||
|
4: FloorAsteroidCoarseSand0
|
||||||
|
5: FloorAsteroidCoarseSandDug
|
||||||
|
6: FloorAsteroidIronsand1
|
||||||
|
7: FloorAsteroidIronsand2
|
||||||
|
8: FloorAsteroidIronsand3
|
||||||
|
9: FloorAsteroidIronsand4
|
||||||
|
10: FloorAsteroidSand
|
||||||
|
11: FloorAsteroidTile
|
||||||
|
12: FloorBar
|
||||||
|
13: FloorBasalt
|
||||||
|
14: FloorBlue
|
||||||
|
15: FloorBlueCircuit
|
||||||
|
16: FloorBoxing
|
||||||
|
17: FloorCarpetClown
|
||||||
|
18: FloorCarpetOffice
|
||||||
|
19: FloorCave
|
||||||
|
20: FloorCaveDrought
|
||||||
|
21: FloorClown
|
||||||
|
22: FloorDark
|
||||||
|
23: FloorDarkDiagonal
|
||||||
|
24: FloorDarkDiagonalMini
|
||||||
|
25: FloorDarkHerringbone
|
||||||
|
26: FloorDarkMini
|
||||||
|
27: FloorDarkMono
|
||||||
|
28: FloorDarkOffset
|
||||||
|
29: FloorDarkPavement
|
||||||
|
30: FloorDarkPavementVertical
|
||||||
|
31: FloorDarkPlastic
|
||||||
|
32: FloorDesert
|
||||||
|
33: FloorDirt
|
||||||
|
34: FloorEighties
|
||||||
|
35: FloorElevatorShaft
|
||||||
|
36: FloorFlesh
|
||||||
|
37: FloorFreezer
|
||||||
|
38: FloorGlass
|
||||||
|
39: FloorGold
|
||||||
|
40: FloorGrass
|
||||||
|
41: FloorGrassDark
|
||||||
|
42: FloorGrassJungle
|
||||||
|
43: FloorGrassLight
|
||||||
|
44: FloorGreenCircuit
|
||||||
|
45: FloorGym
|
||||||
|
46: FloorHydro
|
||||||
|
47: FloorKitchen
|
||||||
|
48: FloorLaundry
|
||||||
|
49: FloorLino
|
||||||
|
50: FloorLowDesert
|
||||||
|
51: FloorMetalDiamond
|
||||||
|
52: FloorMime
|
||||||
|
53: FloorMono
|
||||||
|
54: FloorPlanetDirt
|
||||||
|
55: FloorPlanetGrass
|
||||||
|
56: FloorPlastic
|
||||||
|
57: FloorRGlass
|
||||||
|
58: FloorReinforced
|
||||||
|
59: FloorRockVault
|
||||||
|
60: FloorShowroom
|
||||||
|
61: FloorShuttleBlue
|
||||||
|
62: FloorShuttleOrange
|
||||||
|
63: FloorShuttlePurple
|
||||||
|
64: FloorShuttleRed
|
||||||
|
65: FloorShuttleWhite
|
||||||
|
66: FloorSilver
|
||||||
|
67: FloorSnow
|
||||||
|
68: FloorSteel
|
||||||
|
69: FloorSteelDiagonal
|
||||||
|
70: FloorSteelDiagonalMini
|
||||||
|
71: FloorSteelDirty
|
||||||
|
72: FloorSteelHerringbone
|
||||||
|
73: FloorSteelMini
|
||||||
|
74: FloorSteelMono
|
||||||
|
75: FloorSteelOffset
|
||||||
|
76: FloorSteelPavement
|
||||||
|
77: FloorSteelPavementVertical
|
||||||
|
78: FloorTechMaint
|
||||||
|
79: FloorTechMaint2
|
||||||
|
80: FloorTechMaint3
|
||||||
|
81: FloorWhite
|
||||||
|
82: FloorWhiteDiagonal
|
||||||
|
83: FloorWhiteDiagonalMini
|
||||||
|
84: FloorWhiteHerringbone
|
||||||
|
85: FloorWhiteMini
|
||||||
|
86: FloorWhiteMono
|
||||||
|
87: FloorWhiteOffset
|
||||||
|
88: FloorWhitePavement
|
||||||
|
89: FloorWhitePavementVertical
|
||||||
|
90: FloorWhitePlastic
|
||||||
|
91: FloorWood
|
||||||
|
92: FloorWoodTile
|
||||||
|
93: Lattice
|
||||||
|
94: Plating
|
||||||
|
entities:
|
||||||
|
- uid: 0
|
||||||
|
components:
|
||||||
|
- type: MetaData
|
||||||
|
- type: EscapePod
|
||||||
|
- parent: invalid
|
||||||
|
type: Transform
|
||||||
|
- chunks:
|
||||||
|
-1,-1:
|
||||||
|
ind: -1,-1
|
||||||
|
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABeAAAAPQAAAA==
|
||||||
|
0,0:
|
||||||
|
ind: 0,0
|
||||||
|
tiles: XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
||||||
|
-1,0:
|
||||||
|
ind: -1,0
|
||||||
|
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABeAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXQAAAF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
||||||
|
0,-1:
|
||||||
|
ind: 0,-1
|
||||||
|
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
||||||
|
type: MapGrid
|
||||||
|
- type: Broadphase
|
||||||
|
- angularDamping: 0.05
|
||||||
|
linearDamping: 0.05
|
||||||
|
fixedRotation: False
|
||||||
|
bodyType: Dynamic
|
||||||
|
type: Physics
|
||||||
|
- fixtures: []
|
||||||
|
type: Fixtures
|
||||||
|
- id: Empty
|
||||||
|
type: BecomesStation
|
||||||
|
- type: OccluderTree
|
||||||
|
- type: Shuttle
|
||||||
|
- nextUpdate: 88.8784752
|
||||||
|
type: GridPathfinding
|
||||||
|
- gravityShakeSound: !type:SoundPathSpecifier
|
||||||
|
path: /Audio/Effects/alert.ogg
|
||||||
|
type: Gravity
|
||||||
|
- chunkCollection:
|
||||||
|
version: 2
|
||||||
|
nodes: []
|
||||||
|
type: DecalGrid
|
||||||
|
- version: 2
|
||||||
|
data:
|
||||||
|
tiles:
|
||||||
|
-1,-1:
|
||||||
|
0: 52224
|
||||||
|
0,0:
|
||||||
|
0: 1
|
||||||
|
-1,0:
|
||||||
|
0: 12
|
||||||
|
0,-1:
|
||||||
|
0: 4352
|
||||||
|
uniqueMixes:
|
||||||
|
- volume: 2500
|
||||||
|
temperature: 293.15
|
||||||
|
moles:
|
||||||
|
- 21.824879
|
||||||
|
- 82.10312
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
chunkSize: 4
|
||||||
|
type: GridAtmosphere
|
||||||
|
- type: GasTileOverlay
|
||||||
|
- type: RadiationGridResistance
|
||||||
|
- uid: 1
|
||||||
|
type: WallShuttle
|
||||||
|
components:
|
||||||
|
- pos: -1.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 2
|
||||||
|
type: WallShuttle
|
||||||
|
components:
|
||||||
|
- pos: -1.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 3
|
||||||
|
type: WallShuttle
|
||||||
|
components:
|
||||||
|
- pos: 0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 4
|
||||||
|
type: WallShuttle
|
||||||
|
components:
|
||||||
|
- pos: 0.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 5
|
||||||
|
type: WallShuttleDiagonal
|
||||||
|
components:
|
||||||
|
- pos: -1.5,1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 6
|
||||||
|
type: WallShuttleDiagonal
|
||||||
|
components:
|
||||||
|
- rot: -1.5707963267948966 rad
|
||||||
|
pos: 0.5,1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 7
|
||||||
|
type: ShuttleWindow
|
||||||
|
components:
|
||||||
|
- pos: -0.5,1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 8
|
||||||
|
type: Grille
|
||||||
|
components:
|
||||||
|
- pos: -0.5,1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 9
|
||||||
|
type: AtmosDeviceFanTiny
|
||||||
|
components:
|
||||||
|
- pos: -0.5,-1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 10
|
||||||
|
type: Thruster
|
||||||
|
components:
|
||||||
|
- rot: 3.141592653589793 rad
|
||||||
|
pos: -1.5,-1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- bodyType: Static
|
||||||
|
type: Physics
|
||||||
|
- uid: 11
|
||||||
|
type: Thruster
|
||||||
|
components:
|
||||||
|
- rot: 3.141592653589793 rad
|
||||||
|
pos: 0.5,-1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- bodyType: Static
|
||||||
|
type: Physics
|
||||||
|
- uid: 12
|
||||||
|
type: AirlockExternalShuttleLocked
|
||||||
|
components:
|
||||||
|
- pos: -0.5,-1.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- fixtures:
|
||||||
|
- shape: !type:PolygonShape
|
||||||
|
radius: 0.01
|
||||||
|
vertices:
|
||||||
|
- 0.49,-0.49
|
||||||
|
- 0.49,0.49
|
||||||
|
- -0.49,0.49
|
||||||
|
- -0.49,-0.49
|
||||||
|
mask:
|
||||||
|
- Impassable
|
||||||
|
- MidImpassable
|
||||||
|
- HighImpassable
|
||||||
|
- LowImpassable
|
||||||
|
- InteractImpassable
|
||||||
|
layer:
|
||||||
|
- MidImpassable
|
||||||
|
- HighImpassable
|
||||||
|
- BulletImpassable
|
||||||
|
- InteractImpassable
|
||||||
|
- Opaque
|
||||||
|
density: 100
|
||||||
|
hard: True
|
||||||
|
restitution: 0
|
||||||
|
friction: 0.4
|
||||||
|
id: null
|
||||||
|
- shape: !type:PhysShapeCircle
|
||||||
|
radius: 0.2
|
||||||
|
position: 0,-0.5
|
||||||
|
mask: []
|
||||||
|
layer: []
|
||||||
|
density: 1
|
||||||
|
hard: False
|
||||||
|
restitution: 0
|
||||||
|
friction: 0.4
|
||||||
|
id: docking
|
||||||
|
type: Fixtures
|
||||||
|
- uid: 13
|
||||||
|
type: GeneratorWallmountAPU
|
||||||
|
components:
|
||||||
|
- pos: -1.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 14
|
||||||
|
type: SubstationWallBasic
|
||||||
|
components:
|
||||||
|
- pos: 0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 15
|
||||||
|
type: APCBasic
|
||||||
|
components:
|
||||||
|
- rot: 1.5707963267948966 rad
|
||||||
|
pos: -1.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 16
|
||||||
|
type: CableHV
|
||||||
|
components:
|
||||||
|
- pos: -1.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- enabled: True
|
||||||
|
type: AmbientSound
|
||||||
|
- uid: 17
|
||||||
|
type: CableHV
|
||||||
|
components:
|
||||||
|
- pos: -0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 18
|
||||||
|
type: CableHV
|
||||||
|
components:
|
||||||
|
- pos: 0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- enabled: True
|
||||||
|
type: AmbientSound
|
||||||
|
- uid: 19
|
||||||
|
type: CableMV
|
||||||
|
components:
|
||||||
|
- pos: 0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- enabled: True
|
||||||
|
type: AmbientSound
|
||||||
|
- uid: 20
|
||||||
|
type: CableMV
|
||||||
|
components:
|
||||||
|
- pos: -0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 21
|
||||||
|
type: CableMV
|
||||||
|
components:
|
||||||
|
- pos: -0.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 22
|
||||||
|
type: CableMV
|
||||||
|
components:
|
||||||
|
- pos: -1.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- enabled: True
|
||||||
|
type: AmbientSound
|
||||||
|
- uid: 23
|
||||||
|
type: CableApcExtension
|
||||||
|
components:
|
||||||
|
- pos: -1.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- enabled: True
|
||||||
|
type: AmbientSound
|
||||||
|
- uid: 24
|
||||||
|
type: CableApcExtension
|
||||||
|
components:
|
||||||
|
- pos: -0.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 25
|
||||||
|
type: CableApcExtension
|
||||||
|
components:
|
||||||
|
- pos: -0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- uid: 26
|
||||||
|
type: ChairPilotSeat
|
||||||
|
components:
|
||||||
|
- rot: 3.141592653589793 rad
|
||||||
|
pos: -0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- bodyType: Static
|
||||||
|
type: Physics
|
||||||
|
- uid: 27
|
||||||
|
type: ChairPilotSeat
|
||||||
|
components:
|
||||||
|
- rot: 3.141592653589793 rad
|
||||||
|
pos: -0.5,0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- bodyType: Static
|
||||||
|
type: Physics
|
||||||
|
- uid: 28
|
||||||
|
type: PoweredSmallLight
|
||||||
|
components:
|
||||||
|
- rot: 1.5707963267948966 rad
|
||||||
|
pos: -0.5,-0.5
|
||||||
|
parent: 0
|
||||||
|
type: Transform
|
||||||
|
- powerLoad: 0
|
||||||
|
type: ApcPowerReceiver
|
||||||
|
...
|
||||||
@@ -740,6 +740,13 @@
|
|||||||
- type: PriorityDock
|
- type: PriorityDock
|
||||||
tag: DockArrivals
|
tag: DockArrivals
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: AirlockGlassShuttle
|
||||||
|
id: AirlockExternalGlassShuttleEscape
|
||||||
|
suffix: External, Escape 3x4, Glass, Docking
|
||||||
|
components:
|
||||||
|
- type: GridFill
|
||||||
|
|
||||||
#HighSecDoors
|
#HighSecDoors
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: HighSecDoor
|
parent: HighSecDoor
|
||||||
|
|||||||
Reference in New Issue
Block a user