diff --git a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs index d0c4c48a9fd..f79635959cd 100644 --- a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs @@ -8,6 +8,7 @@ using Content.Server.Mind; using Content.Server.Pinpointer; using Content.Server.Roles; +using Content.Server.RoundEnd; using Content.Server.Shuttles.Components; using Content.Server.Station.Components; using Content.Shared.CCVar; @@ -50,6 +51,7 @@ public async Task TryStopNukeOpsFromConstantlyFailing() var roleSys = server.System(); var invSys = server.System(); var factionSys = server.System(); + var roundEndSys = server.System(); server.CfgMan.SetCVar(CCVars.GridFill, true); @@ -64,11 +66,11 @@ public async Task TryStopNukeOpsFromConstantlyFailing() // Opt into the nukies role. await pair.SetAntagPreference("NukeopsCommander", true); - await pair.SetAntagPreference( "NukeopsMedic", true, dummies[1].UserId); + await pair.SetAntagPreference("NukeopsMedic", true, dummies[1].UserId); // Initially, the players have no attached entities Assert.That(pair.Player?.AttachedEntity, Is.Null); - Assert.That(dummies.All(x => x.AttachedEntity == null)); + Assert.That(dummies.All(x => x.AttachedEntity == null)); // There are no grids or maps Assert.That(entMan.Count(), Is.Zero); @@ -151,7 +153,8 @@ void CheckDummy(int i) } // The game rule exists, and all the stations/shuttles/maps are properly initialized - var rule = entMan.AllComponents().Single().Component; + var rule = entMan.AllComponents().Single(); + var ruleComp = rule.Component; var gridsRule = entMan.AllComponents().Single().Component; foreach (var grid in gridsRule.MapGrids) { @@ -159,12 +162,14 @@ void CheckDummy(int i) Assert.That(entMan.HasComponent(grid)); Assert.That(entMan.HasComponent(grid)); } - Assert.That(entMan.EntityExists(rule.TargetStation)); + Assert.That(entMan.EntityExists(ruleComp.TargetStation)); - Assert.That(entMan.HasComponent(rule.TargetStation)); + Assert.That(entMan.HasComponent(ruleComp.TargetStation)); - var nukieShuttlEnt = entMan.AllComponents().FirstOrDefault().Uid; + var nukieShuttle = entMan.AllComponents().Single(); + var nukieShuttlEnt = nukieShuttle.Uid; Assert.That(entMan.EntityExists(nukieShuttlEnt)); + Assert.That(nukieShuttle.Component.AssociatedRule, Is.EqualTo(rule.Uid)); EntityUid? nukieStationEnt = null; foreach (var grid in gridsRule.MapGrids) @@ -180,12 +185,12 @@ void CheckDummy(int i) var nukieStation = entMan.GetComponent(nukieStationEnt!.Value); Assert.That(entMan.EntityExists(nukieStation.Station)); - Assert.That(nukieStation.Station, Is.Not.EqualTo(rule.TargetStation)); + Assert.That(nukieStation.Station, Is.Not.EqualTo(ruleComp.TargetStation)); Assert.That(server.MapMan.MapExists(gridsRule.Map)); var nukieMap = mapSys.GetMap(gridsRule.Map!.Value); - var targetStation = entMan.GetComponent(rule.TargetStation!.Value); + var targetStation = entMan.GetComponent(ruleComp.TargetStation!.Value); var targetGrid = targetStation.Grids.First(); var targetMap = entMan.GetComponent(targetGrid).MapUid!.Value; Assert.That(targetMap, Is.Not.EqualTo(nukieMap)); @@ -207,7 +212,7 @@ void CheckDummy(int i) Assert.That(LifeStage(targetMap), Is.GreaterThan(EntityLifeStage.Initialized)); Assert.That(LifeStage(nukieStationEnt.Value), Is.GreaterThan(EntityLifeStage.Initialized)); Assert.That(LifeStage(nukieShuttlEnt), Is.GreaterThan(EntityLifeStage.Initialized)); - Assert.That(LifeStage(rule.TargetStation), Is.GreaterThan(EntityLifeStage.Initialized)); + Assert.That(LifeStage(ruleComp.TargetStation), Is.GreaterThan(EntityLifeStage.Initialized)); // Make sure the player has hands. We've had fucking disarmed nukies before. Assert.That(entMan.HasComponent(player)); @@ -223,10 +228,10 @@ void CheckDummy(int i) } Assert.That(total, Is.GreaterThan(3)); - // Finally lets check the nukie commander passed basic training and figured out how to breathe. + // Check the nukie commander passed basic training and figured out how to breathe. var totalSeconds = 30; var totalTicks = (int) Math.Ceiling(totalSeconds / server.Timing.TickPeriod.TotalSeconds); - int increment = 5; + var increment = 5; var resp = entMan.GetComponent(player); var damage = entMan.GetComponent(player); for (var tick = 0; tick < totalTicks; tick += increment) @@ -236,7 +241,24 @@ void CheckDummy(int i) Assert.That(damage.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); } - ticker.SetGamePreset((GamePresetPrototype?)null); + // Check that the round does not end prematurely when agents are deleted in the outpost + var nukies = dummyEnts.Where(entMan.HasComponent).Append(player).ToArray(); + await server.WaitAssertion(() => + { + for (var i = 0; i < nukies.Length - 1; i++) + { + entMan.DeleteEntity(nukies[i]); + Assert.That(roundEndSys.IsRoundEndRequested, Is.False, + $"The round ended, but {nukies.Length - i - 1} nukies are still alive!"); + } + // Delete the last nukie and make sure the round ends. + entMan.DeleteEntity(nukies[^1]); + + Assert.That(roundEndSys.IsRoundEndRequested, + "All nukies were deleted, but the round didn't end!"); + }); + + ticker.SetGamePreset((GamePresetPrototype?) null); await pair.CleanReturnAsync(); } } diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index bcf02481fe3..028d876531b 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -57,13 +57,12 @@ public override void Initialize() SubscribeLocalEvent(OnMobStateChanged); SubscribeLocalEvent(OnOperativeZombified); - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnShuttleFTLAttempt); SubscribeLocalEvent(OnWarDeclared); SubscribeLocalEvent(OnShuttleCallAttempt); SubscribeLocalEvent(OnAfterAntagEntSelected); + SubscribeLocalEvent(OnRuleLoadedGrids); } protected override void Started(EntityUid uid, NukeopsRuleComponent component, GameRuleComponent gameRule, @@ -256,17 +255,18 @@ private void OnOperativeZombified(EntityUid uid, NukeOperativeComponent componen RemCompDeferred(uid, component); } - private void OnMapInit(Entity ent, ref MapInitEvent args) + private void OnRuleLoadedGrids(Entity ent, ref RuleLoadedGridsEvent args) { - var map = Transform(ent).MapID; - - var rules = EntityQueryEnumerator(); - while (rules.MoveNext(out var uid, out _, out var grids)) + // Check each nukie shuttle + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var shuttle)) { - if (map != grids.Map) - continue; - ent.Comp.AssociatedRule = uid; - break; + // Check if the shuttle's mapID is the one that just got loaded for this rule + if (Transform(uid).MapID == args.Map) + { + shuttle.AssociatedRule = ent; + break; + } } } @@ -376,7 +376,7 @@ private void DistributeExtraTc(Entity nukieRule) if (Transform(uid).MapID != Transform(outpost).MapID) // Will receive bonus TC only on their start outpost continue; - _store.TryAddCurrency(new () { { TelecrystalCurrencyPrototype, nukieRule.Comp.WarTcAmountPerNukie } }, uid, component); + _store.TryAddCurrency(new() { { TelecrystalCurrencyPrototype, nukieRule.Comp.WarTcAmountPerNukie } }, uid, component); var msg = Loc.GetString("store-currency-war-boost-given", ("target", uid)); _popupSystem.PopupEntity(msg, uid); diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 22285bf3936..e0d6bbb1945 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: TokenStyle - changes: - - message: Lockers cannot be deconstructed with a screwdriver when locked now. - type: Fix - id: 6356 - time: '2024-04-14T22:26:47.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26961 - author: pissdemon changes: - message: Catwalks over lava are slightly less likely to catch you on fire again. @@ -3820,3 +3813,11 @@ id: 6855 time: '2024-07-01T21:14:38.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29476 +- author: Tayrtahn + changes: + - message: Fixed NukeOps ending prematurely in some situations where operatives + were still alive. + type: Fix + id: 6856 + time: '2024-07-01T22:23:36.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29642