using System.Runtime.InteropServices; using Content.Server.Ghost.Roles.Components; using Content.Shared._Corvax.Respawn; using Content.Shared.Mind.Components; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Robust.Server.Player; using Robust.Shared.Network; using Robust.Shared.Timing; using Content.Shared._NF.CCVar; // Frontier using Robust.Shared.Configuration; // Frontier using Robust.Shared.Player; // Frontier using Content.Shared.Ghost; // Frontier using Content.Server.Administration.Managers; // Frontier using Content.Server.Administration; // Frontier using Content.Shared.GameTicking; // Frontier namespace Content.Server._Corvax.Respawn; public sealed class RespawnSystem : EntitySystem { [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IAdminManager _admin = default!; private float _respawnTime = 0f; // Frontier: struct for respawn lookup private sealed class RespawnData { public TimeSpan RespawnTime; // The next time the user can respawn. } // End Frontier [ViewVariables] private Dictionary _respawnInfo = new(); // Frontier: struct for complete respawn info public override void Initialize() { SubscribeLocalEvent(OnMobStateChanged); SubscribeLocalEvent(OnMindRemoved); SubscribeLocalEvent(OnRoundRestart); // Frontier _admin.OnPermsChanged += OnAdminPermsChanged; // Frontier _player.PlayerStatusChanged += PlayerStatusChanged; // Frontier Subs.CVar(_cfg, NFCCVars.RespawnTime, OnRespawnCryoTimeChanged, true); // Frontier } // Frontier: CVar setters private void OnRespawnCryoTimeChanged(float value) { _respawnTime = value; } // End Frontier private void OnMobStateChanged(EntityUid entity, MindContainerComponent component, MobStateChangedEvent e) { if (e.NewMobState != MobState.Dead) return; if (!_player.TryGetSessionByEntity(entity, out var session)) return; var respawnData = GetRespawnData(session.UserId); SetRespawnTime(session.UserId, ref respawnData, _timing.CurTime + TimeSpan.FromSeconds(_respawnTime)); } /// /// DeltaV: Sets the respawn time for a player to the full death cooldown. /// public void SetDeathRespawnTime(NetUserId player) { var respawnData = GetRespawnData(player); SetRespawnTime(player, ref respawnData, _timing.CurTime + TimeSpan.FromSeconds(_respawnTime)); } private void OnMindRemoved(EntityUid entity, MindContainerComponent _, MindRemovedMessage e) { if (e.Mind.Comp.UserId is null) return; // Mob is dead, don't reset spawn timer twice if (TryComp(entity, out var state) && state.CurrentState == MobState.Dead) return; // Frontier: extra conditions for respawn lenience if (HasComp(entity)) // Don't penalize user for exiting ghost roles return; // Frontier: don't penalize user for exiting ghost roles if (HasComp(entity)) // Don't penalize user for reobserving return; if (TryComp(entity, out var actor) && _admin.IsAdmin(actor.PlayerSession)) // Admins get free respawns return; // Get respawn info var userId = e.Mind.Comp.UserId.Value; var respawnInfo = GetRespawnData(userId); // End Frontier SetRespawnTime(userId, ref respawnInfo, _timing.CurTime + TimeSpan.FromSeconds(_respawnTime)); } // Frontier: admin permissions handler: clear respawn data for admins private void OnAdminPermsChanged(AdminPermsChangedEventArgs args) { if (args.IsAdmin) { var respawnData = GetRespawnData(args.Player.UserId); SetRespawnTime(args.Player.UserId, ref respawnData, TimeSpan.Zero); } } // Frontier: respawn handler: adjusts respawn and cryo timers. public void Respawn(ICommonSession session) { var respawnData = GetRespawnData(session.UserId); } private void SetRespawnTime(NetUserId user, ref RespawnData data, TimeSpan nextSpawn, TimeSpan? cryoTime = null) // Frontier: Reset