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; [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; 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) return; if (prize == null) { Debug.Log("Приз Null"); return; } if (prize is EmptyPrize) { Debug.Log("Пустой приз. Возврат."); 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); } } private IEnumerator GiveCountablePrizeCoroutine(int amount, CountablePrizeType Type) { if (prizingInProcess) { Debug.LogError("Уже идет выдача приза. Повторная выдача отключена"); yield break; } prizingInProcess = true; Debug.Log($"Выдача приза {Type}. Количество: {amount}"); bool atLeastOnePrize = false; for (int i = 0; i < amount; i++) { bool noPrizWhenError = SettingsManager.GetBool(SettingKey.PRIZING_WHEN_ERROR); bool errorRegistred = PlayerPrefs.GetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, 0) == 1; if (errorRegistred && noPrizWhenError) yield 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) { //контроль остатков int prizesCount = PlayerPrefs.GetInt(PrefsKeyVault.PRIZES_AVAILABLE); prizesCount = Mathf.Clamp(prizesCount - 1, 0, 9999); PlayerPrefs.SetInt(PrefsKeyVault.PRIZES_AVAILABLE, prizesCount); //Счетчики IncreasePrizeCounters(Type); //хотя бы что то успешно выпало atLeastOnePrize = true; } else { SetPrizingError(true); SoundManager.instance.playClip(prizeErrorSound); } } if (atLeastOnePrize) { NotificationSystem.instance.Notificate(prizeNotification); SoundNotificationIfNeeds(); } prizingInProcess = false; } 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); } private void SoundNotificationIfNeeds() { if (PrizeNotificationSounds == null || PrizeNotificationSounds.Count == 0) return; int random = UnityEngine.Random.Range(0, PrizeNotificationSounds.Count); AudioClip notification = PrizeNotificationSounds[random]; SoundManager.instance.playClip(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; }