Danro/Assets/Scripts/UI/LoseBannerController.cs
Danil Iarosh 3944534cd0
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat: Implement balance system and fix pause bug
- Добавлена система баланса игры (BalanceManager) для управления внутриигровой валютой
- Баланс начисляется за импульсы оплаты и списывается за начало/продолжение игры
- При старте игры весь внесенный баланс списывается, а жизни начисляются в соответствии с количеством оплат
- Добавлены проверки достаточности баланса для начала и продолжения игры
- Интегрирован BalanceManager с PaymentManager и GameManager
- Исправлен баг с возможностью снятия паузы при показе баннера проигрыша/победы
- Добавлена блокировка переключения паузы через IsActive флаг в PauseMenu
- Жизни больше не могут уйти в минус при повторной смерти во время показа баннера
- Настройки стоимости импульса, начала и продолжения игры берутся из SettingsManager
2026-02-09 11:31:34 +03:00

222 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using RR.Game2D.Core.Managers;
namespace RR.Common.UI
{
/// <summary>
/// Контроллер баннера проигрыша.
/// Модальное окно, которое отображается при поражении игрока.
/// </summary>
public class LoseBannerController : Modal
{
[Header("Элементы баннера проигрыша")]
[SerializeField] private TextMeshProUGUI loseText;
[SerializeField] private TextMeshProUGUI creditText;
[SerializeField] private Button continueButton;
[SerializeField] private TextMeshProUGUI continueButtonText;
[SerializeField] private float continueButtonCountdown = 30f;
[Header("Тексты")]
[SerializeField] private string creditTextFormat = "У вас осталось: {0}";
private RR.Common.Managers.BalanceManager _balanceManager;
private Coroutine _continueCountdownCoroutine;
private bool _isSubscribedToBalance = false;
/// <summary>
/// Событие, вызываемое при нажатии "Продолжить" или закрытии баннера.
/// </summary>
public event Action ContinueClicked;
protected override void Awake()
{
base.Awake();
if (continueButton)
{
continueButton.onClick.AddListener(OnContinueButtonClicked);
}
}
protected override void OnEnable()
{
base.OnEnable();
// Инициализируем BalanceManager
if (_balanceManager == null)
{
_balanceManager = GameManager.Instance?.Balance;
}
// Подписываемся на событие только если еще не подписаны
if (_balanceManager != null && !_isSubscribedToBalance)
{
int balance = _balanceManager.CurrentBalance;
if (creditText)
{
creditText.text = string.Format(creditTextFormat, balance);
}
_balanceManager.OnBalanceChanged.AddListener(UnlockContinueButton);
_isSubscribedToBalance = true;
}
}
protected override void OnDisable()
{
// Остановим корутину, если объект деактивируется
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
_continueCountdownCoroutine = null;
}
// Безопасная отписка от события
if (_balanceManager != null && _isSubscribedToBalance)
{
_balanceManager.OnBalanceChanged.RemoveListener(UnlockContinueButton);
_isSubscribedToBalance = false;
}
base.OnDisable();
}
/// <summary>
/// Показывает баннер проигрыша с указанным временем игры.
/// </summary>
/// <param name="gameTime">Время игры в секундах</param>
public void ShowLose(float gameTime)
{
// Инициализируем BalanceManager до открытия окна
if (_balanceManager == null)
{
_balanceManager = GameManager.Instance?.Balance;
}
// Подписываемся на событие изменения баланса, если еще не подписаны
if (_balanceManager != null && !_isSubscribedToBalance)
{
_balanceManager.OnBalanceChanged.AddListener(UnlockContinueButton);
_isSubscribedToBalance = true;
}
if (loseText)
{
loseText.text = $"Время игры: {TimeFormatHelper.FormatTime(gameTime)}";
}
if (creditText && _balanceManager != null)
{
creditText.text = string.Format(creditTextFormat, (object)_balanceManager.CurrentBalance);
}
if (continueButtonCountdown <= 0f)
{
ContinueClicked?.Invoke();
GameManager.Instance?.SetPause(false);
GameManager.Instance?.LoadScene("MainMenu", false);
return;
}
if (continueButton)
{
continueButton.gameObject.SetActive(true);
// Проверяем возможность продолжить игру через BalanceManager
bool canContinue = _balanceManager != null && _balanceManager.CanContinueGame();
continueButton.interactable = canContinue;
}
Open();
// Остановим предыдущую корутину, если есть
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
}
_continueCountdownCoroutine = StartCoroutine(ContinueCountdownCoroutine(continueButtonCountdown));
}
private IEnumerator ContinueCountdownCoroutine(float duration)
{
float elapsed = 0f;
int initialSeconds = Mathf.RoundToInt(duration);
UpdateContinueText(initialSeconds);
while (elapsed < duration)
{
float startTime = Time.unscaledTime;
yield return null;
while (Time.unscaledTime - startTime < 1.0f)
{
yield return null;
}
elapsed += 1f;
int remaining = Mathf.Max(0, Mathf.RoundToInt(duration - elapsed));
UpdateContinueText(remaining);
}
// Таймер истёк — закрываем баннер и выходим в меню
Close();
ContinueClicked?.Invoke();
if (GameManager.Instance)
{
GameManager.Instance.SetPause(false);
GameManager.Instance.LoadScene("MainMenu", false);
}
_continueCountdownCoroutine = null;
}
private void UpdateContinueText(int secondsRemaining)
{
if (continueButtonText)
{
continueButtonText.text = $"Продолжить? ({secondsRemaining})";
}
}
private void UnlockContinueButton(int newBalance)
{
if (_balanceManager == null) return;
// Проверяем возможность продолжить через BalanceManager
if (continueButton)
{
continueButton.interactable = _balanceManager.CanContinueGame();
}
// Обновляем текст баланса
if (creditText)
{
creditText.text = string.Format(creditTextFormat, newBalance);
}
}
private void OnContinueButtonClicked()
{
// При клике на "Продолжить" — остановим таймер и продолжим игру
if (_continueCountdownCoroutine != null)
{
StopCoroutine(_continueCountdownCoroutine);
_continueCountdownCoroutine = null;
}
Close();
ContinueClicked?.Invoke();
if (GameManager.Instance)
{
GameManager.Instance.SetPause(false);
GameManager.Instance.ContinueGame();
}
}
}
}