allow to unlock modules when destroying defence stations
This commit is contained in:
@@ -570,8 +570,10 @@ ModulesConfig ConfigLoader::loadModules(const std::string& path)
|
||||
toml::table& mt = const_cast<toml::table&>(*st);
|
||||
|
||||
ModuleDef def;
|
||||
def.id = requireString(mt["id"], file, elemPath + ".id");
|
||||
def.surfaceMask = requireStringArray(mt["surface_mask"], file, elemPath + ".surface_mask");
|
||||
def.id = requireString(mt["id"], file, elemPath + ".id");
|
||||
def.unlockAtStationLevel = static_cast<int>(
|
||||
mt["unlock_at_station_level"].value_or<int64_t>(-1));
|
||||
def.surfaceMask = requireStringArray(mt["surface_mask"], file, elemPath + ".surface_mask");
|
||||
def.playerProductionLevel = static_cast<int>(requireInt(
|
||||
mt["player_production_level"], file, elemPath + ".player_production_level"));
|
||||
def.productionTimeSeconds = requireDouble(
|
||||
|
||||
@@ -40,6 +40,7 @@ struct ModuleRepairCapability
|
||||
struct ModuleDef
|
||||
{
|
||||
std::string id;
|
||||
int unlockAtStationLevel;
|
||||
std::vector<std::string> surfaceMask;
|
||||
std::vector<RecipeIngredient> materials;
|
||||
int playerProductionLevel;
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// Emitted in tick step 9 (Deaths & loot) when a destroyed enemy-defence-station
|
||||
// set awards a schematic (REQ-DEF-SCHEMATIC-DROP). The UI renders a toast
|
||||
// (REQ-UI-SCHEMATIC-TOAST); wasNewUnlock chooses between the "unlocked" and
|
||||
// "level -> N" wording.
|
||||
// "level -> N" wording. isModuleSchematic selects ship vs. module toast text.
|
||||
struct SchematicDropEvent
|
||||
{
|
||||
std::string schematicId; // matches ShipDef::id in the config.
|
||||
std::string schematicId; // matches ShipDef::id or ModuleDef::id in the config.
|
||||
int newLevel;
|
||||
bool wasNewUnlock;
|
||||
bool isModuleSchematic;
|
||||
};
|
||||
|
||||
@@ -56,7 +56,8 @@ const ModuleDef* ShipSystem::findModuleDef(const std::string& id) const
|
||||
|
||||
entt::entity ShipSystem::spawn(const std::string& schematicId, int level,
|
||||
QVector2D position, bool isEnemy,
|
||||
const std::optional<ShipLayoutConfig>& layout)
|
||||
const std::optional<ShipLayoutConfig>& layout,
|
||||
const std::map<std::string, int>& moduleLevelOverrides)
|
||||
{
|
||||
const ShipDef* def = findShipDef(schematicId);
|
||||
assert(def != nullptr);
|
||||
@@ -105,7 +106,9 @@ entt::entity ShipSystem::spawn(const std::string& schematicId, int level,
|
||||
const ModuleDef* modDef = findModuleDef(pm.moduleId);
|
||||
if (!modDef) { throw std::runtime_error("unknown module id '" + pm.moduleId + "'"); }
|
||||
|
||||
const double mx = static_cast<double>(modDef->playerProductionLevel);
|
||||
const auto overIt = moduleLevelOverrides.find(pm.moduleId);
|
||||
const double mx = static_cast<double>(
|
||||
overIt != moduleLevelOverrides.end() ? overIt->second : modDef->playerProductionLevel);
|
||||
|
||||
if (modDef->weaponCapability)
|
||||
{
|
||||
@@ -176,7 +179,9 @@ entt::entity ShipSystem::spawn(const std::string& schematicId, int level,
|
||||
const ModuleDef* modDef = findModuleDef(pm.moduleId);
|
||||
if (!modDef) { throw std::runtime_error("unknown module id '" + pm.moduleId + "'"); }
|
||||
|
||||
const double mx = static_cast<double>(modDef->playerProductionLevel);
|
||||
const auto overIt2 = moduleLevelOverrides.find(pm.moduleId);
|
||||
const double mx = static_cast<double>(
|
||||
overIt2 != moduleLevelOverrides.end() ? overIt2->second : modDef->playerProductionLevel);
|
||||
|
||||
for (const ModuleStatModifier& sm : modDef->statModifiers)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
@@ -19,7 +20,8 @@ public:
|
||||
|
||||
entt::entity spawn(const std::string& schematicId, int level, QVector2D position,
|
||||
bool isEnemy = false,
|
||||
const std::optional<ShipLayoutConfig>& layout = std::nullopt);
|
||||
const std::optional<ShipLayoutConfig>& layout = std::nullopt,
|
||||
const std::map<std::string, int>& moduleLevelOverrides = {});
|
||||
void despawn(entt::entity entity);
|
||||
|
||||
// Reset all movement intents to priority 0 before behavior systems run.
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
ShipStats calculateShipStats(const GameConfig& config,
|
||||
const std::string& shipId,
|
||||
int level,
|
||||
const std::vector<PlacedModule>& modules)
|
||||
const std::vector<PlacedModule>& modules,
|
||||
const std::map<std::string, int>& moduleLevelOverrides)
|
||||
{
|
||||
ShipStats result{};
|
||||
|
||||
@@ -70,7 +71,9 @@ ShipStats calculateShipStats(const GameConfig& config,
|
||||
const ModuleDef* def = findModuleDef(pm.moduleId);
|
||||
if (!def) { throw std::runtime_error("unknown module id '" + pm.moduleId + "'"); }
|
||||
|
||||
const double mx = static_cast<double>(def->playerProductionLevel);
|
||||
const auto overIt = moduleLevelOverrides.find(pm.moduleId);
|
||||
const double mx = static_cast<double>(
|
||||
overIt != moduleLevelOverrides.end() ? overIt->second : def->playerProductionLevel);
|
||||
|
||||
if (def->weaponCapability)
|
||||
{
|
||||
@@ -108,7 +111,9 @@ ShipStats calculateShipStats(const GameConfig& config,
|
||||
const ModuleDef* def = findModuleDef(pm.moduleId);
|
||||
if (!def) { throw std::runtime_error("unknown module id '" + pm.moduleId + "'"); }
|
||||
|
||||
const double mx = static_cast<double>(def->playerProductionLevel);
|
||||
const auto overIt = moduleLevelOverrides.find(pm.moduleId);
|
||||
const double mx = static_cast<double>(
|
||||
overIt != moduleLevelOverrides.end() ? overIt->second : def->playerProductionLevel);
|
||||
|
||||
for (const ModuleStatModifier& sm : def->statModifiers)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -50,7 +51,8 @@ struct ShipStats
|
||||
ShipStats calculateShipStats(const GameConfig& config,
|
||||
const std::string& shipId,
|
||||
int level,
|
||||
const std::vector<PlacedModule>& modules);
|
||||
const std::vector<PlacedModule>& modules,
|
||||
const std::map<std::string, int>& moduleLevelOverrides = {});
|
||||
|
||||
ShipStats buildShipStatsFromEntity(const EntityAdmin& admin, entt::entity shipEntity);
|
||||
|
||||
|
||||
@@ -51,7 +51,13 @@ Simulation::Simulation(GameConfig config, unsigned int seed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_shipSystem->spawn(id, it->second.level, pos, /*isEnemy=*/false, layout);
|
||||
std::map<std::string, int> moduleLevels;
|
||||
for (const auto& [mId, mState] : m_moduleSchematicLevels)
|
||||
{
|
||||
moduleLevels[mId] = mState.level;
|
||||
}
|
||||
m_shipSystem->spawn(id, it->second.level, pos, /*isEnemy=*/false, layout,
|
||||
moduleLevels);
|
||||
},
|
||||
m_rng);
|
||||
m_shipSystem = std::make_unique<ShipSystem>(m_config, m_admin);
|
||||
@@ -62,7 +68,7 @@ Simulation::Simulation(GameConfig config, unsigned int seed)
|
||||
m_waveSystem = std::make_unique<WaveSystem>(m_config, m_rng);
|
||||
m_combatSystem = std::make_unique<CombatSystem>(m_config);
|
||||
|
||||
// Initialize schematic unlock state.
|
||||
// Initialize ship schematic unlock state.
|
||||
for (const ShipDef& def : m_config.ships.ships)
|
||||
{
|
||||
SchematicState state;
|
||||
@@ -71,6 +77,15 @@ Simulation::Simulation(GameConfig config, unsigned int seed)
|
||||
m_schematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
// Initialize module schematic unlock state.
|
||||
for (const ModuleDef& def : m_config.modules.modules)
|
||||
{
|
||||
SchematicState state;
|
||||
state.unlocked = (def.unlockAtStationLevel == -1);
|
||||
state.level = (def.unlockAtStationLevel == -1) ? def.playerProductionLevel : 0;
|
||||
m_moduleSchematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
placeInitialStructures();
|
||||
registerForEvents();
|
||||
}
|
||||
@@ -124,7 +139,13 @@ void Simulation::reset(unsigned int seed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_shipSystem->spawn(id, it->second.level, pos, /*isEnemy=*/false, layout);
|
||||
std::map<std::string, int> moduleLevels;
|
||||
for (const auto& [mId, mState] : m_moduleSchematicLevels)
|
||||
{
|
||||
moduleLevels[mId] = mState.level;
|
||||
}
|
||||
m_shipSystem->spawn(id, it->second.level, pos, /*isEnemy=*/false, layout,
|
||||
moduleLevels);
|
||||
},
|
||||
m_rng);
|
||||
m_shipSystem = std::make_unique<ShipSystem>(m_config, m_admin);
|
||||
@@ -144,6 +165,15 @@ void Simulation::reset(unsigned int seed)
|
||||
m_schematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
m_moduleSchematicLevels.clear();
|
||||
for (const ModuleDef& def : m_config.modules.modules)
|
||||
{
|
||||
SchematicState state;
|
||||
state.unlocked = (def.unlockAtStationLevel == -1);
|
||||
state.level = (def.unlockAtStationLevel == -1) ? def.playerProductionLevel : 0;
|
||||
m_moduleSchematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
placeInitialStructures();
|
||||
}
|
||||
|
||||
@@ -482,28 +512,37 @@ void Simulation::tickDeathsAndLoot()
|
||||
|
||||
void Simulation::awardSchematicDrop(int destroyedStationLevel)
|
||||
{
|
||||
std::vector<std::string> ids;
|
||||
ids.reserve(m_config.ships.ships.size());
|
||||
std::vector<std::pair<std::string, bool>> pool; // (id, isModule)
|
||||
for (const ShipDef& def : m_config.ships.ships)
|
||||
{
|
||||
if (def.unlockAtStationLevel == -1 || def.unlockAtStationLevel <= destroyedStationLevel)
|
||||
{
|
||||
ids.push_back(def.id);
|
||||
pool.push_back({def.id, false});
|
||||
}
|
||||
}
|
||||
for (const ModuleDef& def : m_config.modules.modules)
|
||||
{
|
||||
if (def.unlockAtStationLevel == -1 || def.unlockAtStationLevel <= destroyedStationLevel)
|
||||
{
|
||||
pool.push_back({def.id, true});
|
||||
}
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, static_cast<int>(ids.size()) - 1);
|
||||
const std::string chosen = ids[static_cast<std::size_t>(dist(m_rng))];
|
||||
std::uniform_int_distribution<int> dist(0, static_cast<int>(pool.size()) - 1);
|
||||
const auto& [chosen, isModule] = pool[static_cast<std::size_t>(dist(m_rng))];
|
||||
|
||||
SchematicState& state = m_schematicLevels.at(chosen);
|
||||
SchematicState& state = isModule
|
||||
? m_moduleSchematicLevels.at(chosen)
|
||||
: m_schematicLevels.at(chosen);
|
||||
const bool wasNew = !state.unlocked;
|
||||
state.unlocked = true;
|
||||
state.level += 1;
|
||||
|
||||
SchematicDropEvent evt;
|
||||
evt.schematicId = chosen;
|
||||
evt.newLevel = state.level;
|
||||
evt.wasNewUnlock = wasNew;
|
||||
evt.schematicId = chosen;
|
||||
evt.newLevel = state.level;
|
||||
evt.wasNewUnlock = wasNew;
|
||||
evt.isModuleSchematic = isModule;
|
||||
m_schematicDropEvents.push_back(evt);
|
||||
}
|
||||
|
||||
@@ -586,6 +625,28 @@ bool Simulation::isSchematicUnlocked(const std::string& shipId) const
|
||||
return it->second.unlocked;
|
||||
}
|
||||
|
||||
int Simulation::moduleSchematicLevel(const std::string& moduleId) const
|
||||
{
|
||||
const std::map<std::string, SchematicState>::const_iterator it =
|
||||
m_moduleSchematicLevels.find(moduleId);
|
||||
if (it == m_moduleSchematicLevels.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return it->second.level;
|
||||
}
|
||||
|
||||
bool Simulation::isModuleSchematicUnlocked(const std::string& moduleId) const
|
||||
{
|
||||
const std::map<std::string, SchematicState>::const_iterator it =
|
||||
m_moduleSchematicLevels.find(moduleId);
|
||||
if (it == m_moduleSchematicLevels.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return it->second.unlocked;
|
||||
}
|
||||
|
||||
BuildingId Simulation::tryPlaceBuilding(BuildingType type, QPoint anchor, Rotation rotation)
|
||||
{
|
||||
int cost = 0;
|
||||
|
||||
@@ -62,10 +62,14 @@ public:
|
||||
Tick bossCountdownTicks() const;
|
||||
Tick normalGapRemainingTicks() const;
|
||||
|
||||
// Schematic state queries.
|
||||
// Ship schematic state queries.
|
||||
int schematicLevel(const std::string& shipId) const;
|
||||
bool isSchematicUnlocked(const std::string& shipId) const;
|
||||
|
||||
// Module schematic state queries.
|
||||
int moduleSchematicLevel(const std::string& moduleId) const;
|
||||
bool isModuleSchematicUnlocked(const std::string& moduleId) const;
|
||||
|
||||
// Checks affordability, deducts building blocks, and places the building.
|
||||
// Returns the new entity id, or kInvalidBuildingId if blocks are insufficient.
|
||||
BuildingId tryPlaceBuilding(BuildingType type, QPoint anchor, Rotation rotation);
|
||||
@@ -125,6 +129,7 @@ private:
|
||||
int level;
|
||||
};
|
||||
std::map<std::string, SchematicState> m_schematicLevels;
|
||||
std::map<std::string, SchematicState> m_moduleSchematicLevels;
|
||||
|
||||
EntityAdmin m_admin;
|
||||
BeltSystem m_beltSystem;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "ShipSystem.h"
|
||||
#include "StationBodyComponent.h"
|
||||
#include "WeaponComponent.h"
|
||||
#include "ModulesConfig.h"
|
||||
#include "ShipsConfig.h"
|
||||
#include "Simulation.h"
|
||||
#include "Tick.h"
|
||||
#include "WaveSystem.h"
|
||||
@@ -278,10 +280,13 @@ TEST_CASE("WaveSystem: push schematic drop awards a known ship id", "[wave]")
|
||||
bool validId = false;
|
||||
for (const ShipDef& def : sim.config().ships.ships)
|
||||
{
|
||||
if (def.id == events[0].schematicId)
|
||||
if (def.id == events[0].schematicId) { validId = true; break; }
|
||||
}
|
||||
if (!validId)
|
||||
{
|
||||
for (const ModuleDef& def : sim.config().modules.modules)
|
||||
{
|
||||
validId = true;
|
||||
break;
|
||||
if (def.id == events[0].schematicId) { validId = true; break; }
|
||||
}
|
||||
}
|
||||
REQUIRE(validId);
|
||||
|
||||
@@ -194,16 +194,19 @@ void GameWorldView::onFrame()
|
||||
m_sim->drainSchematicDropEvents();
|
||||
for (const SchematicDropEvent& ev : drops)
|
||||
{
|
||||
const QString shipName = toDisplayName(ev.schematicId);
|
||||
const QString name = toDisplayName(ev.schematicId);
|
||||
ToastEntry toast;
|
||||
if (ev.wasNewUnlock)
|
||||
if (ev.isModuleSchematic)
|
||||
{
|
||||
toast.text = "Schematic unlocked: " + shipName;
|
||||
toast.text = ev.wasNewUnlock
|
||||
? tr("Module unlocked: ") + name
|
||||
: name + tr(" production level -> ") + QString::number(ev.newLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
toast.text = shipName + " production level -> "
|
||||
+ QString::number(ev.newLevel);
|
||||
toast.text = ev.wasNewUnlock
|
||||
? tr("Schematic unlocked: ") + name
|
||||
: name + tr(" production level -> ") + QString::number(ev.newLevel);
|
||||
}
|
||||
toast.createdWallMs = m_wallMs;
|
||||
m_toasts.push_back(toast);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCloseEvent>
|
||||
#include <QFile>
|
||||
@@ -233,8 +236,22 @@ void MainWindow::onLayoutDialogRequested(BuildingId shipyardId)
|
||||
currentLayout = *b->shipLayout;
|
||||
}
|
||||
|
||||
std::set<std::string> unlockedModuleIds;
|
||||
std::map<std::string, int> moduleLevels;
|
||||
for (const ModuleDef& def : m_sim->config().modules.modules)
|
||||
{
|
||||
if (m_sim->isModuleSchematicUnlocked(def.id))
|
||||
{
|
||||
unlockedModuleIds.insert(def.id);
|
||||
}
|
||||
moduleLevels[def.id] = m_sim->moduleSchematicLevel(def.id);
|
||||
}
|
||||
|
||||
ShipLayoutDialog dialog(&m_sim->config(), b->recipeId, currentLayout,
|
||||
m_layoutBlueprints, this);
|
||||
m_layoutBlueprints,
|
||||
std::move(unlockedModuleIds),
|
||||
std::move(moduleLevels),
|
||||
this);
|
||||
if (dialog.exec() == QDialog::Accepted && dialog.result().has_value())
|
||||
{
|
||||
m_sim->buildings().setShipLayout(shipyardId, *dialog.result());
|
||||
|
||||
@@ -387,10 +387,14 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
const std::string& shipId,
|
||||
const ShipLayoutConfig& currentLayout,
|
||||
std::vector<ShipLayoutBlueprint>& allBlueprints,
|
||||
std::set<std::string> unlockedModuleIds,
|
||||
std::map<std::string, int> moduleLevels,
|
||||
QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_config(config)
|
||||
, m_shipId(shipId)
|
||||
, m_unlockedModuleIds(std::move(unlockedModuleIds))
|
||||
, m_moduleLevels(std::move(moduleLevels))
|
||||
, m_rows(0)
|
||||
, m_cols(0)
|
||||
, m_placedModules(currentLayout.placedModules)
|
||||
@@ -469,6 +473,11 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
for (int i = 0; i < static_cast<int>(config->modules.modules.size()); ++i)
|
||||
{
|
||||
const ModuleDef& def = config->modules.modules[i];
|
||||
if (m_unlockedModuleIds.count(def.id) == 0)
|
||||
{
|
||||
m_moduleButtons.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
const QString label = displayName(def.id)
|
||||
+ "\n" + QString::fromStdString(def.glyph);
|
||||
QPushButton* btn = new QPushButton(label, this);
|
||||
@@ -509,7 +518,7 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
{
|
||||
for (QPushButton* btn : m_moduleButtons)
|
||||
{
|
||||
btn->setChecked(false);
|
||||
if (btn) { btn->setChecked(false); }
|
||||
}
|
||||
m_activeModuleIndex = -1;
|
||||
m_removeButton->setChecked(true);
|
||||
@@ -628,14 +637,14 @@ void ShipLayoutDialog::onModuleButtonClicked(int index)
|
||||
{
|
||||
if (m_activeModuleIndex == index)
|
||||
{
|
||||
m_moduleButtons[index]->setChecked(false);
|
||||
if (m_moduleButtons[index]) { m_moduleButtons[index]->setChecked(false); }
|
||||
m_activeModuleIndex = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(m_moduleButtons.size()); ++i)
|
||||
{
|
||||
m_moduleButtons[i]->setChecked(i == index);
|
||||
if (m_moduleButtons[i]) { m_moduleButtons[i]->setChecked(i == index); }
|
||||
}
|
||||
m_removeButton->setChecked(false);
|
||||
m_activeModuleIndex = index;
|
||||
@@ -717,7 +726,7 @@ void ShipLayoutDialog::updateStats()
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_statsPanel->refresh(m_shipId, level, m_placedModules);
|
||||
m_statsPanel->refresh(m_shipId, level, m_placedModules, m_moduleLevels);
|
||||
}
|
||||
|
||||
bool ShipLayoutDialog::canPlaceModule(const ModuleDef& def, QPoint position,
|
||||
@@ -779,13 +788,13 @@ void ShipLayoutDialog::loadLayoutBlueprint(const std::vector<PlacedModule>& modu
|
||||
|
||||
for (const PlacedModule& pm : modules)
|
||||
{
|
||||
// Validate module type exists.
|
||||
// Validate module type exists and is unlocked.
|
||||
const ModuleDef* def = nullptr;
|
||||
for (const ModuleDef& d : m_config->modules.modules)
|
||||
{
|
||||
if (d.id == pm.moduleId) { def = &d; break; }
|
||||
}
|
||||
if (!def) { continue; }
|
||||
if (!def || m_unlockedModuleIds.count(def->id) == 0) { continue; }
|
||||
|
||||
const std::vector<std::string> mask = rotatedMask(*def, pm.rotation);
|
||||
bool valid = true;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -24,6 +26,8 @@ public:
|
||||
const std::string& shipId,
|
||||
const ShipLayoutConfig& currentLayout,
|
||||
std::vector<ShipLayoutBlueprint>& allBlueprints,
|
||||
std::set<std::string> unlockedModuleIds,
|
||||
std::map<std::string, int> moduleLevels,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
std::optional<ShipLayoutConfig> result() const;
|
||||
@@ -57,6 +61,8 @@ private:
|
||||
|
||||
const GameConfig* m_config;
|
||||
std::string m_shipId;
|
||||
std::set<std::string> m_unlockedModuleIds;
|
||||
std::map<std::string, int> m_moduleLevels;
|
||||
std::vector<std::string> m_shipLayout;
|
||||
int m_rows;
|
||||
int m_cols;
|
||||
|
||||
@@ -108,9 +108,11 @@ ShipStatsPanel::ShipStatsPanel(const GameConfig* config, QWidget* parent)
|
||||
|
||||
void ShipStatsPanel::refresh(const std::string& shipId,
|
||||
int level,
|
||||
const std::vector<PlacedModule>& modules)
|
||||
const std::vector<PlacedModule>& modules,
|
||||
const std::map<std::string, int>& moduleLevelOverrides)
|
||||
{
|
||||
const ShipStats stats = calculateShipStats(*m_config, shipId, level, modules);
|
||||
const ShipStats stats = calculateShipStats(*m_config, shipId, level, modules,
|
||||
moduleLevelOverrides);
|
||||
const QString hpText = tr("HP: %1").arg(static_cast<int>(stats.hp + 0.5f));
|
||||
applyStats(stats, hpText);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -20,7 +21,8 @@ public:
|
||||
|
||||
void refresh(const std::string& shipId,
|
||||
int level,
|
||||
const std::vector<PlacedModule>& modules);
|
||||
const std::vector<PlacedModule>& modules,
|
||||
const std::map<std::string, int>& moduleLevelOverrides = {});
|
||||
|
||||
void refreshFromLive(const ShipStats& stats, float currentHp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user