Danro/Assets/Scripts/UI/Modal/LevelPrizeSettingsModal.cs
Danil Iarosh cb2e83a596
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat(ui, prizes, spawners, editor): expand prize flow and add spawning/editor tooling
- доработан flow призовой витрины и связанного UI:
  добавлены `PrizeStandButtonView` и `RulesPrizeListPage`, обновлены
  `PrizeStandController`, `PrizeStandPrize`, `PrizeStandModal`,
  `PrizeStandSettingsModal`, `LevelPrizeSettingsModal`, `QRCodeSettingsModal`,
  `BalanceDisplay`, `ButtonTextFocusColor` и связанные prefab'ы,
  чтобы улучшить настройку, навигацию, отображение кнопок и prize flow
- расширена система настроек и сохранения значений:
  `OptionPicker` получил отдельный формат `ValueSelector`,
  обновлены `SettingsDatabase`, `SettingEntryDrawer`, `SettingUIItem`,
  `SettingsUIGenerator`, `ValueSelectorRow` и `MainSettingsDatabase.asset`,
  а сохранение option picker-значений, включая `gameplay.gameDifficulty`,
  исправлено и синхронизировано с остальными настройками
- добавлены универсальные спавнеры сущностей:
  реализованы `EntitySpawner` и `EntitySpawnerManager` с поддержкой
  весов префабов, точек спавна, заполнения по проценту, ограничений
  на количество и автоспавна при инициализации
- доработана логика игрового спавна и сложности:
  процент инициализационного спавна может зависеть от настройки
  `gameplay.gameDifficulty` с градациями 25/50/75/100,
  в одном цикле массового спавна повторно не используется та же точка,
  а gizmo спавнера теперь показывает только сами точки без линий
- упрощена работа в редакторе Unity и добавлены editor-инструменты:
  в `GameManager` лицензия пропускается при запуске в `UNITY_EDITOR`,
  а `HierarchySelectionCounter`, `HierarchySelectionCountOverlay`
  и `HierarchyBulkRenamerWindow` добавляют подсчет выделения,
  realtime overlay в `SceneView` и массовое переименование объектов
  по правилам нумерации из Unity Project Settings
- синхронизированы сцены, ресурсы и UI-ассеты под новый flow:
  обновлены `MainMenu`, `Level UI`, уровни `1-1` и `1-2`,
  строки настроек, кнопки, TMP/font assets, изображения UI,
  `prizes.json` и recovery-данные после правок интерфейса и логики
- очищены и переразложены часть внешних и служебных ресурсов:
  удалён пакет `Lava_Flowing_Shader`, переименованы/заменены
  отдельные UI-prefab'ы и добавлены сопутствующие проектные артефакты,
  которые сейчас используются обновлённой конфигурацией проекта
2026-04-28 14:05:05 +03:00

