Files
TopDown/Assets/Scripts/Quests/QuestManager.cs
2026-08-05 08:18:15 +01:00

139 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace Quests
{
public class QuestManager : MonoBehaviour
{
public static QuestManager Instance { get; private set; }
[Header("Starting Quests (Optional)")]
[SerializeField] private List<QuestData> autoAcceptQuests = new List<QuestData>();
private readonly Dictionary<string, Quest> activeQuests = new Dictionary<string, Quest>();
private readonly Dictionary<string, Quest> completedQuests = new Dictionary<string, Quest>();
// Events for UI or other systems
public event Action<Quest> OnQuestAccepted;
public event Action<Quest> OnQuestObjectiveUpdated;
public event Action<Quest> OnQuestCompleted;
public event Action<Quest> OnQuestHandedIn;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void Start()
{
foreach (var questData in autoAcceptQuests)
{
if (questData != null)
{
AcceptQuest(questData);
}
}
}
public bool AcceptQuest(QuestData questData)
{
if (questData == null || string.IsNullOrEmpty(questData.questID))
{
Debug.LogWarning("[QuestManager] Cannot accept null or unassigned QuestData.");
return false;
}
if (activeQuests.ContainsKey(questData.questID) || completedQuests.ContainsKey(questData.questID))
{
Debug.LogWarning($"[QuestManager] Quest '{questData.title}' already accepted or completed.");
return false;
}
Quest newQuest = new Quest(questData);
newQuest.state = QuestState.InProgress;
activeQuests.Add(questData.questID, newQuest);
Debug.Log($"[QuestManager] Accepted Quest: '{questData.title}'");
OnQuestAccepted?.Invoke(newQuest);
return true;
}
public void ReportKill(string enemyID, int amount = 1)
{
ReportProgress(ObjectiveType.Kill, enemyID, amount);
}
public void ReportLocationReached(string locationID)
{
ReportProgress(ObjectiveType.ReachLocation, locationID, 1);
}
public void ReportTalk(string npcID)
{
ReportProgress(ObjectiveType.Talk, npcID, 1);
}
public void ReportCollect(string itemID, int amount = 1)
{
ReportProgress(ObjectiveType.Collect, itemID, amount);
}
public void ReportInteract(string interactableID, int amount = 1)
{
ReportProgress(ObjectiveType.Interact, interactableID, amount);
}
public void ReportProgress(ObjectiveType type, string targetID, int amount = 1)
{
List<Quest> toCheck = new List<Quest>(activeQuests.Values);
foreach (var quest in toCheck)
{
bool wasCompleted = quest.state == QuestState.Completed;
if (quest.ProgressObjective(type, targetID, amount))
{
OnQuestObjectiveUpdated?.Invoke(quest);
if (!wasCompleted && quest.state == QuestState.Completed)
{
OnQuestCompleted?.Invoke(quest);
}
}
}
}
public bool HandInQuest(string questID)
{
if (!activeQuests.TryGetValue(questID, out Quest quest))
{
Debug.LogWarning($"[QuestManager] Active quest ID '{questID}' not found.");
return false;
}
if (quest.state != QuestState.Completed)
{
Debug.LogWarning($"[QuestManager] Quest '{quest.data.title}' is not complete yet.");
return false;
}
quest.state = QuestState.HandedIn;
activeQuests.Remove(questID);
completedQuests.Add(questID, quest);
Debug.Log($"[QuestManager] Handed in Quest: '{quest.data.title}'. Rewarding Gold: {quest.data.rewardGold}, XP: {quest.data.rewardExperience}");
OnQuestHandedIn?.Invoke(quest);
return true;
}
public IReadOnlyCollection<Quest> GetActiveQuests() => activeQuests.Values;
public IReadOnlyCollection<Quest> GetCompletedQuests() => completedQuests.Values;
}
}