diff --git a/game/ato/flightplans/aewc.py b/game/ato/flightplans/aewc.py index 59c3445a..cc920b62 100644 --- a/game/ato/flightplans/aewc.py +++ b/game/ato/flightplans/aewc.py @@ -12,7 +12,7 @@ from game.utils import Distance, Heading, Speed, knots, meters, nautical_miles class AewcFlightPlan(PatrollingFlightPlan[PatrollingLayout]): @property def patrol_duration(self) -> timedelta: - return timedelta(hours=4) + return self.flight.coalition.game.settings.desired_awacs_mission_duration @property def patrol_speed(self) -> Speed: diff --git a/game/commander/missionscheduler.py b/game/commander/missionscheduler.py index 608ea2fe..093c3ea5 100644 --- a/game/commander/missionscheduler.py +++ b/game/commander/missionscheduler.py @@ -12,6 +12,7 @@ from game.theater import MissionTarget if TYPE_CHECKING: from game.coalition import Coalition + from game.ato import Package class MissionScheduler: @@ -41,6 +42,7 @@ class MissionScheduler: ] carrier_etas = [] + previous_aewc_end_time: dict[MissionTarget, datetime] = defaultdict(now.replace) start_time = start_time_generator( count=len(non_dca_packages), @@ -62,14 +64,19 @@ class MissionScheduler: else: package.time_over_target = previous_end_time - departure_time = package.mission_departure_time - # Should be impossible for CAPs + departure_time = self._get_departure_time(package) if departure_time is None: - logging.error(f"Could not determine mission end time for {package}") continue previous_cap_end_time[package.target] = departure_time elif package.auto_asap: package.set_tot_asap(now) + elif package.primary_task is FlightType.AEWC: + last = previous_aewc_end_time[package.target] + package.time_over_target = tot if tot > last else last + departure_time = self._get_departure_time(package) + if departure_time is None: + continue + previous_aewc_end_time[package.target] = departure_time else: # But other packages should be spread out a bit. Note that take # times are delayed, but all aircraft will become active at @@ -94,3 +101,11 @@ class MissionScheduler: package.time_over_target = carrier_etas.pop(0) else: break + + @staticmethod + def _get_departure_time(package: Package) -> datetime | None: + departure_time = package.mission_departure_time + # Should be impossible for CAP/AEWC + if departure_time is None: + logging.error(f"Could not determine mission end time for {package}") + return departure_time diff --git a/game/commander/theaterstate.py b/game/commander/theaterstate.py index 6cd27dce..acd35501 100644 --- a/game/commander/theaterstate.py +++ b/game/commander/theaterstate.py @@ -185,6 +185,9 @@ class TheaterState(WorldState["TheaterState"]): if not bp.blocking_capture or cp.is_fleet ] + aewc_targets = [cp for cp in finder.friendly_control_points() if cp.is_carrier] + aewc_targets.append(finder.farthest_friendly_control_point()) + return TheaterState( context=context, barcaps_needed={ @@ -194,7 +197,7 @@ class TheaterState(WorldState["TheaterState"]): active_front_lines=list(finder.front_lines()), front_line_stances={f: None for f in finder.front_lines()}, vulnerable_front_lines=list(finder.front_lines()), - aewc_targets=[finder.farthest_friendly_control_point()], + aewc_targets=list(aewc_targets), refueling_targets=[finder.closest_friendly_control_point()], recovery_targets={cp: 0 for cp in finder.friendly_naval_control_points()}, enemy_air_defenses=list(finder.enemy_air_defenses()), diff --git a/game/settings/settings.py b/game/settings/settings.py index a59e70c1..13198a8e 100644 --- a/game/settings/settings.py +++ b/game/settings/settings.py @@ -214,6 +214,16 @@ class Settings: ), ) # CAMPAIGN DOCTRINE + desired_awacs_mission_duration: timedelta = minutes_option( + "Desired AWACS on-station time", + page=CAMPAIGN_DOCTRINE_PAGE, + section=GENERAL_SECTION, + default=timedelta(minutes=120), + min=60, + max=300, + detail="Implicitly determines the number of AWACS flights planned by taking the mission duration" + " and dividing it by the desired on-station time.", + ) autoplan_tankers_for_strike: bool = boolean_option( "Auto-planner plans refueling flights for Strike packages", page=CAMPAIGN_DOCTRINE_PAGE,