Danil Iarosh 301e4be47d refactor: LevelFinish — выдача приза и показ QR разделены
- Добавлен LevelFinish.cs: новый компонент финиша уровня
  - выдача маленького приза через PrizeSystemManager (учитывает enableHopper)
  - настройки: enablePrizeOnFinish, prizeEnabledSettingKey, prizeDelay, debugMode
  - защита от двойной выдачи (_prizeGiven)
- PlayerController: закомментирован старый переход на следующий уровень по тегу 'Finish'
  (теперь за это отвечает LevelFinish)
- QRCodeUIController: помечен [Obsolete], QR-коды показываются только при победе
  через WinBannerController.ShowWin() -> PrizeSystemManager.GetQRCodes()
- Finish.prefab: добавлен компонент LevelFinish (enablePrizeOnFinish=true, prizeDelay=0)
- Сцена 1-1: переопределён enablePrizeOnFinish=false для финиша промежуточного уровня
- Сцена 1-3: minor update
- MainMenu: правки якорей UI-элементов и активация скрытого объекта
2026-02-19 15:15:16 +03:00

149 lines
6.3 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.Collections;
using RR.Common.Managers;
using RR.Game2D.Core.Managers;
using UnityEngine;
namespace RR.Common.Controls
{
/// <summary>
/// Система управления выдачей призов и ведения статистики игры.
/// Отвечает за процесс выдачи призов, подсчет запусков и наград.
/// </summary>
public class PrizeSystem : MonoBehaviour
{
private static PrizeSystem Instance { get; set; }
private static Coroutine prizeCoroutine;
private static bool _prizing;
private static bool _lastPrizeSuccess = true;
public static readonly string key_starts = "STARTS";
public static readonly string key_startsNul = "STARTSNUL";
public static readonly string key_prizesgiven = "PRIZESGIVEN";
public static readonly string key_prizesgivenNul = "PRIZESGIVENNUL";
[SerializeField] AudioClip prizeErrorSound;
//===========================start: PUBLIC API===========================//
/// <summary>
/// Возвращает true, если последняя выдача приза прошла успешно, false - если была ошибка.
/// </summary>
public static bool WasLastPrizeSuccessful => _lastPrizeSuccess;
/// <summary>
/// Возвращает true, если в данный момент идет процесс выдачи приза.
/// </summary>
public static bool IsPrizing => _prizing;
/// <summary>
/// Инициализирует систему призов и счетчики статистики.
/// Должен быть вызван один раз при запуске приложения.
/// </summary>
/// <remarks>
/// Выполняет:
/// - Установку статического экземпляра (singleton)
/// - Инициализацию счетчиков в PlayerPrefs если они отсутствуют
/// - Подготовку системы к работе
/// </remarks>
public void Initialize()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
InitCounters();
}
/// <summary>
/// Запускает процесс выдачи физического приза игроку.
/// Проверяет настройки и текущее состояние перед началом выдачи.
/// </summary>
/// <remarks>
/// Условия для выдачи приза:
/// - В настройках включена выдача призов при игре с ботом
/// - В данный момент не выполняется другая выдача приза
///
/// Процесс выдачи:
/// - Включает мотор хопера
/// - Ожидает подтверждения выдачи от датчиков (10 сек таймаут)
/// - Выключает мотор по завершению
/// - Обновляет счетчики выданных призов
/// - Воспроизводит звук ошибки при неудаче
/// </remarks>
public static void GivePrize()
{
// bool settingEnabled = SettingsManager.instance.GetSettingValue("Выдача призов при игре с ботом") == "Выдавать";
//
// if (!settingEnabled) { DebugWindow.Message("Выдача приза отключена в настройках"); return; }
if (_prizing)
{
GameManager.Logger.Log("PrizeSystem", "Уже идет выдача приза. Не спамь кнопку.");
return;
}
//
// DebugWindow.Message("Выдаю приз");
if (prizeCoroutine != null) Instance.StopCoroutine(prizeCoroutine);
prizeCoroutine = Instance.StartCoroutine(Instance.Prize());
}
//===========================end: PUBLIC API===========================//
#region Приватные методы
private IEnumerator Prize()
{
_prizing = true;
// DebugWindow.Message("Начинаю выдачу");
const float timeout = 10; //сек
ComWrapper.Send("301");//включаем мотор
float startTime = Time.time;
bool success = false;
PlayerPrefs.SetInt("PrizeGivenBuffer", 0);//На всякий случай подготовка буфера
//проверить где он пишется
while (Time.time - startTime < timeout)
{
if (PlayerPrefs.GetInt("PrizeGivenBuffer", 0) == 1)
{
success = true;
IncreasePrizeCounters();
break;
}
yield return null;
}
//Выключаем мотор
ComWrapper.Send("300");
// DebugWindow.Message("Закончил. Успех: " + success);
_lastPrizeSuccess = success;
_prizing = false;
if (!success) AudioManager.Instance.PlaySfx(prizeErrorSound);
}
private static void IncreasePrizeCounters()
{
PlayerPrefs.SetInt(key_prizesgiven, PlayerPrefs.GetInt(key_prizesgiven) + 1);
PlayerPrefs.SetInt(key_prizesgivenNul, PlayerPrefs.GetInt(key_prizesgivenNul) + 1);
}
private static void InitCounters()
{
if (!PlayerPrefs.HasKey(key_starts)) PlayerPrefs.SetInt(key_starts, 0);
if (!PlayerPrefs.HasKey(key_startsNul)) PlayerPrefs.SetInt(key_startsNul, 0);
if (!PlayerPrefs.HasKey(key_prizesgiven)) PlayerPrefs.SetInt(key_prizesgiven, 0);
if (!PlayerPrefs.HasKey(key_prizesgivenNul)) PlayerPrefs.SetInt(key_prizesgivenNul, 0);
}
#endregion
}
}