Adds the Central Command outpost for Roundend and ERT to spawn at. (#9146)

* Adds Reach II

* Updated Reach II to work after refactor

* removing old map

* Adding the Central Command outpost

* Reachii isn't meant to be in here at all.

* updated possible error in .yml

* updating .yml

* Updated CentComm, fixed some issues like lighting.

* Imagine if we also docked at centcomm

* a

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
LittleBuilderJane
2022-06-27 15:11:39 +02:00
committed by GitHub
parent 5e316afe86
commit 6325a10a43
9 changed files with 29210 additions and 107 deletions

View File

@@ -20,6 +20,12 @@ public sealed class HyperspaceComponent : Component
[ViewVariables(VVAccess.ReadWrite)]
public float Accumulator = 0f;
/// <summary>
/// Target Uid to dock with at the end of hyperspace.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("targetUid")]
public EntityUid? TargetUid;
[ViewVariables(VVAccess.ReadWrite), DataField("targetCoordinates")]
public EntityCoordinates TargetCoordinates;
}

View File

@@ -1,3 +1,4 @@
using Content.Server.Doors.Components;
using Content.Server.Doors.Systems;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
@@ -322,6 +323,16 @@ namespace Content.Server.Shuttles.Systems
dockA.DockJoint = joint;
dockB.DockJoint = joint;
if (TryComp<AirlockComponent>(dockA.Owner, out var airlockA))
{
airlockA.SetBoltsWithAudio(true);
}
if (TryComp<AirlockComponent>(dockB.Owner, out var airlockB))
{
airlockB.SetBoltsWithAudio(true);
}
if (TryComp(dockA.Owner, out DoorComponent? doorA))
{
doorA.ChangeAirtight = false;
@@ -406,6 +417,16 @@ namespace Content.Server.Shuttles.Systems
if (dock.DockedWith == null)
return;
if (TryComp<AirlockComponent>(dock.Owner, out var airlockA))
{
airlockA.SetBoltsWithAudio(false);
}
if (TryComp<AirlockComponent>(dock.DockedWith, out var airlockB))
{
airlockB.SetBoltsWithAudio(false);
}
if (TryComp(dock.Owner, out DoorComponent? doorA))
{
doorA.ChangeAirtight = true;

View File

@@ -44,7 +44,7 @@ public sealed partial class ShuttleSystem
/// <summary>
/// How long after the transit is over to end the round.
/// </summary>
private readonly TimeSpan _bufferTime = TimeSpan.FromSeconds(3);
private readonly TimeSpan _bufferTime = TimeSpan.FromSeconds(5);
/// <summary>
/// <see cref="CCVars.EmergencyShuttleTransitTime"/>
@@ -113,13 +113,20 @@ public sealed partial class ShuttleSystem
{
if (!TryComp<ShuttleComponent>(comp.EmergencyShuttle, out var shuttle)) continue;
// TODO: Add support so Hyperspace will just dock it to Centcomm.
if (Deleted(_centcomm))
{
// TODO: Need to get non-overlapping positions.
Hyperspace(shuttle,
new EntityCoordinates(
_mapManager.GetMapEntityId(_centcommMap.Value),
Vector2.One * 1000f), _consoleAccumulator, _transitTime);
}
else
{
Hyperspace(shuttle,
_centcomm.Value, _consoleAccumulator, _transitTime);
}
}
}
}

View File

