371 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using PrizeSystem;
public class Character : MonoBehaviour
{
public Sprite Icon;
public Sprite IconSmall;
public string Name;
public int CharacterIndex; //Для эффектов
public Sprite chipImage;
AudioSource audioSource;
Animator animator;
public Animator Animator => animator ?? GetComponent<Animator>();
public Prize prize;
public bool HasPrize = true;
public Vector2 boxLocalPosition = new Vector2(0, 500);
public Vector2 CharacterLocalPosition = new Vector2(0, 0);
public AnimationClip chipSpawningAnim;
public AudioClip chipThrowClip;
[Header("Списки сложностей")]
public List<DifficultyPreset> difficultyPresetsEasy;
public List<DifficultyPreset> difficultyPresetsMedium;
public List<DifficultyPreset> difficultyPresetsHard;
public List<DifficultyPreset> CurrenDifficultyList
{
get
{
switch (pulledGlobalDifficulty)
{
case "Легкая":
return difficultyPresetsEasy;
case "Средняя":
return difficultyPresetsMedium;
case "Сложная":
return difficultyPresetsHard;
default:
return difficultyPresetsMedium;
}
}
}
public int currentDifficulty;
public float ThinkTime => UnityEngine.Random.Range(minThinkTime, maxThinkTime);
[SerializeField] float minThinkTime = 0;
[SerializeField] float maxThinkTime = 2;
#region РЕПЛИКИ
[Header("Появление")]
[Range(0, 1)] public float appearChance = 1;
public List<Replica> appearReplicas;
List<Replica> appearReplicasTemp;
[Header("Ход игрока")]
[Range(0, 1)] public float playerTurnChance = 1;
public List<Replica> playerTurnReplicas;
List<Replica> playerTurnReplicasTemp;
[Header("Ход бота")]
[Range(0, 1)] public float botTurnChance = 1;
public List<Replica> botTurnReplicas;
List<Replica> botTurnReplicasTemp;
[Header("Игрок выиграл")]
[Range(0, 1)] public float playerWinChance = 1;
public List<Replica> playerWinReplicas;
List<Replica> playerWinReplicasTemp;
[Header("Бот выиграл")]
[Range(0, 1)] public float botWinChance = 1;
public List<Replica> botWinReplicas;
List<Replica> botWinReplicasTemp;
[Header("Вернулись на предыдущий уровень")]
[Range(0, 1)] public float returnChance = 1;
public List<Replica> returnReplicas;
List<Replica> returnReplicasTemp;
[Header("Ничья (редко)")]
[Range(0, 1)] public float drawChance = 1;
public List<Replica> drawReplicas;
List<Replica> drawReplicasTemp;
private CharacterEventBus bus;
private GameObject currentMessageBox;
bool useVoice = true;
#endregion РЕПЛИКИ
private string pulledGlobalDifficulty;
void pullSettings()
{
useVoice = SettingsManager.GetBool("EnableVoices", true);
pulledGlobalDifficulty = SettingsManager.GetString("Difficulty", "Средняя");
currentDifficulty = CurrenDifficultyList.Count / 2;
audioSource.volume = SettingsManager.GetFloat("SoundsVolume", 0.5f);
}
private void OnEnable()
{
SettingsManager.OnSettingsChanged.AddListener(pullSettings);
audioSource = GetComponent<AudioSource>();
pullSettings();
SetupTempReplicaLists();
currentDifficulty = CurrenDifficultyList.Count / 2;
}
private void SetupTempReplicaLists()
{
appearReplicasTemp = new();
playerTurnReplicasTemp = new();
botTurnReplicasTemp = new();
playerWinReplicasTemp = new();
botWinReplicasTemp = new();
returnReplicasTemp = new();
drawReplicasTemp = new();
FillTempList(appearReplicas, appearReplicasTemp);
FillTempList(playerTurnReplicas, playerTurnReplicasTemp);
FillTempList(botTurnReplicas, botTurnReplicasTemp);
FillTempList(playerWinReplicas, playerWinReplicasTemp);
FillTempList(botWinReplicas, botWinReplicasTemp);
FillTempList(returnReplicas, returnReplicasTemp);
FillTempList(drawReplicas, drawReplicasTemp);
}
private void FillTempList(List<Replica> origin, List<Replica> destination)
{
destination.Clear();
foreach (Replica s in origin)
{
destination.Add(s);
}
}
#region Биндинг событий
public void BindEvents()
{
bus = CharacterEventBus.Instance;
bus.OnCharacterAppeared.AddListener(CharacterAppear);
bus.OnPlayerTurn.AddListener(PlayerTurn);
bus.OnBotTurn.AddListener(BotTurn);
bus.OnPlayerWin.AddListener(PlayerWin);
bus.OnBotWin.AddListener(BotWin);
bus.OnLevelDown.AddListener(LevelDown);
bus.OnDraw.AddListener(Draw);
}
public void UnbindEvents()
{
bus = CharacterEventBus.Instance;
bus.OnCharacterAppeared.RemoveListener(CharacterAppear);
bus.OnPlayerTurn.RemoveListener(PlayerTurn);
bus.OnBotTurn.RemoveListener(BotTurn);
bus.OnPlayerWin.RemoveListener(PlayerWin);
bus.OnBotWin.RemoveListener(BotWin);
bus.OnLevelDown.RemoveListener(LevelDown);
bus.OnDraw.RemoveListener(Draw);
}
#endregion
#region Отправка сообщений
public GameObject messageBoxPrefab;
public AudioClip botVoice;
public float typingDelay = 0.05f;
public float culldownTime = 2;
bool nowTyping = false;
bool Message(List<Replica> replicasTemp, List<Replica> replicas, bool priority, float chance, bool showName=false)
{
//Поступило неприоритетное сообщение и бокс занят
if (nowTyping && !priority)
{
return false;
}
//Проверяем вероятность
bool condition = UnityEngine.Random.Range(0, 1f) < chance && replicasTemp.Count > 0;
if (!condition)
{
return false;
}
//сообщение приоритетное
if (nowTyping)
{
StopAllCoroutines();
Destroy(currentMessageBox);
}
nowTyping = true;
//подготовка бокса
currentMessageBox = Instantiate(messageBoxPrefab, transform);
currentMessageBox.transform.GetChild(1).gameObject.SetActive(showName);//включить или выключить имя
currentMessageBox.transform.localPosition = boxLocalPosition;
TextMeshProUGUI label = currentMessageBox.transform.GetComponentInChildren<TextMeshProUGUI>();
//Подготовка сообщения
int index = UnityEngine.Random.Range(0, replicasTemp.Count);
string message = replicasTemp[index].text;
if (replicasTemp[index].clip && useVoice)
{
audioSource.clip = replicasTemp[index].clip;
audioSource.Play();
//скрутить фоновую
SoundManager.instance.MusicFade(fadeDuration: 0.2f,
holdDuration: replicasTemp[index].clip.length - 0.2f,
targetVolumePercent: 0.5f);
}
StartCoroutine(ShowText(message, label, replicasTemp[index].clip.length));
replicasTemp.RemoveAt(index);
if (replicasTemp.Count == 0)
FillTempList(replicas, replicasTemp);
return true;
}
//для прогона реплик
public bool Message(Replica replica)
{
//подготовка бокса
currentMessageBox = Instantiate(messageBoxPrefab, transform);
currentMessageBox.transform.localPosition = boxLocalPosition;
TextMeshProUGUI label = currentMessageBox.transform.GetComponentInChildren<TextMeshProUGUI>();
string message = replica.text;
if (replica.clip && useVoice)
{
audioSource.clip = replica.clip;
audioSource.Play();
}
StartCoroutine(ShowText(message, label, 0.05f));
return true;
}
IEnumerator ShowText(string message, TextMeshProUGUI label, float replicaClipLength)
{
Animator anim = GetComponent<Animator>();
anim.SetBool("Speak", true);
label.text = "";
GameObject sound = null;
AudioSource source = null;
if (botVoice)
{
sound = new GameObject("TypingSound");
source = sound.AddComponent<AudioSource>();
//source.clip = botVoice;
source.volume = SettingsManager.GetFloat("SoundsVolume", 0.5f) * 0.5f;
typingDelay = replicaClipLength / message.Length;
}
else
{
typingDelay = 0.05f;
}
for (int i = 0; i < message.Length; i++)
{
label.text = label.text + message[i];
if (botVoice)
{
source.pitch = UnityEngine.Random.Range(1.5f, 1.6f);
source.PlayOneShot(botVoice);
}
yield return new WaitForSeconds(typingDelay);
}
Destroy(sound, botVoice.length);
anim.SetBool("Speak", false);
yield return new WaitForSeconds(culldownTime);
nowTyping = false;
Destroy(label.transform.parent.gameObject);
}
#endregion
#region Обработчики событий
public void CharacterAppear()
{
if (Message(appearReplicasTemp, appearReplicas, true, appearChance, showName:true))
GetComponent<Animator>().SetTrigger("Appear");
}
public void PlayerTurn()
{
Message(playerTurnReplicasTemp, playerTurnReplicas, false, playerTurnChance);
}
public void BotTurn()
{
Message(botTurnReplicasTemp, botTurnReplicas, false, botTurnChance);
}
public void PlayerWin()
{
Message(playerWinReplicasTemp, playerWinReplicas, true, playerWinChance);
}
public void BotWin()
{
Message(botWinReplicasTemp, botWinReplicas, true, botWinChance);
}
public void LevelDown()
{
Message(returnReplicasTemp, returnReplicas, true, returnChance);
}
public void Draw()
{
Message(drawReplicasTemp, drawReplicas, true, drawChance);
}
#endregion
#region Управление сложностью
public DifficultyPreset CurrentDifficultyPreset => GetDifficultyPreset();
private DifficultyPreset GetDifficultyPreset()
{
List<DifficultyPreset> presets;
if (SettingsManager.GetString("BaseBotDifficulty", "Фиксированная") == "Повышенная")
presets = difficultyPresetsHard;
else
presets = CurrenDifficultyList;
int index = Mathf.Clamp(currentDifficulty, 0, presets.Count-1);//? -1?
return presets[index];
}
public void IncreaseDifficuly() => currentDifficulty = (currentDifficulty+1 + CurrenDifficultyList.Count) % CurrenDifficultyList.Count;
public void DecreaseDifficuly() => currentDifficulty = (currentDifficulty - 1 + CurrenDifficultyList.Count) % CurrenDifficultyList.Count;
#endregion
public void PlayThrowChip()//Инвок в анимациях
{
SoundManager.instance.playClip(chipThrowClip);
}
}
[Serializable] //чтобы редачить в инспекторе
public struct Replica
{
public AudioClip clip;
public string text;
}