After killing all nuclear operatives, shuttle will be called instead of instant round end (#19850)
* ☢️🕵️💀🚫📄🚀 * 🚀📢❌📥📜 * 🔧🐛📢🚹🚉➡👑👑 * 😪 * 🧱 * 🚀🛬🕔➡️🕙 * ☢️⚙️🔵🔚🔨➡️🔵🔚⚙️ these commit names are literally evil who tf does this
This commit is contained in:
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DataField("endsRound")]
|
||||
public bool EndsRound = true;
|
||||
[DataField("roundEndBehavior")]
|
||||
public RoundEndBehavior RoundEndBehavior = RoundEndBehavior.ShuttleCall;
|
||||
|
||||
/// <summary>
|
||||
/// Text for shuttle call if RoundEndBehavior is ShuttleCall.
|
||||
/// </summary>
|
||||
[DataField("roundEndTextSender")]
|
||||
public string RoundEndTextSender = "comms-console-announcement-title-centcom";
|
||||
|
||||
/// <summary>
|
||||
/// Text for shuttle call if RoundEndBehavior is ShuttleCall.
|
||||
/// </summary>
|
||||
[DataField("roundEndTextShuttleCall")]
|
||||
public string RoundEndTextShuttleCall = "nuke-ops-no-more-threat-announcement-shuttle-call";
|
||||
|
||||
/// <summary>
|
||||
/// Text for announcement if RoundEndBehavior is ShuttleCall. Used if shuttle is already called
|
||||
/// </summary>
|
||||
[DataField("roundEndTextAnnouncement")]
|
||||
public string RoundEndTextAnnouncement = "nuke-ops-no-more-threat-announcement";
|
||||
|
||||
/// <summary>
|
||||
/// Time to emergency shuttle to arrive if RoundEndBehavior is ShuttleCall.
|
||||
/// </summary>
|
||||
[DataField("evacShuttleTime")]
|
||||
public TimeSpan EvacShuttleTime = TimeSpan.FromMinutes(10);
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to spawn the nuclear operative outpost. Used by LoneOpsSpawn event.
|
||||
|
||||
@@ -487,14 +487,14 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
|
||||
}
|
||||
}
|
||||
|
||||
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<NukeopsRuleComponent>
|
||||
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<NukeopsRuleComponent>
|
||||
? 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<NukeopsRuleComponent>
|
||||
|
||||
foreach (var (nukeops, gameRule) in EntityQuery<NukeopsRuleComponent, GameRuleComponent>())
|
||||
{
|
||||
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 });
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantly end round
|
||||
/// </summary>
|
||||
InstantEnd,
|
||||
|
||||
/// <summary>
|
||||
/// Call shuttle with custom announcement
|
||||
/// </summary>
|
||||
ShuttleCall,
|
||||
|
||||
/// <summary>
|
||||
/// Do nothing
|
||||
/// </summary>
|
||||
Nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LoneOpsSpawnRuleCompon
|
||||
component.AdditionalRule = nukeopsEntity;
|
||||
var nukeopsComp = EntityManager.GetComponent<NukeopsRuleComponent>(nukeopsEntity);
|
||||
nukeopsComp.SpawnOutpost = false;
|
||||
nukeopsComp.EndsRound = false;
|
||||
nukeopsComp.RoundEndBehavior = RoundEndBehavior.Nothing;
|
||||
_gameTicker.StartGameRule(nukeopsEntity);
|
||||
}
|
||||
|
||||
|
||||
2
Resources/Locale/en-US/nukeops/nuke-ops.ftl
Normal file
2
Resources/Locale/en-US/nukeops/nuke-ops.ftl
Normal file
@@ -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.
|
||||
Reference in New Issue
Block a user