369 lines
11 KiB
C#
369 lines
11 KiB
C#
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;
|
||
|
||
#endregion РЕПЛИКИ
|
||
|
||
private string pulledGlobalDifficulty;
|
||
void pullSettings()
|
||
{
|
||
pulledGlobalDifficulty = SettingsManager.GetString(SettingKey.DIFFICULTY);
|
||
currentDifficulty = CurrenDifficultyList.Count / 2;
|
||
audioSource.volume = SettingsManager.GetFloat(SettingKey.SOUNDS_VOLUME);
|
||
}
|
||
private void OnEnable()
|
||
{
|
||
SettingsManager.OnSettingsChanged += 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)
|
||
{
|
||
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)
|
||
{
|
||
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(SettingKey.SOUNDS_VOLUME) * 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(SettingKey.DIFFICULTY_MODE) == "Заработок")
|
||
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;
|
||
} |