From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Mon, 3 Jun 2024 03:28:38 +0000 (-0400) Subject: RespawnRuleSystem tweaks. (#28528) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=509e3aedf7b91c1e1d11e5a885608bc92909f552;p=space-station-14.git RespawnRuleSystem tweaks. (#28528) --- 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