Files
MovementTests/managers/Wave/WaveManager.cs

100 lines
3.2 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.Introspection;
using Godot;
using Movementtests.tools;
namespace Movementtests.managers;
[GlobalClass, Meta(typeof(IAutoNode))]
public partial class WaveManager : Node
{
public override void _Notification(int what) => this.Notify(what);
public WaveContent WaveContent { get; set; }
public int CurrentWaveIndex { get; set; }
public int CurrentWaveCount => WaveContent.Waves.Length;
public Godot.Collections.Dictionary<EnemyDescription, int> CurrentWave =>
WaveContent.Waves[CurrentWaveIndex].EnemiesToSpawn;
public Dictionary<ulong, Enemy?> CurrentSpawnedEnemies { get; set; } = [];
public Set<Spawner> SpawnersInUse { get; set; } = [];
public List<Spawner> Spawners { get; set; } = [];
public void RegisterSpawner(Spawner spawner) => Spawners.Add(spawner);
public void InitializeFromResource(WaveContent waveContent) => WaveContent = waveContent;
public void StartWaves()
{
CurrentWaveIndex = 0;
StartNextWave();
}
public void StartNextWave()
{
if (CurrentWave.Count == 0)
{
GD.PrintErr("Wave has no enemies");
return;
}
if (Spawners.Count == 0)
{
GD.PrintErr("No spawners registered");
return;
}
SpawnEnemiesAsAvailable();
}
public void SpawnEnemiesAsAvailable()
{
var randomizedSpawners = Spawners.ToArray();
randomizedSpawners.Shuffle();
foreach (var (enemyDescription, numberRemaining) in CurrentWave)
{
if (numberRemaining <= 0) continue;
foreach (var spawner in randomizedSpawners)
{
if (!spawner.SupportedEnemyTypes.Contains(enemyDescription.Type)) continue;
if (SpawnersInUse.Contains(spawner)) continue;
var spawnedEnemy = spawner.SpawnEnemy(enemyDescription);
if (spawnedEnemy == null) continue;
CurrentSpawnedEnemies[spawnedEnemy.GetInstanceId()] = spawnedEnemy;
SpawnersInUse.Add(spawner);
spawnedEnemy.OnKilled += instanceId=> SpawnedEnemyDied(instanceId, spawner);
CurrentWave[enemyDescription]--;
break;
}
}
var remainingEnemiesToSpawn = CurrentWave.Values.Sum();
if (remainingEnemiesToSpawn <= 0) return; // Wave is fully spawned
GetTree().CreateTimer(1.0f).Timeout += SpawnEnemiesAsAvailable; // Call back the same function later to try and spawn the rest
}
public void SpawnedEnemyDied(ulong instanceId, Spawner spawner)
{
CurrentSpawnedEnemies.Remove(instanceId);
SpawnersInUse.Remove(spawner);
if (CurrentSpawnedEnemies.Count == 0) FinishWave();
}
public void FinishWave()
{
if (CurrentWaveIndex >= CurrentWaveCount) return; // All waves finished
CurrentWaveIndex++;
GetTree().CreateTimer(1.0f).Timeout += StartNextWave; // Start next wave in 1s
}
}