mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
113 lines
4.5 KiB
Python
113 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, TYPE_CHECKING, Type
|
|
|
|
from game.ato import FlightType
|
|
from .aewc import AewcFlightPlan
|
|
from .airassault import AirAssaultFlightPlan
|
|
from .airlift import AirliftFlightPlan
|
|
from .antiship import AntiShipFlightPlan
|
|
from .bai import BaiFlightPlan
|
|
from .barcap import BarCapFlightPlan
|
|
from .cas import CasFlightPlan
|
|
from .dead import DeadFlightPlan
|
|
from .escort import EscortFlightPlan
|
|
from .ferry import FerryFlightPlan
|
|
from .flightplan import FlightPlan
|
|
from .ocaaircraft import OcaAircraftFlightPlan
|
|
from .ocarunway import OcaRunwayFlightPlan
|
|
from .packagerefueling import PackageRefuelingFlightPlan
|
|
from .planningerror import PlanningError
|
|
from .sead import SeadFlightPlan
|
|
from .strike import StrikeFlightPlan
|
|
from .sweep import SweepFlightPlan
|
|
from .tarcap import TarCapFlightPlan
|
|
from .theaterrefueling import TheaterRefuelingFlightPlan
|
|
from ..packagewaypoints import PackageWaypoints
|
|
|
|
if TYPE_CHECKING:
|
|
from game.ato import Flight, Package
|
|
from game.coalition import Coalition
|
|
from game.theater import ConflictTheater, FrontLine
|
|
|
|
|
|
class FlightPlanBuilder:
|
|
"""Generates flight plans for flights."""
|
|
|
|
def __init__(
|
|
self, package: Package, coalition: Coalition, theater: ConflictTheater
|
|
) -> None:
|
|
# TODO: Plan similar altitudes for the in-country leg of the mission.
|
|
# Waypoint altitudes for a given flight *shouldn't* differ too much
|
|
# between the join and split points, so we don't need speeds for each
|
|
# leg individually since they should all be fairly similar. This doesn't
|
|
# hold too well right now since nothing is stopping each waypoint from
|
|
# jumping 20k feet each time, but that's a huge waste of energy we
|
|
# should be avoiding anyway.
|
|
self.package = package
|
|
self.coalition = coalition
|
|
self.theater = theater
|
|
|
|
@property
|
|
def is_player(self) -> bool:
|
|
return self.coalition.player
|
|
|
|
def populate_flight_plan(self, flight: Flight) -> None:
|
|
"""Creates a default flight plan for the given mission."""
|
|
if flight not in self.package.flights:
|
|
raise RuntimeError("Flight must be a part of the package")
|
|
|
|
from game.navmesh import NavMeshError
|
|
|
|
try:
|
|
if self.package.waypoints is None:
|
|
self.package.waypoints = PackageWaypoints.create(
|
|
self.package, self.coalition
|
|
)
|
|
flight.flight_plan = self.generate_flight_plan(flight)
|
|
except NavMeshError as ex:
|
|
color = "blue" if self.is_player else "red"
|
|
raise PlanningError(
|
|
f"Could not plan {color} {flight.flight_type.value} from "
|
|
f"{flight.departure} to {flight.package.target}"
|
|
) from ex
|
|
|
|
def plan_type(self, task: FlightType) -> Type[FlightPlan[Any]] | None:
|
|
plan_type: Type[FlightPlan[Any]]
|
|
if task == FlightType.REFUELING:
|
|
if self.package.target.is_friendly(self.is_player) or isinstance(
|
|
self.package.target, FrontLine
|
|
):
|
|
return TheaterRefuelingFlightPlan
|
|
return PackageRefuelingFlightPlan
|
|
|
|
plan_dict: dict[FlightType, Type[FlightPlan[Any]]] = {
|
|
FlightType.ANTISHIP: AntiShipFlightPlan,
|
|
FlightType.BAI: BaiFlightPlan,
|
|
FlightType.BARCAP: BarCapFlightPlan,
|
|
FlightType.CAS: CasFlightPlan,
|
|
FlightType.DEAD: DeadFlightPlan,
|
|
FlightType.ESCORT: EscortFlightPlan,
|
|
FlightType.OCA_AIRCRAFT: OcaAircraftFlightPlan,
|
|
FlightType.OCA_RUNWAY: OcaRunwayFlightPlan,
|
|
FlightType.SEAD: SeadFlightPlan,
|
|
FlightType.SEAD_ESCORT: EscortFlightPlan,
|
|
FlightType.STRIKE: StrikeFlightPlan,
|
|
FlightType.SWEEP: SweepFlightPlan,
|
|
FlightType.TARCAP: TarCapFlightPlan,
|
|
FlightType.AEWC: AewcFlightPlan,
|
|
FlightType.TRANSPORT: AirliftFlightPlan,
|
|
FlightType.FERRY: FerryFlightPlan,
|
|
FlightType.AIR_ASSAULT: AirAssaultFlightPlan,
|
|
}
|
|
return plan_dict.get(task)
|
|
|
|
def generate_flight_plan(self, flight: Flight) -> FlightPlan[Any]:
|
|
plan_type = self.plan_type(flight.flight_type)
|
|
if plan_type is None:
|
|
raise PlanningError(
|
|
f"{flight.flight_type} flight plan generation not implemented"
|
|
)
|
|
layout = plan_type.builder_type()(flight, self.theater).build()
|
|
return plan_type(flight, layout)
|