From eb1572cd8050894df4886e88f1115e66e12142e1 Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Mon, 13 Jul 2026 07:13:29 +0200 Subject: [PATCH] Show total building block cost in multi-selection panel Implement the REQ-UI-MULTI-SELECTION addition: the selected building panel now shows the total placement cost of a multi-selection, counting only player-placeable buildings (HQ and defence stations excluded). Construction sites are charged their type's full cost. Add a shared BuildingsConfig::findBuildingDef accessor and reuse it in BlueprintPanel to remove the duplicated by-type lookup loops. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DZR44tA8sn4dPqDzAVXyps --- src/lib/config/BuildingsConfig.h | 14 ++++++++++++++ src/ui/BlueprintPanel.cpp | 20 ++++---------------- src/ui/SelectedBuildingPanel.cpp | 9 +++++++++ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/lib/config/BuildingsConfig.h b/src/lib/config/BuildingsConfig.h index 086de34..16922f8 100644 --- a/src/lib/config/BuildingsConfig.h +++ b/src/lib/config/BuildingsConfig.h @@ -31,4 +31,18 @@ struct BuildingDef struct BuildingsConfig { std::vector buildings; + + // Returns the definition for the given building type, or nullptr if the + // type has no entry in buildings.toml. + const BuildingDef* findBuildingDef(BuildingType type) const + { + for (const BuildingDef& def : buildings) + { + if (def.type == type) + { + return &def; + } + } + return nullptr; + } }; diff --git a/src/ui/BlueprintPanel.cpp b/src/ui/BlueprintPanel.cpp index e0a777d..2f71331 100644 --- a/src/ui/BlueprintPanel.cpp +++ b/src/ui/BlueprintPanel.cpp @@ -157,14 +157,8 @@ Blueprint BlueprintPanel::createBlueprintFromSelection() const { const Building* b = m_sim->buildings().findBuilding(id); if (!b) { continue; } - const bool placeable = [&]() { - for (const BuildingDef& def : m_config->buildings.buildings) - { - if (def.type == b->type) { return def.playerPlaceable; } - } - return false; - }(); - if (placeable) { entries.push_back({ b }); } + const BuildingDef* def = m_config->buildings.findBuildingDef(b->type); + if (def && def->playerPlaceable) { entries.push_back({ b }); } } if (entries.empty()) { return Blueprint{}; } @@ -213,14 +207,8 @@ int BlueprintPanel::computeBlueprintCost(const Blueprint& bp) const int total = 0; for (const BlueprintBuilding& bb : bp.buildings) { - for (const BuildingDef& def : m_config->buildings.buildings) - { - if (def.type == bb.type) - { - total += def.cost; - break; - } - } + const BuildingDef* def = m_config->buildings.findBuildingDef(bb.type); + if (def) { total += def->cost; } } return total; } diff --git a/src/ui/SelectedBuildingPanel.cpp b/src/ui/SelectedBuildingPanel.cpp index eb1a7c5..d070440 100644 --- a/src/ui/SelectedBuildingPanel.cpp +++ b/src/ui/SelectedBuildingPanel.cpp @@ -694,6 +694,7 @@ void SelectedBuildingPanel::buildMulti(const std::vector& ids) } bool hasBelt = false; + int totalCost = 0; QString text; for (const std::pair& entry : counts) { @@ -703,7 +704,15 @@ void SelectedBuildingPanel::buildMulti(const std::vector& ids) { hasBelt = true; } + // Total placement cost counts only player-placeable buildings; the HQ + // and defence stations are excluded (REQ-UI-MULTI-SELECTION). + const BuildingDef* def = m_config->buildings.findBuildingDef(entry.first); + if (def && def->playerPlaceable) + { + totalCost += def->cost * entry.second; + } } + text += tr("Total: %1 Building Blocks").arg(totalCost); m_titleLabel->setText(text.trimmed()); m_titleLabel->show();