From 9e36c1363591cd043efaf073b4cd2124c1b160b0 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 25 May 2026 21:00:15 +0200 Subject: [PATCH] fix tests --- src/lib/ecs/system/CombatSystem.cpp | 17 ++++++++++++----- src/lib/ecs/system/MovementIntentSystem.cpp | 4 +++- src/test/CombatSystemTest.cpp | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/lib/ecs/system/CombatSystem.cpp b/src/lib/ecs/system/CombatSystem.cpp index 0b3f9cb..4e6e276 100644 --- a/src/lib/ecs/system/CombatSystem.cpp +++ b/src/lib/ecs/system/CombatSystem.cpp @@ -2,8 +2,10 @@ #include "EntityAdmin.h" #include "FactionComponent.h" +#include "StationBodyComponent.h" #include "HealthComponent.h" #include "PositionComponent.h" +#include "SensorRangeComponent.h" #include "ShipIdentityComponent.h" #include "ThreatResponseBehaviorComponent.h" #include "WeaponComponent.h" @@ -31,10 +33,11 @@ void CombatSystem::tick(Tick currentTick, resolveWeapon(e, weapon, pos, faction, currentTick, admin, outFireEvents); }); - // Station weapons. - admin.forEach( + // Station weapons (entities with StationBodyComponent; ships are excluded because + // they lack that component and are already handled by the ship loop above). + admin.forEach( [&](entt::entity e, WeaponComponent& weapon, PositionComponent& pos, - FactionComponent& faction) + FactionComponent& faction, const StationBodyComponent& /*sb*/) { resolveWeapon(e, weapon, pos, faction, currentTick, admin, outFireEvents); }); @@ -77,10 +80,14 @@ void CombatSystem::resolveWeapon( } } - // Acquire a new target if needed (nearest opposing-faction ship). + // Acquire a new target if needed. + // Ships use their sensor range; stations fall back to weapon range. if (!weapon.currentTarget) { - float bestDistanceSquared = weapon.range * weapon.range; + const float acquisitionRange = admin.hasAll(shipEntity) + ? admin.get(shipEntity).value + : weapon.range; + float bestDistanceSquared = acquisitionRange * acquisitionRange; admin.forEach( [&](entt::entity candidate, const ShipIdentityComponent& /*si*/, const PositionComponent& candidatePos, diff --git a/src/lib/ecs/system/MovementIntentSystem.cpp b/src/lib/ecs/system/MovementIntentSystem.cpp index 49a0406..81a7daf 100644 --- a/src/lib/ecs/system/MovementIntentSystem.cpp +++ b/src/lib/ecs/system/MovementIntentSystem.cpp @@ -91,9 +91,11 @@ void MovementIntentSystem::tick(EntityAdmin& admin) const float manAccel = body.maneuveringAccelerationPerTick; const float stoppingDist = (body.maxSpeedPerTick * body.maxSpeedPerTick) / (2.0f * manAccel); - const float desiredSpeed = (dist <= stoppingDist) + // Cap to dist so the ship never overshoots the target in a single tick. + const float baseDesiredSpeed = (dist <= stoppingDist) ? std::sqrt(2.0f * manAccel * dist) : body.maxSpeedPerTick; + const float desiredSpeed = std::min(dist, baseDesiredSpeed); const QVector2D desiredVel = delta.normalized() * desiredSpeed; const QVector2D velError = desiredVel - body.velocity; diff --git a/src/test/CombatSystemTest.cpp b/src/test/CombatSystemTest.cpp index 1528700..b83b799 100644 --- a/src/test/CombatSystemTest.cpp +++ b/src/test/CombatSystemTest.cpp @@ -115,13 +115,24 @@ TEST_CASE("CombatSystem: cooldown prevents firing before it expires", "[combat]" f.wireEnemyTarget(enemy, player); f.admin.get(enemy).cooldownTicks = 3.0f; // override to 3 + auto enemyFiredIn = [&enemy](const std::vector& evts) + { + for (const FireEvent& evt : evts) + { + if (evt.shooter == enemy) { return true; } + } + return false; + }; + std::vector events; f.combat.tick(0, f.admin, f.buildings, events); + REQUIRE_FALSE(enemyFiredIn(events)); + f.combat.tick(1, f.admin, f.buildings, events); - REQUIRE(events.empty()); + REQUIRE_FALSE(enemyFiredIn(events)); f.combat.tick(2, f.admin, f.buildings, events); - REQUIRE(events.size() == 1); + REQUIRE(enemyFiredIn(events)); } TEST_CASE("CombatSystem: no fire when target is out of range", "[combat]")