using System; using System.Collections.Generic; using System.Linq; using LuckerGame.Enums; using LuckerGame.Events; using Sandbox; using Sandbox.UI; namespace LuckerGame.Entities; /// /// Manages rounds. Starting, stopping, triggering minigames from the manager, etc /// public partial class RoundManager : Entity { /// /// The minigame manager we should be using to manage minigames /// private MinigameManager MinigameManager { get; set; } /// /// This percentage of the lobby must be ready to start the countdown for round start /// private const float RequiredReadyPercent = .5f; /// /// The number of seconds from the timer starting before the round starts /// private const float RoundStartCountdownSeconds = 10f; /// /// The state of the current round /// [Net] public RoundState RoundState { get; private set; } #region Countdown State /// /// How long since we started counting down to game start. Only useful if in the StartCountdown state. /// [Net] public TimeSince TimeSinceCountdownStarted { get; set; } /// /// The number of seconds left in the countdown. Only useful if in the StartCountdown state. /// public int SecondsLeftInCountdown => (int)Math.Ceiling( RoundStartCountdownSeconds - TimeSinceCountdownStarted ); #endregion #region In Progress State private const int MinigamesPerRound = 1; private int MinigamesLeftInRound { get; set; } private List Players { get; set; } #endregion /// public override void Spawn() { base.Spawn(); RoundState = RoundState.NotStarted; MinigameManager = new MinigameManager(); } /// /// Fires once per server tick /// [GameEvent.Tick.Server] public void Tick() { if ( RoundState == RoundState.StartCountdown && TimeSinceCountdownStarted > RoundStartCountdownSeconds ) { Log.Info( "Starting round" ); StartRound(); } if ( RoundState == RoundState.InProgress ) { MinigameManager.Tick(); } } /// /// Is triggered whenever a player readies up /// /// the player that readied up, discarded [LuckerEvent.PlayerReady] public void HandlePlayerReady( Lucker readyLucker, bool ready ) { if ( RoundState != RoundState.NotStarted && RoundState != RoundState.StartCountdown ) { return; } Log.Info( $"{readyLucker.Client.Name} set ready to {ready}" ); var message = $"{readyLucker.Client.Name} is {(ready ? "now ready." : "no longer ready.")}"; ChatBox.AddInformation( To.Everyone, message ); var players = All.OfType().ToList(); var readiedCount = players.Count( player => player.Ready ); var totalCount = players.Count; if ( (float)readiedCount / totalCount > RequiredReadyPercent && RoundState == RoundState.NotStarted ) { Log.Info( "Countdown started" ); RoundState = RoundState.StartCountdown; TimeSinceCountdownStarted = 0; } else if ( (float)readiedCount / totalCount <= RequiredReadyPercent && RoundState == RoundState.StartCountdown ) { Log.Info( "Countdown ended" ); RoundState = RoundState.NotStarted; } } private void StartRound() { if ( RoundState == RoundState.InProgress ) { Log.Warning( "Attempted to start round while one was in progress" ); return; } RoundState = RoundState.InProgress; Players = All.OfType().ToList(); MinigameManager.StartRandomMinigame( Players ); } [ConCmd.Server("start_round")] public static void ForceStart() { Entity.All.OfType().FirstOrDefault()?.StartRound(); } }