Compare commits
41 Commits
refactorin
...
1f4503176b
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f4503176b | |||
| fd85e8e10a | |||
| 114a43b205 | |||
| d87d063b10 | |||
| 537597c854 | |||
| 9c3be0fbd0 | |||
| 58b94223f7 | |||
| 1fb63cce4e | |||
| 0b7e94b4e4 | |||
| 0408336cf9 | |||
| 46932e4abf | |||
| 0edea5d961 | |||
| 60cc187d92 | |||
| 3990351a16 | |||
| bd344e4fbe | |||
| 64c344c3a3 | |||
| 02c7fed9b4 | |||
| 5d4a975384 | |||
| 475df0e5fd | |||
| 61634f6fd2 | |||
| c8ff7da345 | |||
| d664ab54cc | |||
| 906000b0e9 | |||
| d9ef6aa728 | |||
| b44a85685e | |||
| edd1c31785 | |||
| 785ce3ebfe | |||
| 7017f8b4dc | |||
| 77a842f884 | |||
| d5ba72d554 | |||
| 83177729e9 | |||
| a8e933b7f2 | |||
| e02e323cb2 | |||
| b4e622daa5 | |||
| 1150985c1f | |||
| 594c3b93c5 | |||
| 932b57720c | |||
| ca727bef35 | |||
| 553a7e0701 | |||
| af6828c348 | |||
| 3671e1d7e6 |
@@ -1,6 +1,3 @@
|
||||
|
||||
|
||||
|
||||
set(TARGET_BASE_NAME "${PRODUCT_NAME}")
|
||||
|
||||
set(TARGET_APP_NAME "${TARGET_BASE_NAME}")
|
||||
|
||||
@@ -324,9 +324,9 @@ void ArenaSimulation::tick()
|
||||
// Ship behavior systems (tick step 7): evaluate, select winner, execute.
|
||||
// Module + combat systems emit their tool beams into a shared buffer.
|
||||
m_shipSystem->clearMovementIntents();
|
||||
m_aiSystem->tick(m_admin, m_factoryState);
|
||||
m_aiSystem->tick(m_admin, m_factoryState, *m_debrisSystem);
|
||||
std::vector<BeamFiredEvent> beamFiredEvents;
|
||||
m_salvagerSystem->tick(m_currentTick, m_factoryState, beamFiredEvents);
|
||||
m_salvagerSystem->tick(m_currentTick, *m_debrisSystem, m_factoryState, beamFiredEvents);
|
||||
m_repairSystem->tick(m_currentTick, beamFiredEvents);
|
||||
|
||||
// Combat resolution (tick step 8).
|
||||
|
||||
@@ -340,7 +340,7 @@ void ArenaView::drawBuildings(QPainter& painter)
|
||||
void ArenaView::drawDebris(QPainter& painter)
|
||||
{
|
||||
const float r = getTilePx() * 0.2f;
|
||||
for (const DebrisInfo& debris : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
for (const DebrisInfo& debris : m_sim->getDebrisSystem().getAllDebrisInfo())
|
||||
{
|
||||
const QPointF center = worldToWidget(debris.position);
|
||||
painter.setBrush(QColor(128, 110, 90));
|
||||
|
||||
@@ -43,7 +43,8 @@ AiSystem::AiSystem(const GameConfig& config)
|
||||
{
|
||||
}
|
||||
|
||||
void AiSystem::tick(EntityAdmin& admin, const FactoryState& state)
|
||||
void AiSystem::tick(EntityAdmin& admin, const FactoryState& state,
|
||||
const DebrisSystem& debris)
|
||||
{
|
||||
TRACE();
|
||||
|
||||
@@ -54,7 +55,7 @@ void AiSystem::tick(EntityAdmin& admin, const FactoryState& state)
|
||||
m_retreatEvaluator.evaluate(admin);
|
||||
m_attackEvaluator.evaluate(admin);
|
||||
m_repairEvaluator.evaluate(admin);
|
||||
m_salvageScrapEvaluator.evaluate(admin);
|
||||
m_salvageScrapEvaluator.evaluate(admin, debris);
|
||||
m_deliverScrapEvaluator.evaluate(admin, state);
|
||||
|
||||
// Phase 2: pick the highest-scoring behavior per ship.
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "StandbyExecutor.h"
|
||||
|
||||
class EntityAdmin;
|
||||
class DebrisSystem;
|
||||
struct GameConfig;
|
||||
|
||||
// Orchestrates ship-behavior decision-making in three batched phases:
|
||||
@@ -34,7 +35,7 @@ class AiSystem
|
||||
public:
|
||||
explicit AiSystem(const GameConfig& config);
|
||||
|
||||
void tick(EntityAdmin& admin, const FactoryState& state);
|
||||
void tick(EntityAdmin& admin, const FactoryState& state, const DebrisSystem& debris);
|
||||
|
||||
private:
|
||||
void selectWinningBehaviors(EntityAdmin& admin);
|
||||
|
||||
@@ -46,13 +46,13 @@ std::optional<int> DebrisSystem::consume(entt::entity entity)
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool collectOne(EntityAdmin& admin, entt::entity entity)
|
||||
bool DebrisSystem::collectOne(entt::entity entity)
|
||||
{
|
||||
if (!admin.isValid(entity) || !admin.hasAll<DebrisComponent>(entity))
|
||||
if (!m_admin.isValid(entity) || !m_admin.hasAll<DebrisComponent>(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DebrisComponent& data = admin.get<DebrisComponent>(entity);
|
||||
DebrisComponent& data = m_admin.get<DebrisComponent>(entity);
|
||||
if (data.amount <= 0)
|
||||
{
|
||||
return false;
|
||||
@@ -60,18 +60,18 @@ bool collectOne(EntityAdmin& admin, entt::entity entity)
|
||||
--data.amount;
|
||||
if (data.amount <= 0)
|
||||
{
|
||||
admin.destroy(entity);
|
||||
m_admin.destroy(entity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<DebrisInfo> getAllDebrisInfo(const EntityAdmin& admin)
|
||||
std::vector<DebrisInfo> DebrisSystem::getAllDebrisInfo() const
|
||||
{
|
||||
std::vector<DebrisInfo> result;
|
||||
admin.forEach<DebrisComponent>(
|
||||
[&result, &admin](entt::entity e, const DebrisComponent& sd)
|
||||
m_admin.forEach<DebrisComponent>(
|
||||
[&result, this](entt::entity e, const DebrisComponent& sd)
|
||||
{
|
||||
result.push_back(DebrisInfo{e, admin.get<PositionComponent>(e).value, sd.amount});
|
||||
result.push_back(DebrisInfo{e, m_admin.get<PositionComponent>(e).value, sd.amount});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,17 +38,9 @@ public:
|
||||
// false if the entity is invalid or already empty (REQ-SHP-SALVAGE).
|
||||
bool collectOne(entt::entity entity);
|
||||
|
||||
// Lightweight snapshot for callers that need to iterate all debris.
|
||||
std::vector<DebrisInfo> getAllDebrisInfo() const;
|
||||
|
||||
private:
|
||||
EntityAdmin& m_admin;
|
||||
};
|
||||
|
||||
// Debris state read and changed straight off the registry — no system needed.
|
||||
|
||||
// Lightweight snapshot for callers that need to iterate all debris.
|
||||
std::vector<DebrisInfo> getAllDebrisInfo(const EntityAdmin& admin);
|
||||
|
||||
// Collects a single scrap unit from the debris: decrements its amount by one,
|
||||
// destroying the entity once depleted. Returns true if a scrap was collected,
|
||||
// false if the entity is invalid or already empty (REQ-SHP-SALVAGE).
|
||||
bool collectOne(EntityAdmin& admin, entt::entity entity);
|
||||
|
||||
@@ -24,14 +24,14 @@ SalvagerSystem::SalvagerSystem(EntityAdmin& admin)
|
||||
{
|
||||
}
|
||||
|
||||
void SalvagerSystem::tick(Tick currentTick, FactoryState& state,
|
||||
void SalvagerSystem::tick(Tick currentTick, DebrisSystem& debris, FactoryState& state,
|
||||
std::vector<BeamFiredEvent>& outBeamFiredEvents)
|
||||
{
|
||||
TRACE();
|
||||
// Apply collections whose mid-beam delay has elapsed (cycles started earlier).
|
||||
applyPendingCollections(currentTick);
|
||||
applyPendingCollections(currentTick, debris);
|
||||
|
||||
const std::vector<DebrisInfo> allDebris = getAllDebrisInfo(m_admin);
|
||||
const std::vector<DebrisInfo> allDebris = debris.getAllDebrisInfo();
|
||||
|
||||
// Tick down per-module collection cooldowns.
|
||||
m_admin.forEach<SalvagerComponent>(
|
||||
@@ -108,7 +108,7 @@ void SalvagerSystem::tick(Tick currentTick, FactoryState& state,
|
||||
});
|
||||
}
|
||||
|
||||
void SalvagerSystem::applyPendingCollections(Tick currentTick)
|
||||
void SalvagerSystem::applyPendingCollections(Tick currentTick, DebrisSystem& debris)
|
||||
{
|
||||
std::vector<PendingCollection>::iterator it = m_pendingCollections.begin();
|
||||
while (it != m_pendingCollections.end())
|
||||
@@ -118,7 +118,7 @@ void SalvagerSystem::applyPendingCollections(Tick currentTick)
|
||||
if (m_admin.isValid(it->ship) && m_admin.hasAll<CargoComponent>(it->ship))
|
||||
{
|
||||
CargoComponent& cargo = m_admin.get<CargoComponent>(it->ship);
|
||||
if (cargo.current < cargo.maxCapacity && collectOne(m_admin, it->debris))
|
||||
if (cargo.current < cargo.maxCapacity && debris.collectOne(it->debris))
|
||||
{
|
||||
++cargo.current;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "entt/entity/entity.hpp"
|
||||
|
||||
class EntityAdmin;
|
||||
class DebrisSystem;
|
||||
|
||||
// World-mutation system for salvage modules: each module runs a collection cycle
|
||||
// on its own cooldown. When a cycle starts it emits a salvage beam toward an
|
||||
@@ -21,7 +22,7 @@ class SalvagerSystem
|
||||
public:
|
||||
explicit SalvagerSystem(EntityAdmin& admin);
|
||||
|
||||
void tick(Tick currentTick, FactoryState& state,
|
||||
void tick(Tick currentTick, DebrisSystem& debris, FactoryState& state,
|
||||
std::vector<BeamFiredEvent>& outBeamFiredEvents);
|
||||
|
||||
private:
|
||||
@@ -32,7 +33,7 @@ private:
|
||||
Tick appliesAt;
|
||||
};
|
||||
|
||||
void applyPendingCollections(Tick currentTick);
|
||||
void applyPendingCollections(Tick currentTick, DebrisSystem& debris);
|
||||
|
||||
EntityAdmin& m_admin;
|
||||
std::vector<PendingCollection> m_pendingCollections;
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#include "SensorRangeComponent.h"
|
||||
#include "tracing.h"
|
||||
|
||||
void SalvageScrapEvaluator::evaluate(EntityAdmin& admin)
|
||||
void SalvageScrapEvaluator::evaluate(EntityAdmin& admin, const DebrisSystem& debris)
|
||||
{
|
||||
TRACE();
|
||||
const std::unordered_map<entt::entity, CargoState> cargoByShip = buildCargoByShip(admin);
|
||||
const std::vector<DebrisInfo> allDebris = getAllDebrisInfo(admin);
|
||||
const std::vector<DebrisInfo> allDebris = debris.getAllDebrisInfo();
|
||||
|
||||
admin.forEach<SalvageScrapBehavior, PositionComponent, SensorRangeComponent>(
|
||||
[&](entt::entity e, SalvageScrapBehavior& salvage, const PositionComponent& pos,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
class EntityAdmin;
|
||||
class DebrisSystem;
|
||||
|
||||
// When cargo is not full, finds the nearest debris within sensor range and sets
|
||||
// it as the target, scoring high. Scores inactive when cargo is full or no debris
|
||||
@@ -8,5 +9,5 @@ class EntityAdmin;
|
||||
class SalvageScrapEvaluator
|
||||
{
|
||||
public:
|
||||
void evaluate(EntityAdmin& admin);
|
||||
void evaluate(EntityAdmin& admin, const DebrisSystem& debris);
|
||||
};
|
||||
|
||||
@@ -181,7 +181,7 @@ int BuildingSystem::deconstruct(FactoryState& state, BuildingId id, Tick current
|
||||
state.deconstructionQueue.push_back(std::move(entry));
|
||||
if (wasEmpty)
|
||||
{
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -189,6 +189,17 @@ int BuildingSystem::deconstruct(FactoryState& state, BuildingId id, Tick current
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BuildingSystem::startFrontDeconstruction(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
if (state.deconstructionQueue.empty()) { return; }
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
front.completesAt =
|
||||
currentTick + secondsToTicks(m_config.world.deconstructionTimeSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Set recipe
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -323,6 +334,53 @@ void BuildingSystem::setSiteSplitterFilters(FactoryState& state, BuildingId id,
|
||||
// Tick hooks
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void BuildingSystem::tickDeconstruction(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
TRACE();
|
||||
if (state.deconstructionQueue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
|
||||
// Guard: if the front entry's timer was never started, start it now.
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTick < front.completesAt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the building from the world and credit its refund (REQ-BLD-DECONSTRUCT).
|
||||
// Belt/tunnel/splitter tiles were already unregistered when the building was
|
||||
// queued (see deconstruct), so only tile occupancy and the record remain.
|
||||
for (std::vector<Building>::iterator it = state.buildings.begin();
|
||||
it != state.buildings.end();
|
||||
++it)
|
||||
{
|
||||
if (it->id != front.id) { continue; }
|
||||
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
state.grid.release(it->bodyCells);
|
||||
state.buildings.erase(it);
|
||||
if (def)
|
||||
{
|
||||
m_addBuildingBlocks(def->cost * m_config.world.refundPercentage / 100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
state.deconstructionQueue.pop_front();
|
||||
|
||||
// Start the next queued deconstruction, if any.
|
||||
startFrontDeconstruction(state, currentTick);
|
||||
}
|
||||
|
||||
void BuildingSystem::cancelDeconstruction(FactoryState& state, BuildingId id)
|
||||
{
|
||||
for (std::deque<DeconstructionEntry>::iterator it = state.deconstructionQueue.begin();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "Building.h"
|
||||
#include "FactoryState.h"
|
||||
#include "BuildingBuffers.h"
|
||||
#include "DeconstructionSystem.h"
|
||||
#include "PlacementRules.h"
|
||||
#include "ProductionRules.h"
|
||||
#include "BuildingType.h"
|
||||
@@ -108,6 +107,7 @@ public:
|
||||
// Advances the deconstruction queue (REQ-BLD-DECON-QUEUE): one building at a
|
||||
// time, in parallel with tickConstruction. Removes the front building and
|
||||
// credits its refund when its timer elapses.
|
||||
void tickDeconstruction(FactoryState& state, Tick currentTick);
|
||||
void tickBeltPull(FactoryState& state);
|
||||
void tickProduction(FactoryState& state, Tick currentTick);
|
||||
void tickShipyardProduction(FactoryState& state, Tick currentTick);
|
||||
@@ -183,6 +183,7 @@ public:
|
||||
private:
|
||||
// Starts the front deconstruction-queue entry's timer if not yet started
|
||||
// (mirrors how tickConstruction starts a queued construction site).
|
||||
void startFrontDeconstruction(FactoryState& state, Tick currentTick);
|
||||
|
||||
// Registers a belt/splitter/tunnel building's tile with the belt subsystem
|
||||
// (on construction completion, or when un-queuing a deconstruction). No-op for
|
||||
|
||||
@@ -14,7 +14,6 @@ SET(HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ConstructionSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DeconstructionSystem.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBuffers.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryState.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryQueries.h
|
||||
@@ -46,7 +45,6 @@ SET(SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingConfig.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingGrid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ConstructionSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DeconstructionSystem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BuildingBuffers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/FactoryQueries.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ProductionRules.cpp
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#include "DeconstructionSystem.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Building.h"
|
||||
#include "tracing.h"
|
||||
|
||||
void startFrontDeconstruction(FactoryState& state, const GameConfig& config,
|
||||
Tick currentTick)
|
||||
{
|
||||
if (state.deconstructionQueue.empty()) { return; }
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
front.completesAt =
|
||||
currentTick + secondsToTicks(config.world.deconstructionTimeSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeconstructionSystem::tick(FactoryState& state, Tick currentTick)
|
||||
{
|
||||
TRACE();
|
||||
if (state.deconstructionQueue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeconstructionEntry& front = state.deconstructionQueue.front();
|
||||
|
||||
// Guard: if the front entry's timer was never started, start it now.
|
||||
if (front.completesAt == 0)
|
||||
{
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTick < front.completesAt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the building from the world and credit its refund (REQ-BLD-DECONSTRUCT).
|
||||
// Belt/tunnel/splitter tiles were already unregistered when the building was
|
||||
// queued (see deconstruct), so only tile occupancy and the record remain.
|
||||
for (std::vector<Building>::iterator it = state.buildings.begin();
|
||||
it != state.buildings.end();
|
||||
++it)
|
||||
{
|
||||
if (it->id != front.id) { continue; }
|
||||
|
||||
const BuildingDef* def = m_config.buildings.findBuildingDef(it->type);
|
||||
state.grid.release(it->bodyCells);
|
||||
state.buildings.erase(it);
|
||||
if (def)
|
||||
{
|
||||
m_addBuildingBlocks(def->cost * m_config.world.refundPercentage / 100);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
state.deconstructionQueue.pop_front();
|
||||
|
||||
// Start the next queued deconstruction, if any.
|
||||
startFrontDeconstruction(state, m_config, currentTick);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "FactoryState.h"
|
||||
#include "GameConfig.h"
|
||||
#include "Tick.h"
|
||||
|
||||
// The queue timer for pending demolitions (REQ-BLD-DECON-QUEUE): one building at a
|
||||
// time, in parallel with construction. When the front entry's timer elapses the
|
||||
// building is removed from the world, its tiles are released, and its partial refund
|
||||
// is credited.
|
||||
//
|
||||
// It needs no BeltSystem: a belt, splitter or tunnel end is unregistered the moment
|
||||
// it is queued (see BuildingSystem::deconstruct), not when the timer completes.
|
||||
//
|
||||
// Holds the config and the refund sink; the world arrives per tick.
|
||||
class DeconstructionSystem
|
||||
{
|
||||
public:
|
||||
DeconstructionSystem(const GameConfig& config,
|
||||
std::function<void(int)> addBuildingBlocks)
|
||||
: m_config(config), m_addBuildingBlocks(std::move(addBuildingBlocks)) {}
|
||||
|
||||
void tick(FactoryState& state, Tick currentTick);
|
||||
|
||||
private:
|
||||
const GameConfig& m_config;
|
||||
std::function<void(int)> m_addBuildingBlocks;
|
||||
};
|
||||
|
||||
// Starts the timer on the front entry of the deconstruction queue, if it has one and
|
||||
// it has not started yet. Shared: BuildingSystem::deconstruct starts the timer when it
|
||||
// queues the first entry, and DeconstructionSystem restarts it after each completion.
|
||||
void startFrontDeconstruction(FactoryState& state, const GameConfig& config,
|
||||
Tick currentTick);
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "FactoryQueries.h"
|
||||
#include "ConstructionSystem.h"
|
||||
#include "DeconstructionSystem.h"
|
||||
#include "PlacementRules.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -126,8 +125,6 @@ void Simulation::initializeSubsystems()
|
||||
[this](const std::string& itemId) -> bool { return isItemUnlocked(itemId); },
|
||||
m_rng);
|
||||
m_constructionSystem = std::make_unique<ConstructionSystem>(m_config);
|
||||
m_deconstructionSystem = std::make_unique<DeconstructionSystem>(
|
||||
m_config, [this](int amount) { m_buildingBlocksStock += amount; });
|
||||
m_shipSystem = std::make_unique<ShipSystem>(m_config, m_admin);
|
||||
m_aiSystem = std::make_unique<AiSystem>(m_config);
|
||||
m_movementIntentSystem = std::make_unique<MovementIntentSystem>();
|
||||
@@ -249,7 +246,7 @@ void Simulation::tick()
|
||||
|
||||
// Construction + production pipeline
|
||||
m_constructionSystem->tick(m_factoryState, m_beltSystem, m_currentTick);
|
||||
m_deconstructionSystem->tick(m_factoryState, m_currentTick); // parallel to construction
|
||||
m_buildingSystem->tickDeconstruction(m_factoryState, m_currentTick); // parallel to construction
|
||||
m_buildingSystem->tickBeltPull(m_factoryState); // step 3
|
||||
m_buildingSystem->tickProduction(m_factoryState, m_currentTick); // step 4
|
||||
m_buildingSystem->tickShipyardProduction(m_factoryState, m_currentTick); // step 4b
|
||||
@@ -268,10 +265,10 @@ void Simulation::tick()
|
||||
m_shipSystem->clearMovementIntents();
|
||||
// Score-based behavior selection: evaluate, select winner, execute (sets
|
||||
// movement intent + preferred module targets only — no world mutation).
|
||||
m_aiSystem->tick(m_admin, m_factoryState);
|
||||
m_aiSystem->tick(m_admin, m_factoryState, *m_debrisSystem);
|
||||
// Module systems perform the world mutation (collection/delivery, healing).
|
||||
// Each emits its tool beams and applies its own delayed (mid-beam) effects.
|
||||
m_salvagerSystem->tick(m_currentTick, m_factoryState, m_beamFiredEvents);
|
||||
m_salvagerSystem->tick(m_currentTick, *m_debrisSystem, m_factoryState, m_beamFiredEvents);
|
||||
m_repairSystem->tick(m_currentTick, m_beamFiredEvents);
|
||||
|
||||
// Step 8: combat resolution
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
class AiSystem;
|
||||
class BuildingSystem;
|
||||
class ConstructionSystem;
|
||||
class DeconstructionSystem;
|
||||
struct Command;
|
||||
class Hasher;
|
||||
class CombatSystem;
|
||||
@@ -221,7 +220,6 @@ private:
|
||||
BeltSystem m_beltSystem;
|
||||
std::unique_ptr<BuildingSystem> m_buildingSystem;
|
||||
std::unique_ptr<ConstructionSystem> m_constructionSystem;
|
||||
std::unique_ptr<DeconstructionSystem> m_deconstructionSystem;
|
||||
std::unique_ptr<ShipSystem> m_shipSystem;
|
||||
std::unique_ptr<AiSystem> m_aiSystem;
|
||||
std::unique_ptr<MovementIntentSystem> m_movementIntentSystem;
|
||||
|
||||
@@ -101,14 +101,14 @@ struct Fixture
|
||||
void decide()
|
||||
{
|
||||
ships.clearMovementIntents();
|
||||
ai.tick(admin, state);
|
||||
ai.tick(admin, state, scraps);
|
||||
}
|
||||
|
||||
// World mutation: collection/delivery and healing.
|
||||
void runModules()
|
||||
{
|
||||
beamEvents.clear();
|
||||
salvager.tick(tick, state, beamEvents);
|
||||
salvager.tick(tick, scraps, state, beamEvents);
|
||||
repair.tick(tick, beamEvents);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ struct Fixture
|
||||
void salvageTick()
|
||||
{
|
||||
beamEvents.clear();
|
||||
salvager.tick(tick, state, beamEvents);
|
||||
salvager.tick(tick, scraps, state, beamEvents);
|
||||
++tick;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -415,7 +415,7 @@ TEST_CASE("CombatSystem: scrap is spawned on ship death", "[combat]")
|
||||
|
||||
sim.tick();
|
||||
|
||||
const std::vector<DebrisInfo> scraps = getAllDebrisInfo(sim.getAdmin());
|
||||
const std::vector<DebrisInfo> scraps = sim.getDebrisSystem().getAllDebrisInfo();
|
||||
REQUIRE(scraps.size() == 1);
|
||||
CHECK(sim.getAdmin().get<DebrisComponent>(scraps[0].entity).amount == 59);
|
||||
}
|
||||
|
||||
@@ -116,16 +116,16 @@ TEST_CASE("DebrisSystem: collectOne depletes one scrap and keeps the debris unti
|
||||
|
||||
const entt::entity e = ss.spawn(QVector2D(0.0f, 0.0f), 3, 100);
|
||||
|
||||
REQUIRE(collectOne(admin, e));
|
||||
REQUIRE(ss.collectOne(e));
|
||||
REQUIRE(admin.isValid(e));
|
||||
REQUIRE(admin.get<DebrisComponent>(e).amount == 2);
|
||||
|
||||
REQUIRE(collectOne(admin, e));
|
||||
REQUIRE(ss.collectOne(e));
|
||||
REQUIRE(admin.isValid(e));
|
||||
REQUIRE(admin.get<DebrisComponent>(e).amount == 1);
|
||||
|
||||
// Final unit collected: the debris is removed once depleted.
|
||||
REQUIRE(collectOne(admin, e));
|
||||
REQUIRE(ss.collectOne(e));
|
||||
REQUIRE_FALSE(admin.isValid(e));
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ TEST_CASE("DebrisSystem: collectOne returns false for an invalid entity", "[debr
|
||||
EntityAdmin admin;
|
||||
DebrisSystem ss(admin);
|
||||
|
||||
REQUIRE_FALSE(collectOne(admin, entt::null));
|
||||
REQUIRE_FALSE(ss.collectOne(entt::null));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -149,7 +149,7 @@ TEST_CASE("DebrisSystem: getAllDebrisInfo returns all spawned debris", "[debris]
|
||||
ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
|
||||
ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
|
||||
|
||||
const std::vector<DebrisInfo> info = getAllDebrisInfo(admin);
|
||||
const std::vector<DebrisInfo> info = ss.getAllDebrisInfo();
|
||||
REQUIRE(info.size() == 2);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ TEST_CASE("DebrisSystem: getAllDebrisInfo reports each debris entry.s remaining
|
||||
const entt::entity a = ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
|
||||
const entt::entity b = ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
|
||||
|
||||
const std::vector<DebrisInfo> info = getAllDebrisInfo(admin);
|
||||
const std::vector<DebrisInfo> info = ss.getAllDebrisInfo();
|
||||
REQUIRE(info.size() == 2);
|
||||
for (const DebrisInfo& i : info)
|
||||
{
|
||||
|
||||
@@ -367,7 +367,7 @@ int FieldSelectionPanel::selectedDebrisScrapTotal() const
|
||||
{
|
||||
// Sum the remaining scrap across the still-living selected debris (REQ-UI-DEBRIS-PANEL).
|
||||
int total = 0;
|
||||
for (const DebrisInfo& info : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
for (const DebrisInfo& info : m_sim->getDebrisSystem().getAllDebrisInfo())
|
||||
{
|
||||
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), info.entity)
|
||||
!= m_selectedDebris.end())
|
||||
|
||||
@@ -777,7 +777,7 @@ void GameWorldView::pruneDespawnedDebris()
|
||||
if (m_selectedDebris.empty()) { return; }
|
||||
|
||||
std::vector<entt::entity> live;
|
||||
for (const DebrisInfo& info : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
for (const DebrisInfo& info : m_sim->getDebrisSystem().getAllDebrisInfo())
|
||||
{
|
||||
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), info.entity)
|
||||
!= m_selectedDebris.end())
|
||||
@@ -1510,7 +1510,7 @@ void GameWorldView::drawSelectionHighlights(QPainter& painter)
|
||||
if (!m_selectedDebris.empty())
|
||||
{
|
||||
const qreal outlineRadius = static_cast<qreal>(getTilePx() * 0.2f) + 3.0;
|
||||
for (const DebrisInfo& debris : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
for (const DebrisInfo& debris : m_sim->getDebrisSystem().getAllDebrisInfo())
|
||||
{
|
||||
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), debris.entity)
|
||||
== m_selectedDebris.end()) { continue; }
|
||||
@@ -1654,7 +1654,7 @@ void GameWorldView::drawBeltItems(QPainter& painter)
|
||||
void GameWorldView::drawDebris(QPainter& painter)
|
||||
{
|
||||
const float r = getTilePx() * 0.2f;
|
||||
for (const DebrisInfo& debris : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
for (const DebrisInfo& debris : m_sim->getDebrisSystem().getAllDebrisInfo())
|
||||
{
|
||||
const QPointF center = worldToWidget(debris.position);
|
||||
painter.setBrush(QColor(128, 110, 90));
|
||||
|
||||
Reference in New Issue
Block a user