230 lines
8.4 KiB
C#
230 lines
8.4 KiB
C#
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<PrizeContainer> OnPrizesChanged;
|
||
public static event Action<bool> OnErrorStateChanged;
|
||
public static event Action OnPrizeIssued;
|
||
|
||
[Header("Звук")]
|
||
[SerializeField] private AudioClip prizeErrorSound;
|
||
[SerializeField] private List<AudioClip> PrizeNotificationSounds;
|
||
[SerializeField] private Notification prizeNotification;
|
||
|
||
private static PrizeSystemManager I;
|
||
private static bool prizingInProcess = false;
|
||
|
||
public static PrizeContainer PrizeContainer { get; private set; }
|
||
|
||
private static Queue<QrPrize> qrPrizes;
|
||
private static Queue<VitrinaPrize> 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<PrizeSet>()
|
||
{
|
||
new PrizeSet() { Prizes = new List<Prize> { new EmptyPrize() } },
|
||
new PrizeSet() { Prizes = new List<Prize> { new EmptyPrize() } },
|
||
new PrizeSet() { Prizes = new List<Prize> { new EmptyPrize() } },
|
||
new PrizeSet() { Prizes = new List<Prize> { new EmptyPrize() } },
|
||
new PrizeSet() { Prizes = new List<Prize> { new QrPrize("5000 руб") } }
|
||
}
|
||
};
|
||
|
||
[SerializeField] private List<PrizeImageMap> 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);
|
||
ReportPrizeIssued();
|
||
|
||
//хотя бы что то успешно выпало
|
||
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);
|
||
}
|
||
|
||
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.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;
|
||
}
|