From 921a0e26fd6b46231dd84f18da9cfc7859e2f0b8 Mon Sep 17 00:00:00 2001
From: deltanedas <39013340+deltanedas@users.noreply.github.com>
Date: Tue, 26 Nov 2024 12:23:26 +0000
Subject: [PATCH] zombie gamemode semi rework (#2194)
* zombie gamemode semi rework
* remove 1
---------
Co-authored-by: deltanedas <@deltanedas:kde.org>
---
.../Rules/Components/DelayedRuleComponent.cs | 46 +++++++++++++++
.../GameTicking/Rules/DelayedRuleSystem.cs | 58 +++++++++++++++++++
.../game-presets/preset-zombies.ftl | 2 +
Resources/Prototypes/GameRules/roundstart.yml | 20 +++++--
4 files changed, 122 insertions(+), 4 deletions(-)
create mode 100644 Content.Server/DeltaV/GameTicking/Rules/Components/DelayedRuleComponent.cs
create mode 100644 Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
create mode 100644 Resources/Locale/en-US/deltav/game-ticking/game-presets/preset-zombies.ftl
diff --git a/Content.Server/DeltaV/GameTicking/Rules/Components/DelayedRuleComponent.cs b/Content.Server/DeltaV/GameTicking/Rules/Components/DelayedRuleComponent.cs
new file mode 100644
index 00000000000..64f90f135e0
--- /dev/null
+++ b/Content.Server/DeltaV/GameTicking/Rules/Components/DelayedRuleComponent.cs
@@ -0,0 +1,46 @@
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server.DeltaV.GameTicking.Rules.Components;
+
+///
+/// Delays adding components to the antags of a gamerule until some time has passed.
+///
+///
+/// This is used for the zombies gamemode so that new players don't hit the funny button immediately and ruin anyone else's plans.
+///
+[RegisterComponent, Access(typeof(DelayedRuleSystem))]
+[AutoGenerateComponentPause]
+public sealed partial class DelayedRuleComponent : Component
+{
+ ///
+ /// The players must wait this length of time before gets added.
+ /// If they are somehow found out and get gibbed/cremated/etc before this delay is up they will not turn.
+ ///
+ [DataField(required: true)]
+ public TimeSpan Delay;
+
+ ///
+ /// Whether to skip the delay if there is only 1 antag selected.
+ ///
+ [DataField]
+ public bool IgnoreSolo;
+
+ ///
+ /// When the will end.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
+ public TimeSpan DelayEnds;
+
+ ///
+ /// The components to add to each player's mob once the delay ends.
+ ///
+ [DataField(required: true)]
+ public ComponentRegistry DelayedComponents = new();
+
+ ///
+ /// Popup to show when the delay ends.
+ ///
+ [DataField(required: true)]
+ public LocId EndedPopup;
+}
diff --git a/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs b/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
new file mode 100644
index 00000000000..ca64ebf45e0
--- /dev/null
+++ b/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
@@ -0,0 +1,58 @@
+using Content.Server.Antag.Components;
+using Content.Server.GameTicking.Rules;
+using Content.Server.DeltaV.GameTicking.Rules.Components;
+using Content.Shared.GameTicking.Components;
+using Content.Shared.Mind;
+using Content.Shared.Popups;
+
+namespace Content.Server.DeltaV.GameTicking.Rules;
+
+public sealed class DelayedRuleSystem : GameRuleSystem
+{
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+ protected override void Started(EntityUid uid, DelayedRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
+ {
+ base.Started(uid, component, gameRule, args);
+
+ component.DelayEnds = Timing.CurTime + component.Delay;
+ }
+
+ protected override void ActiveTick(EntityUid uid, DelayedRuleComponent component, GameRuleComponent gameRule, float frameTime)
+ {
+ base.ActiveTick(uid, component, gameRule, frameTime);
+
+ CheckDelay((uid, component));
+ }
+
+ ///
+ /// Checks if the delay has ended.
+ ///
+ private void CheckDelay(Entity ent)
+ {
+ if (!TryComp(ent, out var selection))
+ return;
+
+ // skip the delay if it's just 1 player, theres no plan to ruin if you are the only one
+ var ends = ent.Comp.DelayEnds;
+ if (ent.Comp.IgnoreSolo && selection.SelectedMinds.Count < 2)
+ ends = Timing.CurTime;
+
+ if (Timing.CurTime < ends)
+ return;
+
+ var comps = ent.Comp.DelayedComponents;
+ foreach (var (mindId, _) in selection.SelectedMinds)
+ {
+ // using OriginalOwnedEntity as the player might have ghosted to try become an evil ghost antag
+ if (!TryComp(mindId, out var mind) || !TryGetEntity(mind.OriginalOwnedEntity, out var mob))
+ continue;
+
+ var uid = mob.Value;
+ _popup.PopupEntity(Loc.GetString(ent.Comp.EndedPopup), uid, uid, PopupType.LargeCaution);
+ EntityManager.AddComponents(uid, comps);
+ }
+
+ RemCompDeferred(ent);
+ }
+}
diff --git a/Resources/Locale/en-US/deltav/game-ticking/game-presets/preset-zombies.ftl b/Resources/Locale/en-US/deltav/game-ticking/game-presets/preset-zombies.ftl
new file mode 100644
index 00000000000..1bc0332154b
--- /dev/null
+++ b/Resources/Locale/en-US/deltav/game-ticking/game-presets/preset-zombies.ftl
@@ -0,0 +1,2 @@
+zombie-bioterrorist-role-greeting = You are a syndicate sponsored bioterrorist sent to overtake the station by use of the Romerol virus. Coordinate with your team, get supplies and prepare for your eventual transformation. Death to nanotrasen!
+zombie-bioterrorist-romerol-active = The romerol in your blood is now active, you are ready to transform!
diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml
index 8359a2fbd94..50de7c4b746 100644
--- a/Resources/Prototypes/GameRules/roundstart.yml
+++ b/Resources/Prototypes/GameRules/roundstart.yml
@@ -248,6 +248,13 @@
min: 600
max: 900
- type: ZombieRule
+ - type: DelayedRule # DeltaV: Grace period of 5 minutes before you can turn, to avoid a random passenger ruining your plan
+ delay: 300
+ delayedComponents:
+ - type: PendingZombie
+ - type: ZombifyOnDeath
+ - type: IncurableZombie
+ endedPopup: zombie-bioterrorist-romerol-active
- type: AntagSelection
definitions:
- prefRoles: [ InitialInfected ]
@@ -258,14 +265,19 @@
- ZombieImmune
- AntagImmune
briefing:
- text: zombie-patientzero-role-greeting
+ text: zombie-bioterrorist-role-greeting # DeltaV: Different greeting
color: Plum
sound: "/Audio/Ambience/Antag/zombie_start.ogg"
components:
- - type: PendingZombie
- - type: ZombifyOnDeath
- - type: IncurableZombie
+ # Begin DeltaV Removals: Moved to DelayedRule above
+ #- type: PendingZombie
+ #- type: ZombifyOnDeath
+ #- type: IncurableZombie
+ # End DeltaV Removals
- type: InitialInfected
+ - type: AutoImplant # DeltaV: Let them communicate to come up with a plan of action
+ implants:
+ - SyndicateRadioImplant
mindRoles:
- MindRoleInitialInfected