305 lines
7.4 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|