using Cysharp.Threading.Tasks; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace BulletHellTemplate { /// /// Manages the display of quests in the UI. /// Displays available quests, handles quest completion logic, /// and can optionally hide completed quests. /// public class UIQuestMenu : MonoBehaviour { #region Singleton and Public Fields [Tooltip("Prefab for individual quest entries")] public QuestEntry questEntryPrefab; [Tooltip("Container where quest entries will be instantiated")] public Transform container; /// /// Singleton reference for global access to UIQuestMenu. /// public static UIQuestMenu Singleton; [Tooltip("Whether or not to hide completed quests from the UI")] public bool hideCompletedQuests; /// /// Current language code or identifier used by the UI. /// [HideInInspector] public string currentLang; #endregion #region Unity Callbacks /// /// Initializes the singleton reference on startup. /// private void Start() { Singleton = this; } /// /// Called when the object becomes enabled and active. /// Sets the current language and loads quests into the UI. /// private void OnEnable() { currentLang = LanguageManager.LanguageManager.Instance.GetCurrentLanguage(); LoadQuestsAsync().Forget(); } #endregion #region Public Methods private async UniTaskVoid LoadQuestsAsync() { await BackendManager.Service.RefreshQuestLevelProgressAsync(); LoadQuests(); } /// /// Loads and displays the available quests in the UI. /// If 'hideCompletedQuests' is true, completed quests (except repeat) will be skipped. /// Otherwise, all quests are shown, with an indicator for those that are completed. /// Additionally, it checks if the player's level or characters' levels /// exceed any quest requirements to set progress to 100%. /// public void LoadQuests() { // Clear containerPassItems foreach (Transform child in container) Destroy(child.gameObject); List allQuests = GameInstance.Singleton.questData.ToList(); foreach (QuestItem quest in allQuests) { bool isCompleted = PlayerSave.IsQuestCompleted(quest.questId); if (hideCompletedQuests && quest.questType != QuestType.Repeat && isCompleted) continue; var entry = Instantiate(questEntryPrefab, container); string title = GetTranslatedString(quest.titleTranslated, quest.title, currentLang); string desc = GetTranslatedString(quest.descriptionTranslated, quest.description, currentLang); entry.Setup(title, desc, quest, isCompleted); int progress = PlayerSave.LoadQuestProgress(quest.questId); int target = quest.requirement.targetAmount; entry.UpdateProgress(progress, target); } } /// /// Called by the QuestEntry when the player tries to complete the quest. /// Checks if the quest is indeed completable, then applies rewards. /// Marks the quest as completed or resets its progress if it's a repeat quest. /// Finally, reloads the quest UI for updated feedback. /// /// The quest item the player is attempting to complete. public async void OnUserAttemptCompleteQuest(QuestItem quest) { if (quest == null) return; RequestResult res = await BackendManager.Service.CompleteQuestAsync(quest.questId); if (!res.Success) { string msg = res.Reason switch { "0" => "Already completed!", "1" => "Not enough progress!", "2" => "Quest not found!", _ => "Unknown error" }; Debug.LogWarning(msg); return; } // Reload UI to reflect new state LoadQuests(); } /// /// Returns a translated string according to the current language /// or a fallback string if no translation is found. /// /// An array of translations for different languages. /// The default (fallback) string if no matching translation is found. /// The language code or identifier currently in use. /// A string in the user's selected language, or the fallback if none is found. public 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; } /// /// Returns a translated description string according to the current language /// or a fallback string if no translation is found. /// /// An array of description translations for different languages. /// The default (fallback) string if no matching translation is found. /// The language code or identifier currently in use. /// A string in the user's selected language, or the fallback if none is found. public 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 } }