ReisenYoumuOuting/Assets/Scripts/WaveManager.cs
2026-07-14 20:23:37 -07:00

305 lines
7.4 KiB
C#

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;
}
public GameObject pauseMenu;
[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 Image 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<Enemy> enemiesInPlay = new();
[SerializeField] private float enemyCheckRadius;
[SerializeField] private LayerMask enemyLayer;
public int healInterval;
[Header("Audio")]
public AudioClip bossDialogueLoop;
public AudioClip bossMusic;
public float bossVolume;
public AudioClip finalDialogueLoop;
public AudioClip finalMusic;
public AudioSource audioSource;
public AudioSource musicSource;
[SerializeField] private AudioClip musicIntro;
public AudioClip musicLoop;
[Header("UI")]
public GameObject loseUI;
public StatsUI statsUI;
[Header("Endless")]
[SerializeField] private Enemy[] enemyList;
[SerializeField] private Enemy[] bossList;
[SerializeField] private int bossWaveInterval;
[Header("Enemy Count Calculations")]
[SerializeField] private float baseSpawnAmount;
[SerializeField] private float exponentIncrease;
public float exponentHealthIncrease;
private void Start()
{
if (GameManager.instance.isEndless)
{
SpawnEndlessWave();
}
else
{
SpawnWave();
}
//SpawnFinalBoss();
musicSource.PlayOneShot(musicIntro);
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;
}
public void CallPauseMenu()
{
GameManager.instance.SetPauseMenu();
}
public void CallExitGame()
{
GameManager.instance.ExitGame();
}
public void CallRestartGame()
{
GameManager.instance.RestartGame();
}
public void CallContinue()
{
GameManager.instance.ContinueGame();
}
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++;
}
private void SpawnEndlessWave()
{
//waveUI.text = $"Wave: {wave}";
int amountToSpawn = Mathf.FloorToInt(baseSpawnAmount * Mathf.Pow(wave, exponentIncrease));
for (int i = 0; i < amountToSpawn; i++)
{
SpawnEnemy(enemyList[Random.Range(0, enemyList.Length)]);
}
if (wave % bossWaveInterval == 0)
{
SpawnBoss(bossList[Random.Range(0, bossList.Length)]);
}
wave++;
}
protected void SpawnBoss(Enemy boss)
{
Enemy newBoss = SpawnEnemy(boss);
bossInstance = newBoss;
bossNameUI.texture = waveList[wave - 1].bossName;
bossNameUI.SetNativeSize();
UpdateBossUI();
if (!GameManager.instance.isEndless)
{
player.isStalled = true; //wait for boss to enter then start dialogue
player.invulnerable = true;
}
else
{
newBoss.maxHealth = Mathf.FloorToInt(newBoss.maxHealth * Mathf.Pow(wave, exponentHealthIncrease));
newBoss.health = newBoss.maxHealth;
}
}
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();
if (GameManager.instance.isEndless)
{
newEnemy.maxHealth = Mathf.FloorToInt(newEnemy.maxHealth * Mathf.Pow(wave, exponentHealthIncrease));
newEnemy.health = newEnemy.maxHealth;
}
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.fillAmount = 1 - (float)prismHP / prismMaxHP;
return;
}
bossHPBar.fillAmount = 1 - (float)bossInstance.health / bossInstance.maxHealth;
}
public virtual void UpdateKills()
{
if (enemiesInPlay.Count == 0)
{
Debug.Log("interval: " + ((wave+1) % healInterval));
if ((wave + 1) % healInterval == 0)
{
Debug.Log("here");
player.Heal(1);
}
if (GameManager.instance.isEndless)
{
SpawnEndlessWave();
return;
}
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();
}
}
}
}