Compare commits
5 Commits
271855781c
...
3d4c0445d1
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d4c0445d1 | |||
| cd8bf1a8b3 | |||
| c4d696c79e | |||
| 1add02eafa | |||
| 129200ff4f |
@@ -1,5 +1,6 @@
|
||||
[[building]]
|
||||
id = "belt"
|
||||
tooltip = "Transports items one tile at a time in the direction it faces."
|
||||
cost = 2
|
||||
player_placeable = true
|
||||
construction_time_seconds = 0.2
|
||||
@@ -7,6 +8,7 @@ surface_mask = ["A>"]
|
||||
|
||||
[[building]]
|
||||
id = "splitter"
|
||||
tooltip = "Splits an incoming item stream between two outputs, with optional per-output filters."
|
||||
cost = 3
|
||||
player_placeable = true
|
||||
construction_time_seconds = 0.5
|
||||
@@ -14,6 +16,7 @@ surface_mask = ["<A>"]
|
||||
|
||||
[[building]]
|
||||
id = "tunnel_entry"
|
||||
tooltip = "Sends items underground to a matching tunnel exit, letting belts cross."
|
||||
cost = 5
|
||||
player_placeable = true
|
||||
construction_time_seconds = 0.5
|
||||
@@ -21,6 +24,7 @@ surface_mask = ["A>"]
|
||||
|
||||
[[building]]
|
||||
id = "tunnel_exit"
|
||||
tooltip = "Receives items from a matching tunnel entry and pushes them onward."
|
||||
cost = 5
|
||||
player_placeable = true
|
||||
construction_time_seconds = 0.5
|
||||
@@ -28,6 +32,7 @@ surface_mask = ["A>"]
|
||||
|
||||
[[building]]
|
||||
id = "miner"
|
||||
tooltip = "Extracts a selected ore from the asteroid; every tile yields any ore."
|
||||
cost = 15
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
@@ -37,6 +42,7 @@ surface_mask = [
|
||||
|
||||
[[building]]
|
||||
id = "smelter"
|
||||
tooltip = "Melts ore or scrap into basic materials. No recipe selection needed."
|
||||
cost = 20
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
@@ -47,6 +53,7 @@ surface_mask = [
|
||||
|
||||
[[building]]
|
||||
id = "assembler"
|
||||
tooltip = "Crafts a selected recipe from the production tree into intermediate or final parts."
|
||||
cost = 35
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
@@ -57,6 +64,7 @@ surface_mask = [
|
||||
|
||||
[[building]]
|
||||
id = "reprocessing_plant"
|
||||
tooltip = "Consumes scrap and yields one random higher-tier product per cycle."
|
||||
cost = 40
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
@@ -68,6 +76,7 @@ surface_mask = [
|
||||
|
||||
[[building]]
|
||||
id = "shipyard"
|
||||
tooltip = "Builds autonomous combat ships from a selected schematic and module layout."
|
||||
cost = 60
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
@@ -78,6 +87,7 @@ surface_mask = [
|
||||
|
||||
[[building]]
|
||||
id = "salvage_bay"
|
||||
tooltip = "Drop-off point where salvage ships unload collected scrap onto belts."
|
||||
cost = 25
|
||||
player_placeable = true
|
||||
construction_time_seconds = 1
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
[[module]]
|
||||
id = "railgun_s"
|
||||
tooltip = "Small railgun. Fast-firing, short range, low damage; fits any hull."
|
||||
unlock_at_station_level = -1
|
||||
surface_mask = ["O"]
|
||||
materials = [{item = "railgun_s_module", amount = 1}]
|
||||
@@ -47,6 +48,7 @@ attack_rate_hz = 2.0
|
||||
|
||||
[[module]]
|
||||
id = "railgun_m"
|
||||
tooltip = "Medium railgun. Higher damage at longer range; needs a 2x2 slot."
|
||||
unlock_at_station_level = 2
|
||||
surface_mask = [
|
||||
"OO",
|
||||
@@ -64,6 +66,7 @@ attack_rate_hz = 1.5
|
||||
|
||||
[[module]]
|
||||
id = "railgun_l"
|
||||
tooltip = "Large railgun. Heavy damage at long range; needs a 3x3 slot."
|
||||
unlock_at_station_level = 6
|
||||
unlock_requires = ["railgun_m"]
|
||||
surface_mask = [
|
||||
@@ -86,6 +89,7 @@ attack_rate_hz = 0.8
|
||||
|
||||
[[module]]
|
||||
id = "salvager"
|
||||
tooltip = "Collects scrap from wrecks and stores it in the ship's cargo hold."
|
||||
unlock_at_station_level = -1
|
||||
surface_mask = ["O"]
|
||||
materials = [{item = "salvager_module", amount = 1}]
|
||||
@@ -101,6 +105,7 @@ collection_rate_hz = 0.5
|
||||
|
||||
[[module]]
|
||||
id = "repair_tool"
|
||||
tooltip = "Repairs damaged friendly ships and defence stations within range."
|
||||
unlock_at_station_level = 0
|
||||
surface_mask = ["O"]
|
||||
materials = [{item = "repair_tool_module", amount = 1}]
|
||||
@@ -119,6 +124,7 @@ repair_range_m = 80
|
||||
|
||||
[[module]]
|
||||
id = "afterburner"
|
||||
tooltip = "Greatly boosts top speed and forward acceleration."
|
||||
unlock_at_station_level = 2
|
||||
surface_mask = ["OOO"]
|
||||
materials = [{item = "afterburner_module", amount = 1}]
|
||||
@@ -133,6 +139,7 @@ added_main_acceleration_mpss = 60
|
||||
|
||||
[[module]]
|
||||
id = "maneuvering_thrusters"
|
||||
tooltip = "Improves top speed and lateral/braking acceleration."
|
||||
unlock_at_station_level = 1
|
||||
surface_mask = ["OO"]
|
||||
materials = [{item = "maneuvering_thrusters_module", amount = 1}]
|
||||
@@ -150,6 +157,7 @@ added_maneuvering_acceleration_mpss = 10
|
||||
|
||||
[[module]]
|
||||
id = "armor_plates"
|
||||
tooltip = "Adds a large flat bonus to the ship's hit points."
|
||||
unlock_at_station_level = 0
|
||||
surface_mask = ["OO"]
|
||||
materials = [{item = "armor_plates_module", amount = 1}]
|
||||
@@ -163,6 +171,7 @@ added_hp = 1200
|
||||
|
||||
[[module]]
|
||||
id = "sensor_booster"
|
||||
tooltip = "Extends the ship's sensor range."
|
||||
unlock_at_station_level = 1
|
||||
surface_mask = ["OO"]
|
||||
materials = [{item = "sensor_booster_module", amount = 1}]
|
||||
@@ -179,6 +188,7 @@ added_sensor_range_m = 50
|
||||
|
||||
[[module]]
|
||||
id = "weapon_upgrade"
|
||||
tooltip = "Increases the damage of all weapons on the ship."
|
||||
unlock_at_station_level = 4
|
||||
surface_mask = [
|
||||
"OO",
|
||||
@@ -195,6 +205,7 @@ multiplied_damage = 1.2
|
||||
|
||||
[[module]]
|
||||
id = "weapon_primer"
|
||||
tooltip = "Increases the fire rate of all weapons on the ship."
|
||||
unlock_at_station_level = 4
|
||||
surface_mask = [
|
||||
"OO",
|
||||
@@ -211,6 +222,7 @@ multiplied_attack_rate_hz = 1.2
|
||||
|
||||
[[module]]
|
||||
id = "weapon_stabilizer"
|
||||
tooltip = "Extends weapon range at the cost of some fire rate."
|
||||
unlock_at_station_level = 3
|
||||
surface_mask = [
|
||||
"OO",
|
||||
@@ -234,6 +246,7 @@ multiplied_attack_rate_hz = 0.8
|
||||
|
||||
[[module]]
|
||||
id = "drone_bay"
|
||||
tooltip = "Drone launch bay (capability not yet implemented)."
|
||||
unlock_at_station_level = 5
|
||||
surface_mask = [
|
||||
"OO",
|
||||
@@ -246,6 +259,7 @@ glyph = "Db"
|
||||
|
||||
[[module]]
|
||||
id = "drone_hangar"
|
||||
tooltip = "Large drone hangar (capability not yet implemented)."
|
||||
unlock_at_station_level = 9
|
||||
surface_mask = [
|
||||
"OOOOOO",
|
||||
|
||||
@@ -10,6 +10,7 @@ tunnel_max_distance_tiles = 10
|
||||
departure_interval_seconds = 20
|
||||
orbit_factor = 0.8
|
||||
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]
|
||||
asteroid_width_tiles = 60
|
||||
|
||||
@@ -84,6 +84,7 @@ cost = 25
|
||||
player_placeable = true
|
||||
construction_time_seconds = 15
|
||||
output_buffer_capacity = 20
|
||||
tooltip = "Drop-off point for salvage ships."
|
||||
surface_mask = [
|
||||
"SAA",
|
||||
"SAA>",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[[module]]
|
||||
id = "armor_plate"
|
||||
tooltip = "Adds a large flat bonus to hit points."
|
||||
unlock_at_station_level = -1
|
||||
surface_mask = ["OO"]
|
||||
materials = [{item = "iron_ingot", amount = 2}]
|
||||
|
||||
@@ -10,6 +10,7 @@ tunnel_max_distance_tiles = 10
|
||||
departure_interval_seconds = 20
|
||||
orbit_factor = 0.8
|
||||
rally_orbit_radius_tiles = 5.0
|
||||
building_blocks_tooltip = "Spend building blocks to build; deliver them to the HQ to gain more."
|
||||
|
||||
[regions]
|
||||
asteroid_width_tiles = 40
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
Config files use the TOML format. The following config files drive game parameters:
|
||||
|
||||
- **world.toml** — world dimensions, region widths, expansion amounts, building refund percentage, wave timing, boss wave timing, belt speed, starting building blocks, departure interval, ship orbit factor, rally orbit radius, scrap-per-threat conversion, combat target-selection parameters (target score formula, overclaim penalty formula, target hysteresis), artifact chance formula, artifact win count, and view pan speeds (slow and fast horizontal pan speed and pan ramp band width).
|
||||
- **buildings.toml** — building block cost and construction time per building type.
|
||||
- **world.toml** — world dimensions, region widths, expansion amounts, building refund percentage, wave timing, boss wave timing, belt speed, starting building blocks, departure interval, ship orbit factor, rally orbit radius, scrap-per-threat conversion, combat target-selection parameters (target score formula, overclaim penalty formula, target hysteresis), artifact chance formula, artifact win count, view pan speeds (slow and fast horizontal pan speed and pan ramp band width), and an optional building blocks tooltip string (shown as the header bar's building blocks stock hover tooltip, REQ-UI-BLOCKS-TOOLTIP; omitted when unset).
|
||||
- **buildings.toml** — building block cost and construction time per building type, plus an optional tooltip description string per building type (shown as the build button's hover tooltip, REQ-UI-BUILD-TOOLTIP; omitted when unset).
|
||||
- **recipes.toml** — crafting recipes: inputs, outputs, quantities, durations, and reprocessing plant probabilities. Assembler recipe entries may optionally define `unlock_at_station_level` (integer): -1 means the recipe is explicitly unlocked at game start; a value ≥ 0 means the recipe starts locked and a schematic for it can be awarded via defence station destruction (see REQ-LOCK-EXPLICIT, REQ-DEF-SCHEMATIC-DROP). An assembler recipe schematic entry may also define an optional `unlock_requires` list of prerequisite schematic ids (REQ-LOCK-PREREQ).
|
||||
- **ships.toml** — per schematic: a human-readable display name (used in the UI), hull stats (HP, max linear speed, sensor range, main acceleration, maneuvering acceleration, angular acceleration, max rotation speed) as plain values, required build materials, the station level at which the schematic becomes available for unlock (`unlock_at_station_level`; -1 means the player starts with the schematic already unlocked), an optional `unlock_requires` prerequisite list (REQ-LOCK-PREREQ), a layout grid defining the ship's module slots, and a `default_modules` list used for enemy wave ships (see REQ-WAV-DEFAULT-MODULES).
|
||||
- **modules.toml** — per module type: id, surface mask, materials list, production time, fill color, glyph, the station level at which the schematic becomes available for unlock (`unlock_at_station_level`; -1 means the player starts with the module schematic already unlocked), an optional `unlock_requires` prerequisite list (REQ-LOCK-PREREQ), and an optional capability section and/or stat modifier formulas. A module with a capability section (`[module.weapon]`, `[module.salvage]`, or `[module.repair]`) containing base stat formulas is a **capability module** that grants the ship a weapon, salvage bay, or repair tool per instance (see REQ-MOD-CONFIG for the full list of formulas per capability type). A module with only `added_*`/`multiplied_*` formulas is a **passive module** that modifies stats on the ship or on capability module instances (see REQ-MOD-STAT-CALC).
|
||||
- **modules.toml** — per module type: id, surface mask, materials list, production time, fill color, glyph, an optional tooltip description string (shown as the module selection button's hover tooltip, REQ-MOD-UI-MODULE-TOOLTIP; omitted when unset), the station level at which the schematic becomes available for unlock (`unlock_at_station_level`; -1 means the player starts with the module schematic already unlocked), an optional `unlock_requires` prerequisite list (REQ-LOCK-PREREQ), and an optional capability section and/or stat modifier formulas. A module with a capability section (`[module.weapon]`, `[module.salvage]`, or `[module.repair]`) containing base stat formulas is a **capability module** that grants the ship a weapon, salvage bay, or repair tool per instance (see REQ-MOD-CONFIG for the full list of formulas per capability type). A module with only `added_*`/`multiplied_*` formulas is a **passive module** that modifies stats on the ship or on capability module instances (see REQ-MOD-STAT-CALC).
|
||||
- **stations.toml** — HP, damage, range, fire rate, and scrap drop for player and enemy defence stations, defined as formulas of station level.
|
||||
- **visuals.toml** — rendering-only config (not game parameters): fill and outline colors and glyphs for every building type, item type, ship schematic, and station type; a distinct beam color per tool type (weapon, repair, salvage) and beam width; overlay and toast colors. Loaded by the UI at startup; the simulation does not read it.
|
||||
- **ship_layouts.toml** — named layout blueprints per ship type; written and read by the application to persist the layout blueprint panel (REQ-MOD-UI-BLUEPRINT-PANEL through REQ-MOD-UI-BLUEPRINT-FILE-LOAD). Not a game parameter file; the simulation does not read it.
|
||||
@@ -269,6 +269,8 @@ Modules in `modules.toml` define a `surface_mask` — a list of strings that des
|
||||
- **Right** (below the grid): The layout blueprint panel (see REQ-MOD-UI-BLUEPRINT-PANEL through REQ-MOD-UI-BLUEPRINT-FILE-LOAD).
|
||||
- **Bottom**: A "Confirm" button and a "Cancel" button. Cancel discards all changes made in this dialog session and closes the dialog. Confirm applies the changes: the shipyard's configured layout is updated, the required materials and cycle time displayed in the selected building panel are recalculated, and the ship layout preview is refreshed.
|
||||
|
||||
- REQ-MOD-UI-MODULE-TOOLTIP: Each module selection button in the layout configuration dialog (REQ-MOD-UI-DIALOG) shows a hover tooltip with the descriptive text defined for that module type in `modules.toml` (the optional per-module tooltip field). If a module type defines no tooltip text, its button shows no tooltip. The "Remove" button is not a module type and has no config-defined tooltip.
|
||||
|
||||
- REQ-MOD-UI-STATS-PANEL: The **ship stats panel** in the layout configuration dialog shows the stats of the currently configured ship layout as they would be computed, incorporating all passive module modifiers per REQ-MOD-STAT-CALC. The panel updates in real time whenever modules are placed or removed in the layout grid.
|
||||
|
||||
The panel always shows all hull stats as final computed values:
|
||||
@@ -401,6 +403,7 @@ The screen is divided into two columns: a main column (75% width) containing the
|
||||
```
|
||||
|
||||
- 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-BLOCKS-TOOLTIP: The header bar's building blocks stock display (REQ-UI-HEADER) shows a hover tooltip with the descriptive text defined in `world.toml [world].building_blocks_tooltip` — intended to tell the player what building blocks are used for and how to obtain them. If the field is unset, the stock display shows no tooltip. This tooltip is distinct from the build/module button tooltips (REQ-UI-BUILD-TOOLTIP, REQ-MOD-UI-MODULE-TOOLTIP).
|
||||
- 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.
|
||||
@@ -473,6 +476,7 @@ The screen is divided into two columns: a main column (75% width) containing the
|
||||
|
||||
- REQ-UI-BUILD-GRID: All placeable building types are shown as a flat grid of buttons with no grouping.
|
||||
- REQ-UI-BUILD-COST: Each button caption shows the building name and its building block cost, e.g. "Belt: 2 Blocks".
|
||||
- REQ-UI-BUILD-TOOLTIP: Each building-type button shows a hover tooltip with the descriptive text defined for that building type in `buildings.toml` (the optional per-building tooltip field). This tooltip is distinct from the recipe/schematic selection tooltip (REQ-UI-SELECT-TOOLTIP). If a building type defines no tooltip text, its button shows no tooltip. The Demolish button (REQ-UI-DEMOLISH-BUTTON) is not a building type and has no config-defined tooltip.
|
||||
- REQ-UI-BUILD-DISABLED: Buttons for buildings the player cannot currently afford are shown as disabled.
|
||||
- REQ-UI-DEMOLISH-BUTTON: A dedicated **Demolish** button is shown in the build button grid. Clicking it toggles demolish mode on and off, equivalent to the Q demolish toggle (REQ-UI-HOTKEYS). The button is shown in a visually active/pressed state while demolish mode is active.
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ struct BuildingDef
|
||||
// Output-buffer holding size for buildings without a recipe-driven buffer.
|
||||
// Only the Salvage Bay sets this (REQ-BLD-SALVAGE-BAY).
|
||||
std::optional<int> outputBufferCapacity;
|
||||
|
||||
// Optional hover-tooltip text for the build button (REQ-UI-BUILD-TOOLTIP).
|
||||
std::optional<std::string> tooltip;
|
||||
};
|
||||
|
||||
struct BuildingsConfig
|
||||
|
||||
@@ -273,6 +273,12 @@ WorldConfig ConfigLoader::loadWorld(const std::string& path)
|
||||
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");
|
||||
|
||||
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.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"));
|
||||
@@ -343,6 +349,11 @@ BuildingsConfig ConfigLoader::loadBuildings(const std::string& path)
|
||||
requireInt(mt["output_buffer_capacity"], file, elemPath + ".output_buffer_capacity"));
|
||||
}
|
||||
|
||||
if (mt.contains("tooltip"))
|
||||
{
|
||||
def.tooltip = requireString(mt["tooltip"], file, elemPath + ".tooltip");
|
||||
}
|
||||
|
||||
const std::optional<BuildingType> parsedType = parseBuildingType(def.id);
|
||||
if (!parsedType)
|
||||
{
|
||||
@@ -603,6 +614,11 @@ ModulesConfig ConfigLoader::loadModules(const std::string& path)
|
||||
def.fillColor = requireString(mt["fill_color"], file, elemPath + ".fill_color");
|
||||
def.glyph = requireString(mt["glyph"], file, elemPath + ".glyph");
|
||||
|
||||
if (mt.contains("tooltip"))
|
||||
{
|
||||
def.tooltip = requireString(mt["tooltip"], file, elemPath + ".tooltip");
|
||||
}
|
||||
|
||||
// Materials
|
||||
{
|
||||
const toml::array& materials = requireArray(mt["materials"], file, elemPath + ".materials");
|
||||
|
||||
@@ -54,6 +54,10 @@ struct ModuleDef
|
||||
std::optional<ModuleWeaponCapability> weaponCapability;
|
||||
std::optional<ModuleSalvageCapability> salvageCapability;
|
||||
std::optional<ModuleRepairCapability> repairCapability;
|
||||
|
||||
// Optional hover-tooltip text for the module selection button
|
||||
// (REQ-MOD-UI-MODULE-TOOLTIP).
|
||||
std::optional<std::string> tooltip;
|
||||
};
|
||||
|
||||
struct ModulesConfig
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "Formula.h"
|
||||
|
||||
// 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 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;
|
||||
WorldExpansion expansion;
|
||||
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.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.
|
||||
// threat_rate_formula = "x": evaluates to the input value.
|
||||
REQUIRE(cfg.world.waves.threatRateFormula.evaluate(1.0) == Approx(1.0));
|
||||
@@ -113,6 +118,12 @@ TEST_CASE("ConfigLoader loads the committed bin/config/ configs end-to-end", "[c
|
||||
REQUIRE(salvageBayIt->outputBufferCapacity.has_value());
|
||||
REQUIRE(*salvageBayIt->outputBufferCapacity == 20);
|
||||
|
||||
// Optional per-building tooltip (REQ-UI-BUILD-TOOLTIP): the Salvage Bay
|
||||
// defines one; the Miner leaves it unset.
|
||||
REQUIRE(salvageBayIt->tooltip.has_value());
|
||||
REQUIRE(*salvageBayIt->tooltip == "Drop-off point for salvage ships.");
|
||||
REQUIRE_FALSE(minerIt->tooltip.has_value());
|
||||
|
||||
// recipes.toml — reprocessing cycle has three weighted outputs.
|
||||
const auto reproIt = std::find_if(
|
||||
cfg.recipes.recipes.begin(), cfg.recipes.recipes.end(),
|
||||
@@ -144,6 +155,21 @@ TEST_CASE("ConfigLoader loads the committed bin/config/ configs end-to-end", "[c
|
||||
REQUIRE(salvageShipIt != cfg.ships.ships.end());
|
||||
REQUIRE(salvageShipIt->defaultModules.empty());
|
||||
|
||||
// modules.toml — optional per-module tooltip (REQ-MOD-UI-MODULE-TOOLTIP):
|
||||
// armor_plate defines one; salvager leaves it unset.
|
||||
const auto armorPlateIt = std::find_if(
|
||||
cfg.modules.modules.begin(), cfg.modules.modules.end(),
|
||||
[](const ModuleDef& m) { return m.id == "armor_plate"; });
|
||||
REQUIRE(armorPlateIt != cfg.modules.modules.end());
|
||||
REQUIRE(armorPlateIt->tooltip.has_value());
|
||||
REQUIRE(*armorPlateIt->tooltip == "Adds a large flat bonus to hit points.");
|
||||
|
||||
const auto salvagerModuleIt = std::find_if(
|
||||
cfg.modules.modules.begin(), cfg.modules.modules.end(),
|
||||
[](const ModuleDef& m) { return m.id == "salvager"; });
|
||||
REQUIRE(salvagerModuleIt != cfg.modules.modules.end());
|
||||
REQUIRE_FALSE(salvagerModuleIt->tooltip.has_value());
|
||||
|
||||
// stations.toml
|
||||
REQUIRE(cfg.stations.playerStation.level == 5);
|
||||
REQUIRE(cfg.stations.playerStation.hpFormula.evaluate(5.0) == Approx(500.0)); // 300 + 40*5
|
||||
|
||||
@@ -239,7 +239,7 @@ void BlueprintPanel::rebuildButtons()
|
||||
{
|
||||
const Blueprint& bp = m_blueprints[static_cast<std::size_t>(i)];
|
||||
const int cost = computeBlueprintCost(bp);
|
||||
const QString label = bp.name + "\n" + tr("%1 Blocks").arg(cost);
|
||||
const QString label = bp.name + "\n" + tr("%1 Building Blocks").arg(cost);
|
||||
|
||||
QWidget* row = new QWidget(m_buttonsContainer);
|
||||
QHBoxLayout* rowLayout = new QHBoxLayout(row);
|
||||
|
||||
@@ -38,10 +38,14 @@ BuildButtonGrid::BuildButtonGrid(const GameConfig* config, QWidget* parent)
|
||||
m_costs[def.type] = def.cost;
|
||||
|
||||
const QString label = QString::fromStdString(toDisplayName(def.id))
|
||||
+ "\n" + tr("%1 Blocks").arg(def.cost);
|
||||
+ "\n" + tr("%1 Building Blocks").arg(def.cost);
|
||||
QPushButton* btn = new QPushButton(label, this);
|
||||
btn->setCheckable(true);
|
||||
btn->setFixedHeight(48);
|
||||
if (def.tooltip)
|
||||
{
|
||||
btn->setToolTip(QString::fromStdString(*def.tooltip));
|
||||
}
|
||||
layout->addWidget(btn, row, col);
|
||||
|
||||
const int idx = static_cast<int>(m_buttons.size());
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
const double HeaderBar::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 10.0 };
|
||||
const int HeaderBar::kSpeedCount = 5;
|
||||
|
||||
HeaderBar::HeaderBar(QWidget* parent)
|
||||
HeaderBar::HeaderBar(const GameConfig* config, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
@@ -25,7 +25,12 @@ HeaderBar::HeaderBar(QWidget* parent)
|
||||
layout->setSpacing(8);
|
||||
|
||||
m_timeLabel = new QLabel("00:00", this);
|
||||
m_blocksLabel = new QLabel(tr("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_bossLabel = new QLabel(tr("Boss Wave #1 Next boss: 5:00"), this);
|
||||
layout->addWidget(m_timeLabel);
|
||||
@@ -81,7 +86,7 @@ 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));
|
||||
m_blocksLabel->setText(tr("Building Blocks: %1").arg(event->blocks));
|
||||
updateExpandButton();
|
||||
}
|
||||
|
||||
@@ -93,7 +98,7 @@ void HeaderBar::handleEvent(std::shared_ptr<const ExpansionCostChangedEvent> eve
|
||||
|
||||
void HeaderBar::updateExpandButton()
|
||||
{
|
||||
m_expandButton->setText(tr("Expand: %1 Blocks").arg(m_expansionCost));
|
||||
m_expandButton->setText(tr("Expand: %1 Building Blocks").arg(m_expansionCost));
|
||||
m_expandButton->setEnabled(m_blocks >= m_expansionCost);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "BuildingBlocksChangedEvent.h"
|
||||
#include "EventHandler.h"
|
||||
#include "ExpansionCostChangedEvent.h"
|
||||
#include "GameConfig.h"
|
||||
#include "GameSpeedChangedEvent.h"
|
||||
#include "Tick.h"
|
||||
#include "TickAdvancedEvent.h"
|
||||
@@ -27,7 +28,7 @@ class HeaderBar : public QWidget,
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HeaderBar(QWidget* parent = nullptr);
|
||||
explicit HeaderBar(const GameConfig* config, QWidget* parent = nullptr);
|
||||
~HeaderBar() override;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -42,7 +42,7 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
|
||||
setWindowTitle(tr("Dota Factory"));
|
||||
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_replay.get(), this);
|
||||
|
||||
@@ -461,6 +461,10 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
QPushButton* btn = new QPushButton(label, this);
|
||||
btn->setCheckable(true);
|
||||
btn->setFixedHeight(48);
|
||||
if (def.tooltip)
|
||||
{
|
||||
btn->setToolTip(QString::fromStdString(*def.tooltip));
|
||||
}
|
||||
buttonGrid->addWidget(btn, row, col);
|
||||
m_moduleButtons.push_back(btn);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user