Files
dota_factory/src/lib/sim/WaveSystem.h

100 lines
3.5 KiB
C++

#pragma once
#include <random>
#include <string>
#include <vector>
#include <QVector2D>
#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 getThreatLevel() const;
// Current rate at which getThreatLevel() is increasing, in threat/second
// (REQ-WAV-THREAT-RATE). 0 during a quiet window (REQ-WAV-QUIET) or when
// the rate formula evaluates to a negative value.
double getThreatAccumulationRate() const;
// Current enemy-station generation level (0 for initial set,
// incremented by 1 after each push — REQ-PSH-STATION-STATS).
int getGeneration() const;
// Boss wave counter (REQ-WAV-BOSS-COUNTER): current cycle number, starts at 1.
int getBossWaveCounter() const;
// Ticks remaining until the next boss wave fires (REQ-WAV-BOSS-COUNTDOWN).
Tick getBossCountdownTicks() const;
// Ticks remaining on the current normal-wave gap timer (REQ-WAV-GAP).
// Frozen during quiet windows.
Tick getNormalGapRemainingTicks() const;
private:
struct SpawnEntry
{
std::string schematicId;
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<SpawnEntry> 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<SpawnEntry> m_normalPendingSpawns;
std::vector<SpawnEntry> m_bossPendingSpawns;
};