Files
dota_factory/src/ui/ShipStatsPanel.cpp

177 lines
6.5 KiB
C++

#include "ShipStatsPanel.h"
#include <QString>
#include <QVBoxLayout>
#include "BarRow.h"
#include "GameConfig.h"
#include "SectionBox.h"
#include "SelectionNames.h"
#include "ShipStatsCalculator.h"
#include "StatRow.h"
#include "ThreatCostCalculator.h"
namespace
{
QString fmt(float value)
{
return QString::number(static_cast<double>(value), 'f', 1);
}
} // namespace
ShipStatsPanel::ShipStatsPanel(const GameConfig* config, QWidget* parent)
: QWidget(parent)
, m_config(config)
{
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(2);
layout->setAlignment(Qt::AlignTop);
// Hull stats -- always visible, except cargo capacity, which only a ship that can
// carry anything shows (REQ-MOD-UI-STATS-PANEL).
m_hpBar = new BarRow(tr("HP"), this);
m_speedRow = new StatRow(tr("Max speed"), this);
m_sensorRangeRow = new StatRow(tr("Sensor range"), this);
m_mainAccelRow = new StatRow(tr("Main accel"), this);
m_maneuveringAccelRow = new StatRow(tr("Maneuvering accel"), this);
m_angularAccelRow = new StatRow(tr("Angular accel"), this);
m_maxRotSpeedRow = new StatRow(tr("Max rotation"), this);
m_cargoCapacityRow = new StatRow(tr("Cargo capacity"), this);
m_cargoCapacityRow->hide();
layout->addWidget(m_hpBar);
layout->addWidget(m_speedRow);
layout->addWidget(m_sensorRangeRow);
layout->addWidget(m_mainAccelRow);
layout->addWidget(m_maneuveringAccelRow);
layout->addWidget(m_angularAccelRow);
layout->addWidget(m_maxRotSpeedRow);
layout->addWidget(m_cargoCapacityRow);
// One section per capability module type, each shown only while at least one such
// module is installed (REQ-MOD-UI-STATS-PANEL).
m_weaponSection = new SectionBox(tr("Weapons"), this);
m_weaponDpsRow = new StatRow(tr("DPS"), m_weaponSection);
m_weaponRangeRow = new StatRow(tr("Range"), m_weaponSection);
m_weaponSection->getContentLayout()->addWidget(m_weaponDpsRow);
m_weaponSection->getContentLayout()->addWidget(m_weaponRangeRow);
m_weaponSection->hide();
layout->addWidget(m_weaponSection);
m_salvageSection = new SectionBox(tr("Salvage"), this);
m_salvageRateRow = new StatRow(tr("Collection rate"), m_salvageSection);
m_salvageRangeRow = new StatRow(tr("Range"), m_salvageSection);
m_salvageSection->getContentLayout()->addWidget(m_salvageRateRow);
m_salvageSection->getContentLayout()->addWidget(m_salvageRangeRow);
m_salvageSection->hide();
layout->addWidget(m_salvageSection);
m_repairSection = new SectionBox(tr("Repair"), this);
m_repairRateRow = new StatRow(tr("Repair rate"), m_repairSection);
m_repairRangeRow = new StatRow(tr("Range"), m_repairSection);
m_repairSection->getContentLayout()->addWidget(m_repairRateRow);
m_repairSection->getContentLayout()->addWidget(m_repairRangeRow);
m_repairSection->hide();
layout->addWidget(m_repairSection);
// Live entities only; the design preview has no behavior to show
// (REQ-UI-SHIP-BEHAVIOR).
m_behaviorRow = new StatRow(tr("Behavior"), this);
m_behaviorRow->hide();
layout->addWidget(m_behaviorRow);
// Threat cost -- shown only while debug draw is active (REQ-UI-SHIP-STATS-PANEL).
m_threatCostRow = new StatRow(tr("Threat cost"), this);
m_threatCostRow->hide();
layout->addWidget(m_threatCostRow);
}
void ShipStatsPanel::setBehavior(BehaviorKind kind)
{
const QString label = getBehaviorLabel(kind);
m_behaviorRow->setValue(label);
m_behaviorRow->setVisible(!label.isEmpty());
}
void ShipStatsPanel::refresh(const std::string& shipId,
const std::vector<PlacedModule>& modules)
{
const ShipStats stats = calculateShipStats(*m_config, shipId, modules);
applyStats(stats, 1.0, QString::number(static_cast<int>(stats.hp + 0.5f)));
setThreatCost(calculateShipThreatCost(m_config->threatCosts, *m_config,
shipId, modules));
}
void ShipStatsPanel::refreshFromLive(const ShipStats& stats, float currentHp)
{
const double fraction = (stats.hp > 0.0f)
? static_cast<double>(currentHp) / stats.hp
: 0.0;
applyStats(stats, fraction, tr("%1 / %2")
.arg(static_cast<int>(currentHp + 0.5f))
.arg(static_cast<int>(stats.hp + 0.5f)));
}
void ShipStatsPanel::applyStats(const ShipStats& stats, double hpFraction,
const QString& hpText)
{
m_hpBar->setValue(hpFraction, hpText);
m_speedRow->setValue(tr("%1 tiles/s").arg(fmt(stats.maxSpeed_tps)));
m_sensorRangeRow->setValue(tr("%1 tiles").arg(fmt(stats.sensorRange_tiles)));
m_mainAccelRow->setValue(
tr("%1 tiles/s\xc2\xb2").arg(fmt(stats.mainAcceleration_tpss)));
m_maneuveringAccelRow->setValue(
tr("%1 tiles/s\xc2\xb2").arg(fmt(stats.maneuveringAcceleration_tpss)));
m_angularAccelRow->setValue(
tr("%1 rad/s\xc2\xb2").arg(fmt(stats.angularAcceleration_radpss)));
m_maxRotSpeedRow->setValue(tr("%1 rad/s").arg(fmt(stats.maxRotationSpeed_radps)));
// Cargo capacity is shown only when the ship can actually hold cargo
// (REQ-MOD-UI-STATS-PANEL).
m_cargoCapacityRow->setVisible(stats.cargoCapacity > 0);
if (stats.cargoCapacity > 0)
{
m_cargoCapacityRow->setValue(QString::number(stats.cargoCapacity));
}
m_weaponSection->setVisible(stats.weapons.has_value());
if (stats.weapons.has_value())
{
m_weaponDpsRow->setValue(fmt(stats.weapons->combinedDps));
m_weaponRangeRow->setValue(tr("%1 tiles").arg(fmt(stats.weapons->maxRange_tiles)));
}
m_salvageSection->setVisible(stats.salvage.has_value());
if (stats.salvage.has_value())
{
m_salvageRateRow->setValue(
tr("%1 /s").arg(fmt(stats.salvage->combinedCollectionRate)));
m_salvageRangeRow->setValue(tr("%1 tiles").arg(fmt(stats.salvage->maxRange_tiles)));
}
m_repairSection->setVisible(stats.repair.has_value());
if (stats.repair.has_value())
{
m_repairRateRow->setValue(
tr("%1 HP/s").arg(fmt(stats.repair->combinedRepairRate_hps)));
m_repairRangeRow->setValue(tr("%1 tiles").arg(fmt(stats.repair->maxRange_tiles)));
}
}
void ShipStatsPanel::setThreatCost(double cost)
{
m_threatCostRow->setValue(QString::number(cost, 'f', 1));
m_threatCostRow->setVisible(m_debugDraw);
}
void ShipStatsPanel::setDebugDrawEnabled(bool enabled)
{
m_debugDraw = enabled;
m_threatCostRow->setVisible(m_debugDraw);
}