using PrizeSystem; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using static PrizeView; namespace PrizeSystem { public class PrizeSystemManager : MonoBehaviour { public static event Action OnPrizesChanged; public static event Action OnErrorStateChanged; public static event Action OnPrizeIssued; public static event Action PrizeIssueFinished; [Header("Звук")] [SerializeField] private AudioClip prizeErrorSound; [SerializeField] private List PrizeNotificationSounds; [SerializeField] private Notification prizeNotification; private static PrizeSystemManager I; private static bool prizingInProcess = false; public static PrizeContainer PrizeContainer { get; private set; } private static Queue qrPrizes; private static Queue vitrinaPrizes; public static bool HasQrPrizeToGive => qrPrizes.Count > 0; public static bool HasVitrinaPrizeToGive => vitrinaPrizes.Count > 0; private string StartHopperCommand => "303"; private string StopHopperCommand => "302"; public static bool ErrorState => PlayerPrefs.GetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, 0) == 1; private PrizeContainer _defaultPrizes = new PrizeContainer { Sets = new List() { new PrizeSet() { Prizes = new List { new EmptyPrize() } }, new PrizeSet() { Prizes = new List { new EmptyPrize() } }, new PrizeSet() { Prizes = new List { new EmptyPrize() } }, new PrizeSet() { Prizes = new List { new EmptyPrize() } }, new PrizeSet() { Prizes = new List { new QrPrize("5000 руб") } } } }; [SerializeField] private List iconsMap; [SerializeField] private Sprite defaultIcon; public void Initialize() { I = this; PrizeStockService.Initialize(); PrizeSerializer.Initialize(_defaultPrizes); PrizeContainer = PrizeSerializer.LoadFromFile(); qrPrizes = new(); vitrinaPrizes = new(); } public static QrPrize DequeueQrPrize() => HasQrPrizeToGive ? qrPrizes.Dequeue() : null; public static VitrinaPrize DequeueVitrinaPrize() => HasVitrinaPrizeToGive ? vitrinaPrizes.Dequeue() : null; public static void SavePrizes() { OnPrizesChanged?.Invoke(PrizeContainer); } public static void GivePrize(Prize prize) { bool prizingEnabled = SettingsManager.GetBool(SettingKey.PRIZING); if (prizingEnabled == false) { PrizeIssueFinished?.Invoke(false); return; } if (prize == null) { Debug.Log("Приз Null"); PrizeIssueFinished?.Invoke(false); return; } if (prize is EmptyPrize) { Debug.Log("Пустой приз. Возврат."); PrizeIssueFinished?.Invoke(false); return; } else if (prize is CountablePrize countablePrize) { I.StartCoroutine(I.GiveCountablePrizeCoroutine(countablePrize.Amount, countablePrize.Type)); } else if (prize is VitrinaPrize vitrinaPrize) { vitrinaPrizes.Enqueue(vitrinaPrize); } else if (prize is QrPrize qrPrize) { qrPrizes.Enqueue(qrPrize); } else { PrizeIssueFinished?.Invoke(false); } } private IEnumerator GiveCountablePrizeCoroutine(int amount, CountablePrizeType Type) { if (prizingInProcess) { Debug.LogError("Уже идет выдача приза. Повторная выдача отключена"); PrizeIssueFinished?.Invoke(false); yield break; } prizingInProcess = true; Debug.Log($"Выдача приза {Type}. Количество: {amount}"); bool atLeastOnePrize = false; for (int i = 0; i < amount; i++) { bool prizeWhenError = SettingsManager.GetBool(SettingKey.PRIZING_WHEN_ERROR); bool errorRegistred = PlayerPrefs.GetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, 0) == 1; if (errorRegistred && !prizeWhenError) break; PlayerPrefs.SetInt(PrefsKeyVault.PRIZE_GIVEN_BUFFER, 0); ComWrapper.Send(StartHopperCommand); float startTime = Time.time; bool success = false; float timeout = 10; while (Time.time - startTime < timeout) { if (PlayerPrefs.GetInt(PrefsKeyVault.PRIZE_GIVEN_BUFFER, 0) == 1) { success = true; break; } yield return null; } ComWrapper.Send(StopHopperCommand); if (success) { PrizeStockService.RecordSuccessfulCountableIssue(); LightSystem.SpecialEffect(40, 2); //Счетчики IncreasePrizeCounters(Type); ReportPrizeIssued(); //хотя бы что то успешно выпало atLeastOnePrize = true; } else { SetPrizingError(true); SoundManager.instance.PlaySfx(prizeErrorSound); } } if (atLeastOnePrize) { NotificationSystem.instance.Notificate(prizeNotification); SoundNotificationIfNeeds(); } prizingInProcess = false; PrizeIssueFinished?.Invoke(atLeastOnePrize); } public static void SetPrizingError(bool error) { PlayerPrefs.SetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, error ? 1 : 0); OnErrorStateChanged?.Invoke(error); } private void IncreasePrizeCounters(CountablePrizeType Type) { string prizeCounterKey = Type switch { CountablePrizeType.Marbles => PrefsKeyVault.MARBLES_GIVEN_COUNTER, CountablePrizeType.Hopper => PrefsKeyVault.HOPPER_GIVEN_COUNTER, CountablePrizeType.Hopper2 => PrefsKeyVault.HOPPER_GIVEN_COUNTER, CountablePrizeType.Ticket => PrefsKeyVault.TICKET_GIVEN_COUNTER, _ => "none" }; string prizeCounterKeyNullable = prizeCounterKey + "Nullable"; PlayerPrefs.SetInt(prizeCounterKey, PlayerPrefs.GetInt(prizeCounterKey, 0) + 1); PlayerPrefs.SetInt(prizeCounterKeyNullable, PlayerPrefs.GetInt(prizeCounterKeyNullable, 0) + 1); } public static void ResetPrizeCounters() { PlayerPrefs.SetInt(PrefsKeyVault.HOPPER_GIVEN_COUNTER + "Nullable", 0); PlayerPrefs.SetInt(PrefsKeyVault.MARBLES_GIVEN_COUNTER + "Nullable", 0); PlayerPrefs.SetInt(PrefsKeyVault.TICKET_GIVEN_COUNTER + "Nullable", 0); PlayerPrefs.SetInt(PrefsKeyVault.SPECIAL_GIVEN_COUNTER + "Nullable", 0); } public static void ReportPrizeIssued() { PlayerPrefs.SetInt( PrefsKeyVault.PRIZES_GIVEN_COUNTER, PlayerPrefs.GetInt(PrefsKeyVault.PRIZES_GIVEN_COUNTER, 0) + 1); PlayerPrefs.SetInt( PrefsKeyVault.PRIZES_GIVEN_COUNTER_NUL, PlayerPrefs.GetInt(PrefsKeyVault.PRIZES_GIVEN_COUNTER_NUL, 0) + 1); OnPrizeIssued?.Invoke(); } private void SoundNotificationIfNeeds() { if (PrizeNotificationSounds == null || PrizeNotificationSounds.Count == 0) return; int random = UnityEngine.Random.Range(0, PrizeNotificationSounds.Count); AudioClip notification = PrizeNotificationSounds[random]; SoundManager.instance.PlaySfx(notification); } public static Sprite GetPrizeIcon(PrizeType prizeType) { foreach (var mapItem in I.iconsMap) if (mapItem.prizeType == prizeType) return mapItem.sprite; return I.defaultIcon; } } } [Serializable] public struct PrizeImageMap { public PrizeType prizeType; public Sprite sprite; }