163 lines
4.4 KiB
C#
163 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class NPC : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public class DialogueOption
|
|
{
|
|
public string playerReply;
|
|
public string npcReply;
|
|
public bool closeAfterSelection;
|
|
public bool requiresAllNotes;
|
|
public string unavailableReply;
|
|
}
|
|
|
|
[SerializeField] private string npcName = "Смотритель";
|
|
[SerializeField] private string openingLine = "Вы нашли что-нибудь интересное?";
|
|
[SerializeField] private List<DialogueOption> dialogueOptions = new List<DialogueOption>();
|
|
[SerializeField] private Renderer npcRenderer;
|
|
[SerializeField] private Material defaultMaterial;
|
|
[SerializeField] private Material highlightMaterial;
|
|
|
|
private bool playerInRange;
|
|
private bool hasRegisteredConversation;
|
|
|
|
public string NPCName => npcName;
|
|
public string OpeningLine => openingLine;
|
|
public IReadOnlyList<DialogueOption> DialogueOptions => dialogueOptions;
|
|
|
|
public void Configure(
|
|
string characterName,
|
|
string introLine,
|
|
Renderer targetRenderer,
|
|
Material baseMaterial,
|
|
Material selectedMaterial,
|
|
List<DialogueOption> options)
|
|
{
|
|
npcName = characterName;
|
|
openingLine = introLine;
|
|
npcRenderer = targetRenderer;
|
|
defaultMaterial = baseMaterial;
|
|
highlightMaterial = selectedMaterial;
|
|
dialogueOptions = options ?? new List<DialogueOption>();
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
if (npcRenderer == null)
|
|
{
|
|
npcRenderer = GetComponentInChildren<Renderer>();
|
|
}
|
|
|
|
if (defaultMaterial == null && npcRenderer != null)
|
|
{
|
|
defaultMaterial = npcRenderer.sharedMaterial;
|
|
}
|
|
|
|
SetHighlighted(false);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (playerInRange && !GameUIState.IsAnyBlockingUIOpen && Input.GetKeyDown(KeyCode.E))
|
|
{
|
|
Interact();
|
|
}
|
|
}
|
|
|
|
public void SetPlayerInRange(bool isInRange)
|
|
{
|
|
playerInRange = isInRange;
|
|
SetHighlighted(isInRange);
|
|
|
|
if (isInRange)
|
|
{
|
|
InteractionPromptUI.Instance?.ShowPrompt(this, "Нажмите E");
|
|
}
|
|
else
|
|
{
|
|
InteractionPromptUI.Instance?.HidePrompt(this);
|
|
}
|
|
}
|
|
|
|
public void Interact()
|
|
{
|
|
DialogueUI.Instance?.ShowDialogue(this);
|
|
}
|
|
|
|
public bool IsOptionAvailable(DialogueOption option)
|
|
{
|
|
if (option == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return !option.requiresAllNotes || (QuestManager.Instance != null && QuestManager.Instance.HasCollectedAllNotes);
|
|
}
|
|
|
|
public string GetOptionLabel(DialogueOption option)
|
|
{
|
|
if (option == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
if (IsOptionAvailable(option))
|
|
{
|
|
return option.playerReply;
|
|
}
|
|
|
|
var requiredNotes = QuestManager.Instance != null ? QuestManager.Instance.TotalNotes : 3;
|
|
return $"{option.playerReply} (нужно {requiredNotes} записки)";
|
|
}
|
|
|
|
public void SelectOption(DialogueOption option)
|
|
{
|
|
if (option == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!IsOptionAvailable(option))
|
|
{
|
|
var fallbackReply = string.IsNullOrWhiteSpace(option.unavailableReply)
|
|
? "Сначала найди все записки, потом мы продолжим этот разговор."
|
|
: option.unavailableReply;
|
|
|
|
DialogueUI.Instance?.ShowFollowUp(npcName, fallbackReply);
|
|
return;
|
|
}
|
|
|
|
if (!hasRegisteredConversation)
|
|
{
|
|
hasRegisteredConversation = true;
|
|
QuestManager.Instance?.NPCTalked();
|
|
}
|
|
|
|
if (option.closeAfterSelection || string.IsNullOrWhiteSpace(option.npcReply))
|
|
{
|
|
DialogueUI.Instance?.CloseDialogue();
|
|
return;
|
|
}
|
|
|
|
DialogueUI.Instance?.ShowFollowUp(npcName, option.npcReply);
|
|
}
|
|
|
|
private void SetHighlighted(bool highlighted)
|
|
{
|
|
if (npcRenderer == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var targetMaterial = highlighted && highlightMaterial != null ? highlightMaterial : defaultMaterial;
|
|
|
|
if (targetMaterial != null)
|
|
{
|
|
npcRenderer.material = targetMaterial;
|
|
}
|
|
}
|
|
}
|