mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add arrival/divert airfield selection.
Breaks save compat because it adds new fields to `Flight` that have no constant default. Removing all of our other save compat at the same time. Note that player flights with a divert point will have a nav point for their actual landing point. This is because we place the divert point last, and DCS won't let us have a land point anywhere but the final waypoint. It would allow a LandingReFuAr point, but they're only generated for player flights anyway so it doesn't really matter. Fixes https://github.com/Khopa/dcs_liberation/issues/342
This commit is contained in:
47
qt_ui/widgets/combos/QArrivalAirfieldSelector.py
Normal file
47
qt_ui/widgets/combos/QArrivalAirfieldSelector.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""Combo box for selecting a departure airfield."""
|
||||
from typing import Iterable
|
||||
|
||||
from PySide2.QtWidgets import QComboBox
|
||||
from dcs.planes import PlaneType
|
||||
|
||||
from game import db
|
||||
from game.theater.controlpoint import ControlPoint
|
||||
|
||||
|
||||
class QArrivalAirfieldSelector(QComboBox):
|
||||
"""A combo box for selecting a flight's arrival or divert airfield.
|
||||
|
||||
The combo box will automatically be populated with all airfields the given
|
||||
aircraft type is able to land at.
|
||||
"""
|
||||
|
||||
def __init__(self, destinations: Iterable[ControlPoint],
|
||||
aircraft: PlaneType, optional_text: str) -> None:
|
||||
super().__init__()
|
||||
self.destinations = list(destinations)
|
||||
self.aircraft = aircraft
|
||||
self.optional_text = optional_text
|
||||
self.rebuild_selector()
|
||||
self.setCurrentIndex(0)
|
||||
|
||||
def change_aircraft(self, aircraft: PlaneType) -> None:
|
||||
if self.aircraft == aircraft:
|
||||
return
|
||||
self.aircraft = aircraft
|
||||
self.rebuild_selector()
|
||||
|
||||
def valid_destination(self, destination: ControlPoint) -> bool:
|
||||
if destination.is_carrier and self.aircraft not in db.CARRIER_CAPABLE:
|
||||
return False
|
||||
if destination.is_lha and self.aircraft not in db.LHA_CAPABLE:
|
||||
return False
|
||||
return True
|
||||
|
||||
def rebuild_selector(self) -> None:
|
||||
self.clear()
|
||||
for destination in self.destinations:
|
||||
if self.valid_destination(destination):
|
||||
self.addItem(destination.name, destination)
|
||||
self.model().sort(0)
|
||||
self.insertItem(0, self.optional_text, None)
|
||||
self.update()
|
||||
@@ -373,6 +373,10 @@ class QLiberationMap(QGraphicsView):
|
||||
FlightWaypointType.TARGET_SHIP,
|
||||
)
|
||||
for idx, point in enumerate(flight.flight_plan.waypoints[1:]):
|
||||
if point.waypoint_type == FlightWaypointType.DIVERT:
|
||||
# Don't clutter the map showing divert points.
|
||||
continue
|
||||
|
||||
new_pos = self._transform_point(Point(point.x, point.y))
|
||||
self.draw_flight_path(scene, prev_pos, new_pos, is_player,
|
||||
selected)
|
||||
@@ -386,7 +390,6 @@ class QLiberationMap(QGraphicsView):
|
||||
self.draw_waypoint_info(scene, idx + 1, point, new_pos,
|
||||
flight.flight_plan)
|
||||
prev_pos = tuple(new_pos)
|
||||
self.draw_flight_path(scene, prev_pos, pos, is_player, selected)
|
||||
|
||||
def draw_waypoint(self, scene: QGraphicsScene, position: Tuple[int, int],
|
||||
player: bool, selected: bool) -> None:
|
||||
|
||||
@@ -16,6 +16,8 @@ from qt_ui.uiconstants import EVENT_ICONS
|
||||
from qt_ui.widgets.QFlightSizeSpinner import QFlightSizeSpinner
|
||||
from qt_ui.widgets.QLabeledWidget import QLabeledWidget
|
||||
from qt_ui.widgets.combos.QAircraftTypeSelector import QAircraftTypeSelector
|
||||
from qt_ui.widgets.combos.QArrivalAirfieldSelector import \
|
||||
QArrivalAirfieldSelector
|
||||
from qt_ui.widgets.combos.QFlightTypeComboBox import QFlightTypeComboBox
|
||||
from qt_ui.widgets.combos.QOriginAirfieldSelector import QOriginAirfieldSelector
|
||||
from theater import ControlPoint, OffMapSpawn
|
||||
@@ -49,16 +51,30 @@ class QFlightCreator(QDialog):
|
||||
self.on_aircraft_changed)
|
||||
layout.addLayout(QLabeledWidget("Aircraft:", self.aircraft_selector))
|
||||
|
||||
self.airfield_selector = QOriginAirfieldSelector(
|
||||
self.departure = QOriginAirfieldSelector(
|
||||
self.game.aircraft_inventory,
|
||||
[cp for cp in game.theater.controlpoints if cp.captured],
|
||||
self.aircraft_selector.currentData()
|
||||
)
|
||||
self.airfield_selector.availability_changed.connect(self.update_max_size)
|
||||
layout.addLayout(QLabeledWidget("Airfield:", self.airfield_selector))
|
||||
self.departure.availability_changed.connect(self.update_max_size)
|
||||
layout.addLayout(QLabeledWidget("Departure:", self.departure))
|
||||
|
||||
self.arrival = QArrivalAirfieldSelector(
|
||||
[cp for cp in game.theater.controlpoints if cp.captured],
|
||||
self.aircraft_selector.currentData(),
|
||||
"Same as departure"
|
||||
)
|
||||
layout.addLayout(QLabeledWidget("Arrival:", self.arrival))
|
||||
|
||||
self.divert = QArrivalAirfieldSelector(
|
||||
[cp for cp in game.theater.controlpoints if cp.captured],
|
||||
self.aircraft_selector.currentData(),
|
||||
"None"
|
||||
)
|
||||
layout.addLayout(QLabeledWidget("Divert:", self.divert))
|
||||
|
||||
self.flight_size_spinner = QFlightSizeSpinner()
|
||||
self.update_max_size(self.airfield_selector.available)
|
||||
self.update_max_size(self.departure.available)
|
||||
layout.addLayout(QLabeledWidget("Size:", self.flight_size_spinner))
|
||||
|
||||
self.client_slots_spinner = QFlightSizeSpinner(
|
||||
@@ -82,10 +98,16 @@ class QFlightCreator(QDialog):
|
||||
|
||||
def verify_form(self) -> Optional[str]:
|
||||
aircraft: PlaneType = self.aircraft_selector.currentData()
|
||||
origin: ControlPoint = self.airfield_selector.currentData()
|
||||
origin: ControlPoint = self.departure.currentData()
|
||||
arrival: ControlPoint = self.arrival.currentData()
|
||||
divert: ControlPoint = self.divert.currentData()
|
||||
size: int = self.flight_size_spinner.value()
|
||||
if not origin.captured:
|
||||
return f"{origin.name} is not owned by your coalition."
|
||||
if arrival is not None and not arrival.captured:
|
||||
return f"{arrival.name} is not owned by your coalition."
|
||||
if divert is not None and not divert.captured:
|
||||
return f"{divert.name} is not owned by your coalition."
|
||||
available = origin.base.aircraft.get(aircraft, 0)
|
||||
if not available:
|
||||
return f"{origin.name} has no {aircraft.id} available."
|
||||
@@ -104,16 +126,22 @@ class QFlightCreator(QDialog):
|
||||
|
||||
task = self.task_selector.currentData()
|
||||
aircraft = self.aircraft_selector.currentData()
|
||||
origin = self.airfield_selector.currentData()
|
||||
origin = self.departure.currentData()
|
||||
arrival = self.arrival.currentData()
|
||||
divert = self.divert.currentData()
|
||||
size = self.flight_size_spinner.value()
|
||||
|
||||
if arrival is None:
|
||||
arrival = origin
|
||||
|
||||
if isinstance(origin, OffMapSpawn):
|
||||
start_type = "In Flight"
|
||||
elif self.game.settings.perf_ai_parking_start:
|
||||
start_type = "Cold"
|
||||
else:
|
||||
start_type = "Warm"
|
||||
flight = Flight(self.package, aircraft, size, origin, task, start_type)
|
||||
flight = Flight(self.package, aircraft, size, task, start_type, origin,
|
||||
arrival, divert)
|
||||
flight.client_count = self.client_slots_spinner.value()
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
@@ -122,7 +150,9 @@ class QFlightCreator(QDialog):
|
||||
|
||||
def on_aircraft_changed(self, index: int) -> None:
|
||||
new_aircraft = self.aircraft_selector.itemData(index)
|
||||
self.airfield_selector.change_aircraft(new_aircraft)
|
||||
self.departure.change_aircraft(new_aircraft)
|
||||
self.arrival.change_aircraft(new_aircraft)
|
||||
self.divert.change_aircraft(new_aircraft)
|
||||
|
||||
def update_max_size(self, available: int) -> None:
|
||||
self.flight_size_spinner.setMaximum(min(available, 4))
|
||||
|
||||
Reference in New Issue
Block a user