mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Recovery tanker follow up (#2659)
Fix timing issues for RecoveryTankerFlightPlan. AEWC and Refueling can be planned on LHA.
This commit is contained in:
parent
22503d4e95
commit
0fd0f0e7c0
@ -15,6 +15,7 @@ Saves from 6.0.0 are compatible with 6.1.0
|
|||||||
* **[Engine]** Support for DCS 2.8.1.34437.
|
* **[Engine]** Support for DCS 2.8.1.34437.
|
||||||
* **[Factions]** Defaulted bluefor modern to use Georgian and Ukrainian liveries for Russian aircraft.
|
* **[Factions]** Defaulted bluefor modern to use Georgian and Ukrainian liveries for Russian aircraft.
|
||||||
* **[Factions]** Added Peru.
|
* **[Factions]** Added Peru.
|
||||||
|
* **[Flight Planning]** AEW&C and Refueling flights are now plannable on LHA carriers.
|
||||||
* **[Flight Planning]** Refueling flights planned on aircraft carriers will act as a recovery tanker for the carrier.
|
* **[Flight Planning]** Refueling flights planned on aircraft carriers will act as a recovery tanker for the carrier.
|
||||||
* **[Loadouts]** Adjusted F-15E loadouts.
|
* **[Loadouts]** Adjusted F-15E loadouts.
|
||||||
* **[Mission Generation]** The previous turn will now be saved as last_turn.liberation when submitting mission results. This is often essential for debugging bug reports. **Include this file in the bug report whenever it is available.**
|
* **[Mission Generation]** The previous turn will now be saved as last_turn.liberation when submitting mission results. This is often essential for debugging bug reports. **Include this file in the bug report whenever it is available.**
|
||||||
|
|||||||
@ -3,8 +3,7 @@ from __future__ import annotations
|
|||||||
from typing import Any, TYPE_CHECKING, Type
|
from typing import Any, TYPE_CHECKING, Type
|
||||||
|
|
||||||
from game.ato import FlightType
|
from game.ato import FlightType
|
||||||
from game.ato.flightplans.shiprecoverytanker import RecoveryTankerFlightPlan
|
from game.theater.controlpoint import NavalControlPoint
|
||||||
from game.theater.controlpoint import Carrier
|
|
||||||
from .aewc import AewcFlightPlan
|
from .aewc import AewcFlightPlan
|
||||||
from .airassault import AirAssaultFlightPlan
|
from .airassault import AirAssaultFlightPlan
|
||||||
from .airlift import AirliftFlightPlan
|
from .airlift import AirliftFlightPlan
|
||||||
@ -21,6 +20,7 @@ from .ocarunway import OcaRunwayFlightPlan
|
|||||||
from .packagerefueling import PackageRefuelingFlightPlan
|
from .packagerefueling import PackageRefuelingFlightPlan
|
||||||
from .planningerror import PlanningError
|
from .planningerror import PlanningError
|
||||||
from .sead import SeadFlightPlan
|
from .sead import SeadFlightPlan
|
||||||
|
from .shiprecoverytanker import RecoveryTankerFlightPlan
|
||||||
from .strike import StrikeFlightPlan
|
from .strike import StrikeFlightPlan
|
||||||
from .sweep import SweepFlightPlan
|
from .sweep import SweepFlightPlan
|
||||||
from .tarcap import TarCapFlightPlan
|
from .tarcap import TarCapFlightPlan
|
||||||
@ -37,7 +37,7 @@ class FlightPlanBuilderTypes:
|
|||||||
if flight.flight_type is FlightType.REFUELING:
|
if flight.flight_type is FlightType.REFUELING:
|
||||||
target = flight.package.target
|
target = flight.package.target
|
||||||
if target.is_friendly(flight.squadron.player) and isinstance(
|
if target.is_friendly(flight.squadron.player) and isinstance(
|
||||||
target, Carrier
|
target, NavalControlPoint
|
||||||
):
|
):
|
||||||
return RecoveryTankerFlightPlan.builder_type()
|
return RecoveryTankerFlightPlan.builder_type()
|
||||||
if target.is_friendly(flight.squadron.player) or isinstance(
|
if target.is_friendly(flight.squadron.player) or isinstance(
|
||||||
|
|||||||
@ -8,7 +8,6 @@ from game.ato.flightplans.ibuilder import IBuilder
|
|||||||
from game.ato.flightplans.standard import StandardLayout
|
from game.ato.flightplans.standard import StandardLayout
|
||||||
from game.ato.flightplans.waypointbuilder import WaypointBuilder
|
from game.ato.flightplans.waypointbuilder import WaypointBuilder
|
||||||
from game.ato.flightwaypoint import FlightWaypoint
|
from game.ato.flightwaypoint import FlightWaypoint
|
||||||
from game.utils import feet
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@ -39,7 +38,7 @@ class RecoveryTankerFlightPlan(StandardFlightPlan[RecoveryTankerLayout]):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def mission_departure_time(self) -> timedelta:
|
def mission_departure_time(self) -> timedelta:
|
||||||
return timedelta(hours=2)
|
return self.patrol_end_time
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def patrol_start_time(self) -> timedelta:
|
def patrol_start_time(self) -> timedelta:
|
||||||
@ -47,7 +46,7 @@ class RecoveryTankerFlightPlan(StandardFlightPlan[RecoveryTankerLayout]):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def patrol_end_time(self) -> timedelta:
|
def patrol_end_time(self) -> timedelta:
|
||||||
return self.tot + self.mission_departure_time
|
return self.tot + timedelta(hours=2)
|
||||||
|
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||||
if waypoint == self.tot_waypoint:
|
if waypoint == self.tot_waypoint:
|
||||||
@ -56,28 +55,33 @@ class RecoveryTankerFlightPlan(StandardFlightPlan[RecoveryTankerLayout]):
|
|||||||
|
|
||||||
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||||
if waypoint == self.tot_waypoint:
|
if waypoint == self.tot_waypoint:
|
||||||
return self.tot + self.mission_departure_time
|
return self.mission_departure_time
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Builder(IBuilder[RecoveryTankerFlightPlan, RecoveryTankerLayout]):
|
class Builder(IBuilder[RecoveryTankerFlightPlan, RecoveryTankerLayout]):
|
||||||
def layout(self) -> RecoveryTankerLayout:
|
def layout(self) -> RecoveryTankerLayout:
|
||||||
|
|
||||||
# TODO: Propagate the ship position.
|
|
||||||
ship = self.package.target.position
|
|
||||||
|
|
||||||
builder = WaypointBuilder(self.flight, self.coalition)
|
builder = WaypointBuilder(self.flight, self.coalition)
|
||||||
|
|
||||||
recovery = builder.recovery_tanker(ship)
|
# TODO: Propagate the ship position to the Tanker's TOT,
|
||||||
|
# so that we minimize the tanker's need to catch up to the carrier.
|
||||||
|
recovery_ship = self.package.target.position
|
||||||
|
recovery_tanker = builder.recovery_tanker(recovery_ship)
|
||||||
|
|
||||||
|
# We don't have per aircraft cruise altitudes, so just reuse patrol altitude?
|
||||||
tanker_type = self.flight.unit_type
|
tanker_type = self.flight.unit_type
|
||||||
altitude = tanker_type.preferred_patrol_altitude
|
nav_cruise_altitude = tanker_type.preferred_patrol_altitude
|
||||||
|
|
||||||
return RecoveryTankerLayout(
|
return RecoveryTankerLayout(
|
||||||
departure=builder.takeoff(self.flight.departure),
|
departure=builder.takeoff(self.flight.departure),
|
||||||
nav_to=builder.nav_path(self.flight.departure.position, ship, altitude),
|
nav_to=builder.nav_path(
|
||||||
nav_from=builder.nav_path(ship, self.flight.arrival.position, altitude),
|
self.flight.departure.position, recovery_ship, nav_cruise_altitude
|
||||||
recovery_ship=recovery,
|
),
|
||||||
|
nav_from=builder.nav_path(
|
||||||
|
recovery_ship, self.flight.arrival.position, nav_cruise_altitude
|
||||||
|
),
|
||||||
|
recovery_ship=recovery_tanker,
|
||||||
arrival=builder.land(self.flight.arrival),
|
arrival=builder.land(self.flight.arrival),
|
||||||
divert=builder.divert(self.flight.divert),
|
divert=builder.divert(self.flight.divert),
|
||||||
bullseye=builder.bullseye(),
|
bullseye=builder.bullseye(),
|
||||||
|
|||||||
@ -2,24 +2,27 @@ from dcs.point import MovingPoint
|
|||||||
from dcs.task import ActivateBeaconCommand, RecoveryTanker
|
from dcs.task import ActivateBeaconCommand, RecoveryTanker
|
||||||
|
|
||||||
from game.ato import FlightType
|
from game.ato import FlightType
|
||||||
from game.missiongenerator.missiondata import TankerInfo
|
|
||||||
from game.utils import feet, knots
|
from game.utils import feet, knots
|
||||||
from .pydcswaypointbuilder import PydcsWaypointBuilder
|
from .pydcswaypointbuilder import PydcsWaypointBuilder
|
||||||
|
|
||||||
|
|
||||||
class RecoveryTankerBuilder(PydcsWaypointBuilder):
|
class RecoveryTankerBuilder(PydcsWaypointBuilder):
|
||||||
def add_tasks(self, waypoint: MovingPoint) -> None:
|
def add_tasks(self, waypoint: MovingPoint) -> None:
|
||||||
if self.flight.flight_type == FlightType.REFUELING:
|
|
||||||
group_id = self._get_carrier_group_id()
|
|
||||||
speed = knots(250).meters_per_second
|
|
||||||
altitude = feet(6000).meters
|
|
||||||
# Last waypoint has index of 1.
|
|
||||||
last_waypoint = 2
|
|
||||||
recovery_tanker = RecoveryTanker(group_id, speed, altitude, last_waypoint)
|
|
||||||
|
|
||||||
waypoint.add_task(recovery_tanker)
|
assert self.flight.flight_type == FlightType.REFUELING
|
||||||
|
group_id = self._get_carrier_group_id()
|
||||||
|
speed = knots(250).meters_per_second
|
||||||
|
altitude = feet(6000).meters
|
||||||
|
|
||||||
self.configure_tanker_tacan(waypoint)
|
# Last waypoint has index of 1.
|
||||||
|
# Give the tanker a end condition of the last carrier waypoint.
|
||||||
|
# If the carrier ever gets more than one waypoint this approach needs to change.
|
||||||
|
last_waypoint = 2
|
||||||
|
recovery_tanker = RecoveryTanker(group_id, speed, altitude, last_waypoint)
|
||||||
|
|
||||||
|
waypoint.add_task(recovery_tanker)
|
||||||
|
|
||||||
|
self.configure_tanker_tacan(waypoint)
|
||||||
|
|
||||||
def _get_carrier_group_id(self) -> int:
|
def _get_carrier_group_id(self) -> int:
|
||||||
name = self.package.target.name
|
name = self.package.target.name
|
||||||
|
|||||||
@ -1177,6 +1177,8 @@ class NavalControlPoint(ControlPoint, ABC):
|
|||||||
|
|
||||||
if self.is_friendly(for_player):
|
if self.is_friendly(for_player):
|
||||||
yield from [
|
yield from [
|
||||||
|
FlightType.AEWC,
|
||||||
|
FlightType.REFUELING,
|
||||||
# TODO: FlightType.INTERCEPTION
|
# TODO: FlightType.INTERCEPTION
|
||||||
# TODO: Buddy tanking for the A-4?
|
# TODO: Buddy tanking for the A-4?
|
||||||
# TODO: Rescue chopper?
|
# TODO: Rescue chopper?
|
||||||
@ -1272,8 +1274,7 @@ class Carrier(NavalControlPoint):
|
|||||||
yield from super().mission_types(for_player)
|
yield from super().mission_types(for_player)
|
||||||
if self.is_friendly(for_player):
|
if self.is_friendly(for_player):
|
||||||
yield from [
|
yield from [
|
||||||
FlightType.AEWC,
|
# Nothing yet.
|
||||||
FlightType.REFUELING,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def capture(self, game: Game, events: GameUpdateEvents, for_player: bool) -> None:
|
def capture(self, game: Game, events: GameUpdateEvents, for_player: bool) -> None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user