From 5fa20c954cbcdcf5077fd7b5dd650a78ebcc612b Mon Sep 17 00:00:00 2001 From: mrtoine Date: Fri, 10 Oct 2025 10:46:01 +0200 Subject: [PATCH] refactorisation du QuestSystem --- .../Core/Runtime/LocalizationSystem.cs | 15 +++++++-- Assets/_/Features/Decor/Runtime/QuestSign.cs | 26 ++++++++++++--- .../Quests/Runtime/QuestInitializer.cs | 17 ++++++---- .../_/Features/Quests/Runtime/QuestManager.cs | 13 ++++---- .../Features/Quests/Runtime/QuestStateEnum.cs | 1 + Assets/_/Features/Quests/Runtime/SaveKeys.cs | 10 ++++++ .../UI/Runtime/Quests/InfoQuestPanel.cs | 33 ++++++++++++++++--- .../UI/Runtime/Quests/InteractionQuestCard.cs | 1 + .../Features/UI/Runtime/Quests/QuestCardUI.cs | 20 ++++++++--- .../UI/Runtime/Quests/QuestsBoardPanel.cs | 18 ++++++++-- .../Features/UI/Runtime/Quests/QuestsPanel.cs | 13 ++++---- 11 files changed, 128 insertions(+), 39 deletions(-) create mode 100644 Assets/_/Features/Quests/Runtime/SaveKeys.cs diff --git a/Assets/_/Features/Core/Runtime/LocalizationSystem.cs b/Assets/_/Features/Core/Runtime/LocalizationSystem.cs index a4ed5eeb..ffe6518e 100644 --- a/Assets/_/Features/Core/Runtime/LocalizationSystem.cs +++ b/Assets/_/Features/Core/Runtime/LocalizationSystem.cs @@ -45,10 +45,19 @@ namespace Core.Runtime public string GetLocalizedText(string key) { - if (GameManager.Instance.GetLocalTexts.TryGetValue(key, out var value)) + // Guard against null or empty keys + if (string.IsNullOrEmpty(key)) + { + return string.Empty; + } + + // Guard against missing dictionary + var dict = GameManager.Instance?.GetLocalTexts; + if (dict != null && dict.TryGetValue(key, out var value)) return value; - - return $"{key}"; + + // Fallback: return the key itself so UI shows something meaningful + return key; } public void SaveLanguage(string newLanguage) diff --git a/Assets/_/Features/Decor/Runtime/QuestSign.cs b/Assets/_/Features/Decor/Runtime/QuestSign.cs index f67c8d73..4b5bf8b5 100644 --- a/Assets/_/Features/Decor/Runtime/QuestSign.cs +++ b/Assets/_/Features/Decor/Runtime/QuestSign.cs @@ -29,11 +29,29 @@ namespace Decor.Runtime void Start() { - //UpdateParchmentState(); - Info($"Il y a actuellement {_quests} quêtes affichés sur le Panneau"); + // Trigger an initial refresh + QuestManager.Instance.NotifyAvailableQuestsUpdated(_player.GuildLevel); + UpdateParchmentState(); } - void Update() + void OnEnable() + { + QuestManager.OnAvailableQuestsUpdated += HandleAvailableChanged; + QuestManager.OnQuestCompleted += HandleQuestCompleted; + } + + void OnDisable() + { + QuestManager.OnAvailableQuestsUpdated -= HandleAvailableChanged; + QuestManager.OnQuestCompleted -= HandleQuestCompleted; + } + + void HandleAvailableChanged(System.Collections.Generic.List _) + { + UpdateParchmentState(); + } + + void HandleQuestCompleted(QuestClass _) { UpdateParchmentState(); } @@ -66,8 +84,6 @@ namespace Decor.Runtime ) ); _parchment.SetActive(hasTrulyAvailableQuests); - - Info($"Il y a actuellement {hasTrulyAvailableQuests} disponibles"); } #endregion diff --git a/Assets/_/Features/Quests/Runtime/QuestInitializer.cs b/Assets/_/Features/Quests/Runtime/QuestInitializer.cs index c2ee00b1..60858dfc 100644 --- a/Assets/_/Features/Quests/Runtime/QuestInitializer.cs +++ b/Assets/_/Features/Quests/Runtime/QuestInitializer.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Core.Runtime; using Quest.Runtime; +using Quests.Runtime; using UnityEngine; namespace Quests.Runtime._.Features.Quests @@ -15,16 +16,20 @@ namespace Quests.Runtime._.Features.Quests void Start() { - if (!FactExists>("active_quests", out var _)) + if (!FactExists>(SaveKeys.Active, out var _)) { - SetFact>("active_quests", new List(), FactPersistence.Persistent); + SetFact>(SaveKeys.Active, new List(), FactPersistence.Persistent); } - QuestManager.Instance.ActiveQuests = GetFact>("active_quests"); - if (!FactExists>("active_quests", out var _)) + QuestManager.Instance.ActiveQuests = GetFact>(SaveKeys.Active); + if (!FactExists>(SaveKeys.Completed, out var _)) { - SetFact>("completed_quests", new List(), FactPersistence.Persistent); + SetFact>(SaveKeys.Completed, new List(), FactPersistence.Persistent); + } + QuestManager.Instance.CompletedQuests = GetFact>(SaveKeys.Completed); + if (!FactExists>>(SaveKeys.EventLogs, out var _)) + { + SetFact>>(SaveKeys.EventLogs, new Dictionary>(), FactPersistence.Persistent); } - QuestManager.Instance.CompletedQuests = GetFact>("completed_quests"); Invoke(nameof(NotifyLater), 0.1f); } diff --git a/Assets/_/Features/Quests/Runtime/QuestManager.cs b/Assets/_/Features/Quests/Runtime/QuestManager.cs index c09902af..cc30cf6b 100644 --- a/Assets/_/Features/Quests/Runtime/QuestManager.cs +++ b/Assets/_/Features/Quests/Runtime/QuestManager.cs @@ -72,6 +72,7 @@ namespace Quests.Runtime public QuestManager() { + _activeEvents = new List(); GameManager.OnTimeAdvanced += CheckMissionsProgress; } @@ -119,7 +120,7 @@ namespace Quests.Runtime { QuestClass quest = GetQuestById(questId); - List events = GetFact>>("events_quests_history")[questId]; + List events = GetFact>>(SaveKeys.EventLogs)[questId]; return new QuestSummary(quest, events); } @@ -137,8 +138,8 @@ namespace Quests.Runtime /// public bool IsQuestCompleted(string questName) { - return ActiveQuests != null - && ActiveQuests.Any(q => q.Name == questName && q.State == QuestStateEnum.Completed); + return CompletedQuests != null + && CompletedQuests.Any(q => q.Name == questName); } /// @@ -207,7 +208,7 @@ namespace Quests.Runtime void UpdateQuestStatus(QuestClass quest) { _activeQuests.Add(quest); - List saveQuests = GetFact>("quests"); + List saveQuests = GetFact>(SaveKeys.All); foreach (var saveQuest in saveQuests) { if (saveQuest.Name == quest.Name) @@ -242,7 +243,7 @@ namespace Quests.Runtime _activeQuests.RemoveAll(q => q.Name == quest.Name); _completedQuests.Add(quest); - List quests = GetFact>("quests"); + List quests = GetFact>(SaveKeys.All); QuestClass questToUpdate = quests.FirstOrDefault(q => q.ID == quest.ID); if (questToUpdate != null) { @@ -319,7 +320,7 @@ namespace Quests.Runtime var targets = questEvent.GetTargets(quest.AssignedAdventurersID); ApplyEffect(questEvent.Effects, targets); - Dictionary> events = GetFact>>("events_quests_history"); + Dictionary> events = GetFact>>(SaveKeys.EventLogs); if(!events.ContainsKey(quest.ID)) { diff --git a/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs b/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs index 5feda78b..e70fd094 100644 --- a/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs +++ b/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs @@ -3,6 +3,7 @@ namespace Quests.Runtime public enum QuestStateEnum { Disponible, + Accepted, Active, Completed, } diff --git a/Assets/_/Features/Quests/Runtime/SaveKeys.cs b/Assets/_/Features/Quests/Runtime/SaveKeys.cs new file mode 100644 index 00000000..ec2abbd9 --- /dev/null +++ b/Assets/_/Features/Quests/Runtime/SaveKeys.cs @@ -0,0 +1,10 @@ +namespace Quests.Runtime +{ + public static class SaveKeys + { + public const string Active = "active_quests"; + public const string Completed = "completed_quests"; + public const string All = "quests"; // legacy/misc list if still used elsewhere + public const string EventLogs = "events_quests_history"; + } +} \ No newline at end of file diff --git a/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs b/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs index ae171ab9..07ccb14f 100644 --- a/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs +++ b/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs @@ -108,6 +108,12 @@ namespace GameUI.Runtime _panelRecap.SetActive(true); _panelRecap.GetComponent().ShowFor(QuestManager.Instance.CurrentQuest.ID); break; + case QuestStateEnum.Accepted: + _buttonActivation.SetActive(true); + _adventurersOnThisQuestPanel.SetActive(false); + _adventurersSelection.SetActive(true); + _panelRecap.SetActive(false); + break; case QuestStateEnum.Active: Info("La quête est active."); _buttonActivation.SetActive(false); @@ -146,15 +152,16 @@ namespace GameUI.Runtime #region Quest Operations private QuestClass FindMatchingActiveQuest(QuestClass quest) { - if (!FactExists>("active_quests", out _)) return quest; + if (!FactExists>(SaveKeys.Active, out _)) return quest; - var activeQuests = GetFact>("active_quests"); + var activeQuests = GetFact>(SaveKeys.Active); var matchingQuest = activeQuests.FirstOrDefault(q => q.ID == quest.ID); return matchingQuest ?? quest; } private void UpdateQuestInfoDisplay(QuestClass quest) { + Info($"UpdateQuestInfoDisplay : {quest.Name}"); m_title.text = LocalizationSystem.Instance.GetLocalizedText(quest?.Name); string descKey = quest?.Description; if (string.IsNullOrEmpty(descKey)) @@ -171,9 +178,25 @@ namespace GameUI.Runtime var gameTime = GetFact("game_time"); QuestManager.Instance.StartQuest(QuestManager.Instance.CurrentQuest, _adventurersSelected, gameTime); - // Ajouter la quête à la liste des quêtes actives - var activeQuests = GetFact>("active_quests"); - activeQuests.Add(QuestManager.Instance.CurrentQuest); + // Mettre à jour la quête dans la liste des quêtes acceptées (Active repo) + var activeQuests = GetFact>(SaveKeys.Active); + var idx = activeQuests.FindIndex(q => q.ID == QuestManager.Instance.CurrentQuest.ID); + if (idx >= 0) + { + activeQuests[idx].State = QuestStateEnum.Active; + activeQuests[idx].StartSeconds = QuestManager.Instance.CurrentQuest.StartSeconds; + activeQuests[idx].EndSeconds = QuestManager.Instance.CurrentQuest.EndSeconds; + } + else + { + // fallback: if not found, add it once + activeQuests.Add(QuestManager.Instance.CurrentQuest); + } + SaveFacts(); + // Notify panels + QuestSignals.RaiseRefreshQuests(); + var player = GetFact(GameManager.Instance.Profile); + QuestManager.Instance.NotifyAvailableQuestsUpdated(player.GuildLevel); } private void CleanupAfterQuestLaunch() diff --git a/Assets/_/Features/UI/Runtime/Quests/InteractionQuestCard.cs b/Assets/_/Features/UI/Runtime/Quests/InteractionQuestCard.cs index de9bab06..9eeb326d 100644 --- a/Assets/_/Features/UI/Runtime/Quests/InteractionQuestCard.cs +++ b/Assets/_/Features/UI/Runtime/Quests/InteractionQuestCard.cs @@ -16,6 +16,7 @@ namespace GameUI.Runtime public void SetQuest(QuestClass quest) { + Info($"SetQuest : {quest.Name}"); _quest = quest; } diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs b/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs index aa53a6c5..dede39e1 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs @@ -57,11 +57,21 @@ namespace GameUI.Runtime public void AcceptQuest() { - List quests = GetFact>("quests"); - quests.Add(_quest); - SaveFacts(); - QuestSignals.RaiseRefreshQuests(); - Destroy(gameObject); + // Mark as accepted and add to accepted (active list used as accepted repository for now) + _quest.State = QuestStateEnum.Accepted; + List active = GetFact>(SaveKeys.Active); + // Idempotency: avoid duplicates + bool alreadyThere = active.Any(q => q.ID == _quest.ID || q.Name == _quest.Name); + if (!alreadyThere) + { + active.Add(_quest); + SaveFacts(); + } + // Notify panels + QuestSignals.RaiseRefreshQuests(); // refresh QuestsPanel + var player = GetFact(GameManager.Instance.Profile); + QuestManager.Instance.NotifyAvailableQuestsUpdated(player.GuildLevel); // refresh board availability + Destroy(gameObject); } #endregion diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs b/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs index c720a2c9..30a87215 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs @@ -65,13 +65,25 @@ namespace GameUI.Runtime void DisplayAvailableQuests(List availableTemplates, List acceptedQuests) { - foreach (var quest in availableTemplates) + // Build a set of started quest IDs (Accepted/Active + Completed) + var startedIds = new HashSet(); + foreach (var q in QuestManager.Instance.ActiveQuests ?? new List()) { - if (acceptedQuests.Any(q => q.Name == quest.data.Name)) + if (q.ID != System.Guid.Empty) startedIds.Add(q.ID); + } + foreach (var q in QuestManager.Instance.CompletedQuests ?? new List()) + { + if (q.ID != System.Guid.Empty) startedIds.Add(q.ID); + } + + foreach (var template in availableTemplates) + { + // Skip if this template already started (by GUID) + if (System.Guid.TryParse(template.m_assetGuid, out var guid) && startedIds.Contains(guid)) { continue; } - DisplayCard(quest); + DisplayCard(template); } } diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestsPanel.cs b/Assets/_/Features/UI/Runtime/Quests/QuestsPanel.cs index 02b62fe1..aba8a011 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestsPanel.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestsPanel.cs @@ -44,14 +44,13 @@ namespace GameUI.Runtime Destroy(child.gameObject); } - if (FactExists>("quests", out _)) + if (FactExists>(SaveKeys.Active, out _)) { - List questsFromSave = GetFact>("quests"); - - List quests = QuestManager.Instance.ResolveQuestsList(questsFromSave); - foreach (var quest in quests) + // Show only accepted quests in this panel + List accepted = GetFact>(SaveKeys.Active); + foreach (var quest in accepted.Where(q => q.State == QuestStateEnum.Accepted)) { - DisplayQuest(quest); //=> Key : L'id de la quête, Value : Le State + DisplayQuest(quest); } } } @@ -70,6 +69,8 @@ namespace GameUI.Runtime questMini.m_check?.SetActive(isCompleted); } + Info($"On affiche la quete : {quest.Name}"); + questGO.GetComponent().SetQuest(quest); }