From 509e3aedf7b91c1e1d11e5a885608bc92909f552 Mon Sep 17 00:00:00 2001
From: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
Date: Sun, 2 Jun 2024 23:28:38 -0400
Subject: [PATCH] RespawnRuleSystem tweaks. (#28528)
---
.../Components/RespawnDeadRuleComponent.cs | 5 +
.../Components/RespawnTrackerComponent.cs | 12 +-
.../GameTicking/Rules/DeathMatchRuleSystem.cs | 4 +-
.../GameTicking/Rules/RespawnRuleSystem.cs | 115 +++++++++---------
Resources/Prototypes/GameRules/roundstart.yml | 11 ++
5 files changed, 84 insertions(+), 63 deletions(-)
diff --git a/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs
index fafe811dd9..f6e4a3b129 100644
--- a/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs
+++ b/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs
@@ -6,4 +6,9 @@
[RegisterComponent, Access(typeof(RespawnRuleSystem))]
public sealed partial class RespawnDeadRuleComponent : Component
{
+ ///
+ /// Whether or not we want to add everyone who dies to the respawn tracker
+ ///
+ [DataField]
+ public bool AlwaysRespawnDead;
}
diff --git a/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs b/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs
index 3d338c2d13..b9c8fe1096 100644
--- a/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs
+++ b/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs
@@ -13,18 +13,24 @@ public sealed partial class RespawnTrackerComponent : Component
/// A list of the people that should be respawned.
/// Used to make sure that we don't respawn aghosts or observers.
///
- [DataField("players")]
+ [DataField]
public HashSet Players = new();
///
/// The delay between dying and respawning.
///
- [DataField("respawnDelay")]
+ [DataField]
public TimeSpan RespawnDelay = TimeSpan.Zero;
///
/// A dictionary of player netuserids and when they will respawn.
///
- [DataField("respawnQueue")]
+ [DataField]
public Dictionary RespawnQueue = new();
+
+ ///
+ /// Whether or not to delete the original body when respawning
+ ///
+ [DataField]
+ public bool DeleteBody = true;
}
diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs
index ad7c63ff58..9e3203d170 100644
--- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs
+++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs
@@ -56,7 +56,7 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem(mob);
- _respawn.AddToTracker(ev.Player.UserId, uid, tracker);
+ _respawn.AddToTracker(ev.Player.UserId, (uid, tracker));
_point.EnsurePlayer(ev.Player.UserId, uid, point);
@@ -73,7 +73,7 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem
SubscribeLocalEvent(OnMobStateChanged);
}
- private void OnSuicide(SuicideEvent ev)
- {
- if (!TryComp(ev.Victim, out var actor))
- return;
-
- var query = EntityQueryEnumerator();
- while (query.MoveNext(out _, out var respawn))
- {
- if (respawn.Players.Remove(actor.PlayerSession.UserId))
- QueueDel(ev.Victim);
- }
- }
-
- private void OnMobStateChanged(MobStateChangedEvent args)
- {
- if (args.NewMobState == MobState.Alive)
- return;
-
- if (!TryComp(args.Target, out var actor))
- return;
-
- var query = EntityQueryEnumerator();
- while (query.MoveNext(out var uid, out _, out var rule))
- {
- if (!GameTicker.IsGameRuleActive(uid, rule))
- continue;
-
- if (RespawnPlayer(args.Target, uid, actor: actor))
- break;
- }
- }
-
public override void Update(float frameTime)
{
base.Update(frameTime);
@@ -75,8 +44,7 @@ public sealed class RespawnRuleSystem : GameRuleSystem
foreach (var tracker in EntityQuery())
{
- var queue = new Dictionary(tracker.RespawnQueue);
- foreach (var (player, time) in queue)
+ foreach (var (player, time) in tracker.RespawnQueue)
{
if (_timing.CurTime < time)
continue;
@@ -92,53 +60,84 @@ public sealed class RespawnRuleSystem : GameRuleSystem
}
}
- ///
- /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die.
- ///
- public void AddToTracker(EntityUid player, EntityUid tracker, RespawnTrackerComponent? component = null, ActorComponent? actor = null)
+ private void OnSuicide(SuicideEvent ev)
{
- if (!Resolve(tracker, ref component) || !Resolve(player, ref actor, false))
- return;
+ if (!TryComp(ev.Victim, out var actor))
+ return;
- AddToTracker(actor.PlayerSession.UserId, tracker, component);
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out _, out var respawn))
+ {
+ if (respawn.Players.Remove(actor.PlayerSession.UserId))
+ QueueDel(ev.Victim);
+ }
}
- ///
- /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die.
- ///
- public void AddToTracker(NetUserId id, EntityUid tracker, RespawnTrackerComponent? component = null)
+ private void OnMobStateChanged(MobStateChangedEvent args)
{
- if (!Resolve(tracker, ref component))
+ if (args.NewMobState != MobState.Dead)
return;
- component.Players.Add(id);
+ if (!TryComp(args.Target, out var actor))
+ return;
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var respawnRule, out var tracker, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ if (respawnRule.AlwaysRespawnDead)
+ AddToTracker(actor.PlayerSession.UserId, (uid, tracker));
+ if (RespawnPlayer((args.Target, actor), (uid, tracker)))
+ break;
+ }
}
///
/// Attempts to directly respawn a player, skipping the lobby screen.
///
- public bool RespawnPlayer(EntityUid player, EntityUid respawnTracker, RespawnTrackerComponent? component = null, ActorComponent? actor = null)
+ public bool RespawnPlayer(Entity player, Entity respawnTracker)
{
- if (!Resolve(respawnTracker, ref component) || !Resolve(player, ref actor, false))
+ if (!respawnTracker.Comp.Players.Contains(player.Comp.PlayerSession.UserId) || respawnTracker.Comp.RespawnQueue.ContainsKey(player.Comp.PlayerSession.UserId))
return false;
- if (!component.Players.Contains(actor.PlayerSession.UserId) || component.RespawnQueue.ContainsKey(actor.PlayerSession.UserId))
- return false;
-
- if (component.RespawnDelay == TimeSpan.Zero)
+ if (respawnTracker.Comp.RespawnDelay == TimeSpan.Zero)
{
if (_station.GetStations().FirstOrNull() is not { } station)
return false;
- QueueDel(player);
- GameTicker.MakeJoinGame(actor.PlayerSession, station, silent: true);
+ if (respawnTracker.Comp.DeleteBody)
+ QueueDel(player);
+ GameTicker.MakeJoinGame(player.Comp.PlayerSession, station, silent: true);
return false;
}
- var msg = Loc.GetString("rule-respawn-in-seconds", ("second", component.RespawnDelay.TotalSeconds));
+ var msg = Loc.GetString("rule-respawn-in-seconds", ("second", respawnTracker.Comp.RespawnDelay.TotalSeconds));
var wrappedMsg = Loc.GetString("chat-manager-server-wrap-message", ("message", msg));
- _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMsg, respawnTracker, false, actor.PlayerSession.Channel, Color.LimeGreen);
- component.RespawnQueue[actor.PlayerSession.UserId] = _timing.CurTime + component.RespawnDelay;
+ _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMsg, respawnTracker, false, player.Comp.PlayerSession.Channel, Color.LimeGreen);
+
+ respawnTracker.Comp.RespawnQueue[player.Comp.PlayerSession.UserId] = _timing.CurTime + respawnTracker.Comp.RespawnDelay;
+
return true;
}
+
+ ///
+ /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die.
+ ///
+ public void AddToTracker(Entity player, Entity respawnTracker)
+ {
+ if (!Resolve(respawnTracker, ref respawnTracker.Comp) || !Resolve(player, ref player.Comp, false))
+ return;
+
+ AddToTracker(player.Comp.PlayerSession.UserId, (respawnTracker, respawnTracker.Comp));
+ }
+
+ ///
+ /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die.
+ ///
+ public void AddToTracker(NetUserId id, Entity tracker)
+ {
+ tracker.Comp.Players.Add(id);
+ }
}
diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml
index 93350163f6..cf2c5b2f47 100644
--- a/Resources/Prototypes/GameRules/roundstart.yml
+++ b/Resources/Prototypes/GameRules/roundstart.yml
@@ -5,6 +5,17 @@
components:
- type: GameRule
+- type: entity
+ noSpawn: true
+ parent: BaseGameRule
+ id: RespawnDeadRule
+ components:
+ - type: RespawnDeadRule
+ alwaysRespawnDead: true
+ - type: RespawnTracker
+ respawnDelay: 10
+ deleteBody: false
+
- type: entity
noSpawn: true
parent: BaseGameRule
--
2.51.2