using System.Collections.Generic; using UnityEngine; public class WaveObserver : Singleton { private List _subjects = new List(); private List _aliveEnemyCount = new List(); private List _copyConstantSpawn; private List _copyGroupSpawn; private List _groupSpawnTimers; private WaveConfig _levelConfig; private const int MAXTOUGHNESS = 10; private int _spawnerTiming = 0; private List _intervalTiming = new List(); private bool _once = true; private int _currentGroupIndex = 0; public void SetLevelConfig(WaveConfig config) { _levelConfig = config; _copyConstantSpawn = new List(); _copyGroupSpawn = new List(); _groupSpawnTimers = new List(); foreach (EnemyType enemy in _levelConfig.ConstantSpawn) { _copyConstantSpawn.Add(enemy.Count); } for (int index = 0; index < _levelConfig.NestedGroupSpawn.Count; index++) { _copyGroupSpawn.Add(_levelConfig.NestedGroupSpawn[index]); _groupSpawnTimers.Add(_levelConfig.NestedGroupSpawn[index].triggerTime); } } /** * Called by spawner at the start of the game * Assigns enemy to spawn and registers them */ public void Attach(SpawnerTile spawnerSubject) { spawnerSubject.Prefab = _levelConfig.GetRandomSpawn().GetEnemyObject(); _subjects.Add(spawnerSubject); _aliveEnemyCount.Add(0); _intervalTiming.Add(++_spawnerTiming); // Ensures that only one spawner keeps track of the grouped spawn timer. if (_once) { _once = false; spawnerSubject.SetGroupSpawnTimers(_groupSpawnTimers); } } /** * Called by spawner when making enemies * Assigns a new interval */ public void NotifySpawned(SpawnerTile spawnerSubject) { GameObject paramPrefab = spawnerSubject.Prefab; spawnerSubject.ChangeSpawnSpeed(_levelConfig.Interval * _spawnerTiming); if (paramPrefab.Equals(_levelConfig.ConstantSpawn[0].GetEnemyObject())) { int currentCount = 0; for (int i = 0; i < _copyConstantSpawn.Count; i++) { if (_levelConfig.ConstantSpawn[i].GetEnemyObject() == paramPrefab) { currentCount = --_copyConstantSpawn[i]; break; } } if (currentCount <= 0) { foreach (SpawnerTile spawner in _subjects) { if (spawner.Prefab.Equals(paramPrefab)) { spawner.StopSpawn(); } } } } } /** * Called by enemy when they spawn * Keeps track of their row */ public int NotifyEnemy(float yPosition, float toughness) { int index = FindEnemyIndex(yPosition); _aliveEnemyCount[index] += toughness; if (_aliveEnemyCount[index] >= MAXTOUGHNESS) { _subjects[index].StopSpawn(); } return index; } /** * Called when an enemy dies * Reactivates spawning on that row if disabled before */ public void NotifyDies(int position, float toughness) { _aliveEnemyCount[position] -= toughness; if (_aliveEnemyCount[position] < MAXTOUGHNESS) { _subjects[position].StartSpawn(); } } /** * Called when an enemy is spawned automatically at the start of the game * Adjusts the intervall between spawns */ public void NotifyOnStart(SpawnerTile spawnerSubject) { float interval = _levelConfig.GetUpdatedInterval(); foreach (var subject in _subjects) { subject.ChangeSpawnSpeed(interval); } NotifySpawned(spawnerSubject); } // To find which spawner an ennemy came from. private int FindEnemyIndex(float yPosition) { for (int i = 0; i < _subjects.Count; i++) { if (_subjects[i].Position.y == yPosition) { return i; } } return -1; } /** * Spawners wait 1 second to have time to register them all * Then gets assigned a random spawn interval */ public void NotifyEndCooldown(SpawnerTile spawnerTile) { System.Random rand = new System.Random(); int index; do { index = rand.Next(_subjects.Count); } while (_intervalTiming.Count <= index); spawnerTile.ChangeSpawnSpeed(_levelConfig.Interval * _intervalTiming[index]); _intervalTiming.Remove(index); } /** * Called when it is time to spawn a group * Assigns a random element of the group to a random spawner */ public void NotifyGroupSpawn() { System.Random rand = new System.Random(); foreach (EnemyType groupEnemy in _copyGroupSpawn[_currentGroupIndex].groupSpawn) { for (int i = 0; i < groupEnemy.Count; i++) { _subjects[rand.Next(_subjects.Count)].TriggerSpawn(groupEnemy.GetEnemyObject()); } } _currentGroupIndex++; } }