using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; 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 Texture bossName; //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")] public int wave = 1; public Wave[] waveList; [Header("Boss")] public Enemy bossInstance; public GameObject bossUI; [SerializeField] private RawImage bossNameUI; [SerializeField] private Transform bossHPBar; [Header("Final Boss")] [SerializeField] private Prismriver lunasa; [SerializeField] private Prismriver merlin; [SerializeField] private Prismriver lyrica; public Prismriver lunasaInstance; public Prismriver merlinInstance; public Prismriver lyricaInstance; public int prismMaxHP; public int prismHP; public DialogueScript prismriverDialogue; [Header("Enemies")] public Transform enemyFolder; public List enemiesInPlay = new(); [SerializeField] private float enemyCheckRadius; [SerializeField] private LayerMask enemyLayer; [Header("Audio")] public AudioClip bossDialogueLoop; public AudioClip bossMusic; public float bossVolume; public AudioClip finalDialogueLoop; public AudioClip finalMusic; public float finalVolume; public AudioSource audioSource; public AudioSource musicSource; [SerializeField] private AudioClip musicIntro; public AudioClip musicLoop; public float musicVolume; private void Start() { SpawnWave(); //SpawnFinalBoss(); 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; int currentAttempts = 0; do { randomPoint = new Vector3(Random.Range(enemyTLPoint.position.x, enemyBRPoint.position.x), Random.Range(enemyBRPoint.position.y, enemyTLPoint.position.y), 0); currentAttempts++; if (currentAttempts > 50) { return 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() { foreach (Enemy enemy in waveList[wave-1].enemies) { SpawnEnemy(enemy); } if (wave == waveList.Length) { SpawnFinalBoss(); Debug.Log("here"); } else if (waveList[wave-1].bossWave) { SpawnBoss(waveList[wave-1].bossEnemy); } wave++; } protected void SpawnBoss(Enemy boss) { Enemy newBoss = SpawnEnemy(boss); bossInstance = newBoss; bossNameUI.texture = waveList[wave - 1].bossName; bossNameUI.SetNativeSize(); UpdateBossUI(); player.isStalled = true; //wait for boss to enter then start dialogue player.invulnerable = true; } private void SpawnFinalBoss() { lunasaInstance = SpawnPrism(lunasa); merlinInstance = SpawnPrism(merlin); lyricaInstance = SpawnPrism(lyrica); //DialogueManager.instance.StartDialogue(prismriverDialogue); lunasaInstance.isStalled = true; merlinInstance.isStalled = true; lyricaInstance.isStalled = true; player.isStalled = true; //wait for boss to enter then start dialogue player.invulnerable = true; bossNameUI.texture = waveList[wave - 1].bossName; bossNameUI.SetNativeSize(); } 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 Prismriver SpawnPrism(Prismriver prism) { Prismriver newEnemy = Instantiate(prism, 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() { if (lyricaInstance) { bossHPBar.localScale = new Vector3(1 - (float)prismHP / prismMaxHP, 1f, 1f); return; } bossHPBar.localScale = new Vector3(1 - (float)bossInstance.health / bossInstance.maxHealth, 1f, 1f); } public virtual void UpdateKills() { if (enemiesInPlay.Count == 0) { if (waveList[wave - 1].bossEnemy) { } SpawnWave(); } if (lunasaInstance && prismHP <= 0) { GameManager.instance.WinGame(); } } private IEnumerator WaitForLoop() { bool stopped = false; while (!stopped) { if (musicSource.isPlaying) { yield return null; } else { stopped = true; musicSource.Play(); } } } }