diff --git a/gen/aircraft.py b/gen/aircraft.py index f4581989..9eeb1836 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -929,6 +929,14 @@ class AircraftConflictGenerator: group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) group.points[0].tasks.append(OptRestrictJettison(True)) + elif flight_type == FlightType.ESCORT: + group.task = Escort.name + self._setup_group(group, Escort, flight, dynamic_runways) + # TODO: Cleanup duplication... + group.points[0].tasks.clear() + group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) + group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire)) + group.points[0].tasks.append(OptRestrictJettison(True)) group.points[0].tasks.append(OptRTBOnBingoFuel(True)) group.points[0].tasks.append(OptRestrictAfterburner(True)) diff --git a/gen/flights/ai_flight_planner.py b/gen/flights/ai_flight_planner.py index e65dc74a..98ef2bd2 100644 --- a/gen/flights/ai_flight_planner.py +++ b/gen/flights/ai_flight_planner.py @@ -116,6 +116,8 @@ class AircraftAllocator: types = SEAD_CAPABLE elif flight.task == FlightType.STRIKE: types = STRIKE_CAPABLE + elif flight.task == FlightType.ESCORT: + types = CAP_CAPABLE else: logging.error(f"Unplannable flight type: {flight.task}") return None @@ -373,7 +375,7 @@ class CoalitionMissionPlanner: yield ProposedMission(sam, [ ProposedFlight(FlightType.DEAD, 2, self.MAX_SEAD_RANGE), # TODO: Max escort range. - ProposedFlight(FlightType.CAP, 2, self.MAX_SEAD_RANGE), + ProposedFlight(FlightType.ESCORT, 2, self.MAX_SEAD_RANGE), ]) # Plan strike missions. @@ -382,7 +384,7 @@ class CoalitionMissionPlanner: ProposedFlight(FlightType.STRIKE, 2, self.MAX_STRIKE_RANGE), # TODO: Max escort range. ProposedFlight(FlightType.SEAD, 2, self.MAX_STRIKE_RANGE), - ProposedFlight(FlightType.CAP, 2, self.MAX_STRIKE_RANGE), + ProposedFlight(FlightType.ESCORT, 2, self.MAX_STRIKE_RANGE), ]) def plan_missions(self) -> None: diff --git a/gen/flights/flightplan.py b/gen/flights/flightplan.py index ab22c13d..6a213f7a 100644 --- a/gen/flights/flightplan.py +++ b/gen/flights/flightplan.py @@ -67,6 +67,8 @@ class FlightPlanBuilder: self.generate_sead(flight, objective_location) elif task == FlightType.ELINT: logging.error("ELINT flight plan generation not implemented") + elif task == FlightType.ESCORT: + self.generate_escort(flight, objective_location) elif task == FlightType.EVAC: logging.error("Evac flight plan generation not implemented") elif task == FlightType.EWAR: @@ -310,6 +312,39 @@ class FlightPlanBuilder: flight.points = builder.build() + def generate_escort(self, flight: Flight, location: MissionTarget) -> None: + flight.flight_type = FlightType.ESCORT + + # TODO: Decide common waypoints for the package ahead of time. + # Packages should determine some common points like push, ingress, + # egress, and split points ahead of time so they can be shared by all + # flights. + heading = flight.from_cp.position.heading_between_point( + location.position + ) + ingress_heading = heading - 180 + 25 + + ingress_pos = location.position.point_from_heading( + ingress_heading, self.doctrine.ingress_egress_distance + ) + + egress_heading = heading - 180 - 25 + egress_pos = location.position.point_from_heading( + egress_heading, self.doctrine.ingress_egress_distance + ) + + patrol_alt = random.randint( + self.doctrine.min_patrol_altitude, + self.doctrine.max_patrol_altitude + ) + + builder = WaypointBuilder(self.doctrine) + builder.ascent(flight.from_cp) + builder.race_track(ingress_pos, egress_pos, patrol_alt) + builder.rtb(flight.from_cp) + + flight.points = builder.build() + def generate_cas(self, flight: Flight, location: MissionTarget) -> None: """Generate a CAS flight plan for the given target.