using BulletHellTemplate; using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; namespace BulletHellTemplate { public class InventoryItemInfo : MonoBehaviour { [Header("Item UI Elements")] public Image icon; public TextMeshProUGUI title; public TextMeshProUGUI description; [Header("Upgrade UI Elements")] public TextMeshProUGUI levelText; public Image currencyUpgradeIcon; public Image upgradeProgressBar; public float progressDuration; public TextMeshProUGUI upgradeCostText; public TextMeshProUGUI successRateText; public TextMeshProUGUI upgradeResult; public Button upgradeButton; [Header("UI Settings")] public Color baseStatsColor; public Color bonusStatsColor; public Color sucessColor; public Color failColor; [Header("Translated Messages")] public string sucessMessage; public NameTranslatedByLanguage[] sucessMessageTranslated; public string failMessage; public NameTranslatedByLanguage[] failMessageTranslated; public string sucessRateString; public NameTranslatedByLanguage[] sucessRateStringTranslated; public string maxLevelString; public NameTranslatedByLanguage[] maxLevelStringTranslated; [Header("Rarity Frame")] public Image frame; public Sprite commonFrame; public Sprite uncommonFrame; public Sprite rareFrame; public Sprite epicFrame; public Sprite legendaryFrame; [Header("Item Stats UI Elements")] public TextMeshProUGUI hpText; public TextMeshProUGUI hpRegenText; public TextMeshProUGUI hpLeechText; public TextMeshProUGUI mpText; public TextMeshProUGUI mpRegenText; public TextMeshProUGUI damageText; public TextMeshProUGUI attackSpeedText; public TextMeshProUGUI cooldownReductionText; public TextMeshProUGUI criticalRateText; public TextMeshProUGUI criticalDamageMultiplierText; public TextMeshProUGUI defenseText; public TextMeshProUGUI shieldText; public TextMeshProUGUI moveSpeedText; public TextMeshProUGUI collectRangeText; private InventoryItem currentItem; private string currentUniqueGuid; // The unique ID for this purchased item instance /// /// Opens the item information UI, displaying item details such as stats, upgrade levels, and costs. /// Receives both the inventory ScriptableObject and the unique GUID for the purchased instance. /// /// The inventory item (scriptable) to display. /// The purchased instance unique GUID. public void OpenItemInfo(InventoryItem item, string uniqueGuid) { currentItem = item; currentUniqueGuid = uniqueGuid; if (icon != null) icon.sprite = item.itemIcon; string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); title.text = GetTranslatedString(item.titleTranslatedByLanguage, item.title, currentLang); description.text = GetTranslatedDescriptionString(item.descriptionTranslatedByLanguage, item.description, currentLang); // Get the level of this specific item instance int currentLevel = InventorySave.GetItemUpgradeLevel(uniqueGuid); if (currentLevel >= item.itemUpgrades.Count) { levelText.text = GetTranslatedString(maxLevelStringTranslated, maxLevelString, currentLang); upgradeCostText.text = GetTranslatedString(maxLevelStringTranslated, maxLevelString, currentLang); successRateText.text = ""; upgradeButton.interactable = false; currencyUpgradeIcon.gameObject.SetActive(false); } else { levelText.text = $"Lv: {currentLevel}"; upgradeButton.interactable = true; currencyUpgradeIcon.gameObject.SetActive(true); var nextUpgrade = item.itemUpgrades[currentLevel]; upgradeCostText.text = $"{nextUpgrade.upgradeCosts}"; currencyUpgradeIcon.sprite = MonetizationManager.Singleton.GetCurrencyIcon(nextUpgrade.currencyTag); SetSuccessRateText(nextUpgrade.successRate); } SetRarityFrame(item); DisplayImportantStats(item, currentLevel); gameObject.SetActive(true); } /// /// Updates the item info UI after an upgrade with the new level data. /// /// The inventory item ScriptableObject being updated. /// The new upgrade level of the item. public void UpdateItemInfo(InventoryItem item, int newLevel) { string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); if (newLevel >= item.itemUpgrades.Count) { levelText.text = newLevel + " " + GetTranslatedString(maxLevelStringTranslated, maxLevelString, currentLang); upgradeButton.interactable = false; upgradeCostText.text = GetTranslatedString(maxLevelStringTranslated, maxLevelString, currentLang); successRateText.text = ""; currencyUpgradeIcon.gameObject.SetActive(false); } else { levelText.text = $"Lv: {newLevel}"; var nextUpgrade = item.itemUpgrades[newLevel]; upgradeCostText.text = $"{nextUpgrade.upgradeCosts}"; currencyUpgradeIcon.sprite = MonetizationManager.Singleton.GetCurrencyIcon(nextUpgrade.currencyTag); SetSuccessRateText(nextUpgrade.successRate); upgradeButton.interactable = true; currencyUpgradeIcon.gameObject.SetActive(true); } DisplayImportantStats(item, newLevel); } /// /// Called by the upgrade button. Triggers the upgrade process in the UIInventoryMenu, /// using the current item's unique GUID. /// public void OnClickUpgrade() { UIInventoryMenu.Singleton.UpgradeItem(currentUniqueGuid, currentItem, this); } /// /// Sets the success rate text with color feedback based on the value. /// private void SetSuccessRateText(float successRate) { string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); string successRateLabel = GetTranslatedString(sucessRateStringTranslated, sucessRateString, currentLang); float percentage = successRate * 100f; successRateText.text = $"{successRateLabel}: {percentage:F1}%"; if (percentage > 70) successRateText.color = Color.green; else if (percentage >= 40) successRateText.color = Color.yellow; else successRateText.color = Color.red; } /// /// Displays the item's stats: base value plus a bonus increment colored in 'bonusStatsColor'. /// The bonus is based on summing the statIncreasePercentagePerLevel for all levels up to currentLevel. /// private void DisplayImportantStats(InventoryItem item, int currentLevel) { if (item == null) return; CharacterStats stats = item.itemStats; float totalUpgradePercentage = 0f; for (int i = 0; i < currentLevel; i++) { totalUpgradePercentage += item.itemUpgrades[i].statIncreasePercentagePerLevel; } // Helper function to build a "base + bonus" text with colors string BuildStatText(float baseValue) { float bonusValue = baseValue * totalUpgradePercentage; return $"{baseValue} " + $"+ {bonusValue:F1}"; } if (hpText != null) hpText.text = BuildStatText(stats.baseHP); if (hpRegenText != null) hpRegenText.text = BuildStatText(stats.baseHPRegen); if (hpLeechText != null) hpLeechText.text = BuildStatText(stats.baseHPLeech); if (mpText != null) mpText.text = BuildStatText(stats.baseMP); if (mpRegenText != null) mpRegenText.text = BuildStatText(stats.baseMPRegen); if (damageText != null) damageText.text = BuildStatText(stats.baseDamage); if (attackSpeedText != null) attackSpeedText.text = BuildStatText(stats.baseAttackSpeed); if (cooldownReductionText != null) cooldownReductionText.text = BuildStatText(stats.baseCooldownReduction); if (criticalRateText != null) criticalRateText.text = BuildStatText(stats.baseCriticalRate); if (criticalDamageMultiplierText != null) criticalDamageMultiplierText.text = BuildStatText(stats.baseCriticalDamageMultiplier); if (defenseText != null) defenseText.text = BuildStatText(stats.baseDefense); if (shieldText != null) shieldText.text = BuildStatText(stats.baseShield); if (moveSpeedText != null) moveSpeedText.text = BuildStatText(stats.baseMoveSpeed); if (collectRangeText != null) collectRangeText.text = BuildStatText(stats.baseCollectRange); } /// /// Sets the frame sprite based on the item's rarity. /// private void SetRarityFrame(InventoryItem item) { if (frame == null) return; switch (item.rarity) { case Rarity.Common: frame.sprite = commonFrame; break; case Rarity.Uncommon: frame.sprite = uncommonFrame; break; case Rarity.Rare: frame.sprite = rareFrame; break; case Rarity.Epic: frame.sprite = epicFrame; break; case Rarity.Legendary: frame.sprite = legendaryFrame; break; } } /// /// Coroutine to animate an upgrade progress bar and display a success/fail message. /// public IEnumerator UpgradeProgressRoutine(bool isSuccess, float duration) { upgradeProgressBar.fillAmount = 0f; float timer = 0f; while (timer < progressDuration) { timer += Time.deltaTime; upgradeProgressBar.fillAmount = Mathf.Clamp01(timer / progressDuration); yield return null; } upgradeProgressBar.fillAmount = 0f; string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); if (isSuccess) { string successMsg = GetTranslatedString(sucessMessageTranslated, sucessMessage, currentLang); StartCoroutine(showUpgradeResult(successMsg, sucessColor, duration)); } else { string failMsg = GetTranslatedString(failMessageTranslated, failMessage, currentLang); StartCoroutine(showUpgradeResult(failMsg, failColor, duration)); } } /// /// Displays a temporary upgrade result message. /// public IEnumerator showUpgradeResult(string message, Color _color, float duration) { upgradeResult.color = _color; upgradeResult.text = message; yield return new WaitForSeconds(duration); upgradeResult.text = ""; } /// /// Gets a translated string if available in translations; otherwise returns the fallback. /// private string GetTranslatedString(NameTranslatedByLanguage[] translations, string fallback, string currentLang) { if (translations != null) { foreach (var trans in translations) { if (!string.IsNullOrEmpty(trans.LanguageId) && trans.LanguageId.Equals(currentLang) && !string.IsNullOrEmpty(trans.Translate)) { return trans.Translate; } } } return fallback; } /// /// Gets a translated description if available; otherwise returns fallback. /// private string GetTranslatedDescriptionString(DescriptionTranslatedByLanguage[] translations, string fallback, string currentLang) { if (translations != null) { foreach (var trans in translations) { if (!string.IsNullOrEmpty(trans.LanguageId) && trans.LanguageId.Equals(currentLang) && !string.IsNullOrEmpty(trans.Translate)) { return trans.Translate; } } } return fallback; } } }