Port respawning from Frontierstation/Corvax (#3021)
This commit is contained in:
parent
d5379b17f2
commit
07e11dda25
|
|
@ -3,8 +3,13 @@ using Content.Client.Ghost;
|
|||
using Content.Client.UserInterface.Systems.Gameplay;
|
||||
using Content.Client.UserInterface.Systems.Ghost.Widgets;
|
||||
using Content.Shared.Ghost;
|
||||
using Robust.Client.Console; // Frontier
|
||||
using Robust.Shared.Console; // Frontier
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Content.Client._Corvax.Respawn; // Frontier
|
||||
using Content.Shared._NF.CCVar; // Frontier
|
||||
using Robust.Shared.Configuration; // Frontier
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Ghost;
|
||||
|
||||
|
|
@ -12,8 +17,11 @@ namespace Content.Client.UserInterface.Systems.Ghost;
|
|||
public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSystem>
|
||||
{
|
||||
[Dependency] private readonly IEntityNetworkManager _net = default!;
|
||||
[Dependency] private readonly IConsoleHost _consoleHost = default!; // Frontier
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!; // Frontier
|
||||
|
||||
[UISystemDependency] private readonly GhostSystem? _system = default;
|
||||
[UISystemDependency] private readonly RespawnSystem? _respawn = default; // Frontier
|
||||
|
||||
private GhostGui? Gui => UIManager.GetActiveUIWidgetOrNull<GhostGui>();
|
||||
|
||||
|
|
@ -56,6 +64,24 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
system.GhostRoleCountUpdated -= OnRoleCountUpdated;
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
public void OnSystemLoaded(RespawnSystem system)
|
||||
{
|
||||
system.RespawnReseted += OnRespawnReseted;
|
||||
}
|
||||
|
||||
public void OnSystemUnloaded(RespawnSystem system)
|
||||
{
|
||||
system.RespawnReseted -= OnRespawnReseted;
|
||||
}
|
||||
|
||||
private void OnRespawnReseted()
|
||||
{
|
||||
UpdateGui();
|
||||
UpdateRespawn(_respawn?.RespawnResetTime);
|
||||
}
|
||||
// End Frontier
|
||||
|
||||
public void UpdateGui()
|
||||
{
|
||||
if (Gui == null)
|
||||
|
|
@ -67,6 +93,13 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
Gui.Update(_system?.AvailableGhostRoleCount, _system?.Player?.CanReturnToBody);
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
private void UpdateRespawn(TimeSpan? timeOfDeath)
|
||||
{
|
||||
Gui?.UpdateRespawn(timeOfDeath);
|
||||
}
|
||||
// End Frontier
|
||||
|
||||
private void OnPlayerRemoved(GhostComponent component)
|
||||
{
|
||||
Gui?.Hide();
|
||||
|
|
@ -83,6 +116,7 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
return;
|
||||
|
||||
Gui.Visible = true;
|
||||
UpdateRespawn(_respawn?.RespawnResetTime); // Frontier
|
||||
UpdateGui();
|
||||
}
|
||||
|
||||
|
|
@ -127,10 +161,18 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
Gui.GhostRolesPressed += GhostRolesPressed;
|
||||
Gui.TargetWindow.WarpClicked += OnWarpClicked;
|
||||
Gui.TargetWindow.OnGhostnadoClicked += OnGhostnadoClicked;
|
||||
Gui.GhostRespawnPressed += GuiOnGhostRespawnPressed; // Frontier
|
||||
|
||||
UpdateGui();
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
private void GuiOnGhostRespawnPressed()
|
||||
{
|
||||
_consoleHost.ExecuteCommand("ghostrespawn");
|
||||
}
|
||||
// End Frontier
|
||||
|
||||
public void UnloadGui()
|
||||
{
|
||||
if (Gui == null)
|
||||
|
|
@ -140,6 +182,7 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
Gui.ReturnToBodyPressed -= ReturnToBody;
|
||||
Gui.GhostRolesPressed -= GhostRolesPressed;
|
||||
Gui.TargetWindow.WarpClicked -= OnWarpClicked;
|
||||
Gui.GhostRespawnPressed -= GuiOnGhostRespawnPressed; // Frontier
|
||||
|
||||
Gui.Hide();
|
||||
}
|
||||
|
|
@ -160,4 +203,11 @@ public sealed class GhostUIController : UIController, IOnSystemChanged<GhostSyst
|
|||
{
|
||||
_system?.OpenGhostRoles();
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
private void RespawnPressed()
|
||||
{
|
||||
IoCManager.Resolve<IClientConsoleHost>().RemoteExecuteCommand(null, "ghostrespawn");
|
||||
}
|
||||
// End Frontier
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@
|
|||
<Button Name="ReturnToBodyButton" Text="{Loc ghost-gui-return-to-body-button}" />
|
||||
<Button Name="GhostWarpButton" Text="{Loc ghost-gui-ghost-warp-button}" />
|
||||
<Button Name="GhostRolesButton" />
|
||||
<Button Name="GhostRespawnButton" Text="{Loc ghost-gui-respawn}" /> <!-- Frontier -->
|
||||
</BoxContainer>
|
||||
</widgets:GhostGui>
|
||||
|
|
|
|||
|
|
@ -3,29 +3,42 @@ using Content.Client.UserInterface.Systems.Ghost.Controls;
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing; // Frontier
|
||||
using Robust.Shared.Configuration; // Frontier
|
||||
using Content.Client._NF.UserInterface.Systems.Ghost.Controls; // Frontier
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Ghost.Widgets;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GhostGui : UIWidget
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!; // Frontier
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!; // Frontier
|
||||
|
||||
private TimeSpan? _respawnTime; // Frontier
|
||||
|
||||
public GhostTargetWindow TargetWindow { get; }
|
||||
public GhostRespawnRulesWindow RulesWindow { get; } // Frontier
|
||||
|
||||
public event Action? RequestWarpsPressed;
|
||||
public event Action? ReturnToBodyPressed;
|
||||
public event Action? GhostRolesPressed;
|
||||
public event Action? GhostRespawnPressed; // Frontier
|
||||
|
||||
public GhostGui()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
TargetWindow = new GhostTargetWindow();
|
||||
RulesWindow = new GhostRespawnRulesWindow(); // Frontier
|
||||
RulesWindow.RespawnButton.OnPressed += _ => GhostRespawnPressed?.Invoke(); // Frontier
|
||||
|
||||
MouseFilter = MouseFilterMode.Ignore;
|
||||
|
||||
GhostWarpButton.OnPressed += _ => RequestWarpsPressed?.Invoke();
|
||||
ReturnToBodyButton.OnPressed += _ => ReturnToBodyPressed?.Invoke();
|
||||
GhostRolesButton.OnPressed += _ => GhostRolesPressed?.Invoke();
|
||||
GhostRespawnButton.OnPressed += _ => RulesWindow.OpenCentered(); // Frontier
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
|
|
@ -34,6 +47,13 @@ public sealed partial class GhostGui : UIWidget
|
|||
Visible = false;
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
public void UpdateRespawn(TimeSpan? respawnTime)
|
||||
{
|
||||
_respawnTime = respawnTime;
|
||||
}
|
||||
// End Frontier
|
||||
|
||||
public void Update(int? roles, bool? canReturnToBody)
|
||||
{
|
||||
ReturnToBodyButton.Disabled = !canReturnToBody ?? true;
|
||||
|
|
@ -54,6 +74,23 @@ public sealed partial class GhostGui : UIWidget
|
|||
TargetWindow.Populate();
|
||||
}
|
||||
|
||||
// Begin Frontier
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
if (_respawnTime is null || _gameTiming.CurTime > _respawnTime)
|
||||
{
|
||||
GhostRespawnButton.Text = Loc.GetString("ghost-gui-respawn-button-allowed");
|
||||
GhostRespawnButton.Disabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
double delta = (_respawnTime.Value - _gameTiming.CurTime).TotalSeconds;
|
||||
GhostRespawnButton.Text = Loc.GetString("ghost-gui-respawn-button-denied", ("time", $"{delta:f1}"));
|
||||
GhostRespawnButton.Disabled = true;
|
||||
}
|
||||
}
|
||||
// End Frontier
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
using Content.Shared._Corvax.Respawn;
|
||||
|
||||
namespace Content.Client._Corvax.Respawn;
|
||||
|
||||
public sealed class RespawnSystem : EntitySystem
|
||||
{
|
||||
public TimeSpan? RespawnResetTime { get; private set; }
|
||||
|
||||
public event Action? RespawnReseted;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeNetworkEvent<RespawnResetEvent>(OnRespawnReset);
|
||||
}
|
||||
|
||||
private void OnRespawnReset(RespawnResetEvent e)
|
||||
{
|
||||
RespawnResetTime = e.Time;
|
||||
|
||||
RespawnReseted?.Invoke();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
Title="{Loc 'ghost-respawn-rules-window-title'}"
|
||||
MinSize="500 350">
|
||||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False" Margin="5">
|
||||
<PanelContainer StyleClasses="Inset">
|
||||
<PanelContainer.PanelOverride>
|
||||
<graphics:StyleBoxFlat BackgroundColor="#303133"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" SeparationOverride="5">
|
||||
<PanelContainer Name="TextContainer" StyleClasses="Inset" Margin="5">
|
||||
<PanelContainer.PanelOverride>
|
||||
<!-- <graphics:StyleBoxFlat BackgroundColor="#464950"/> -->
|
||||
<graphics:StyleBoxFlat BackgroundColor="#303133"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
|
||||
<Control VerticalExpand="True" VerticalAlignment="Stretch" />
|
||||
<Button Name="ConfirmRespawnButton" Text="{Loc 'ghost-respawn-rules-window-confirm-button'}" Margin="5" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</ScrollContainer>
|
||||
</controls:FancyWindow>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._NF.UserInterface.Systems.Ghost.Controls
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GhostRespawnRulesWindow : FancyWindow
|
||||
{
|
||||
public PanelContainer RulesContainer => TextContainer;
|
||||
public RichTextLabel RulesLabel = new() { Margin = new Thickness(5, 5, 5, 5) };
|
||||
public Button RespawnButton => ConfirmRespawnButton;
|
||||
|
||||
public GhostRespawnRulesWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
var message = new FormattedMessage();
|
||||
message.AddMarkup(Loc.GetString("ghost-respawn-rules-window-rules"));
|
||||
RulesLabel.SetMessage(message);
|
||||
RulesContainer.AddChild(RulesLabel);
|
||||
RulesLabel.SetPositionFirst();
|
||||
|
||||
RespawnButton.OnPressed += _ => Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
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<NetUserId, RespawnData> _respawnInfo = new(); // Frontier: struct for complete respawn info
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<MindContainerComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<MindContainerComponent, MindRemovedMessage>(OnMindRemoved);
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(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));
|
||||
}
|
||||
|
||||
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<MobStateComponent>(entity, out var state) && state.CurrentState == MobState.Dead)
|
||||
return;
|
||||
|
||||
// Frontier: extra conditions for respawn lenience
|
||||
if (HasComp<GhostRoleComponent>(entity)) // Don't penalize user for exiting ghost roles
|
||||
return; // Frontier: don't penalize user for exiting ghost roles
|
||||
|
||||
if (HasComp<GhostComponent>(entity)) // Don't penalize user for reobserving
|
||||
return;
|
||||
|
||||
if (e.Mind.Comp.Session != null && _admin.IsAdmin(e.Mind.Comp.Session)) // 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<Set, added cryoTime, time changed to be time of next respawn, not time of death
|
||||
{
|
||||
data.RespawnTime = nextSpawn;
|
||||
|
||||
if (_player.TryGetSessionById(user, out var session)) // Frontier: try first, if no valid session, nothing to do.
|
||||
RaiseNetworkEvent(new RespawnResetEvent(nextSpawn), session);
|
||||
}
|
||||
|
||||
public TimeSpan? GetRespawnTime(NetUserId user) // Frontier: GetRespawnResetTime<GetRespawnTime
|
||||
{
|
||||
return _respawnInfo.TryGetValue(user, out var data) ? data.RespawnTime : null;
|
||||
}
|
||||
|
||||
// Frontier: return a writable reference
|
||||
private ref RespawnData GetRespawnData(NetUserId player)
|
||||
{
|
||||
if (!_respawnInfo.ContainsKey(player))
|
||||
_respawnInfo[player] = new RespawnData();
|
||||
return ref CollectionsMarshal.GetValueRefOrNullRef(_respawnInfo, player);
|
||||
}
|
||||
|
||||
// Frontier: send ghost timer on player connection
|
||||
private void PlayerStatusChanged(object? _, SessionStatusEventArgs args)
|
||||
{
|
||||
var session = args.Session;
|
||||
|
||||
if (args.NewStatus == Robust.Shared.Enums.SessionStatus.InGame &&
|
||||
_respawnInfo.ContainsKey(session.UserId))
|
||||
{
|
||||
RaiseNetworkEvent(new RespawnResetEvent(_respawnInfo[session.UserId].RespawnTime), session);
|
||||
}
|
||||
}
|
||||
|
||||
// Frontier: reset game state, we have a new round.
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
_respawnInfo.Clear();
|
||||
}
|
||||
// End Frontier
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
using Content.Server._Corvax.Respawn;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Mind;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared._NF.CCVar;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._NF.Commands;
|
||||
|
||||
[AnyCommand()]
|
||||
public sealed class GhostRespawnCommand : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entity = default!;
|
||||
|
||||
public string Command => "ghostrespawn";
|
||||
public string Description => "Allows the player to return to the lobby if they've been dead long enough, allowing re-entering the round AS ANOTHER CHARACTER.";
|
||||
public string Help => $"{Command}";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (!_configurationManager.GetCVar(NFCCVars.RespawnEnabled))
|
||||
{
|
||||
shell.WriteLine("Respawning is disabled, ask an admin to respawn you.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell.Player is null)
|
||||
{
|
||||
shell.WriteLine("You cannot run this from the console!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell.Player.AttachedEntity is null)
|
||||
{
|
||||
shell.WriteLine("You cannot run this in the lobby, or without an entity.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_entityManager.TryGetComponent<GhostComponent>(shell.Player.AttachedEntity, out var ghost))
|
||||
{
|
||||
shell.WriteLine("You are not a ghost.");
|
||||
return;
|
||||
}
|
||||
|
||||
var respawnResetTime = _entity.GetEntitySystem<RespawnSystem>().GetRespawnTime(shell.Player.UserId);
|
||||
|
||||
if (respawnResetTime is not null)
|
||||
{
|
||||
if (_gameTiming.CurTime < respawnResetTime.Value)
|
||||
{
|
||||
var timeLeft = (respawnResetTime.Value - _gameTiming.CurTime).TotalSeconds;
|
||||
shell.WriteLine($"You haven't been dead long enough. You can respawn in {timeLeft} seconds.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var gameTicker = _entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
|
||||
gameTicker.Respawn(shell.Player);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Corvax.Respawn;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class RespawnResetEvent(TimeSpan? time) : EntityEventArgs
|
||||
{
|
||||
public readonly TimeSpan? Time = time;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Shared._NF.CCVar;
|
||||
|
||||
[CVarDefs]
|
||||
public sealed class NFCCVars
|
||||
{
|
||||
/*
|
||||
* Respawn
|
||||
*/
|
||||
/// <summary>
|
||||
/// Whether or not respawning is enabled.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> RespawnEnabled =
|
||||
CVarDef.Create("nf14.respawn.enabled", true, CVar.SERVER | CVar.REPLICATED);
|
||||
|
||||
/// <summary>
|
||||
/// Respawn time, how long the player has to wait in seconds after going into cryosleep. Should be small, misclicks happen.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> RespawnCryoFirstTime =
|
||||
CVarDef.Create("nf14.respawn.cryo_first_time", 20.0f, CVar.SERVER | CVar.REPLICATED);
|
||||
|
||||
/// <summary>
|
||||
/// Respawn time, how long the player has to wait in seconds after death, or on subsequent cryo attempts.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> RespawnTime =
|
||||
CVarDef.Create("nf14.respawn.time", 1200.0f, CVar.SERVER | CVar.REPLICATED);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
## UI
|
||||
ghost-respawn-rules-window-title = Ghost Respawn Rules
|
||||
ghost-respawn-rules-window-confirm-button = I understand, respawn me
|
||||
ghost-gui-respawn-button-denied = Respawn ({$time}s)
|
||||
ghost-gui-respawn-button-allowed = Respawn
|
||||
# DeltaV - we have our own rules for respawning
|
||||
ghost-respawn-rules-window-rules = Respawning follows our rule B1.3: Follow the new life
|
||||
|
||||
You MAY NOT respawn as a character who has died this round. This applies to variants of that same character; the character you choose must be entirely new to the station's shift.
|
||||
|
||||
Your newly spawned character is treated as if they are a fresh arrival to the station.
|
||||
|
||||
## COMMMANDS
|
||||
ghost-respawn-command-desc = Respawns you if you're an eligible ghost.
|
||||
ghost-respawn-not-a-ghost = You're not currently ghosted.
|
||||
ghost-respawn-ineligible = You're not currently eligible
|
||||
Loading…
Reference in New Issue