Implements the requirements rename in the codebase. The salvageable object dropped by destroyed ships and defence stations is now the "debris" entity; the scrap resource it yields (cargo, delivery, smelting, threat, scrap_drop_formula, scrap_per_threat) is unchanged. Entity renames: ScrapDataComponent->DebrisComponent, ScrapSystem->DebrisSystem, ScrapInfo->DebrisInfo, ScrapSelectionChangedEvent->DebrisSelectionChangedEvent (member scrap->debris), spawnScrap->spawnDebris, getScraps->getDebrisSystem, getAllScrapInfo->getAllDebrisInfo, scrapAtWorldPos/scrapInBox->debris*, SalvageScrapBehavior::scrapTarget->debrisTarget, PendingCollection::scrap->debris, ScrapTest.cpp->DebrisTest.cpp. Config key scrap_despawn_seconds-> debris_despawn_seconds (WorldConfig.scrapDespawnSeconds->debrisDespawnSeconds). The salvage/deliver behavior classes keep their names (they act on the scrap resource). Also implements the new REQ-UI-DEBRIS-PANEL behavior in SelectedBuildingPanel: a single selected piece of debris shows a "Debris" heading plus a "Scrap" stat row; a multi/mixed field selection appends "Debris x N" and "Scrap x N" lines. Updates the four renamed REQ-ID references in comments/docs, plus architecture.md and derived.md. All 449 test cases pass; app, tests, and balancing targets build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y7N59FsLA5e2kuVdqe4Uhc
140 lines
4.0 KiB
C++
140 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <random>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "BalancingConfig.h"
|
|
#include "BeltSystem.h"
|
|
#include "EntityAdmin.h"
|
|
#include "BuildingId.h"
|
|
|
|
#include "entt/entity/entity.hpp"
|
|
#include "BeamFiredEvent.h"
|
|
#include "GameConfig.h"
|
|
#include "Tick.h"
|
|
|
|
class AiSystem;
|
|
class BuildingSystem;
|
|
class CombatSystem;
|
|
class DynamicBodySystem;
|
|
class MovementIntentSystem;
|
|
class RepairSystem;
|
|
class SalvagerSystem;
|
|
class ShipSystem;
|
|
class DebrisSystem;
|
|
|
|
struct ArenaStatus
|
|
{
|
|
struct Entry
|
|
{
|
|
std::string displayName;
|
|
// Level suffix shown in the widget/inspect display. Set for the HQ and
|
|
// defence stations; empty for ships, which no longer have a level.
|
|
std::optional<int> level;
|
|
int total;
|
|
int surviving;
|
|
};
|
|
|
|
struct TeamStatus
|
|
{
|
|
std::string name;
|
|
double threatLevel = 0.0; // accumulated threat of the team's configured ships
|
|
// Remaining durability of the team's ships and defence stations (HQ
|
|
// excluded). currentEhp is summed live; maxEhp is the fixed full-HP
|
|
// baseline. See getEhpPercentText() for the displayed value.
|
|
double currentEhp = 0.0;
|
|
double maxEhp = 0.0;
|
|
std::vector<Entry> entries; // HQ first, then ships, then stations
|
|
|
|
// Remaining EHP as a whole-number percentage ("NN%"), or "n/a" when the
|
|
// team has no ships or stations (maxEhp == 0).
|
|
std::string getEhpPercentText() const;
|
|
};
|
|
|
|
TeamStatus teams[2];
|
|
bool finished = false;
|
|
std::optional<int> winnerTeam; // 0 or 1 when finished; nullopt while running
|
|
// Game time the fight has lasted (simulated ticks * fixed tick duration).
|
|
// Meaningful once finished; the battle duration shown for completed runs.
|
|
double durationSeconds = 0.0;
|
|
};
|
|
|
|
class ArenaSimulation
|
|
{
|
|
public:
|
|
ArenaSimulation(const GameConfig& gameConfig,
|
|
ArenaConfig arenaConfig,
|
|
unsigned int seed = 0);
|
|
~ArenaSimulation();
|
|
|
|
void run();
|
|
void requestStop();
|
|
|
|
void tickOnce();
|
|
std::vector<BeamFiredEvent> drainBeamFiredEvents();
|
|
|
|
ArenaStatus getStatus() const;
|
|
bool isFinished() const;
|
|
std::optional<int> getWinnerTeam() const;
|
|
Tick getCurrentTick() const;
|
|
|
|
const ArenaConfig& getArenaConfig() const;
|
|
const BuildingSystem& getBuildings() const;
|
|
const ShipSystem& getShips() const;
|
|
const DebrisSystem& getDebrisSystem() const;
|
|
EntityAdmin& getAdmin();
|
|
const EntityAdmin& getAdmin() const;
|
|
|
|
private:
|
|
BuildingId allocateBuildingId();
|
|
void placeStructures();
|
|
void spawnShips();
|
|
void computeTeamMaxEhp();
|
|
void tick();
|
|
void tickDeaths();
|
|
void updateStatus();
|
|
|
|
const GameConfig& m_gameConfig;
|
|
ArenaConfig m_arenaConfig;
|
|
std::mt19937 m_rng;
|
|
|
|
Tick m_currentTick;
|
|
BuildingId m_nextBuildingId;
|
|
|
|
EntityAdmin m_admin;
|
|
BeltSystem m_beltSystem;
|
|
std::unique_ptr<BuildingSystem> m_buildingSystem;
|
|
std::unique_ptr<ShipSystem> m_shipSystem;
|
|
std::unique_ptr<AiSystem> m_aiSystem;
|
|
std::unique_ptr<MovementIntentSystem> m_movementIntentSystem;
|
|
std::unique_ptr<DynamicBodySystem> m_dynamicBodySystem;
|
|
std::unique_ptr<CombatSystem> m_combatSystem;
|
|
std::unique_ptr<DebrisSystem> m_debrisSystem;
|
|
std::unique_ptr<SalvagerSystem> m_salvagerSystem;
|
|
std::unique_ptr<RepairSystem> m_repairSystem;
|
|
|
|
entt::entity m_team1HqEntity;
|
|
entt::entity m_team2HqEntity;
|
|
|
|
bool m_finished;
|
|
std::optional<int> m_winnerTeam;
|
|
std::atomic<bool> m_stopRequested;
|
|
|
|
// Static accumulated threat per team, computed once from the configured roster.
|
|
double m_teamThreat[2] = {0.0, 0.0};
|
|
|
|
// Full-HP baseline per team (ships + defence stations, HQ excluded), computed
|
|
// once after spawning; the EHP-percentage denominator.
|
|
double m_teamMaxEhp[2] = {0.0, 0.0};
|
|
|
|
std::vector<BeamFiredEvent> m_beamFiredEvents;
|
|
|
|
mutable std::mutex m_statusMutex;
|
|
ArenaStatus m_status;
|
|
};
|