@@ -38,6 +38,7 @@ public sealed partial class ShuttleSystem
[Dependency] private readonly StationSystem _station = default!;
private MapId? _centcommMap;
private EntityUid? _centcomm;
/// <summary>
/// Used for multiple shuttle spawn offsets.
@@ -91,19 +92,20 @@ public sealed partial class ShuttleSystem
var player = args.SenderSession.AttachedEntity;
if (player == null ||
!TryComp<StationDataComponent>(_station.GetOwningStation(player.Value), out var stationData)) return;
!TryComp<StationDataComponent>(_station.GetOwningStation(player.Value), out var stationData) ||
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle)) return;
var config = GetDockingConfig(stationData);
var targetGrid = GetLargestGrid(stationData);
if (targetGrid == null) return;
var config = GetDockingConfig(shuttle, targetGrid.Value);
if (config == null) return;
if (config != null)
{
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
{
StationUid = config.TargetGrid,
StationUid = targetGrid,
Position = config.Area,
});
}
}
/// <summary>
/// Checks whether the emergency shuttle can warp to the specified position.
@@ -113,38 +115,23 @@ public sealed partial class ShuttleSystem
return !grid.Grid.GetLocalTilesIntersecting(area).Any();
}
/// <summary>
/// Tries to find the most valid docking config for the station.
/// </summary>
private DockingConfig? GetDockingConfig(StationDataComponent dataComponent)
private DockingConfig? GetDockingConfig(ShuttleComponent component, EntityUid targetGrid)
{
// Find the largest grid associated with the station, then try all combinations of docks on it with
// all of them on the shuttle and try to find the most appropriate.
if (dataComponent.EmergencyShuttle == null) return null;
var targetGrid = GetLargestGrid(dataComponent);
if (targetGrid == null) return null;
var gridDocks = GetDocks(targetGrid.Value);
var gridDocks = GetDocks(targetGrid);
if (gridDocks.Count <= 0) return null;
var xformQuery = GetEntityQuery<TransformComponent>();
var targetGridGrid = Comp<IMapGridComponent>(targetGrid.Value);
var targetGridXform = xformQuery.GetComponent(targetGrid.Value);
var targetGridMatrix = targetGridXform.WorldMatrix;
var targetGridGrid = Comp<IMapGridComponent>(targetGrid);
var targetGridXform = xformQuery.GetComponent(targetGrid);
var targetGridAngle = targetGridXform.WorldRotation.Reduced();
var targetGridRotation = targetGridAngle.ToVec();
var shuttleDocks = GetDocks(dataComponent.EmergencyShuttle.Value);
var shuttleAABB = Comp<IMapGridComponent>(dataComponent.EmergencyShuttle.Value).Grid.LocalAABB;
var shuttleDocks = GetDocks(component.Owner);
var shuttleAABB = Comp<IMapGridComponent>(component.Owner).Grid.LocalAABB;
var validDockConfigs = new List<DockingConfig>();
if (TryComp<ShuttleComponent>(dataComponent.EmergencyShuttle, out var shuttle))
{
SetPilotable(shuttle, false);
}
SetPilotable(component, false);
if (shuttleDocks.Count > 0)
{
@@ -168,7 +155,7 @@ public sealed partial class ShuttleSystem
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.Value, matty.Transform(Vector2.Zero));
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);
@@ -240,7 +227,7 @@ public sealed partial class ShuttleSystem
.ThenBy(x => Math.Abs(Angle.ShortestDistance(x.Angle.Reduced(), targetGridAngle).Theta)).ToList();
var location = validDockConfigs.First();
location.TargetGrid = targetGrid.Value;
location.TargetGrid = targetGrid;
// TODO: Ideally do a hyperspace warpin, just have it run on like a 10 second timer.
return location;
@@ -249,72 +236,33 @@ public sealed partial class ShuttleSystem
/// <summary>
/// Calls the emergency shuttle for the station.
/// </summary>
/// <param name="stationUid"></param>
/// <param name="dryRun">Should we show the debug data and not actually call it.</param>
public void CallEmergencyShuttle(EntityUid? stationUid)
{
if (!TryComp<StationDataComponent>(stationUid, out var stationData) ||
!TryComp<TransformComponent>(stationData.EmergencyShuttle, out var xform)) return;
!TryComp<TransformComponent>(stationData.EmergencyShuttle, out var xform) ||
!TryComp<ShuttleComponent>(stationData.EmergencyShuttle, out var shuttle)) return;
var config = GetDockingConfig(stationData);
if (config != null)
{
// Set position
xform.Coordinates = config.Coordinates;
xform.WorldRotation = config.Angle;
// Connect everything
foreach (var (dockA, dockB) in config.Docks)
{
_dockSystem.Dock(dockA, dockB);
}
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} docked with stations");
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}")), playDefaultSound: false);
// TODO: Need filter extensions or something don't blame me.
SoundSystem.Play("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast());
// Bolt all the airlocks so they don't stuff around with them.
SetDockBolts(stationData.EmergencyShuttle.Value, true);
}
else
{
var shuttleAABB = Comp<IMapGridComponent>(stationData.EmergencyShuttle.Value).Grid.WorldAABB;
Box2? aabb = null;
// Spawn nearby.
foreach (var gridUid in stationData.Grids)
{
var grid = Comp<IMapGridComponent>(gridUid).Grid;
var gridAABB = grid.WorldAABB;
aabb = aabb?.Union(gridAABB) ?? gridAABB;
}
var targetGrid = GetLargestGrid(stationData);
// UHH GOOD LUCK
if (aabb == null)
if (targetGrid == null)
{
_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);
// TODO: Need filter extensions or something don't blame me.
SoundSystem.Play("/Audio/Misc/notice1.ogg", Filter.Broadcast());
return;
}
var minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height);
var spawnPos = aabb.Value.Center + _random.NextVector2(minRadius, minRadius + 10f);
if (TryComp<PhysicsComponent>(stationData.EmergencyShuttle, out var shuttleBody))
if (TryHyperspaceDock(shuttle, targetGrid.Value))
{
shuttleBody.LinearVelocity = Vector2.Zero;
shuttleBody.AngularVelocity = 0f;
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} docked with stations");
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}")), playDefaultSound: false);
// TODO: Need filter extensions or something don't blame me.
SoundSystem.Play("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast());
}
xform.WorldPosition = spawnPos;
xform.WorldRotation = _random.NextAngle();
else
{
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid.Value)} unable to find a valid docking port for {ToPrettyString(stationUid.Value)}");
_chatSystem.DispatchStationAnnouncement(stationUid.Value, Loc.GetString("emergency-shuttle-nearby"), playDefaultSound: false);
// TODO: Need filter extensions or something don't blame me.
@@ -443,9 +391,18 @@ public sealed partial class ShuttleSystem
_centcommMap = _mapManager.CreateMap();
_mapManager.SetMapPaused(_centcommMap.Value, true);
// Load Centcomm, when we get it!
// var (_, centcomm) = _loader.LoadBlueprint(_centcommMap.Value, "/Maps/Salvage/saltern.yml", new MapLoadOptions());
// _centcomm = centcomm;
// Load Centcomm
var centcommPath = _configManager.GetCVar(CCVars.CentcommMap);
if (!string.IsNullOrEmpty(centcommPath))
{
var (_, centcomm) = _loader.LoadBlueprint(_centcommMap.Value, "/Maps/centcomm.yml");
_centcomm = centcomm;
}
else
{
_sawmill.Info("No centcomm map found, skipping setup.");
}
foreach (var comp in EntityQuery<StationDataComponent>(true))
{

View File

@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Buckle.Components;
using Content.Server.Doors.Components;
using Content.Server.Doors.Systems;
@@ -51,20 +52,49 @@ public sealed partial class ShuttleSystem
float startupTime = DefaultStartupTime,
float hyperspaceTime = DefaultTravelTime)
{
if (HasComp<HyperspaceComponent>(component.Owner))
{
_sawmill.Warning($"Tried queuing {ToPrettyString(component.Owner)} which already has HyperspaceComponent?");
if (!TrySetupHyperspace(component.Owner, out var hyperspace))
return;
}
SetDocks(component.Owner, false);
var hyperspace = AddComp<HyperspaceComponent>(component.Owner);
hyperspace.StartupTime = startupTime;
hyperspace.TravelTime = hyperspaceTime;
hyperspace.Accumulator = hyperspace.StartupTime;
hyperspace.TargetCoordinates = coordinates;
}
/// <summary>
/// Moves a shuttle from its current position to docked on the target one. Goes through the hyperspace map while the timer is running.
/// </summary>
public void Hyperspace(ShuttleComponent component,
EntityUid target,
float startupTime = DefaultStartupTime,
float hyperspaceTime = DefaultTravelTime)
{
if (!TrySetupHyperspace(component.Owner, out var hyperspace))
return;
hyperspace.StartupTime = startupTime;
hyperspace.TravelTime = hyperspaceTime;
hyperspace.Accumulator = hyperspace.StartupTime;
hyperspace.TargetUid = target;
}
private bool TrySetupHyperspace(EntityUid uid, [NotNullWhen(true)] out HyperspaceComponent? component)
{
component = null;
if (HasComp<HyperspaceComponent>(uid))
{
_sawmill.Warning($"Tried queuing {ToPrettyString(uid)} which already has HyperspaceComponent?");
return false;
}
// TODO: Maybe move this to docking instead?
SetDocks(uid, false);
component = AddComp<HyperspaceComponent>(uid);
// TODO: Need BroadcastGrid to not be bad.
SoundSystem.Play(_startupSound.GetSound(), Filter.Pvs(component.Owner, GetSoundRange(component.Owner), entityManager: EntityManager), _startupSound.Params);
return true;
}
private void UpdateHyperspace(float frameTime)
@@ -107,8 +137,8 @@ public sealed partial class ShuttleSystem
// Arrive.
case HyperspaceState.Travelling:
DoTheDinosaur(xform);
SetDocks(comp.Owner, true);
SetDockBolts(comp.Owner, false);
SetDocks(comp.Owner, true);
if (TryComp(comp.Owner, out body))
{
@@ -118,7 +148,15 @@ public sealed partial class ShuttleSystem
body.AngularDamping = ShuttleIdleAngularDamping;
}
if (comp.TargetUid != null && TryComp<ShuttleComponent>(comp.Owner, out var shuttle))
{
TryHyperspaceDock(shuttle, comp.TargetUid.Value);
}
else
{
xform.Coordinates = comp.TargetCoordinates;
}
SoundSystem.Play(_arrivalSound.GetSound(),
Filter.Pvs(comp.Owner, GetSoundRange(comp.Owner), entityManager: EntityManager));
RemComp<HyperspaceComponent>(comp.Owner);
@@ -141,11 +179,11 @@ public sealed partial class ShuttleSystem
private void SetDockBolts(EntityUid uid, bool enabled)
{
foreach (var (dock, door, xform) in EntityQuery<DockingComponent, AirlockComponent, TransformComponent>(true))
foreach (var (_, door, xform) in EntityQuery<DockingComponent, AirlockComponent, TransformComponent>(true))
{
if (xform.ParentUid != uid) continue;
_doors.TryClose(dock.Owner);
_doors.TryClose(door.Owner);
door.SetBoltsWithAudio(enabled);
}
}
@@ -209,4 +247,52 @@ public sealed partial class ShuttleSystem
toKnock.Add(child.Value);
}
}
private bool TryHyperspaceDock(ShuttleComponent component, EntityUid targetUid)
{
if (!TryComp<TransformComponent>(component.Owner, out var xform) ||
!TryComp<TransformComponent>(targetUid, out var targetXform)) return false;
var config = GetDockingConfig(component, targetUid);
if (config != null)
{
// Set position
xform.Coordinates = config.Coordinates;
xform.WorldRotation = config.Angle;
// Connect everything
foreach (var (dockA, dockB) in config.Docks)
{
_dockSystem.Dock(dockA, dockB);
}
return true;
}
var shuttleAABB = Comp<IMapGridComponent>(component.Owner).Grid.WorldAABB;
Box2? aabb = null;
// Spawn nearby.
foreach (var grid in _mapManager.GetAllMapGrids(targetXform.MapID))
{
var gridAABB = grid.WorldAABB;
aabb = aabb?.Union(gridAABB) ?? gridAABB;
}
aabb ??= new Box2();
var minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height);
var spawnPos = aabb.Value.Center + _random.NextVector2(minRadius, minRadius + 10f);
if (TryComp<PhysicsComponent>(component.Owner, out var shuttleBody))
{
shuttleBody.LinearVelocity = Vector2.Zero;
shuttleBody.AngularVelocity = 0f;
}
xform.WorldPosition = spawnPos;
xform.WorldRotation = _random.NextAngle();
return false;
}
}

