Draft Dialogue System and Started Quest System
This commit is contained in:
@@ -3,22 +3,5 @@ using System.Collections.Generic;
|
||||
[System.Serializable]
|
||||
public class Dialogue
|
||||
{
|
||||
public string npcId;
|
||||
public string name;
|
||||
public List<string> sentences;
|
||||
public List<DialogueOption> options;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class DialogueOption
|
||||
{
|
||||
public string text;
|
||||
public DialogueOutcome outcome;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class DialogueOutcome
|
||||
{
|
||||
public List<Quest> quests;
|
||||
public Dialogue dialogue;
|
||||
}
|
||||
|
||||
11
Assets/Scripts/DialogueAssets.cs
Normal file
11
Assets/Scripts/DialogueAssets.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
[CreateAssetMenu(fileName = "DialogueDatabase", menuName = "Dialogue/Dialogue Database", order = 0)]
|
||||
public class DialogueAssets : ScriptableObject
|
||||
{
|
||||
[SerializeField] private List<DialogueEntry> entries = new List<DialogueEntry>();
|
||||
|
||||
public List<DialogueEntry> Entries => entries;
|
||||
}
|
||||
2
Assets/Scripts/DialogueAssets.cs.meta
Normal file
2
Assets/Scripts/DialogueAssets.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27a69891d053e674d962dfbb0e0eb283
|
||||
24
Assets/Scripts/DialogueDatabase.asset
Normal file
24
Assets/Scripts/DialogueDatabase.asset
Normal file
@@ -0,0 +1,24 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 27a69891d053e674d962dfbb0e0eb283, type: 3}
|
||||
m_Name: DialogueDatabase
|
||||
m_EditorClassIdentifier:
|
||||
entries:
|
||||
- npcId: Villager_01
|
||||
npcName: Villager
|
||||
dialogues:
|
||||
- sentences:
|
||||
- Welcome to the village boy, it is lovely and quiet, see to it that it stays
|
||||
that way...
|
||||
- If you are looking for something to do rather than bothering me, talk to
|
||||
the farmer next to us. He is having some troubles I am sure you can help
|
||||
with.
|
||||
8
Assets/Scripts/DialogueDatabase.asset.meta
Normal file
8
Assets/Scripts/DialogueDatabase.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c996dbde4d1b2840b324512a0dcc3f3
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -13,7 +13,7 @@ public class DialogueEntry
|
||||
[System.Serializable]
|
||||
public class DialogueDatabase : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<DialogueEntry> entries;
|
||||
[SerializeField] private DialogueAssets dialogueAssets;
|
||||
private Dictionary<string, DialogueEntry> dialogueDictionary;
|
||||
|
||||
private static DialogueDatabase instance;
|
||||
@@ -23,7 +23,7 @@ public class DialogueDatabase : MonoBehaviour
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = FindObjectOfType<DialogueDatabase>();
|
||||
instance = FindFirstObjectByType<DialogueDatabase>();
|
||||
if (instance == null)
|
||||
{
|
||||
GameObject obj = new GameObject("DialogueDatabase");
|
||||
@@ -50,8 +50,14 @@ public class DialogueDatabase : MonoBehaviour
|
||||
|
||||
private void InitializeDictionary()
|
||||
{
|
||||
if (dialogueAssets == null)
|
||||
{
|
||||
Debug.LogError("DialogueAssets not assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
dialogueDictionary = new Dictionary<string, DialogueEntry>();
|
||||
foreach (DialogueEntry entry in entries)
|
||||
foreach (DialogueEntry entry in dialogueAssets.Entries)
|
||||
{
|
||||
dialogueDictionary[entry.npcId] = entry;
|
||||
}
|
||||
@@ -95,4 +101,13 @@ public class DialogueDatabase : MonoBehaviour
|
||||
}
|
||||
return "Unknown NPC";
|
||||
}
|
||||
|
||||
public string GetNPCId(string npcId)
|
||||
{
|
||||
if (dialogueDictionary.TryGetValue(npcId, out DialogueEntry entry))
|
||||
{
|
||||
return entry.npcId;
|
||||
}
|
||||
return npcId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,35 +2,51 @@ using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using StarterAssets;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class DialogueManager : MonoBehaviour
|
||||
{
|
||||
private static DialogueManager instance;
|
||||
public UnityEvent OnDialogueComplete = new UnityEvent();
|
||||
[Header("UI Elements")]
|
||||
[SerializeField] private GameObject dialoguePanel;
|
||||
[SerializeField] private Text dialogueText;
|
||||
[SerializeField] private GameObject optionsPanel;
|
||||
[SerializeField] private RectTransform optionsContainer;
|
||||
[SerializeField] private GameObject optionPrefab;
|
||||
[SerializeField] private TMP_Text dialogueText;
|
||||
|
||||
[Header("Dialogue Settings")]
|
||||
[SerializeField] private float textSpeed = 0.05f;
|
||||
[SerializeField] private float dialogueDelay = 1f;
|
||||
|
||||
private Queue<string> sentences;
|
||||
private Dialogue currentDialogue;
|
||||
private bool isTyping;
|
||||
private bool isDialogueActive;
|
||||
|
||||
private ThirdPersonController playerController;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
sentences = new Queue<string>();
|
||||
dialoguePanel.SetActive(false);
|
||||
optionsPanel.SetActive(false);
|
||||
playerController = FindFirstObjectByType<ThirdPersonController>();
|
||||
}
|
||||
|
||||
public void StartDialogue(string npcId)
|
||||
{
|
||||
Dialogue dialogue = DialogueDatabase.Instance.GetRandomDialogue(npcId);
|
||||
// Get the NPC ID from the database
|
||||
string actualNpcId = DialogueDatabase.Instance.GetNPCId(npcId);
|
||||
|
||||
// Freeze player controls
|
||||
if (playerController != null)
|
||||
{
|
||||
playerController.enabled = false;
|
||||
}
|
||||
|
||||
// Unlock mouse
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
Cursor.visible = true;
|
||||
|
||||
Dialogue dialogue = DialogueDatabase.Instance.GetRandomDialogue(actualNpcId);
|
||||
if (dialogue == null)
|
||||
{
|
||||
Debug.LogWarning($"No dialogue found for NPC with ID: {npcId}");
|
||||
@@ -72,65 +88,63 @@ public class DialogueManager : MonoBehaviour
|
||||
|
||||
foreach (char letter in sentence.ToCharArray())
|
||||
{
|
||||
if (Input.GetMouseButtonDown(1)) // Right click skips
|
||||
{
|
||||
dialogueText.text = sentence;
|
||||
break;
|
||||
}
|
||||
|
||||
dialogueText.text += letter;
|
||||
yield return new WaitForSeconds(textSpeed);
|
||||
}
|
||||
|
||||
isTyping = false;
|
||||
|
||||
if (currentDialogue.options != null && currentDialogue.options.Count > 0)
|
||||
{
|
||||
ShowOptions(currentDialogue.options);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowOptions(List<DialogueOption> options)
|
||||
{
|
||||
optionsPanel.SetActive(true);
|
||||
optionsContainer.sizeDelta = new Vector2(optionsContainer.sizeDelta.x, options.Count * 50);
|
||||
|
||||
foreach (Transform child in optionsContainer)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
foreach (DialogueOption option in options)
|
||||
{
|
||||
GameObject optionObj = Instantiate(optionPrefab, optionsContainer);
|
||||
Button button = optionObj.GetComponent<Button>();
|
||||
Text buttonText = optionObj.GetComponentInChildren<Text>();
|
||||
|
||||
buttonText.text = option.text;
|
||||
button.onClick.AddListener(() => SelectOption(option));
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectOption(DialogueOption option)
|
||||
{
|
||||
optionsPanel.SetActive(false);
|
||||
|
||||
if (option.outcome != null)
|
||||
{
|
||||
if (option.outcome.quests != null)
|
||||
{
|
||||
foreach (Quest quest in option.outcome.quests)
|
||||
{
|
||||
quest.StartQuest();
|
||||
}
|
||||
}
|
||||
|
||||
if (option.outcome.dialogue != null)
|
||||
{
|
||||
StartDialogue(option.outcome.dialogue.npcId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EndDialogue()
|
||||
{
|
||||
dialoguePanel.SetActive(false);
|
||||
optionsPanel.SetActive(false);
|
||||
isDialogueActive = false;
|
||||
dialoguePanel.SetActive(false);
|
||||
|
||||
// Reset player controls
|
||||
if (playerController != null)
|
||||
{
|
||||
playerController.enabled = true;
|
||||
}
|
||||
|
||||
// Lock mouse back
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
Cursor.visible = false;
|
||||
OnDialogueComplete.Invoke();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else if (instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
OnDialogueComplete.RemoveAllListeners();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isDialogueActive)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
DisplayNextSentence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDialogueActive()
|
||||
|
||||
@@ -4,34 +4,103 @@ public class NPC : MonoBehaviour
|
||||
{
|
||||
[Header("NPC Settings")]
|
||||
[SerializeField] private string npcId;
|
||||
[SerializeField] private string npcName;
|
||||
[SerializeField] private bool canTalk;
|
||||
[SerializeField] private string initialDialogueId;
|
||||
[SerializeField] private string repeatedDialogueId;
|
||||
[SerializeField] public string npcName;
|
||||
[SerializeField] public bool canTalk;
|
||||
[SerializeField] public bool isInteractable;
|
||||
[SerializeField] public float interactionRange = 2f;
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private bool startQuest;
|
||||
[SerializeField] private int questId;
|
||||
|
||||
private DialogueManager dialogueManager;
|
||||
private bool hasShownInitialDialogue = false;
|
||||
private QuestDatabase questDatabase;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
dialogueManager = FindObjectOfType<DialogueManager>();
|
||||
dialogueManager = FindAnyObjectByType<DialogueManager>();
|
||||
questDatabase = QuestDatabase.Instance;
|
||||
|
||||
// Subscribe to quest completion event if this NPC is involved in quest completion
|
||||
if (startQuest && questId != 0)
|
||||
{
|
||||
QuestData quest = questDatabase.GetQuest(questId);
|
||||
if (quest != null)
|
||||
{
|
||||
// Add any additional quest start logic here
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Quest with ID {questId} not found for NPC {npcName}");
|
||||
}
|
||||
}
|
||||
|
||||
// Set default dialogue IDs if not specified
|
||||
if (string.IsNullOrEmpty(initialDialogueId))
|
||||
{
|
||||
initialDialogueId = npcId + "_initial";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(repeatedDialogueId))
|
||||
{
|
||||
repeatedDialogueId = npcId + "_repeat";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseDown()
|
||||
public bool IsInRange(Vector3 playerPosition)
|
||||
{
|
||||
if (canTalk && !dialogueManager.IsDialogueActive())
|
||||
return Vector3.Distance(transform.position, playerPosition) <= interactionRange;
|
||||
}
|
||||
|
||||
public void Interact()
|
||||
{
|
||||
if (canTalk && isInteractable && !dialogueManager.IsDialogueActive())
|
||||
{
|
||||
string dialogueId = hasShownInitialDialogue ? repeatedDialogueId : initialDialogueId;
|
||||
|
||||
if (string.IsNullOrEmpty(dialogueId))
|
||||
{
|
||||
Debug.LogWarning($"No dialogue ID specified for NPC {npcName}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Use npcId as the base ID for dialogue lookup
|
||||
dialogueManager.StartDialogue(npcId);
|
||||
animator.SetTrigger("Talk");
|
||||
|
||||
// Only set hasShownInitialDialogue to true after the first dialogue
|
||||
if (!hasShownInitialDialogue)
|
||||
{
|
||||
hasShownInitialDialogue = true;
|
||||
}
|
||||
|
||||
// If this NPC starts a quest, add a callback to start the quest after dialogue
|
||||
if (startQuest && questId != 0)
|
||||
{
|
||||
// Validate quest ID before adding listener
|
||||
QuestData quest = questDatabase.GetQuest(questId);
|
||||
if (quest != null)
|
||||
{
|
||||
dialogueManager.OnDialogueComplete.AddListener(() =>
|
||||
{
|
||||
questDatabase.UpdateQuestUI(quest);
|
||||
// Add any additional quest start logic here
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Quest with ID {questId} not found for NPC {npcName}. Skipping quest start.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseOver()
|
||||
public void SetInteractable(bool interactable)
|
||||
{
|
||||
if (canTalk)
|
||||
{
|
||||
// Show interaction prompt
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseExit()
|
||||
{
|
||||
// Hide interaction prompt
|
||||
isInteractable = interactable;
|
||||
hasShownInitialDialogue = false; // Reset dialogue state when interactable changes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,69 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEditor.VisionOS;
|
||||
|
||||
public class PopUpManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_Text _popUpText;
|
||||
private Transform _target;
|
||||
private bool _isShowing;
|
||||
|
||||
public static PopUpManager instance; // Singleton instance of PopUpManager
|
||||
public void Awake()
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this; // Assign the current instance to the static instance variable
|
||||
}
|
||||
public TMP_Text popUpText; // Reference to the TextMeshPro component for displaying the message
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else if (instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
if (_popUpText == null)
|
||||
{
|
||||
Debug.LogError("PopUpManager: TMP_Text component not assigned!");
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
private void Update()
|
||||
{
|
||||
|
||||
if (_isShowing && _target != null)
|
||||
{
|
||||
// Position the pop-up above the target object
|
||||
Vector3 offset = new Vector3(0, 0.5f, 0); // Adjust the Y offset as needed
|
||||
transform.position = _target.position + offset;
|
||||
transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0); // Lock rotation to Y-axis
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowPopUp(string objectName, string objectDesc, Transform targetObject)
|
||||
public void ShowObjectPopUp(string objectName, string objectDescription, Transform target)
|
||||
{
|
||||
// Set the text of the pop-up to the provided message
|
||||
popUpText.text = objectName + "\n" + objectDesc;
|
||||
_target = target;
|
||||
_isShowing = true;
|
||||
_popUpText.text = $"{objectName}\n{objectDescription}";
|
||||
UpdatePositionAndRotation();
|
||||
}
|
||||
|
||||
public void ShowNPCPopUp(string npcName, Transform target)
|
||||
{
|
||||
_target = target;
|
||||
_isShowing = true;
|
||||
_popUpText.text = npcName;
|
||||
UpdatePositionAndRotation();
|
||||
}
|
||||
|
||||
private void UpdatePositionAndRotation()
|
||||
{
|
||||
if (_target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Position the pop-up above the target object
|
||||
Vector3 offset = new Vector3(0, 0.5f, 0); // Adjust the Y offset as needed
|
||||
transform.position = targetObject.position + offset;
|
||||
transform.position = _target.position + offset;
|
||||
|
||||
// Make the pop-up face the camera
|
||||
Camera mainCamera = Camera.main;
|
||||
@@ -41,8 +74,15 @@ public class PopUpManager : MonoBehaviour
|
||||
transform.rotation = Quaternion.LookRotation(directionToCamera);
|
||||
transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0); // Lock rotation to Y-axis
|
||||
}
|
||||
}
|
||||
|
||||
// Activate the pop-up GameObject to make it visible
|
||||
gameObject.SetActive(true);
|
||||
public void HidePopUp()
|
||||
{
|
||||
if (_isShowing)
|
||||
{
|
||||
_isShowing = false;
|
||||
_target = null;
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/QuestAssets.cs
Normal file
11
Assets/Scripts/QuestAssets.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
[CreateAssetMenu(fileName = "QuestDatabase", menuName = "Quest/Quest Database", order = 0)]
|
||||
public class QuestAssets : ScriptableObject
|
||||
{
|
||||
[SerializeField] private List<QuestEntry> entries = new List<QuestEntry>();
|
||||
|
||||
public List<QuestEntry> Entries => entries;
|
||||
}
|
||||
2
Assets/Scripts/QuestAssets.cs.meta
Normal file
2
Assets/Scripts/QuestAssets.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f28f2357391dea543a0edc80401bce44
|
||||
29
Assets/Scripts/QuestDatabase.asset
Normal file
29
Assets/Scripts/QuestDatabase.asset
Normal file
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f28f2357391dea543a0edc80401bce44, type: 3}
|
||||
m_Name: QuestDatabase
|
||||
m_EditorClassIdentifier:
|
||||
entries:
|
||||
- questId: 1
|
||||
questName: Farmer's Woes
|
||||
questDescription: Help the farmer resolve his woes
|
||||
quests:
|
||||
- id: 1
|
||||
name: Talk To Farmer
|
||||
description: Find out what the farmer's issue is
|
||||
type: 2
|
||||
targetAmount: 0
|
||||
targetItem:
|
||||
experienceReward: 0
|
||||
goldReward: 0
|
||||
isRepeatable: 0
|
||||
requiredQuests:
|
||||
8
Assets/Scripts/QuestDatabase.asset.meta
Normal file
8
Assets/Scripts/QuestDatabase.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56924919879e6bc4bb2b99a727cddd8c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
323
Assets/Scripts/QuestDatabase.cs
Normal file
323
Assets/Scripts/QuestDatabase.cs
Normal file
@@ -0,0 +1,323 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using TMPro;
|
||||
|
||||
[System.Serializable]
|
||||
public class QuestEntry
|
||||
{
|
||||
public int questId; // Changed from string to int
|
||||
public string questName;
|
||||
public string questDescription;
|
||||
public List<QuestData> quests;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class QuestData
|
||||
{
|
||||
public int id;
|
||||
public string name;
|
||||
public string description;
|
||||
public QuestType type;
|
||||
public int targetAmount;
|
||||
public string targetItem;
|
||||
public int experienceReward;
|
||||
public int goldReward;
|
||||
public bool isRepeatable;
|
||||
public List<int> requiredQuests; // Quest IDs that must be completed first
|
||||
}
|
||||
|
||||
public enum QuestType
|
||||
{
|
||||
Collect,
|
||||
Kill,
|
||||
TalkTo,
|
||||
Deliver,
|
||||
Explore,
|
||||
Reach
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class QuestDatabase : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private QuestAssets questAssets;
|
||||
[SerializeField] private TMPro.TMP_Text questNameText;
|
||||
[SerializeField] private TMPro.TMP_Text questObjectiveText;
|
||||
private Dictionary<int, QuestEntry> questDictionary;
|
||||
|
||||
private static QuestDatabase instance;
|
||||
public static QuestDatabase Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = FindFirstObjectByType<QuestDatabase>();
|
||||
if (instance == null)
|
||||
{
|
||||
GameObject obj = new GameObject("QuestDatabase");
|
||||
instance = obj.AddComponent<QuestDatabase>();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
InitializeDictionary();
|
||||
}
|
||||
else if (instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeDictionary()
|
||||
{
|
||||
questDictionary = new Dictionary<int, QuestEntry>();
|
||||
if (questAssets != null)
|
||||
{
|
||||
foreach (var entry in questAssets.Entries)
|
||||
{
|
||||
questDictionary.Add(entry.questId, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public QuestData GetQuest(int questId)
|
||||
{
|
||||
if (questDictionary.TryGetValue(questId, out var entry))
|
||||
{
|
||||
return entry.quests.Find(q => q.id == questId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<QuestData> GetAvailableQuests(int npcId)
|
||||
{
|
||||
List<QuestData> availableQuests = new List<QuestData>();
|
||||
|
||||
foreach (var entry in questDictionary.Values)
|
||||
{
|
||||
foreach (var quest in entry.quests)
|
||||
{
|
||||
// Check prerequisites
|
||||
bool prerequisitesMet = true;
|
||||
foreach (int requiredQuest in quest.requiredQuests)
|
||||
{
|
||||
if (!IsQuestCompleted(requiredQuest))
|
||||
{
|
||||
prerequisitesMet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prerequisitesMet)
|
||||
{
|
||||
availableQuests.Add(quest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug log available quests
|
||||
Debug.Log($"Available quests for NPC {npcId}:");
|
||||
foreach (var quest in availableQuests)
|
||||
{
|
||||
Debug.Log($"- {quest.id}: {quest.name}");
|
||||
}
|
||||
|
||||
return availableQuests;
|
||||
}
|
||||
|
||||
private Dictionary<int, int> questProgress = new Dictionary<int, int>();
|
||||
private Dictionary<int, bool> completedQuests = new Dictionary<int, bool>();
|
||||
|
||||
public void UpdateQuestProgress(int questId, int amount = 1)
|
||||
{
|
||||
if (questProgress.ContainsKey(questId))
|
||||
{
|
||||
questProgress[questId] += amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
questProgress[questId] = amount;
|
||||
}
|
||||
|
||||
// Check if quest is completed
|
||||
QuestData quest = GetQuest(questId);
|
||||
if (quest != null && questProgress[questId] >= quest.targetAmount)
|
||||
{
|
||||
CompleteQuest(questId);
|
||||
}
|
||||
}
|
||||
|
||||
public void CompleteQuest(int questId)
|
||||
{
|
||||
if (completedQuests.ContainsKey(questId))
|
||||
{
|
||||
if (completedQuests[questId])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
completedQuests[questId] = true;
|
||||
QuestData quest = GetQuest(questId);
|
||||
if (quest != null)
|
||||
{
|
||||
// Grant rewards
|
||||
// TODO: Implement reward system
|
||||
|
||||
// Update UI
|
||||
if (questNameText != null)
|
||||
{
|
||||
questNameText.text = quest.name + " (Completed)";
|
||||
questNameText.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (questObjectiveText != null)
|
||||
{
|
||||
questObjectiveText.text = "Quest completed!";
|
||||
questObjectiveText.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Check for any quests that require this quest as a prerequisite
|
||||
foreach (var entry in questDictionary.Values)
|
||||
{
|
||||
foreach (var q in entry.quests)
|
||||
{
|
||||
if (q.requiredQuests.Contains(questId))
|
||||
{
|
||||
// TODO: Make these quests available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any quests that require this quest as a prerequisite
|
||||
foreach (var entry in questDictionary.Values)
|
||||
{
|
||||
foreach (var q in entry.quests)
|
||||
{
|
||||
if (q.requiredQuests.Contains(questId))
|
||||
{
|
||||
// TODO: Make these quests available
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsQuestCompleted(int questId)
|
||||
{
|
||||
return completedQuests.ContainsKey(questId) && completedQuests[questId];
|
||||
}
|
||||
|
||||
public int GetQuestProgress(int questId)
|
||||
{
|
||||
return questProgress.ContainsKey(questId) ? questProgress[questId] : 0;
|
||||
}
|
||||
|
||||
public void ResetQuestProgress(int questId)
|
||||
{
|
||||
questProgress[questId] = 0;
|
||||
completedQuests[questId] = false;
|
||||
|
||||
// Reset UI visibility
|
||||
if (questNameText != null)
|
||||
{
|
||||
questNameText.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (questObjectiveText != null)
|
||||
{
|
||||
questObjectiveText.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void FailQuest(int questId)
|
||||
{
|
||||
if (completedQuests.ContainsKey(questId))
|
||||
{
|
||||
if (completedQuests[questId])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
completedQuests[questId] = true;
|
||||
QuestData quest = GetQuest(questId);
|
||||
if (quest != null)
|
||||
{
|
||||
// Update UI
|
||||
if (questNameText != null)
|
||||
{
|
||||
questNameText.text = quest.name + " (Failed)";
|
||||
questNameText.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (questObjectiveText != null)
|
||||
{
|
||||
questObjectiveText.text = "Quest failed!";
|
||||
questObjectiveText.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelQuest(int questId)
|
||||
{
|
||||
if (completedQuests.ContainsKey(questId))
|
||||
{
|
||||
if (completedQuests[questId])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
completedQuests[questId] = true;
|
||||
QuestData quest = GetQuest(questId);
|
||||
if (quest != null)
|
||||
{
|
||||
// Update UI
|
||||
if (questNameText != null)
|
||||
{
|
||||
questNameText.text = quest.name + " (Cancelled)";
|
||||
questNameText.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (questObjectiveText != null)
|
||||
{
|
||||
questObjectiveText.text = "Quest cancelled!";
|
||||
questObjectiveText.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateQuestUI(QuestData quest)
|
||||
{
|
||||
if (quest == null)
|
||||
{
|
||||
Debug.LogWarning("QuestDatabase: Attempted to update UI with null quest");
|
||||
return;
|
||||
}
|
||||
|
||||
if (questNameText != null)
|
||||
{
|
||||
questNameText.text = quest.name;
|
||||
questNameText.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (questObjectiveText != null)
|
||||
{
|
||||
int progress = GetQuestProgress(quest.id);
|
||||
string objectiveText = $"{quest.description}";
|
||||
questObjectiveText.text = objectiveText;
|
||||
questObjectiveText.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/QuestDatabase.cs.meta
Normal file
2
Assets/Scripts/QuestDatabase.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2389feddc157cee42a502e282623daa5
|
||||
Reference in New Issue
Block a user