ArenaRoundManeger1.cs

Round manager component for an arena game. It tracks round state (waiting, countdown, in-game, round end), transitions based on timers and player count, logs state changes, respawns players at a spawn point, and disables eliminated players.

File Access
using Sandbox;
using System.Linq;

public enum ArenaRoundState
{
    WaitingForPlayers,
    Countdown,
    InGame,
    RoundEnd
}

public sealed class ArenaRoundManager : Component
{
    [Property] public float CountdownDuration { get; set; } = 5.0f;
    [Property] public float RoundDuration { get; set; } = 60.0f;
    [Property] public float EndPauseDuration { get; set; } = 4.0f;

    public ArenaRoundState CurrentState { get; private set; } = ArenaRoundState.WaitingForPlayers;
    public TimeUntil StateTimer { get; private set; }
    private SpawnPoint _spawnPoint;

    protected override void OnStart()
    {
        _spawnPoint = Scene.GetAllComponents<SpawnPoint>().FirstOrDefault();
        SetState( ArenaRoundState.WaitingForPlayers );
    }

    protected override void OnUpdate()
    {
        switch ( CurrentState )
        {
            case ArenaRoundState.WaitingForPlayers:
                if ( Connection.All.Count >= 1 )
                {
                    SetState( ArenaRoundState.Countdown );
                }
                break;

            case ArenaRoundState.Countdown:
                if ( StateTimer )
                {
                    SetState( ArenaRoundState.InGame );
                }
                break;

            case ArenaRoundState.InGame:
                if ( StateTimer )
                {
                    SetState( ArenaRoundState.RoundEnd );
                }
                break;

            case ArenaRoundState.RoundEnd:
                if ( StateTimer )
                {
                    SetState( ArenaRoundState.WaitingForPlayers );
                }
                break;
        }
    }

    private void SetState( ArenaRoundState newState )
    {
        CurrentState = newState;

        switch ( newState )
        {
            case ArenaRoundState.WaitingForPlayers:
                Log.Info( "[ArenaRoundManager] Ожидание игроков..." );
                break;

            case ArenaRoundState.Countdown:
                StateTimer = CountdownDuration;
                Log.Info( $"[ArenaRoundManager] Отсчёт! До старта: {CountdownDuration} сек." );
                break;

            case ArenaRoundState.InGame:
                RespawnPlayers();
                StateTimer = RoundDuration;
                Log.Info( "[ArenaRoundManager] РАУНД НАЧАЛСЯ!" );
                break;

            case ArenaRoundState.RoundEnd:
                StateTimer = EndPauseDuration;
                Log.Info( "[ArenaRoundManager] Раунд окончен!" );
                break;
        }
    }

    public void OnPlayerEliminated( GameObject player )
    {
        if ( CurrentState != ArenaRoundState.InGame || !player.IsValid() ) return;

        player.Enabled = false;
        int remainingPlayers = Scene.GetAllComponents<PlayerHealth>()
            .Count( health => health.IsValid() && health.GameObject.IsValid() &&
                              health.GameObject.Enabled && !health.IsDead && !health.IsDowned );

        if ( remainingPlayers <= 1 )
        {
            SetState( ArenaRoundState.RoundEnd );
        }
    }

    private void RespawnPlayers()
    {
        Vector3 spawnPosition = _spawnPoint.IsValid() ? _spawnPoint.WorldPosition : new Vector3( 0, 0, 250 );

        foreach ( var health in Scene.GetAllComponents<PlayerHealth>() )
        {
            if ( !health.IsValid() || !health.GameObject.IsValid() ) continue;

            health.GameObject.Enabled = true;
            health.GameObject.WorldPosition = spawnPosition;
            health.Respawn();
        }
    }
}