PJ/Assets/scripts/dotfs_scripts/UI_ShopItem.cs

282 lines
8.6 KiB
C#
Raw Normal View History

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class UI_ShopItem : MonoBehaviour
{
[Header("Databases")]
[SerializeField] private ShopAudioDatabase audioDatabase; // Ссылка на БД звуков
[Header("UI Elements")]
[SerializeField] public Color giftBackgroundColor = new Color32(255, 0, 69, 255); // Твой FF0045
[SerializeField] private TMP_Text titleText;
[SerializeField] private TMP_Text priceText;
[SerializeField] private TMP_Text oldPriceText;
[SerializeField] private TMP_Text descpText;
[SerializeField] private Image iconImage;
[Header("Audio Overrides (Optional)")]
[SerializeField] private AudioClip customPurchaseSfx;
[SerializeField] private AudioClip customErrorSfx;
[Header("Settings & Config")]
[SerializeField] private ShopVisualConfig config;
[SerializeField] private ShopIconDatabase iconDb;
// Внимание: если у тебя несколько товаров, статический инстанс делать нельзя!
// public static UI_ShopItem Instance;
private ShopItem _data;
private Button _button;
private Image _backgroundImage;
private Color _initialColor;
private Vector3 _originalScale;
private Coroutine _pulseCoroutine;
private Coroutine _shakeCoroutine;
private readonly Color _giftBgColor = new Color32(255, 0, 69, 255);
private void Awake()
{
_button = GetComponent<Button>();
_backgroundImage = GetComponent<Image>();
if (_backgroundImage != null)
_initialColor = _backgroundImage.color;
_originalScale = transform.localScale;
if (_button != null) _button.onClick.AddListener(OnPurchaseAttempt);
}
public void Setup(ShopItem item)
{
_data = item;
if (_data.isLocked)
{
gameObject.SetActive(false);
return;
}
gameObject.SetActive(true);
StopAllCoroutines();
transform.localScale = _originalScale;
titleText.text = item.title;
descpText.text = item.description;
if (iconImage != null && iconDb != null)
{
Sprite foundIcon = iconDb.GetIcon(item.icon_id);
iconImage.sprite = foundIcon;
iconImage.gameObject.SetActive(foundIcon != null);
iconImage.preserveAspect = item.preserve_aspect;
}
UpdateVisualState();
HandleAnimations();
}
public void SetPrice(float price, float discountPercent)
{
if (config == null) return;
if (price <= 0)
{
priceText.text = "0000";
priceText.color = config.giftColor;
}
else if (discountPercent > 0 && discountPercent < 100)
{
float finalPrice = price * (1 - (discountPercent / 100f));
priceText.text = Mathf.CeilToInt(finalPrice).ToString();
priceText.color = config.discountedPriceColor;
}
else
{
priceText.text = price.ToString();
priceText.color = config.ironColor;
}
}
public void UpdateVisualState()
{
if (config == null || _data == null) return;
bool isFree = _data.isGift || _data.FinalPrice <= 0;
bool hasDiscount = _data.discount > 0 && _data.discount < 100;
// --- ЛОГИКА ЦВЕТА ФОНА ---
if (_backgroundImage != null)
{
if (isFree)
{
_backgroundImage.color = config.giftBackgroundColor;
}
else if (hasDiscount)
{
_backgroundImage.color = config.discountBackgroundColor;
}
else
{
_backgroundImage.color = _initialColor;
}
}
// --- ЛОГИКА ТЕКСТА ЦЕНЫ ---
if (isFree)
{
priceText.text = "FREE";
priceText.color = config.giftColor;
priceText.outlineWidth = 0;
oldPriceText.gameObject.SetActive(false);
}
else
{
string symbol = _data.currency_type == "Gold" ? "Go" : "Ir";
priceText.text = $"{_data.FinalPrice}{symbol}";
ApplyCurrencyStyle(_data.currency_type);
if (hasDiscount)
{
priceText.color = config.discountedPriceColor;
oldPriceText.text = $"<s>{_data.price}{symbol}</s>";
oldPriceText.gameObject.SetActive(true);
}
else
{
oldPriceText.gameObject.SetActive(false);
}
}
}
private void ApplyCurrencyStyle(string type)
{
if (type == "Gold")
{
priceText.color = config.goldColor;
priceText.outlineWidth = 0;
}
else // Iron
{
priceText.color = config.ironColor;
priceText.outlineColor = config.ironOutlineColor;
priceText.outlineWidth = config.ironOutlineWidth;
}
}
private void HandleAnimations()
{
if (_data.isGift || _data.discount > 0)
{
_pulseCoroutine = StartCoroutine(PulseAnimation());
}
}
private void OnPurchaseAttempt()
{
bool canAfford = MANAGER_Shop.Instance.CanPlayerAfford(_data);
if (canAfford)
{
StartCoroutine(SuccessfulPurchaseSequence());
}
else
{
FeedbackInsufficientFunds();
}
}
private void FeedbackInsufficientFunds()
{
if (_shakeCoroutine != null) StopCoroutine(_shakeCoroutine);
_shakeCoroutine = StartCoroutine(ShakeAndRedden());
// Воспроизводим звук ошибки
PlayShopSound(_data?.errorSfxId, SFX_AudioControl.Instance.defaultErrorSFX, customErrorSfx);
}
private IEnumerator ShakeAndRedden()
{
Color originalColor = priceText.color;
priceText.color = config.insufficientFundsColor;
Vector3 originalPos = transform.localPosition;
float elapsed = 0f;
while (elapsed < config.shakeDuration)
{
elapsed += Time.deltaTime;
float x = Random.Range(-1f, 1f) * config.shakeIntensity;
transform.localPosition = originalPos + new Vector3(x, 0, 0);
yield return null;
}
transform.localPosition = originalPos;
priceText.color = originalColor;
}
private IEnumerator PulseAnimation()
{
while (true)
{
float scale = 1f + Mathf.Sin(Time.time * config.pulseSpeed) * config.pulseAmount;
transform.localScale = _originalScale * scale;
yield return null;
}
}
private IEnumerator SuccessfulPurchaseSequence()
{
// Воспроизводим звук успешной покупки
PlayShopSound(_data?.purchaseSfxId, SFX_AudioControl.Instance.defaultPurchaseSFX, customPurchaseSfx);
_button.interactable = false;
// Анимация исчезновения
float timer = 0;
float duration = 0.3f;
while (timer < duration)
{
timer += Time.deltaTime;
transform.localScale = Vector3.Lerp(_originalScale, Vector3.zero, timer / duration);
yield return null;
}
MANAGER_Shop.Instance.BuyItem(_data);
}
// --- ИДЕТ ПОЛНОСТЬЮ ПЕРЕРАБОТАННЫЙ МЕТОД ЗВУКА ---
private void PlayShopSound(string jsonId, AudioClip globalDefault, AudioClip localOverride)
{
if (SFX_AudioControl.Instance == null) return;
AudioClip clipToPlay = null;
// 1. Поиск клипа (логика та же)
if (audioDatabase != null && !string.IsNullOrEmpty(jsonId))
clipToPlay = audioDatabase.GetAudioClip(jsonId);
if (clipToPlay == null && localOverride != null)
clipToPlay = localOverride;
if (clipToPlay == null)
clipToPlay = globalDefault;
// 2. А вот тут магия затухания!
if (clipToPlay != null)
{
// Если ID из JSON равен "dohodyaga", вызываем метод с затуханием музыки
if (jsonId == "dohodyaga")
{
SFX_AudioControl.Instance.PlaySfxWithDucking(clipToPlay);
}
else
{
// Для всех остальных — обычный звук
SFX_AudioControl.Instance.PlayOneShot(clipToPlay);
}
}
}
}