From 94c5ed8bdca96c2d60a504ea928791067eb181d2 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Thu, 19 Nov 2020 00:29:05 -0800 Subject: [PATCH] Fix custom waypoints. Like with deleting waypoints, these will degrade the flight plan to the 2.1 behavior. Ascend/descend points aren't in use any more, so I removed those. --- game/theater/theatergroundobject.py | 8 +++ gen/flights/flightplan.py | 41 ++----------- gen/flights/traveltime.py | 7 ++- gen/flights/waypointbuilder.py | 55 ------------------ .../QPredefinedWaypointSelectionComboBox.py | 3 +- .../flight/waypoints/QFlightWaypointTab.py | 58 +++++++------------ .../QPredefinedWaypointSelectionWindow.py | 29 +++++----- 7 files changed, 58 insertions(+), 143 deletions(-) diff --git a/game/theater/theatergroundobject.py b/game/theater/theatergroundobject.py index 2a829de2..c267a0eb 100644 --- a/game/theater/theatergroundobject.py +++ b/game/theater/theatergroundobject.py @@ -101,6 +101,10 @@ class TheaterGroundObject(MissionTarget): """The name of the unit group.""" return f"{self.category}|{self.group_id}" + @property + def waypoint_name(self) -> str: + return f"[{self.name}] {self.category}" + def __str__(self) -> str: return NAME_BY_CATEGORY[self.category] @@ -155,6 +159,10 @@ class BuildingGroundObject(TheaterGroundObject): """The name of the unit group.""" return f"{self.category}|{self.group_id}|{self.object_id}" + @property + def waypoint_name(self) -> str: + return f"{super().waypoint_name} #{self.object_id}" + class NavalGroundObject(TheaterGroundObject): def mission_types(self, for_player: bool) -> Iterator[FlightType]: diff --git a/gen/flights/flightplan.py b/gen/flights/flightplan.py index 3b5c1e40..918861e2 100644 --- a/gen/flights/flightplan.py +++ b/gen/flights/flightplan.py @@ -769,7 +769,6 @@ class FlightPlanBuilder: builder = WaypointBuilder(self.game.conditions, flight, self.doctrine) start, end = builder.race_track(start, end, patrol_alt) - descent, land = builder.rtb(flight.from_cp) return BarCapFlightPlan( package=self.package, @@ -778,7 +777,7 @@ class FlightPlanBuilder: takeoff=builder.takeoff(flight.from_cp), patrol_start=start, patrol_end=end, - land=land + land=builder.land(flight.from_cp) ) def generate_sweep(self, flight: Flight) -> SweepFlightPlan: @@ -794,8 +793,6 @@ class FlightPlanBuilder: -self.doctrine.sweep_distance) builder = WaypointBuilder(self.game.conditions, flight, self.doctrine) - descent, land = builder.rtb(flight.from_cp) - start, end = builder.sweep(start, target, self.doctrine.ingress_altitude) @@ -807,7 +804,7 @@ class FlightPlanBuilder: hold=builder.hold(self._hold_point(flight)), sweep_start=start, sweep_end=end, - land=land + land=builder.land(flight.from_cp) ) def racetrack_for_objective(self, @@ -894,7 +891,6 @@ class FlightPlanBuilder: orbit0p, orbit1p = self.racetrack_for_objective(location) start, end = builder.race_track(orbit0p, orbit1p, patrol_alt) - descent, land = builder.rtb(flight.from_cp) return TarCapFlightPlan( package=self.package, flight=flight, @@ -907,7 +903,7 @@ class FlightPlanBuilder: takeoff=builder.takeoff(flight.from_cp), patrol_start=start, patrol_end=end, - land=land + land=builder.land(flight.from_cp) ) def generate_dead(self, flight: Flight, @@ -965,7 +961,6 @@ class FlightPlanBuilder: ingress, target, egress = builder.escort( self.package.waypoints.ingress, self.package.target, self.package.waypoints.egress) - descent, land = builder.rtb(flight.from_cp) return StrikeFlightPlan( package=self.package, @@ -977,7 +972,7 @@ class FlightPlanBuilder: targets=[target], egress=egress, split=builder.split(self.package.waypoints.split), - land=land + land=builder.land(flight.from_cp) ) def generate_cas(self, flight: Flight) -> CasFlightPlan: @@ -999,7 +994,6 @@ class FlightPlanBuilder: egress = ingress.point_from_heading(heading, distance) builder = WaypointBuilder(self.game.conditions, flight, self.doctrine) - descent, land = builder.rtb(flight.from_cp) return CasFlightPlan( package=self.package, @@ -1009,7 +1003,7 @@ class FlightPlanBuilder: patrol_start=builder.ingress_cas(ingress, location), target=builder.cas(center), patrol_end=builder.egress(egress, location), - land=land + land=builder.land(flight.from_cp) ) @staticmethod @@ -1081,28 +1075,6 @@ class FlightPlanBuilder: self.doctrine.hold_distance) # TODO: Make a model for the waypoint builder and use that in the UI. - def generate_ascend_point(self, flight: Flight, - departure: ControlPoint) -> FlightWaypoint: - """Generate ascend point. - - Args: - flight: The flight to generate the descend point for. - departure: Departure airfield or carrier. - """ - builder = WaypointBuilder(self.game.conditions, flight, self.doctrine) - return builder.ascent(departure) - - def generate_descend_point(self, flight: Flight, - arrival: ControlPoint) -> FlightWaypoint: - """Generate approach/descend point. - - Args: - flight: The flight to generate the descend point for. - arrival: Arrival airfield or carrier. - """ - builder = WaypointBuilder(self.game.conditions, flight, self.doctrine) - return builder.descent(arrival) - def generate_rtb_waypoint(self, flight: Flight, arrival: ControlPoint) -> FlightWaypoint: """Generate RTB landing point. @@ -1143,7 +1115,6 @@ class FlightPlanBuilder: target_waypoints.append( self.target_area_waypoint(flight, location, builder)) - descent, land = builder.rtb(flight.from_cp) return StrikeFlightPlan( package=self.package, flight=flight, @@ -1154,7 +1125,7 @@ class FlightPlanBuilder: targets=target_waypoints, egress=builder.egress(self.package.waypoints.egress, location), split=builder.split(self.package.waypoints.split), - land=land + land=builder.land(flight.from_cp) ) def _retreating_rendezvous_point(self, attack_transition: Point) -> Point: diff --git a/gen/flights/traveltime.py b/gen/flights/traveltime.py index f83708d9..742dfce3 100644 --- a/gen/flights/traveltime.py +++ b/gen/flights/traveltime.py @@ -118,8 +118,11 @@ class TotEstimator: def takeoff_time_for_flight(self, flight: Flight) -> Optional[timedelta]: travel_time = self.travel_time_to_rendezvous_or_target(flight) if travel_time is None: - logging.warning("Found no rendezvous or target point. Cannot " - f"estimate takeoff time takeoff time for {flight}") + from gen.flights.flightplan import CustomFlightPlan + if not isinstance(flight.flight_plan, CustomFlightPlan): + logging.warning( + "Found no rendezvous or target point. Cannot estimate " + f"takeoff time takeoff time for {flight}.") return None from gen.flights.flightplan import FormationFlightPlan diff --git a/gen/flights/waypointbuilder.py b/gen/flights/waypointbuilder.py index d22d4324..f220ebb4 100644 --- a/gen/flights/waypointbuilder.py +++ b/gen/flights/waypointbuilder.py @@ -58,52 +58,6 @@ class WaypointBuilder: waypoint.pretty_name = "Takeoff" return waypoint - def ascent(self, departure: ControlPoint) -> FlightWaypoint: - """Create ascent waypoint for the given departure airfield or carrier. - - Args: - departure: Departure airfield or carrier. - """ - heading = RunwayAssigner(self.conditions).takeoff_heading(departure) - position = departure.position.point_from_heading( - heading, nm_to_meter(5) - ) - waypoint = FlightWaypoint( - FlightWaypointType.ASCEND_POINT, - position.x, - position.y, - 500 if self.is_helo else self.doctrine.pattern_altitude - ) - waypoint.name = "ASCEND" - waypoint.alt_type = "RADIO" - waypoint.description = "Ascend" - waypoint.pretty_name = "Ascend" - return waypoint - - def descent(self, arrival: ControlPoint) -> FlightWaypoint: - """Create descent waypoint for the given arrival airfield or carrier. - - Args: - arrival: Arrival airfield or carrier. - """ - landing_heading = RunwayAssigner(self.conditions).landing_heading( - arrival) - heading = (landing_heading + 180) % 360 - position = arrival.position.point_from_heading( - heading, nm_to_meter(5) - ) - waypoint = FlightWaypoint( - FlightWaypointType.DESCENT_POINT, - position.x, - position.y, - 300 if self.is_helo else self.doctrine.pattern_altitude - ) - waypoint.name = "DESCEND" - waypoint.alt_type = "RADIO" - waypoint.description = "Descend to pattern altitude" - waypoint.pretty_name = "Descend" - return waypoint - @staticmethod def land(arrival: ControlPoint) -> FlightWaypoint: """Create descent waypoint for the given arrival airfield or carrier. @@ -385,15 +339,6 @@ class WaypointBuilder: return (self.sweep_start(start, altitude), self.sweep_end(end, altitude)) - def rtb(self, - arrival: ControlPoint) -> Tuple[FlightWaypoint, FlightWaypoint]: - """Creates descent ant landing waypoints for the given control point. - - Args: - arrival: Arrival airfield or carrier. - """ - return self.descent(arrival), self.land(arrival) - def escort(self, ingress: Point, target: MissionTarget, egress: Point) -> \ Tuple[FlightWaypoint, FlightWaypoint, FlightWaypoint]: """Creates the waypoints needed to escort the package. diff --git a/qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py b/qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py index c339ffb1..8af3c3f4 100644 --- a/qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py +++ b/qt_ui/widgets/combos/QPredefinedWaypointSelectionComboBox.py @@ -44,7 +44,6 @@ class QPredefinedWaypointSelectionComboBox(QFilteredComboBox): i = 0 def add_model_item(i, model, name, wpt): - print(name) item = QStandardItem(name) model.setItem(i, 0, item) self.wpts.append(wpt) @@ -79,7 +78,7 @@ class QPredefinedWaypointSelectionComboBox(QFilteredComboBox): 0 ) wpt.alt_type = "RADIO" - wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id) + wpt.name = ground_object.waypoint_name wpt.pretty_name = wpt.name wpt.obj_name = ground_object.obj_name wpt.targets.append(ground_object) diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py index 9eda4863..791c7d5b 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py @@ -1,5 +1,5 @@ import logging -from typing import List, Optional +from typing import Iterable, List, Optional from PySide2.QtCore import Signal from PySide2.QtWidgets import ( @@ -39,8 +39,6 @@ class QFlightWaypointTab(QFrame): self.planner = FlightPlanBuilder(self.game, package, is_player=True) self.flight_waypoint_list: Optional[QFlightWaypointList] = None - self.ascend_waypoint: Optional[QPushButton] = None - self.descend_waypoint: Optional[QPushButton] = None self.rtb_waypoint: Optional[QPushButton] = None self.delete_selected: Optional[QPushButton] = None self.open_fast_waypoint_button: Optional[QPushButton] = None @@ -74,14 +72,6 @@ class QFlightWaypointTab(QFrame): rlayout.addWidget(QLabel("Advanced : ")) rlayout.addWidget(QLabel("Do not use for AI flights")) - self.ascend_waypoint = QPushButton("Add Ascend Waypoint") - self.ascend_waypoint.clicked.connect(self.on_ascend_waypoint) - rlayout.addWidget(self.ascend_waypoint) - - self.descend_waypoint = QPushButton("Add Descend Waypoint") - self.descend_waypoint.clicked.connect(self.on_descend_waypoint) - rlayout.addWidget(self.descend_waypoint) - self.rtb_waypoint = QPushButton("Add RTB Waypoint") self.rtb_waypoint.clicked.connect(self.on_rtb_waypoint) rlayout.addWidget(self.rtb_waypoint) @@ -107,47 +97,43 @@ 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. - flight_plan = self.flight.flight_plan - if isinstance(flight_plan, StrikeFlightPlan): - if waypoint in flight_plan.targets and len(flight_plan.targets) > 1: - flight_plan.targets.remove(waypoint) + if isinstance(self.flight.flight_plan, StrikeFlightPlan): + is_target = waypoint in self.flight.flight_plan.targets + if is_target and len(self.flight.flight_plan.targets) > 1: + self.flight.flight_plan.targets.remove(waypoint) return - if not isinstance(flight_plan, CustomFlightPlan): - flight_plan = CustomFlightPlan( - package=self.flight.package, - flight=self.flight, - custom_waypoints=flight_plan.waypoints - ) - - flight_plan.waypoints.remove(waypoint) - self.flight.flight_plan = flight_plan + self.degrade_to_custom_flight_plan() + self.flight.flight_plan.waypoints.remove(waypoint) def on_fast_waypoint(self): self.subwindow = QPredefinedWaypointSelectionWindow(self.game, self.flight, self.flight_waypoint_list) - self.subwindow.finished.connect(self.on_change) + self.subwindow.waypoints_added.connect(self.on_waypoints_added) self.subwindow.show() - def on_ascend_waypoint(self): - ascend = self.planner.generate_ascend_point(self.flight, - self.flight.from_cp) - self.flight.points.append(ascend) + def on_waypoints_added(self, waypoints: Iterable[FlightWaypoint]) -> None: + if not waypoints: + return + self.degrade_to_custom_flight_plan() + self.flight.flight_plan.waypoints.extend(waypoints) self.flight_waypoint_list.update_list() self.on_change() def on_rtb_waypoint(self): rtb = self.planner.generate_rtb_waypoint(self.flight, self.flight.from_cp) - self.flight.points.append(rtb) + self.degrade_to_custom_flight_plan() + self.flight.flight_plan.waypoints.append(rtb) self.flight_waypoint_list.update_list() self.on_change() - def on_descend_waypoint(self): - descend = self.planner.generate_descend_point(self.flight, - self.flight.from_cp) - self.flight.points.append(descend) - self.flight_waypoint_list.update_list() - self.on_change() + def degrade_to_custom_flight_plan(self) -> None: + if not isinstance(self.flight.flight_plan, CustomFlightPlan): + self.flight.flight_plan = CustomFlightPlan( + package=self.flight.package, + flight=self.flight, + custom_waypoints=self.flight.flight_plan.waypoints + ) def confirm_recreate(self, task: FlightType) -> None: result = QMessageBox.question( diff --git a/qt_ui/windows/mission/flight/waypoints/QPredefinedWaypointSelectionWindow.py b/qt_ui/windows/mission/flight/waypoints/QPredefinedWaypointSelectionWindow.py index e7e2a90c..ccec5034 100644 --- a/qt_ui/windows/mission/flight/waypoints/QPredefinedWaypointSelectionWindow.py +++ b/qt_ui/windows/mission/flight/waypoints/QPredefinedWaypointSelectionWindow.py @@ -1,11 +1,20 @@ -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QCheckBox +from PySide2.QtCore import Qt, Signal +from PySide2.QtWidgets import ( + QCheckBox, + QDialog, + QHBoxLayout, + QLabel, + QPushButton, + QVBoxLayout, +) from game import Game from gen.flights.flight import Flight from qt_ui.uiconstants import EVENT_ICONS -from qt_ui.widgets.combos.QPredefinedWaypointSelectionComboBox import QPredefinedWaypointSelectionComboBox -from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import QFlightWaypointInfoBox +from qt_ui.widgets.combos.QPredefinedWaypointSelectionComboBox import \ + QPredefinedWaypointSelectionComboBox +from qt_ui.windows.mission.flight.waypoints.QFlightWaypointInfoBox import \ + QFlightWaypointInfoBox PREDEFINED_WAYPOINT_CATEGORIES = [ "Frontline (CAS AREA)", @@ -17,6 +26,8 @@ PREDEFINED_WAYPOINT_CATEGORIES = [ class QPredefinedWaypointSelectionWindow(QDialog): + # List of FlightWaypoint + waypoints_added = Signal(list) def __init__(self, game: Game, flight: Flight, flight_waypoint_list): super(QPredefinedWaypointSelectionWindow, self).__init__() @@ -44,7 +55,6 @@ class QPredefinedWaypointSelectionWindow(QDialog): self.init_ui() self.on_select_wpt_changed() - print("DONE") def init_ui(self): @@ -77,12 +87,5 @@ class QPredefinedWaypointSelectionWindow(QDialog): self.add_button.setDisabled(False) def add_waypoint(self): - - for wpt in self.selected_waypoints: - self.flight.points.append(wpt) - - self.flight_waypoint_list.update_list() + self.waypoints_added.emit(self.selected_waypoints) self.close() - - -