A Razor UI panel for the escape menu (pause/menu) in the game. It renders buttons for resume, options, restart, and return/quit, shows confirmation dialogs, and handles input (keyboard/controller) and RPC-triggered fades/restarts/scene loads via Manager and Networking calls.
@namespace Sandbox
@using Sandbox;
@using Sandbox.UI;
@using System;
@using System.Linq;
@inherits Panel
@attribute [StyleSheet("EscMenu.razor.scss")]
<root>
@* <label class="title">@(Manager.Instance.IsPaused ? "Paused" : "")</label> *@
<div class="blank" />
<div class="content">
@* <div class="equipment">
@{
var _gunId = ProgressManager.GetEffectiveSelectedGunId();
var _gunDef = ProgressManager.ShopItems.FirstOrDefault( x => x.Id == _gunId );
var _charmId = ProgressManager.GetEffectiveSelectedCharmIds().FirstOrDefault() ?? "";
var _charmDef = !string.IsNullOrEmpty( _charmId )
? ProgressManager.ShopItems.FirstOrDefault( x => x.Id == _charmId )
: default;
var _equippedGems = ProgressManager.GetEffectiveEquippedGems();
}
@if ( _gunDef.Id != null )
{
<div class="equip_item">
<div class="equip_icon" style="background-image:url(@_gunDef.IconPath);"></div>
<div class="equip_info">
<label class="equip_name">@_gunDef.Name</label>
@if ( _gunDef.ItemDescription != null )
{
<RichText class="equip_desc" Text=@_gunDef.ItemDescription() />
}
</div>
</div>
}
@if ( _charmDef.Id != null )
{
<div class="equip_item">
<div class="equip_icon" style="background-image:url(@_charmDef.IconPath);"></div>
<div class="equip_info">
<label class="equip_name">@_charmDef.Name</label>
@if ( _charmDef.ItemDescription != null )
{
<RichText class="equip_desc" Text=@_charmDef.ItemDescription() />
}
</div>
</div>
}
@foreach ( var _gemId in _equippedGems )
{
var _gemDef = ProgressManager.ShopItems.FirstOrDefault( x => x.Id == _gemId );
if ( _gemDef.Id != null )
{
<div class="equip_item">
<div class="equip_icon" style="background-image:url(@_gemDef.IconPath);"></div>
<div class="equip_info">
<label class="equip_name">@_gemDef.Name <span class="equip_level">Lv @ProgressManager.GetGemDisplayLevel( _gemId )</span></label>
@if ( _gemDef.GemDescription != null )
{
<RichText class="equip_desc" Text=@_gemDef.GemDescription( ProgressManager.GetGemDisplayLevel( _gemId ) ) />
}
</div>
</div>
}
}
</div> *@
@if(Manager.Instance.IsMultiplayer && Networking.IsHost)
{
<div class="col">
@* <label>HOST SETTINGS</label> *@
<button class="@(Manager.Instance.IsPaused ? "unpause_button" : "pause_button")" style="opacity:@(Networking.IsHost ? 1f : 0.1f);" onclick=@(() => TogglePause())></button>
</div>
}
<div class="row">
<div class="col">
<button class="resume_button @(Input.UsingController ? "controller" : "") @(_resumeActivated ? "ctrl-activated" : _resumeHeld ? "ctrl-held" : "")" onclick=@ResumeButton>
</button>
<button class="options_button @(Input.UsingController ? "controller" : "") @(_optionsActivated ? "ctrl-activated" : _optionsHeld ? "ctrl-held" : "")" onclick=@(() => Options())>
</button>
</div>
<div class="col">
<button class="@(Networking.IsHost ? "restart_button" : "restart_button_client") @(Input.UsingController && Networking.IsHost ? "controller" : "") @(_restartActivated ? "ctrl-activated" : _restartHeld ? "ctrl-held" : "")" onclick=@(() => Restart())>
</button>
<button class="@(Networking.IsHost ? "quit_to_lobby_button" : "leave_button") @(Input.UsingController ? "controller" : "") @(_quitHeld ? "ctrl-held" : _quitActivated ? "ctrl-activated" : "")" onclick=@(() => ReturnToLobby())>
</button>
</div>
</div>
</div>
@if ( AreYouSureAction is not null)
{
<div class="are-you-sure" onclick=@(() => { Manager.Instance.PlaySfxUI("click", pitch: 0.75f, volume: 0.6f); AreYouSureAction = null; })>
<div class="panel">
<label class="title">@AreYouSureText</label>
<div class="row">
<button class="confirm_no_button" style="width: 25%;" onclick=@(() => { AreYouSureAction = null; })>
@if(Input.UsingController) { <InputHint class="inputbutton" Button="Back" /> }
</button>
<button class="confirm_yes_button" style="width: 25%;" onclick=@(() => { AreYouSureAction?.Invoke(); AreYouSureAction = null; })>
@if(Input.UsingController) { <InputHint class="inputbutton" Button="LB" /> }
</button>
</div>
</div>
</div>
}
</root>
@code
{
Action AreYouSureAction = null;
string AreYouSureText = "Are you sure?";
bool _resumeHeld;
bool _resumeActivated;
bool _restartHeld;
bool _restartActivated;
bool _quitHeld;
bool _quitActivated;
bool _optionsHeld;
bool _optionsActivated;
public void Restart()
{
if (!Networking.IsHost)
return;
if( Manager.Instance.DontConfirmRestart )
{
DoRestart();
}
else
{
AreYouSureText = "Restart the run?";
AreYouSureAction = () =>
{
DoRestart();
};
}
}
void DoRestart()
{
Manager.Instance.PlaySfxUIRpc("restart", pitch: Game.Random.Float(1.15f, 1.2f), volume: 0.8f);
Manager.Instance.SetEscMenuOpen(false);
DoRestartAsync();
}
async void DoRestartAsync()
{
Manager.Instance.FadeRpc(fadeIn: false);
await Task.Frame();
Manager.Instance.Restart();
}
void ResumeButton()
{
Manager.Instance.SetEscMenuOpen( false );
}
public void ReturnToLobby()
{
if(Manager.Instance.DontConfirmRestart)
{
DoReturnToLobby();
}
else
{
if(Networking.IsHost)
{
AreYouSureText = Manager.Instance.IsMultiplayer
? "Quit the run and return party to lobby?"
: "Quit the run and return to lobby?";
}
else
{
AreYouSureText = "Quit the run and abandon party?";
}
AreYouSureAction = () =>
{
DoReturnToLobby();
};
}
}
void DoReturnToLobby()
{
if(!Networking.IsHost)
{
Networking.Disconnect();
Scene.LoadFromFile("scenes/game.scene");
return;
}
Manager.Instance.SetEscMenuOpen(false);
DoReturnToLobbyAsync();
}
async void DoReturnToLobbyAsync()
{
Manager.Instance.FadeRpc(fadeIn: false);
await Task.Frame();
Manager.Instance.SetGameState(GameState.Lobby);
}
public void TogglePause()
{
if (!Networking.IsHost)
return;
if(Manager.Instance.IsPaused)
Manager.Instance.SetEscMenuOpen(false);
Manager.Instance.SetPaused(!Manager.Instance.IsPaused);
}
public void Options()
{
Manager.Instance.SetOptionsMenuOpen(true);
}
public override void Tick()
{
base.Tick();
if (!Input.UsingController)
{
_resumeHeld = false;
_resumeActivated = false;
_restartHeld = false;
_restartActivated = false;
_quitHeld = false;
_quitActivated = false;
_optionsHeld = false;
_optionsActivated = false;
return;
}
if (AreYouSureAction is not null)
{
if(Input.Pressed("LB")) { Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f); AreYouSureAction?.Invoke(); AreYouSureAction = null; }
else if (Input.Pressed("Back") || Input.Pressed("Dash")) { Manager.Instance.PlaySfxUI("click", pitch: 0.75f, volume: 0.6f); AreYouSureAction = null; }
return;
}
if (_resumeActivated)
{
_resumeActivated = false;
ResumeButton();
return;
}
bool resumeDown = Input.Down("R");
if (_resumeHeld && !resumeDown)
{
_resumeHeld = false;
_resumeActivated = true;
Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f);
}
else
{
if (!_resumeHeld && resumeDown) Manager.Instance.PlaySfxUI("click", pitch: 0.85f, volume: 0.6f);
_resumeHeld = resumeDown;
}
if (_restartActivated)
{
_restartActivated = false;
Restart();
return;
}
bool restartDown = Input.Down("LB");
if (_restartHeld && !restartDown)
{
_restartHeld = false;
_restartActivated = true;
Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f);
}
else
{
if (!_restartHeld && restartDown) Manager.Instance.PlaySfxUI("click", pitch: 0.85f, volume: 0.6f);
_restartHeld = restartDown;
}
if (_quitActivated)
{
_quitActivated = false;
ReturnToLobby();
return;
}
bool quitDown = Input.Down("banish");
if (_quitHeld && !quitDown)
{
_quitHeld = false;
_quitActivated = true;
Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f);
}
else
{
if (!_quitHeld && quitDown) Manager.Instance.PlaySfxUI("click", pitch: 0.85f, volume: 0.6f);
_quitHeld = quitDown;
}
if (_optionsActivated)
{
_optionsActivated = false;
Options();
return;
}
bool optionsDown = Input.Down("DpadUp");
if (_optionsHeld && !optionsDown)
{
_optionsHeld = false;
_optionsActivated = true;
Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f);
}
else
{
if (!_optionsHeld && optionsDown) Manager.Instance.PlaySfxUI("click", pitch: 0.85f, volume: 0.6f);
_optionsHeld = optionsDown;
}
}
protected override int BuildHash()
{
int buttonHash = System.HashCode.Combine(
_resumeHeld,
_resumeActivated,
_restartHeld,
_restartActivated,
_quitHeld,
_quitActivated,
_optionsHeld,
_optionsActivated
);
var gunId = ProgressManager.GetEffectiveSelectedGunId() ?? "";
var charmId = ProgressManager.GetEffectiveSelectedCharmIds().FirstOrDefault() ?? "";
var gemsHash = string.Join( ",", ProgressManager.GetEffectiveEquippedGems() ).GetHashCode();
return System.HashCode.Combine(
Manager.Instance.IsEscMenuOpen,
Manager.Instance.IsMultiplayer,
Input.UsingController,
AreYouSureAction is not null,
buttonHash,
gunId,
charmId,
gemsHash
);
}
}