#include "AttackEvaluator.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 "SensorRangeComponent.h" #include "tracing.h" void AttackEvaluator::evaluate(EntityAdmin& admin) { TRACE(); const std::vector combatants = buildCombatants(admin); admin.forEach( [&](entt::entity e, AttackBehavior& attack, const PositionComponent& pos, const FactionComponent& faction, const SensorRangeComponent& sensor, const HealthComponent& health) { const float range = sensor.value_tiles; // Validate current target: still valid, still in range. bool targetValid = false; if (attack.currentTarget) { const entt::entity t = *attack.currentTarget; if (admin.isValid(t) && admin.hasAll(t)) { const float dist = (admin.get(t).value - pos.value).length(); if (dist <= range) { targetValid = true; } } } // Acquire nearest valid target if needed. if (!targetValid) { attack.currentTarget = std::nullopt; float bestDist = range; for (const CombatantInfo& c : combatants) { if (c.entity == e) { continue; } const bool isValidTarget = faction.isEnemy ? !c.isEnemy : c.isEnemy; if (!isValidTarget) { continue; } const float dist = (c.position - pos.value).length(); if (dist < bestDist) { bestDist = dist; attack.currentTarget = c.entity; } } } const bool healthy = (health.maxHp > 0.0f) && (health.hp / health.maxHp >= BehaviorScores::kLowHpFraction); attack.score = (healthy && attack.currentTarget) ? BehaviorScores::kAttack : BehaviorScores::kInactive; }); }