using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using Random = UnityEngine.Random; public class WaveManager : MonoBehaviour { #region Statication public static WaveManager instance; private void Awake() { if (instance != null && instance != this) { Destroy(gameObject); return; } instance = this; } #endregion [System.Serializable] public class Wave { public Enemy[] enemies; public bool bossWave; public Enemy bossEnemy; //optional public string bossName; public string bossDescription; //public DialogueScript bossDialogue; } [Header("Player Point")] public Player player; //only for continues lol [SerializeField] private Transform tlPoint; [SerializeField] private Transform brPoint; [Header("Enemy Point")] [SerializeField] private Transform enemyTLPoint; [SerializeField] private Transform enemyBRPoint; public Transform enemySpawnPoint; [Header("Waves")] [SerializeField] protected TextMeshProUGUI waveUI; public int wave = 1; public Wave[] waveList; [Header("Boss")] public Enemy bossInstance; public GameObject bossUI; [SerializeField] private TextMeshProUGUI bossNameUI; [SerializeField] private TextMeshProUGUI bossDescriptionUI; [SerializeField] private Transform bossHPBar; [SerializeField] private TextMeshProUGUI bossHPText; [Header("Enemies")] public Transform enemyFolder; public List enemiesInPlay = new(); [SerializeField] private float enemyCheckRadius; [SerializeField] private LayerMask enemyLayer; [Header("Audio")] public AudioSource audioSource; [SerializeField] private AudioSource musicSource; [SerializeField] private AudioClip musicIntro; public float musicVolume; private void Start() { SpawnWave(); musicSource.volume = musicVolume; musicSource.PlayOneShot(musicIntro, musicVolume); StartCoroutine(WaitForLoop()); } public Vector3 GetRandomPlayerPoint() { return new Vector3(Random.Range(tlPoint.position.x, brPoint.position.x), Random.Range(brPoint.position.y, tlPoint.position.y), 0); } public Vector3 GetRandomEnemyPoint() { Vector3 randomPoint; do { randomPoint = new Vector3(Random.Range(enemyTLPoint.position.x, enemyBRPoint.position.x), Random.Range(enemyBRPoint.position.y, enemyTLPoint.position.y), 0); } while (CheckEnemyOverlap(randomPoint)); return randomPoint; } private bool CheckEnemyOverlap(Vector3 areaToCheck) { if (Physics2D.OverlapCircle(areaToCheck, enemyCheckRadius, enemyLayer)) { return true; } return false; } protected virtual void SpawnWave() { waveUI.text = $"Wave: {wave}"; foreach (Enemy enemy in waveList[wave-1].enemies) { SpawnEnemy(enemy); } if (waveList[wave-1].bossWave) { SpawnBoss(waveList[wave-1].bossEnemy); } wave++; } protected void SpawnBoss(Enemy boss) { Enemy newBoss = SpawnEnemy(boss); bossInstance = newBoss; bossUI.SetActive(true); bossNameUI.text = waveList[wave - 1].bossName; bossDescriptionUI.text = waveList[wave - 1].bossDescription; UpdateBossUI(); player.isStalled = true; //wait for boss to enter then start dialogue player.invulnerable = true; } public Enemy SpawnEnemy(Enemy enemy) { Enemy newEnemy = Instantiate(enemy, enemyFolder); Vector3 movepos = GetRandomEnemyPoint(); newEnemy.currentMovementRoutine = newEnemy.StartCoroutine(newEnemy.MoveToPosition(enemySpawnPoint.position,movepos, newEnemy.moveSpeed)); newEnemy.originalPosition = movepos; enemiesInPlay.Add(newEnemy); newEnemy.isStalled = true; newEnemy.invulnerable = true; return newEnemy; } public void UpdateBossUI() { bossHPText.text = $"{bossInstance.health}/{bossInstance.maxHealth}"; bossHPBar.localScale = new Vector3((float)bossInstance.health / bossInstance.maxHealth, 1f, 1f); } public virtual void UpdateKills() { if (enemiesInPlay.Count == 0) { if (wave > waveList.Length) { GameManager.instance.WinGame(); } else { SpawnWave(); } } } private IEnumerator WaitForLoop() { bool stopped = false; while (!stopped) { if (musicSource.isPlaying) { yield return null; } else { stopped = true; musicSource.Play(); } } } }