diff --git a/src/lib/sim/ShipSystem.cpp b/src/lib/sim/ShipSystem.cpp index 49e0e07..432aafd 100644 --- a/src/lib/sim/ShipSystem.cpp +++ b/src/lib/sim/ShipSystem.cpp @@ -245,7 +245,7 @@ void ShipSystem::tickThreatResponse(const BuildingSystem& buildings) if (!s.isEnemy) { - // Player combat ship: target nearest enemy ship. + // Player combat ship: target nearest enemy ship or enemy building. if (!isTargetValid(s.threatResponse->currentTarget.value_or(kInvalidEntityId), range, s, buildings)) { @@ -264,14 +264,39 @@ void ShipSystem::tickThreatResponse(const BuildingSystem& buildings) s.threatResponse->currentTarget = candidate.id; } } + + for (const Building& b : allBuildings) + { + if (b.type != BuildingType::EnemyDefenceStation) + { + continue; + } + float dist = (buildingCenter(b) - s.position).length(); + if (dist < bestDist) + { + bestDist = dist; + s.threatResponse->currentTarget = b.id; + } + } } if (s.threatResponse->currentTarget) { - const Ship* target = findShip(*s.threatResponse->currentTarget); - if (target && 3 > s.intent.priority) + QVector2D dest; + const Ship* tShip = findShip(*s.threatResponse->currentTarget); + if (tShip) { - s.intent = MovementIntent{3, target->position}; + dest = tShip->position; + } + else + { + const Building* tBld = buildings.findBuilding( + *s.threatResponse->currentTarget); + dest = tBld ? buildingCenter(*tBld) : s.position; + } + if (3 > s.intent.priority) + { + s.intent = MovementIntent{3, dest}; } } else diff --git a/src/test/CombatSystemTest.cpp b/src/test/CombatSystemTest.cpp index bec09af..97396a1 100644 --- a/src/test/CombatSystemTest.cpp +++ b/src/test/CombatSystemTest.cpp @@ -283,6 +283,47 @@ TEST_CASE("CombatSystem: enemy station fires at player ship in range", "[combat] REQUIRE(stationFired); } +TEST_CASE("CombatSystem: player ship fires at enemy station in range", "[combat]") +{ + Simulation sim(loadConfig(), 42); + + EntityId stationId = kInvalidEntityId; + QVector2D stationCenter; + for (const Building& b : sim.buildings().allBuildings()) + { + if (b.type == BuildingType::EnemyDefenceStation) + { + stationId = b.id; + stationCenter = QVector2D( + b.anchor.x() + b.footprint.width() / 2.0f, + b.anchor.y() + b.footprint.height() / 2.0f); + break; + } + } + REQUIRE(stationId != kInvalidEntityId); + + const ShipDef* combatDef = findCombatShip(sim.config()); + REQUIRE(combatDef != nullptr); + + const EntityId playerId = sim.ships().spawn( + combatDef->id, 1, + QVector2D(stationCenter.x() - 1.0f, stationCenter.y()), + /*isEnemy=*/false); + + sim.tick(); + + const std::vector events = sim.drainFireEvents(); + bool playerFiredAtStation = false; + for (const FireEvent& e : events) + { + if (e.shooter == playerId && e.target == stationId) + { + playerFiredAtStation = true; + } + } + REQUIRE(playerFiredAtStation); +} + // --------------------------------------------------------------------------- // Deaths & loot (tick step 9) // ---------------------------------------------------------------------------