using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using TMPro; using UnityEngine; using static UnityEngine.EventSystems.EventTrigger; namespace BulletHellTemplate { /// /// Manages the maps UI menu, including loading standard and event maps. /// Adapted for offline mode by completely removing Firebase dependencies. /// public class UIMapsMenu : MonoBehaviour { #region Map Entry Settings /// /// Prefab for standard map entries in the UI. /// [Tooltip("Prefab for standard map entries in the UI.")] public MapEntry mapEntryPrefab; /// /// Container for standard map entries. /// [Tooltip("Container for standard map entries.")] public Transform mapContainer; /// /// Prefab for event map entries in the UI. /// [Tooltip("Prefab for event map entries in the UI.")] public MapEntry eventMapEntryPrefab; /// /// Container for event map entries. /// [Tooltip("Container for event map entries.")] public Transform eventMapContainer; #endregion #region Event Map Settings /// /// Bypass Firebase check and display all event maps. /// [Tooltip("Bypass Firebase check and display all event maps")] public bool alwaysShowEventMap; #endregion #region UI Elements /// /// Text component for error messages. /// [Tooltip("Text component for error messages")] public TextMeshProUGUI errorMessage; /// /// Difficulty label. /// public string difficulty = "Difficulty:"; /// /// Translated difficulty labels. /// public NameTranslatedByLanguage[] difficultyTranslated; /// /// Fallback string for insufficient currency. /// public string insufficientCurrency = "Insufficient Tickets!"; /// /// Translated messages for insufficient currency. /// public NameTranslatedByLanguage[] insufficientCurrencyTranslated; #endregion #region Private Variables private List mapEntries = new List(); public static UIMapsMenu Singleton; private string currentLang; #endregion #region Unity Callbacks private void Awake() { if (Singleton == null) { Singleton = this; } else { Destroy(gameObject); } } private void OnEnable() { currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); StartCoroutine(LoadMapsCoroutine()); } #endregion #region Map Loading /// /// Coroutine that loads and processes map entries. /// private IEnumerator LoadMapsCoroutine() { ClearMapEntries(); if (GameInstance.Singleton == null || GameInstance.Singleton.mapInfoData == null) { Debug.LogError("Missing GameInstance or map data"); yield break; } List allMaps = new List(GameInstance.Singleton.mapInfoData); for (int i = 0; i < allMaps.Count; i++) { MapInfoData current = allMaps[i]; if (!current.isEventMap) { CreateStandardMapEntry(current); } else { yield return StartCoroutine(ProcessEventMap(current)); } } } /// /// Creates a standard map entry UI element. /// /// Map information data. /// The created map entry. private MapEntry CreateStandardMapEntry(MapInfoData mapData) { MapEntry entry = Instantiate(mapEntryPrefab, mapContainer); string mapNameTranslated = GetTranslatedString(mapData.mapNameTranslated, mapData.mapName, currentLang); string mapDescriptionTranslated = GetTranslatedString(mapData.mapDescriptionTranslated, mapData.mapDescription, currentLang); string difficultyTranslatedStr = GetTranslatedString(difficultyTranslated, difficulty, currentLang); entry.Setup(mapData, mapNameTranslated, mapDescriptionTranslated, difficultyTranslatedStr, IsMapUnlocked(mapData)); mapEntries.Add(entry); return entry; } /// /// Processes event map entries. /// /// Map information data for event map. private IEnumerator ProcessEventMap(MapInfoData mapData) { bool shouldDisplay = alwaysShowEventMap; if (shouldDisplay) { MapEntry eventEntry = Instantiate(eventMapEntryPrefab, eventMapContainer); string mapNameTranslated = GetTranslatedString(mapData.mapNameTranslated, mapData.mapName, currentLang); string mapDescriptionTranslated = GetTranslatedString(mapData.mapDescriptionTranslated, mapData.mapDescription, currentLang); string difficultyTranslatedStr = GetTranslatedString(difficultyTranslated, difficulty, currentLang); eventEntry.Setup(mapData, mapNameTranslated, mapDescriptionTranslated, difficultyTranslatedStr, IsMapUnlocked(mapData)); mapEntries.Add(eventEntry); } yield return null; } /// /// Clears all map entries from the UI containers. /// private void ClearMapEntries() { foreach (Transform child in mapContainer) Destroy(child.gameObject); foreach (Transform child in eventMapContainer) Destroy(child.gameObject); mapEntries.Clear(); } /// /// Reloads the map entries. /// public void ReloadMaps() { StartCoroutine(LoadMapsCoroutine()); } #endregion #region Map Unlocking and Translation /// /// Determines if a map is unlocked. /// /// Map information data. /// True if unlocked; otherwise, false. /// Retorna true se o mapa estiver jogável. private bool IsMapUnlocked(MapInfoData mapData) { if (mapData.isUnlocked) return true; if (PlayerSave.GetUnlockedMaps().Contains(mapData.mapId)) return true; foreach (var m in GameInstance.Singleton.mapInfoData) { if (m.isEventMap) continue; return m.mapId == mapData.mapId; } return false; } /// /// Retrieves a translated string based on the current language. /// /// Array of translations. /// Fallback string if no translation is found. /// Current language ID. /// Translated string. 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; } /// /// Retrieves a translated string for map descriptions based on the current language. /// /// Array of description translations. /// Fallback description if no translation is found. /// Current language ID. /// Translated description. private string GetTranslatedString(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; } #endregion #region Error Display /// /// Displays an error message for a specified duration. /// /// Duration in seconds to display the error message. /// IEnumerator for coroutine. public IEnumerator ShowErrorMessage(float duration) { string errorTranslated = GetTranslatedString(insufficientCurrencyTranslated, insufficientCurrency, currentLang); errorMessage.text = errorTranslated; yield return new WaitForSeconds(duration); errorMessage.text = ""; } #endregion } }