Allow squadron switch in flight's edit-dialog

This commit is contained in:
Raffson 2024-06-09 00:52:09 +02:00
parent b2315efb6c
commit 31630b4d42
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
5 changed files with 122 additions and 3 deletions

View File

@ -17,6 +17,7 @@
* **[ATO]** Allow planning as OPFOR
* **[Campaign Design]** Support for Kola map by Orbx
* **[UI]** Zoom level retained when switching campaigns
* **[UX]** Allow changing squadrons in flight's edit dialog
## Fixes
* **[UI/UX]** A-10A flights can be edited again

View File

@ -26,6 +26,8 @@ class QEditFlightDialog(QDialog):
self.game_model = game_model
self.flight = flight
self.package_model = package_model
self.events = GameUpdateEvents()
self.setWindowTitle("Edit flight")
self.setWindowIcon(EVENT_ICONS["strike"])
@ -34,11 +36,24 @@ class QEditFlightDialog(QDialog):
layout = QVBoxLayout()
self.flight_planner = QFlightPlanner(package_model, flight, game_model)
self.flight_planner.squadron_changed.connect(self.on_squadron_change)
layout.addWidget(self.flight_planner)
self.setLayout(layout)
self.finished.connect(self.on_close)
def on_close(self, _result) -> None:
EventStream.put_nowait(GameUpdateEvents().update_flight(self.flight))
def on_squadron_change(self, flight: Flight):
self.events = GameUpdateEvents().delete_flight(self.flight)
self.events = self.events.new_flight(flight)
self.game_model.ato_model.client_slots_changed.emit()
self.flight = flight
self.reject()
new_dialog = QEditFlightDialog(
self.game_model, self.package_model, flight, self.parent()
)
new_dialog.show()
def on_close(self, _result) -> None:
self.events = self.events.update_flight(self.flight)
EventStream.put_nowait(self.events)
self.game_model.ato_model.client_slots_changed.emit()

View File

@ -1,3 +1,4 @@
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QTabWidget
from game.ato.flight import Flight
@ -10,6 +11,8 @@ from qt_ui.windows.mission.flight.waypoints.QFlightWaypointTab import QFlightWay
class QFlightPlanner(QTabWidget):
squadron_changed = Signal(Flight)
def __init__(self, package_model: PackageModel, flight: Flight, gm: GameModel):
super().__init__()
@ -28,6 +31,7 @@ class QFlightPlanner(QTabWidget):
self.general_settings_tab.flight_size_changed.connect(
self.payload_tab.resize_for_flight
)
self.general_settings_tab.squadron_changed.connect(self.squadron_changed)
self.addTab(self.general_settings_tab, "General Flight settings")
self.addTab(self.payload_tab, "Payload")
self.addTab(self.waypoint_tab, "Waypoints")

View File

