Razor UI panel for the Options menu. It renders volume sliders, crosshair size slider, toggle switches for DontConfirmRestart and DisableChat, and buttons for system settings and closing; it updates GameSettingsSystem and calls Manager and Networking APIs to apply changes and control game state.
@namespace Sandbox
@using Sandbox;
@using Sandbox.UI;
@using System;
@inherits Panel
@attribute [StyleSheet("OptionsMenu.razor.scss")]
<root>
<div class="content">
@* <div class="title">Options</div> *@
<div class="header">Volume</div>
<div class="option_row slider_row">
<div class="option_label">Overall</div>
<SliderControl style="min-width: 250px;" Value:bind="@GameSettingsSystem.Current.MasterVolume" Min=@(0f) Max=@(100f) Step=@(1) OnValueChanged=@SetMasterVolume></SliderControl>
</div>
<div class="option_row slider_row">
<div class="option_label">SFX</div>
<SliderControl style="min-width: 250px;" Value:bind="@GameSettingsSystem.Current.SfxVolume" Min=@(0f) Max=@(100f) Step=@(1) OnValueChanged=@SetSfxVolume></SliderControl>
</div>
<div class="option_row slider_row">
<div class="option_label">Music</div>
<SliderControl style="min-width: 250px;" Value:bind="@GameSettingsSystem.Current.MusicVolume" Min=@(0f) Max=@(100f) Step=@(1) OnValueChanged=@SetMusicVolume></SliderControl>
</div>
<div class="option_row slider_row crosshair_row">
<div class="option_label crosshair_label">Crosshair Size</div>
<SliderControl style="min-width: 250px;" Value:bind="@GameSettingsSystem.Current.CrosshairScale" Min=@(0.5f) Max=@(3f) Step=@(0.05f) OnValueChanged=@SetCrosshairScale></SliderControl>
</div>
<div class="section_spacer"></div>
<div class="option_row toggle_row">
<div class="option_label toggle_label" style="min-width: 350px; text-shadow: 4px 4px 0px black;">Don't Confirm Restart</div>
<SwitchControl Value:bind="@DontConfirmRestartValue"></SwitchControl>
</div>
<div class="option_row toggle_row second_toggle_row">
<div class="option_label toggle_label" style="min-width: 350px; text-shadow: 4px 4px 0px black;">Disable Chat</div>
<SwitchControl Value:bind="@DisableChatValue"></SwitchControl>
</div>
@* <div class="option_row" style="margin-top: -2px;">
<div class="header" style="font-size: 28px; padding-top: 0; color: #ccc;">Lobby Privacy</div>
<DropDown style="margin-left: 12px; margin-right: -40px;" Value:bind=@LobbyPrivacyValue Options=@LobbyPrivacyOptions></DropDown>
</div> *@
@* <div class="blank"></div> *@
<button class="gear_button" onclick=@OpenSystemSettings>⚙</button>
</div>
<button class="close_button @(Input.UsingController ? "controller" : "") @(_closeActivated ? "ctrl-activated" : _closeHeld ? "ctrl-held" : "")" onclick=@(() => Manager.Instance.SetOptionsMenuOpen(false))>
</button>
</root>
@code
{
public void Restart()
{
if (!Networking.IsHost)
return;
Manager.Instance.PlaySfxUIRpc("restart", pitch: Game.Random.Float(1.15f, 1.2f), volume: 0.8f);
Manager.Instance.Restart();
Manager.Instance.SetEscMenuOpen(false);
}
public void ReturnToLobby()
{
if (!Networking.IsHost)
return;
Manager.Instance.SetGameState(GameState.Lobby);
Manager.Instance.SetEscMenuOpen(false);
}
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);
}
void OpenSystemSettings()
{
Game.Overlay.ShowSettingsModal();
}
void SetMasterVolume(float value)
{
Manager.Instance.RefreshMasterMixerVolume();
GameSettingsSystem.Save();
}
void SetSfxVolume(float value)
{
Manager.Instance.RefreshSfxMixerVolume();
GameSettingsSystem.Save();
}
void SetMusicVolume(float value)
{
Manager.Instance.RefreshMusicMixerVolume();
GameSettingsSystem.Save();
}
void SetCrosshairScale(float value)
{
var clamped = Math.Clamp( value, 0.5f, 3f );
GameSettingsSystem.Current.CrosshairScale = clamped;
var crosshair = Manager.Instance?.Components.Get<CrosshairComponent>();
if ( crosshair != null )
crosshair.Scale = clamped;
GameSettingsSystem.Save();
}
bool _closeHeld;
bool _closeActivated;
public override void Tick()
{
base.Tick();
if (!Input.UsingController)
{
_closeHeld = false;
_closeActivated = false;
return;
}
if (_closeActivated)
{
_closeActivated = false;
Manager.Instance.SetOptionsMenuOpen(false);
return;
}
bool closeDown = Input.Down("R") || Input.Down("Back");
if (_closeHeld && !closeDown)
{
_closeHeld = false;
_closeActivated = true;
Manager.Instance.PlaySfxUI("click", pitch: 1.15f, volume: 0.75f);
}
else
{
if (!_closeHeld && closeDown) Manager.Instance.PlaySfxUI("click", pitch: 0.85f, volume: 0.6f);
_closeHeld = closeDown;
}
}
protected override int BuildHash()
{
return System.HashCode.Combine(
Manager.Instance.IsOptionsMenuOpen,
Input.UsingController,
_closeHeld,
_closeActivated
);
}
void SetDontConfirmRestart(bool value)
{
Manager.Instance.DontConfirmRestart = value;
GameSettingsSystem.Current.DontConfirmRestart = value;
GameSettingsSystem.Save();
}
void SetDisableChat(bool value)
{
GameSettingsSystem.Current.DisableChat = value;
GameSettingsSystem.Save();
}
bool DontConfirmRestartValue
{
get => GameSettingsSystem.Current.DontConfirmRestart;
set => SetDontConfirmRestart( value );
}
bool DisableChatValue
{
get => GameSettingsSystem.Current.DisableChat;
set => SetDisableChat( value );
}
List<Option> LobbyPrivacyOptions = new List<Option>()
{
new Option("Public", 0),
new Option("Friends", 2),
new Option("Private", 1),
};
int LobbyPrivacyValue
{
get => Manager.Instance.LobbyPrivacy;
set
{
Manager.Instance.LobbyPrivacy = value;
GameSettingsSystem.Save();
if ( Networking.IsActive )
{
Networking.Disconnect();
Manager.Instance.CreateLobby();
}
}
}
}