chip-gameV3/Assets/Scripts/PrizeSystem/PrizeSystemManager.cs
2026-07-14 11:14:13 +03:00

268 lines
10 KiB
C#
Raw Permalink 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;
using System.Collections;
using System.Collections.Generic;
using System.Text;
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 string key_cash = "STARTS";
public static string key_cashNul = "STARTSNUL";
public static string key_prizesgiven = "PRIZESGIVEN";
public static string key_prizesgivenNul = "PRIZESGIVENNUL";
public static string HopperPrizeCounter = "HopperCounter";
public static string MarblesPrizeCounter = "MarblesCounter";
public static string TicketPrizeCounter = "TicketCounter";
public static string SpecialPrizeCounter = "SpecialCounter";
public static event Action<List<Prize>> PrizesChanged;
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 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;
InitCounters();
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("Prizing", false);
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;
Logger.Instance.Log($"Выдача приза {Type}. Количество: {amount}");
bool atLeastOnePrize = false;
for (int i = 0; i < amount; i++)
{
bool noPrizWhenError = SettingsManager.GetBool("PrizingWhenError", true);
bool errorRegistred = PlayerPrefs.GetInt(KeyVault.PRIZING_ERROR_REGISTRED, 0) == 1;
if (errorRegistred && noPrizWhenError) yield break;
Logger.Instance.Log($"Включаю мотор хоппера: {StartHopperCommand}");
ComWrapper.Send(StartHopperCommand);//включаем мотор
PlayerPrefs.SetInt("PrizeGivenBuffer", 0);//подготовка буфера
Logger.Instance.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)
{
Logger.Instance.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(KeyVault.PRIZES_AVAILABLE);
prizesCount = Mathf.Clamp(prizesCount - 1, 0, 9999);
PlayerPrefs.SetInt(KeyVault.PRIZES_AVAILABLE, prizesCount);
//Счетчики
IncreasePrizeCounters(Type);
//хотя бы что то успешно выпало
atLeastOnePrize = true;
}
else
{
PlayerPrefs.SetInt(KeyVault.PRIZING_ERROR_REGISTRED, 1);
SoundManager.instance.playClip(prizeErrorSound);
}
}
if (atLeastOnePrize)
{
NotificationSystem.instance.Notificate(prizeNotification);
SoundNotificationIfNeeds();
}
prizing = false;
}
void IncreasePrizeCounters(CountablePrizeType Type)
{
string prizeCounterKey = Type switch
{
CountablePrizeType.Marbles => MarblesPrizeCounter,
CountablePrizeType.Hopper => HopperPrizeCounter,
CountablePrizeType.Hopper2 => HopperPrizeCounter,
CountablePrizeType.Ticket => TicketPrizeCounter,
_ => "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(HopperPrizeCounter + "Nullable", 0);
PlayerPrefs.SetInt(MarblesPrizeCounter + "Nullable", 0);
PlayerPrefs.SetInt(TicketPrizeCounter + "Nullable", 0);
PlayerPrefs.SetInt(SpecialPrizeCounter + "Nullable", 0);
}
public static string GetPrizesCounterNullableString()
{
StringBuilder sb = new();
sb.Append($"Х: {PlayerPrefs.GetInt(HopperPrizeCounter + "Nullable", 0)}. ");
sb.Append($"Т: {PlayerPrefs.GetInt(TicketPrizeCounter + "Nullable", 0)}. ");
sb.Append($"М: {PlayerPrefs.GetInt(MarblesPrizeCounter + "Nullable", 0)}. ");
sb.Append($"С: {PlayerPrefs.GetInt(SpecialPrizeCounter + "Nullable", 0)}. ");
return sb.ToString();
}
public static string GetPrizesCounterString()
{
StringBuilder sb = new();
sb.Append($"Х: {PlayerPrefs.GetInt(HopperPrizeCounter, 0)}. ");
sb.Append($"Т: {PlayerPrefs.GetInt(TicketPrizeCounter, 0)}. ");
sb.Append($"М: {PlayerPrefs.GetInt(MarblesPrizeCounter, 0)}. ");
sb.Append($"С: {PlayerPrefs.GetInt(SpecialPrizeCounter, 0)}. ");
return sb.ToString();
}
void InitCounters()
{
if (!PlayerPrefs.HasKey(key_cash)) PlayerPrefs.SetInt(key_cash, 0);
if (!PlayerPrefs.HasKey(key_cashNul)) PlayerPrefs.SetInt(key_cashNul, 0);
}
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
}
}