Files

289 lines
9.0 KiB
C#

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;
/// <summary>
/// Called when player interacts with this NPC
/// </summary>
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);
}
}
/// <summary>
/// Display dialogue for this NPC using EasyTalk with centralized DialogueController
/// </summary>
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}");
}
}
/// <summary>
/// Finds the central DialogueController in the scene
/// </summary>
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<DialogueController>();
if (controller != null)
{
Log($"Found central DialogueController on '{dialogueManagerName}'");
return controller;
}
}
}
// Fallback: search for any DialogueController in the scene
DialogueController foundController = FindAnyObjectByType<DialogueController>();
if (foundController != null)
{
Log($"Found DialogueController via FindAnyObjectByType on '{foundController.gameObject.name}'");
return foundController;
}
return null;
}
/// <summary>
/// Offer quest to the player
/// </summary>
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.");
}
}
/// <summary>
/// Complete a quest with this NPC (quest turn-in)
/// </summary>
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;
}
/// <summary>
/// Open merchant trading interface
/// </summary>
protected virtual void OpenMerchantInterface(GameObject player)
{
Debug.Log($"Opening merchant interface for {npcName}", gameObject);
// TODO: Implement merchant UI
}
/// <summary>
/// Open training interface for learning skills
/// </summary>
protected virtual void OpenTrainingInterface(GameObject player)
{
Debug.Log($"Opening training interface for {npcName}", gameObject);
// TODO: Implement training UI
}
/// <summary>
/// Check if this NPC can perform a specific service
/// </summary>
public bool CanProvideService(NPCType serviceType)
{
return npcType == serviceType ||
(serviceType == NPCType.Merchant && isMerchant) ||
(serviceType == NPCType.Trainer && isTrainer) ||
(serviceType == NPCType.QuestGiver && isQuestGiver);
}
/// <summary>
/// NPCs don't die by default - override for hostile NPCs
/// </summary>
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);
}
}
}