728 lines
26 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.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using RR.Common.Managers;
using RR.Common.Prizes;
namespace RR.Common.UI
{
/// <summary>
/// Модальное окно настройки приза за конкретный уровень.
/// Для QR настраивает ранг на уровне, для витрины редактирует общую игровую конфигурацию.
/// </summary>
public class LevelPrizeSettingsModal : Modal
{
[Header("UI — Общее")]
[SerializeField] private TMP_Text titleText;
[SerializeField] private TMP_Text prizeTypeLabel;
[SerializeField] private TMP_Text detailsText;
[Header("UI — QR")]
[SerializeField] private GameObject qrParamsGroup;
[SerializeField] private TMP_Text qrTierLabel;
[Header("UI — Параметры хоппера")]
[SerializeField] private GameObject hopperParamsGroup;
[SerializeField] private TMP_Text hopperCapsuleCountLabel;
[Header("UI — Параметры витрины")]
[SerializeField] private GameObject prizeStandParamsGroup;
[SerializeField] private TMP_Text prizeStandStatusLabel;
[SerializeField] private TMP_Text prizeStandBoxCountLabel;
[SerializeField] private TMP_Text prizeStandSelectedBoxLabel;
[SerializeField] private TMP_Text prizeStandThresholdLabel;
[Header("Строки (RectTransform)")]
[SerializeField] private RectTransform prizeTypeRow;
[SerializeField] private RectTransform qrTierRow;
[SerializeField] private RectTransform hopperParamRow;
[SerializeField] private RectTransform prizeStandBoxCountRow;
[SerializeField] private RectTransform prizeStandSelectedBoxRow;
[SerializeField] private RectTransform prizeStandThresholdRow;
[Header("Указатель")]
[SerializeField] private UIRowPointer rowPointer;
[Header("Кнопка закрытия")]
[SerializeField] private Button closeModalButton;
[Header("Навигация (Input System)")]
[SerializeField] private InputActionReference navigateAction;
[SerializeField] private float deadZone = 0.5f;
[Header("QR Tier Colors")]
[SerializeField] private Color bronzeTierColor = new Color32(205, 127, 50, 255);
[SerializeField] private Color silverTierColor = new Color32(192, 192, 192, 255);
[SerializeField] private Color goldTierColor = new Color32(255, 215, 0, 255);
[Header("Лимиты")]
[SerializeField] private int maxCapsules = 10;
[SerializeField] private int maxBoxes = 48;
[SerializeField] private int defaultPrizeStandBoxesCount = 5;
[SerializeField] private int scoreStep = 50;
private const int ROW_TYPE = 0;
private const int ROW_QR_TIER = 1;
private const int ROW_HOPPER_PARAM = 2;
private const int ROW_STAND_BOX_COUNT = 3;
private const int ROW_STAND_SELECTED_BOX = 4;
private const int ROW_STAND_THRESHOLD = 5;
private const int ROW_CLOSE = 6;
private const int ROW_COUNT = 7;
private static readonly PrizeType[] PrizeTypes = (PrizeType[])Enum.GetValues(typeof(PrizeType));
private static readonly QRTier[] QRTiers = { QRTier.Bronze, QRTier.Silver, QRTier.Gold };
private string _levelName;
private LevelPrizeConfig _config;
private PrizeStandSettings _prizeStandSettings;
private int _currentTypeIndex;
private int _currentTierIndex;
private int _activeRow;
private int _selectedPrizeStandBoxIndex;
private bool _axisHeldX;
private bool _axisHeldY;
private Selectable _pendingFocusTarget;
private int _pendingFocusFrames;
private Selectable _prizeTypeRowSelectable;
private Selectable _qrTierRowSelectable;
private Selectable _hopperParamRowSelectable;
private Selectable _prizeStandBoxCountRowSelectable;
private Selectable _prizeStandSelectedBoxRowSelectable;
private Selectable _prizeStandThresholdRowSelectable;
public event Action<string> OnApplied;
protected override void OnEnable()
{
base.OnEnable();
if (navigateAction != null && navigateAction.action != null)
{
navigateAction.action.Enable();
navigateAction.action.performed += OnNavigatePerformed;
navigateAction.action.canceled += OnNavigateCanceled;
}
}
protected override void OnDisable()
{
if (navigateAction != null && navigateAction.action != null)
{
navigateAction.action.performed -= OnNavigatePerformed;
navigateAction.action.canceled -= OnNavigateCanceled;
}
_axisHeldX = false;
_axisHeldY = false;
_pendingFocusTarget = null;
_pendingFocusFrames = 0;
base.OnDisable();
}
protected override void OnReturnedToTop()
{
_axisHeldX = false;
_axisHeldY = false;
_pendingFocusTarget = null;
_pendingFocusFrames = 0;
RefreshRowHighlights();
}
private void LateUpdate()
{
if (!_isOpen)
{
return;
}
ApplyPendingFocus();
}
private void OnNavigatePerformed(InputAction.CallbackContext ctx)
{
if (!_isOpen) return;
Vector2 v = ctx.ReadValue<Vector2>();
if (Mathf.Abs(v.y) >= deadZone)
{
if (!_axisHeldY)
{
_axisHeldY = true;
MoveRow(v.y > 0f ? -1 : 1);
}
}
else
{
_axisHeldY = false;
}
if (Mathf.Abs(v.x) >= deadZone)
{
if (!_axisHeldX)
{
_axisHeldX = true;
HandleLeftRight(v.x > 0f ? 1 : -1);
}
}
else
{
_axisHeldX = false;
}
}
private void OnNavigateCanceled(InputAction.CallbackContext ctx)
{
_axisHeldX = false;
_axisHeldY = false;
}
private void MoveRow(int delta)
{
int next = _activeRow;
for (int i = 0; i < ROW_COUNT; i++)
{
next = (next + delta + ROW_COUNT) % ROW_COUNT;
if (IsRowVisible(next))
{
_activeRow = next;
break;
}
}
RefreshRowHighlights();
}
private bool IsRowVisible(int row)
{
return row switch
{
ROW_QR_TIER => _config.type == PrizeType.QRCode,
ROW_HOPPER_PARAM => _config.type == PrizeType.Hopper,
ROW_STAND_BOX_COUNT => HasVisiblePrizeStandLevelSettings(),
ROW_STAND_SELECTED_BOX => HasVisiblePrizeStandLevelSettings() && GetPrizeStandBoxes().Count > 0,
ROW_STAND_THRESHOLD => HasVisiblePrizeStandLevelSettings() && GetPrizeStandBoxes().Count > 0,
_ => true
};
}
private void HandleLeftRight(int direction)
{
switch (_activeRow)
{
case ROW_TYPE:
CyclePrizeType(direction);
break;
case ROW_QR_TIER:
AdjustQrTier(direction);
break;
case ROW_HOPPER_PARAM:
AdjustCapsules(direction);
break;
case ROW_STAND_BOX_COUNT:
AdjustPrizeStandBoxCount(direction);
break;
case ROW_STAND_SELECTED_BOX:
AdjustSelectedPrizeStandBox(direction);
break;
case ROW_STAND_THRESHOLD:
AdjustPrizeStandThreshold(direction);
break;
}
}
public void OpenForLevel(string levelName)
{
_levelName = levelName;
PrizeDatabase db = PrizeSystemManager.Instance?.Database;
_config = db != null
? CopyConfig(db.GetConfig(levelName))
: new LevelPrizeConfig();
_prizeStandSettings = db != null
? CopyPrizeStandSettings(db.GetPrizeStandSettings())
: CreateDefaultPrizeStandSettings();
EnsurePrizeStandSettingsInitialized();
_currentTypeIndex = Array.IndexOf(PrizeTypes, _config.type);
if (_currentTypeIndex < 0)
_currentTypeIndex = 0;
_currentTierIndex = GetTierIndex(_config.qrTier);
_selectedPrizeStandBoxIndex = Mathf.Clamp(_selectedPrizeStandBoxIndex, 0, Mathf.Max(0, GetPrizeStandBoxes().Count - 1));
_activeRow = ROW_TYPE;
AutoResolveRows();
EnsureRowSelectables();
RefreshUI();
RefreshRowHighlights();
Open();
}
public override void Close()
{
Save();
base.Close();
}
private void CyclePrizeType(int direction)
{
_currentTypeIndex = (_currentTypeIndex + direction + PrizeTypes.Length) % PrizeTypes.Length;
_config.type = PrizeTypes[_currentTypeIndex];
if (_config.type == PrizeType.QRCode && _config.qrTier == QRTier.None)
_config.qrTier = QRTiers[0];
EnsurePrizeStandSettingsInitialized();
if (!IsRowVisible(_activeRow))
_activeRow = ROW_TYPE;
RefreshUI();
RefreshRowHighlights();
}
private void AdjustQrTier(int direction)
{
_currentTierIndex = (_currentTierIndex + direction + QRTiers.Length) % QRTiers.Length;
_config.qrTier = QRTiers[_currentTierIndex];
RefreshUI();
}
private void AdjustCapsules(int delta)
{
_config.hopperCapsuleCount = Mathf.Clamp(_config.hopperCapsuleCount + delta, 1, maxCapsules);
RefreshUI();
}
private void AdjustPrizeStandBoxCount(int delta)
{
List<PrizeStandBoxConfig> boxes = GetPrizeStandBoxes();
int currentCount = boxes.Count;
int nextCount = Mathf.Clamp(currentCount + delta, 1, maxBoxes);
if (nextCount == currentCount)
return;
if (nextCount > currentCount)
{
for (int i = currentCount + 1; i <= nextCount; i++)
boxes.Add(new PrizeStandBoxConfig { boxNumber = i, requiredScore = 0 });
}
else
{
boxes.RemoveRange(nextCount, currentCount - nextCount);
}
NormalizePrizeStandBoxes();
_selectedPrizeStandBoxIndex = Mathf.Clamp(_selectedPrizeStandBoxIndex, 0, boxes.Count - 1);
RefreshUI();
RefreshRowHighlights();
}
private void AdjustSelectedPrizeStandBox(int delta)
{
List<PrizeStandBoxConfig> boxes = GetPrizeStandBoxes();
if (boxes.Count == 0)
return;
_selectedPrizeStandBoxIndex = (_selectedPrizeStandBoxIndex + delta + boxes.Count) % boxes.Count;
RefreshUI();
}
private void AdjustPrizeStandThreshold(int direction)
{
PrizeStandBoxConfig selectedBox = GetSelectedPrizeStandBox();
if (selectedBox == null)
return;
selectedBox.requiredScore = Mathf.Max(0, selectedBox.requiredScore + direction * scoreStep);
RefreshUI();
}
private void Save()
{
if (string.IsNullOrEmpty(_levelName) || _config == null)
return;
PrizeDatabase db = PrizeSystemManager.Instance?.Database;
PrizeSystemManager manager = PrizeSystemManager.Instance;
if (db == null || manager == null)
{
Debug.LogError("[LevelPrizeSettingsModal] PrizeDatabase недоступна.");
return;
}
db.SetConfig(_levelName, _config);
Debug.Log($"[LevelPrizeSettingsModal] Уровень «{_levelName}» → приз «{_config.type}» сохранён.");
OnApplied?.Invoke(_levelName);
}
private void RefreshUI()
{
EnsurePrizeStandSettingsInitialized();
if (titleText)
titleText.text = $"Приз за уровень {_levelName}";
if (prizeTypeLabel)
prizeTypeLabel.text = GetPrizeTypeName(_config.type);
if (qrParamsGroup) qrParamsGroup.SetActive(_config.type == PrizeType.QRCode);
if (hopperParamsGroup) hopperParamsGroup.SetActive(_config.type == PrizeType.Hopper);
if (prizeStandParamsGroup) prizeStandParamsGroup.SetActive(HasVisiblePrizeStandLevelSettings());
if (qrTierLabel)
{
qrTierLabel.text = GetTierName(_config.qrTier);
qrTierLabel.color = GetTierColor(_config.qrTier);
}
if (hopperCapsuleCountLabel)
hopperCapsuleCountLabel.text = _config.hopperCapsuleCount.ToString();
PrizeStandConnectionInfo connectionInfo = PrizeSystemManager.Instance != null
? PrizeSystemManager.Instance.GetPrizeStandConnectionInfo()
: new PrizeStandConnectionInfo(false, 0);
List<PrizeStandBoxConfig> boxes = GetPrizeStandBoxes();
PrizeStandBoxConfig selectedBox = GetSelectedPrizeStandBox();
if (prizeStandStatusLabel)
prizeStandStatusLabel.text = connectionInfo.IsConnected
? $"Подключена ({connectionInfo.ConnectedBoxesCount} ячеек)"
: "Не подключена";
if (prizeStandBoxCountLabel)
prizeStandBoxCountLabel.text = boxes.Count.ToString();
if (prizeStandSelectedBoxLabel)
prizeStandSelectedBoxLabel.text = selectedBox != null ? selectedBox.boxNumber.ToString() : "-";
if (prizeStandThresholdLabel)
prizeStandThresholdLabel.text = selectedBox != null ? selectedBox.requiredScore.ToString() : "-";
if (detailsText)
detailsText.text = BuildDetailsText(connectionInfo, boxes, selectedBox);
}
private string BuildDetailsText(PrizeStandConnectionInfo connectionInfo, List<PrizeStandBoxConfig> boxes, PrizeStandBoxConfig selectedBox)
{
return _config.type switch
{
PrizeType.QRCode => $"Ранг QR-приза: {GetTierName(_config.qrTier)}",
PrizeType.Hopper => $"Капсул за выдачу: {_config.hopperCapsuleCount}",
PrizeType.PrizeStand => BuildPrizeStandDetails(connectionInfo, boxes, selectedBox),
_ => "Для уровня приз не назначен."
};
}
private string BuildPrizeStandDetails(PrizeStandConnectionInfo connectionInfo, List<PrizeStandBoxConfig> boxes, PrizeStandBoxConfig selectedBox)
{
string connectionText = connectionInfo.IsConnected
? $"Витрина подключена, доступно на устройстве: {connectionInfo.ConnectedBoxesCount} ячеек."
: "Витрина не подключена.";
if (HasVisiblePrizeStandLevelSettings())
{
string selectedText = selectedBox != null
? $"Выбрана ячейка {selectedBox.boxNumber}, порог: {selectedBox.requiredScore} очков."
: "Ячейки не настроены.";
return $"{connectionText}\nСконфигурировано ячеек: {boxes.Count}\n{selectedText}";
}
return $"{connectionText}\nПараметры витрины настраиваются отдельно в глобальных настройках витрины.";
}
private void RefreshRowHighlights()
{
Selectable selectableToFocus = _activeRow switch
{
ROW_TYPE => _prizeTypeRowSelectable,
ROW_QR_TIER => _qrTierRowSelectable,
ROW_HOPPER_PARAM => _hopperParamRowSelectable,
ROW_STAND_BOX_COUNT => _prizeStandBoxCountRowSelectable,
ROW_STAND_SELECTED_BOX => _prizeStandSelectedBoxRowSelectable,
ROW_STAND_THRESHOLD => _prizeStandThresholdRowSelectable,
ROW_CLOSE => closeModalButton,
_ => _prizeTypeRowSelectable
};
if (_activeRow == ROW_CLOSE)
{
if (rowPointer) rowPointer.Hide();
}
else
{
if (rowPointer)
{
RectTransform target = GetActiveRowTransform();
if (target) rowPointer.SetTarget(target);
}
}
FocusSelectable(selectableToFocus);
}
private RectTransform GetActiveRowTransform()
{
return _activeRow switch
{
ROW_TYPE => prizeTypeRow,
ROW_QR_TIER => qrTierRow != null ? qrTierRow : prizeTypeRow,
ROW_HOPPER_PARAM => hopperParamRow != null ? hopperParamRow : prizeTypeRow,
ROW_STAND_BOX_COUNT => prizeStandBoxCountRow,
ROW_STAND_SELECTED_BOX => prizeStandSelectedBoxRow,
ROW_STAND_THRESHOLD => prizeStandThresholdRow,
_ => prizeTypeRow
};
}
private void AutoResolveRows()
{
if (prizeTypeRow == null && prizeTypeLabel != null)
prizeTypeRow = prizeTypeLabel.transform.parent as RectTransform;
if (qrTierRow == null && qrTierLabel != null)
qrTierRow = qrTierLabel.transform.parent as RectTransform;
if (hopperParamRow == null && hopperCapsuleCountLabel != null)
hopperParamRow = hopperCapsuleCountLabel.transform.parent as RectTransform;
if (prizeStandBoxCountRow == null && prizeStandBoxCountLabel != null)
prizeStandBoxCountRow = prizeStandBoxCountLabel.transform.parent as RectTransform;
if (prizeStandSelectedBoxRow == null && prizeStandSelectedBoxLabel != null)
prizeStandSelectedBoxRow = prizeStandSelectedBoxLabel.transform.parent as RectTransform;
if (prizeStandThresholdRow == null && prizeStandThresholdLabel != null)
prizeStandThresholdRow = prizeStandThresholdLabel.transform.parent as RectTransform;
}
private void EnsureRowSelectables()
{
_prizeTypeRowSelectable = EnsureRowSelectable(prizeTypeRow);
_qrTierRowSelectable = EnsureRowSelectable(qrTierRow);
_hopperParamRowSelectable = EnsureRowSelectable(hopperParamRow);
_prizeStandBoxCountRowSelectable = EnsureRowSelectable(prizeStandBoxCountRow);
_prizeStandSelectedBoxRowSelectable = EnsureRowSelectable(prizeStandSelectedBoxRow);
_prizeStandThresholdRowSelectable = EnsureRowSelectable(prizeStandThresholdRow);
}
private Selectable EnsureRowSelectable(RectTransform row)
{
if (row == null)
{
return null;
}
Selectable selectable = row.GetComponent<Selectable>();
if (selectable == null)
{
selectable = row.gameObject.AddComponent<Selectable>();
selectable.transition = Selectable.Transition.None;
selectable.navigation = new Navigation { mode = Navigation.Mode.None };
}
selectable.interactable = true;
return selectable;
}
private void FocusSelectable(Selectable selectable)
{
if (selectable == null || !selectable.gameObject.activeInHierarchy)
{
return;
}
SetFirstSelected(selectable);
_pendingFocusTarget = selectable;
_pendingFocusFrames = 2;
ApplyPendingFocus();
}
private void ApplyPendingFocus()
{
if (_pendingFocusTarget == null || _pendingFocusFrames <= 0)
{
return;
}
if (EventSystem.current == null || !_pendingFocusTarget.gameObject.activeInHierarchy)
{
_pendingFocusTarget = null;
_pendingFocusFrames = 0;
return;
}
if (EventSystem.current.currentSelectedGameObject != _pendingFocusTarget.gameObject)
{
EventSystem.current.SetSelectedGameObject(null);
EventSystem.current.SetSelectedGameObject(_pendingFocusTarget.gameObject);
_pendingFocusTarget.Select();
}
_pendingFocusFrames--;
if (_pendingFocusFrames <= 0)
{
_pendingFocusTarget = null;
}
}
private bool HasVisiblePrizeStandLevelSettings()
{
if (_config == null || _config.type != PrizeType.PrizeStand)
{
return false;
}
return prizeStandParamsGroup != null
&& (prizeStandBoxCountRow != null || prizeStandSelectedBoxRow != null || prizeStandThresholdRow != null);
}
private void EnsurePrizeStandSettingsInitialized()
{
_prizeStandSettings ??= CreateDefaultPrizeStandSettings();
_prizeStandSettings.boxes ??= new List<PrizeStandBoxConfig>();
if (_prizeStandSettings.boxes.Count == 0)
{
int initialCount = defaultPrizeStandBoxesCount;
PrizeStandConnectionInfo connectionInfo = PrizeSystemManager.Instance != null
? PrizeSystemManager.Instance.GetPrizeStandConnectionInfo()
: new PrizeStandConnectionInfo(false, 0);
if (connectionInfo.IsConnected && connectionInfo.ConnectedBoxesCount > 0)
initialCount = Mathf.Clamp(connectionInfo.ConnectedBoxesCount, 1, maxBoxes);
for (int i = 1; i <= initialCount; i++)
_prizeStandSettings.boxes.Add(new PrizeStandBoxConfig { boxNumber = i, requiredScore = 0 });
}
NormalizePrizeStandBoxes();
}
private void NormalizePrizeStandBoxes()
{
List<PrizeStandBoxConfig> boxes = _prizeStandSettings.boxes;
boxes.Sort((a, b) => a.boxNumber.CompareTo(b.boxNumber));
for (int i = 0; i < boxes.Count; i++)
{
if (boxes[i] == null)
boxes[i] = new PrizeStandBoxConfig();
boxes[i].boxNumber = i + 1;
boxes[i].requiredScore = Mathf.Max(0, boxes[i].requiredScore);
}
}
private List<PrizeStandBoxConfig> GetPrizeStandBoxes()
{
EnsurePrizeStandSettingsInitialized();
return _prizeStandSettings.boxes;
}
private PrizeStandBoxConfig GetSelectedPrizeStandBox()
{
List<PrizeStandBoxConfig> boxes = GetPrizeStandBoxes();
if (boxes.Count == 0)
return null;
_selectedPrizeStandBoxIndex = Mathf.Clamp(_selectedPrizeStandBoxIndex, 0, boxes.Count - 1);
return boxes[_selectedPrizeStandBoxIndex];
}
private static string GetPrizeTypeName(PrizeType type)
{
return type switch
{
PrizeType.None => "Нет приза",
PrizeType.QRCode => "QR-код",
PrizeType.Hopper => "Хоппер",
PrizeType.PrizeStand => "Витрина",
_ => type.ToString()
};
}
private static string GetTierName(QRTier tier)
{
return tier switch
{
QRTier.Bronze => "Бронзовый",
QRTier.Silver => "Серебряный",
QRTier.Gold => "Золотой",
_ => "Не задан"
};
}
private Color GetTierColor(QRTier tier)
{
return tier switch
{
QRTier.Bronze => bronzeTierColor,
QRTier.Silver => silverTierColor,
QRTier.Gold => goldTierColor,
_ => qrTierLabel != null ? qrTierLabel.color : Color.white
};
}
private static int GetTierIndex(QRTier tier)
{
int index = Array.IndexOf(QRTiers, tier);
return index >= 0 ? index : 0;
}
private static LevelPrizeConfig CopyConfig(LevelPrizeConfig src)
{
return new LevelPrizeConfig
{
type = src.type,
qrTier = src.qrTier,
hopperCapsuleCount = src.hopperCapsuleCount,
hopperDelayBetweenCapsules = src.hopperDelayBetweenCapsules
};
}
private static PrizeStandSettings CopyPrizeStandSettings(PrizeStandSettings src)
{
PrizeStandSettings copy = new PrizeStandSettings();
if (src?.boxes == null)
return copy;
for (int i = 0; i < src.boxes.Count; i++)
{
PrizeStandBoxConfig box = src.boxes[i];
if (box == null)
continue;
copy.boxes.Add(new PrizeStandBoxConfig
{
boxNumber = box.boxNumber,
requiredScore = box.requiredScore
});
}
return copy;
}
private PrizeStandSettings CreateDefaultPrizeStandSettings()
{
PrizeStandSettings settings = new PrizeStandSettings();
for (int i = 1; i <= defaultPrizeStandBoxesCount; i++)
{
settings.boxes.Add(new PrizeStandBoxConfig
{
boxNumber = i,
requiredScore = 0
});
}
return settings;
}
}
}