diff --git a/changelog.md b/changelog.md index 263c1508..4f334c32 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,8 @@ Saves from 7.0.0 are compatible with 7.1.0 * **[Mission Generation]** Added option to prevent scud and V2 sites from firing at the start of the mission. * **[Mission Generation]** Added settings for controlling number of tactical commander, observer, JTAC, and game master slots. * **[Mission Planning]** Per-flight TOT offsets can now be set in the flight details UI. This allows individual flights to be scheduled ahead of or behind the rest of the package. +* **[New Game Wizard]** The air wing configuration dialog will check for and reject overfull airbases before continuing when the new squadron rules are used. +* **[New Game Wizard]** Closing the air wing configuration dialog will now cancel and return to the new game wizard rather than reverting changes and continuing. * **[UI]** Parking capacity of each squadron's base is now shown during air wing configuration to avoid overcrowding bases when beginning the game with full squadrons. ## Fixes diff --git a/qt_ui/main.py b/qt_ui/main.py index 5672b10e..57988d17 100644 --- a/qt_ui/main.py +++ b/qt_ui/main.py @@ -13,7 +13,7 @@ import yaml from PySide6 import QtWidgets from PySide6.QtCore import Qt from PySide6.QtGui import QPixmap -from PySide6.QtWidgets import QApplication, QCheckBox, QSplashScreen +from PySide6.QtWidgets import QApplication, QCheckBox, QSplashScreen, QDialog from dcs.payloads import PayloadDirectories from game import Game, VERSION, logging_config, persistence @@ -357,7 +357,8 @@ def create_game(params: CreateGameParams) -> Game: ) game = generator.generate() if params.show_air_wing_config: - AirWingConfigurationDialog(game, None).exec_() + if AirWingConfigurationDialog(game, None).exec() == QDialog.DialogCode.Rejected: + sys.exit("Aborted air wing configuration") game.begin_turn_0(squadrons_start_full=params.use_new_squadron_rules) return game diff --git a/qt_ui/windows/AirWingConfigurationDialog.py b/qt_ui/windows/AirWingConfigurationDialog.py index 38f29ee2..4203a9ab 100644 --- a/qt_ui/windows/AirWingConfigurationDialog.py +++ b/qt_ui/windows/AirWingConfigurationDialog.py @@ -1,3 +1,4 @@ +import textwrap from collections import defaultdict from typing import Iterable, Iterator, Optional @@ -630,6 +631,32 @@ class AircraftTypeList(QListView): self.update(self.selectionModel().currentIndex()) +def describe_overfull_airbases( + overfull: Iterable[tuple[ControlPoint, int, list[Squadron]]] +) -> str: + string_builder = [] + for ( + control_point, + used_parking, + squadrons, + ) in overfull: + capacity = control_point.total_aircraft_parking + base_description = f"{control_point.name} {used_parking}/{capacity}" + string_builder.append(f"
{base_description}
") + squadron_descriptions = [] + for squadron in squadrons: + squadron_details = ( + f"{squadron.aircraft} {squadron.name} {squadron.max_size} aircraft" + ) + squadron_descriptions.append(f"{base_description}
") - squadron_descriptions = [] - for squadron in squadrons: - squadron_details = ( - f"{squadron.aircraft} {squadron.name} {squadron.max_size} aircraft" - ) - squadron_descriptions.append(f"The following airbases are over capacity:
" + f"{describe_overfull_airbases(overfull)}" + ) + QMessageBox().critical( + self, + "Cannot continue with overfull bases", + description, + QMessageBox.Ok, + ) + return False + def accept(self) -> None: + if not self.can_continue(): + return for tab in self.tabs: tab.apply() super().accept() @@ -829,8 +861,16 @@ class AirWingConfigurationDialog(QDialog): def reject(self) -> None: result = QMessageBox.information( None, - "Discard changes?", - "Are you sure you want to discard your changes and start the campaign?", + "Abort new game?", + "