#include "RetreatEvaluator.h" #include #include #include "AttackBehavior.h" #include "BehaviorScores.h" #include "BehaviorTargeting.h" #include "EntityAdmin.h" #include "FactionComponent.h" #include "HealthComponent.h" #include "PositionComponent.h" #include "RepairBehavior.h" #include "RetreatBehavior.h" #include "SensorRangeComponent.h" #include "ShipIdentityComponent.h" #include "tracing.h" void RetreatEvaluator::evaluate(EntityAdmin& admin) { TRACE(); // Snapshot enemy ship positions for threat detection. std::vector enemyShips; admin.forEach( [&enemyShips](entt::entity /*e*/, const ShipIdentityComponent& /*si*/, const PositionComponent& pos, const FactionComponent& f) { if (f.isEnemy) { enemyShips.push_back(pos.value); } }); // Snapshot repairables so weaponless repair ships can decide whether there is // still a damaged ally worth holding ground for. const std::vector repairables = buildRepairables(admin); admin.forEach( [&](entt::entity e, RetreatBehavior& retreat, const PositionComponent& pos, const HealthComponent& health, const SensorRangeComponent& sensor, const FactionComponent& faction) { const bool lowHp = (health.maxHp > 0.0f) && (health.hp / health.maxHp < retreat.retreatHpFraction); bool threatened = false; const bool hasWeapons = admin.hasAll(e); if (!hasWeapons) { bool enemyInRange = false; for (const QVector2D& enemy : enemyShips) { if ((enemy - pos.value).length() <= sensor.value_tiles) { enemyInRange = true; 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(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) ? BehaviorScores::kRetreat : BehaviorScores::kInactive; }); }