259 lines
9.9 KiB
C#
259 lines
9.9 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using UnityEditor.PackageManager;
|
||
using UnityEngine;
|
||
|
||
|
||
|
||
namespace PrizeSystem
|
||
{
|
||
/// <summary>
|
||
/// Система управления выдачей призов и ведения статистики игры.
|
||
/// Отвечает за процесс выдачи призов, подсчет запусков и наград.
|
||
/// </summary>
|
||
public class PrizeSystemManager : MonoBehaviour
|
||
{
|
||
[SerializeField] AudioClip prizeErrorSound;
|
||
|
||
[SerializeField] bool SoundNotification = true;
|
||
[SerializeField] List<AudioClip> PrizeNotificationSounds;
|
||
|
||
[SerializeField] Notification prizeNotification;
|
||
[SerializeField] VitrinaPanel vitrinaPanel;
|
||
|
||
|
||
public static event Action<List<Prize>> PrizesChanged;
|
||
public static event Action<bool> OnErrorStateChanged;
|
||
|
||
private static PrizeSystemManager instance;
|
||
private static bool prizing = false;
|
||
|
||
public static List<Prize> cachedPrizes { 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;
|
||
|
||
public static bool ErrorState => PlayerPrefs.GetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, 0) == 1;
|
||
|
||
|
||
|
||
|
||
//=========================== PUBLIC API ===========================//
|
||
public static Prize GetFirstNonEmptyPrizeAfter(Prize referencePrize)
|
||
{
|
||
if (referencePrize == null) return null;
|
||
|
||
int currentPrizeIndex = cachedPrizes.IndexOf(referencePrize);
|
||
if (currentPrizeIndex < 0) return null;
|
||
|
||
for (int i = currentPrizeIndex + 1; i < cachedPrizes.Count; i++)
|
||
{
|
||
var selectedPrize = cachedPrizes[i];
|
||
if (selectedPrize is not EmptyPrize)
|
||
{
|
||
return selectedPrize;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public void Initialize()
|
||
{
|
||
instance = this;
|
||
|
||
qrPrizes = new();
|
||
vitrinaPrizes = new();
|
||
}
|
||
|
||
public static QrPrize DequeueQrPrize() => HasQrPrizeToGive ? qrPrizes.Dequeue() : null;
|
||
public static VitrinaPrize DequeueVitrinaPrize() => HasVitrinaPrizeToGive ? vitrinaPrizes.Dequeue() : null;
|
||
|
||
|
||
public static void SetPrizesCache(List<Prize> prizes)
|
||
{
|
||
cachedPrizes = prizes;
|
||
PrizesChanged?.Invoke(prizes);
|
||
}
|
||
public static void GivePrize(Prize prize)
|
||
{
|
||
if (prize == null)
|
||
{
|
||
Debug.Log("Приз Null"); return;
|
||
}
|
||
//Если призы отключены в принципе, то не выдаем.
|
||
bool prizingEnabled = SettingsManager.GetBool(SettingKey.PRIZING);
|
||
if (!prizingEnabled) return;
|
||
|
||
|
||
|
||
Debug.Log($"Поступил заказ приз: {prize.Body}");
|
||
|
||
|
||
if (prize is EmptyPrize)
|
||
{
|
||
Debug.Log("Пустой приз. Возврат.");
|
||
return;
|
||
}
|
||
else if (prize is CountablePrize countablePrize)
|
||
{
|
||
instance.StartCoroutine(instance.PrizingProcess(countablePrize.Amount, countablePrize.Type));
|
||
}
|
||
else if (prize is VitrinaPrize vitrinaPrize)
|
||
{
|
||
vitrinaPrizes.Enqueue(vitrinaPrize);
|
||
}
|
||
else if (prize is QrPrize qrPrize)
|
||
{
|
||
qrPrizes.Enqueue(qrPrize);
|
||
}
|
||
}
|
||
|
||
//=========================== privates ===========================//
|
||
#region Приватные методы
|
||
//private string StartHopperCommand => ComWrapper.BoardVersion switch { 1 => "303", 2 => "301", _ => "303" };
|
||
//private string StopHopperCommand => ComWrapper.BoardVersion switch { 1 => "302", 2 => "300", _ => "302" };
|
||
private string StartHopperCommand => "303";
|
||
private string StopHopperCommand => "302";
|
||
private IEnumerator PrizingProcess(int amount, CountablePrizeType Type)
|
||
{
|
||
if (prizing)
|
||
{
|
||
Debug.LogError("Уже идет выдача приза. Повторная выдача отключена");
|
||
yield break;
|
||
}
|
||
prizing = 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;
|
||
|
||
Debug.Log($"Включаю мотор хоппера: {StartHopperCommand}");
|
||
ComWrapper.Send(StartHopperCommand);//включаем мотор
|
||
|
||
PlayerPrefs.SetInt("PrizeGivenBuffer", 0);//подготовка буфера
|
||
Debug.Log($"Буфер подготовлен. Значение: {PlayerPrefs.GetInt("PrizeGivenBuffer")}");
|
||
|
||
float startTime = Time.time;
|
||
bool success = false;
|
||
float timeout = 10;
|
||
while (Time.time - startTime < timeout)
|
||
{
|
||
if (PlayerPrefs.GetInt("PrizeGivenBuffer", 0) == 1)
|
||
{
|
||
Debug.Log($"Считан приз. Значение буфера {PlayerPrefs.GetInt("PrizeGivenBuffer")}");
|
||
success = true;
|
||
break;
|
||
}
|
||
yield return null;
|
||
}
|
||
|
||
Debug.Log($"Выключаю мотор: {StopHopperCommand}");
|
||
ComWrapper.Send(StopHopperCommand);
|
||
Debug.Log("Закончил. Успех: " + success);
|
||
|
||
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();
|
||
}
|
||
|
||
prizing = false;
|
||
}
|
||
|
||
|
||
public static void SetPrizingError(bool error)
|
||
{
|
||
PlayerPrefs.SetInt(PrefsKeyVault.PRIZING_ERROR_REGISTRED, error ? 1 : 0);
|
||
OnErrorStateChanged?.Invoke(error);
|
||
}
|
||
|
||
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 string GetPrizesCounterNullableString()
|
||
{
|
||
StringBuilder sb = new();
|
||
|
||
sb.Append($"Х: {PlayerPrefs.GetInt(PrefsKeyVault.HOPPER_GIVEN_COUNTER + "Nullable", 0)}. ");
|
||
sb.Append($"Т: {PlayerPrefs.GetInt(PrefsKeyVault.TICKET_GIVEN_COUNTER + "Nullable", 0)}. ");
|
||
sb.Append($"М: {PlayerPrefs.GetInt(PrefsKeyVault.MARBLES_GIVEN_COUNTER + "Nullable", 0)}. ");
|
||
sb.Append($"С: {PlayerPrefs.GetInt(PrefsKeyVault.SPECIAL_GIVEN_COUNTER + "Nullable", 0)}. ");
|
||
|
||
return sb.ToString();
|
||
}
|
||
|
||
public static string GetPrizesCounterString()
|
||
{
|
||
StringBuilder sb = new();
|
||
|
||
sb.Append($"Х: {PlayerPrefs.GetInt(PrefsKeyVault.HOPPER_GIVEN_COUNTER, 0)}. ");
|
||
sb.Append($"Т: {PlayerPrefs.GetInt(PrefsKeyVault.TICKET_GIVEN_COUNTER, 0)}. ");
|
||
sb.Append($"М: {PlayerPrefs.GetInt(PrefsKeyVault.MARBLES_GIVEN_COUNTER, 0)}. ");
|
||
sb.Append($"С: {PlayerPrefs.GetInt(PrefsKeyVault.SPECIAL_GIVEN_COUNTER, 0)}. ");
|
||
|
||
return sb.ToString();
|
||
}
|
||
|
||
private void SoundNotificationIfNeeds()
|
||
{
|
||
if (!SoundNotification) return;
|
||
if (PrizeNotificationSounds == null || PrizeNotificationSounds.Count == 0) return;
|
||
|
||
int random = UnityEngine.Random.Range(0, PrizeNotificationSounds.Count);
|
||
AudioClip notification = PrizeNotificationSounds[random];
|
||
SoundManager.instance.playClip(notification);
|
||
}
|
||
#endregion
|
||
}
|
||
} |