#pragma once #include #include #include #include #include "GameConfig.h" #include "ShipLayout.h" #include "Tick.h" class ShipSystem; // Manages wave scheduling (tick-order step 1) and threat-level accumulation // (tick-order step 2). REQ-WAV-*. class WaveSystem { public: WaveSystem(const GameConfig& config, std::mt19937& rng); // Tick step 1: advance the boss countdown and normal wave gap; trigger // normal or boss waves when their timers expire; spawn any ships in the // pending queues whose scheduled tick has arrived. void tickWaveScheduler(Tick currentTick, ShipSystem& ships, int worldHeightTiles); // Tick step 2: accumulate threat from the rate formula evaluated at the // current boss wave counter (REQ-WAV-THREAT-RATE). void tickThreatAccumulation(); // Called by Simulation (tick step 9) when the current enemy-station set // is fully destroyed: advances the boss countdown and increments generation // (REQ-WAV-BOSS-ADVANCE, REQ-PSH-STATION-STATS). void onEnemyStationsDestroyed(); double threatLevel() const; // Current enemy-station generation level (0 for initial set, // incremented by 1 after each push — REQ-PSH-STATION-STATS). int generation() const; private: struct SpawnEntry { std::string schematicId; int level; Tick spawnAt; QVector2D position; ShipLayoutConfig layout; }; // Select ships from the given threat budget until no eligible ship fits. // Reduces budget in-place to the remaining (carry-over) amount. std::vector selectWaveShips(double& budget, Tick currentTick, int worldHeightTiles); void triggerNormalWave(Tick currentTick, int worldHeightTiles); void triggerBossWave(Tick currentTick, int worldHeightTiles); // Returns true while normal-wave spawning should be suppressed (REQ-WAV-QUIET). bool isInQuietWindow() const; // Draw a random gap duration in ticks from [gapMin, gapMax]. Tick drawGapTicks(); const GameConfig& m_config; std::mt19937& m_rng; double m_threatLevel = 0.0; int m_generation = 0; // Boss wave cycle (REQ-WAV-BOSS-COUNTER, REQ-WAV-BOSS-COUNTDOWN). int m_bossWaveCounter = 1; Tick m_bossCountdownTicks; // counts down each tick; reset after boss fires Tick m_postBossQuietRemainingTicks = 0; // Normal wave gap — frozen during quiet windows (REQ-WAV-GAP). bool m_normalWaveActive = false; Tick m_normalGapRemainingTicks; // replaces old m_nextEventTick // Spawn queues — kept separate so normal-wave completion is trackable. std::vector m_normalPendingSpawns; std::vector m_bossPendingSpawns; };