From 6c210c9d15243c58e320c5252ba851a0575e23ed Mon Sep 17 00:00:00 2001 From: Raffson Date: Mon, 3 Jul 2023 00:36:19 +0200 Subject: [PATCH] Fine-tuning stuff for 'SEAD Sweep' --- game/ato/flightplans/formation.py | 7 ++---- game/ato/flightplans/formationattack.py | 33 +++++++++++++++++++++---- game/ato/flightplans/loiter.py | 4 +-- game/ato/flightplans/sweep.py | 3 ++- game/ato/flightplans/waypointbuilder.py | 6 ++++- game/ato/package.py | 1 + 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/game/ato/flightplans/formation.py b/game/ato/flightplans/formation.py index 3f380813..b71aac8b 100644 --- a/game/ato/flightplans/formation.py +++ b/game/ato/flightplans/formation.py @@ -19,7 +19,7 @@ if TYPE_CHECKING: @dataclass class FormationLayout(LoiterLayout, ABC): nav_to: list[FlightWaypoint] - join: FlightWaypoint + join: Optional[FlightWaypoint] split: FlightWaypoint refuel: Optional[FlightWaypoint] nav_from: list[FlightWaypoint] @@ -73,10 +73,7 @@ class FormationFlightPlan(LoiterFlightPlan, ABC): return min(speeds) def speed_between_waypoints(self, a: FlightWaypoint, b: FlightWaypoint) -> Speed: - if b in self.package_speed_waypoints: - # Should be impossible, as any package with at least one - # FormationFlightPlan flight needs a formation speed. - assert self.package.formation_speed is not None + if self.package.formation_speed and b in self.package_speed_waypoints: return self.package.formation_speed return super().speed_between_waypoints(a, b) diff --git a/game/ato/flightplans/formationattack.py b/game/ato/flightplans/formationattack.py index b55eee26..7ca77236 100644 --- a/game/ato/flightplans/formationattack.py +++ b/game/ato/flightplans/formationattack.py @@ -111,9 +111,19 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC): ) return tot - travel_time + @property + def initial_time(self) -> timedelta: + tot = self.tot + travel_time = self.travel_time_between_waypoints( + self.layout.initial, self.target_area_waypoint + ) + return tot - travel_time + def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: if waypoint == self.layout.ingress: return self.ingress_time + elif waypoint == self.layout.initial: + return self.initial_time elif waypoint in self.layout.targets: return self.tot return super().tot_for_waypoint(waypoint) @@ -127,9 +137,11 @@ class FormationAttackLayout(FormationLayout): def iter_waypoints(self) -> Iterator[FlightWaypoint]: yield self.departure - yield self.hold + if self.hold: + yield self.hold yield from self.nav_to - yield self.join + if self.join: + yield self.join yield self.ingress if self.initial is not None: yield self.initial @@ -170,8 +182,17 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC): ) ) - hold = builder.hold(self._hold_point()) - join = builder.join(self.package.waypoints.join) + hold = None + join = None + if ( + self.flight is self.package.primary_flight + or self.package.primary_flight + and isinstance( + self.package.primary_flight.flight_plan, FormationAttackFlightPlan + ) + ): + hold = builder.hold(self._hold_point()) + join = builder.join(self.package.waypoints.join) split = builder.split(self.package.waypoints.split) refuel = builder.refuel(self.package.waypoints.refuel) @@ -189,7 +210,9 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC): departure=builder.takeoff(self.flight.departure), hold=hold, nav_to=builder.nav_path( - hold.position, join.position, self.doctrine.ingress_altitude + hold.position if hold else self.flight.departure.position, + join.position if join else ingress.position, + self.doctrine.ingress_altitude, ), join=join, ingress=ingress, diff --git a/game/ato/flightplans/loiter.py b/game/ato/flightplans/loiter.py index 9cd96b77..ee306907 100644 --- a/game/ato/flightplans/loiter.py +++ b/game/ato/flightplans/loiter.py @@ -3,7 +3,7 @@ from __future__ import annotations from abc import ABC, abstractmethod from dataclasses import dataclass from datetime import timedelta -from typing import Any, TYPE_CHECKING, TypeGuard +from typing import Any, TYPE_CHECKING, TypeGuard, Optional from game.typeguard import self_type_guard from .flightplan import FlightPlan @@ -15,7 +15,7 @@ if TYPE_CHECKING: @dataclass class LoiterLayout(StandardLayout, ABC): - hold: FlightWaypoint + hold: Optional[FlightWaypoint] class LoiterFlightPlan(StandardFlightPlan[Any], ABC): diff --git a/game/ato/flightplans/sweep.py b/game/ato/flightplans/sweep.py index 7ef093a7..d178cf7f 100644 --- a/game/ato/flightplans/sweep.py +++ b/game/ato/flightplans/sweep.py @@ -26,7 +26,8 @@ class SweepLayout(LoiterLayout): def iter_waypoints(self) -> Iterator[FlightWaypoint]: yield self.departure - yield self.hold + if self.hold: + yield self.hold yield from self.nav_to yield self.sweep_start yield self.sweep_end diff --git a/game/ato/flightplans/waypointbuilder.py b/game/ato/flightplans/waypointbuilder.py index bea1a294..4f47511b 100644 --- a/game/ato/flightplans/waypointbuilder.py +++ b/game/ato/flightplans/waypointbuilder.py @@ -458,7 +458,11 @@ class WaypointBuilder: assert self.flight.package.waypoints ingress = self.flight.package.waypoints.ingress ingress2tgt_dist = ingress.distance_to_point(target.position) - threat_range = 1.1 * max([x.threat_range for x in target.strike_targets]).meters + threat_range = nautical_miles(5).meters + if target.strike_targets: + threat_range = ( + 1.1 * max([x.threat_range for x in target.strike_targets]).meters + ) hdg = target.position.heading_between_point(ingress) hold = target.position.point_from_heading( hdg, min(threat_range, ingress2tgt_dist * 0.95) diff --git a/game/ato/package.py b/game/ato/package.py index 037231c6..6b031d2b 100644 --- a/game/ato/package.py +++ b/game/ato/package.py @@ -176,6 +176,7 @@ class Package(RadioFrequencyContainer): FlightType.TRANSPORT, FlightType.AIR_ASSAULT, FlightType.SEAD, + FlightType.SEAD_SWEEP, FlightType.TARCAP, FlightType.BARCAP, FlightType.AEWC,