UI/SandboxSetupPage.razor
@using System;
@using Sandbox.UI;
@using Sandbox.UI.Navigation;
@inherits Panel
@attribute [Route( "/practice/sandbox" )]
<root class="menu-page sandbox-setup-page">
<label class="page-heading">
SANDBOX SETUP
</label>
<label class="page-copy">
@ConnectedPlayerCount PLAYER@(ConnectedPlayerCount == 1 ? "" : "S") CONNECTED
</label>
@if (
RoundManager is not null &&
Networking.IsHost
)
{
<div class="setup-grid">
<div class="setup-section">
<div class="setup-section-title">
LOADOUTS
</div>
<div class="setup-row">
<div class="setup-label">PLAYER A</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxWeaponAPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxWeaponName( 0 )</div>
<div class="selector-arrow" onclick=@SandboxWeaponANext>></div>
</div>
</div>
<div class="setup-row">
<div class="setup-label">PLAYER B</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxWeaponBPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxWeaponName( 1 )</div>
<div class="selector-arrow" onclick=@SandboxWeaponBNext>></div>
</div>
</div>
</div>
<div class="setup-section bot-setup-section">
<div class="setup-section-title">
BOT OPPONENT
</div>
<div class="setup-row">
<div class="setup-label">SANDBOX BOT</div>
<div
class="bot-toggle @(RoundManager.SandboxBotEnabled ? "enabled" : "disabled")"
onclick=@ToggleSandboxBot
>
<div class="bot-toggle-state">
@(RoundManager.SandboxBotEnabled ? "ENABLED" : "DISABLED")
</div>
<div class="bot-toggle-copy">
@(RoundManager.SandboxBotEnabled ? "BOT FILLS PLAYER B" : "PLAYER B REMAINS HUMAN / EMPTY")
</div>
</div>
</div>
<div class="setup-row @(RoundManager.SandboxBotEnabled ? "" : "setup-row-muted")">
<div class="setup-label">DIFFICULTY PROFILE</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxBotDifficultyPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxBotDifficultyName()</div>
<div class="selector-arrow" onclick=@SandboxBotDifficultyNext>></div>
</div>
</div>
<div class="setup-row @(RoundManager.SandboxBotEnabled ? "" : "setup-row-muted")">
<div class="setup-label">BEHAVIOR TEST</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxBotBehaviorPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxBotBehaviorName()</div>
<div class="selector-arrow" onclick=@SandboxBotBehaviorNext>></div>
</div>
</div>
<div class="setup-row @(RoundManager.SandboxBotEnabled ? "" : "setup-row-muted")">
<div class="setup-label">RULE TEST</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxBotModifierPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxBotModifierName()</div>
<div class="selector-arrow" onclick=@SandboxBotModifierNext>></div>
</div>
</div>
<div class="setup-row @(RoundManager.SandboxBotEnabled ? "" : "setup-row-muted")">
<div class="setup-label">NAVMESH DEBUG</div>
<div
class="bot-toggle @(RoundManager.SandboxBotDrawNavMesh ? "enabled" : "disabled")"
onclick=@ToggleSandboxBotDrawNavMesh
>
<div class="bot-toggle-state">
@(RoundManager.SandboxBotDrawNavMesh ? "VISIBLE" : "HIDDEN")
</div>
<div class="bot-toggle-copy">EDITOR NAVIGATION SURFACE</div>
</div>
</div>
<div class="bot-foundation-note">
<div class="bot-foundation-title">BOT 6 · ADAPTIVE TACTICAL + MODIFIER AWARENESS</div>
<div class="bot-foundation-copy">
Dynamic tactics + opponent learning + modifier-aware combat + continuous mobility
</div>
</div>
</div>
<div class="setup-section">
<div class="setup-section-title">
ARENA MODULES
</div>
<div class="setup-row">
<div class="setup-label">SPAWN A</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxSpawnAPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxSpawnALayoutName()</div>
<div class="selector-arrow" onclick=@SandboxSpawnANext>></div>
</div>
</div>
<div class="setup-row">
<div class="setup-label">CENTER</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxCenterPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxCenterLayoutName()</div>
<div class="selector-arrow" onclick=@SandboxCenterNext>></div>
</div>
</div>
<div class="setup-row">
<div class="setup-label">SPAWN B</div>
<div class="setup-selector">
<div class="selector-arrow" onclick=@SandboxSpawnBPrevious><</div>
<div class="selector-value">@RoundManager.GetSandboxSpawnBLayoutName()</div>
<div class="selector-arrow" onclick=@SandboxSpawnBNext>></div>
</div>
</div>
</div>
</div>
<div class="setup-actions">
<a
href="/practice"
class="menu-back"
>
BACK
</a>
<div
class="menu-primary"
onclick=@StartSandbox
>
START SANDBOX
</div>
</div>
}
else
{
<div class="client-message">
CONNECTED TO HOST
</div>
<label class="page-copy">
The host is configuring the sandbox session.
</label>
<a
href="/practice"
class="menu-back"
>
BACK
</a>
}
</root>
@code
{
private MainMenuHost Host =>
MainMenuHost.Current;
private RoundManager RoundManager =>
Host?.
RoundManager;
private int ConnectedPlayerCount =>
Host?.
ConnectedPlayerCount ??
0;
private void StartSandbox() =>
Host?.
StartSandbox();
private void ToggleSandboxBot() =>
RoundManager?.ToggleSandboxBot();
private void SandboxBotDifficultyPrevious() =>
RoundManager?.CycleSandboxBotDifficulty( -1 );
private void SandboxBotDifficultyNext() =>
RoundManager?.CycleSandboxBotDifficulty( 1 );
private void SandboxBotBehaviorPrevious() =>
RoundManager?.CycleSandboxBotBehavior( -1 );
private void SandboxBotBehaviorNext() =>
RoundManager?.CycleSandboxBotBehavior( 1 );
private void SandboxBotModifierPrevious() =>
RoundManager?.CycleSandboxBotModifier( -1 );
private void SandboxBotModifierNext() =>
RoundManager?.CycleSandboxBotModifier( 1 );
private void ToggleSandboxBotDrawNavMesh() =>
RoundManager?.ToggleSandboxBotDrawNavMesh();
private void SandboxWeaponAPrevious() =>
RoundManager?.
CycleSandboxWeapon(
0,
-1
);
private void SandboxWeaponANext() =>
RoundManager?.
CycleSandboxWeapon(
0,
1
);
private void SandboxWeaponBPrevious() =>
RoundManager?.
CycleSandboxWeapon(
1,
-1
);
private void SandboxWeaponBNext() =>
RoundManager?.
CycleSandboxWeapon(
1,
1
);
private void SandboxSpawnAPrevious() =>
RoundManager?.
CycleSandboxSpawnALayout(
-1
);
private void SandboxSpawnANext() =>
RoundManager?.
CycleSandboxSpawnALayout(
1
);
private void SandboxCenterPrevious() =>
RoundManager?.
CycleSandboxCenterLayout(
-1
);
private void SandboxCenterNext() =>
RoundManager?.
CycleSandboxCenterLayout(
1
);
private void SandboxSpawnBPrevious() =>
RoundManager?.
CycleSandboxSpawnBLayout(
-1
);
private void SandboxSpawnBNext() =>
RoundManager?.
CycleSandboxSpawnBLayout(
1
);
protected override int BuildHash()
{
HashCode hash =
new();
hash.Add(
ConnectedPlayerCount
);
if ( RoundManager is not null )
{
hash.Add(
RoundManager.SandboxWeaponAIndex
);
hash.Add(
RoundManager.SandboxWeaponBIndex
);
hash.Add(
RoundManager.SandboxBotEnabled
);
hash.Add(
(int)RoundManager.SandboxBotDifficulty
);
hash.Add(
(int)RoundManager.SandboxBotBehavior
);
hash.Add(
(int)RoundManager.SandboxBotTestModifier
);
hash.Add(
RoundManager.SandboxBotDrawNavMesh
);
hash.Add(
RoundManager.SandboxSpawnALayoutIndex
);
hash.Add(
RoundManager.SandboxCenterLayoutIndex
);
hash.Add(
RoundManager.SandboxSpawnBLayoutIndex
);
}
return hash.ToHashCode();
}
}