sea-battle/Assets/Scripts/UI/EnemyCardController.cs
2026-01-09 08:45:22 +03:00

226 lines
6.2 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class EnemyCardController : MonoBehaviour
{
[Header("UI Elements")]
public Image avatarImage;
public Animator avatarAnimator;
public TMP_Text nicknameText;
public TMP_Text dialogueText;
public RectTransform dialoguePanel;
[Header("Settings")]
public float typingSpeed = 0.05f;
public float panelExpandWidth = 300f;
public float panelExpandSpeed = 5f;
public float dialogueHoldTime = 1f;
[Header("Animation names")]
public string idleAnimationName = "Idle_bot_1";
public string transitionIn = "forvard_bot";
public string transitionOut = "back_bot";
private EnemyData currentEnemy;
private int dialogueIndex = 0;
private Coroutine dialogueCoroutine;
private Vector2 dialogueOriginalPos;
private DialogueLine? pendingDialogue;
private HashSet<string> availableStates = new HashSet<string>(); // ðåàëüíî ïåðåîïðåäåë¸ííûå ñîñòîÿíèÿ
private int playerId = 1;
private void Awake()
{
if (dialoguePanel != null)
dialogueOriginalPos = dialoguePanel.anchoredPosition;
playerId = gameObject.GetComponentInParent<Player>().PlayerId;
}
private void OnEnable()
{
if (pendingDialogue.HasValue)
{
StartDialogue(pendingDialogue.Value);
pendingDialogue = null;
}
}
public void SetEnemy(EnemyData enemy)
{
currentEnemy = enemy;
nicknameText.text = enemy.nickname;
dialogueIndex = 0;
availableStates.Clear();
if (enemy.animatorOverride != null && avatarAnimator != null)
{
avatarAnimator.runtimeAnimatorController = enemy.animatorOverride;
avatarAnimator.enabled = true;
// Ïîëó÷àåì ðåàëüíî ïåðåîïðåäåë¸ííûå àíèìàöèè
var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
enemy.animatorOverride.GetOverrides(overrides);
foreach (var kv in overrides)
{
if (kv.Value != null)
availableStates.Add(kv.Key.name);
}
}
else
{
if (enemy.characterSprite != null)
avatarImage.sprite = enemy.characterSprite;
avatarAnimator.enabled = false;
}
dialogueText.text = "";
if (dialoguePanel != null)
{
dialoguePanel.anchoredPosition = dialogueOriginalPos;
dialoguePanel.SetSiblingIndex(0); // ïàíåëü ïîä ïîðòðåòîì
}
}
public void ShowNextDialogue()
{
if (currentEnemy == null || currentEnemy.dialogues.Length == 0) return;
DialogueLine line = currentEnemy.dialogues[dialogueIndex];
dialogueIndex = (dialogueIndex + 1) % currentEnemy.dialogues.Length;
if (!gameObject.activeInHierarchy)
{
pendingDialogue = line;
return;
}
StartDialogue(line);
}
private void StartDialogue(DialogueLine line)
{
if (dialogueCoroutine != null)
StopCoroutine(dialogueCoroutine);
dialogueCoroutine = StartCoroutine(DialogueSequence(line));
}
/// <summary>
/// Ïîêàçûâàåò äèàëîã, ñîîòâåòñòâóþùèé óêàçàííîìó ñîáûòèþ
/// </summary>
public void ShowEventDialogue(DialogueEventType eventType)
{
if (currentEnemy == null) return;
DialogueLine? line = currentEnemy.GetRandomDialogue(eventType);
if (line.HasValue)
{
if (!gameObject.activeInHierarchy)
{
pendingDialogue = line.Value;
return;
}
StartDialogue(line.Value);
}
}
private IEnumerator DialogueSequence(DialogueLine line)
{
// 1. Âðåìåííî óñòàíàâëèâàåì ïîëíûé òåêñò (íåâèäèìî)
dialogueText.enableWordWrapping = true;
dialogueText.overflowMode = TextOverflowModes.Overflow;
dialogueText.text = line.text;
// 2. Âêëþ÷àåì àâòî-ïîäáîð ðàçìåðà
dialogueText.enableAutoSizing = true;
dialogueText.fontSizeMin = 5;
// 3. Æä¸ì 1 êàäð — ÷òîáû TMP ïðîñ÷èòàë ðàçìåð
yield return null;
// 4. Ñîõðàíÿåì ïîäîáðàííûé ðàçìåð
float finalFontSize = dialogueText.fontSize;
// 5. Ôèêñèðóåì ðàçìåð (àâòîñàéç âûêëþ÷àåì)
dialogueText.enableAutoSizing = false;
dialogueText.fontSize = finalFontSize;
// 6. Î÷èùàåì òåêñò ïåðåä ïå÷àòüþ
dialogueText.text = "";
// Ïîçèöèè ïàíåëè
Vector2 hiddenPos = dialogueOriginalPos;
Vector2 shownPos = hiddenPos + new Vector2(panelExpandWidth, 0);
// Âõîä ïàíåëè
SetEmotion(transitionIn);
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime * panelExpandSpeed;
dialoguePanel.anchoredPosition = Vector2.Lerp(hiddenPos, shownPos, t);
yield return null;
}
dialoguePanel.anchoredPosition = shownPos;
// Àíèìàöèÿ ýìîöèè
SetEmotion(line.animationName);
if (line.voiceClip != null)
{
SoundManager.Instance.PlayVoice(playerId, line.voiceClip);
}
// Ïå÷àòü òåêñòà
dialogueText.text = "";
foreach (char c in line.text)
{
dialogueText.text += c;
yield return new WaitForSeconds(typingSpeed);
}
// Æä¸ì
yield return new WaitForSeconds(dialogueHoldTime);
// Âûõîä ïàíåëè
SetEmotion(transitionOut);
dialogueText.text = "";
t = 0f;
while (t < 1f)
{
t += Time.deltaTime * panelExpandSpeed;
dialoguePanel.anchoredPosition = Vector2.Lerp(shownPos, hiddenPos, t);
yield return null;
}
dialoguePanel.anchoredPosition = hiddenPos;
// Âîçâðàò â idle
SetEmotion(idleAnimationName);
}
public void SetEmotion(string stateName)
{
if (avatarAnimator == null || string.IsNullOrEmpty(stateName)) return;
if (availableStates.Contains(stateName))
avatarAnimator.Play(stateName);
}
}