using UnityEngine; using EasyTalk.Controller; using EasyTalk.Nodes; public enum NPCType { Villager, Merchant, Trainer, Guard, QuestGiver, Other } public class NPC : Character { [Header("NPC Settings")] public string npcName = "NPC"; public NPCType npcType = NPCType.Villager; [Header("Debug")] [SerializeField] private bool enableDebugLogs = false; [Header("Interaction Capabilities")] public bool hasDialogue = true; public bool isQuestGiver = false; public bool isMerchant = false; public bool isTrainer = false; [Header("EasyTalk Integration")] [Tooltip("The Dialogue asset for this NPC. Will be loaded into the central DialogueController.")] public Dialogue dialogue; [Tooltip("Optional: Entry point name for starting dialogue. Leave empty to use default entry point.")] public string dialogueEntryPoint = ""; [Tooltip("Name of the GameObject with the central DialogueController. Leave empty to auto-find.")] public string dialogueManagerName = "Manager"; // Cache the central DialogueController private static DialogueController centralDialogueController; [Header("Fallback Dialogue (if no EasyTalk)")] [TextArea(3, 10)] public string greetingText = "Hello, traveler!"; [Header("Quest")] public string questId = ""; // ID of the quest this NPC offers [Header("Merchant Settings")] [Tooltip("Gold required to access merchant services")] public int merchantGoldRequirement = 0; [Header("Trainer Settings")] [Tooltip("Skills this trainer can teach")] public string[] trainableSkills; public int trainingCost = 100; /// /// Called when player interacts with this NPC /// public virtual void OnInteract(GameObject player) { Log($"Interacting with {npcName} ({npcType})"); if (hasDialogue) { ShowDialogue(); } if (isQuestGiver && !string.IsNullOrEmpty(questId)) { //OfferQuest(player); } if (isMerchant) { OpenMerchantInterface(player); } if (isTrainer) { OpenTrainingInterface(player); } } /// /// Display dialogue for this NPC using EasyTalk with centralized DialogueController /// protected virtual void ShowDialogue() { // Find the central DialogueController if not cached if (centralDialogueController == null) { centralDialogueController = FindCentralDialogueController(); } // Check if we have both a controller and dialogue asset if (centralDialogueController != null && dialogue != null) { // Load this NPC's dialogue into the central controller centralDialogueController.ChangeDialogue(dialogue); // Play dialogue with optional entry point if (!string.IsNullOrEmpty(dialogueEntryPoint)) { centralDialogueController.PlayDialogue(dialogueEntryPoint); Log($"{npcName}: Starting EasyTalk dialogue at entry point '{dialogueEntryPoint}'"); } else { centralDialogueController.PlayDialogue(); Log($"{npcName}: Starting EasyTalk dialogue"); } } else { // Fallback to simple greeting if no EasyTalk setup if (centralDialogueController == null) { Debug.LogWarning($"No central DialogueController found. Make sure there's a DialogueController on a GameObject named '{dialogueManagerName}'.", gameObject); } if (dialogue == null) { Debug.LogWarning($"No Dialogue asset assigned to {npcName}. Assign a Dialogue asset in the inspector.", gameObject); } Log($"{npcName}: {greetingText}"); } } /// /// Finds the central DialogueController in the scene /// private DialogueController FindCentralDialogueController() { // First, try to find by the specified manager name if (!string.IsNullOrEmpty(dialogueManagerName)) { GameObject manager = GameObject.Find(dialogueManagerName); if (manager != null) { DialogueController controller = manager.GetComponent(); if (controller != null) { Log($"Found central DialogueController on '{dialogueManagerName}'"); return controller; } } } // Fallback: search for any DialogueController in the scene DialogueController foundController = FindAnyObjectByType(); if (foundController != null) { Log($"Found DialogueController via FindAnyObjectByType on '{foundController.gameObject.name}'"); return foundController; } return null; } /// /// Offer quest to the player /// protected virtual void OfferQuest(GameObject player) { if (QuestManager.Instance == null) { Debug.LogWarning("QuestManager not found in scene. Cannot offer quest.", gameObject); return; } if (string.IsNullOrEmpty(questId)) { Debug.LogWarning($"{npcName} has no questId assigned.", gameObject); return; } // Check if player can accept this quest if (QuestManager.Instance.CanAcceptQuest(questId)) { // Start the quest bool started = QuestManager.Instance.StartQuest(questId); if (started) { Log($"{npcName} gave quest '{questId}' to player!"); } } else if (QuestManager.Instance.IsQuestActive(questId)) { // Quest already active - check if it can be turned in Quest activeQuest = QuestManager.Instance.GetActiveQuest(questId); if (activeQuest != null && activeQuest.IsComplete()) { Log($"{npcName}: You've completed the quest! Turn it in."); // Player should use CompleteQuestWithNPC method or turn-in dialogue option } else { Log($"{npcName}: You already have this quest active."); } } else if (QuestManager.Instance.IsQuestCompleted(questId)) { Log($"{npcName}: You've already completed this quest."); } else { Log($"{npcName}: You don't meet the requirements for this quest yet."); } } /// /// Complete a quest with this NPC (quest turn-in) /// public virtual bool CompleteQuestWithNPC(string questIdToComplete) { if (QuestManager.Instance == null) { Debug.LogWarning("QuestManager not found in scene.", gameObject); return false; } Quest quest = QuestManager.Instance.GetActiveQuest(questIdToComplete); if (quest != null && quest.IsComplete()) { bool completed = QuestManager.Instance.CompleteQuest(questIdToComplete); if (completed) { Log($"{npcName}: Quest complete! Here's your reward."); return true; } } else { Log($"{npcName}: You haven't completed that quest yet."); } return false; } /// /// Open merchant trading interface /// protected virtual void OpenMerchantInterface(GameObject player) { Debug.Log($"Opening merchant interface for {npcName}", gameObject); // TODO: Implement merchant UI } /// /// Open training interface for learning skills /// protected virtual void OpenTrainingInterface(GameObject player) { Debug.Log($"Opening training interface for {npcName}", gameObject); // TODO: Implement training UI } /// /// Check if this NPC can perform a specific service /// public bool CanProvideService(NPCType serviceType) { return npcType == serviceType || (serviceType == NPCType.Merchant && isMerchant) || (serviceType == NPCType.Trainer && isTrainer) || (serviceType == NPCType.QuestGiver && isQuestGiver); } /// /// NPCs don't die by default - override for hostile NPCs /// public override void Die() { Log($"{npcName} has been defeated!"); // NPCs might drop loot, give quest credit, etc. base.Die(); } private void Log(string message) { if (enableDebugLogs) { Debug.Log(message); } } }