From 7bb3dd09c7463c16c112c90fcd0b11820fd081ab Mon Sep 17 00:00:00 2001 From: csqrb <56765288+CaptainSqrBeard@users.noreply.github.com> Date: Mon, 25 Sep 2023 02:16:33 +0600 Subject: [PATCH] After killing all nuclear operatives, shuttle will be called instead of instant round end (#19850) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * ☢️🕵️💀🚫📄🚀 * 🚀📢❌📥📜 * 🔧🐛📢🚹🚉➡👑👑 * 😪 * 🧱 * 🚀🛬🕔➡️🕙 * ☢️⚙️🔵🔚🔨➡️🔵🔚⚙️ these commit names are literally evil who tf does this --- .../Rules/Components/NukeopsRuleComponent.cs | 31 ++++++- .../GameTicking/Rules/NukeopsRuleSystem.cs | 15 ++-- Content.Server/RoundEnd/RoundEndSystem.cs | 82 +++++++++++++------ .../StationEvents/Events/LoneOpsSpawnRule.cs | 3 +- Resources/Locale/en-US/nukeops/nuke-ops.ftl | 2 + 5 files changed, 100 insertions(+), 33 deletions(-) create mode 100644 Resources/Locale/en-US/nukeops/nuke-ops.ftl diff --git a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs index 760b684e1a..8ddfd9c14b 100644 --- a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs @@ -1,4 +1,5 @@ using Content.Server.NPC.Components; +using Content.Server.RoundEnd; using Content.Server.StationEvents.Events; using Content.Shared.Dataset; using Content.Shared.Roles; @@ -31,10 +32,34 @@ public sealed partial class NukeopsRuleComponent : Component public int MaxOperatives = 5; /// - /// Whether or not all of the nuclear operatives dying will end the round. Used by LoneOpsSpawn event. + /// What will happen if all of the nuclear operatives will die. Used by LoneOpsSpawn event. /// - [DataField("endsRound")] - public bool EndsRound = true; + [DataField("roundEndBehavior")] + public RoundEndBehavior RoundEndBehavior = RoundEndBehavior.ShuttleCall; + + /// + /// Text for shuttle call if RoundEndBehavior is ShuttleCall. + /// + [DataField("roundEndTextSender")] + public string RoundEndTextSender = "comms-console-announcement-title-centcom"; + + /// + /// Text for shuttle call if RoundEndBehavior is ShuttleCall. + /// + [DataField("roundEndTextShuttleCall")] + public string RoundEndTextShuttleCall = "nuke-ops-no-more-threat-announcement-shuttle-call"; + + /// + /// Text for announcement if RoundEndBehavior is ShuttleCall. Used if shuttle is already called + /// + [DataField("roundEndTextAnnouncement")] + public string RoundEndTextAnnouncement = "nuke-ops-no-more-threat-announcement"; + + /// + /// Time to emergency shuttle to arrive if RoundEndBehavior is ShuttleCall. + /// + [DataField("evacShuttleTime")] + public TimeSpan EvacShuttleTime = TimeSpan.FromMinutes(10); /// /// Whether or not to spawn the nuclear operative outpost. Used by LoneOpsSpawn event. diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index d94c9dae48..df9fbcc130 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -487,14 +487,14 @@ public sealed class NukeopsRuleSystem : GameRuleSystem } } - private void SetWinType(EntityUid uid, WinType type, NukeopsRuleComponent? component = null) + private void SetWinType(EntityUid uid, WinType type, NukeopsRuleComponent? component = null, bool endRound = true) { if (!Resolve(uid, ref component)) return; component.WinType = type; - if (type == WinType.CrewMajor || type == WinType.OpsMajor) + if (endRound && (type == WinType.CrewMajor || type == WinType.OpsMajor)) _roundEndSystem.EndRound(); } @@ -506,7 +506,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem if (!GameTicker.IsGameRuleAdded(uid, gameRule)) continue; - if (!nukeops.EndsRound || nukeops.WinType == WinType.CrewMajor || nukeops.WinType == WinType.OpsMajor) + if (nukeops.RoundEndBehavior == RoundEndBehavior.Nothing || nukeops.WinType == WinType.CrewMajor || nukeops.WinType == WinType.OpsMajor) continue; // If there are any nuclear bombs that are active, immediately return. We're not over yet. @@ -559,7 +559,12 @@ public sealed class NukeopsRuleSystem : GameRuleSystem ? WinCondition.NukiesAbandoned : WinCondition.AllNukiesDead); - SetWinType(uid, WinType.CrewMajor, nukeops); + SetWinType(uid, WinType.CrewMajor, nukeops, false); + _roundEndSystem.DoRoundEndBehavior( + nukeops.RoundEndBehavior, nukeops.EvacShuttleTime, nukeops.RoundEndTextSender, nukeops.RoundEndTextShuttleCall, nukeops.RoundEndTextAnnouncement); + + // prevent it called multiple times + nukeops.RoundEndBehavior = RoundEndBehavior.Nothing; } } @@ -763,7 +768,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem foreach (var (nukeops, gameRule) in EntityQuery()) { - if (nukeops.OperativeMindPendingData.TryGetValue(uid, out var role) || !nukeops.SpawnOutpost || !nukeops.EndsRound) + if (nukeops.OperativeMindPendingData.TryGetValue(uid, out var role) || !nukeops.SpawnOutpost || nukeops.RoundEndBehavior == RoundEndBehavior.Nothing) { role ??= nukeops.OperativeRoleProto; _roles.MindAddRole(mindId, new NukeopsRoleComponent { PrototypeId = role }); diff --git a/Content.Server/RoundEnd/RoundEndSystem.cs b/Content.Server/RoundEnd/RoundEndSystem.cs index 4681acc227..12cfb0e666 100644 --- a/Content.Server/RoundEnd/RoundEndSystem.cs +++ b/Content.Server/RoundEnd/RoundEndSystem.cs @@ -90,7 +90,12 @@ namespace Content.Server.RoundEnd return _cooldownTokenSource == null; } - public void RequestRoundEnd(EntityUid? requester = null, bool checkCooldown = true, bool autoCall = false) + public bool IsRoundEndRequested() + { + return _countdownTokenSource != null; + } + + public void RequestRoundEnd(EntityUid? requester = null, bool checkCooldown = true, string text = "round-end-system-shuttle-called-announcement", string name = "Station") { var duration = DefaultCountdownDuration; @@ -105,10 +110,10 @@ namespace Content.Server.RoundEnd } } - RequestRoundEnd(duration, requester, checkCooldown, autoCall); + RequestRoundEnd(duration, requester, checkCooldown, text, name); } - public void RequestRoundEnd(TimeSpan countdownTime, EntityUid? requester = null, bool checkCooldown = true, bool autoCall = false) + public void RequestRoundEnd(TimeSpan countdownTime, EntityUid? requester = null, bool checkCooldown = true, string text = "round-end-system-shuttle-called-announcement", string name = "Station") { if (_gameTicker.RunLevel != GameRunLevel.InRound) return; @@ -141,26 +146,13 @@ namespace Content.Server.RoundEnd units = "eta-units-minutes"; } - if (autoCall) - { - _chatSystem.DispatchGlobalAnnouncement(Loc.GetString("round-end-system-shuttle-auto-called-announcement", - ("time", time), - ("units", Loc.GetString(units))), - Loc.GetString("Station"), - false, - null, - Color.Gold); - } - else - { - _chatSystem.DispatchGlobalAnnouncement(Loc.GetString("round-end-system-shuttle-called-announcement", - ("time", time), - ("units", Loc.GetString(units))), - Loc.GetString("Station"), - false, - null, - Color.Gold); - } + _chatSystem.DispatchGlobalAnnouncement(Loc.GetString(text, + ("time", time), + ("units", Loc.GetString(units))), + name, + false, + null, + Color.Gold); SoundSystem.Play("/Audio/Announcements/shuttlecalled.ogg", Filter.Broadcast()); @@ -232,6 +224,30 @@ namespace Content.Server.RoundEnd Timer.Spawn(countdownTime.Value, AfterEndRoundRestart, _countdownTokenSource.Token); } + public void DoRoundEndBehavior(RoundEndBehavior behavior, TimeSpan time, string sender, string textCall, string textAnnounce) + { + switch (behavior) + { + case RoundEndBehavior.InstantEnd: + EndRound(); + break; + case RoundEndBehavior.ShuttleCall: + // Check is shuttle called or not. We should only dispatch announcement if it's already called + if (IsRoundEndRequested()) + { + _chatSystem.DispatchGlobalAnnouncement(Loc.GetString(textAnnounce), + Loc.GetString(sender), + colorOverride: Color.Gold); + } + else + { + RequestRoundEnd(time, null, false, textCall, + Loc.GetString(sender)); + } + break; + } + } + private void AfterEndRoundRestart() { if (_gameTicker.RunLevel != GameRunLevel.PostRound) return; @@ -260,7 +276,7 @@ namespace Content.Server.RoundEnd { if (!_shuttle.EmergencyShuttleArrived && ExpectedCountdownEnd is null) { - RequestRoundEnd(null, false, true); + RequestRoundEnd(null, false, "round-end-system-shuttle-auto-called-announcement"); AutoCalledBefore = true; } @@ -274,4 +290,22 @@ namespace Content.Server.RoundEnd { public static RoundEndSystemChangedEvent Default { get; } = new(); } + + public enum RoundEndBehavior : byte +{ + /// + /// Instantly end round + /// + InstantEnd, + + /// + /// Call shuttle with custom announcement + /// + ShuttleCall, + + /// + /// Do nothing + /// + Nothing +} } diff --git a/Content.Server/StationEvents/Events/LoneOpsSpawnRule.cs b/Content.Server/StationEvents/Events/LoneOpsSpawnRule.cs index 8e1a2f3b3b..ce5f826d0c 100644 --- a/Content.Server/StationEvents/Events/LoneOpsSpawnRule.cs +++ b/Content.Server/StationEvents/Events/LoneOpsSpawnRule.cs @@ -5,6 +5,7 @@ using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; +using Content.Server.RoundEnd; namespace Content.Server.StationEvents.Events; @@ -37,7 +38,7 @@ public sealed class LoneOpsSpawnRule : StationEventSystem(nukeopsEntity); nukeopsComp.SpawnOutpost = false; - nukeopsComp.EndsRound = false; + nukeopsComp.RoundEndBehavior = RoundEndBehavior.Nothing; _gameTicker.StartGameRule(nukeopsEntity); } diff --git a/Resources/Locale/en-US/nukeops/nuke-ops.ftl b/Resources/Locale/en-US/nukeops/nuke-ops.ftl new file mode 100644 index 0000000000..b4f2238e07 --- /dev/null +++ b/Resources/Locale/en-US/nukeops/nuke-ops.ftl @@ -0,0 +1,2 @@ +nuke-ops-no-more-threat-announcement-shuttle-call = Based on our scans from our long-range sensors, the nuclear threat is now eliminated. We will call emergency shuttle that will arrive shortly. ETA: {$time} {$units}. You can recall the shuttle to extend the shift. +nuke-ops-no-more-threat-announcement = Based on our scans from our long-range sensors, the nuclear threat is now eliminated. Shuttle is already called. \ No newline at end of file -- 2.51.2