import os from PySide2.QtGui import QWindow from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QVBoxLayout, QGridLayout, QGroupBox, QCheckBox, \ QSpinBox, QPushButton, QMessageBox, QComboBox from pip._internal.utils import typing from game.game import AWACS_BUDGET_COST, PinpointStrike, db, Event, FrontlineAttackEvent, Task, \ UnitType from qt_ui.windows.QWaitingForMissionResultWindow import QWaitingForMissionResultWindow from userdata.persistency import base_path import qt_ui.uiconstants as CONST class QBriefingWindow(QDialog): def __init__(self, gameEvent: Event): super(QBriefingWindow, self).__init__() self.gameEvent = gameEvent self.setWindowTitle("Briefing : " + str(gameEvent)) self.setMinimumSize(200,200) self.setWindowIcon(CONST.EVENT_ICONS[self.gameEvent.__class__]) self.setModal(True) self.game = self.gameEvent.game if self.gameEvent.attacker_name == self.game.player_name: self.base = self.gameEvent.from_cp.base self.playerFromCp = self.gameEvent.from_cp else: self.base = self.gameEvent.to_cp.base self.playerFromCp = self.gameEvent.to_cp self.scramble_entries = {k: {} for k in self.gameEvent.tasks} self.initUi() def initUi(self): self.layout = QVBoxLayout() self.depart_box = QGroupBox("Departure") self.depart_layout = QHBoxLayout() self.depart_box.setLayout(self.depart_layout) self.depart_from_label = QLabel("Depart from : ") self.depart_from = QComboBox() for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]): self.depart_from.addItem(str(cp.name), cp) if cp.name == self.playerFromCp.name: self.depart_from.setCurrentIndex(i) self.depart_from.currentTextChanged.connect(self.on_departure_cp_changed) self.depart_layout.addWidget(self.depart_from_label) self.depart_layout.addWidget(self.depart_from) # Mission Description self.gridLayout = QGridLayout() self.initUnitRows() self.scramble_box = QGroupBox("Units") self.scramble_box.setLayout(self.gridLayout) self.action_layout = QHBoxLayout() self.commit_button = QPushButton("Commit") self.back_button = QPushButton("Cancel") self.commit_button.clicked.connect(self.start) self.back_button.clicked.connect(self.close) self.action_layout.addWidget(self.commit_button) self.action_layout.addWidget(self.back_button) self.support_box = self.initSupportBox() self.layout.addWidget(QLabel("

{} on {}

