using CharacterSystem; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Serialization; public class EndGameHandler : MonoBehaviour { [SerializeField, FormerlySerializedAs("winPanel")] private PveWinPanel _winPanel; [SerializeField, FormerlySerializedAs("lossPanel")] private PveLossPanel _lossPanel; [SerializeField, FormerlySerializedAs("pvpWinPanel")] private PvpWinPanel _pvpWinPanel; [SerializeField, FormerlySerializedAs("drawPanel")] private PveLossPanel _drawPanel; [SerializeField] private float _resultPanelDelay = 3f; private const float WinAnimationFrameRate = 40f; private Coroutine _resultDelayCoroutine; private Coroutine _winAnimationCoroutine; private void OnDisable() { if (_winAnimationCoroutine != null) { StopCoroutine(_winAnimationCoroutine); _winAnimationCoroutine = null; } if (_resultDelayCoroutine != null) { StopCoroutine(_resultDelayCoroutine); _resultDelayCoroutine = null; } } public void HandleEndGame(Team lastPlayer, GameMode gameMode, CheckResult lastResult) { Debug.Log("Конец игры"); GameManager.Instance.turnTracker.EnableTimer(false); if (lastResult.Draw) DrawHandler(gameMode); else WinHandler(lastPlayer, gameMode, lastResult.WinningIndexes); } public void HandlePveTimeout() { MachineCountersService.RecordBotResult(false); EventBus.TriggerEvent(GameEvent.BotWin); ShowResultAfterDelay(() => _lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss)); } private void DrawHandler(GameMode gameMode) { if (gameMode == GameMode.pve) { EventBus.TriggerEvent(GameEvent.Draw); ShowResultAfterDelay(() => _drawPanel.Open(GameManager.Instance.ContinueAfterPveDraw)); } else { GameManager gameManager = GameManager.Instance; ShowResultAfterDelay(() => _pvpWinPanel.Open( Team.None, false, gameManager.player1score, gameManager.player2score, gameManager.ContinueAfterPvpRound)); } } private void WinHandler(Team winner, GameMode gameMode, HashSet<(int row, int col)> winChipsCoords) { Debug.Log($"Победа {winner}; Режим {gameMode}"); PlayWinChipsAnimation(winChipsCoords); if (gameMode == GameMode.pve) { if (winner == Team.Player1) { LightSystem.SpecialEffect(42, 2); MachineCountersService.RecordBotResult(true); EventBus.TriggerEvent(GameEvent.PlayerWin); ShowResultAfterDelay(ShowPveWinResult); } else { MachineCountersService.RecordBotResult(false); EventBus.TriggerEvent(GameEvent.BotWin); ShowResultAfterDelay(() => _lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss)); } } else { GameManager gameManager = GameManager.Instance; DualAvatarController.Instance?.PlayWin(winner); gameManager.IncreaseScore(winner); bool isMatchWin = gameManager.HasPvpMatchWinner(winner); Action restartAction = isMatchWin ? gameManager.RestartPvpMatch : gameManager.ContinueAfterPvpRound; ShowResultAfterDelay(() => _pvpWinPanel.Open( winner, isMatchWin, gameManager.player1score, gameManager.player2score, restartAction)); } } private void ShowPveWinResult() { if (GameManager.Instance.TryStartPvePrizeFlow()) return; bool isLastBot = CharactersController.CharacterIndex == CharactersController.CharactersAmount - 1; if (isLastBot) GameManager.Instance.ShowFinalVictoryNameInput(); else _winPanel.Open(); } private void ShowResultAfterDelay(Action showResult) { if (_resultDelayCoroutine != null) StopCoroutine(_resultDelayCoroutine); _resultDelayCoroutine = StartCoroutine(ShowResultAfterDelayCoroutine(showResult)); } private IEnumerator ShowResultAfterDelayCoroutine(Action showResult) { yield return new WaitForSecondsRealtime(Mathf.Max(0f, _resultPanelDelay)); _resultDelayCoroutine = null; showResult?.Invoke(); } private void PlayWinChipsAnimation(HashSet<(int row, int col)> winChipsCoords) { Chip[,] grid = Board.Instance.Grid; Chip[] winChips = new Chip[winChipsCoords.Count]; int chipIndex = 0; foreach ((int row, int col) winCoord in winChipsCoords) { Chip chip = grid[winCoord.col, winCoord.row]; winChips[chipIndex++] = chip; chip.WinAnimation(); } if (winChips.Length == 0) return; if (_winAnimationCoroutine != null) StopCoroutine(_winAnimationCoroutine); _winAnimationCoroutine = StartCoroutine(PlayWinDotsAnimation(winChips)); } private IEnumerator PlayWinDotsAnimation(Chip[] winChips) { int frameCount = winChips[0].WinAnimationFrameCount; WaitForSeconds frameDelay = new WaitForSeconds(1f / WinAnimationFrameRate); for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { for (int chipIndex = 0; chipIndex < winChips.Length; chipIndex++) winChips[chipIndex].SetWinAnimationFrame(frameIndex); yield return frameDelay; } _winAnimationCoroutine = null; } }