implement cost formula for asteroid expansion
This commit is contained in:
@@ -19,9 +19,7 @@ enemy_buffer_width_tiles = 20
|
||||
|
||||
[expansion]
|
||||
columns_per_expansion_tiles = 10
|
||||
# Flat until the escalating cost formula lands (progression_design.md
|
||||
# action item 4).
|
||||
cost_building_blocks = 400
|
||||
cost_building_blocks_formula = "300 + 50*x + 10*x*x"
|
||||
|
||||
[push]
|
||||
push_expand_columns_tiles = 10
|
||||
|
||||
@@ -19,7 +19,7 @@ enemy_buffer_width_tiles = 15
|
||||
|
||||
[expansion]
|
||||
columns_per_expansion_tiles = 10
|
||||
cost_building_blocks = 200
|
||||
cost_building_blocks_formula = "400 * 2^x"
|
||||
|
||||
[push]
|
||||
push_expand_columns_tiles = 20
|
||||
|
||||
@@ -367,7 +367,7 @@ Modules in `modules.toml` define a `surface_mask` — a list of strings that des
|
||||
## Asteroid Expansion
|
||||
|
||||
- REQ-EXP-UNLOCK: The player can unlock additional asteroid tile columns to the left of the existing asteroid by spending building blocks from the global stock.
|
||||
- REQ-EXP-COST: Each expansion adds `world.toml [expansion].columns_per_expansion` columns and costs `[expansion].cost_building_blocks` building blocks.
|
||||
- REQ-EXP-COST: Each expansion adds `world.toml [expansion].columns_per_expansion` columns. The building block cost of an expansion is defined by the formula `world.toml [expansion].cost_building_blocks_formula`, where `x` is the number of expansions already purchased (0 for the first expansion, incrementing by 1 for each subsequent expansion). The formula is evaluated at purchase time and its result is floored to an integer number of building blocks.
|
||||
|
||||
## UI
|
||||
|
||||
@@ -392,9 +392,10 @@ The screen is divided into two columns: a main column (75% width) containing the
|
||||
(75% width) (25% width)
|
||||
```
|
||||
|
||||
- REQ-UI-HEADER: The header bar spans the width of the game world column (75% of the screen width) and always shows the elapsed survival time, the current global building blocks stock, and the artifact count (REQ-WIN-ARTIFACT-COUNT) displayed as `Artifacts: x/y` (where `x` is the current artifact count and `y` is `world.toml [world].artifact_win_count`) on the left, the boss wave counter and boss countdown (REQ-UI-BOSS-STATUS) to the left of the speed buttons, and game speed controls on the right.
|
||||
- REQ-UI-HEADER: The header bar spans the width of the game world column (75% of the screen width) and always shows the elapsed survival time, the current global building blocks stock, and the artifact count (REQ-WIN-ARTIFACT-COUNT) displayed as `Artifacts: x/y` (where `x` is the current artifact count and `y` is `world.toml [world].artifact_win_count`) on the left, the boss wave counter and boss countdown (REQ-UI-BOSS-STATUS) and an asteroid expansion button (REQ-UI-EXPAND-BUTTON) to the left of the speed buttons, and game speed controls on the right.
|
||||
- REQ-UI-BOSS-STATUS: The header bar displays, to the left of the speed buttons, the current boss wave counter (REQ-WAV-BOSS-COUNTER) and the time remaining on the boss countdown (REQ-WAV-BOSS-COUNTDOWN). The boss wave counter is shown as `Boss Wave #<x>` and the countdown as `Next boss: <M:SS>`, where `<M:SS>` is the remaining seconds formatted as whole minutes and two-digit seconds. Both values update continuously as the simulation runs.
|
||||
- REQ-UI-SPEED: The game speed controls in the header bar are buttons for 0×, 0.5×, 1×, 2×, and 4× speed. The currently active speed is shown as selected. All game simulation (production, movement, threat accumulation, wave timing) scales with the selected speed. 0× pauses the game.
|
||||
- REQ-UI-EXPAND-BUTTON: The header bar shows an asteroid expansion button captioned `Expand: <x> Blocks`, where `<x>` is the current expansion cost computed from `world.toml [expansion].cost_building_blocks_formula` at the current number of purchased expansions (REQ-EXP-COST). Clicking the button unlocks the next asteroid expansion (REQ-EXP-UNLOCK, REQ-GW-ASTEROID-EXPAND), spending that many building blocks from the global stock. The button is disabled when the player cannot currently afford the cost (consistent with REQ-UI-BUILD-DISABLED). The caption updates as the cost changes with each purchased expansion.
|
||||
- REQ-UI-WORLD-SIZE: The game world view occupies the full height below the header bar in the main column (75% of the screen width).
|
||||
- REQ-UI-PANEL-COLUMN: The side panel column occupies 25% of the screen width and the full screen height. It is divided into three equal-height panels stacked top to bottom: selected building panel (top), build button grid (middle), and blueprint panel (bottom).
|
||||
|
||||
|
||||
@@ -278,8 +278,8 @@ WorldConfig ConfigLoader::loadWorld(const std::string& path)
|
||||
cfg.regions.contestZoneWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["contest_zone_width_tiles"], file, "regions.contest_zone_width_tiles"));
|
||||
cfg.regions.enemyBufferWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["enemy_buffer_width_tiles"], file, "regions.enemy_buffer_width_tiles"));
|
||||
|
||||
cfg.expansion.columnsPerExpansion_tiles = static_cast<int>(requireInt(tbl["expansion"]["columns_per_expansion_tiles"], file, "expansion.columns_per_expansion_tiles"));
|
||||
cfg.expansion.costBuildingBlocks = static_cast<int>(requireInt(tbl["expansion"]["cost_building_blocks"], file, "expansion.cost_building_blocks"));
|
||||
cfg.expansion.columnsPerExpansion_tiles = static_cast<int>(requireInt(tbl["expansion"]["columns_per_expansion_tiles"], file, "expansion.columns_per_expansion_tiles"));
|
||||
cfg.expansion.costBuildingBlocksFormula = requireFormula(tbl["expansion"]["cost_building_blocks_formula"], file, "expansion.cost_building_blocks_formula");
|
||||
|
||||
cfg.push.pushExpandColumns_tiles = static_cast<int>(requireInt(tbl["push"]["push_expand_columns_tiles"], file, "push.push_expand_columns_tiles"));
|
||||
cfg.push.bossAdvanceSeconds = requireDouble(tbl["push"]["boss_advance_seconds"], file, "push.boss_advance_seconds");
|
||||
|
||||
@@ -14,8 +14,8 @@ struct WorldRegions
|
||||
// Asteroid expansion (REQ-EXP-UNLOCK, REQ-EXP-COST).
|
||||
struct WorldExpansion
|
||||
{
|
||||
int columnsPerExpansion_tiles;
|
||||
int costBuildingBlocks;
|
||||
int columnsPerExpansion_tiles;
|
||||
Formula costBuildingBlocksFormula; // cost in building blocks; x = expansions already purchased
|
||||
};
|
||||
|
||||
// Push effects (REQ-PSH-*, REQ-WAV-BOSS-ADVANCE).
|
||||
|
||||
@@ -3,6 +3,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TracePrintRequestedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TickAdvancedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBlocksChangedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ExpansionCostChangedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntitySelectedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/GameSpeedChangedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BossWaveUpdatedEvent.h
|
||||
|
||||
17
src/lib/eventsystem/event/ExpansionCostChangedEvent.h
Normal file
17
src/lib/eventsystem/event/ExpansionCostChangedEvent.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef EXPANSION_COST_CHANGED_EVENT_H
|
||||
#define EXPANSION_COST_CHANGED_EVENT_H
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
// Fired when the current asteroid-expansion cost changes (REQ-EXP-COST): once at
|
||||
// startup and again after each expansion is purchased. Carries the cost in
|
||||
// building blocks so the header Expand button can update its caption/enabled
|
||||
// state (REQ-UI-EXPAND-BUTTON).
|
||||
class ExpansionCostChangedEvent : public Event
|
||||
{
|
||||
public:
|
||||
explicit ExpansionCostChangedEvent(int cost) : cost(cost) {}
|
||||
const int cost;
|
||||
};
|
||||
|
||||
#endif // EXPANSION_COST_CHANGED_EVENT_H
|
||||
@@ -24,6 +24,7 @@ BuildingSystem::BuildingSystem(const GameConfig& config,
|
||||
, m_spawnShip(std::move(spawnShip))
|
||||
, m_isItemUnlocked(std::move(isItemUnlocked))
|
||||
, m_rng(rng)
|
||||
, m_asteroidWidth_tiles(config.world.regions.asteroidWidth_tiles)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -281,7 +282,7 @@ bool BuildingSystem::bodyCellsWithinWorldBounds(const std::vector<QPoint>& bodyC
|
||||
QPoint anchor) const
|
||||
{
|
||||
const int heightTiles = m_config.world.heightTiles;
|
||||
const int leftEdgeX = -m_config.world.regions.asteroidWidth_tiles;
|
||||
const int leftEdgeX = -m_asteroidWidth_tiles;
|
||||
for (const QPoint& cell : bodyCells)
|
||||
{
|
||||
const QPoint worldCell = anchor + cell;
|
||||
|
||||
@@ -59,6 +59,11 @@ public:
|
||||
bool isPlacementValid(BuildingType type, QPoint anchor,
|
||||
Rotation rotation) const;
|
||||
|
||||
// Sets the current buildable asteroid width in tiles. Grows the left
|
||||
// placement bound as the player unlocks asteroid expansions (REQ-EXP-UNLOCK).
|
||||
// Defaults to world.regions.asteroid_width_tiles at construction.
|
||||
void setAsteroidWidth_tiles(int widthTiles) { m_asteroidWidth_tiles = widthTiles; }
|
||||
|
||||
// Remove a building or construction site by id. Returns the refund in
|
||||
// building blocks (floor(cost * refundPercentage / 100)). Returns 0 for
|
||||
// unknown ids.
|
||||
@@ -179,6 +184,7 @@ private:
|
||||
const std::optional<ShipLayoutConfig>&)> m_spawnShip;
|
||||
std::function<bool(const std::string&)> m_isItemUnlocked;
|
||||
std::mt19937& m_rng;
|
||||
int m_asteroidWidth_tiles;
|
||||
|
||||
std::vector<Building> m_buildings;
|
||||
std::deque<ConstructionSite> m_constructionQueue;
|
||||
|
||||
@@ -35,6 +35,7 @@ enum class CommandKind
|
||||
SetSplitterFilters,
|
||||
ClearBeltTiles,
|
||||
ApplySchematicChoice,
|
||||
ExpandAsteroid,
|
||||
Reset
|
||||
};
|
||||
|
||||
@@ -129,6 +130,14 @@ struct ApplySchematicChoiceCommand : Command
|
||||
int choiceIndex = 0;
|
||||
};
|
||||
|
||||
// Unlocks the next asteroid expansion (REQ-EXP-UNLOCK). Carries no payload: the
|
||||
// simulation derives the cost and column count from its own expansion counter
|
||||
// and config, so a recorded command replays identically.
|
||||
struct ExpandAsteroidCommand : Command
|
||||
{
|
||||
ExpandAsteroidCommand() : Command(CommandKind::ExpandAsteroid) {}
|
||||
};
|
||||
|
||||
// Restart boundary: reinitializes the simulation with a fresh seed and, if
|
||||
// config is set, a reloaded config (GameConfig is move-only, so it is carried by
|
||||
// shared_ptr and moved into the sim on apply). A null config keeps the current
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "AiSystem.h"
|
||||
#include "Command.h"
|
||||
@@ -132,6 +133,7 @@ void Simulation::reset(unsigned int seed)
|
||||
m_nextDepartureTick = secondsToTicks(m_config.world.departureIntervalSeconds);
|
||||
m_nextBuildingId = 1;
|
||||
m_buildingBlocksStock = m_config.world.startingBuildingBlocks;
|
||||
m_expansionsPurchased = 0;
|
||||
m_gameOver = false;
|
||||
m_isWon = false;
|
||||
m_artifactCount = 0;
|
||||
@@ -275,6 +277,9 @@ void Simulation::apply(const Command& command)
|
||||
case CommandKind::ApplySchematicChoice:
|
||||
applySchematicChoice(static_cast<const ApplySchematicChoiceCommand&>(command).choiceIndex);
|
||||
break;
|
||||
case CommandKind::ExpandAsteroid:
|
||||
tryExpandAsteroid();
|
||||
break;
|
||||
case CommandKind::Reset:
|
||||
{
|
||||
const ResetCommand& c = static_cast<const ResetCommand&>(command);
|
||||
@@ -993,6 +998,7 @@ unsigned long long Simulation::computeStateChecksum() const
|
||||
hasher.append(m_gameOver);
|
||||
hasher.append(m_isWon);
|
||||
hasher.append(m_artifactCount);
|
||||
hasher.append(m_expansionsPurchased);
|
||||
|
||||
// WaveSystem scalar state, reached through existing accessors.
|
||||
hasher.append(threatLevel());
|
||||
@@ -1100,6 +1106,31 @@ int Simulation::buildingBlocksStock() const
|
||||
return m_buildingBlocksStock;
|
||||
}
|
||||
|
||||
int Simulation::currentAsteroidWidth_tiles() const
|
||||
{
|
||||
return m_config.world.regions.asteroidWidth_tiles
|
||||
+ m_expansionsPurchased * m_config.world.expansion.columnsPerExpansion_tiles;
|
||||
}
|
||||
|
||||
int Simulation::currentExpansionCost() const
|
||||
{
|
||||
const double cost = m_config.world.expansion.costBuildingBlocksFormula.evaluate(
|
||||
static_cast<double>(m_expansionsPurchased));
|
||||
return static_cast<int>(std::floor(cost));
|
||||
}
|
||||
|
||||
void Simulation::tryExpandAsteroid()
|
||||
{
|
||||
const int cost = currentExpansionCost();
|
||||
if (m_buildingBlocksStock < cost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_buildingBlocksStock -= cost;
|
||||
++m_expansionsPurchased;
|
||||
m_buildingSystem->setAsteroidWidth_tiles(currentAsteroidWidth_tiles());
|
||||
}
|
||||
|
||||
bool Simulation::isGameOver() const
|
||||
{
|
||||
return m_gameOver;
|
||||
|
||||
@@ -72,6 +72,12 @@ public:
|
||||
// The seed this run was (re)initialized with; written to the replay header.
|
||||
unsigned int getSeed() const;
|
||||
int buildingBlocksStock() const;
|
||||
// Current asteroid width in tiles = base width + purchased expansions
|
||||
// (REQ-EXP-UNLOCK, REQ-GW-ASTEROID-EXPAND).
|
||||
int currentAsteroidWidth_tiles() const;
|
||||
// Building block cost of the next expansion, floored to an integer
|
||||
// (REQ-EXP-COST); x = number of expansions already purchased.
|
||||
int currentExpansionCost() const;
|
||||
bool isGameOver() const;
|
||||
bool isWon() const;
|
||||
int artifactCount() const;
|
||||
@@ -136,6 +142,11 @@ private:
|
||||
// Clears the pending choices after application.
|
||||
void applySchematicChoice(int choiceIndex);
|
||||
|
||||
// Unlocks one asteroid expansion if affordable (REQ-EXP-UNLOCK): checks the
|
||||
// current cost against the stock, deducts it, increments the expansion
|
||||
// counter, and widens the buildable asteroid. No-op if blocks are short.
|
||||
void tryExpandAsteroid();
|
||||
|
||||
// Mutable subsystem accessors; same chokepoint rule as the mutators above.
|
||||
BuildingSystem& buildingsMutable();
|
||||
BeltSystem& beltsMutable();
|
||||
@@ -165,6 +176,7 @@ private:
|
||||
Tick m_nextDepartureTick;
|
||||
BuildingId m_nextBuildingId;
|
||||
int m_buildingBlocksStock;
|
||||
int m_expansionsPurchased = 0; // REQ-EXP-COST formula variable x
|
||||
bool m_gameOver = false;
|
||||
bool m_isWon = false;
|
||||
int m_artifactCount = 0;
|
||||
|
||||
@@ -76,6 +76,8 @@ TEST_CASE("ConfigLoader loads the committed bin/config/ configs end-to-end", "[c
|
||||
REQUIRE(cfg.world.regions.playerBufferWidth_tiles == 10);
|
||||
REQUIRE(cfg.world.regions.enemyBufferWidth_tiles == 15);
|
||||
REQUIRE(cfg.world.expansion.columnsPerExpansion_tiles == 10);
|
||||
REQUIRE(cfg.world.expansion.costBuildingBlocksFormula.evaluate(0) == Approx(400.0));
|
||||
REQUIRE(cfg.world.expansion.costBuildingBlocksFormula.evaluate(1) == Approx(800.0));
|
||||
REQUIRE(cfg.world.push.bossAdvanceSeconds == Approx(60.0));
|
||||
REQUIRE(cfg.world.orbitFactor == Approx(0.8));
|
||||
REQUIRE(cfg.world.rallyOrbitRadius_tiles == Approx(5.0));
|
||||
@@ -186,7 +188,7 @@ contest_zone_width_tiles = 30
|
||||
|
||||
[expansion]
|
||||
columns_per_expansion_tiles = 10
|
||||
cost_building_blocks = 200
|
||||
cost_building_blocks_formula = "400 * 2^x"
|
||||
|
||||
[push]
|
||||
push_expand_columns_tiles = 20
|
||||
@@ -237,7 +239,7 @@ enemy_buffer_width_tiles = 15
|
||||
|
||||
[expansion]
|
||||
columns_per_expansion_tiles = 10
|
||||
cost_building_blocks = 200
|
||||
cost_building_blocks_formula = "400 * 2^x"
|
||||
|
||||
[push]
|
||||
push_expand_columns_tiles = 20
|
||||
@@ -284,7 +286,7 @@ enemy_buffer_width_tiles = 15
|
||||
|
||||
[expansion]
|
||||
columns_per_expansion_tiles = 10
|
||||
cost_building_blocks = 200
|
||||
cost_building_blocks_formula = "400 * 2^x"
|
||||
|
||||
[push]
|
||||
push_expand_columns_tiles = 20
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "BuilderModeExitedEvent.h"
|
||||
#include "BlueprintModeExitedEvent.h"
|
||||
#include "BuildingBlocksChangedEvent.h"
|
||||
#include "ExpansionCostChangedEvent.h"
|
||||
#include "GameSpeedChangedEvent.h"
|
||||
#include "SchematicChoicesAvailableEvent.h"
|
||||
#include "TickAdvancedEvent.h"
|
||||
@@ -276,6 +277,7 @@ void GameWorldView::onFrame()
|
||||
{
|
||||
const Tick newTick = m_sim->currentTick();
|
||||
const int newBlocks = m_sim->buildingBlocksStock();
|
||||
const int newExpCost = m_sim->currentExpansionCost();
|
||||
const int newBoss = m_sim->bossWaveCounter();
|
||||
const Tick newCountdown = m_sim->bossCountdownTicks();
|
||||
|
||||
@@ -291,6 +293,12 @@ void GameWorldView::onFrame()
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<BuildingBlocksChangedEvent>(newBlocks));
|
||||
}
|
||||
if (newExpCost != m_lastExpansionCost)
|
||||
{
|
||||
m_lastExpansionCost = newExpCost;
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<ExpansionCostChangedEvent>(newExpCost));
|
||||
}
|
||||
if (newBoss != m_lastBossCounter || newCountdown != m_lastBossCountdown)
|
||||
{
|
||||
m_lastBossCounter = newBoss;
|
||||
@@ -435,7 +443,7 @@ QRect GameWorldView::viewportRect() const
|
||||
|
||||
float GameWorldView::asteroidLeftEdge() const
|
||||
{
|
||||
float leftX = -static_cast<float>(m_config->world.regions.asteroidWidth_tiles);
|
||||
float leftX = -static_cast<float>(m_sim->currentAsteroidWidth_tiles());
|
||||
for (const Building& b : m_sim->buildings().allBuildings())
|
||||
{
|
||||
for (const QPoint& cell : b.bodyCells)
|
||||
@@ -1827,6 +1835,7 @@ void GameWorldView::resetForNewGame()
|
||||
m_prevNonZeroSpeed = 1.0;
|
||||
m_lastTick = Tick(-1);
|
||||
m_lastBlocks = -1;
|
||||
m_lastExpansionCost = -1;
|
||||
m_lastBossCounter = -1;
|
||||
m_lastBossCountdown = Tick(-1);
|
||||
m_lastArtifactCount = -1;
|
||||
|
||||
@@ -226,6 +226,7 @@ private:
|
||||
|
||||
Tick m_lastTick = Tick(-1);
|
||||
int m_lastBlocks = -1;
|
||||
int m_lastExpansionCost = -1;
|
||||
int m_lastBossCounter = -1;
|
||||
Tick m_lastBossCountdown = Tick(-1);
|
||||
int m_lastArtifactCount = -1;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <QPushButton>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "Command.h"
|
||||
#include "CommandRequestedEvent.h"
|
||||
#include "EventManager.h"
|
||||
#include "SpeedChangeRequestedEvent.h"
|
||||
#include "Tick.h"
|
||||
@@ -32,6 +34,17 @@ HeaderBar::HeaderBar(QWidget* parent)
|
||||
layout->addStretch();
|
||||
layout->addWidget(m_bossLabel);
|
||||
|
||||
// Asteroid expansion button, to the left of the speed buttons (REQ-UI-HEADER,
|
||||
// REQ-UI-EXPAND-BUTTON). Caption/enabled state are set on the first
|
||||
// ExpansionCostChangedEvent; clicking requests an ExpandAsteroidCommand.
|
||||
m_expandButton = new QPushButton(tr("Expand"), this);
|
||||
layout->addWidget(m_expandButton);
|
||||
connect(m_expandButton, &QPushButton::clicked, this, []() {
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<CommandRequestedEvent>(
|
||||
std::make_shared<ExpandAsteroidCommand>()));
|
||||
});
|
||||
|
||||
const char* labels[] = { "0x", "0.5x", "1x", "2x", "10x" };
|
||||
QSignalMapper* mapper = new QSignalMapper(this);
|
||||
for (int i = 0; i < kSpeedCount; ++i)
|
||||
@@ -67,7 +80,21 @@ void HeaderBar::handleEvent(std::shared_ptr<const TickAdvancedEvent> event)
|
||||
|
||||
void HeaderBar::handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event)
|
||||
{
|
||||
m_blocks = event->blocks;
|
||||
m_blocksLabel->setText(tr("Blocks: %1").arg(event->blocks));
|
||||
updateExpandButton();
|
||||
}
|
||||
|
||||
void HeaderBar::handleEvent(std::shared_ptr<const ExpansionCostChangedEvent> event)
|
||||
{
|
||||
m_expansionCost = event->cost;
|
||||
updateExpandButton();
|
||||
}
|
||||
|
||||
void HeaderBar::updateExpandButton()
|
||||
{
|
||||
m_expandButton->setText(tr("Expand: %1 Blocks").arg(m_expansionCost));
|
||||
m_expandButton->setEnabled(m_blocks >= m_expansionCost);
|
||||
}
|
||||
|
||||
void HeaderBar::handleEvent(std::shared_ptr<const GameSpeedChangedEvent> event)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "BossWaveUpdatedEvent.h"
|
||||
#include "BuildingBlocksChangedEvent.h"
|
||||
#include "EventHandler.h"
|
||||
#include "ExpansionCostChangedEvent.h"
|
||||
#include "GameSpeedChangedEvent.h"
|
||||
#include "Tick.h"
|
||||
#include "TickAdvancedEvent.h"
|
||||
@@ -18,6 +19,7 @@ class QPushButton;
|
||||
class HeaderBar : public QWidget,
|
||||
public CombinedEventHandler<TickAdvancedEvent,
|
||||
BuildingBlocksChangedEvent,
|
||||
ExpansionCostChangedEvent,
|
||||
GameSpeedChangedEvent,
|
||||
BossWaveUpdatedEvent,
|
||||
ArtifactCountChangedEvent>
|
||||
@@ -34,16 +36,25 @@ private slots:
|
||||
private:
|
||||
void handleEvent(std::shared_ptr<const TickAdvancedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const ExpansionCostChangedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const GameSpeedChangedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const BossWaveUpdatedEvent> event) override;
|
||||
void handleEvent(std::shared_ptr<const ArtifactCountChangedEvent> event) override;
|
||||
|
||||
// Refreshes the Expand button caption and enabled state from the current
|
||||
// expansion cost and building block stock (REQ-UI-EXPAND-BUTTON).
|
||||
void updateExpandButton();
|
||||
|
||||
QLabel* m_timeLabel;
|
||||
QLabel* m_blocksLabel;
|
||||
QLabel* m_artifactsLabel;
|
||||
QLabel* m_bossLabel;
|
||||
QPushButton* m_expandButton;
|
||||
std::vector<QPushButton*> m_speedButtons;
|
||||
|
||||
int m_blocks = 0;
|
||||
int m_expansionCost = 0;
|
||||
|
||||
static const double kSpeeds[];
|
||||
static const int kSpeedCount;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user