440 lines
16 KiB
C#
440 lines
16 KiB
C#
using BulletHellTemplate;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
|
|
namespace BulletHellTemplate
|
|
{
|
|
/// <summary>
|
|
/// UI menu for displaying and managing inventory items that have been purchased.
|
|
/// Supports filtering by rarity, category, and slot, and upgrading items.
|
|
/// </summary>
|
|
public class UIInventoryMenu : MonoBehaviour
|
|
{
|
|
public static UIInventoryMenu Singleton;
|
|
|
|
[Header("Inventory UI Elements")]
|
|
public InventoryEntry inventoryEntryPrefab;
|
|
public Transform inventoryContainer;
|
|
|
|
[Header("Item Info")]
|
|
public InventoryItemInfo inventoryItemInfoPrefab;
|
|
|
|
[Header("Message UI")]
|
|
public TextMeshProUGUI messageText;
|
|
|
|
[Header("Dropdowns")]
|
|
public TMP_Dropdown sortDropdown;
|
|
public TMP_Dropdown filterRarityDropdown;
|
|
public TMP_Dropdown filterCategoryDropdown;
|
|
public TMP_Dropdown filterSlotDropdown;
|
|
|
|
[Header("Filter Options")]
|
|
public List<string> categoryOptions;
|
|
public OptionsTranslate[] categoryOptionsTranslate;
|
|
public List<string> slotOptions;
|
|
public OptionsTranslate[] slotOptionsTranslate;
|
|
|
|
// Localization for sorting
|
|
[Header("Dropdown Localization")]
|
|
public NameTranslatedByLanguage[] sortByRarityAscTranslated;
|
|
public string sortByRarityAscFallback = "Sort by Rarity (Asc)";
|
|
|
|
public NameTranslatedByLanguage[] sortByRarityDescTranslated;
|
|
public string sortByRarityDescFallback = "Sort by Rarity (Desc)";
|
|
|
|
public NameTranslatedByLanguage[] sortBySlotTranslated;
|
|
public string sortBySlotFallback = "Sort by Slot";
|
|
|
|
public NameTranslatedByLanguage[] allOptionTranslated;
|
|
public string allOptionFallback = "All";
|
|
|
|
// Messages Localization
|
|
[Header("Upgrade Messages Localization")]
|
|
public NameTranslatedByLanguage[] maxLevelReachedTranslated;
|
|
public string maxLevelReachedFallback = "Max Level Reached!";
|
|
|
|
public NameTranslatedByLanguage[] insufficientCurrencyTranslated;
|
|
public string insufficientCurrencyFallback = "Insufficient currency!";
|
|
|
|
public NameTranslatedByLanguage[] upgradeSuccessTranslated;
|
|
public string upgradeSuccessFallback = "Upgrade Successful!";
|
|
|
|
public NameTranslatedByLanguage[] upgradeFailTranslated;
|
|
public string upgradeFailFallback = "Upgrade Failed!";
|
|
|
|
public NameTranslatedByLanguage[] levelDecreasedTranslated;
|
|
public string levelDecreasedFallback = "Level Decreased!";
|
|
|
|
private Dictionary<string, string> categoryTranslationMap = new Dictionary<string, string>();
|
|
private Dictionary<string, string> slotTranslationMap = new Dictionary<string, string>();
|
|
private List<InventoryEntry> spawnedEntries = new List<InventoryEntry>();
|
|
|
|
private string currentRarityFilter = "";
|
|
private string currentCategoryFilter = "";
|
|
private string currentSlotFilter = "";
|
|
|
|
private void Awake()
|
|
{
|
|
if (Singleton == null)
|
|
Singleton = this;
|
|
else
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
SetupDropdowns();
|
|
UpdateInventoryUI();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures the dropdown options for sorting and filtering, using translations.
|
|
/// </summary>
|
|
private void SetupDropdowns()
|
|
{
|
|
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
|
|
|
// Sort dropdown
|
|
string rarityAsc = GetTranslatedString(sortByRarityAscTranslated, sortByRarityAscFallback, currentLang);
|
|
string rarityDesc = GetTranslatedString(sortByRarityDescTranslated, sortByRarityDescFallback, currentLang);
|
|
string slotSort = GetTranslatedString(sortBySlotTranslated, sortBySlotFallback, currentLang);
|
|
|
|
sortDropdown.ClearOptions();
|
|
var sortOptions = new List<string> { rarityAsc, rarityDesc, slotSort };
|
|
sortDropdown.AddOptions(sortOptions);
|
|
sortDropdown.onValueChanged.AddListener(OnSortDropdownChanged);
|
|
|
|
// Rarity dropdown
|
|
filterRarityDropdown.ClearOptions();
|
|
List<string> rarityNames = System.Enum.GetNames(typeof(Rarity)).ToList();
|
|
string allString = GetTranslatedString(allOptionTranslated, allOptionFallback, currentLang);
|
|
rarityNames.Insert(0, allString);
|
|
filterRarityDropdown.AddOptions(rarityNames);
|
|
filterRarityDropdown.onValueChanged.AddListener(OnFilterRarityDropdownChanged);
|
|
|
|
// Category dropdown
|
|
filterCategoryDropdown.ClearOptions();
|
|
categoryTranslationMap.Clear();
|
|
var catOptions = new List<string> { allString };
|
|
for (int i = 0; i < categoryOptions.Count; i++)
|
|
{
|
|
string originalCat = categoryOptions[i];
|
|
var matchedStruct = FindTranslationStruct(categoryOptionsTranslate, i);
|
|
if (matchedStruct.HasValue)
|
|
{
|
|
string translatedCat = GetTranslatedString(matchedStruct.Value.optionsTranslates, originalCat, currentLang);
|
|
categoryTranslationMap[translatedCat] = originalCat;
|
|
catOptions.Add(translatedCat);
|
|
}
|
|
else
|
|
{
|
|
categoryTranslationMap[originalCat] = originalCat;
|
|
catOptions.Add(originalCat);
|
|
}
|
|
}
|
|
filterCategoryDropdown.AddOptions(catOptions);
|
|
filterCategoryDropdown.onValueChanged.AddListener(OnFilterCategoryDropdownChanged);
|
|
|
|
// Slot dropdown
|
|
filterSlotDropdown.ClearOptions();
|
|
slotTranslationMap.Clear();
|
|
var slotOpts = new List<string> { allString };
|
|
for (int i = 0; i < slotOptions.Count; i++)
|
|
{
|
|
string origSlot = slotOptions[i];
|
|
var matchedStruct = FindTranslationStruct(slotOptionsTranslate, i);
|
|
if (matchedStruct.HasValue)
|
|
{
|
|
string translatedSlot = GetTranslatedString(matchedStruct.Value.optionsTranslates, origSlot, currentLang);
|
|
slotTranslationMap[translatedSlot] = origSlot;
|
|
slotOpts.Add(translatedSlot);
|
|
}
|
|
else
|
|
{
|
|
slotTranslationMap[origSlot] = origSlot;
|
|
slotOpts.Add(origSlot);
|
|
}
|
|
}
|
|
filterSlotDropdown.AddOptions(slotOpts);
|
|
filterSlotDropdown.onValueChanged.AddListener(OnFilterSlotDropdownChanged);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears and rebuilds the inventory UI based on the purchased items.
|
|
/// </summary>
|
|
public void UpdateInventoryUI()
|
|
{
|
|
ClearInventory();
|
|
|
|
// Get purchased items from MonetizationManager
|
|
var purchasedItems = PlayerSave.GetInventoryItems();
|
|
|
|
foreach (var purchasedItem in purchasedItems)
|
|
{
|
|
// Get the scriptable object (InventoryItem) by itemId
|
|
var matchingSO = GameInstance.Singleton.inventoryItems
|
|
.FirstOrDefault(so => so.itemId == purchasedItem.itemId);
|
|
|
|
int currentLevel = InventorySave.GetItemUpgradeLevel(purchasedItem.uniqueItemGuid);
|
|
|
|
if (matchingSO == null)
|
|
{
|
|
Debug.LogWarning($"No scriptable for itemId {purchasedItem.itemId}");
|
|
continue;
|
|
}
|
|
|
|
// Filter by Rarity
|
|
if (!string.IsNullOrEmpty(currentRarityFilter) && currentRarityFilter != "All")
|
|
{
|
|
if (matchingSO.rarity.ToString() != currentRarityFilter)
|
|
continue;
|
|
}
|
|
|
|
// Filter by Category
|
|
if (!string.IsNullOrEmpty(currentCategoryFilter) && currentCategoryFilter != "All")
|
|
{
|
|
if (matchingSO.category != currentCategoryFilter)
|
|
continue;
|
|
}
|
|
|
|
// Filter by Slot
|
|
if (!string.IsNullOrEmpty(currentSlotFilter) && currentSlotFilter != "All")
|
|
{
|
|
if (matchingSO.slot != currentSlotFilter)
|
|
continue;
|
|
}
|
|
|
|
// Create Entry
|
|
InventoryEntry entry = Instantiate(inventoryEntryPrefab, inventoryContainer);
|
|
|
|
// Setup: now pass uniqueItemGuid and itemLevel from purchasedItem
|
|
entry.Setup(purchasedItem.uniqueItemGuid, matchingSO, currentLevel);
|
|
spawnedEntries.Add(entry);
|
|
}
|
|
}
|
|
|
|
private void ClearInventory()
|
|
{
|
|
foreach (Transform child in inventoryContainer)
|
|
Destroy(child.gameObject);
|
|
|
|
spawnedEntries.Clear();
|
|
}
|
|
|
|
public void DeselectAllEntries()
|
|
{
|
|
foreach (var entry in spawnedEntries)
|
|
{
|
|
entry.Deselect();
|
|
}
|
|
}
|
|
|
|
// Filter
|
|
private void OnFilterRarityDropdownChanged(int index)
|
|
{
|
|
string selectedText = filterRarityDropdown.options[index].text;
|
|
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
|
string allString = GetTranslatedString(allOptionTranslated, allOptionFallback, currentLang);
|
|
|
|
currentRarityFilter = (selectedText == allString) ? "All" : selectedText;
|
|
UpdateInventoryUI();
|
|
}
|
|
|
|
private void OnFilterCategoryDropdownChanged(int index)
|
|
{
|
|
string selectedText = filterCategoryDropdown.options[index].text;
|
|
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
|
string allString = GetTranslatedString(allOptionTranslated, allOptionFallback, currentLang);
|
|
|
|
if (selectedText == allString)
|
|
{
|
|
currentCategoryFilter = "All";
|
|
}
|
|
else if (categoryTranslationMap.ContainsKey(selectedText))
|
|
{
|
|
currentCategoryFilter = categoryTranslationMap[selectedText];
|
|
}
|
|
else
|
|
{
|
|
currentCategoryFilter = "All";
|
|
}
|
|
UpdateInventoryUI();
|
|
}
|
|
|
|
private void OnFilterSlotDropdownChanged(int index)
|
|
{
|
|
string selectedText = filterSlotDropdown.options[index].text;
|
|
string currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
|
string allString = GetTranslatedString(allOptionTranslated, allOptionFallback, currentLang);
|
|
|
|
if (selectedText == allString)
|
|
{
|
|
currentSlotFilter = "All";
|
|
}
|
|
else if (slotTranslationMap.ContainsKey(selectedText))
|
|
{
|
|
currentSlotFilter = slotTranslationMap[selectedText];
|
|
}
|
|
else
|
|
{
|
|
currentSlotFilter = "All";
|
|
}
|
|
UpdateInventoryUI();
|
|
}
|
|
|
|
// Sort
|
|
private void OnSortDropdownChanged(int index)
|
|
{
|
|
switch (index)
|
|
{
|
|
case 0:
|
|
SortByRarity(false);
|
|
break;
|
|
case 1:
|
|
SortByRarity(true);
|
|
break;
|
|
case 2:
|
|
SortBySlot();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void SortByRarity(bool descending)
|
|
{
|
|
if (descending)
|
|
spawnedEntries = spawnedEntries.OrderByDescending(e => e.RarityValue()).ToList();
|
|
else
|
|
spawnedEntries = spawnedEntries.OrderBy(e => e.RarityValue()).ToList();
|
|
|
|
ReorderSpawnedEntries();
|
|
}
|
|
|
|
public void SortBySlot()
|
|
{
|
|
spawnedEntries = spawnedEntries.OrderBy(e => e.SlotValue()).ToList();
|
|
ReorderSpawnedEntries();
|
|
}
|
|
|
|
private void ReorderSpawnedEntries()
|
|
{
|
|
for (int i = 0; i < spawnedEntries.Count; i++)
|
|
{
|
|
spawnedEntries[i].transform.SetSiblingIndex(i);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Sends an upgrade request to the backend and refreshes UI based on the result.
|
|
/// </summary>
|
|
public async void UpgradeItem(string uniqueItemGuid, InventoryItem inventorySO, InventoryItemInfo itemInfo)
|
|
{
|
|
if (string.IsNullOrEmpty(uniqueItemGuid) || inventorySO == null)
|
|
return;
|
|
|
|
int oldLevel = InventorySave.GetItemUpgradeLevel(uniqueItemGuid);
|
|
|
|
RequestResult res = await InventorySave.UpgradeItemAsync(uniqueItemGuid, inventorySO);
|
|
|
|
string lang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage();
|
|
string msg;
|
|
bool isError;
|
|
|
|
if (res.Success)
|
|
{
|
|
int newLevel = InventorySave.GetItemUpgradeLevel(uniqueItemGuid);
|
|
|
|
if (newLevel > oldLevel)
|
|
{
|
|
msg = GetTranslatedString(upgradeSuccessTranslated, upgradeSuccessFallback, lang);
|
|
isError = false;
|
|
}
|
|
else if (newLevel < oldLevel)
|
|
{
|
|
msg = GetTranslatedString(levelDecreasedTranslated, levelDecreasedFallback, lang);
|
|
isError = true;
|
|
}
|
|
else
|
|
{
|
|
msg = GetTranslatedString(upgradeFailTranslated, upgradeFailFallback, lang);
|
|
isError = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
msg = res.Reason switch
|
|
{
|
|
"0" => GetTranslatedString(maxLevelReachedTranslated, maxLevelReachedFallback, lang),
|
|
"1" => GetTranslatedString(insufficientCurrencyTranslated, insufficientCurrencyFallback, lang),
|
|
"2" or _ => GetTranslatedString(upgradeFailTranslated, upgradeFailFallback, lang),
|
|
};
|
|
isError = true;
|
|
}
|
|
|
|
ShowMessage(msg, isError);
|
|
|
|
int finalLevel = InventorySave.GetItemUpgradeLevel(uniqueItemGuid);
|
|
if (itemInfo != null)
|
|
{
|
|
bool didLevelUp = finalLevel > oldLevel;
|
|
itemInfo.StartCoroutine(itemInfo.UpgradeProgressRoutine(didLevelUp, 2f));
|
|
itemInfo.UpdateItemInfo(inventorySO, finalLevel);
|
|
}
|
|
|
|
UpdateInventoryUI();
|
|
}
|
|
|
|
|
|
private OptionsTranslate? FindTranslationStruct(OptionsTranslate[] translationsArray, int indexToMatch)
|
|
{
|
|
if (translationsArray == null || translationsArray.Length == 0) return null;
|
|
foreach (var item in translationsArray)
|
|
{
|
|
if (item.optionIndex == indexToMatch)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private IEnumerator ClearMessageAfterDelay(float delay)
|
|
{
|
|
yield return new WaitForSeconds(delay);
|
|
messageText.text = string.Empty;
|
|
}
|
|
|
|
public void ShowMessage(string msg, bool isError)
|
|
{
|
|
messageText.text = msg;
|
|
messageText.color = isError ? Color.red : Color.green;
|
|
StartCoroutine(ClearMessageAfterDelay(3f));
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public struct OptionsTranslate
|
|
{
|
|
public int optionIndex;
|
|
public NameTranslatedByLanguage[] optionsTranslates;
|
|
}
|
|
}
|