".format(self.gameEvent, self.gameEvent.to_cp.name))) self.layout.addWidget(self.depart_box) self.layout.addWidget(self.scramble_box) self.layout.addWidget(self.support_box) self.layout.addWidget(QLabel("Ready?")) self.layout.addLayout(self.action_layout) self.setLayout(self.layout) def initUnitRows(self): row = 0 def header(text, row): self.gridLayout.addWidget(QLabel("" + text + ""), row, 0, 1, 2) def scramble_row(task_type, unit_type, unit_count, client_slots: bool, row: int): unit_name = QLabel("{} ({})".format(db.unit_type_name(unit_type), unit_count)) self.gridLayout.addWidget(unit_name, row, 0) scramble_entry = QSpinBox() self.gridLayout.addWidget(scramble_entry, row, 1) if client_slots: client_entry = QSpinBox() self.gridLayout.addWidget(client_entry, row, 2) else: client_entry = None self.scramble_entries[task_type][unit_type] = scramble_entry, client_entry # Table headers self.gridLayout.addWidget(QLabel("Amount"), row, 1) self.gridLayout.addWidget(QLabel("Client slots"), row, 2) row += 1 for flight_task in self.gameEvent.tasks: header("{}:".format(self.gameEvent.flight_name(flight_task)), row) row += 1 if flight_task == PinpointStrike: if not self.base.armor: self.gridLayout.addWidget(QLabel("No units"), row, 1) row += 1 for t, c in self.base.armor.items(): scramble_row(flight_task, t, c, False, row) row += 1 else: if not self.base.aircraft: self.gridLayout.addWidget(QLabel("No units"), row, 1) row += 1 for t, c in self.base.aircraft.items(): scramble_row(flight_task, t, c, t.flyable, row) row += 1 return self.gridLayout def initSupportBox(self): self.support_box = QGroupBox("Support") self.support_layout = QGridLayout() self.support_box.setLayout(self.support_layout) self.awacs_label = QLabel("AWACS ({}m)".format(AWACS_BUDGET_COST)) self.awacs_checkbox = QCheckBox() self.ca_slot_label = QLabel("Combined Arms Slots") self.ca_slot_entry = QSpinBox() self.ca_slot_entry.setValue(0) self.ca_slot_entry.setMinimum(0) self.ca_slot_entry.setMaximum(32) self.support_layout.addWidget(self.awacs_label, 0, 0) self.support_layout.addWidget(self.awacs_checkbox, 0, 1) self.support_layout.addWidget(self.ca_slot_label, 1, 0) self.support_layout.addWidget(self.ca_slot_entry, 1, 1) return self.support_box def initWaitingForResults(self): layout = QVBoxLayout() layout.addWidget(QLabel("You are clear for takeoff")) layout.addWidget(QLabel("In DCS open and play the mission : ")) layout.addWidget(QLabel("liberation_nextturn")) layout.addWidget(QLabel("or")) layout.addWidget(QLabel("liberation_nextturn_quick")) layout.addWidget(QLabel("Then save the debriefing to folder :")) layout.addWidget(QLabel("Then save the debriefing to the folder:")) layout.addWidget(QLabel("" + self.debriefing_directory_location() + "")) layout.addWidget(QLabel("Waiting for results...")) # layout.addWidget(QLabel("In DCS open and play the mission : ")) # layout.addWidget(QLabel("You are clear for takeoff")) self.setLayout(layout) pass def debriefing_directory_location(self) -> str: return os.path.join(base_path(), "liberation_debriefings") def start(self): if self.awacs_checkbox.isChecked() == 1: self.gameEvent.is_awacs_enabled = True self.game.awacs_expense_commit() else: self.gameEvent.is_awacs_enabled = False ca_slot_entry_value = self.ca_slot_entry.value() try: ca_slots = int(ca_slot_entry_value and ca_slot_entry_value or "0") except: ca_slots = 0 self.gameEvent.ca_slots = ca_slots # Resolve Departure CP self.gameEvent.departure_cp = self.depart_from.itemData(self.depart_from.currentIndex()) flights = {k: {} for k in self.gameEvent.tasks} # type: db.TaskForceDict units_scramble_counts = {} # type: typing.Dict[typing.Type[UnitType], int] tasks_scramble_counts = {} # type: typing.Dict[typing.Type[Task], int] tasks_clients_counts = {} # type: typing.Dict[typing.Type[Task], int] def dampen_count(unit_type, count: int) -> int: nonlocal units_scramble_counts total_count = self.base.total_units_of_type(unit_type) total_scrambled = units_scramble_counts.get(unit_type, 0) dampened_value = count if count + total_scrambled < total_count else total_count - total_scrambled units_scramble_counts[unit_type] = units_scramble_counts.get(unit_type, 0) + dampened_value return dampened_value for task_type, dict in self.scramble_entries.items(): for unit_type, (count_entry, clients_entry) in dict.items(): try: count = int(count_entry.value()) except: count = 0 try: clients_count = int(clients_entry and clients_entry.value() or 0) except: clients_count = 0 dampened_count = dampen_count(unit_type, count) tasks_clients_counts[task_type] = tasks_clients_counts.get(task_type, 0) + clients_count tasks_scramble_counts[task_type] = tasks_scramble_counts.get(task_type, 0) + dampened_count flights[task_type][unit_type] = dampened_count, clients_count for task in self.gameEvent.ai_banned_tasks: if tasks_clients_counts.get(task, 0) == 0 and tasks_scramble_counts.get(task, 0) > 0: self.showErrorMessage("Need at least one player in flight {}".format(self.gameEvent.flight_name(task))) return for task in self.gameEvent.player_banned_tasks: if tasks_clients_counts.get(task, 0) != 0: self.showErrorMessage("Players are not allowed on flight {}".format(self.gameEvent.flight_name(task))) return if self.game.is_player_attack(self.gameEvent): if isinstance(self.gameEvent, FrontlineAttackEvent): if self.base.total_armor == 0: self.showErrorMessage("No ground vehicles available to attack!") return self.gameEvent.player_attacking(flights) else: if isinstance(self.gameEvent, FrontlineAttackEvent): if self.gameEvent.to_cp.base.total_armor == 0: self.showErrorMessage("No ground vehicles available to defend!") return self.gameEvent.player_defending(flights) self.game.initiate_event(self.gameEvent) waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game) waiting.show() self.close() def showErrorMessage(self, text): about = QMessageBox() about.setWindowTitle("Error") about.setIcon(QMessageBox.Icon.Critical) about.setText(text) about.exec_() def on_departure_cp_changed(self): selectedBase = self.depart_from.itemData(self.depart_from.currentIndex()) for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]): if cp.name == selectedBase.name: self.base = cp.base self.playerFromCp = cp break # Clear current selection self.scramble_entries = {k: {} for k in self.gameEvent.tasks} # Clear the grid layout for i in reversed(range(self.gridLayout.count())): self.gridLayout.itemAt(i).widget().setParent(None) # Rebuild the grid layout, so that it correspond to the newly selected CP self.initUnitRows()