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