mirror of
https://github.com/DeltaV-Station/Delta-v.git
synced 2026-10-04 13:27:30 +00:00
+24









Debug
deltanedas
metalgearsloth
Nemanja
PJBot
Psychpsyo
deltanedas
metalgearsloth
ravage
Pieter-Jan Briers
LEVELcat
Repo
nikthechampiongr
Doru991
DrSmugleaf
Skarletto
NULL882
lunarcomets
Miro Kavaliou
Kara
Kacper Urbańczyk
TsjipTsjip
daerSeebaer
Fluffiest Floofers
Flareguy
Leon Friedrich
Kevin Zheng
drteaspoon420
Ubaser
Nim
Kacper Urbańczyk
Tox Cruize
Ed
Michael Cu
fd2cc8570d
* Automatic changelog update * Make NPC names proper nouns & fix some genders (#20534) * Proper names & genders * Uppercase proper names * Make Smile female * fix bingus wrinkly head (#20531) * rouny meat and steak (#20526) * lost friendship flavor * add rouny steak * rouny special meat * rouny meat textures --------- Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Wearable Wet Floor Sign and 'Janitorial Suicide Vest' (#20311) * Explosive wet floor sign & janitorial suicide vest * fix attributions * Remove name & desc from explosive wet floor sign * Make wet floor sign chameleonable * Automatic changelog update * Minor slippery stuff (#20535) * Update submodule to 162.2.0 (#20570) * Predicted armor (#20560) * clean up some lines in smile the slime prototype (#20552) * Revert "Use full file path for temp replays (#19002)" (#20545) * Add EyesGlasses into ClothesMate (#20523) * Automatic changelog update * Fix Punpun crew monitor sensor (#20484) * Automatic changelog update * EasyPry airlocks for arrivals. Now also prying refactor I guess (#19394) Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> * Automatic changelog update * Make arcades hackable again (#20555) * Automatic changelog update * Health alert tweaks (#20557) * Automatic changelog update * Add active and ended game rule components, generic TryRoundStartAttempt and minPlayers field (#20564) * Improve active game rule querying, add generic try round start attempt method, move minPlayers to GameRuleComponent * Nukeops todo and cleanup * Remove Active field * Add EndedGameRuleComponent * bartender suit (#20521) * give me a drink bartender * guh * aARG * Necropolis and mine walls (#20578) * Automatic changelog update * archaic accent tweaks (#20567) * Automatic changelog update * Add confirmation to kick and respawn in the admin player actions panel (#20542) * Remove windows-latest CI runs, remove unused build-test-release.yml (#20540) * Change .editorconfig to keep existing attribute arrangement (#20538) * Automatic changelog update * Catch replay start and end errors on round restarts (#20565) * Update trivial components to use auto comp states (#20539) * Fix role unbans not applying in real time (#20547) * Disable AHelp buttons when no player is selected, update button styling (#20568) * Automatic changelog update * Added a toggle fullscreen button (default F11) (#20272) * Added a toggle fullscreen button (default F11) * Removed un-needed comments * Review Requested Changes * Fixed Acidental Spacing Change * bwoink, removed extraneous code * nothing, litterally * Automatic changelog update * Fix not networking markings (#20588) * Automatic changelog update * Update RobustToolbox to v162.2.1 (#20590) * Automatic changelog update * Glorfcode (force say on damage/stun/crit) (#20562) * Automatic changelog update * Fix AHelp progressively showing more AHelp panels (#20591) * Automatic changelog update * caninsert entitystorage tweaks (#20589) * Automatic changelog update * Fix mapping actions crashing on load (#20592) * Fix loading a map with a ThirstComponent crashing the game (#20594) * Fix electrocution displaying real name of disguised players (#20603) * Organ fixes (#20488) * Automatic changelog update * Kettle medical rework (#20435) * Initial try at medical rework for kettle * Re-add decal decorations to Kettle's medical * Add more lockers to kettle's med * Actually upload kettle's map, not its proto * Automatic changelog update * Added blocked visuals to volumetric pump (#20610) * Automatic changelog update * Move TimedDespawn to engine (#20515) * Update submodule to 163.0.0 (#20616) * Remove v0.1 version number from local main menu screen (#20617) * Remove cloneData parameter from AutoNetworkedField (#20596) * Update submodule to 164.0.0 (#20618) * fix cognizine ghost role (#20632) Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Move ID layer one pixel to correct alignment (#20630) * Update nukie hardsuit descriptions (#20529) * Make holofans destructable (#20445) * Automatic changelog update * bowl is open (#20453) Co-authored-by: deltanedas <@deltanedas:kde.org> * Add TestPair.WaitCommand() (#20615) * Rename ThreatPrototype and mark fields as required (#20611) * Adjust hard bomb shape (#20608) * dragon refactor, objectives and use GenericAntag (#20201) Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Added generic empty liquids tank (#20563) * Move view variables verb to the top of the list with no category and localize it (#20546) * saltern update (#20325) Co-authored-by: deltanedas <@deltanedas:kde.org> * Fix followers leaking (#20643) * Add Winter Boots (#20622) * add * fix prototype * Add QM mantle (#20621) * add * fix prototype * Automatic changelog update * Slime mobs breathe nitrogen and resprite their organs (#20577) * Slimes breathe nitrogen and resprite their organs * ups * mmm * Automatic changelog update * Fix the new lizard horn's consistency + issue (#20620) * fix * add * Revert "add" This reverts commit a054a3204a8f185a94ceb80b1bd3bc9f30423711. * Add RandomHumanoidAppearance component to for space ninjas (#20605) * Automatic changelog update * Space cat breathes space (#20550) * Space cat breathes space Made Space Cat lungs ROBUST * Made Space Cat's lungs ROBUST 2.0 * Automatic changelog update * Wide anomaly locator (#20581) * Add files via upload * Add files via upload * Add files via upload * Add files via upload * add textures * fix encoding * fix 2 * Automatic changelog update * Fixed Telescopic Shield Lighting (#20650) * Fixed Telescopic Shield Lighting Bug fix #20199 * no need for these at all --------- Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * Automatic changelog update * Add a special hardsuit for nukie medic (#20471) * Automatic changelog update * Carry over other mutations when doing species mutation (#20551) * Automatic changelog update * Add Spanish accent to poncho and sombrero (#20377) --------- Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: ravage <142820619+ravage123321@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: LEVELcat <68501903+LEVELcat@users.noreply.github.com> Co-authored-by: Repo <47093363+Titian3@users.noreply.github.com> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: Doru991 <75124791+Doru991@users.noreply.github.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> Co-authored-by: Skarletto <122584947+Skarletto@users.noreply.github.com> Co-authored-by: NULL882 <104377798+NULL882@users.noreply.github.com> Co-authored-by: lunarcomets <140772713+lunarcomets@users.noreply.github.com> Co-authored-by: Miro Kavaliou <miraslauk@gmail.com> Co-authored-by: Kara <lunarautomaton6@gmail.com> Co-authored-by: Kacper Urbańczyk <kacperjaroslawurbanczyk@gmail.com> Co-authored-by: TsjipTsjip <19798667+TsjipTsjip@users.noreply.github.com> Co-authored-by: daerSeebaer <61566539+daerSeebaer@users.noreply.github.com> Co-authored-by: Fluffiest Floofers <thebluewulf@gmail.com> Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Co-authored-by: Kevin Zheng <kevinz5000@gmail.com> Co-authored-by: drteaspoon420 <87363733+drteaspoon420@users.noreply.github.com> Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com> Co-authored-by: Nim <128169402+Nimfar11@users.noreply.github.com> Co-authored-by: Kacper Urbańczyk <mikrel071204@gmail.com> Co-authored-by: Tox Cruize <141375638+TexCruize@users.noreply.github.com> Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> Co-authored-by: Michael Cu <43478115+michaelcu@users.noreply.github.com>
487 lines
18 KiB
C#
487 lines
18 KiB
C#
using System.Linq;
|
|
using Content.Server.Administration;
|
|
using Content.Server.GameTicking;
|
|
using Content.Server.GameTicking.Events;
|
|
using Content.Server.Shuttles.Components;
|
|
using Content.Server.Shuttles.Events;
|
|
using Content.Server.Spawners.Components;
|
|
using Content.Server.Spawners.EntitySystems;
|
|
using Content.Server.Station.Components;
|
|
using Content.Server.Station.Systems;
|
|
using Content.Shared.Administration;
|
|
using Content.Shared.CCVar;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.Movement.Components;
|
|
using Content.Shared.Shuttles.Components;
|
|
using Robust.Shared.Spawners;
|
|
using Content.Shared.Tiles;
|
|
using Robust.Server.GameObjects;
|
|
using Robust.Shared.Collections;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Random;
|
|
using Robust.Shared.Timing;
|
|
using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent;
|
|
|
|
namespace Content.Server.Shuttles.Systems;
|
|
|
|
/// <summary>
|
|
/// If enabled spawns players on a separate arrivals station before they can transfer to the main station.
|
|
/// </summary>
|
|
public sealed class ArrivalsSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
|
[Dependency] private readonly IConsoleHost _console = default!;
|
|
[Dependency] private readonly IGameTiming _timing = default!;
|
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
[Dependency] private readonly IRobustRandom _random = default!;
|
|
[Dependency] private readonly GameTicker _ticker = default!;
|
|
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
|
[Dependency] private readonly ShuttleSystem _shuttles = default!;
|
|
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
|
|
[Dependency] private readonly StationSystem _station = default!;
|
|
|
|
/// <summary>
|
|
/// If enabled then spawns players on an alternate map so they can take a shuttle to the station.
|
|
/// </summary>
|
|
public bool Enabled { get; private set; }
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<PlayerSpawningEvent>(OnPlayerSpawn, before: new []{typeof(SpawnPointSystem)});
|
|
SubscribeLocalEvent<StationArrivalsComponent, ComponentStartup>(OnArrivalsStartup);
|
|
|
|
SubscribeLocalEvent<ArrivalsShuttleComponent, ComponentStartup>(OnShuttleStartup);
|
|
SubscribeLocalEvent<ArrivalsShuttleComponent, EntityUnpausedEvent>(OnShuttleUnpaused);
|
|
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLTagEvent>(OnShuttleTag);
|
|
|
|
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStarting);
|
|
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLStartedEvent>(OnArrivalsFTL);
|
|
|
|
// Don't invoke immediately as it will get set in the natural course of things.
|
|
Enabled = _cfgManager.GetCVar(CCVars.ArrivalsShuttles);
|
|
_cfgManager.OnValueChanged(CCVars.ArrivalsShuttles, SetArrivals);
|
|
|
|
// Command so admins can set these for funsies
|
|
_console.RegisterCommand("arrivals", ArrivalsCommand, ArrivalsCompletion);
|
|
}
|
|
|
|
private void OnShuttleTag(EntityUid uid, ArrivalsShuttleComponent component, ref FTLTagEvent args)
|
|
{
|
|
if (args.Handled)
|
|
return;
|
|
|
|
// Just saves mappers forgetting. (v2 boogaloo)
|
|
args.Handled = true;
|
|
args.Tag = "DockArrivals";
|
|
}
|
|
|
|
private CompletionResult ArrivalsCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length != 1)
|
|
return CompletionResult.Empty;
|
|
|
|
return new CompletionResult(new CompletionOption[]
|
|
{
|
|
// Enables and disable are separate comms in case you don't want to accidentally toggle it, compared to
|
|
// returns which doesn't have an immediate effect
|
|
new("enable", Loc.GetString("cmd-arrivals-enable-hint")),
|
|
new("disable", Loc.GetString("cmd-arrivals-disable-hint")),
|
|
new("returns", Loc.GetString("cmd-arrivals-returns-hint")),
|
|
new ("force", Loc.GetString("cmd-arrivals-force-hint"))
|
|
}, "Option");
|
|
}
|
|
|
|
[AdminCommand(AdminFlags.Fun)]
|
|
private void ArrivalsCommand(IConsoleShell shell, string argstr, string[] args)
|
|
{
|
|
if (args.Length != 1)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-arrivals-invalid"));
|
|
return;
|
|
}
|
|
|
|
switch (args[0])
|
|
{
|
|
case "enable":
|
|
_cfgManager.SetCVar(CCVars.ArrivalsShuttles, true);
|
|
break;
|
|
case "disable":
|
|
_cfgManager.SetCVar(CCVars.ArrivalsShuttles, false);
|
|
break;
|
|
case "returns":
|
|
var existing = _cfgManager.GetCVar(CCVars.ArrivalsReturns);
|
|
_cfgManager.SetCVar(CCVars.ArrivalsReturns, !existing);
|
|
shell.WriteLine(Loc.GetString("cmd-arrivals-returns", ("value", !existing)));
|
|
break;
|
|
case "force":
|
|
var query = AllEntityQuery<PendingClockInComponent, TransformComponent>();
|
|
var spawnPoints = EntityQuery<SpawnPointComponent, TransformComponent>().ToList();
|
|
|
|
TryGetArrivals(out var arrivalsUid);
|
|
|
|
while (query.MoveNext(out var uid, out _, out var pendingXform))
|
|
{
|
|
_random.Shuffle(spawnPoints);
|
|
|
|
foreach (var (point, xform) in spawnPoints)
|
|
{
|
|
if (point.SpawnType != SpawnPointType.LateJoin || xform.GridUid == arrivalsUid)
|
|
continue;
|
|
|
|
_transform.SetCoordinates(uid, pendingXform, xform.Coordinates);
|
|
break;
|
|
}
|
|
|
|
RemCompDeferred<AutoOrientComponent>(uid);
|
|
RemCompDeferred<PendingClockInComponent>(uid);
|
|
shell.WriteLine(Loc.GetString("cmd-arrivals-forced", ("uid", ToPrettyString(uid))));
|
|
}
|
|
break;
|
|
default:
|
|
shell.WriteError(Loc.GetString($"cmd-arrivals-invalid"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override void Shutdown()
|
|
{
|
|
base.Shutdown();
|
|
_cfgManager.UnsubValueChanged(CCVars.ArrivalsShuttles, SetArrivals);
|
|
}
|
|
|
|
private void OnArrivalsFTL(EntityUid shuttleUid, ArrivalsShuttleComponent component, ref FTLStartedEvent args)
|
|
{
|
|
if (!TryGetArrivals(out EntityUid arrivals))
|
|
return;
|
|
|
|
var arrivalsMapUid = Transform(arrivals).MapUid;
|
|
// Don't do anything here when leaving arrivals.
|
|
if (args.FromMapUid == arrivalsMapUid)
|
|
return;
|
|
|
|
// Any mob then yeet them off the shuttle.
|
|
if (!_cfgManager.GetCVar(CCVars.ArrivalsReturns) && args.FromMapUid != null)
|
|
{
|
|
var pendingEntQuery = GetEntityQuery<PendingClockInComponent>();
|
|
var arrivalsBlacklistQuery = GetEntityQuery<ArrivalsBlacklistComponent>();
|
|
var mobQuery = GetEntityQuery<MobStateComponent>();
|
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
|
DumpChildren(shuttleUid, ref args, pendingEntQuery, arrivalsBlacklistQuery, mobQuery, xformQuery);
|
|
}
|
|
|
|
var pendingQuery = AllEntityQuery<PendingClockInComponent, TransformComponent>();
|
|
|
|
// We're heading from the station back to arrivals (if leaving arrivals, would have returned above).
|
|
// Process everyone who holds a PendingClockInComponent
|
|
// Note, due to way DumpChildren works, anyone who doesn't have a PendingClockInComponent gets left in space
|
|
// and will not warp. This is intended behavior.
|
|
while (pendingQuery.MoveNext(out var pUid, out _, out var xform))
|
|
{
|
|
if (xform.GridUid == shuttleUid)
|
|
{
|
|
// Warp all players who are still on this shuttle to a spawn point. This doesn't let them return to
|
|
// arrivals. It also ensures noobs, slow players or AFK players safely leave the shuttle.
|
|
TryTeleportToMapSpawn(pUid, component.Station, xform);
|
|
}
|
|
|
|
// Players who have remained at arrives keep their warp coupon (PendingClockInComponent) for now.
|
|
if (xform.MapUid == arrivalsMapUid)
|
|
continue;
|
|
|
|
// The player has successfully left arrivals and is also not on the shuttle. Remove their warp coupon.
|
|
RemCompDeferred<PendingClockInComponent>(pUid);
|
|
RemCompDeferred<AutoOrientComponent>(pUid);
|
|
}
|
|
}
|
|
|
|
private void DumpChildren(EntityUid uid,
|
|
ref FTLStartedEvent args,
|
|
EntityQuery<PendingClockInComponent> pendingEntQuery,
|
|
EntityQuery<ArrivalsBlacklistComponent> arrivalsBlacklistQuery,
|
|
EntityQuery<MobStateComponent> mobQuery,
|
|
EntityQuery<TransformComponent> xformQuery)
|
|
{
|
|
if (pendingEntQuery.HasComponent(uid))
|
|
return;
|
|
|
|
var xform = xformQuery.GetComponent(uid);
|
|
|
|
if (mobQuery.HasComponent(uid) || arrivalsBlacklistQuery.HasComponent(uid))
|
|
{
|
|
var rotation = xform.LocalRotation;
|
|
_transform.SetCoordinates(uid, new EntityCoordinates(args.FromMapUid!.Value, args.FTLFrom.Transform(xform.LocalPosition)));
|
|
_transform.SetWorldRotation(uid, args.FromRotation + rotation);
|
|
return;
|
|
}
|
|
|
|
var children = xform.ChildEnumerator;
|
|
|
|
while (children.MoveNext(out var child))
|
|
{
|
|
DumpChildren(child.Value, ref args, pendingEntQuery, arrivalsBlacklistQuery, mobQuery, xformQuery);
|
|
}
|
|
}
|
|
|
|
private void OnPlayerSpawn(PlayerSpawningEvent ev)
|
|
{
|
|
// Only works on latejoin even if enabled.
|
|
if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound)
|
|
return;
|
|
|
|
if (!HasComp<StationArrivalsComponent>(ev.Station))
|
|
return;
|
|
|
|
TryGetArrivals(out var arrivals);
|
|
|
|
if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
|
|
{
|
|
var mapId = arrivalsXform.MapID;
|
|
|
|
var points = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
|
|
var possiblePositions = new List<EntityCoordinates>();
|
|
while ( points.MoveNext(out var uid, out var spawnPoint, out var xform))
|
|
{
|
|
if (spawnPoint.SpawnType != SpawnPointType.LateJoin || xform.MapID != mapId)
|
|
continue;
|
|
|
|
possiblePositions.Add(xform.Coordinates);
|
|
}
|
|
|
|
if (possiblePositions.Count > 0)
|
|
{
|
|
var spawnLoc = _random.Pick(possiblePositions);
|
|
ev.SpawnResult = _stationSpawning.SpawnPlayerMob(
|
|
spawnLoc,
|
|
ev.Job,
|
|
ev.HumanoidCharacterProfile,
|
|
ev.Station);
|
|
|
|
EnsureComp<PendingClockInComponent>(ev.SpawnResult.Value);
|
|
EnsureComp<AutoOrientComponent>(ev.SpawnResult.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool TryTeleportToMapSpawn(EntityUid player, EntityUid stationId, TransformComponent? transform = null)
|
|
{
|
|
if (!Resolve(player, ref transform))
|
|
return false;
|
|
|
|
var points = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
|
|
var possiblePositions = new ValueList<EntityCoordinates>(32);
|
|
|
|
// Find a spawnpoint on the same map as the player is already docked with now.
|
|
while ( points.MoveNext(out var uid, out var spawnPoint, out var xform))
|
|
{
|
|
if (spawnPoint.SpawnType == SpawnPointType.LateJoin &&
|
|
_station.GetOwningStation(uid, xform) == stationId)
|
|
{
|
|
// Add to list of possible spawn locations
|
|
possiblePositions.Add(xform.Coordinates);
|
|
}
|
|
}
|
|
|
|
if (possiblePositions.Count > 0)
|
|
{
|
|
// Move the player to a random late-join spawnpoint.
|
|
_transform.SetCoordinates(player, transform, _random.Pick(possiblePositions));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void OnShuttleStartup(EntityUid uid, ArrivalsShuttleComponent component, ComponentStartup args)
|
|
{
|
|
EnsureComp<PreventPilotComponent>(uid);
|
|
}
|
|
|
|
private void OnShuttleUnpaused(EntityUid uid, ArrivalsShuttleComponent component, ref EntityUnpausedEvent args)
|
|
{
|
|
component.NextTransfer += args.PausedTime;
|
|
}
|
|
|
|
private bool TryGetArrivals(out EntityUid uid)
|
|
{
|
|
var arrivalsQuery = EntityQueryEnumerator<ArrivalsSourceComponent>();
|
|
|
|
while (arrivalsQuery.MoveNext(out uid, out _))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public TimeSpan? NextShuttleArrival()
|
|
{
|
|
var query = EntityQueryEnumerator<ArrivalsShuttleComponent>();
|
|
var time = TimeSpan.MaxValue;
|
|
while (query.MoveNext(out var uid, out var comp))
|
|
{
|
|
if (comp.NextArrivalsTime < time)
|
|
time = comp.NextArrivalsTime;
|
|
}
|
|
|
|
var duration = _timing.CurTime;
|
|
return (time < duration) ? null : time - duration;
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
var query = EntityQueryEnumerator<ArrivalsShuttleComponent, ShuttleComponent, TransformComponent>();
|
|
var curTime = _timing.CurTime;
|
|
TryGetArrivals(out var arrivals);
|
|
|
|
// TODO: FTL fucker, if on an edge tile every N seconds check for wall or w/e
|
|
// TODO: Docking should be per-grid rather than per dock and bump off when undocking.
|
|
|
|
// TODO: Stop dispatch if emergency shuttle has arrived.
|
|
// TODO: Need server join message specifying shuttle wait time or smth.
|
|
// TODO: Need maps
|
|
// TODO: Need emergency suits on shuttle probs
|
|
// TODO: Need some kind of comp to shunt people off if they try to get on?
|
|
if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
|
|
{
|
|
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))
|
|
continue;
|
|
|
|
var tripTime = ShuttleSystem.DefaultTravelTime + ShuttleSystem.DefaultStartupTime ;
|
|
|
|
// Go back to arrivals source
|
|
if (xform.MapUid != arrivalsXform.MapUid)
|
|
{
|
|
if (arrivals.IsValid())
|
|
_shuttles.FTLTravel(uid, shuttle, arrivals, dock: true);
|
|
|
|
comp.NextArrivalsTime = _timing.CurTime + TimeSpan.FromSeconds(tripTime);
|
|
}
|
|
// Go to station
|
|
else
|
|
{
|
|
var targetGrid = _station.GetLargestGrid(data);
|
|
|
|
if (targetGrid != null)
|
|
_shuttles.FTLTravel(uid, shuttle, targetGrid.Value, dock: true);
|
|
|
|
// The ArrivalsCooldown includes the trip there, so we only need to add the time taken for
|
|
// the trip back.
|
|
comp.NextArrivalsTime = _timing.CurTime + TimeSpan.FromSeconds(
|
|
_cfgManager.GetCVar(CCVars.ArrivalsCooldown) + tripTime);
|
|
}
|
|
|
|
comp.NextTransfer += TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnRoundStarting(RoundStartingEvent ev)
|
|
{
|
|
// Setup arrivals station
|
|
if (!Enabled)
|
|
return;
|
|
|
|
SetupArrivalsStation();
|
|
}
|
|
|
|
private void SetupArrivalsStation()
|
|
{
|
|
var mapId = _mapManager.CreateMap();
|
|
|
|
if (!_loader.TryLoad(mapId, _cfgManager.GetCVar(CCVars.ArrivalsMap), out var uids))
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (var id in uids)
|
|
{
|
|
EnsureComp<ArrivalsSourceComponent>(id);
|
|
EnsureComp<ProtectedGridComponent>(id);
|
|
EnsureComp<PreventPilotComponent>(id);
|
|
}
|
|
|
|
// Handle roundstart stations.
|
|
var query = AllEntityQuery<StationArrivalsComponent>();
|
|
|
|
while (query.MoveNext(out var uid, out var comp))
|
|
{
|
|
SetupShuttle(uid, comp);
|
|
}
|
|
}
|
|
|
|
private void SetArrivals(bool obj)
|
|
{
|
|
Enabled = obj;
|
|
|
|
if (Enabled)
|
|
{
|
|
SetupArrivalsStation();
|
|
var query = AllEntityQuery<StationArrivalsComponent>();
|
|
|
|
while (query.MoveNext(out var sUid, out var comp))
|
|
{
|
|
SetupShuttle(sUid, comp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var sourceQuery = AllEntityQuery<ArrivalsSourceComponent>();
|
|
|
|
while (sourceQuery.MoveNext(out var uid, out _))
|
|
{
|
|
QueueDel(uid);
|
|
}
|
|
|
|
var shuttleQuery = AllEntityQuery<ArrivalsShuttleComponent>();
|
|
|
|
while (shuttleQuery.MoveNext(out var uid, out _))
|
|
{
|
|
QueueDel(uid);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnArrivalsStartup(EntityUid uid, StationArrivalsComponent component, ComponentStartup args)
|
|
{
|
|
if (!Enabled)
|
|
return;
|
|
|
|
// If it's a latespawn station then this will fail but that's okey
|
|
SetupShuttle(uid, component);
|
|
}
|
|
|
|
private void SetupShuttle(EntityUid uid, StationArrivalsComponent component)
|
|
{
|
|
if (!Deleted(component.Shuttle))
|
|
return;
|
|
|
|
// Spawn arrivals on a dummy map then dock it to the source.
|
|
var dummyMap = _mapManager.CreateMap();
|
|
|
|
if (TryGetArrivals(out var arrivals) &&
|
|
_loader.TryLoad(dummyMap, component.ShuttlePath.ToString(), out var shuttleUids))
|
|
{
|
|
component.Shuttle = shuttleUids[0];
|
|
var shuttleComp = Comp<ShuttleComponent>(component.Shuttle);
|
|
var arrivalsComp = EnsureComp<ArrivalsShuttleComponent>(component.Shuttle);
|
|
arrivalsComp.Station = uid;
|
|
EnsureComp<ProtectedGridComponent>(uid);
|
|
_shuttles.FTLTravel(component.Shuttle, shuttleComp, arrivals, hyperspaceTime: 10f, dock: true);
|
|
arrivalsComp.NextTransfer = _timing.CurTime + TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.ArrivalsCooldown));
|
|
}
|
|
|
|
// Don't start the arrivals shuttle immediately docked so power has a time to stabilise?
|
|
var timer = AddComp<TimedDespawnComponent>(_mapManager.GetMapEntityId(dummyMap));
|
|
timer.Lifetime = 15f;
|
|
}
|
|
}
|