using Godot; using Newlon.Components.Zombies; using System.Collections.Generic; namespace Newlon.Components.Level; [GlobalClass] public partial class LevelRunner : Node { private AdventureLevelResource resource; private int waveIndex = -1; private bool hugeWaveApproaching = false; public float waveHealth = 0; public float waveHealthMax = 0; public List zombies = []; [Export] private RowSpawner rowSpawner; [Export] private Timer waveTimer; [Export] private float approachNotificationTime; [Signal] public delegate void ResourceChangedEventHandler(AdventureLevelResource resource); [Signal] public delegate void WaveChangedEventHandler(int to); [Signal] public delegate void HugeWaveApproachingCallbackEventHandler(); [Signal] public delegate void HugeWaveInitiatedEventHandler(int waveNumber); [Signal] public delegate void FinalWaveInitiatedEventHandler(); public override void _Ready() { waveTimer.Timeout += SummonWave; } public override void _Process(double delta) { if (RuntimeLevelData.Instance.GetLevelState() != RuntimeLevelData.LevelStates.Game) return; if (waveIndex == resource.waves.Count - 1) return; if (waveTimer.TimeLeft < approachNotificationTime && resource.waves[waveIndex + 1].isHugeWave && hugeWaveApproaching == false) { hugeWaveApproaching = true; EmitSignal(SignalName.HugeWaveApproachingCallback); } } public void SetLevelResource(AdventureLevelResource data) { resource = data; waveTimer.Stop(); waveTimer.WaitTime = resource.initialWaveDelay; waveTimer.Start(); EmitSignal(SignalName.ResourceChanged, resource); } private void SummonWave() { waveIndex += 1; hugeWaveApproaching = false; EmitSignal(SignalName.WaveChanged, waveIndex); if (resource.waves[waveIndex].isHugeWave) EmitSignal(SignalName.HugeWaveInitiated, waveIndex); rowSpawner.Add(resource.waves[waveIndex].zombiesOrdered); ClearZombies(); if (waveIndex == resource.waves.Count - 1) { EmitSignal(SignalName.FinalWaveInitiated); return; } waveTimer.WaitTime = resource.waves[waveIndex].customWaveDelay > 0 ? resource.waves[waveIndex].customWaveDelay : resource.standardWaveDelay; waveTimer.Start(); } private void OnHPChanged(float delta) { if (waveIndex == resource.waves.Count - 1) return; waveHealth += delta; if (waveHealth / waveHealthMax <= resource.wavePercentage) { if (resource.waves[waveIndex + 1].isHugeWave && waveTimer.TimeLeft > 6) { waveTimer.WaitTime = 6; waveTimer.Start(); ClearZombies(); } else { waveTimer.Stop(); SummonWave(); } } } public void ClearZombies() { foreach (var zom in zombies) { if (zom != null) { zom.HPChangedMixed -= OnHPChanged; } } waveHealthMax = 0; waveHealth = waveHealthMax; zombies.Clear(); } public void AddZombie(RuntimeZombieData zombie) { zombies.Add(zombie); waveHealthMax += zombie.GetMaxHPMixed(); waveHealth = waveHealthMax; zombie.HPChangedMixed += OnHPChanged; } }