using UnityEngine; using Unheimlich.Core.Interaction; using Unheimlich.Features.Dialogue.Data; using Unheimlich.Features.Dialogue; using Unheimlich.Features.Player; using Unheimlich.Features.Dialogue.UI; namespace Unheimlich.Features.Dialogue { /// /// NPC interactable that starts dialogue conversations. /// Rotates to face player during dialogue and pauses if player moves too far away. /// public class NPCDialogueTrigger : InteractableBase { [Header("Dialogue Reference")] [Tooltip("DialogueConversation to use for this NPC")] public DialogueConversation Conversation; [Header("Trigger Settings")] [Tooltip("Can the dialogue be retriggered after completion")] [SerializeField] private bool _isRetriggerable = true; [Header("Floating Word Setting")] [SerializeField] private Transform _floatingWordAnchor; [Header("Animation Settings")] [SerializeField] private DialogueAnimationSettings _animationSettings; [Header("UI Reference")] [Tooltip("Local DialogueUI for this NPC. Uses DialogueManager's UI if null")] [SerializeField] private DialogueUI _localDialogueUI; [Header("Distance Settings")] [Tooltip("Maximum distance before dialogue pauses")] [SerializeField] private float _maxDialogueDistance = 5f; [Header("Blur Effect")] [Tooltip("Enable blur effect when dialogue starts")] [SerializeField] private bool _enableBlurEffect = false; public Transform FloatingWordAnchor => _floatingWordAnchor; private bool _isDialogueActive = false; private DialogueStateHandler _dialogueState; private void Awake() { _dialogueState = new DialogueStateHandler(this); } private void Start() { InteractionText = "Talk"; } private void Update() { if (_isDialogueActive && PlayerController.Instance != null) { float distance = Vector3.Distance(transform.position, PlayerController.Instance.transform.position); if (distance > _maxDialogueDistance && DialogueManager.Instance != null && DialogueManager.Instance.IsDialogueActive) { if ((Object)DialogueManager.Instance.CurrentOwner == this) { _dialogueState.PauseDialogue(); _isDialogueActive = false; } } else LookAtPlayer(); } } public override void Interact() { if (DialogueManager.Instance == null) return; if (_dialogueState.IsCompleted && !_isRetriggerable) return; if (_dialogueState.HasPausedDialogue) { _dialogueState.ResumeDialogue(); DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted; _isDialogueActive = true; } else { if (Conversation == null) { Debug.LogWarning($"NPC {gameObject.name} has no conversation configured!"); return; } DialogueManager.Instance.StartConversation( Conversation, _floatingWordAnchor, _animationSettings, _localDialogueUI, this, _enableBlurEffect ); DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted; _isDialogueActive = true; } } private void OnDialogueCompleted(object owner) { if ((Object)owner == this) { _dialogueState.MarkAsCompleted(); if (_isRetriggerable) _dialogueState.AllowRetrigger(); _isDialogueActive = false; } if (DialogueManager.Instance != null) DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted; } private void OnDestroy() { if (DialogueManager.Instance != null) DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted; } public void LookAtPlayer() { if (PlayerController.Instance == null) return; Vector3 lookAtPosition = PlayerController.Instance.transform.position; lookAtPosition.y = transform.position.y; transform.LookAt(lookAtPosition); } } }