change repair_tool application and add beams for salvager and repair_tool
This commit is contained in:
@@ -19,52 +19,91 @@ RepairSystem::RepairSystem(EntityAdmin& admin)
|
||||
{
|
||||
}
|
||||
|
||||
void RepairSystem::tick()
|
||||
void RepairSystem::tick(Tick currentTick, std::vector<BeamFiredEvent>& outBeamFiredEvents)
|
||||
{
|
||||
TRACE();
|
||||
// Apply heals whose mid-beam delay has elapsed (cycles started on prior ticks).
|
||||
applyPendingHeals(currentTick);
|
||||
|
||||
const std::vector<RepairableInfo> repairables = buildRepairables(m_admin);
|
||||
|
||||
m_admin.forEach<RepairToolComponent, ModuleOwnerComponent>(
|
||||
[&](entt::entity /*re*/, RepairToolComponent& tool, const ModuleOwnerComponent& owner)
|
||||
{
|
||||
if (tool.cooldownTicksRemaining > 0) { --tool.cooldownTicksRemaining; }
|
||||
if (tool.cooldownTicksRemaining > 0) { return; }
|
||||
if (tool.repairIntervalTicks <= 0) { return; }
|
||||
if (!m_admin.hasAll<PositionComponent>(owner.owner)) { return; }
|
||||
const QVector2D ownerPos = m_admin.get<PositionComponent>(owner.owner).value;
|
||||
|
||||
// Honour the executor-set target if it is still valid and in range.
|
||||
// Choose a target: honour the executor-set target if it is still valid
|
||||
// and in range, else fall back to the nearest damaged friendly in range.
|
||||
std::optional<entt::entity> target;
|
||||
if (tool.currentTarget)
|
||||
{
|
||||
const entt::entity t = *tool.currentTarget;
|
||||
if (m_admin.isValid(t) && m_admin.hasAll<HealthComponent, PositionComponent>(t))
|
||||
{
|
||||
HealthComponent& th = m_admin.get<HealthComponent>(t);
|
||||
const HealthComponent& th = m_admin.get<HealthComponent>(t);
|
||||
const float dist =
|
||||
(m_admin.get<PositionComponent>(t).value - ownerPos).length();
|
||||
if (th.hp > 0.0f && th.hp < th.maxHp && dist <= tool.range_tiles)
|
||||
{
|
||||
th.hp = std::min(th.hp + tool.ratePerTick, th.maxHp);
|
||||
return;
|
||||
target = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: heal the nearest damaged friendly within tool range.
|
||||
tool.currentTarget = std::nullopt;
|
||||
float bestDist = tool.range_tiles;
|
||||
for (const RepairableInfo& r : repairables)
|
||||
if (!target)
|
||||
{
|
||||
if (r.isEnemy) { continue; }
|
||||
if (r.hp <= 0.0f || r.hp >= r.maxHp) { continue; }
|
||||
const float dist = (r.position - ownerPos).length();
|
||||
if (dist < bestDist)
|
||||
tool.currentTarget = std::nullopt;
|
||||
float bestDist = tool.range_tiles;
|
||||
for (const RepairableInfo& r : repairables)
|
||||
{
|
||||
bestDist = dist;
|
||||
tool.currentTarget = r.entity;
|
||||
if (r.isEnemy) { continue; }
|
||||
if (r.hp <= 0.0f || r.hp >= r.maxHp) { continue; }
|
||||
const float dist = (r.position - ownerPos).length();
|
||||
if (dist < bestDist)
|
||||
{
|
||||
bestDist = dist;
|
||||
tool.currentTarget = r.entity;
|
||||
}
|
||||
}
|
||||
target = tool.currentTarget;
|
||||
}
|
||||
|
||||
if (!tool.currentTarget) { return; }
|
||||
if (!target) { return; }
|
||||
|
||||
HealthComponent& targetHealth = m_admin.get<HealthComponent>(*tool.currentTarget);
|
||||
targetHealth.hp = std::min(targetHealth.hp + tool.ratePerTick, targetHealth.maxHp);
|
||||
// Start a repair cycle: emit the beam now, apply the heal mid-beam, and
|
||||
// begin the cooldown at cycle start (not at effect application).
|
||||
outBeamFiredEvents.push_back(
|
||||
BeamFiredEvent{BeamKind::Repair, owner.owner, *target, currentTick});
|
||||
m_pendingHeals.push_back({*target, tool.repairAmountHp,
|
||||
currentTick + kBeamImpactDelayTicks});
|
||||
tool.cooldownTicksRemaining = tool.repairIntervalTicks;
|
||||
});
|
||||
}
|
||||
|
||||
void RepairSystem::applyPendingHeals(Tick currentTick)
|
||||
{
|
||||
std::vector<PendingHeal>::iterator it = m_pendingHeals.begin();
|
||||
while (it != m_pendingHeals.end())
|
||||
{
|
||||
if (it->appliesAt <= currentTick)
|
||||
{
|
||||
if (m_admin.isValid(it->target) && m_admin.hasAll<HealthComponent>(it->target))
|
||||
{
|
||||
HealthComponent& h = m_admin.get<HealthComponent>(it->target);
|
||||
if (h.hp > 0.0f && h.hp < h.maxHp)
|
||||
{
|
||||
h.hp = std::min(h.hp + it->amountHp, h.maxHp);
|
||||
}
|
||||
}
|
||||
it = m_pendingHeals.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user