mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
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:
parent
8363a7e8fa
commit
198ff7d8a3
@ -16,6 +16,7 @@
|
||||
* **[Modding]** Support for Iron Dome v1.2 by IDF Mods Project
|
||||
* **[New Game Wizard]** Re-organized generator options & show the regular settings menu instead of the limited "Difficulty & Automation" page.
|
||||
* **[Campaign Management]** Ability to operate harriers from FOBs/FARPs for <ins>__human pilots only__</ins>. Please note that the autoplanner won't generate flights for harriers at FOBs/FARPs, which means you need to plan your missions manually.
|
||||
* **[Mission Planning]** Allow NAV/REFUEL/DIVERT waypoints to be deleted without degrading to a custom flight-plan, also warning the user before actually degrading the flight-plan.
|
||||
|
||||
## Fixes
|
||||
* **[New Game Wizard]** Settings would not persist when going back to a previous page (obsolete due to overhaul).
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@dataclass
|
||||
class CasLayout(PatrollingLayout):
|
||||
target: FlightWaypoint
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@dataclass
|
||||
class CustomLayout(Layout):
|
||||
custom_waypoints: list[FlightWaypoint]
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@dataclass
|
||||
class LoiterLayout(StandardLayout, ABC):
|
||||
hold: FlightWaypoint
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -15,7 +15,7 @@ if TYPE_CHECKING:
|
||||
from ..flightwaypoint import FlightWaypoint
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@dataclass
|
||||
class TarCapLayout(PatrollingLayout):
|
||||
refuel: FlightWaypoint | None
|
||||
|
||||
|
||||
@ -437,7 +437,7 @@ class WaypointBuilder:
|
||||
|
||||
return FlightWaypoint(
|
||||
"SEAD Search",
|
||||
FlightWaypointType.CUSTOM,
|
||||
FlightWaypointType.INGRESS_SEAD,
|
||||
hold,
|
||||
self.doctrine.ingress_altitude,
|
||||
alt_type="BARO",
|
||||
|
||||
@ -109,13 +109,28 @@ class QFlightWaypointTab(QFrame):
|
||||
# Need to degrade to a custom flight plan and remove the waypoint.
|
||||
# If the waypoint is a target waypoint and is not the last target
|
||||
# waypoint, we don't need to degrade.
|
||||
if isinstance(self.flight.flight_plan, FormationAttackFlightPlan):
|
||||
is_target = waypoint in self.flight.flight_plan.target_area_waypoint.targets
|
||||
count = len(self.flight.flight_plan.target_area_waypoint.targets)
|
||||
fp = self.flight.flight_plan
|
||||
if isinstance(fp, FormationAttackFlightPlan):
|
||||
is_target = waypoint in fp.target_area_waypoint.targets
|
||||
count = len(fp.target_area_waypoint.targets)
|
||||
if is_target and count > 1:
|
||||
self.flight.flight_plan.target_area_waypoint.targets.remove(waypoint)
|
||||
fp.target_area_waypoint.targets.remove(waypoint)
|
||||
return
|
||||
|
||||
if fp.layout.delete_waypoint(waypoint):
|
||||
return
|
||||
|
||||
result = QMessageBox.warning(
|
||||
self,
|
||||
"Degrade flight-plan?",
|
||||
"Deleting the selected waypoint(s) will require degradation to a custom flight-plan. "
|
||||
"A custom flight-plan will no longer respect the TOTs of the package.<br><br>"
|
||||
"<b>Are you sure you wish to continue?</b>",
|
||||
QMessageBox.Yes,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if result == QMessageBox.No:
|
||||
return
|
||||
self.degrade_to_custom_flight_plan()
|
||||
assert isinstance(self.flight.flight_plan, CustomFlightPlan)
|
||||
self.flight.flight_plan.layout.custom_waypoints.remove(waypoint)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user