Update du système de quêtes. Refactorisation et redefinission des états d'une quête.

This commit is contained in:
mrtoine 2025-10-10 14:25:05 +02:00
parent 2370cb670d
commit 3dbddc57ae
7 changed files with 94 additions and 19 deletions

View file

@ -29,11 +29,30 @@ namespace Decor.Runtime
void Start() void Start()
{ {
//UpdateParchmentState(); // Trigger an initial refresh
QuestManager.Instance.NotifyAvailableQuestsUpdated(_player.GuildLevel);
Info($"<color=yellow>Il y a actuellement {_quests} quêtes affichés sur le Panneau</color>"); Info($"<color=yellow>Il y a actuellement {_quests} quêtes affichés sur le Panneau</color>");
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<QuestTemplate> _)
{
UpdateParchmentState();
}
void HandleQuestCompleted(QuestClass _)
{ {
UpdateParchmentState(); UpdateParchmentState();
} }

View file

@ -72,6 +72,7 @@ namespace Quests.Runtime
public QuestManager() public QuestManager()
{ {
_activeEvents = new List<QuestEvent>();
GameManager.OnTimeAdvanced += CheckMissionsProgress; GameManager.OnTimeAdvanced += CheckMissionsProgress;
} }
@ -84,6 +85,12 @@ namespace Quests.Runtime
/// </summary> /// </summary>
public void StartQuest(QuestClass quest, List<AdventurerClass> team, GameTime gameTime) public void StartQuest(QuestClass quest, List<AdventurerClass> 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); AssignAdventurersToQuest(quest, team);
SetQuestTimings(quest, gameTime); SetQuestTimings(quest, gameTime);
UpdateQuestStatus(quest); UpdateQuestStatus(quest);
@ -94,7 +101,7 @@ namespace Quests.Runtime
/// </summary> /// </summary>
public void CompleteQuest(QuestClass quest, List<Guid> team) public void CompleteQuest(QuestClass quest, List<Guid> team)
{ {
if (quest.State != QuestStateEnum.Active) return; if (quest.State != QuestStateEnum.InProgress) return;
ReleaseAdventurers(team); ReleaseAdventurers(team);
UpdateQuestCompletionStatus(quest); UpdateQuestCompletionStatus(quest);
@ -129,7 +136,8 @@ namespace Quests.Runtime
/// </summary> /// </summary>
public bool CanSelectedAdventurers() 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;
} }
/// <summary> /// <summary>
@ -138,7 +146,7 @@ namespace Quests.Runtime
public bool IsQuestCompleted(string questName) public bool IsQuestCompleted(string questName)
{ {
return ActiveQuests != null return ActiveQuests != null
&& ActiveQuests.Any(q => q.Name == questName && q.State == QuestStateEnum.Completed); && ActiveQuests.Any(q => q.Name == questName);
} }
/// <summary> /// <summary>
@ -196,7 +204,7 @@ namespace Quests.Runtime
/// </summary> /// </summary>
void SetQuestTimings(QuestClass quest, GameTime gameTime) void SetQuestTimings(QuestClass quest, GameTime gameTime)
{ {
quest.State = QuestStateEnum.Active; quest.State = QuestStateEnum.InProgress;
quest.StartSeconds = gameTime.TotalSeconds; quest.StartSeconds = gameTime.TotalSeconds;
quest.EndSeconds = gameTime.TotalSeconds + (quest.Duration * 60); quest.EndSeconds = gameTime.TotalSeconds + (quest.Duration * 60);
} }
@ -205,14 +213,18 @@ namespace Quests.Runtime
/// Met à jour le statut d'une quête dans les listes actives et sauvegardées /// Met à jour le statut d'une quête dans les listes actives et sauvegardées
/// </summary> /// </summary>
void UpdateQuestStatus(QuestClass quest) void UpdateQuestStatus(QuestClass quest)
{
// Avoid duplicates in active quests
if (_activeQuests.All(q => q.ID != quest.ID))
{ {
_activeQuests.Add(quest); _activeQuests.Add(quest);
}
List<QuestClass> saveQuests = GetFact<List<QuestClass>>("quests"); List<QuestClass> saveQuests = GetFact<List<QuestClass>>("quests");
foreach (var saveQuest in saveQuests) foreach (var saveQuest in saveQuests)
{ {
if (saveQuest.Name == quest.Name) if (saveQuest.Name == quest.Name)
{ {
saveQuest.State = QuestStateEnum.Active; saveQuest.State = QuestStateEnum.InProgress;
saveQuest.StartSeconds = quest.StartSeconds; saveQuest.StartSeconds = quest.StartSeconds;
saveQuest.EndSeconds = quest.EndSeconds; saveQuest.EndSeconds = quest.EndSeconds;
} }
@ -268,14 +280,14 @@ namespace Quests.Runtime
if(_activeQuests == null) return; if(_activeQuests == null) return;
var questsToComplete = new List<QuestClass>(); var questsToComplete = new List<QuestClass>();
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) foreach (var quest in activeQuests)
{ {
_snapTime = currentSeconds - quest.StartSeconds; _snapTime = currentSeconds - quest.StartSeconds;
CheckQuestEvents(quest, currentSeconds); CheckQuestEvents(quest, currentSeconds);
if (quest.State == QuestStateEnum.Active && currentSeconds >= quest.EndSeconds) if (quest.State == QuestStateEnum.InProgress && currentSeconds >= quest.EndSeconds)
{ {
questsToComplete.Add(quest); questsToComplete.Add(quest);
} }

View file

@ -3,7 +3,8 @@ namespace Quests.Runtime
public enum QuestStateEnum public enum QuestStateEnum
{ {
Disponible, Disponible,
Active, Accepted,
InProgress,
Completed, Completed,
} }
} }

View file

@ -97,8 +97,17 @@ namespace GameUI.Runtime
switch (state) switch (state)
{ {
case QuestStateEnum.Disponible: 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); _buttonActivation.SetActive(true);
_adventurersOnThisQuestPanel.SetActive(false); _adventurersOnThisQuestPanel.SetActive(false);
_adventurersSelection.SetActive(true);
_panelRecap.SetActive(false); _panelRecap.SetActive(false);
break; break;
case QuestStateEnum.Completed: case QuestStateEnum.Completed:
@ -108,7 +117,7 @@ namespace GameUI.Runtime
_panelRecap.SetActive(true); _panelRecap.SetActive(true);
_panelRecap.GetComponent<QuestLogsListUI>().ShowFor(QuestManager.Instance.CurrentQuest.ID); _panelRecap.GetComponent<QuestLogsListUI>().ShowFor(QuestManager.Instance.CurrentQuest.ID);
break; break;
case QuestStateEnum.Active: case QuestStateEnum.InProgress:
Info("La quête est active."); Info("La quête est active.");
_buttonActivation.SetActive(false); _buttonActivation.SetActive(false);
_adventurersOnThisQuestPanel.SetActive(true); _adventurersOnThisQuestPanel.SetActive(true);

View file

@ -57,10 +57,32 @@ namespace GameUI.Runtime
public void AcceptQuest() public void AcceptQuest()
{ {
List<QuestClass> quests = GetFact<List<QuestClass>>("quests"); // Ensure state order: Disponible -> Accepted
quests.Add(_quest); _quest.State = QuestStateEnum.Accepted;
// Persist in saved quests list
List<QuestClass> savedQuests = GetFact<List<QuestClass>>("quests");
savedQuests.Add(_quest);
// Also add to runtime active quests list so other systems can find it
if (FactExists<List<QuestClass>>("active_quests", out _))
{
var activeQuests = GetFact<List<QuestClass>>("active_quests");
// Avoid duplicates by GUID
if (!activeQuests.Any(q => q.ID == _quest.ID))
{
activeQuests.Add(_quest);
}
}
SaveFacts(); SaveFacts();
// Refresh quest UIs and availability board
QuestSignals.RaiseRefreshQuests(); QuestSignals.RaiseRefreshQuests();
var player = GetFact<Player.Runtime.PlayerClass>(GameManager.Instance.Profile);
QuestManager.Instance.NotifyAvailableQuestsUpdated(player.GuildLevel);
// Remove the accepted card from the board
Destroy(gameObject); Destroy(gameObject);
} }

View file

@ -58,7 +58,7 @@ namespace GameUI.Runtime
m_check.SetActive(false); m_check.SetActive(false);
m_hourglass.SetActive(false); m_hourglass.SetActive(false);
break; break;
case QuestStateEnum.Active: case QuestStateEnum.InProgress:
m_check.SetActive(false); m_check.SetActive(false);
m_hourglass.SetActive(true); m_hourglass.SetActive(true);
break; break;

View file

@ -65,13 +65,25 @@ namespace GameUI.Runtime
void DisplayAvailableQuests(List<QuestTemplate> availableTemplates, List<QuestClass> acceptedQuests) void DisplayAvailableQuests(List<QuestTemplate> availableTemplates, List<QuestClass> acceptedQuests)
{ {
foreach (var quest in availableTemplates) // Build a set of started quest IDs (Accepted/Active + Completed)
var startedIds = new HashSet<System.Guid>();
foreach (var q in QuestManager.Instance.ActiveQuests ?? new List<QuestClass>())
{ {
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<QuestClass>())
{
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; continue;
} }
DisplayCard(quest); DisplayCard(template);
} }
} }