diff --git a/Assets/_/Features/Decor/Runtime/QuestSign.cs b/Assets/_/Features/Decor/Runtime/QuestSign.cs index f67c8d73..6ea3efa6 100644 --- a/Assets/_/Features/Decor/Runtime/QuestSign.cs +++ b/Assets/_/Features/Decor/Runtime/QuestSign.cs @@ -29,11 +29,30 @@ namespace Decor.Runtime void Start() { - //UpdateParchmentState(); + // Trigger an initial refresh + QuestManager.Instance.NotifyAvailableQuestsUpdated(_player.GuildLevel); Info($"Il y a actuellement {_quests} quêtes affichés sur le Panneau"); + 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(); } diff --git a/Assets/_/Features/Quests/Runtime/QuestManager.cs b/Assets/_/Features/Quests/Runtime/QuestManager.cs index c09902af..5ddf769f 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; } @@ -84,6 +85,12 @@ namespace Quests.Runtime /// public void StartQuest(QuestClass quest, List team, GameTime gameTime) { + // Enforce state order: must be Accepted before starting + if (quest.State != QuestStateEnum.Accepted) + { + Debug.LogWarning($"Cannot start quest '{quest.Name}' because it is not in Accepted state (current: {quest.State})."); + return; + } AssignAdventurersToQuest(quest, team); SetQuestTimings(quest, gameTime); UpdateQuestStatus(quest); @@ -94,7 +101,7 @@ namespace Quests.Runtime /// public void CompleteQuest(QuestClass quest, List team) { - if (quest.State != QuestStateEnum.Active) return; + if (quest.State != QuestStateEnum.InProgress) return; ReleaseAdventurers(team); UpdateQuestCompletionStatus(quest); @@ -129,7 +136,8 @@ namespace Quests.Runtime /// public bool CanSelectedAdventurers() { - return _currentQuest != null && _currentQuest.State == QuestStateEnum.Disponible; + // Adventurers can be selected only when the quest has been accepted + return _currentQuest != null && _currentQuest.State == QuestStateEnum.Accepted; } /// @@ -138,7 +146,7 @@ namespace Quests.Runtime public bool IsQuestCompleted(string questName) { return ActiveQuests != null - && ActiveQuests.Any(q => q.Name == questName && q.State == QuestStateEnum.Completed); + && ActiveQuests.Any(q => q.Name == questName); } /// @@ -196,7 +204,7 @@ namespace Quests.Runtime /// void SetQuestTimings(QuestClass quest, GameTime gameTime) { - quest.State = QuestStateEnum.Active; + quest.State = QuestStateEnum.InProgress; quest.StartSeconds = gameTime.TotalSeconds; quest.EndSeconds = gameTime.TotalSeconds + (quest.Duration * 60); } @@ -206,13 +214,17 @@ namespace Quests.Runtime /// void UpdateQuestStatus(QuestClass quest) { - _activeQuests.Add(quest); + // Avoid duplicates in active quests + if (_activeQuests.All(q => q.ID != quest.ID)) + { + _activeQuests.Add(quest); + } List saveQuests = GetFact>("quests"); foreach (var saveQuest in saveQuests) { if (saveQuest.Name == quest.Name) { - saveQuest.State = QuestStateEnum.Active; + saveQuest.State = QuestStateEnum.InProgress; saveQuest.StartSeconds = quest.StartSeconds; saveQuest.EndSeconds = quest.EndSeconds; } @@ -268,14 +280,14 @@ namespace Quests.Runtime if(_activeQuests == null) return; var questsToComplete = new List(); - var activeQuests = _activeQuests.Where(q => q.State == QuestStateEnum.Active).ToList(); + var activeQuests = _activeQuests.Where(q => q.State == QuestStateEnum.InProgress).ToList(); foreach (var quest in activeQuests) { _snapTime = currentSeconds - quest.StartSeconds; CheckQuestEvents(quest, currentSeconds); - if (quest.State == QuestStateEnum.Active && currentSeconds >= quest.EndSeconds) + if (quest.State == QuestStateEnum.InProgress && currentSeconds >= quest.EndSeconds) { questsToComplete.Add(quest); } diff --git a/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs b/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs index 5feda78b..29c1faca 100644 --- a/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs +++ b/Assets/_/Features/Quests/Runtime/QuestStateEnum.cs @@ -3,7 +3,8 @@ namespace Quests.Runtime public enum QuestStateEnum { Disponible, - Active, + Accepted, + InProgress, Completed, } } diff --git a/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs b/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs index ae171ab9..f5e02fb9 100644 --- a/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs +++ b/Assets/_/Features/UI/Runtime/Quests/InfoQuestPanel.cs @@ -97,8 +97,17 @@ namespace GameUI.Runtime switch (state) { case QuestStateEnum.Disponible: + // Before acceptance: can see info but shouldn't assign adventurers yet + _buttonActivation.SetActive(false); + _adventurersOnThisQuestPanel.SetActive(false); + _adventurersSelection.SetActive(false); + _panelRecap.SetActive(false); + break; + case QuestStateEnum.Accepted: + // After acceptance: allow selecting adventurers and launching the quest _buttonActivation.SetActive(true); _adventurersOnThisQuestPanel.SetActive(false); + _adventurersSelection.SetActive(true); _panelRecap.SetActive(false); break; case QuestStateEnum.Completed: @@ -108,7 +117,7 @@ namespace GameUI.Runtime _panelRecap.SetActive(true); _panelRecap.GetComponent().ShowFor(QuestManager.Instance.CurrentQuest.ID); break; - case QuestStateEnum.Active: + case QuestStateEnum.InProgress: Info("La quête est active."); _buttonActivation.SetActive(false); _adventurersOnThisQuestPanel.SetActive(true); diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs b/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs index aa53a6c5..b574b847 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestCardUI.cs @@ -57,10 +57,32 @@ namespace GameUI.Runtime public void AcceptQuest() { - List quests = GetFact>("quests"); - quests.Add(_quest); + // Ensure state order: Disponible -> Accepted + _quest.State = QuestStateEnum.Accepted; + + // Persist in saved quests list + List savedQuests = GetFact>("quests"); + savedQuests.Add(_quest); + + // Also add to runtime active quests list so other systems can find it + if (FactExists>("active_quests", out _)) + { + var activeQuests = GetFact>("active_quests"); + // Avoid duplicates by GUID + if (!activeQuests.Any(q => q.ID == _quest.ID)) + { + activeQuests.Add(_quest); + } + } + SaveFacts(); + + // Refresh quest UIs and availability board QuestSignals.RaiseRefreshQuests(); + var player = GetFact(GameManager.Instance.Profile); + QuestManager.Instance.NotifyAvailableQuestsUpdated(player.GuildLevel); + + // Remove the accepted card from the board Destroy(gameObject); } diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestMini.cs b/Assets/_/Features/UI/Runtime/Quests/QuestMini.cs index e9c32725..79cee6da 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestMini.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestMini.cs @@ -58,7 +58,7 @@ namespace GameUI.Runtime m_check.SetActive(false); m_hourglass.SetActive(false); break; - case QuestStateEnum.Active: + case QuestStateEnum.InProgress: m_check.SetActive(false); m_hourglass.SetActive(true); break; diff --git a/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs b/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs index c720a2c9..df691f08 100644 --- a/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs +++ b/Assets/_/Features/UI/Runtime/Quests/QuestsBoardPanel.cs @@ -65,15 +65,27 @@ 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); } - } + } void DisplayCard(QuestTemplate quest) {