241 lines
7.0 KiB
C#
241 lines
7.0 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using Unheimlich.Data.Dialogues;
|
|
using Unheimlich.Gameplay.Player;
|
|
using Unheimlich.UI;
|
|
using Unheimlich.Interactions.Dialogues;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Unheimlich.Managers
|
|
{
|
|
public class DialogueManager : MonoBehaviour
|
|
{
|
|
public static DialogueManager Instance { get; private set; }
|
|
|
|
[Header("State")]
|
|
public bool IsInDialogue = false;
|
|
|
|
[Header("Focus Settings")]
|
|
[SerializeField] private LayerMask _choiceLayer;
|
|
[SerializeField] private float _focusRange = 5f;
|
|
[SerializeField] private float _focusTime = 1.5f;
|
|
[SerializeField] private float _raycastInterval = 0.05f;
|
|
|
|
[Header("Focus Stabilization")]
|
|
[SerializeField] private float _recoveryDuration = 0.5f;
|
|
[SerializeField] private float _focusRetentionTime = 0.1f;
|
|
[SerializeField] private float _shakeIntensity = 30f;
|
|
|
|
public DialogueAnimationSettings CurrentAnimationSettings => _currentAnimationSettings;
|
|
public bool IsDialogueActive => IsInDialogue;
|
|
public Transform CurrentChoiceAnchor => _currentChoiceAnchor;
|
|
public DialogueUI CurrentDialogueUI => _activeDialogueUI;
|
|
public object CurrentOwner { get; private set; }
|
|
public DialogueConversation CurrentConversation => _currentConversation;
|
|
public DialogueNode CurrentNode => _currentNode;
|
|
|
|
public event Action<DialogueChoiceData> OnChoiceMade;
|
|
public event Action<object> OnDialogueCompleted;
|
|
|
|
private DialogueFocusSystem _focusSystem;
|
|
private Camera _mainCamera;
|
|
private PlayerLook _playerLook;
|
|
private DialogueAnimationSettings _currentAnimationSettings;
|
|
private DialogueUI _activeDialogueUI;
|
|
private Transform _currentChoiceAnchor;
|
|
|
|
private DialogueConversation _currentConversation;
|
|
private DialogueNode _currentNode;
|
|
private float _autoCloseTimer = 0f;
|
|
private bool _isWaitingForAutoClose = false;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(this);
|
|
return;
|
|
}
|
|
Instance = this;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_playerLook = PlayerLook.Instance;
|
|
_mainCamera = Camera.main;
|
|
|
|
_focusSystem = new DialogueFocusSystem(
|
|
this,
|
|
_mainCamera,
|
|
_playerLook,
|
|
_choiceLayer,
|
|
_focusRange,
|
|
_focusTime,
|
|
_raycastInterval,
|
|
_recoveryDuration,
|
|
_focusRetentionTime,
|
|
_shakeIntensity
|
|
);
|
|
|
|
_focusSystem.OnChoiceMade += (choice) => OnChoiceMade?.Invoke(choice);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsInDialogue)
|
|
return;
|
|
|
|
if (!_activeDialogueUI.AreChoicesVisible())
|
|
{
|
|
if (_isWaitingForAutoClose && _currentNode != null && _currentNode.AutoCloseDelay > 0f)
|
|
{
|
|
_autoCloseTimer += Time.deltaTime;
|
|
|
|
if (_autoCloseTimer >= _currentNode.AutoCloseDelay)
|
|
{
|
|
_activeDialogueUI.FadeOutAndHide(() =>
|
|
{
|
|
OnDialogueCompleted?.Invoke(CurrentOwner);
|
|
CleanupDialogue();
|
|
});
|
|
|
|
IsInDialogue = false;
|
|
_isWaitingForAutoClose = false;
|
|
|
|
if (DialogueBlurEffectURP.Instance != null)
|
|
{
|
|
DialogueBlurEffectURP.Instance.HideBlur();
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (PlayerInputManager.Instance != null &&
|
|
PlayerInputManager.Instance.InteractAction.action.WasPressedThisFrame())
|
|
{
|
|
EndDialogue();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_focusSystem?.Update();
|
|
}
|
|
}
|
|
|
|
public void StartConversation(DialogueConversation conversation, Transform choiceAnchor = null, DialogueAnimationSettings animationSettings = null, DialogueUI customDialogueUI = null, object owner = null)
|
|
{
|
|
if (conversation == null)
|
|
{
|
|
Debug.LogError("Cannot start conversation: conversation is null");
|
|
return;
|
|
}
|
|
|
|
DialogueNode firstNode = conversation.GetFirstNode();
|
|
if (firstNode == null)
|
|
{
|
|
Debug.LogError($"Cannot start conversation {conversation.name}: no dialogue nodes found");
|
|
return;
|
|
}
|
|
|
|
_currentConversation = conversation;
|
|
_currentNode = firstNode;
|
|
_currentChoiceAnchor = choiceAnchor;
|
|
_currentAnimationSettings = animationSettings;
|
|
_activeDialogueUI = customDialogueUI;
|
|
CurrentOwner = owner;
|
|
|
|
ShowCurrentNode();
|
|
}
|
|
|
|
private void ShowCurrentNode()
|
|
{
|
|
if (_currentNode == null || _currentConversation == null)
|
|
return;
|
|
|
|
UnlockFocus();
|
|
IsInDialogue = true;
|
|
|
|
if(_currentChoiceAnchor == null)
|
|
{
|
|
Debug.LogWarning("No choice anchor found!");
|
|
return;
|
|
}
|
|
Transform anchor = _currentChoiceAnchor;
|
|
|
|
string speakerName = _currentConversation.SpeakerName;
|
|
string dialogueText = _currentNode.DialogueText;
|
|
|
|
_activeDialogueUI.ShowDialogueBox(speakerName, dialogueText);
|
|
|
|
_autoCloseTimer = 0f;
|
|
_isWaitingForAutoClose = false;
|
|
|
|
if (_currentNode.Choices != null && _currentNode.Choices.Count > 0)
|
|
{
|
|
List<DialogueChoiceData> validChoices = new List<DialogueChoiceData>();
|
|
|
|
foreach (var choiceData in _currentNode.Choices)
|
|
{
|
|
if (choiceData != null && choiceData.IsValid())
|
|
validChoices.Add(choiceData);
|
|
}
|
|
|
|
if (validChoices.Count > 0)
|
|
_activeDialogueUI.ShowChoices(validChoices, anchor, _currentAnimationSettings);
|
|
}
|
|
else
|
|
_isWaitingForAutoClose = true;
|
|
}
|
|
|
|
public void GoToNextNode(DialogueNode nextNode)
|
|
{
|
|
if (nextNode == null)
|
|
{
|
|
OnDialogueCompleted?.Invoke(CurrentOwner);
|
|
EndDialogue();
|
|
return;
|
|
}
|
|
|
|
UnlockFocus();
|
|
|
|
if (_activeDialogueUI != null)
|
|
_activeDialogueUI.HideChoices();
|
|
|
|
_currentNode = nextNode;
|
|
ShowCurrentNode();
|
|
}
|
|
|
|
public void EndDialogue()
|
|
{
|
|
IsInDialogue = false;
|
|
|
|
if (_activeDialogueUI != null)
|
|
_activeDialogueUI.HideDialogueBox();
|
|
|
|
if (DialogueBlurEffectURP.Instance != null)
|
|
DialogueBlurEffectURP.Instance.HideBlur();
|
|
|
|
CleanupDialogue();
|
|
}
|
|
|
|
private void CleanupDialogue()
|
|
{
|
|
_currentChoiceAnchor = null;
|
|
_currentAnimationSettings = null;
|
|
_activeDialogueUI = null;
|
|
CurrentOwner = null;
|
|
|
|
_currentConversation = null;
|
|
_currentNode = null;
|
|
_autoCloseTimer = 0f;
|
|
_isWaitingForAutoClose = false;
|
|
}
|
|
|
|
public void UnlockFocus()
|
|
{
|
|
_focusSystem?.UnlockFocus();
|
|
}
|
|
}
|
|
}
|