From a27af30acd7c93927c1214b11b68d82bcb124281 Mon Sep 17 00:00:00 2001
From: deltanedas <@deltanedas:kde.org>
Date: Thu, 14 Nov 2024 17:57:43 +0000
Subject: [PATCH 1/2] zombie gamemode semi rework
---
.../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..f66189ae98f
--- /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; // amazing language
+ _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 8b72770b647..871fe4bfeb3 100644
--- a/Resources/Prototypes/GameRules/roundstart.yml
+++ b/Resources/Prototypes/GameRules/roundstart.yml
@@ -243,6 +243,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 ]
@@ -253,14 +260,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
From 89a806ff7bb9d8a5b198e8660379fcacf95baadc Mon Sep 17 00:00:00 2001
From: deltanedas <@deltanedas:kde.org>
Date: Tue, 26 Nov 2024 09:25:43 +0000
Subject: [PATCH 2/2] remove 1
---
Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs b/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
index f66189ae98f..ca64ebf45e0 100644
--- a/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
+++ b/Content.Server/DeltaV/GameTicking/Rules/DelayedRuleSystem.cs
@@ -48,7 +48,7 @@ private void CheckDelay(Entity ent)
if (!TryComp(mindId, out var mind) || !TryGetEntity(mind.OriginalOwnedEntity, out var mob))
continue;
- var uid = mob!.Value; // amazing language
+ var uid = mob.Value;
_popup.PopupEntity(Loc.GetString(ent.Comp.EndedPopup), uid, uid, PopupType.LargeCaution);
EntityManager.AddComponents(uid, comps);
}