mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Recovery tanker support (#429)
* fix conflict * squash bugs and reuse patrol layout * fix tanker tacan and formatting * fix unlimited fuel option * update pretense for tanker changes * reuse refueling flight plan and bugfix for sunken carrier changelog * remove unitmap dependency * formatting and more unit map removal * more formatting * typing and black * keep tanker out of clouds * fix if there are no clouds * better cloud handling * groundwork for recovery task * remove changes to game/commander * Finishing up recovery tankers --------- Co-authored-by: Raffson <Raffson@users.noreply.github.com>
This commit is contained in:
@@ -60,6 +60,16 @@ class CustomFlightPlan(FlightPlan[CustomLayout]):
|
||||
def mission_departure_time(self) -> datetime:
|
||||
return self.package.time_over_target
|
||||
|
||||
@property
|
||||
def landing_time(self) -> datetime:
|
||||
arrival = (
|
||||
self.layout.custom_waypoints[-1]
|
||||
if self.layout.custom_waypoints
|
||||
else self.layout.departure
|
||||
)
|
||||
return_time = self.total_time_between_waypoints(self.tot_waypoint, arrival)
|
||||
return self.tot + return_time
|
||||
|
||||
|
||||
class Builder(IBuilder[CustomFlightPlan, CustomLayout]):
|
||||
def __init__(
|
||||
|
||||
@@ -296,6 +296,10 @@ class FlightPlan(ABC, Generic[LayoutT]):
|
||||
"""The time that the mission is complete and the flight RTBs."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def landing_time(self) -> datetime:
|
||||
raise NotImplementedError
|
||||
|
||||
@self_type_guard
|
||||
def is_loiter(self, flight_plan: FlightPlan[Any]) -> TypeGuard[LoiterFlightPlan]:
|
||||
return False
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
from typing import Any, TYPE_CHECKING, Type
|
||||
|
||||
from game.ato import FlightType
|
||||
from game.theater.controlpoint import NavalControlPoint
|
||||
from .aewc import AewcFlightPlan
|
||||
from .airassault import AirAssaultFlightPlan
|
||||
from .airlift import AirliftFlightPlan
|
||||
@@ -22,6 +23,7 @@ from .planningerror import PlanningError
|
||||
from .pretensecargo import PretenseCargoFlightPlan
|
||||
from .sead import SeadFlightPlan
|
||||
from .seadsweep import SeadSweepFlightPlan
|
||||
from .shiprecoverytanker import RecoveryTankerFlightPlan
|
||||
from .strike import StrikeFlightPlan
|
||||
from .sweep import SweepFlightPlan
|
||||
from .tarcap import TarCapFlightPlan
|
||||
@@ -64,6 +66,7 @@ class FlightPlanBuilderTypes:
|
||||
FlightType.AIR_ASSAULT: AirAssaultFlightPlan.builder_type(),
|
||||
FlightType.PRETENSE_CARGO: PretenseCargoFlightPlan.builder_type(),
|
||||
FlightType.ARMED_RECON: ArmedReconFlightPlan.builder_type(),
|
||||
FlightType.RECOVERY: RecoveryTankerFlightPlan.builder_type(),
|
||||
}
|
||||
try:
|
||||
return builder_dict[flight.flight_type]
|
||||
|
||||
61
game/ato/flightplans/shiprecoverytanker.py
Normal file
61
game/ato/flightplans/shiprecoverytanker.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Type
|
||||
|
||||
from game.ato.flightplans.ibuilder import IBuilder
|
||||
from game.ato.flightplans.waypointbuilder import WaypointBuilder
|
||||
from .patrolling import PatrollingLayout
|
||||
from .refuelingflightplan import RefuelingFlightPlan
|
||||
from .. import FlightWaypoint
|
||||
from ...utils import knots
|
||||
|
||||
|
||||
class RecoveryTankerFlightPlan(RefuelingFlightPlan):
|
||||
@staticmethod
|
||||
def builder_type() -> Type[Builder]:
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def patrol_duration(self) -> timedelta:
|
||||
return self.flight.coalition.game.settings.desired_tanker_on_station_time
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.departure
|
||||
|
||||
|
||||
class Builder(IBuilder[RecoveryTankerFlightPlan, PatrollingLayout]):
|
||||
def layout(self) -> PatrollingLayout:
|
||||
|
||||
builder = WaypointBuilder(self.flight)
|
||||
altitude = builder.get_patrol_altitude
|
||||
|
||||
station_time = self.coalition.game.settings.desired_tanker_on_station_time
|
||||
time_to_landing = station_time.total_seconds()
|
||||
hdg = (self.coalition.game.conditions.weather.wind.at_0m.direction + 180) % 360
|
||||
recovery_ship = self.package.target.position.point_from_heading(
|
||||
hdg, time_to_landing * knots(20).meters_per_second
|
||||
)
|
||||
recovery_tanker = builder.recovery_tanker(recovery_ship)
|
||||
patrol_end = builder.race_track_end(recovery_tanker.position, altitude)
|
||||
patrol_end.only_for_player = True # avoid generating the waypoints
|
||||
|
||||
return PatrollingLayout(
|
||||
departure=builder.takeoff(self.flight.departure),
|
||||
nav_to=builder.nav_path(
|
||||
self.flight.departure.position, recovery_ship, altitude
|
||||
),
|
||||
nav_from=builder.nav_path(
|
||||
recovery_ship, self.flight.arrival.position, altitude
|
||||
),
|
||||
patrol_start=recovery_tanker,
|
||||
patrol_end=patrol_end,
|
||||
arrival=builder.land(self.flight.arrival),
|
||||
divert=builder.divert(self.flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
custom_waypoints=list(),
|
||||
)
|
||||
|
||||
def build(self, dump_debug_info: bool = False) -> RecoveryTankerFlightPlan:
|
||||
return RecoveryTankerFlightPlan(self.flight, self.layout())
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
from abc import ABC
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, TypeVar, Optional
|
||||
|
||||
from game.ato.flightplans.flightplan import FlightPlan, Layout
|
||||
@@ -86,3 +87,10 @@ class StandardFlightPlan(FlightPlan[LayoutT], ABC):
|
||||
others are guaranteed to have certain properties like departure and arrival points,
|
||||
potentially a divert field, and a bullseye
|
||||
"""
|
||||
|
||||
@property
|
||||
def landing_time(self) -> datetime:
|
||||
return_time = self.total_time_between_waypoints(
|
||||
self.tot_waypoint, self.layout.arrival
|
||||
)
|
||||
return self.tot + return_time
|
||||
|
||||
@@ -800,3 +800,18 @@ class WaypointBuilder:
|
||||
x_adj = random.randint(int(-deviation.meters), int(deviation.meters))
|
||||
y_adj = random.randint(int(-deviation.meters), int(deviation.meters))
|
||||
return point + Vector2(x_adj, y_adj)
|
||||
|
||||
@staticmethod
|
||||
def recovery_tanker(position: Point) -> FlightWaypoint:
|
||||
alt_type: AltitudeReference = "BARO"
|
||||
|
||||
return FlightWaypoint(
|
||||
"RECOVERY",
|
||||
FlightWaypointType.RECOVERY_TANKER,
|
||||
position,
|
||||
feet(6000),
|
||||
alt_type,
|
||||
description="Recovery tanker for aircraft carriers",
|
||||
pretty_name="Recovery",
|
||||
only_for_player=True, # for visual purposes in Retribution only
|
||||
)
|
||||
|
||||
@@ -60,6 +60,7 @@ class FlightType(Enum):
|
||||
SEAD_SWEEP = "SEAD Sweep" # Reintroduce legacy "engage-whatever-you-can-find" SEAD
|
||||
PRETENSE_CARGO = "Cargo Transport" # For Pretense campaign AI cargo planes
|
||||
ARMED_RECON = "Armed Recon"
|
||||
RECOVERY = "Recovery"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
@@ -117,6 +118,7 @@ class FlightType(Enum):
|
||||
FlightType.INTERCEPTION: AirEntity.FIGHTER,
|
||||
FlightType.OCA_AIRCRAFT: AirEntity.ATTACK_STRIKE,
|
||||
FlightType.OCA_RUNWAY: AirEntity.ATTACK_STRIKE,
|
||||
FlightType.RECOVERY: AirEntity.TANKER,
|
||||
FlightType.REFUELING: AirEntity.TANKER,
|
||||
FlightType.SEAD: AirEntity.SUPPRESSION_OF_ENEMY_AIR_DEFENCE,
|
||||
FlightType.SEAD_ESCORT: AirEntity.SUPPRESSION_OF_ENEMY_AIR_DEFENCE,
|
||||
|
||||
@@ -52,3 +52,4 @@ class FlightWaypointType(IntEnum):
|
||||
INGRESS_ANTI_SHIP = 32
|
||||
INGRESS_SEAD_SWEEP = 33
|
||||
INGRESS_ARMED_RECON = 34
|
||||
RECOVERY_TANKER = 35 # Tanker recovery point
|
||||
|
||||
@@ -188,6 +188,7 @@ class Package(RadioFrequencyContainer):
|
||||
FlightType.BARCAP,
|
||||
FlightType.AEWC,
|
||||
FlightType.FERRY,
|
||||
FlightType.RECOVERY,
|
||||
FlightType.REFUELING,
|
||||
FlightType.SWEEP,
|
||||
FlightType.SEAD_ESCORT,
|
||||
|
||||
Reference in New Issue
Block a user