diff --git a/game/ato/flightplans/airassault.py b/game/ato/flightplans/airassault.py index 015d287d..0d25074b 100644 --- a/game/ato/flightplans/airassault.py +++ b/game/ato/flightplans/airassault.py @@ -67,6 +67,10 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout], UiZoneDisplay): def ctld_target_zone_radius(self) -> Distance: return meters(2500) + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return self.package.time_over_target diff --git a/game/ato/flightplans/airlift.py b/game/ato/flightplans/airlift.py index 1f143a35..0771f10f 100644 --- a/game/ato/flightplans/airlift.py +++ b/game/ato/flightplans/airlift.py @@ -75,6 +75,10 @@ class AirliftFlightPlan(StandardFlightPlan[AirliftLayout]): def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: return None + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return self.package.time_over_target diff --git a/game/ato/flightplans/custom.py b/game/ato/flightplans/custom.py index 35caa8e0..8b249986 100644 --- a/game/ato/flightplans/custom.py +++ b/game/ato/flightplans/custom.py @@ -50,6 +50,10 @@ class CustomFlightPlan(FlightPlan[CustomLayout]): def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: return None + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return self.package.time_over_target diff --git a/game/ato/flightplans/ferry.py b/game/ato/flightplans/ferry.py index 0ddd82ac..d3382e55 100644 --- a/game/ato/flightplans/ferry.py +++ b/game/ato/flightplans/ferry.py @@ -45,6 +45,10 @@ class FerryFlightPlan(StandardFlightPlan[FerryLayout]): def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: return None + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return self.package.time_over_target diff --git a/game/ato/flightplans/flightplan.py b/game/ato/flightplans/flightplan.py index fcb1e12a..0ddcae7e 100644 --- a/game/ato/flightplans/flightplan.py +++ b/game/ato/flightplans/flightplan.py @@ -8,7 +8,7 @@ generating the waypoints for the mission. from __future__ import annotations import math -from abc import ABC +from abc import ABC, abstractmethod from collections.abc import Iterator from dataclasses import dataclass from datetime import timedelta @@ -296,6 +296,16 @@ class FlightPlan(ABC, Generic[LayoutT]): else: return timedelta(minutes=8) + @property + @abstractmethod + def mission_begin_on_station_time(self) -> timedelta | None: + """The time that the mission is first on-station. + + Not all mission types will have a time when they can be considered on-station. + Missions that patrol or loiter (CAPs, CAS, refueling, AEW&C, etc) will have this + defined, but strike-like missions will not. + """ + @property def mission_departure_time(self) -> timedelta: """The time that the mission is complete and the flight RTBs.""" diff --git a/game/ato/flightplans/formation.py b/game/ato/flightplans/formation.py index 5aa39263..2c498ce4 100644 --- a/game/ato/flightplans/formation.py +++ b/game/ato/flightplans/formation.py @@ -96,6 +96,10 @@ class FormationFlightPlan(LoiterFlightPlan, ABC): GroundSpeed.for_flight(self.flight, self.layout.hold.alt), ) + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return self.split_time diff --git a/game/ato/flightplans/patrolling.py b/game/ato/flightplans/patrolling.py index eecc1828..247a6c12 100644 --- a/game/ato/flightplans/patrolling.py +++ b/game/ato/flightplans/patrolling.py @@ -89,6 +89,10 @@ class PatrollingFlightPlan(StandardFlightPlan[LayoutT], UiZoneDisplay, ABC): def tot_waypoint(self) -> FlightWaypoint: return self.layout.patrol_start + @property + def mission_begin_on_station_time(self) -> timedelta: + return self.patrol_start_time + @property def mission_departure_time(self) -> timedelta: return self.patrol_end_time diff --git a/game/ato/flightplans/rtb.py b/game/ato/flightplans/rtb.py index 8f1cbfa8..2ae72645 100644 --- a/game/ato/flightplans/rtb.py +++ b/game/ato/flightplans/rtb.py @@ -49,6 +49,10 @@ class RtbFlightPlan(StandardFlightPlan[RtbLayout]): def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: return None + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + @property def mission_departure_time(self) -> timedelta: return timedelta() diff --git a/game/ato/flightplans/shiprecoverytanker.py b/game/ato/flightplans/shiprecoverytanker.py index cfa20e46..94409d9d 100644 --- a/game/ato/flightplans/shiprecoverytanker.py +++ b/game/ato/flightplans/shiprecoverytanker.py @@ -3,9 +3,9 @@ from __future__ import annotations from dataclasses import dataclass from datetime import timedelta from typing import Iterator, Type -from game.ato.flightplans.standard import StandardFlightPlan, StandardLayout + from game.ato.flightplans.ibuilder import IBuilder -from game.ato.flightplans.standard import StandardLayout +from game.ato.flightplans.standard import StandardFlightPlan, StandardLayout from game.ato.flightplans.waypointbuilder import WaypointBuilder from game.ato.flightwaypoint import FlightWaypoint @@ -37,15 +37,11 @@ class RecoveryTankerFlightPlan(StandardFlightPlan[RecoveryTankerLayout]): return self.layout.recovery_ship @property - def mission_departure_time(self) -> timedelta: - return self.patrol_end_time - - @property - def patrol_start_time(self) -> timedelta: + def mission_begin_on_station_time(self) -> timedelta: return self.package.time_over_target @property - def patrol_end_time(self) -> timedelta: + def mission_departure_time(self) -> timedelta: return self.tot + timedelta(hours=2) def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None: diff --git a/game/ato/flightplans/sweep.py b/game/ato/flightplans/sweep.py index 1ff3718d..f5043eef 100644 --- a/game/ato/flightplans/sweep.py +++ b/game/ato/flightplans/sweep.py @@ -89,6 +89,10 @@ class SweepFlightPlan(LoiterFlightPlan): GroundSpeed.for_flight(self.flight, self.layout.hold.alt), ) + @property + def mission_begin_on_station_time(self) -> timedelta | None: + return None + def mission_departure_time(self) -> timedelta: return self.sweep_end_time diff --git a/game/missiongenerator/aircraft/flightgroupconfigurator.py b/game/missiongenerator/aircraft/flightgroupconfigurator.py index b3d6e73c..8d7a58aa 100644 --- a/game/missiongenerator/aircraft/flightgroupconfigurator.py +++ b/game/missiongenerator/aircraft/flightgroupconfigurator.py @@ -10,12 +10,11 @@ from dcs.unit import Skill from dcs.unitgroup import FlyingGroup from game.ato import Flight, FlightType -from game.ato.flightplans.shiprecoverytanker import RecoveryTankerFlightPlan from game.callsigns import callsign_for_support_unit from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum -from game.missiongenerator.missiondata import MissionData, AwacsInfo, TankerInfo from game.missiongenerator.lasercoderegistry import LaserCodeRegistry from game.missiongenerator.logisticsgenerator import LogisticsGenerator +from game.missiongenerator.missiondata import AwacsInfo, MissionData, TankerInfo from game.radio.radios import RadioFrequency, RadioRegistry from game.radio.tacan import TacanBand, TacanRegistry, TacanUsage from game.runways import RunwayData @@ -25,8 +24,6 @@ from .aircraftbehavior import AircraftBehavior from .aircraftpainter import AircraftPainter from .flightdata import FlightData from .waypoints import WaypointGenerator -from ...ato.flightplans.aewc import AewcFlightPlan -from ...ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan if TYPE_CHECKING: from game import Game @@ -149,7 +146,7 @@ class FlightGroupConfigurator: def register_air_support(self, channel: RadioFrequency) -> None: callsign = callsign_for_support_unit(self.group) - if isinstance(self.flight.flight_plan, AewcFlightPlan): + if self.flight.flight_type is FlightType.AEWC: self.mission_data.awacs.append( AwacsInfo( group_name=str(self.group.name), @@ -161,9 +158,7 @@ class FlightGroupConfigurator: blue=self.flight.departure.captured, ) ) - elif isinstance( - self.flight.flight_plan, TheaterRefuelingFlightPlan - ) or isinstance(self.flight.flight_plan, RecoveryTankerFlightPlan): + elif self.flight.flight_type is FlightType.REFUELING: tacan = self.tacan_registry.alloc_for_band(TacanBand.Y, TacanUsage.AirToAir) self.mission_data.tankers.append( TankerInfo( @@ -172,8 +167,8 @@ class FlightGroupConfigurator: variant=self.flight.unit_type.name, freq=channel, tacan=tacan, - start_time=self.flight.flight_plan.patrol_start_time, - end_time=self.flight.flight_plan.patrol_end_time, + start_time=self.flight.flight_plan.mission_begin_on_station_time, + end_time=self.flight.flight_plan.mission_departure_time, blue=self.flight.departure.captured, ) )