Files
FablishRPG/Assets/Scripts/QuestManager.cs

179 lines
5.3 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public enum ObjectiveType { Interact, Kill, Collect, None }
[System.Serializable]
public class QuestObjective
{
[Tooltip("Unique ID for this objective (e.g., 'bandit_leader', 'wolf_pelt')")]
public string targetID;
[Tooltip("What action the player must perform")]
public ObjectiveType type;
[Tooltip("The text shown in the UI")]
public string description;
[Header("Counting")]
public bool requiresCount;
public int currentCount;
public int targetCount;
[HideInInspector]
public bool isCompleted;
}
[System.Serializable]
public class Quest
{
public string questName;
public List<QuestObjective> objectives = new List<QuestObjective>();
public bool isCompleted;
}
public class QuestManager : MonoBehaviour
{
public static QuestManager Instance { get; private set; }
[Header("Current Quest")]
public Quest activeQuest;
[Header("Testing")]
[Tooltip("Set the key to automatically progress the first incomplete objective")]
public Key completeObjectiveKey = Key.O;
// We notify the UI when the quest updates
public delegate void OnQuestUpdated();
public event OnQuestUpdated onQuestUpdated;
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
// Tell UI to draw whatever quest is assigned in the inspector (if any)
NotifyUI();
}
private void Update()
{
if (Keyboard.current != null && Keyboard.current[completeObjectiveKey].wasPressedThisFrame)
{
// For testing: progress the first incomplete objective
if (activeQuest != null && !activeQuest.isCompleted)
{
foreach (var obj in activeQuest.objectives)
{
if (!obj.isCompleted)
{
ProgressObjective(obj.type, obj.targetID, 1);
break;
}
}
}
}
}
/// <summary>
/// NPCs or Items can call this to progress the current quest!
/// Example: QuestManager.Instance.ProgressObjective(ObjectiveType.Kill, "wolf");
/// </summary>
public bool ProgressObjective(ObjectiveType type, string targetID, int amount = 1)
{
if (activeQuest == null || activeQuest.isCompleted) return false;
foreach (var obj in activeQuest.objectives)
{
// Only progress the FIRST incomplete objective (Linear Quests)
if (!obj.isCompleted)
{
// Check if this objective matches the action
if (obj.type == type && obj.targetID == targetID)
{
if (obj.requiresCount)
{
obj.currentCount += amount;
Debug.Log($"[QuestManager] Progressed '{obj.description}': {obj.currentCount}/{obj.targetCount}");
if (obj.currentCount >= obj.targetCount)
{
obj.currentCount = obj.targetCount;
obj.isCompleted = true;
Debug.Log($"[QuestManager] Objective Completed: {obj.description}");
}
}
else
{
obj.isCompleted = true;
Debug.Log($"[QuestManager] Objective Completed: {obj.description}");
}
CheckQuestCompletion();
NotifyUI();
return true; // Successfully progressed!
}
// If it didn't match, we still stop here because we only allow
// progressing the CURRENT active objective.
return false;
}
}
return false;
}
/// <summary>
/// Checks if a specific objective is the CURRENT active objective the player needs to do.
/// </summary>
public bool IsObjectiveActive(ObjectiveType type, string targetID)
{
if (activeQuest == null || activeQuest.isCompleted) return false;
foreach (var obj in activeQuest.objectives)
{
if (!obj.isCompleted)
{
// We found the FIRST incomplete objective! Is it this one?
return (obj.type == type && obj.targetID == targetID);
}
}
return false;
}
private void CheckQuestCompletion()
{
foreach (var obj in activeQuest.objectives)
{
if (!obj.isCompleted) return; // Still have objectives left
}
activeQuest.isCompleted = true;
Debug.Log($"[QuestManager] Quest Completed: {activeQuest.questName}");
}
public void NotifyUI()
{
onQuestUpdated?.Invoke();
}
/// <summary>
/// An NPC or Item can call this to give the player a brand new quest!
/// </summary>
public void StartNewQuest(Quest newQuest)
{
activeQuest = newQuest;
NotifyUI();
Debug.Log($"[QuestManager] Started new quest: {newQuest.questName}");
}
}