mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Implemented spawning of Pretense cargo aircraft. To support that, implemented a separate flight plan called PretenseCargoFlightPlan. Also, will now automatically generate transport squadrons for factions which don't have pre-defined squadrons for it, but have access to transport aircraft.
This commit is contained in:
@@ -18,6 +18,7 @@ from .ocaaircraft import OcaAircraftFlightPlan
|
||||
from .ocarunway import OcaRunwayFlightPlan
|
||||
from .packagerefueling import PackageRefuelingFlightPlan
|
||||
from .planningerror import PlanningError
|
||||
from .pretensecargo import PretenseCargoFlightPlan
|
||||
from .sead import SeadFlightPlan
|
||||
from .seadsweep import SeadSweepFlightPlan
|
||||
from .strike import StrikeFlightPlan
|
||||
@@ -60,6 +61,7 @@ class FlightPlanBuilderTypes:
|
||||
FlightType.TRANSPORT: AirliftFlightPlan.builder_type(),
|
||||
FlightType.FERRY: FerryFlightPlan.builder_type(),
|
||||
FlightType.AIR_ASSAULT: AirAssaultFlightPlan.builder_type(),
|
||||
FlightType.PRETENSE_CARGO: PretenseCargoFlightPlan.builder_type(),
|
||||
}
|
||||
try:
|
||||
return builder_dict[flight.flight_type]
|
||||
|
||||
99
game/ato/flightplans/pretensecargo.py
Normal file
99
game/ato/flightplans/pretensecargo.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import TYPE_CHECKING, Type
|
||||
|
||||
from game.utils import feet
|
||||
from .ferry import FerryLayout
|
||||
from .ibuilder import IBuilder
|
||||
from .planningerror import PlanningError
|
||||
from .standard import StandardFlightPlan, StandardLayout
|
||||
from .waypointbuilder import WaypointBuilder
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
|
||||
|
||||
PRETENSE_CARGO_FLIGHT_DISTANCE = 50000
|
||||
|
||||
|
||||
class PretenseCargoFlightPlan(StandardFlightPlan[FerryLayout]):
|
||||
@staticmethod
|
||||
def builder_type() -> Type[Builder]:
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.arrival
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
# TOT planning isn't really useful for ferries. They're behind the front
|
||||
# lines so no need to wait for escorts or for other missions to complete.
|
||||
return None
|
||||
|
||||
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def mission_departure_time(self) -> timedelta:
|
||||
return self.package.time_over_target
|
||||
|
||||
|
||||
class Builder(IBuilder[PretenseCargoFlightPlan, FerryLayout]):
|
||||
def layout(self) -> FerryLayout:
|
||||
# Find the spawn location for off-map transport planes
|
||||
distance_to_flot = 0
|
||||
heading_from_flot = 0.0
|
||||
offmap_transport_cp_id = self.flight.departure.id
|
||||
for front_line_cp in self.coalition.game.theater.controlpoints:
|
||||
for front_line in self.coalition.game.theater.conflicts():
|
||||
if front_line_cp.captured == self.flight.coalition.player:
|
||||
if (
|
||||
front_line_cp.position.distance_to_point(front_line.position)
|
||||
> distance_to_flot
|
||||
):
|
||||
distance_to_flot = front_line_cp.position.distance_to_point(
|
||||
front_line.position
|
||||
)
|
||||
heading_from_flot = front_line.position.heading_between_point(
|
||||
front_line_cp.position
|
||||
)
|
||||
offmap_transport_cp_id = front_line_cp.id
|
||||
offmap_transport_cp = self.coalition.game.theater.find_control_point_by_id(
|
||||
offmap_transport_cp_id
|
||||
)
|
||||
offmap_transport_spawn = offmap_transport_cp.position.point_from_heading(
|
||||
heading_from_flot, PRETENSE_CARGO_FLIGHT_DISTANCE
|
||||
)
|
||||
|
||||
altitude_is_agl = self.flight.unit_type.dcs_unit_type.helicopter
|
||||
altitude = (
|
||||
feet(1500)
|
||||
if altitude_is_agl
|
||||
else self.flight.unit_type.preferred_patrol_altitude
|
||||
)
|
||||
|
||||
builder = WaypointBuilder(self.flight, self.coalition)
|
||||
ferry_layout = FerryLayout(
|
||||
departure=builder.join(offmap_transport_spawn),
|
||||
nav_to=builder.nav_path(
|
||||
offmap_transport_spawn,
|
||||
self.flight.arrival.position,
|
||||
altitude,
|
||||
altitude_is_agl,
|
||||
),
|
||||
arrival=builder.land(self.flight.arrival),
|
||||
divert=builder.divert(self.flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
nav_from=[],
|
||||
)
|
||||
ferry_layout.departure = builder.join(offmap_transport_spawn)
|
||||
ferry_layout.nav_to.append(builder.join(offmap_transport_spawn))
|
||||
ferry_layout.nav_from.append(builder.join(offmap_transport_spawn))
|
||||
print(ferry_layout)
|
||||
return ferry_layout
|
||||
|
||||
def build(self) -> PretenseCargoFlightPlan:
|
||||
return PretenseCargoFlightPlan(self.flight, self.layout())
|
||||
@@ -29,11 +29,8 @@ class Navigating(InFlight):
|
||||
events.update_flight_position(self.flight, self.estimate_position())
|
||||
|
||||
def progress(self) -> float:
|
||||
# if next waypoint is very close, assume we reach it immediately to avoid divide
|
||||
# by zero error
|
||||
if self.total_time_to_next_waypoint.total_seconds() < 1:
|
||||
return 1.0
|
||||
|
||||
if self.total_time_to_next_waypoint.total_seconds() == 0.0:
|
||||
return 99.9
|
||||
return (
|
||||
self.elapsed_time.total_seconds()
|
||||
/ self.total_time_to_next_waypoint.total_seconds()
|
||||
|
||||
@@ -58,6 +58,9 @@ class FlightType(Enum):
|
||||
FERRY = "Ferry"
|
||||
AIR_ASSAULT = "Air Assault"
|
||||
SEAD_SWEEP = "SEAD Sweep" # Reintroduce legacy "engage-whatever-you-can-find" SEAD
|
||||
PRETENSE_CARGO = (
|
||||
"Cargo Transport" # Flight type for Pretense campaign AI cargo planes
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
@@ -121,5 +124,6 @@ class FlightType(Enum):
|
||||
FlightType.SWEEP: AirEntity.FIGHTER,
|
||||
FlightType.TARCAP: AirEntity.FIGHTER,
|
||||
FlightType.TRANSPORT: AirEntity.UTILITY,
|
||||
FlightType.PRETENSE_CARGO: AirEntity.UTILITY,
|
||||
FlightType.AIR_ASSAULT: AirEntity.ROTARY_WING,
|
||||
}.get(self, AirEntity.UNSPECIFIED)
|
||||
|
||||
Reference in New Issue
Block a user