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(); 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 difficultyPresetsEasy; public List difficultyPresetsMedium; public List difficultyPresetsHard; public List 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 appearReplicas; List appearReplicasTemp; [Header("Ход игрока")] [Range(0, 1)] public float playerTurnChance = 1; public List playerTurnReplicas; List playerTurnReplicasTemp; [Header("Ход бота")] [Range(0, 1)] public float botTurnChance = 1; public List botTurnReplicas; List botTurnReplicasTemp; [Header("Игрок выиграл")] [Range(0, 1)] public float playerWinChance = 1; public List playerWinReplicas; List playerWinReplicasTemp; [Header("Бот выиграл")] [Range(0, 1)] public float botWinChance = 1; public List botWinReplicas; List botWinReplicasTemp; [Header("Вернулись на предыдущий уровень")] [Range(0, 1)] public float returnChance = 1; public List returnReplicas; List returnReplicasTemp; [Header("Ничья (редко)")] [Range(0, 1)] public float drawChance = 1; public List drawReplicas; List 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(); 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 origin, List 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 replicasTemp, List 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(); //Подготовка сообщения 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(); 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(); anim.SetBool("Speak", true); label.text = ""; GameObject sound = null; AudioSource source = null; if (botVoice) { sound = new GameObject("TypingSound"); source = sound.AddComponent(); //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().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 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; }