add live ship stats panel
This commit is contained in:
@@ -3,6 +3,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TracePrintRequestedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TickAdvancedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBlocksChangedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntitySelectedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/GameSpeedChangedEvent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BossWaveUpdatedEvent.h
|
||||
PARENT_SCOPE
|
||||
|
||||
21
src/lib/eventsystem/event/EntitySelectedEvent.h
Normal file
21
src/lib/eventsystem/event/EntitySelectedEvent.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef ENTITY_SELECTED_EVENT_H
|
||||
#define ENTITY_SELECTED_EVENT_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "entt/entity/entity.hpp"
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
class EntitySelectedEvent : public Event
|
||||
{
|
||||
public:
|
||||
explicit EntitySelectedEvent(std::optional<entt::entity> entity)
|
||||
: entity(entity)
|
||||
{
|
||||
}
|
||||
|
||||
const std::optional<entt::entity> entity;
|
||||
};
|
||||
|
||||
#endif // ENTITY_SELECTED_EVENT_H
|
||||
@@ -5,6 +5,7 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Building.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntityHitTest.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipLayout.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipLayoutBlueprint.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsCalculator.h
|
||||
@@ -18,6 +19,7 @@ SET(SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TickDriver.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BeltSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/EntityHitTest.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsCalculator.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/WaveSystem.cpp
|
||||
PARENT_SCOPE
|
||||
|
||||
56
src/lib/sim/EntityHitTest.cpp
Normal file
56
src/lib/sim/EntityHitTest.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "EntityHitTest.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "EntityAdmin.h"
|
||||
#include "PositionComponent.h"
|
||||
#include "StationBodyComponent.h"
|
||||
#include "HealthComponent.h"
|
||||
|
||||
entt::entity entityAtWorldPos(EntityAdmin& admin, QVector2D worldPos)
|
||||
{
|
||||
const QPoint tile(static_cast<int>(std::floor(worldPos.x())),
|
||||
static_cast<int>(std::floor(worldPos.y())));
|
||||
|
||||
entt::entity stationHit = entt::null;
|
||||
admin.forEach<StationBodyComponent, HealthComponent>(
|
||||
[&](entt::entity entity, const StationBodyComponent& sb, const HealthComponent& h)
|
||||
{
|
||||
if (stationHit != entt::null) { return; }
|
||||
if (h.hp <= 0.0f) { return; }
|
||||
for (const QPoint& cell : sb.bodyCells)
|
||||
{
|
||||
if (cell == tile)
|
||||
{
|
||||
stationHit = entity;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (stationHit != entt::null)
|
||||
{
|
||||
return stationHit;
|
||||
}
|
||||
|
||||
constexpr float kShipHitRadiusSquared = 0.5f * 0.5f;
|
||||
entt::entity bestShip = entt::null;
|
||||
float bestDistSquared = kShipHitRadiusSquared;
|
||||
|
||||
admin.forEach<PositionComponent, HealthComponent>(
|
||||
[&](entt::entity entity, const PositionComponent& pos, const HealthComponent& h)
|
||||
{
|
||||
if (h.hp <= 0.0f) { return; }
|
||||
if (admin.hasAll<StationBodyComponent>(entity)) { return; }
|
||||
const float dx = pos.value.x() - worldPos.x();
|
||||
const float dy = pos.value.y() - worldPos.y();
|
||||
const float distSquared = dx * dx + dy * dy;
|
||||
if (distSquared < bestDistSquared)
|
||||
{
|
||||
bestDistSquared = distSquared;
|
||||
bestShip = entity;
|
||||
}
|
||||
});
|
||||
|
||||
return bestShip;
|
||||
}
|
||||
9
src/lib/sim/EntityHitTest.h
Normal file
9
src/lib/sim/EntityHitTest.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <QVector2D>
|
||||
|
||||
#include "entt/entity/entity.hpp"
|
||||
|
||||
class EntityAdmin;
|
||||
|
||||
entt::entity entityAtWorldPos(EntityAdmin& admin, QVector2D worldPos);
|
||||
@@ -3,6 +3,16 @@
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "DynamicBodyComponent.h"
|
||||
#include "EntityAdmin.h"
|
||||
#include "HealthComponent.h"
|
||||
#include "ModuleOwnerComponent.h"
|
||||
#include "RepairToolComponent.h"
|
||||
#include "SalvageCargoComponent.h"
|
||||
#include "SensorRangeComponent.h"
|
||||
#include "Tick.h"
|
||||
#include "WeaponComponent.h"
|
||||
|
||||
ShipStats calculateShipStats(const GameConfig& config,
|
||||
const std::string& shipId,
|
||||
int level,
|
||||
@@ -216,3 +226,68 @@ ShipStats calculateShipStats(const GameConfig& config,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ShipStats buildShipStatsFromEntity(const EntityAdmin& admin, entt::entity shipEntity)
|
||||
{
|
||||
ShipStats result{};
|
||||
|
||||
const HealthComponent& health = admin.get<HealthComponent>(shipEntity);
|
||||
const DynamicBodyComponent& body = admin.get<DynamicBodyComponent>(shipEntity);
|
||||
const SensorRangeComponent& sensor = admin.get<SensorRangeComponent>(shipEntity);
|
||||
|
||||
result.hp = health.maxHp;
|
||||
result.maxSpeed_tps = body.maxSpeed_tpt * kTickRateHz;
|
||||
result.sensorRange_tiles = sensor.value_tiles;
|
||||
result.mainAcceleration_tpss = body.mainAcceleration_tptt * kTickRateHz * kTickRateHz;
|
||||
result.maneuveringAcceleration_tpss = body.maneuveringAcceleration_tptt * kTickRateHz * kTickRateHz;
|
||||
result.angularAcceleration_radpss = body.maxAngularAcceleration_rptt * kTickRateHz * kTickRateHz;
|
||||
result.maxRotationSpeed_radps = body.maxRotationSpeed_rpt * kTickRateHz;
|
||||
|
||||
float weaponDps = 0.0f;
|
||||
float weaponMaxRange = 0.0f;
|
||||
bool hasWeapons = false;
|
||||
|
||||
float salvageRate = 0.0f;
|
||||
float salvageMaxRange = 0.0f;
|
||||
bool hasSalvage = false;
|
||||
|
||||
float repairRate = 0.0f;
|
||||
float repairMaxRange = 0.0f;
|
||||
bool hasRepair = false;
|
||||
|
||||
admin.forEach<ModuleOwnerComponent, WeaponComponent>(
|
||||
[&](entt::entity /*child*/, const ModuleOwnerComponent& owner, const WeaponComponent& w)
|
||||
{
|
||||
if (owner.owner != shipEntity) { return; }
|
||||
hasWeapons = true;
|
||||
weaponDps += w.damage * w.fireRateHz;
|
||||
if (w.range_tiles > weaponMaxRange) { weaponMaxRange = w.range_tiles; }
|
||||
});
|
||||
|
||||
admin.forEach<ModuleOwnerComponent, SalvageCargoComponent>(
|
||||
[&](entt::entity /*child*/, const ModuleOwnerComponent& owner, const SalvageCargoComponent& s)
|
||||
{
|
||||
if (owner.owner != shipEntity) { return; }
|
||||
hasSalvage = true;
|
||||
const float rate = (s.collectionIntervalTicks > 0)
|
||||
? static_cast<float>(kTickRateHz) / static_cast<float>(s.collectionIntervalTicks)
|
||||
: 0.0f;
|
||||
salvageRate += rate;
|
||||
if (s.collectionRange_tiles > salvageMaxRange) { salvageMaxRange = s.collectionRange_tiles; }
|
||||
});
|
||||
|
||||
admin.forEach<ModuleOwnerComponent, RepairToolComponent>(
|
||||
[&](entt::entity /*child*/, const ModuleOwnerComponent& owner, const RepairToolComponent& r)
|
||||
{
|
||||
if (owner.owner != shipEntity) { return; }
|
||||
hasRepair = true;
|
||||
repairRate += r.ratePerTick * kTickRateHz;
|
||||
if (r.range_tiles > repairMaxRange) { repairMaxRange = r.range_tiles; }
|
||||
});
|
||||
|
||||
if (hasWeapons) { result.weapons = ShipStats::WeaponStats{weaponDps, weaponMaxRange}; }
|
||||
if (hasSalvage) { result.salvage = ShipStats::SalvageStats{salvageRate, salvageMaxRange}; }
|
||||
if (hasRepair) { result.repair = ShipStats::RepairStats{repairRate, repairMaxRange}; }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "entt/entity/entity.hpp"
|
||||
|
||||
#include "GameConfig.h"
|
||||
#include "ShipLayout.h"
|
||||
|
||||
class EntityAdmin;
|
||||
|
||||
// Effective stats for a ship with a given layout, after applying all passive
|
||||
// module modifiers per REQ-MOD-STAT-CALC. Values are in display units:
|
||||
// speeds in tiles/s, ranges in tiles, accelerations in tiles/s² or rad/s².
|
||||
@@ -47,3 +51,6 @@ ShipStats calculateShipStats(const GameConfig& config,
|
||||
const std::string& shipId,
|
||||
int level,
|
||||
const std::vector<PlacedModule>& modules);
|
||||
|
||||
ShipStats buildShipStatsFromEntity(const EntityAdmin& admin, entt::entity shipEntity);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user