using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class BattleControl : MonoBehaviour { public static BattleControl Instance; public Slider unitHealthSlider, enemyUnitHealthSlider, actionTimerSlider; [SerializeField] private Button attackButton, defendButton, healButton, retreatButton; [SerializeField] private TextMeshProUGUI unitHealthText, enemyUnitHealthText, combinedATKText, combinedDEFText, combinedMedText, combinedEnemyATKText, combinedEnemyDEFText, combinedEnemyMedText; [Space] [SerializeField] private Animator playerUnitAnim, enemyUnitAnim, overlayAnim; [Space] [SerializeField] private float enemyAttackWaitTime, enemyAttackWaitVariance, playerAttackWaitTime; [Space] [SerializeField] AudioSource unitAttackHitAudio, unitHealAudio, unitBlockAudio; private int playerAttackDamage = 1, enemyAttackDamage = 1, playerHealthMax = 10, playerMedicalMax = 1, enemyHealthMax = 10, playerDefense = 0, enemyDefense = 0; private float playerTimeWaited; private bool playerActionsDisabled, enemyAttackBlocked; private bool battleOver; private Coroutine enemyAttacked = null; public bool BattleOver { get => battleOver; set => battleOver = value; } private void Awake() { Instance = this; enemyUnitHealthText.text = enemyUnitHealthSlider.value + " / " + enemyHealthMax; unitHealthText.text = unitHealthSlider.value + " / " + playerHealthMax; actionTimerSlider.maxValue = playerAttackWaitTime; } private void Update() { if(playerActionsDisabled) { playerTimeWaited += Time.deltaTime; actionTimerSlider.value = playerTimeWaited; if(playerTimeWaited >= playerAttackWaitTime) { EnableOrDisableAllButtons(true); playerTimeWaited = 0; playerActionsDisabled = false; } } if(unitHealthSlider.value <= 0) { battleOver = true; if(overlayAnim.GetCurrentAnimatorStateInfo(0).IsName("Idle")) overlayAnim.Play("Defeat Fade"); if (enemyAttacked != null) StopCoroutine(enemyAttacked); } if(enemyAttacked == null && enemyUnitHealthSlider.value > 0) enemyAttacked = StartCoroutine(WaitForEnemyAttack()); if (battleOver) StartCoroutine(WaitToUnloadBattle()); } public void OnAttack() { enemyUnitHealthSlider.value -= determineDamageOnPlayerAttack(); enemyUnitHealthText.text = enemyUnitHealthSlider.value + " / " + enemyHealthMax; playerUnitAnim.Play("Unit_Attack_Anim"); enemyUnitAnim.Play("Enemy_Unit_Hit_Anim"); unitAttackHitAudio.Play(); if (enemyAttacked != null && enemyUnitHealthSlider.value <= 0) { StopCoroutine(enemyAttacked); overlayAnim.Play("Victory Fade"); battleOver = true; } EnableOrDisableAllButtons(false); playerActionsDisabled = true; } public void OnDefend() { enemyAttackBlocked = true; EnableOrDisableAllButtons(false); playerActionsDisabled = true; } public void OnHeal() { unitHealthSlider.value += playerMedicalMax; unitHealthText.text = unitHealthSlider.value + " / " + playerHealthMax; playerUnitAnim.Play("Unit_Heal"); unitHealAudio.Play(); EnableOrDisableAllButtons(false); playerActionsDisabled = true; } public void OnRetreat() { //leave the battle StopCoroutine(enemyAttacked); playerUnitAnim.Play("Unit_Retreat"); overlayAnim.Play("Retreat Fade"); battleOver = true; } private int determineDamageOnPlayerAttack() { int damage = playerAttackDamage - enemyDefense; if (damage <= 0) damage = 1; return damage; } private int determineDamageOnEnemyAttack() { int damage = enemyAttackDamage - playerDefense; if (damage <= 0) damage = 1; return damage; } private void EnableOrDisableAllButtons(bool newState) { attackButton.interactable = newState; defendButton.interactable = newState; healButton.interactable = newState; retreatButton.interactable = newState; } public IEnumerator WaitForEnemyAttack() { yield return new WaitForSecondsRealtime(enemyAttackWaitTime + Random.Range(-enemyAttackWaitVariance, enemyAttackWaitVariance)); if(!enemyAttackBlocked) { unitHealthSlider.value -= determineDamageOnEnemyAttack(); unitHealthText.text = unitHealthSlider.value + " / " + playerHealthMax; playerUnitAnim.Play("Unit_Hit_Anim"); enemyUnitAnim.Play("Enemy_Unit_Attack_Anim"); unitAttackHitAudio.Play(); } else { playerUnitAnim.Play("Unit_Block"); enemyUnitAnim.Play("Enemy_Unit_Attack_Anim"); unitBlockAudio.Play(); enemyAttackBlocked = false; } enemyAttacked = null; } /// <summary> /// Called to initialize battle sequence with aggregated stats /// </summary> /// <param name="playerRoster"></param> /// <param name="enemyRoster"></param> public void SetBattleStatsForCombat(Roster playerRoster, Roster enemyRoster, int unitHealth, int enemyHealth) { //Aggregate player stats playerAttackDamage = 0; playerDefense = 0; playerHealthMax = 0; foreach(var unit in playerRoster.units) { playerAttackDamage += unit.attack; playerDefense += unit.defense; playerHealthMax += unit.maxHealth; playerMedicalMax += unit.medical; } //show player stats on battle screen combinedATKText.text = playerAttackDamage.ToString(); combinedDEFText.text = playerDefense.ToString(); combinedMedText.text = playerMedicalMax.ToString(); //Aggregate enemy stats enemyAttackDamage = 0; enemyDefense = 0; enemyHealthMax = 0; foreach (var unit in enemyRoster.units) { enemyAttackDamage += unit.attack; enemyDefense += unit.defense; enemyHealthMax += unit.maxHealth; } //show enemy stats on battle screen combinedEnemyATKText.text = enemyAttackDamage.ToString(); combinedEnemyDEFText.text = enemyDefense.ToString(); combinedEnemyMedText.text = enemyHealthMax.ToString(); enemyUnitHealthSlider.maxValue = enemyHealthMax; enemyUnitHealthSlider.value = enemyHealth; enemyUnitHealthText.text = enemyUnitHealthSlider.value + " / " + enemyHealthMax; unitHealthSlider.maxValue = playerHealthMax; unitHealthSlider.value = unitHealth; unitHealthText.text = unitHealthSlider.value + " / " + playerHealthMax; } public static void LoadBattleScene(string scene = "Battle Scene") { Instance = null; SceneManager.LoadSceneAsync(scene, LoadSceneMode.Additive); } public static void UnloadBattleScene(string scene = "Battle Scene") //called instead from update to start the wait below VVVVVV { //Instance = null; //SceneManager.UnloadSceneAsync(scene); } public IEnumerator WaitToUnloadBattle() { yield return new WaitForSecondsRealtime(6); Instance = null; SceneManager.UnloadSceneAsync("Battle Scene"); } }