View File

@@ -1,5 +1,6 @@
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Utility;
namespace Content.Shared.CCVar
{
@@ -934,6 +935,12 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> EmergencyShuttleEnabled =
CVarDef.Create("shuttle.emergency_enabled", true, CVar.SERVERONLY);
/// <summary>
/// The map to load for centcomm for the emergency shuttle to dock to.
/// </summary>
public static readonly CVarDef<string> CentcommMap =
CVarDef.Create("shuttle.centcomm_map", "/Maps/centcomm.yml", CVar.SERVERONLY);
/*
* VIEWPORT
*/

View File

@@ -11,7 +11,7 @@ emergency-shuttle-command-dock-desc = Calls the emergency shuttle and docks it t
emergency-shuttle-command-launch-desc = Early launches the emergency shuttle if possible.
# Emergency shuttle
emergency-shuttle-left = The Emergency Shuttle has left the station. Estimate {$transitTime} seconds until the shuttle clears the area.
emergency-shuttle-left = The Emergency Shuttle has left the station. Estimate {$transitTime} seconds until the shuttle arives at Centcomm.
emergency-shuttle-launch-time = The emergency shuttle will launch in {$consoleAccumulator} seconds.
emergency-shuttle-docked = The Emergency Shuttle has docked with the station. It will leave in {$time} seconds.
emergency-shuttle-good-luck = The Emergency Shuttle is unable to find a station. Good luck.

29004
Resources/Maps/centcomm.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
- type: gameMap
id: centcomm
mapName: 'Central Command'
mapPath: /Maps/centcomm.yml
minPlayers: 10
stations:
centcomm:
mapNameTemplate: '{0} Central Command {1}'
nameGenerator:
!type:NanotrasenNameGenerator
prefixCreator: 'TG'
overflowJobs:
- Passenger
availableJobs:
Passenger: [ 0, 1 ]