272 lines
8.8 KiB
C#
272 lines
8.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class EnemyManager : MonoBehaviour
|
|
{
|
|
[Header("Ñïèñîê âðàãîâ")]
|
|
public EnemyData[] enemies;
|
|
|
|
[Header("UI êîíòðîëëåð êàðòî÷êè")]
|
|
public EnemyCardController cardController;
|
|
|
|
[Header("Settings")]
|
|
public float dialogueHoldTime = 1f;
|
|
|
|
private int currentIndex = 0;
|
|
private int playerId = 1;
|
|
private Coroutine currentDialogueCoroutine;
|
|
private bool isDialoguePlaying = false;
|
|
|
|
// Îòñëåæèâàíèå èñïîëüçîâàííûõ ðåïëèê äëÿ êàæäîãî òèïà ñîáûòèÿ
|
|
private Dictionary<DialogueEventType, List<int>> usedDialogueIndices = new Dictionary<DialogueEventType, List<int>>();
|
|
|
|
private void Start()
|
|
{
|
|
var player = gameObject.GetComponentInParent<Player>();
|
|
if (player != null)
|
|
playerId = player.PlayerId;
|
|
else
|
|
Debug.LogWarning($"[{name}] Player íå íàéäåí â ðîäèòåëÿõ!");
|
|
}
|
|
|
|
public void SetEnemy(int index)
|
|
{
|
|
if (enemies == null || index < 0 || index >= enemies.Length)
|
|
{
|
|
Debug.LogWarning($"[{name}] SetEnemy: invalid index {index}");
|
|
return;
|
|
}
|
|
|
|
if (!cardController.gameObject.activeSelf)
|
|
cardController.gameObject.SetActive(true);
|
|
|
|
currentIndex = index;
|
|
cardController.SetEnemy(enemies[index]);
|
|
isDialoguePlaying = false;
|
|
|
|
// Ñáðàñûâàåì èñòîðèþ èñïîëüçîâàííûõ ðåïëèê ïðè ñìåíå âðàãà
|
|
usedDialogueIndices.Clear();
|
|
}
|
|
|
|
public void SetEnemyPlayer()
|
|
{
|
|
// Ïðîôèëè èãðîêîâ - ýòî ïîñëåäíèå 2 ýëåìåíòà â ìàññèâå enemies
|
|
// playerId = 1 -> enemies[Length-2], playerId = 2 -> enemies[Length-1]
|
|
if (enemies == null || enemies.Length < 2)
|
|
{
|
|
Debug.LogWarning($"[{name}] SetEnemyPlayer: íåäîñòàòî÷íî âðàãîâ â ìàññèâå äëÿ ïðîôèëåé èãðîêîâ!");
|
|
cardController.gameObject.SetActive(false);
|
|
return;
|
|
}
|
|
|
|
int playerProfileIndex = enemies.Length - (3 - playerId); // playerId 1 -> -2, playerId 2 -> -1
|
|
|
|
if (playerProfileIndex < 0 || playerProfileIndex >= enemies.Length)
|
|
{
|
|
Debug.LogWarning($"[{name}] SetEnemyPlayer: íåêîððåêòíûé èíäåêñ ïðîôèëÿ èãðîêà {playerProfileIndex}");
|
|
cardController.gameObject.SetActive(false);
|
|
return;
|
|
}
|
|
|
|
currentIndex = playerProfileIndex;
|
|
|
|
// Ñêðûâàåì êàðòî÷êó (èãðîê íå ïîêàçûâàåò UI)
|
|
cardController.gameObject.SetActive(false);
|
|
|
|
isDialoguePlaying = false;
|
|
|
|
// Ñáðàñûâàåì èñòîðèþ èñïîëüçîâàííûõ ðåïëèê
|
|
usedDialogueIndices.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïîêàçûâàåò äèàëîã ñ êàðòî÷êîé: îòêðûâàåò ? ãîâîðèò ? çàêðûâàåò
|
|
/// Åñëè êàðòî÷êà íåàêòèâíà - ïðîñòî èãðàåò çâóê
|
|
/// </summary>
|
|
public void ShowDialogueWithCard(DialogueLine line)
|
|
{
|
|
// Åñëè êàðòî÷êà íåàêòèâíà - ïðîñòî èãðàåì çâóê
|
|
if (cardController == null || !cardController.gameObject.activeInHierarchy)
|
|
{
|
|
PlayVoiceOnly(line.voiceClip);
|
|
return;
|
|
}
|
|
|
|
|
|
if (currentDialogueCoroutine != null)
|
|
StopCoroutine(currentDialogueCoroutine);
|
|
|
|
currentDialogueCoroutine = StartCoroutine(DialogueWithCardSequence(line));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïðîèãðûâàåò òîëüêî çâóê áåç êàðòî÷êè
|
|
/// </summary>
|
|
public void PlayVoiceOnly(AudioClip clip)
|
|
{
|
|
if (clip != null && SoundManager.Instance != null)
|
|
{
|
|
SoundManager.Instance.PlayVoice(playerId, clip);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïîêàçûâàåò òåêñò íà óæå îòêðûòîé êàðòî÷êå (áåç àíèìàöèè îòêðûòèÿ/çàêðûòèÿ)
|
|
/// </summary>
|
|
public void ShowTextOnly(string text, string emotion = null)
|
|
{
|
|
if (!string.IsNullOrEmpty(emotion))
|
|
cardController.SetEmotion(emotion);
|
|
|
|
cardController.TypeText(text);
|
|
}
|
|
|
|
private IEnumerator DialogueWithCardSequence(DialogueLine line)
|
|
{
|
|
isDialoguePlaying = true;
|
|
|
|
// 1. Ïîäãîòàâëèâàåì ðàçìåð òåêñòà ÄÎ îòêðûòèÿ ïàíåëè (÷òîáû íå áûëî "áëèêà")
|
|
yield return cardController.PrepareTextSizeAsync(line.text);
|
|
|
|
// 2. Îòêðûâàåì êàðòî÷êó ñ ýìîöèåé ïåðåõîäà
|
|
bool cardOpened = false;
|
|
cardController.ShowCard(line.animationName.ToStateName(), () => cardOpened = true);
|
|
|
|
// Æä¸ì, ïîêà êàðòî÷êà îòêðîåòñÿ
|
|
yield return new WaitUntil(() => cardOpened);
|
|
|
|
// 3. Èãðàåì çâóê
|
|
if (line.voiceClip != null && SoundManager.Instance != null)
|
|
{
|
|
SoundManager.Instance.PlayVoice(playerId, line.voiceClip);
|
|
}
|
|
|
|
// 4. Ïå÷àòàåì òåêñò (ðàçìåð óæå ïîäãîòîâëåí)
|
|
bool textComplete = false;
|
|
cardController.TypeText(line.text, () => textComplete = true, skipSizePreparation: true);
|
|
|
|
// Æä¸ì, ïîêà òåêñò íàïå÷àòàåòñÿ
|
|
yield return new WaitUntil(() => textComplete);
|
|
|
|
// 4. Äåðæèì òåêñò íåìíîãî
|
|
yield return new WaitForSeconds(dialogueHoldTime);
|
|
|
|
// 5. Çàêðûâàåì êàðòî÷êó
|
|
bool cardClosed = false;
|
|
cardController.HideCard(() => cardClosed = true);
|
|
|
|
yield return new WaitUntil(() => cardClosed);
|
|
|
|
isDialoguePlaying = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Âûçûâàåò äèàëîã ðåàêöèè íà ñîáûòèå (ñ êàðòî÷êîé)
|
|
/// Âûáèðàåò ðåïëèêó êîòîðàÿ åù¸ íå èñïîëüçîâàëàñü, ïîêà âñå íå êîí÷àòñÿ
|
|
/// </summary>
|
|
public void TriggerEventReaction(DialogueEventType eventType)
|
|
{
|
|
if (enemies == null || currentIndex < 0 || currentIndex >= enemies.Length)
|
|
return;
|
|
|
|
if(isDialoguePlaying) return;
|
|
|
|
var enemy = enemies[currentIndex];
|
|
DialogueLine? line = GetNonRepeatingDialogue(enemy, eventType);
|
|
|
|
if (line.HasValue)
|
|
{
|
|
ShowDialogueWithCard(line.Value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïîëó÷àåò ñëó÷àéíóþ ðåïëèêó êîòîðàÿ åù¸ íå èñïîëüçîâàëàñü äëÿ äàííîãî òèïà ñîáûòèÿ
|
|
/// </summary>
|
|
private DialogueLine? GetNonRepeatingDialogue(EnemyData enemy, DialogueEventType eventType)
|
|
{
|
|
if (enemy == null)
|
|
return null;
|
|
|
|
// Ïîëó÷àåì íóæíûé ìàññèâ ðåïëèê ïî òèïó ñîáûòèÿ
|
|
DialogueLine[] sourceArray = null;
|
|
switch (eventType)
|
|
{
|
|
case DialogueEventType.PlayerHit: sourceArray = enemy.onPlayerHit; break;
|
|
case DialogueEventType.PlayerMiss: sourceArray = enemy.onPlayerMiss; break;
|
|
case DialogueEventType.BotHit: sourceArray = enemy.onBotHit; break;
|
|
case DialogueEventType.BotMiss: sourceArray = enemy.onBotMiss; break;
|
|
case DialogueEventType.PlayerShipDestroyed: sourceArray = enemy.onPlayerShipDestroyed; break;
|
|
case DialogueEventType.BotShipDestroyed: sourceArray = enemy.onBotShipDestroyed; break;
|
|
}
|
|
|
|
if (sourceArray == null || sourceArray.Length == 0)
|
|
return null;
|
|
|
|
// Èíèöèàëèçèðóåì ñïèñîê èñïîëüçîâàííûõ ðåïëèê äëÿ ýòîãî òèïà ñîáûòèÿ åñëè íóæíî
|
|
if (!usedDialogueIndices.ContainsKey(eventType))
|
|
{
|
|
usedDialogueIndices[eventType] = new List<int>();
|
|
}
|
|
|
|
var usedList = usedDialogueIndices[eventType];
|
|
|
|
// Ñîçäà¸ì ñïèñîê íåèñïîëüçîâàííûõ èíäåêñîâ
|
|
var unusedIndices = new List<int>();
|
|
for (int i = 0; i < sourceArray.Length; i++)
|
|
{
|
|
if (!usedList.Contains(i))
|
|
unusedIndices.Add(i);
|
|
}
|
|
|
|
// Åñëè âñå ðåïëèêè èñïîëüçîâàíû - ñáðàñûâàåì è íà÷èíàåì çàíîâî
|
|
if (unusedIndices.Count == 0)
|
|
{
|
|
usedList.Clear();
|
|
for (int i = 0; i < sourceArray.Length; i++)
|
|
{
|
|
unusedIndices.Add(i);
|
|
}
|
|
}
|
|
|
|
// Âûáèðàåì ñëó÷àéíûé íåèñïîëüçîâàííûé èíäåêñ
|
|
int randomIndex = unusedIndices[Random.Range(0, unusedIndices.Count)];
|
|
usedList.Add(randomIndex);
|
|
|
|
return sourceArray[randomIndex];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ðåàêöèÿ íà êîíåö èãðû (òîëüêî çâóê, áåç êàðòî÷êè)
|
|
/// </summary>
|
|
public void TriggerEndGameReaction(bool playerWon)
|
|
{
|
|
if (enemies == null || enemies.Length == 0) return;
|
|
if (currentIndex < 0 || currentIndex >= enemies.Length) return;
|
|
isDialoguePlaying = true;
|
|
|
|
var enemy = enemies[currentIndex];
|
|
var clips = playerWon ? enemy.playerVictory : enemy.playerDefeat;
|
|
|
|
if (clips == null || clips.Length == 0) return;
|
|
|
|
// Îñòàíàâëèâàåì ãîëîñîâîé êàíàë òåêóùåãî èãðîêà, çàòåì ïðîèãðûâàåì ôèíàëüíóþ ôðàçó
|
|
if (SoundManager.Instance != null)
|
|
{
|
|
SoundManager.Instance.StopVoice(playerId);
|
|
}
|
|
Debug.Log(clips[0].name);
|
|
|
|
PlayVoiceOnly(clips[Random.Range(0, clips.Length)]);
|
|
}
|
|
|
|
public EnemyData GetCurrentEnemy()
|
|
{
|
|
if (enemies == null || currentIndex < 0 || currentIndex >= enemies.Length)
|
|
return null;
|
|
|
|
return enemies[currentIndex];
|
|
}
|
|
}
|