change repair_tool application and add beams for salvager and repair_tool

This commit is contained in:
2026-06-18 22:14:09 +02:00
parent 7924e037aa
commit 9573b9789a
37 changed files with 498 additions and 199 deletions

View File

@@ -8,9 +8,12 @@
#include "BuildingSystem.h"
#include "DeliverScrapBehavior.h"
#include "EntityAdmin.h"
#include <map>
#include "ModuleOwnerComponent.h"
#include "PositionComponent.h"
#include "SalvageCargoComponent.h"
#include "ScrapDataComponent.h"
#include "ScrapSystem.h"
#include "tracing.h"
@@ -19,9 +22,13 @@ SalvagerSystem::SalvagerSystem(EntityAdmin& admin)
{
}
void SalvagerSystem::tick(ScrapSystem& scraps, BuildingSystem& buildings)
void SalvagerSystem::tick(Tick currentTick, ScrapSystem& scraps, BuildingSystem& buildings,
std::vector<BeamFiredEvent>& outBeamFiredEvents)
{
TRACE();
// Apply collections whose mid-beam delay has elapsed (cycles started earlier).
applyPendingCollections(currentTick, scraps);
const std::vector<ScrapInfo> allScrap = scraps.allScrapInfo();
// Tick down per-module collection cooldowns.
@@ -31,23 +38,39 @@ void SalvagerSystem::tick(ScrapSystem& scraps, BuildingSystem& buildings)
if (c.cooldownTicksRemaining > 0) { --c.cooldownTicksRemaining; }
});
// Collection: each ready, in-range module collects one scrap.
// Scrap units already claimed by not-yet-applied collection cycles, so two
// modules don't both target the last unit of the same pile (the claim would be
// dropped at apply time). A pile is available while its amount exceeds its claims.
std::map<entt::entity, int> claimedUnits;
for (const PendingCollection& pc : m_pendingCollections)
{
++claimedUnits[pc.scrap];
}
// Cycle start: each ready, in-range module with free cargo begins a collection
// cycle — emit the beam now, collect one scrap mid-beam, start the cooldown now.
m_admin.forEach<SalvageCargoComponent, ModuleOwnerComponent>(
[&](entt::entity /*ce*/, SalvageCargoComponent& c, const ModuleOwnerComponent& o)
[&](entt::entity moduleEntity, SalvageCargoComponent& c, const ModuleOwnerComponent& o)
{
if (c.current >= c.capacity || c.cooldownTicksRemaining > 0) { return; }
if (c.collectionIntervalTicks <= 0) { return; }
if (!m_admin.hasAll<PositionComponent>(o.owner)) { return; }
const QVector2D ownerPos = m_admin.get<PositionComponent>(o.owner).value;
for (const ScrapInfo& si : allScrap)
{
if ((si.position - ownerPos).length() > c.collectionRange_tiles) { continue; }
if (scraps.consume(si.entity))
if (claimedUnits[si.entity] >= m_admin.get<ScrapDataComponent>(si.entity).amount)
{
++c.current;
c.cooldownTicksRemaining = c.collectionIntervalTicks;
break;
continue; // every remaining unit of this pile is already spoken for
}
outBeamFiredEvents.push_back(
BeamFiredEvent{BeamKind::Salvage, o.owner, si.entity, currentTick});
m_pendingCollections.push_back({moduleEntity, si.entity,
currentTick + kBeamImpactDelayTicks});
++claimedUnits[si.entity];
c.cooldownTicksRemaining = c.collectionIntervalTicks;
break;
}
});
@@ -77,3 +100,27 @@ void SalvagerSystem::tick(ScrapSystem& scraps, BuildingSystem& buildings)
});
});
}
void SalvagerSystem::applyPendingCollections(Tick currentTick, ScrapSystem& scraps)
{
std::vector<PendingCollection>::iterator it = m_pendingCollections.begin();
while (it != m_pendingCollections.end())
{
if (it->appliesAt <= currentTick)
{
if (m_admin.isValid(it->module) && m_admin.hasAll<SalvageCargoComponent>(it->module))
{
SalvageCargoComponent& c = m_admin.get<SalvageCargoComponent>(it->module);
if (c.current < c.capacity && scraps.collectOne(it->scrap))
{
++c.current;
}
}
it = m_pendingCollections.erase(it);
}
else
{
++it;
}
}
}