* sync * sync * no more squiggles.. * last build error * updated maps for testing * some issue with receiving arrivals setup * networkpayload refactor. TODO: accurate timings * timings accurate. TODO: backport old bugfix * all set? * cleaned up source. TODO: diff arrivals methods * cleaned component. TODO: escape polish, docs * first documentation pass * escape timers work * no more magic numbers * removed dead code leads * sync sync * Automatic changelog update * shuttle timer groundwork no more squiggles.. last build error updated maps for testing some issue with receiving arrivals setup networkpayload refactor. TODO: accurate timings timings accurate. TODO: backport old bugfix all set? cleaned up source. TODO: diff arrivals methods cleaned component. TODO: escape polish, docs first documentation pass escape timers work no more magic numbers * BBQ rib sandwich (#21180) * Fix missing toggle fullscreen loc string (#21264) * Cave Decoration pack (#21265) * add chromite chasm * add desert chasm * snow chasm * finish * fixes and tweaks (#21172) * Automatic changelog update * Fix ItemPlacer (#21160) This is going to lead to many entities being ticked unnecessarily and performance problems. * headrev spawn music (#21119) * headrev spawn music * :trollface: * skill issue * double skill issue * :trollface: * :trollface: * :trollface: * Automatic changelog update * Techfab resprite + department fab sprites (#21136) * Fix popup messages appearing when someone tries to open a door without a tool. (#21099) * The fixTM * typo fix * addressing review * Show "departed and moved on" for when a ghost role is taken (#21092) * fix ghost role not counting for "departed and moved on" * I don't think that bit was needed so away it goes * hopefully finish the upsream merge * Automatic changelog update * Implant whitelist/blacklisting (#20678) * add whitelist and blacklist to implant and implanter components * handle whitelist and blacklist in systems * move hardcoded whitelist/blacklist to base implanter + add admeme implanter * give implants sensible whitelists * cleaner CheckTarget and fix * remove unused imports * network lists --------- Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * Ion storm event (#20277) * ion storm event prototype + locale * add lawsets * use lawsets, make borgs ion storm targets * ion storm rule and ion storm target * lawset prototype * use lawsets * update silicon law system to use lawsets and support ion storm event * new toys * fix * more fix * fixy * ion storm admin logging * assigning laws makes borg provide its own laws, other stuff * 1h reoccurence * 50% chance * better call saul * emagLaws is required * add announcment audio * fixy * family friendly gaming * fixy * address reviews * fixy * more fixy and no erp * pro --------- Co-authored-by: deltanedas <@deltanedas:kde.org> * Automatic changelog update * A return to foam (foam rework) (#20831) * Automatic changelog update * ERT Loadout overhaul + Real deathsquad mobs + ERT fixes (#21230) * "assist with medical efforts" * CentComm official description change * give cburn ert mask * Ert medic hardsuit uses blood-red medic values * description changes, they all used to use the blood-red description * ert engineer hardsuit uses cburn values, good for handling all possible engineering problems. * janitor hardsuit uses cburn values for extreme messes, otherwise we'd send the non eva variant. * spawn suffix changes * shorten suffix * drop armor from ert jumpsuits * drop armor from DS jumpsuit * add more armor to death squad to make up for removed armor in the uniform. * give sec gas masks armor, give syndicate gas masks armor. ERT gas mask uses syndicate mask values * add nanotrasen * removed duplicate * give centcom IDs their hud icon * replace all ert bulletproof armor with basic universal armor * replace all oxygen tanks with air tanks; species is random. * remove gun and meds from ert engineer kit * give ert engineer materials * remove weapons and meds from janitor ert * give ert janitor light replacer * remove ert sec pulse weapons, admins will assign loadout. Either the lecter or enforcer, probably. * Give ert sec the security pistol kit * typo * give eva ert sec pistol * give eva janitor ert gas mask * give jani purple gloves * medical gloves for medical ert * replicate security loadout to leader * quick ert lecter spawns for lazy admins * better suffixes to find them easier * add cburn to ertspawn * Replace "Spawn" with "role" * Add death squad. Give ert engineer gas analyzer. * death squad using wrong equipment * typo * missing ghost roles on lecter loadouts * add freedom implanter to deathsquad * deathsquad ghost role text * Operative sounds better * give Ds flashbang box (why isn't it entirely filled?) * fix typo. add energy shield to DS * fix typos * all centcomm roles are now mindshielded. These cannot be removed. * Rider didnt include some of the changes ? * give zipties instead of cuffs for mass arrests! * upgrade ERT survival boxes to extended capacity * give cburn extended oxygen too * Automatic changelog update * Restore Leviathan's 80 pop cap (#21281) * Un-revert IPlayerManager refactor (#21244) * Update engine to v172.0.0 (#21288) * Bandaid tests (#21292) * rename the rocks (#21275) * Make crystals noRot (#21279) IDK might be better. Ideally the anchoring would be offset 0-0 but this is the world we live in atm. * Fix nukies sound not played (#21268) * Play sound and sending greeting message works for nukies now!!!!! * oops * silly change * Automatic changelog update * Fix hijack objective (#21241) * Fix hijack * Max difficulty * Remove GridModifiedEvent (#21291) * Update submodule to 173.0.0 (#21296) * Fix namespace error (#21298) * Update yaml sequence option in editorconfig (#21297) * Fix namespace (#21299) * fix cburn bag issue, make new bag entity for them and filled bag entity (#21295) * Health analyzer UI improve (#17280) * Automatic changelog update * User accessible playtime (#21242) Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> * Automatic changelog update * Moves cloning comp & cloning event to shared (#21253) * Generalizes solution overflow & slightly increases space lube yield (#21094) * generalize SolutionSpikeOverflowEvent * let reactions overflow * spacelube: 3 -> 5 * restore TryMixAndOverflow threshold cap * Automatic changelog update * Move ActorComponent to shared (#21293) * Update engine to v174.0.0 (#21311) * Fix planet command help message (#21312) * Wearable bee plush (#20623) * add * fix * temporary change, needs fixing * mayb fix * actually fix FR * yes * Automatic changelog update * remove pulse rifle from ert medic (#21310) * Content audio (#20862) * Automatic changelog update * Update submodule to 175.0.0 (#21318) * Revert "Update submodule to 175.0.0 (#21318)" (#21319) * Atomic bomb add uranium (#21143) * fix: Incendiary bullets no longer deal cold, acid, or shock damage that ignores all armor. * Atomic bomb * Action bugfixes (#21321) * Disable OOC during round (#21323) * Fix PDA notifications when creating a news entry using the Mass-Media console. (#21320) * Automatic changelog update * Update belt.yml (#21317) changes the chief engineer's belt to remove the lv wires (they take up a lot of space and are easy to get anyways) in exchange for a holofan, a t-ray, and a gas analyzer (first time coding ever this might have to be edited) * New foam sprites (edge sprites) (#21308) * New foam sprites (icon smoothing) * changed to edge sprites for foam * fix * edges for metal foams * fix * Fix bola stam damage, bring back old construction requirements (#21340) * Automatic changelog update * Added thermal insulation to flannel jackets (#21273) * Automatic changelog update * Space Asshole Gear (#21243) * Add Space Asshole Coat * Add sledgehammer * Adjust sledgehammer damage values * Add copyright string to sledgehammer * Fix broken slot highlight in midnight theme. (#21331) * removed dead code leads removed redundant ensurecomps * textscreen documentation * remove redundant ensurecomps * Add hint for the examine trigger effect (#21166) * examine locale * examine trigger desc Automatic changelog update cornmeal is actually obtainable now (#21162) * do the thing * lets find out * Update Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> --------- Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Automatic changelog update Healing skeletons by pouring milk over them (and clean pie remains off their skulls) (#21231) * mvp done - skellies can heal by spillink regular milk on themselves and clean themselves off creaming with water * added other types of healing milk, also made a separate reaction to oat milk - it has almost no calcium in it * fixed indent error, made a dumb mistake Automatic changelog update Fix anomaly locators frantically beeping when entering detection range. (#21178) * reset beep timer when out of range * prevent deficit from impacting beep timing Automatic changelog update Remove "mk --> mmm, okay" and "u --> you" to chatsan anti slang (#21177) Automatic changelog update Adds AttemptEntity(Uns|S)tickEvent. (#20728) * try-stick * convert spider charge to attempt-stick-events Change ListContainer to send null when selected is removed from the data (#20595) fix feeding unremovable items (#21234) Automatic changelog update Power switchable refactor (#20419) Co-authored-by: deltanedas <@deltanedas:kde.org> simple space mobs cant be flashed (#20784) Co-authored-by: deltanedas <@deltanedas:kde.org> give roundstart borgs names (#20081) Co-authored-by: deltanedas <@deltanedas:kde.org> fix searching on vending machines (#21233) syndicate snack box (#21024) Co-authored-by: deltanedas <@deltanedas:kde.org> Fix DockingControl (#21238) Shadow Dimension visual pack (#21237) Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Potato battery update + potato AI (#21142) Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> [TEST MERGE] Slot-based Storage (#21212) Automatic changelog update Some mild item size balancing + fixes (#21250) Automatic changelog update Revert "Storage TEST MERGE" (#21258) Add missing changelog for storage refactor revert (#21259) * sync sync * Automatic changelog update shuttle timer groundwork no more squiggles.. last build error updated maps for testing some issue with receiving arrivals setup networkpayload refactor. TODO: accurate timings timings accurate. TODO: backport old bugfix all set? cleaned up source. TODO: diff arrivals methods cleaned component. TODO: escape polish, docs first documentation pass escape timers work no more magic numbers BBQ rib sandwich (#21180) Fix missing toggle fullscreen loc string (#21264) Cave Decoration pack (#21265) * add chromite chasm * add desert chasm * snow chasm * finish fixes and tweaks (#21172) Automatic changelog update Fix ItemPlacer (#21160) This is going to lead to many entities being ticked unnecessarily and performance problems. headrev spawn music (#21119) * headrev spawn music * :trollface: * skill issue * double skill issue * :trollface: * :trollface: * :trollface: Automatic changelog update Techfab resprite + department fab sprites (#21136) Fix popup messages appearing when someone tries to open a door without a tool. (#21099) * The fixTM * typo fix * addressing review Show "departed and moved on" for when a ghost role is taken (#21092) * fix ghost role not counting for "departed and moved on" * I don't think that bit was needed so away it goes * hopefully finish the upsream merge Automatic changelog update Implant whitelist/blacklisting (#20678) * add whitelist and blacklist to implant and implanter components * handle whitelist and blacklist in systems * move hardcoded whitelist/blacklist to base implanter + add admeme implanter * give implants sensible whitelists * cleaner CheckTarget and fix * remove unused imports * network lists --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Automatic changelog update Ion storm event (#20277) * ion storm event prototype + locale * add lawsets * use lawsets, make borgs ion storm targets * ion storm rule and ion storm target * lawset prototype * use lawsets * update silicon law system to use lawsets and support ion storm event * new toys * fix * more fix * fixy * ion storm admin logging * assigning laws makes borg provide its own laws, other stuff * 1h reoccurence * 50% chance * better call saul * emagLaws is required * add announcment audio * fixy * family friendly gaming * fixy * address reviews * fixy * more fixy and no erp * pro --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Automatic changelog update A return to foam (foam rework) (#20831) Automatic changelog update ERT Loadout overhaul + Real deathsquad mobs + ERT fixes (#21230) * "assist with medical efforts" * CentComm official description change * give cburn ert mask * Ert medic hardsuit uses blood-red medic values * description changes, they all used to use the blood-red description * ert engineer hardsuit uses cburn values, good for handling all possible engineering problems. * janitor hardsuit uses cburn values for extreme messes, otherwise we'd send the non eva variant. * spawn suffix changes * shorten suffix * drop armor from ert jumpsuits * drop armor from DS jumpsuit * add more armor to death squad to make up for removed armor in the uniform. * give sec gas masks armor, give syndicate gas masks armor. ERT gas mask uses syndicate mask values * add nanotrasen * removed duplicate * give centcom IDs their hud icon * replace all ert bulletproof armor with basic universal armor * replace all oxygen tanks with air tanks; species is random. * remove gun and meds from ert engineer kit * give ert engineer materials * remove weapons and meds from janitor ert * give ert janitor light replacer * remove ert sec pulse weapons, admins will assign loadout. Either the lecter or enforcer, probably. * Give ert sec the security pistol kit * typo * give eva ert sec pistol * give eva janitor ert gas mask * give jani purple gloves * medical gloves for medical ert * replicate security loadout to leader * quick ert lecter spawns for lazy admins * better suffixes to find them easier * add cburn to ertspawn * Replace "Spawn" with "role" * Add death squad. Give ert engineer gas analyzer. * death squad using wrong equipment * typo * missing ghost roles on lecter loadouts * add freedom implanter to deathsquad * deathsquad ghost role text * Operative sounds better * give Ds flashbang box (why isn't it entirely filled?) * fix typo. add energy shield to DS * fix typos * all centcomm roles are now mindshielded. These cannot be removed. * Rider didnt include some of the changes ? * give zipties instead of cuffs for mass arrests! * upgrade ERT survival boxes to extended capacity * give cburn extended oxygen too Automatic changelog update Restore Leviathan's 80 pop cap (#21281) Un-revert IPlayerManager refactor (#21244) Update engine to v172.0.0 (#21288) Bandaid tests (#21292) rename the rocks (#21275) Make crystals noRot (#21279) IDK might be better. Ideally the anchoring would be offset 0-0 but this is the world we live in atm. Fix nukies sound not played (#21268) * Play sound and sending greeting message works for nukies now!!!!! * oops * silly change Automatic changelog update Fix hijack objective (#21241) * Fix hijack * Max difficulty Remove GridModifiedEvent (#21291) Update submodule to 173.0.0 (#21296) Fix namespace error (#21298) Update yaml sequence option in editorconfig (#21297) Fix namespace (#21299) fix cburn bag issue, make new bag entity for them and filled bag entity (#21295) Health analyzer UI improve (#17280) Automatic changelog update User accessible playtime (#21242) Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Automatic changelog update Moves cloning comp & cloning event to shared (#21253) Generalizes solution overflow & slightly increases space lube yield (#21094) * generalize SolutionSpikeOverflowEvent * let reactions overflow * spacelube: 3 -> 5 * restore TryMixAndOverflow threshold cap Automatic changelog update Move ActorComponent to shared (#21293) Update engine to v174.0.0 (#21311) Fix planet command help message (#21312) Wearable bee plush (#20623) * add * fix * temporary change, needs fixing * mayb fix * actually fix FR * yes Automatic changelog update remove pulse rifle from ert medic (#21310) Content audio (#20862) Automatic changelog update Update submodule to 175.0.0 (#21318) Revert "Update submodule to 175.0.0 (#21318)" (#21319) Atomic bomb add uranium (#21143) * fix: Incendiary bullets no longer deal cold, acid, or shock damage that ignores all armor. * Atomic bomb Action bugfixes (#21321) Disable OOC during round (#21323) Fix PDA notifications when creating a news entry using the Mass-Media console. (#21320) Automatic changelog update Update belt.yml (#21317) changes the chief engineer's belt to remove the lv wires (they take up a lot of space and are easy to get anyways) in exchange for a holofan, a t-ray, and a gas analyzer (first time coding ever this might have to be edited) New foam sprites (edge sprites) (#21308) * New foam sprites (icon smoothing) * changed to edge sprites for foam * fix * edges for metal foams * fix Fix bola stam damage, bring back old construction requirements (#21340) Automatic changelog update Added thermal insulation to flannel jackets (#21273) Automatic changelog update Space Asshole Gear (#21243) * Add Space Asshole Coat * Add sledgehammer * Adjust sledgehammer damage values * Add copyright string to sledgehammer Fix broken slot highlight in midnight theme. (#21331) * removed old ensurecomps, stubs removed dead code leads removed redundant ensurecomps sync sync no more squiggles.. last build error updated maps for testing some issue with receiving arrivals setup networkpayload refactor. TODO: accurate timings timings accurate. TODO: backport old bugfix all set? cleaned up source. TODO: diff arrivals methods cleaned component. TODO: escape polish, docs first documentation pass escape timers work no more magic numbers removed dead code leads textscreen documentation remove redundant ensurecomps * sync * new shuttletimer sprite/offset * sync * sync * sync * sync * sync * builds * sync * sync * sync * offset adjustments * timer pattern implemented * arrivals timer system seems to work * sync * sync * sync * sync * sync * sync * sync * sync * sync * sync * implements shuttletimers * centcomm timers * set color to tg 1097fb * textscreen -> signalscreen, shuttletimer -> screen * move screens out of timer.yml * pruned unused properties/imports * license+copyright for screen.rsi * forgor change signaltimer event handler doc * roundstart arrivals ftl logic * block signaltimer screentext updates during timing * merged robust 185 * centcomm carpet uid collision PLEASE MERGE MY PR * remove arrivalssystem entitymanager dependency * refactored magic strings, added roundend getters * specific vgstation sprite commit licensing ---------
581 lines
22 KiB
C#
581 lines
22 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Server.Administration;
|
|
using Content.Server.GameTicking;
|
|
using Content.Server.GameTicking.Events;
|
|
using Content.Server.Parallax;
|
|
using Content.Server.DeviceNetwork;
|
|
using Content.Server.DeviceNetwork.Components;
|
|
using Content.Server.DeviceNetwork.Systems;
|
|
using Content.Server.Salvage;
|
|
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.Parallax.Biomes;
|
|
using Content.Shared.Salvage;
|
|
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.Prototypes;
|
|
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 IPrototypeManager _protoManager = default!;
|
|
[Dependency] private readonly IRobustRandom _random = default!;
|
|
[Dependency] private readonly BiomeSystem _biomes = default!;
|
|
[Dependency] private readonly GameTicker _ticker = default!;
|
|
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
|
[Dependency] private readonly RestrictedRangeSystem _restricted = 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; }
|
|
|
|
/// <summary>
|
|
/// The first arrival is a little early, to save everyone 10s
|
|
/// </summary>
|
|
private const float RoundStartFTLDuration = 10f;
|
|
|
|
private readonly List<ProtoId<BiomeTemplatePrototype>> _arrivalsBiomeOptions = new()
|
|
{
|
|
"Grasslands",
|
|
"LowDesert",
|
|
"Snow",
|
|
};
|
|
|
|
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);
|
|
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLCompletedEvent>(OnArrivalsDocked);
|
|
|
|
// 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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// First sends shuttle timer data, then kicks people off the shuttle if it isn't leaving the arrivals terminal
|
|
/// </summary>
|
|
private void OnArrivalsFTL(EntityUid shuttleUid, ArrivalsShuttleComponent component, ref FTLStartedEvent args)
|
|
{
|
|
if (!TryGetArrivals(out EntityUid arrivals))
|
|
return;
|
|
|
|
if (TryComp<DeviceNetworkComponent>(shuttleUid, out var netComp))
|
|
{
|
|
TryComp<FTLComponent>(shuttleUid, out var ftlComp);
|
|
var ftlTime = TimeSpan.FromSeconds(ftlComp?.TravelTime ?? ShuttleSystem.DefaultTravelTime);
|
|
|
|
var payload = new NetworkPayload
|
|
{
|
|
[ShuttleTimerMasks.ShuttleMap] = shuttleUid,
|
|
[ShuttleTimerMasks.ShuttleTime] = ftlTime
|
|
};
|
|
|
|
// unfortunate levels of spaghetti due to roundstart arrivals ftl behavior
|
|
EntityUid? sourceMap;
|
|
var arrivalsDelay = _cfgManager.GetCVar(CCVars.ArrivalsCooldown);
|
|
|
|
if (component.FirstRun)
|
|
{
|
|
var station = _station.GetLargestGrid(Comp<StationDataComponent>(component.Station));
|
|
sourceMap = station == null ? null : Transform(station.Value)?.MapUid;
|
|
arrivalsDelay += RoundStartFTLDuration;
|
|
component.FirstRun = false;
|
|
payload.Add(ShuttleTimerMasks.DestMap, Transform(args.TargetCoordinates.EntityId).MapUid);
|
|
payload.Add(ShuttleTimerMasks.DestTime, ftlTime);
|
|
}
|
|
else
|
|
sourceMap = args.FromMapUid;
|
|
|
|
payload.Add(ShuttleTimerMasks.SourceMap, sourceMap);
|
|
payload.Add(ShuttleTimerMasks.SourceTime, ftlTime + TimeSpan.FromSeconds(arrivalsDelay));
|
|
|
|
_deviceNetworkSystem.QueuePacket(shuttleUid, null, payload, netComp.TransmitFrequency);
|
|
}
|
|
|
|
// Don't do anything here when leaving arrivals.
|
|
var arrivalsMapUid = Transform(arrivals).MapUid;
|
|
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 arrivals 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 OnArrivalsDocked(EntityUid uid, ArrivalsShuttleComponent component, ref FTLCompletedEvent args)
|
|
{
|
|
TimeSpan dockTime = component.NextTransfer - _timing.CurTime + TimeSpan.FromSeconds(ShuttleSystem.DefaultStartupTime);
|
|
|
|
if (TryComp<DeviceNetworkComponent>(uid, out var netComp))
|
|
{
|
|
var payload = new NetworkPayload
|
|
{
|
|
[ShuttleTimerMasks.ShuttleMap] = uid,
|
|
[ShuttleTimerMasks.ShuttleTime] = dockTime,
|
|
[ShuttleTimerMasks.SourceMap] = args.MapUid,
|
|
[ShuttleTimerMasks.SourceTime] = dockTime,
|
|
[ShuttleTimerMasks.Docked] = true
|
|
};
|
|
_deviceNetworkSystem.QueuePacket(uid, null, payload, netComp.TransmitFrequency);
|
|
}
|
|
}
|
|
|
|
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, 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 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();
|
|
var mapUid = _mapManager.GetMapEntityId(mapId);
|
|
_mapManager.AddUninitializedMap(mapId);
|
|
|
|
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);
|
|
}
|
|
|
|
// Setup planet arrivals if relevant
|
|
if (_cfgManager.GetCVar(CCVars.ArrivalsPlanet))
|
|
{
|
|
var template = _random.Pick(_arrivalsBiomeOptions);
|
|
_biomes.EnsurePlanet(mapUid, _protoManager.Index(template));
|
|
var restricted = new RestrictedRangeComponent
|
|
{
|
|
Range = 32f
|
|
};
|
|
AddComp(mapUid, restricted);
|
|
}
|
|
|
|
_mapManager.DoMapInitialize(mapId);
|
|
|
|
// 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: RoundStartFTLDuration, 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;
|
|
}
|
|
}
|