mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
134 lines
4.5 KiB
Python
134 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import timedelta
|
|
from typing import Type
|
|
|
|
from .airassault import AirAssaultLayout
|
|
from .airlift import AirliftLayout
|
|
from .formationattack import (
|
|
FormationAttackBuilder,
|
|
FormationAttackFlightPlan,
|
|
FormationAttackLayout,
|
|
)
|
|
from .waypointbuilder import WaypointBuilder
|
|
from .. import FlightType
|
|
from ..traveltime import TravelTime, GroundSpeed
|
|
from ...utils import feet
|
|
|
|
|
|
class EscortFlightPlan(FormationAttackFlightPlan):
|
|
@property
|
|
def push_time(self) -> timedelta:
|
|
hold2join_time = (
|
|
TravelTime.between_points(
|
|
self.layout.hold.position,
|
|
self.layout.join.position,
|
|
GroundSpeed.for_flight(self.flight, self.layout.hold.alt),
|
|
)
|
|
if self.layout.hold is not None
|
|
else timedelta(0)
|
|
)
|
|
return self.join_time - hold2join_time
|
|
|
|
@staticmethod
|
|
def builder_type() -> Type[Builder]:
|
|
return Builder
|
|
|
|
|
|
class Builder(FormationAttackBuilder[EscortFlightPlan, FormationAttackLayout]):
|
|
def layout(self) -> FormationAttackLayout:
|
|
assert self.package.waypoints is not None
|
|
|
|
builder = WaypointBuilder(self.flight, self.coalition)
|
|
ingress, target = builder.escort(
|
|
self.package.waypoints.ingress, self.package.target
|
|
)
|
|
ingress.only_for_player = True
|
|
target.only_for_player = True
|
|
hold = None
|
|
if not self.primary_flight_is_air_assault:
|
|
hold = builder.hold(self._hold_point())
|
|
elif self.package.primary_flight is not None:
|
|
fp = self.package.primary_flight.flight_plan
|
|
assert isinstance(fp.layout, AirAssaultLayout)
|
|
assert fp.layout.pickup is not None
|
|
hold = builder.hold(fp.layout.pickup.position)
|
|
|
|
join = builder.join(self.package.waypoints.join)
|
|
split = builder.split(self.package.waypoints.split)
|
|
|
|
ingress_alt = self.doctrine.ingress_altitude
|
|
initial = builder.escort_hold(
|
|
target.position
|
|
if builder.flight.is_helo
|
|
else self.package.waypoints.initial,
|
|
min(feet(500), ingress_alt) if builder.flight.is_helo else ingress_alt,
|
|
)
|
|
|
|
pf = self.package.primary_flight
|
|
if pf and pf.flight_type in [FlightType.AIR_ASSAULT, FlightType.TRANSPORT]:
|
|
layout = pf.flight_plan.layout
|
|
assert isinstance(layout, AirAssaultLayout) or isinstance(
|
|
layout, AirliftLayout
|
|
)
|
|
if isinstance(layout, AirliftLayout):
|
|
join = builder.join(layout.departure.position)
|
|
else:
|
|
join = builder.join(layout.ingress.position)
|
|
if layout.pickup:
|
|
join = builder.join(layout.pickup.position)
|
|
split = builder.split(layout.arrival.position)
|
|
if layout.drop_off:
|
|
initial = builder.escort_hold(
|
|
layout.drop_off.position,
|
|
min(feet(200), ingress_alt)
|
|
if builder.flight.is_helo
|
|
else ingress_alt,
|
|
)
|
|
|
|
refuel = None
|
|
if not self.flight.is_helo:
|
|
refuel = builder.refuel(self.package.waypoints.refuel)
|
|
|
|
departure = builder.takeoff(self.flight.departure)
|
|
if hold:
|
|
nav_to = builder.nav_path(
|
|
hold.position, join.position, self.doctrine.ingress_altitude
|
|
)
|
|
else:
|
|
nav_to = builder.nav_path(
|
|
departure.position, join.position, self.doctrine.ingress_altitude
|
|
)
|
|
|
|
if refuel:
|
|
nav_from = builder.nav_path(
|
|
refuel.position,
|
|
self.flight.arrival.position,
|
|
self.doctrine.ingress_altitude,
|
|
)
|
|
else:
|
|
nav_from = builder.nav_path(
|
|
split.position,
|
|
self.flight.arrival.position,
|
|
self.doctrine.ingress_altitude,
|
|
)
|
|
|
|
return FormationAttackLayout(
|
|
departure=departure,
|
|
hold=hold,
|
|
nav_to=nav_to,
|
|
join=join,
|
|
ingress=ingress,
|
|
initial=initial,
|
|
targets=[target],
|
|
split=split,
|
|
refuel=refuel,
|
|
nav_from=nav_from,
|
|
arrival=builder.land(self.flight.arrival),
|
|
divert=builder.divert(self.flight.divert),
|
|
bullseye=builder.bullseye(),
|
|
)
|
|
|
|
def build(self) -> EscortFlightPlan:
|
|
return EscortFlightPlan(self.flight, self.layout())
|