@ -11,14 +11,21 @@ from PySide6.QtWidgets import (
QHBoxLayout,
QCheckBox,
QVBoxLayout,
QPushButton,
QDialog,
QWidget,
)
from game import Game
from game.ato.closestairfields import ClosestAirfields
from game.ato.flight import Flight
from game.ato.flightroster import FlightRoster
from game.ato.iflightroster import IFlightRoster
from game.dcs.aircrafttype import AircraftType
from game.squadrons import Squadron
from game.squadrons.pilot import Pilot
from game.theater import ControlPoint, OffMapSpawn
from game.utils import nautical_miles
from qt_ui.models import PackageModel
@ -237,8 +244,49 @@ class FlightRosterEditor(QVBoxLayout):
controls.replace(squadron, new_roster)
class QSquadronSelector(QDialog):
def __init__(self, flight: Flight, parent: Optional[QWidget] = None):
super().__init__(parent)
self.flight = flight
self.parent = parent
self.init()
def init(self):
vbox = QVBoxLayout()
self.setLayout(vbox)
self.selector = QComboBox()
air_wing = self.flight.coalition.air_wing
for squadron in air_wing.best_squadrons_for(
self.flight.package.target,
self.flight.flight_type,
self.flight.roster.max_size,
self.flight.is_helo,
True,
ignore_range=True,
):
if squadron is self.flight.squadron:
continue
self.selector.addItem(
f"{squadron.name} - {squadron.aircraft.variant_id}", squadron
)
vbox.addWidget(self.selector)
hbox = QHBoxLayout()
accept = QPushButton("Accept")
accept.clicked.connect(self.accept)
hbox.addWidget(accept)
cancel = QPushButton("Cancel")
cancel.clicked.connect(self.reject)
hbox.addWidget(cancel)
vbox.addLayout(hbox)
class QFlightSlotEditor(QGroupBox):
flight_resized = Signal(int)
squadron_changed = Signal(Flight)
def __init__(
self,
@ -250,6 +298,10 @@ class QFlightSlotEditor(QGroupBox):
self.package_model = package_model
self.flight = flight
self.game = game
self.closest_airfields = ClosestAirfields(
flight.package.target,
list(game.theater.control_points_for(self.flight.coalition.player)),
)
available = self.flight.squadron.untasked_aircraft
max_count = self.flight.count + available
if max_count > 4:
@ -268,7 +320,12 @@ class QFlightSlotEditor(QGroupBox):
layout.addWidget(self.aircraft_count_spinner, 0, 1)
layout.addWidget(QLabel("Squadron:"), 1, 0)
layout.addWidget(QLabel(str(self.flight.squadron)), 1, 1)
hbox = QHBoxLayout()
hbox.addWidget(QLabel(str(self.flight.squadron)))
squadron_btn = QPushButton("Change Squadron")
squadron_btn.clicked.connect(self._change_squadron)
hbox.addWidget(squadron_btn)
layout.addLayout(hbox, 1, 1)
layout.addWidget(QLabel("Assigned pilots:"), 2, 0)
self.roster_editor = FlightRosterEditor(flight.squadron, flight.roster)
@ -276,6 +333,46 @@ class QFlightSlotEditor(QGroupBox):
self.setLayout(layout)
def _change_squadron(self):
dialog = QSquadronSelector(self.flight)
if dialog.exec():
squadron: Optional[Squadron] = dialog.selector.currentData()
if not squadron:
return
flight = Flight(
self.package_model.package,
squadron,
self.flight.count,
self.flight.flight_type,
self.flight.start_type,
self._find_divert_field(squadron.aircraft, squadron.location),
frequency=self.flight.frequency,
cargo=self.flight.cargo,
channel=self.flight.tacan,
callsign_tcn=self.flight.tcn_name,
)
self.package_model.add_flight(flight)
self.package_model.delete_flight(self.flight)
self.squadron_changed.emit(flight)
def _find_divert_field(
self, aircraft: AircraftType, arrival: ControlPoint
) -> Optional[ControlPoint]:
divert_limit = nautical_miles(150)
for airfield in self.closest_airfields.operational_airfields_within(
divert_limit
):
if airfield.captured != self.flight.coalition.player:
continue
if airfield == arrival:
continue
if not airfield.can_operate(aircraft):
continue
if isinstance(airfield, OffMapSpawn):
continue
return airfield
return None
def _changed_aircraft_count(self):
old_count = self.flight.count
new_count = int(self.aircraft_count_spinner.value())

View File

@ -21,6 +21,7 @@ from qt_ui.windows.mission.flight.waypoints.QFlightWaypointList import (
class QGeneralFlightSettingsTab(QFrame):
flight_size_changed = Signal()
squadron_changed = Signal(Flight)
def __init__(
self,
@ -36,6 +37,7 @@ class QGeneralFlightSettingsTab(QFrame):
self.flight_slot_editor = QFlightSlotEditor(package_model, flight, game.game)
self.flight_slot_editor.flight_resized.connect(self.flight_size_changed)
self.flight_slot_editor.squadron_changed.connect(self.squadron_changed)
for pc in self.flight_slot_editor.roster_editor.pilot_controls:
pc.player_toggled.connect(self.on_player_toggle)
pc.player_toggled.connect(