Add config-defined tooltip to header building blocks stock
Implement REQ-UI-BLOCKS-TOOLTIP: an optional world.toml [world].building_blocks_tooltip, threaded into HeaderBar via a new const GameConfig* parameter and shown as the building blocks stock label's hover tooltip. Omitted when unset. Author the text in the app config and extend ConfigLoaderTest to cover the field. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DZR44tA8sn4dPqDzAVXyps
This commit is contained in:
@@ -10,6 +10,7 @@ tunnel_max_distance_tiles = 10
|
|||||||
departure_interval_seconds = 20
|
departure_interval_seconds = 20
|
||||||
orbit_factor = 0.8
|
orbit_factor = 0.8
|
||||||
rally_orbit_radius_tiles = 5.0
|
rally_orbit_radius_tiles = 5.0
|
||||||
|
building_blocks_tooltip = "Building blocks are the currency for construction. Spend them to place buildings and to expand the asteroid. Produce building blocks in your factory and deliver them to the HQ on a belt to grow your stock."
|
||||||
|
|
||||||
[regions]
|
[regions]
|
||||||
asteroid_width_tiles = 60
|
asteroid_width_tiles = 60
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ tunnel_max_distance_tiles = 10
|
|||||||
departure_interval_seconds = 20
|
departure_interval_seconds = 20
|
||||||
orbit_factor = 0.8
|
orbit_factor = 0.8
|
||||||
rally_orbit_radius_tiles = 5.0
|
rally_orbit_radius_tiles = 5.0
|
||||||
|
building_blocks_tooltip = "Spend building blocks to build; deliver them to the HQ to gain more."
|
||||||
|
|
||||||
[regions]
|
[regions]
|
||||||
asteroid_width_tiles = 40
|
asteroid_width_tiles = 40
|
||||||
|
|||||||
@@ -273,6 +273,12 @@ WorldConfig ConfigLoader::loadWorld(const std::string& path)
|
|||||||
cfg.orbitFactor = requireDouble(tbl["world"]["orbit_factor"], file, "world.orbit_factor");
|
cfg.orbitFactor = requireDouble(tbl["world"]["orbit_factor"], file, "world.orbit_factor");
|
||||||
cfg.rallyOrbitRadius_tiles = requireDouble(tbl["world"]["rally_orbit_radius_tiles"], file, "world.rally_orbit_radius_tiles");
|
cfg.rallyOrbitRadius_tiles = requireDouble(tbl["world"]["rally_orbit_radius_tiles"], file, "world.rally_orbit_radius_tiles");
|
||||||
|
|
||||||
|
if (const std::optional<std::string> tip =
|
||||||
|
tbl["world"]["building_blocks_tooltip"].value<std::string>())
|
||||||
|
{
|
||||||
|
cfg.buildingBlocksTooltip = *tip;
|
||||||
|
}
|
||||||
|
|
||||||
cfg.regions.asteroidWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["asteroid_width_tiles"], file, "regions.asteroid_width_tiles"));
|
cfg.regions.asteroidWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["asteroid_width_tiles"], file, "regions.asteroid_width_tiles"));
|
||||||
cfg.regions.playerBufferWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["player_buffer_width_tiles"], file, "regions.player_buffer_width_tiles"));
|
cfg.regions.playerBufferWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["player_buffer_width_tiles"], file, "regions.player_buffer_width_tiles"));
|
||||||
cfg.regions.contestZoneWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["contest_zone_width_tiles"], file, "regions.contest_zone_width_tiles"));
|
cfg.regions.contestZoneWidth_tiles = static_cast<int>(requireInt(tbl["regions"]["contest_zone_width_tiles"], file, "regions.contest_zone_width_tiles"));
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "Formula.h"
|
#include "Formula.h"
|
||||||
|
|
||||||
// Region widths are in tiles (REQ-GW-REGIONS).
|
// Region widths are in tiles (REQ-GW-REGIONS).
|
||||||
@@ -75,6 +78,10 @@ struct WorldConfig
|
|||||||
double orbitFactor; // REQ-SHP-ORBIT (multiplies tool range for orbit radius)
|
double orbitFactor; // REQ-SHP-ORBIT (multiplies tool range for orbit radius)
|
||||||
double rallyOrbitRadius_tiles; // REQ-SHP-ORBIT (fixed orbit radius around the rally point)
|
double rallyOrbitRadius_tiles; // REQ-SHP-ORBIT (fixed orbit radius around the rally point)
|
||||||
|
|
||||||
|
// Optional hover-tooltip for the header building blocks stock display
|
||||||
|
// (REQ-UI-BLOCKS-TOOLTIP). Presentation-only; the simulation ignores it.
|
||||||
|
std::optional<std::string> buildingBlocksTooltip;
|
||||||
|
|
||||||
WorldRegions regions;
|
WorldRegions regions;
|
||||||
WorldExpansion expansion;
|
WorldExpansion expansion;
|
||||||
WorldPush push;
|
WorldPush push;
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ TEST_CASE("ConfigLoader loads the committed bin/config/ configs end-to-end", "[c
|
|||||||
REQUIRE(cfg.world.rallyOrbitRadius_tiles == Approx(5.0));
|
REQUIRE(cfg.world.rallyOrbitRadius_tiles == Approx(5.0));
|
||||||
REQUIRE(cfg.world.scrapPerThreat == Approx(1.0));
|
REQUIRE(cfg.world.scrapPerThreat == Approx(1.0));
|
||||||
|
|
||||||
|
// Optional header building blocks tooltip (REQ-UI-BLOCKS-TOOLTIP).
|
||||||
|
REQUIRE(cfg.world.buildingBlocksTooltip.has_value());
|
||||||
|
REQUIRE(*cfg.world.buildingBlocksTooltip ==
|
||||||
|
"Spend building blocks to build; deliver them to the HQ to gain more.");
|
||||||
|
|
||||||
// Spot-check that a config-derived formula computes as expected.
|
// Spot-check that a config-derived formula computes as expected.
|
||||||
// threat_rate_formula = "x": evaluates to the input value.
|
// threat_rate_formula = "x": evaluates to the input value.
|
||||||
REQUIRE(cfg.world.waves.threatRateFormula.evaluate(1.0) == Approx(1.0));
|
REQUIRE(cfg.world.waves.threatRateFormula.evaluate(1.0) == Approx(1.0));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
const double HeaderBar::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 10.0 };
|
const double HeaderBar::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 10.0 };
|
||||||
const int HeaderBar::kSpeedCount = 5;
|
const int HeaderBar::kSpeedCount = 5;
|
||||||
|
|
||||||
HeaderBar::HeaderBar(QWidget* parent)
|
HeaderBar::HeaderBar(const GameConfig* config, QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||||
@@ -26,6 +26,11 @@ HeaderBar::HeaderBar(QWidget* parent)
|
|||||||
|
|
||||||
m_timeLabel = new QLabel("00:00", this);
|
m_timeLabel = new QLabel("00:00", this);
|
||||||
m_blocksLabel = new QLabel(tr("Building Blocks: 0"), this);
|
m_blocksLabel = new QLabel(tr("Building Blocks: 0"), this);
|
||||||
|
if (config->world.buildingBlocksTooltip)
|
||||||
|
{
|
||||||
|
m_blocksLabel->setToolTip(
|
||||||
|
QString::fromStdString(*config->world.buildingBlocksTooltip));
|
||||||
|
}
|
||||||
m_artifactsLabel = new QLabel(tr("Artifacts: 0/?"), this);
|
m_artifactsLabel = new QLabel(tr("Artifacts: 0/?"), this);
|
||||||
m_bossLabel = new QLabel(tr("Boss Wave #1 Next boss: 5:00"), this);
|
m_bossLabel = new QLabel(tr("Boss Wave #1 Next boss: 5:00"), this);
|
||||||
layout->addWidget(m_timeLabel);
|
layout->addWidget(m_timeLabel);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "BuildingBlocksChangedEvent.h"
|
#include "BuildingBlocksChangedEvent.h"
|
||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
#include "ExpansionCostChangedEvent.h"
|
#include "ExpansionCostChangedEvent.h"
|
||||||
|
#include "GameConfig.h"
|
||||||
#include "GameSpeedChangedEvent.h"
|
#include "GameSpeedChangedEvent.h"
|
||||||
#include "Tick.h"
|
#include "Tick.h"
|
||||||
#include "TickAdvancedEvent.h"
|
#include "TickAdvancedEvent.h"
|
||||||
@@ -27,7 +28,7 @@ class HeaderBar : public QWidget,
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HeaderBar(QWidget* parent = nullptr);
|
explicit HeaderBar(const GameConfig* config, QWidget* parent = nullptr);
|
||||||
~HeaderBar() override;
|
~HeaderBar() override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
|
|||||||
setWindowTitle(tr("Dota Factory"));
|
setWindowTitle(tr("Dota Factory"));
|
||||||
resize(1280, 768);
|
resize(1280, 768);
|
||||||
|
|
||||||
m_headerBar = new HeaderBar(this);
|
m_headerBar = new HeaderBar(&sim->config(), this);
|
||||||
|
|
||||||
m_gameWorldView = new GameWorldView(sim, &sim->config(), &m_visuals, m_configDir,
|
m_gameWorldView = new GameWorldView(sim, &sim->config(), &m_visuals, m_configDir,
|
||||||
m_replay.get(), this);
|
m_replay.get(), this);
|
||||||
|
|||||||
Reference in New Issue
Block a user