mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Allow user to add navigation waypoints where possible
This commit is contained in:
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import TYPE_CHECKING, Type
|
||||
from typing import TYPE_CHECKING, Type, Optional
|
||||
|
||||
from game.theater.missiontarget import MissionTarget
|
||||
from game.utils import feet
|
||||
@@ -12,6 +12,7 @@ from .ibuilder import IBuilder
|
||||
from .planningerror import PlanningError
|
||||
from .standard import StandardFlightPlan, StandardLayout
|
||||
from .waypointbuilder import WaypointBuilder
|
||||
from ..flightwaypointtype import FlightWaypointType
|
||||
from ...theater.interfaces.CTLD import CTLD
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -21,7 +22,6 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass
|
||||
class AirliftLayout(StandardLayout):
|
||||
nav_to_pickup: list[FlightWaypoint]
|
||||
# There will not be a pickup waypoint when the pickup airfield is the departure
|
||||
# airfield for cargo planes, as the cargo is pre-loaded. Helicopters will still pick
|
||||
# up the cargo near the airfield.
|
||||
@@ -36,25 +36,30 @@ class AirliftLayout(StandardLayout):
|
||||
drop_off: FlightWaypoint | None
|
||||
# drop_off_zone will be used for player flights to create the CTLD stuff
|
||||
ctld_drop_off_zone: FlightWaypoint | None
|
||||
nav_to_home: list[FlightWaypoint]
|
||||
|
||||
def add_waypoint(
|
||||
self, wpt: FlightWaypoint, next_wpt: Optional[FlightWaypoint]
|
||||
) -> bool:
|
||||
new_wpt = self.get_midpoint(wpt, next_wpt)
|
||||
if wpt.waypoint_type in [
|
||||
FlightWaypointType.PICKUP_ZONE,
|
||||
FlightWaypointType.CARGO_STOP,
|
||||
]:
|
||||
self.nav_to_drop_off.insert(0, new_wpt)
|
||||
return True
|
||||
return super().add_waypoint(wpt, next_wpt)
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if super().delete_waypoint(waypoint):
|
||||
return True
|
||||
if waypoint in self.nav_to_pickup:
|
||||
self.nav_to_pickup.remove(waypoint)
|
||||
return True
|
||||
elif waypoint in self.nav_to_drop_off:
|
||||
if waypoint in self.nav_to_drop_off:
|
||||
self.nav_to_drop_off.remove(waypoint)
|
||||
return True
|
||||
elif waypoint in self.nav_to_home:
|
||||
self.nav_to_home.remove(waypoint)
|
||||
elif super().delete_waypoint(waypoint):
|
||||
return True
|
||||
return False
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
yield from self.nav_to_pickup
|
||||
yield from self.nav_to
|
||||
if self.pickup is not None:
|
||||
yield self.pickup
|
||||
if self.ctld_pickup_zone is not None:
|
||||
@@ -64,7 +69,7 @@ class AirliftLayout(StandardLayout):
|
||||
yield self.drop_off
|
||||
if self.ctld_drop_off_zone is not None:
|
||||
yield self.ctld_drop_off_zone
|
||||
yield from self.nav_to_home
|
||||
yield from self.nav_from
|
||||
yield self.arrival
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
@@ -141,7 +146,7 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
||||
|
||||
return AirliftLayout(
|
||||
departure=builder.takeoff(self.flight.departure),
|
||||
nav_to_pickup=nav_to_pickup,
|
||||
nav_to=nav_to_pickup,
|
||||
pickup=pickup,
|
||||
ctld_pickup_zone=pickup_zone,
|
||||
nav_to_drop_off=builder.nav_path(
|
||||
@@ -152,7 +157,7 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
||||
),
|
||||
drop_off=drop_off,
|
||||
ctld_drop_off_zone=drop_off_zone,
|
||||
nav_to_home=builder.nav_path(
|
||||
nav_from=builder.nav_path(
|
||||
cargo.origin.position,
|
||||
self.flight.arrival.position,
|
||||
altitude,
|
||||
|
||||
@@ -29,6 +29,10 @@ class CustomFlightPlan(FlightPlan[CustomLayout]):
|
||||
def builder_type() -> Type[Builder]:
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def is_custom(self) -> bool:
|
||||
return True
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
target_types = (
|
||||
|
||||
@@ -17,19 +17,9 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass
|
||||
class FerryLayout(StandardLayout):
|
||||
nav_to_destination: list[FlightWaypoint]
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if super().delete_waypoint(waypoint):
|
||||
return True
|
||||
if waypoint in self.nav_to_destination:
|
||||
self.nav_to_destination.remove(waypoint)
|
||||
return True
|
||||
return False
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
yield from self.nav_to_destination
|
||||
yield from self.nav_to
|
||||
yield self.arrival
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
@@ -76,7 +66,7 @@ class Builder(IBuilder[FerryFlightPlan, FerryLayout]):
|
||||
builder = WaypointBuilder(self.flight, self.coalition)
|
||||
return FerryLayout(
|
||||
departure=builder.takeoff(self.flight.departure),
|
||||
nav_to_destination=builder.nav_path(
|
||||
nav_to=builder.nav_path(
|
||||
self.flight.departure.position,
|
||||
self.flight.arrival.position,
|
||||
altitude,
|
||||
@@ -85,6 +75,7 @@ class Builder(IBuilder[FerryFlightPlan, FerryLayout]):
|
||||
arrival=builder.land(self.flight.arrival),
|
||||
divert=builder.divert(self.flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
nav_from=[],
|
||||
)
|
||||
|
||||
def build(self) -> FerryFlightPlan:
|
||||
|
||||
@@ -317,6 +317,10 @@ class FlightPlan(ABC, Generic[LayoutT]):
|
||||
def is_airassault(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_custom(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def mission_departure_time(self) -> timedelta:
|
||||
"""The time that the mission is complete and the flight RTBs."""
|
||||
|
||||
@@ -18,24 +18,16 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass
|
||||
class FormationLayout(LoiterLayout, ABC):
|
||||
nav_to: list[FlightWaypoint]
|
||||
join: Optional[FlightWaypoint]
|
||||
split: FlightWaypoint
|
||||
refuel: Optional[FlightWaypoint]
|
||||
nav_from: list[FlightWaypoint]
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if super().delete_waypoint(waypoint):
|
||||
return True
|
||||
if waypoint in self.nav_to:
|
||||
self.nav_to.remove(waypoint)
|
||||
return True
|
||||
elif waypoint in self.nav_from:
|
||||
self.nav_from.remove(waypoint)
|
||||
return True
|
||||
elif waypoint == self.refuel:
|
||||
if waypoint == self.refuel:
|
||||
self.refuel = None
|
||||
return True
|
||||
elif super().delete_waypoint(waypoint):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -18,21 +18,8 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass
|
||||
class PatrollingLayout(StandardLayout):
|
||||
nav_to: list[FlightWaypoint]
|
||||
patrol_start: FlightWaypoint
|
||||
patrol_end: FlightWaypoint
|
||||
nav_from: list[FlightWaypoint]
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if super().delete_waypoint(waypoint):
|
||||
return True
|
||||
if waypoint in self.nav_to:
|
||||
self.nav_to.remove(waypoint)
|
||||
return True
|
||||
elif waypoint in self.nav_from:
|
||||
self.nav_from.remove(waypoint)
|
||||
return True
|
||||
return False
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
|
||||
@@ -18,12 +18,11 @@ if TYPE_CHECKING:
|
||||
@dataclass
|
||||
class RtbLayout(StandardLayout):
|
||||
abort_location: FlightWaypoint
|
||||
nav_to_destination: list[FlightWaypoint]
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
yield self.abort_location
|
||||
yield from self.nav_to_destination
|
||||
yield from self.nav_to
|
||||
yield self.arrival
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
@@ -78,7 +77,7 @@ class Builder(IBuilder[RtbFlightPlan, RtbLayout]):
|
||||
return RtbLayout(
|
||||
departure=builder.takeoff(self.flight.departure),
|
||||
abort_location=abort_point,
|
||||
nav_to_destination=builder.nav_path(
|
||||
nav_to=builder.nav_path(
|
||||
current_position,
|
||||
self.flight.arrival.position,
|
||||
altitude,
|
||||
@@ -87,6 +86,7 @@ class Builder(IBuilder[RtbFlightPlan, RtbLayout]):
|
||||
arrival=builder.land(self.flight.arrival),
|
||||
divert=builder.divert(self.flight.divert),
|
||||
bullseye=builder.bullseye(),
|
||||
nav_from=[],
|
||||
)
|
||||
|
||||
def build(self) -> RtbFlightPlan:
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
from typing import TYPE_CHECKING, TypeVar, Optional
|
||||
|
||||
from game.ato.flightplans.flightplan import FlightPlan, Layout
|
||||
from .waypointbuilder import WaypointBuilder
|
||||
from ..flightwaypointtype import FlightWaypointType
|
||||
from ...utils import feet
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
@@ -15,11 +19,57 @@ class StandardLayout(Layout, ABC):
|
||||
arrival: FlightWaypoint
|
||||
divert: FlightWaypoint | None
|
||||
bullseye: FlightWaypoint
|
||||
nav_to: list[FlightWaypoint]
|
||||
nav_from: list[FlightWaypoint]
|
||||
|
||||
def add_waypoint(
|
||||
self, wpt: FlightWaypoint, next_wpt: Optional[FlightWaypoint]
|
||||
) -> bool:
|
||||
new_wpt = self.get_midpoint(wpt, next_wpt)
|
||||
if wpt.waypoint_type in [FlightWaypointType.TAKEOFF, FlightWaypointType.LOITER]:
|
||||
self.nav_to.insert(0, new_wpt)
|
||||
return True
|
||||
elif wpt.waypoint_type in [
|
||||
FlightWaypointType.SPLIT,
|
||||
FlightWaypointType.REFUEL,
|
||||
FlightWaypointType.PATROL,
|
||||
FlightWaypointType.EGRESS,
|
||||
]:
|
||||
self.nav_from.insert(0, new_wpt)
|
||||
return True
|
||||
elif wpt.waypoint_type is FlightWaypointType.NAV:
|
||||
if wpt in self.nav_to:
|
||||
index = self.nav_to.index(wpt) + 1
|
||||
self.nav_to.insert(index, new_wpt)
|
||||
return True
|
||||
elif wpt in self.nav_from:
|
||||
index = self.nav_from.index(wpt) + 1
|
||||
self.nav_from.insert(index, new_wpt)
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_midpoint(
|
||||
wpt: FlightWaypoint, next_wpt: Optional[FlightWaypoint]
|
||||
) -> FlightWaypoint:
|
||||
new_pos = deepcopy(wpt.position)
|
||||
next_alt = feet(20000)
|
||||
if next_wpt:
|
||||
new_pos = wpt.position.lerp(next_wpt.position, 0.5)
|
||||
next_alt = next_wpt.alt
|
||||
new_wpt = WaypointBuilder.nav(new_pos, max(wpt.alt, next_alt))
|
||||
return new_wpt
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if waypoint is self.divert:
|
||||
self.divert = None
|
||||
return True
|
||||
elif waypoint in self.nav_to:
|
||||
self.nav_to.remove(waypoint)
|
||||
return True
|
||||
elif waypoint in self.nav_from:
|
||||
self.nav_from.remove(waypoint)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@ class TarCapLayout(PatrollingLayout):
|
||||
yield self.divert
|
||||
yield self.bullseye
|
||||
|
||||
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
|
||||
if waypoint == self.refuel:
|
||||
self.refuel = None
|
||||
return True
|
||||
elif super().delete_waypoint(waypoint):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class TarCapFlightPlan(PatrollingFlightPlan[TarCapLayout]):
|
||||
@property
|
||||
|
||||
Reference in New Issue
Block a user