139 lines
4.6 KiB
C#
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;
|
|
}
|
|
}
|