PushHud.razor
@using Sandbox;
@using Sandbox.UI;
@using System;
@using System.Linq;
@using System.Collections.Generic;
@inherits PanelComponent
@attribute [StyleSheet( "PushHud.scss" )]
<root class="hud-root">
<div class="score-box">
<div class="score-card">
<label class="score-title">@L( "Сбито", "Score" )</label>
<label class="score-value">@GetScore()</label>
</div>
<div class="score-card death">
<label class="score-title">@L( "Смерти", "Deaths" )</label>
<label class="score-value">@GetDeaths()</label>
</div>
<div class="score-card highlight">
<label class="score-title">@L( "Рекорд", "Best" )</label>
<label class="score-value">@GetHighScore()</label>
</div>
</div>
<div class="scoreboard-box">
<div class="scoreboard-header">
<label class="header-title">@L( "ИГРОКИ", "PLAYERS" )</label>
</div>
<div class="player-list">
@foreach ( var p in GetPlayerList() )
{
<div class="player-row @(p.IsLocal ? "local" : "")">
<label class="player-name">@p.Name</label>
<label class="player-score">@p.Score</label>
</div>
}
</div>
</div>
<div class="hotbar-container">
@if ( ShopManager.Instance != null )
{
@foreach ( var item in ShopManager.Instance.Items )
{
bool isSelected = item == ShopManager.Instance.SelectedItem;
<div class="slot-wrapper">
<div class="hotbar-slot @(isSelected ? "selected" : "") @(!item.IsUnlocked ? "locked" : "")"
onclick="@(() => ShopManager.Instance.TryBuyOrSelect(item))">
<label class="slot-name">@item.GetName( CurrentLanguage )</label>
@if ( !item.IsUnlocked )
{
<label class="slot-cost">💰 @item.Cost</label>
}
</div>
<div class="key-badge @(isSelected ? "selected" : "")">@item.Key</div>
</div>
}
}
</div>
<div class="top-left-box">
<div class="chat-box @(IsChatOpen ? "open" : "")">
<div class="chat-messages">
@foreach ( var msg in CanvasMessages )
{
<div class="chat-row">
<label class="chat-author">@msg.Author:</label>
<label class="chat-text">@msg.Text</label>
</div>
}
</div>
@if ( IsChatOpen )
{
<div class="chat-input-row">
<textentry @ref="ChatInput" onsubmit="@SendChatMessage" placeholder="@L( "Введите сообщение...", "Type a message..." )"></textentry>
</div>
}
else
{
<label class="chat-hint" onclick="@OpenChat">@L( "Нажмите [Enter] для чата", "Press [Enter] to chat" )</label>
}
</div>
</div>
<div class="cooldown-box">
<label class="cooldown-title">@L( "Перезарядка", "Cooldown" )</label>
<div class="bar-background">
<div class="bar-fill" style="width: @($"{GetPercent():F1}%");"></div>
</div>
</div>
@if ( !IsMenuOpen && !IsSettingsOpen )
{
<button class="side-settings-btn" onclick="@OpenMenu">
<label class="key-hint">[ESC]</label>
<label class="icon">⚙</label>
</button>
}
@if ( IsMenuOpen )
{
<div class="menu-overlay">
<div class="menu-card">
<label class="menu-title">ONE MORE PUSH</label>
<button class="menu-btn play" onclick="@StartGame">@L( "ИГРАТЬ", "PLAY" )</button>
<button class="menu-btn" onclick="@OpenSettings">@L( "НАСТРОЙКИ", "SETTINGS" )</button>
<button class="menu-btn quit" onclick="@QuitGame">@L( "ВЫХОД", "QUIT" )</button>
</div>
</div>
}
@if ( IsSettingsOpen )
{
<div class="menu-overlay">
<div class="menu-card settings-card">
<label class="menu-title">@L( "НАСТРОЙКИ", "SETTINGS" )</label>
<div class="settings-content">
<div class="setting-item lang-row">
<label class="setting-label">@L( "ЯЗЫК:", "LANGUAGE:" )</label>
<div class="lang-selector">
<button class="lang-btn @(CurrentLanguage == "EN" ? "active" : "")" onclick="@(() => SetLanguage("EN"))">EN</button>
<button class="lang-btn @(CurrentLanguage == "RU" ? "active" : "")" onclick="@(() => SetLanguage("RU"))">RU</button>
</div>
</div>
<div class="setting-item lang-row">
<label class="setting-label">@L( "СПАВН БОТОВ:", "SPAWN BOTS:" )</label>
<button class="lang-btn @(BotSpawner.EnableBots ? "active" : "")" onclick="@ToggleBots">
@(BotSpawner.EnableBots ? L( "ВКЛ", "ON" ) : L( "ВЫКЛ", "OFF" ))
</button>
</div>
<div class="setting-item lang-row">
<label class="setting-label">@L( "МУЗЫКА:", "MUSIC:" )</label>
<button class="lang-btn @(EnableMusic ? "active" : "")" onclick="@ToggleMusic">
@(EnableMusic ? L( "ВКЛ", "ON" ) : L( "ВЫКЛ", "OFF" ))
</button>
</div>
<label class="setting-item">@L( "ЧУВСТВИТЕЛЬНОСТЬ: 1.0", "SENSITIVITY: 1.0" )</label>
</div>
<button class="menu-btn" onclick="@CloseSettings">@L( "НАЗАД", "BACK" )</button>
</div>
</div>
}
</root>
@code {
[Property] public PushAbility PushAbility { get; set; }
public bool IsMenuOpen { get; set; } = true;
public bool IsSettingsOpen { get; set; } = false;
// Установлен английский язык по умолчанию
public static string CurrentLanguage { get; set; } = "EN";
public struct ChatMessage
{
public string Author { get; set; }
public string Text { get; set; }
}
public List<ChatMessage> CanvasMessages { get; set; } = new();
public bool IsChatOpen { get; set; } = false;
private TextEntry ChatInput { get; set; }
public struct PlayerInfo
{
public string Name { get; set; }
public int Score { get; set; }
public bool IsLocal { get; set; }
}
private string L( string ru, string en )
{
return CurrentLanguage == "RU" ? ru : en;
}
private bool IsReady => PushAbility?.IsReady ?? false;
protected override void OnEnabled()
{
base.OnEnabled();
AddMessage( L( "Система", "System" ), L( "Чат готов. Нажмите Enter для ввода.", "Chat ready. Press Enter to type." ) );
ApplyMouseState();
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( PushAbility == null )
{
PushAbility = Scene.GetAllComponents<PushAbility>()
.FirstOrDefault( x => !x.IsProxy );
}
if ( Input.EscapePressed || Input.Pressed( "menu" ) )
{
Input.EscapePressed = false;
ToggleMenu();
}
if ( Input.Pressed( "chat" ) || Input.Pressed( "enter" ) )
{
if ( !IsMenuOpen && !IsSettingsOpen )
{
if ( !IsChatOpen ) OpenChat();
}
}
ApplyMouseState();
}
private void SetLanguage( string lang )
{
CurrentLanguage = lang;
StateHasChanged();
}
private void ApplyMouseState()
{
bool needsMouse = IsMenuOpen || IsSettingsOpen || IsChatOpen;
Mouse.Visibility = needsMouse ? MouseVisibility.Visible : MouseVisibility.Hidden;
if ( !needsMouse && Panel != null )
{
Panel.Focus();
}
}
private void ToggleMenu()
{
if ( IsSettingsOpen ) CloseSettings();
else if ( IsMenuOpen ) StartGame();
else OpenMenu();
}
private void StartGame()
{
IsMenuOpen = false;
IsSettingsOpen = false;
ApplyMouseState();
}
private void OpenMenu()
{
IsMenuOpen = true;
IsSettingsOpen = false;
ApplyMouseState();
}
private void OpenSettings()
{
IsMenuOpen = false;
IsSettingsOpen = true;
ApplyMouseState();
}
private void CloseSettings()
{
IsSettingsOpen = false;
IsMenuOpen = true;
ApplyMouseState();
}
private void QuitGame()
{
Game.Close();
}
private int GetScore()
{
return ScoreManager.Instance?.Score ?? 0;
}
private float GetPercent()
{
if ( PushAbility == null ) return 0f;
return MathX.Clamp( PushAbility.CooldownProgress * 100f, 0f, 100f );
}
private void ToggleBots()
{
BotSpawner.EnableBots = !BotSpawner.EnableBots;
StateHasChanged();
}
private int GetHighScore()
{
return SaveManager.Current?.HighScore ?? 0;
}
private void OpenChat()
{
IsChatOpen = true;
ApplyMouseState();
StateHasChanged();
ChatInput?.Focus();
}
private void SendChatMessage()
{
if ( ChatInput == null || string.IsNullOrWhiteSpace( ChatInput.Text ) )
{
IsChatOpen = false;
ApplyMouseState();
return;
}
string name = Connection.Local?.DisplayName ?? L( "Вы", "You" );
AddMessage( name, ChatInput.Text );
ChatInput.Text = "";
IsChatOpen = false;
ApplyMouseState();
}
public void AddMessage( string author, string text )
{
CanvasMessages.Add( new ChatMessage { Author = author, Text = text } );
if ( CanvasMessages.Count > 6 )
{
CanvasMessages.RemoveAt( 0 );
}
StateHasChanged();
}
private IEnumerable<PlayerInfo> GetPlayerList()
{
if ( Connection.All != null && Connection.All.Any() )
{
foreach ( var conn in Connection.All )
{
bool isLocal = conn == Connection.Local;
int score = isLocal ? GetScore() : 0;
yield return new PlayerInfo
{
Name = string.IsNullOrEmpty( conn.DisplayName ) ? "Player" : conn.DisplayName,
Score = score,
IsLocal = isLocal
};
}
}
else
{
yield return new PlayerInfo
{
Name = L( "Вы", "You" ),
Score = GetScore(),
IsLocal = true
};
}
}
private int GetDeaths()
{
return ScoreManager.Instance?.Deaths ?? 0;
}
public static bool EnableMusic { get; set; } = true;
private void ToggleMusic()
{
EnableMusic = !EnableMusic;
MusicManager.Instance?.ToggleMusic( EnableMusic );
StateHasChanged();
}
protected override int BuildHash()
{
var hash = new HashCode();
hash.Add( GetPercent() );
hash.Add( IsReady );
hash.Add( EnableMusic );
hash.Add( GetScore() );
hash.Add( GetDeaths() );
hash.Add( IsMenuOpen );
hash.Add( ShopManager.Instance?.SelectedItem?.Id );
hash.Add( IsSettingsOpen );
hash.Add( CurrentLanguage );
hash.Add( IsChatOpen );
hash.Add( CanvasMessages.Count );
hash.Add( Connection.All?.Count() ?? 0 );
return hash.ToHashCode();
}
}