make repair ships not retreat if someone needs help

This commit is contained in:
2026-06-17 22:40:58 +02:00
parent 313fed02ca
commit abab2bbb6e

View File

@@ -6,10 +6,12 @@
#include "AttackBehavior.h" #include "AttackBehavior.h"
#include "BehaviorScores.h" #include "BehaviorScores.h"
#include "BehaviorTargeting.h"
#include "EntityAdmin.h" #include "EntityAdmin.h"
#include "FactionComponent.h" #include "FactionComponent.h"
#include "HealthComponent.h" #include "HealthComponent.h"
#include "PositionComponent.h" #include "PositionComponent.h"
#include "RepairBehavior.h"
#include "RetreatBehavior.h" #include "RetreatBehavior.h"
#include "SensorRangeComponent.h" #include "SensorRangeComponent.h"
#include "ShipIdentityComponent.h" #include "ShipIdentityComponent.h"
@@ -28,9 +30,15 @@ void RetreatEvaluator::evaluate(EntityAdmin& admin)
if (f.isEnemy) { enemyShips.push_back(pos.value); } if (f.isEnemy) { enemyShips.push_back(pos.value); }
}); });
admin.forEach<RetreatBehavior, PositionComponent, HealthComponent, SensorRangeComponent>( // Snapshot repairables so weaponless repair ships can decide whether there is
// still a damaged ally worth holding ground for.
const std::vector<RepairableInfo> repairables = buildRepairables(admin);
admin.forEach<RetreatBehavior, PositionComponent, HealthComponent,
SensorRangeComponent, FactionComponent>(
[&](entt::entity e, RetreatBehavior& retreat, const PositionComponent& pos, [&](entt::entity e, RetreatBehavior& retreat, const PositionComponent& pos,
const HealthComponent& health, const SensorRangeComponent& sensor) const HealthComponent& health, const SensorRangeComponent& sensor,
const FactionComponent& faction)
{ {
const bool lowHp = (health.maxHp > 0.0f) const bool lowHp = (health.maxHp > 0.0f)
&& (health.hp / health.maxHp < retreat.retreatHpFraction); && (health.hp / health.maxHp < retreat.retreatHpFraction);
@@ -39,14 +47,36 @@ void RetreatEvaluator::evaluate(EntityAdmin& admin)
const bool hasWeapons = admin.hasAll<AttackBehavior>(e); const bool hasWeapons = admin.hasAll<AttackBehavior>(e);
if (!hasWeapons) if (!hasWeapons)
{ {
bool enemyInRange = false;
for (const QVector2D& enemy : enemyShips) for (const QVector2D& enemy : enemyShips)
{ {
if ((enemy - pos.value).length() <= sensor.value_tiles) if ((enemy - pos.value).length() <= sensor.value_tiles)
{ {
threatened = true; enemyInRange = true;
break; break;
} }
} }
// A weaponless ship with a repair tool holds its ground while a
// damaged ally remains within sensor range; it only flees once
// there is nothing left to repair.
bool repairTargetInRange = false;
if (enemyInRange && admin.hasAll<RepairBehavior>(e))
{
for (const RepairableInfo& r : repairables)
{
if (r.entity == e) { continue; }
if (r.isEnemy != faction.isEnemy) { continue; }
if (r.hp <= 0.0f || r.hp >= r.maxHp) { continue; }
if ((r.position - pos.value).length() <= sensor.value_tiles)
{
repairTargetInRange = true;
break;
}
}
}
threatened = enemyInRange && !repairTargetInRange;
} }
retreat.score = (lowHp || threatened) retreat.score = (lowHp || threatened)