Allow deletion of certain types of waypoints

Resolves #60
NAV/REFUEL/DIVERT waypoints should have no effect on the timings.
This commit is contained in:
Raffson
2023-05-29 00:11:27 +02:00
parent 8363a7e8fa
commit 198ff7d8a3
17 changed files with 96 additions and 24 deletions

View File

@@ -4,11 +4,11 @@ from dataclasses import dataclass
from datetime import timedelta
from typing import Iterator, TYPE_CHECKING, Type
from ._common_ctld import generate_random_ctld_point
from game.ato.flightplans.standard import StandardFlightPlan, StandardLayout
from game.theater.controlpoint import ControlPointType
from game.theater.missiontarget import MissionTarget
from game.utils import Distance, feet, meters
from ._common_ctld import generate_random_ctld_point
from .ibuilder import IBuilder
from .planningerror import PlanningError
from .uizonedisplay import UiZone, UiZoneDisplay
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class AirAssaultLayout(StandardLayout):
# The pickup point is optional because we don't always need to load the cargo. When
# departing from a carrier, LHA, or off-map spawn, the cargo is pre-loaded.

View File

@@ -5,9 +5,9 @@ from dataclasses import dataclass
from datetime import timedelta
from typing import TYPE_CHECKING, Type
from ._common_ctld import generate_random_ctld_point
from game.theater.missiontarget import MissionTarget
from game.utils import feet
from ._common_ctld import generate_random_ctld_point
from .ibuilder import IBuilder
from .planningerror import PlanningError
from .standard import StandardFlightPlan, StandardLayout
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
from dcs import Point
@dataclass(frozen=True)
@dataclass
class AirliftLayout(StandardLayout):
nav_to_pickup: list[FlightWaypoint]
# There will not be a pickup waypoint when the pickup airfield is the departure
@@ -38,6 +38,20 @@ class AirliftLayout(StandardLayout):
ctld_drop_off_zone: FlightWaypoint | None
nav_to_home: list[FlightWaypoint]
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:
self.nav_to_drop_off.remove(waypoint)
return True
elif waypoint in self.nav_to_home:
self.nav_to_home.remove(waypoint)
return True
return False
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
yield self.departure
yield from self.nav_to_pickup

View File

@@ -18,7 +18,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class CasLayout(PatrollingLayout):
target: FlightWaypoint

View File

@@ -15,7 +15,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class CustomLayout(Layout):
custom_waypoints: list[FlightWaypoint]

View File

@@ -15,10 +15,18 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@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

View File

@@ -41,7 +41,7 @@ INGRESS_TYPES = {
}
@dataclass(frozen=True)
@dataclass
class Layout(ABC):
departure: FlightWaypoint
@@ -50,6 +50,9 @@ class Layout(ABC):
"""A list of all waypoints in the flight plan, in order."""
return list(self.iter_waypoints())
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
return False
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
"""Iterates over all waypoints in the flight plan, in order."""
raise NotImplementedError

View File

@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import timedelta
from functools import cached_property
from typing import Any, TYPE_CHECKING, TypeGuard
from typing import Any, TYPE_CHECKING, TypeGuard, Optional
from game.typeguard import self_type_guard
from game.utils import Speed
@@ -16,14 +16,28 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class FormationLayout(LoiterLayout, ABC):
nav_to: list[FlightWaypoint]
join: FlightWaypoint
split: FlightWaypoint
refuel: 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:
self.refuel = None
return True
return False
class FormationFlightPlan(LoiterFlightPlan, ABC):
@property

View File

@@ -10,7 +10,7 @@ from dcs import Point
from game.flightplan import HoldZoneGeometry
from game.theater import MissionTarget
from game.utils import Speed, meters, Distance
from game.utils import Speed, meters
from .flightplan import FlightPlan
from .formation import FormationFlightPlan, FormationLayout
from .ibuilder import IBuilder
@@ -130,7 +130,7 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC):
return super().tot_for_waypoint(waypoint)
@dataclass(frozen=True)
@dataclass
class FormationAttackLayout(FormationLayout):
ingress: FlightWaypoint
targets: list[FlightWaypoint]

View File

@@ -13,7 +13,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class LoiterLayout(StandardLayout, ABC):
hold: FlightWaypoint

View File

@@ -16,13 +16,24 @@ if TYPE_CHECKING:
from .flightplan import FlightPlan
@dataclass(frozen=True)
@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
yield from self.nav_to

View File

@@ -15,7 +15,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class RtbLayout(StandardLayout):
abort_location: FlightWaypoint
nav_to_destination: list[FlightWaypoint]

View File

@@ -10,12 +10,18 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class StandardLayout(Layout, ABC):
arrival: FlightWaypoint
divert: FlightWaypoint | None
bullseye: FlightWaypoint
def delete_waypoint(self, waypoint: FlightWaypoint) -> bool:
if waypoint is self.divert:
self.divert = None
return True
return False
LayoutT = TypeVar("LayoutT", bound=StandardLayout)

View File

@@ -17,7 +17,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class SweepLayout(LoiterLayout):
nav_to: list[FlightWaypoint]
sweep_start: FlightWaypoint

View File

@@ -15,7 +15,7 @@ if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint
@dataclass(frozen=True)
@dataclass
class TarCapLayout(PatrollingLayout):
refuel: FlightWaypoint | None

View File

@@ -437,7 +437,7 @@ class WaypointBuilder:
return FlightWaypoint(
"SEAD Search",
FlightWaypointType.CUSTOM,
FlightWaypointType.INGRESS_SEAD,
hold,
self.doctrine.ingress_altitude,
alt_type="BARO",