sega 826ff5782a Доработать игровые режимы, призы и настройки
Добавить таймеры и шкалы прогресса, расширить призовую систему и контроль остатков, восстановить настройки и обновить таблицу призов главного меню.
2026-09-14 10:47:25 +03:00

186 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class VitrinaPanel : MonoBehaviour, IControlable
{
public event Action<bool> OnComplete;
[SerializeField] private Transform BoxesRoot;
[SerializeField] private GameObject BoxViewPrefab;
private readonly List<VitrinaBox> _generatedBoxes = new();
private int _pointerIndex;
private bool _initialized;
private bool _waitForActionRelease;
private bool _waitingForResult;
public bool ControlsEnabled { get; set; }
private VitrinaBox CurrentBox => _generatedBoxes[_pointerIndex];
private void OnDisable()
{
ControlsEnabled = false;
_initialized = false;
_waitingForResult = false;
UnsubscribeFromResult();
ClearBoxes();
}
public async void Initialize(int[] requiredBoxes)
{
if (_initialized)
return;
_initialized = true;
ControlsEnabled = false;
ClearBoxes();
if (VitrinaCatcher.Instance == null)
{
Debug.LogError("VitrinaCatcher не инициализирован", gameObject);
_initialized = false;
gameObject.SetActive(false);
OnComplete?.Invoke(false);
return;
}
SubscribeToResult();
if (!PrizeStandController.Initialized)
{
_waitingForResult = true;
VitrinaCatcher.Instance.DisplayOpenResult(false, "Витрина не подключена");
return;
}
int[] readyBoxes = await PrizeStandController.GetReadyBoxesAsync();
if (!_initialized)
return;
int[] availableBoxes = FindIntersection(requiredBoxes, readyBoxes);
if (availableBoxes.Length == 0)
{
_waitingForResult = true;
VitrinaCatcher.Instance.DisplayOpenResult(false, "Нет доступных призов в витрине");
return;
}
_pointerIndex = 0;
GenerateBoxes(availableBoxes);
CurrentBox.SetEnabled(true);
_waitForActionRelease = true;
ControlsEnabled = true;
ControlsPerformer.Instance.SetControlable(this);
}
public void UpdateControls()
{
if (!_initialized || _waitingForResult)
return;
if (_waitForActionRelease)
{
if (In.GetAction(JoystickSide.Both, InteractMode.Continious))
return;
_waitForActionRelease = false;
}
int direction = In.GetAxis(JoystickSide.Both, InteractMode.Discrete).x;
if (direction != 0 && _generatedBoxes.Count > 1)
{
CurrentBox.SetEnabled(false);
CurrentBox.shake = false;
_pointerIndex = (_pointerIndex + direction + _generatedBoxes.Count) % _generatedBoxes.Count;
CurrentBox.SetEnabled(true);
}
if (!In.GetAction(JoystickSide.Both, InteractMode.Discrete))
return;
ControlsEnabled = false;
ControlsPerformer.Instance.SetControlable(null);
CurrentBox.shake = true;
_waitingForResult = true;
_ = PrizeStandController.OpenBoxAsync(CurrentBox.Number);
}
public static int[] FindIntersection(int[] array1, int[] array2)
{
if (array1 == null || array2 == null || array1.Length == 0 || array2.Length == 0)
return Array.Empty<int>();
HashSet<int> requiredBoxes = new(array1);
return array2.Where(requiredBoxes.Contains).Distinct().OrderBy(number => number).ToArray();
}
public void Close()
{
ControlsEnabled = false;
ControlsPerformer.Instance.SetControlable(null);
gameObject.SetActive(false);
}
private void GenerateBoxes(int[] indexes)
{
foreach (int index in indexes)
{
GameObject boxObject = Instantiate(BoxViewPrefab, BoxesRoot);
if (boxObject.TryGetComponent(out VitrinaBox box))
{
_generatedBoxes.Add(box);
box.SetNumber(index);
}
else
{
Destroy(boxObject);
Debug.LogError("Префаб не содержит компонента VitrinaBox", gameObject);
}
}
}
private void ClearBoxes()
{
foreach (VitrinaBox box in _generatedBoxes)
{
if (box != null)
Destroy(box.gameObject);
}
_generatedBoxes.Clear();
}
private void SubscribeToResult()
{
if (VitrinaCatcher.Instance == null)
return;
VitrinaCatcher.Instance.ResultClosed -= HandleResultClosed;
VitrinaCatcher.Instance.ResultClosed += HandleResultClosed;
}
private void UnsubscribeFromResult()
{
if (VitrinaCatcher.Instance != null)
VitrinaCatcher.Instance.ResultClosed -= HandleResultClosed;
}
private void HandleResultClosed(bool success)
{
if (!_initialized || !_waitingForResult)
return;
UnsubscribeFromResult();
_initialized = false;
_waitingForResult = false;
gameObject.SetActive(false);
OnComplete?.Invoke(success);
}
}