diff --git a/Content.Server/GameTicking/Rules/Components/XenoborgsRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/XenoborgsRuleComponent.cs
index 4a018d7e6c6..d08364fea96 100644
--- a/Content.Server/GameTicking/Rules/Components/XenoborgsRuleComponent.cs
+++ b/Content.Server/GameTicking/Rules/Components/XenoborgsRuleComponent.cs
@@ -1,3 +1,4 @@
+using Content.Server.RoundEnd; // DeltaV
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.GameTicking.Rules.Components;
@@ -43,4 +44,17 @@ public sealed partial class XenoborgsRuleComponent : Component
///
[DataField]
public bool XenoborgShuttleCalled = false;
+
+
+ ///
+ /// DeltaV - The behavior of the round if the mothership core is deleted.
+ ///
+ [DataField]
+ public RoundEndBehavior XenoborgRoundEndBehavior = RoundEndBehavior.BecomeSurvival;
+
+ ///
+ /// DeltaV - The amount of time before the evac shuttle will arrive if the XenoborgRoundEndBehavior is set to ShuttleCall.
+ ///
+ [DataField]
+ public TimeSpan XenoborgShuttleDelay = TimeSpan.FromMinutes(10);
}
diff --git a/Content.Server/GameTicking/Rules/Components/ZombieRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/ZombieRuleComponent.cs
index 5fa81098ab0..863c72ce506 100644
--- a/Content.Server/GameTicking/Rules/Components/ZombieRuleComponent.cs
+++ b/Content.Server/GameTicking/Rules/Components/ZombieRuleComponent.cs
@@ -30,10 +30,20 @@ public sealed partial class ZombieRuleComponent : Component
///
/// DeltaV - The behavior of the round if all zombies are defeated.
///
+ [DataField]
public RoundEndBehavior ZombieRoundEndBehavior = RoundEndBehavior.BecomeSurvival;
///
/// DeltaV - The amount of time before the evac shuttle will arrive if the ZombieRoundEndBehavior is set to ShuttleCall.
///
+ [DataField]
public TimeSpan ZombieShuttleDelay = TimeSpan.FromMinutes(10);
+
+ ///
+ /// DeltaV - If true, ZombieRuleSystem will do the ZombieRoundEndBehavior if zombies are defeated.
+ /// This is needed because ZombieOutbreak uses the ZombieRuleComponent but the system won't know if
+ /// it was roundstart or not.
+ ///
+ [DataField]
+ public bool IsRoundStartZombies = false;
}
diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
index 34342de9285..70d6f732fe1 100644
--- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
@@ -520,18 +520,17 @@ public sealed class NukeopsRuleSystem : GameRuleSystem
// BEGIN DeltaV - Detect Nukie Failure Better
// We need to use a EntityQueryEnumerator instead of a EntityQuery, because we need the uid to check for cuffs
- var operatives = new List>();
- var operativesEnumerator = EntityQueryEnumerator();
- while (operativesEnumerator.MoveNext(out var uid, out var nukeOp, out var mobState, out var transform))
+ var operatives = new List>();
+ var operativesEnumerator = EntityQueryEnumerator();
+ while (operativesEnumerator.MoveNext(out var uid, out var nukeOp, out var mobState))
{
- operatives.Add((uid, nukeOp, mobState, transform));
+ operatives.Add((uid, nukeOp, mobState));
}
var operativesAlive = operatives
- .Where(op => op.Comp3.MapID == shuttleMapId
- || op.Comp3.MapID == targetStationMap)
- .Any(op => op.Comp2.CurrentState == MobState.Alive && op.Comp1.Running &&
- !TryComp(op, out _)); // in the case the crew keeps one alive
+ .Any(op => op.Comp1.Running
+ && op.Comp2.CurrentState == MobState.Alive
+ && TryComp(op, out var cuffable) && cuffable.CuffedHandCount == 0); // in the case the crew keeps one alive
// END DeltaV
if (operativesAlive)
diff --git a/Content.Server/GameTicking/Rules/XenoborgsRuleSystem.cs b/Content.Server/GameTicking/Rules/XenoborgsRuleSystem.cs
index 0b6a700d110..b9923c161e7 100644
--- a/Content.Server/GameTicking/Rules/XenoborgsRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/XenoborgsRuleSystem.cs
@@ -42,6 +42,14 @@ public sealed class XenoborgsRuleSystem : GameRuleSystem
colorOverride: AnnouncmentColor);
ent.Comp.MothershipCoreDeathAnnouncmentSent = true;
+
+ // BEGIN DeltaV - Convert to Survival
+ if (ent.Comp.XenoborgRoundEndBehavior != RoundEndBehavior.Nothing)
+ {
+ _roundEnd.DoRoundEndBehavior(ent.Comp.XenoborgRoundEndBehavior, ent.Comp.XenoborgShuttleDelay);
+ ent.Comp.XenoborgRoundEndBehavior = RoundEndBehavior.Nothing;
+ }
+ // END DeltaV
}
// TODO: Refactor the end of round text
diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs
index b5590e878b0..b3dd9b5ede3 100644
--- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs
@@ -115,29 +115,30 @@ public sealed class ZombieRuleSystem : GameRuleSystem
///
private void CheckRoundEnd(ZombieRuleComponent zombieRuleComponent)
{
- // BEGIN DeltaV - Change mode to survival if zombies die
- // Zombies have failed to launch and the mode has been switched to survival
- if (zombieRuleComponent.ZombieRoundEndBehavior == RoundEndBehavior.Nothing)
- return;
- // END DeltaV
-
var healthy = GetHealthyHumans();
if (healthy.Count == 1) // Only one human left. spooky
_popup.PopupEntity(Loc.GetString("zombie-alone"), healthy[0], healthy[0]);
-
// BEGIN DeltaV - Change mode to survival if zombies die
- var anyInitialInfectedAlive = EntityQuery(false)
- .Any(x => x.Item2.CurrentState != MobState.Dead);
- var anyLivingZombies = EntityQuery(false)
- .Any(x => x.Item2.CurrentState != MobState.Dead);
- var anyPendingZombies = EntityQuery(false).Any();
-
- // All II turned/dead, all entities that have turned are dead, and there are no more pending zombies
- if (!anyInitialInfectedAlive && !anyLivingZombies && !anyPendingZombies)
+ if (zombieRuleComponent.IsRoundStartZombies)
{
- _roundEnd.DoRoundEndBehavior(zombieRuleComponent.ZombieRoundEndBehavior, zombieRuleComponent.ZombieShuttleDelay);
- zombieRuleComponent.ZombieRoundEndBehavior = RoundEndBehavior.Nothing; // stop this check in the future
+ // Zombies have failed to launch and the mode has been switched to survival
+ if (zombieRuleComponent.ZombieRoundEndBehavior == RoundEndBehavior.Nothing)
+ return;
+
+ // BEGIN DeltaV - Change mode to survival if zombies die
+ var anyInitialInfectedAlive = EntityQuery(false)
+ .Any(x => x.Item2.CurrentState != MobState.Dead);
+ var anyLivingZombies = EntityQuery(false)
+ .Any(x => x.Item2.CurrentState != MobState.Dead);
+ var anyPendingZombies = EntityQuery(false).Any();
+
+ // All II turned/dead, all entities that have turned are dead, and there are no more pending zombies
+ if (!anyInitialInfectedAlive && !anyLivingZombies && !anyPendingZombies)
+ {
+ _roundEnd.DoRoundEndBehavior(zombieRuleComponent.ZombieRoundEndBehavior, zombieRuleComponent.ZombieShuttleDelay);
+ zombieRuleComponent.ZombieRoundEndBehavior = RoundEndBehavior.Nothing; // stop this check in the future
+ }
}
// END DeltaV
diff --git a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
index 214638895c4..4961fa3f459 100644
--- a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
+++ b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
@@ -41,7 +41,7 @@ namespace Content.Server.StationEvents
if (TryComp(uid, out var nextEventComponent)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, TimeSpan.FromSeconds(component.TimeUntilNextEvent)) is {} firstEvent)
{
- _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("seconds", (int)component.TimeUntilNextEvent)));
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("time", nextEventTime.ToString(@"hh\:mm\:ss"))));
_next.UpdateNextEvent(nextEventComponent, firstEvent, GameTicker.RoundDuration() + TimeSpan.FromSeconds(component.TimeUntilNextEvent));
}
// End DeltaV Additions
@@ -81,7 +81,7 @@ namespace Content.Server.StationEvents
if (_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, nextEventTime) is not {} generatedEvent)
continue;
- _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", generatedEvent), ("seconds", (int)eventScheduler.TimeUntilNextEvent)));
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", generatedEvent), ("time", nextEventTime.ToString(@"hh\:mm\:ss"))));
// Cycle the stashed event with the new generated event and time.
var storedEvent = _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
if (string.IsNullOrEmpty(storedEvent)) //If there was no stored event don't try to run it.
diff --git a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
index 6f96dcf130d..ae220150489 100644
--- a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
+++ b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
@@ -14,9 +14,12 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem
/// Returns the ChaosModifier which increases as round time increases to a point.
@@ -50,7 +53,8 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem(uid, out var nextEventComponent)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, TimeSpan.FromSeconds(component.TimeUntilNextEvent)) is {} firstEvent)
{
- _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("seconds", (int)component.TimeUntilNextEvent)));
+ var nextEventTime = GameTicker.RoundDuration() + TimeSpan.FromSeconds(component.TimeUntilNextEvent);
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("time", nextEventTime.ToString(@"hh\:mm\:ss"))));
_next.UpdateNextEvent(nextEventComponent, firstEvent, GameTicker.RoundDuration() + TimeSpan.FromSeconds(component.TimeUntilNextEvent));
}
// End DeltaV Additions: init NextEventComp
@@ -83,7 +87,7 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem(uid, out var gameRule))
+ {
+ ruleActivated = gameRule.ActivatedAt;
+ }
+
+ var ruleTime = _timing.CurTime.Subtract(ruleActivated);
+
+#if DEBUG
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-debug-round-time", ("time", _gameTicker.RoundDuration())));
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-debug-ramping-time", ("time", ruleActivated)));
+ // This will be what the keypoint system looks at to determine where to start ramping
+ _chatManager.SendAdminAlert(Loc.GetString("station-event-system-debug-keypoint-time", ("time", ruleTime)));
+ _chatManager.SendAdminAlert("_______________"); // Easier to read
+#endif
+
+ var absoluteTimePoint = 0f;
foreach (var point in component.TimeKeyPoints)
{
absoluteTimePoint += point.X;
- if (roundTime >= absoluteTimePoint)
+ if (ruleTime.TotalMinutes >= absoluteTimePoint)
averageTimeUntilNextEvent = point.Y;
}
diff --git a/Content.Server/_DV/GameTicking/GameTicker.BecomeSurvival.cs b/Content.Server/_DV/GameTicking/GameTicker.BecomeSurvival.cs
index 0cecced2bc2..5762fe3cf76 100644
--- a/Content.Server/_DV/GameTicking/GameTicker.BecomeSurvival.cs
+++ b/Content.Server/_DV/GameTicking/GameTicker.BecomeSurvival.cs
@@ -33,7 +33,7 @@ public sealed partial class GameTicker
public bool ConvertRoundToSurvival()
{
// Ramping scheduler is already added. Do nothing.
- if (IsGameRuleActive(RampingSchedulerProto))
+ if (IsGameRuleAdded(RampingSchedulerProto))
{
_chatManager.SendAdminAlert("RampingStationEventScheduler detected. No rules added.");
return true;
@@ -44,7 +44,7 @@ public sealed partial class GameTicker
var rampingSchedulerStart = _gameTiming.CurTime.Add(GracePeriod);
EnsureComp(rampingScheduler).RuleStartTime = rampingSchedulerStart;
- _chatManager.SendAdminAlert($"Major antag defeated. Converting to survival at {rampingSchedulerStart}.");
+ _chatManager.SendAdminAlert($"Major antag defeated. Converting to survival at {(RoundDuration() + GracePeriod).ToString(@"hh\:mm\:ss")}.");
// End Basic Rules
var basicRules = EntityQueryEnumerator();
diff --git a/Resources/Locale/en-US/_DV/station-events/station-event-system.ftl b/Resources/Locale/en-US/_DV/station-events/station-event-system.ftl
index fa9ba45a048..689dc2e6b4d 100644
--- a/Resources/Locale/en-US/_DV/station-events/station-event-system.ftl
+++ b/Resources/Locale/en-US/_DV/station-events/station-event-system.ftl
@@ -1,4 +1,10 @@
-station-event-system-run-event-delayed = Running event {$eventName} in {$seconds} seconds
+station-event-system-run-event-delayed = Running event {$eventName} @ {$time}
station-event-system-meteor-swarm-starting = {$count} waves of meteors will target the area between {$targetCorner1} and {$targetCorner2}
station-event-system-meteors-spawned = {$count} meteors inbound; impact in {$impactSeconds} seconds
+
+
+# Local debugging
+station-event-system-debug-round-time = Round Time @ {$time}
+station-event-system-debug-ramping-time = Ramping Rule Added @ {$time}
+station-event-system-debug-keypoint-time = Keypoint Time: {$time}
diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml
index 085629169fa..9e529398424 100644
--- a/Resources/Prototypes/GameRules/roundstart.yml
+++ b/Resources/Prototypes/GameRules/roundstart.yml
@@ -441,6 +441,7 @@
min: 600
max: 900
- type: ZombieRule
+ isRoundStartZombies: true # DeltaV - convert to survival if they all die
- type: DelayedRule # DeltaV: Grace period of 5 minutes before you can turn, to avoid a random passenger ruining your plan
delay: 300
delayedComponents:
diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml
index f0824be6ed1..028e0c8f261 100644
--- a/Resources/Prototypes/game_presets.yml
+++ b/Resources/Prototypes/game_presets.yml
@@ -245,7 +245,6 @@
- MeteorSwarmScheduler
- SpaceTrafficControlEventScheduler
- BasicRoundstartVariation
- - RampingStationEventScheduler # DeltaV
- GlimmerEventScheduler # DeltaV
- type: gamePreset