diff --git a/.gitignore b/.gitignore index 2d61eba..aea95bd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,10 @@ Generator/.idea Generator/__pycache__ Generator/build Generator/venv -Generator/dist \ No newline at end of file +Generator/dist +Generator/generator.log +MissionGenerator.exe +incoming templates/ +Generator/utils/extract units/source.miz +Generator/utils/extract units/units.txt +generator.log diff --git a/Generator/Forces/_How to add your own templates.txt b/Generator/Forces/_How to add your own templates.txt index 20b8d42..1838d7d 100644 --- a/Generator/Forces/_How to add your own templates.txt +++ b/Generator/Forces/_How to add your own templates.txt @@ -4,6 +4,15 @@ You can add your own unit templates in this directory and they will appear in th 2) Add ground unit groups. 3) Save the mission in this directory. +Optional: +4) Add helicopters with "CAS" main task for attack helicopters. +5) Add helicopters with "Transport" main task for transport helicopters. +6) Add planes with "CAS" main task for attack planes. +7) Add planes with "CAP" main task for fighters. +8) Configure loadouts, liveries, and skill for aircraft. + Tips: -Drop your templates in the RotorOps Discord if you'd like to have them added in a release for everyone. -The mission generator will only extract blue ground units from the template when selected from the "Blue Forces" menu, and vice versa. +-Only unit types are used from ground units. Liveries or other attributes are able to be copied. +-For aircraft, group size is currently capped at 2 units per group to help prevent issues with parking. Only the first unit in the group is used as a source. diff --git a/Generator/Forces/blue/BLUE Default Armor.miz b/Generator/Forces/blue/BLUE Default Armor.miz index ffd71fd..fc9903a 100644 Binary files a/Generator/Forces/blue/BLUE Default Armor.miz and b/Generator/Forces/blue/BLUE Default Armor.miz differ diff --git a/Generator/Forces/blue/BLUE Vietnam Armor (Mr Nobody).miz b/Generator/Forces/blue/BLUE Vietnam Armor (Mr Nobody).miz new file mode 100644 index 0000000..8d049d1 Binary files /dev/null and b/Generator/Forces/blue/BLUE Vietnam Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/red/RED Armor (Hard).miz b/Generator/Forces/red/RED Armor (Hard).miz index 17e12e3..b599356 100644 Binary files a/Generator/Forces/red/RED Armor (Hard).miz and b/Generator/Forces/red/RED Armor (Hard).miz differ diff --git a/Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz b/Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz index fa4ada1..b2eec21 100644 Binary files a/Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz and b/Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz differ diff --git a/Generator/Forces/red/RED Trucks & Infantry (Easy).miz b/Generator/Forces/red/RED Trucks & Infantry (Easy).miz index 85e75b8..5713a14 100644 Binary files a/Generator/Forces/red/RED Trucks & Infantry (Easy).miz and b/Generator/Forces/red/RED Trucks & Infantry (Easy).miz differ diff --git a/Generator/Forces/red/RED Vietnam Armor & Infantry (Mr Nobody).miz b/Generator/Forces/red/RED Vietnam Armor & Infantry (Mr Nobody).miz new file mode 100644 index 0000000..b939702 Binary files /dev/null and b/Generator/Forces/red/RED Vietnam Armor & Infantry (Mr Nobody).miz differ diff --git a/Generator/MissionGenerator.py b/Generator/MissionGenerator.py index b9d8367..ccb4384 100644 --- a/Generator/MissionGenerator.py +++ b/Generator/MissionGenerator.py @@ -5,7 +5,7 @@ import dcs import RotorOpsMission as ROps import RotorOpsUtils import RotorOpsUnits - +import logging from PyQt5.QtWidgets import ( QApplication, QDialog, QMainWindow, QMessageBox @@ -13,12 +13,38 @@ from PyQt5.QtWidgets import ( from PyQt5 import QtGui from MissionGeneratorUI import Ui_MainWindow + +#Setup logfile and exception handler +logger = logging.getLogger(__name__) +logging.basicConfig(filename='generator.log', encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') +handler = logging.StreamHandler(stream=sys.stdout) +logger.addHandler(handler) + +def handle_exception(exc_type, exc_value, exc_traceback): + if issubclass(exc_type, KeyboardInterrupt): #example of handling error subclasses + sys.__excepthook__(exc_type, exc_value, exc_traceback) + return + + logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) + msg = QMessageBox() + msg.setWindowTitle("Uncaught exception") + msg.setText("Oops, there was a problem. Please check the log file or post it in the RotorOps discord where some helpful people will have a look.") + x = msg.exec_() + + +sys.excepthook = handle_exception + + maj_version = 0 -minor_version = 3 +minor_version = 4 version_string = str(maj_version) + "." + str(minor_version) scenarios = [] red_forces_files = [] blue_forces_files = [] +defenders_text = "Defending Forces:" +attackers_text = "Attacking Forces:" + +logger.info("RotorOps v" + version_string) class Window(QMainWindow, Ui_MainWindow): @@ -27,11 +53,11 @@ class Window(QMainWindow, Ui_MainWindow): super().__init__(parent) if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): - print('running in a PyInstaller bundle') + logger.info('running in a PyInstaller bundle') home_dir = os.getcwd() os.chdir(home_dir + "/Generator") else: - print('running in a normal Python process') + logger.info('running in a normal Python process') self.m = ROps.RotorOpsMission() @@ -42,6 +68,8 @@ class Window(QMainWindow, Ui_MainWindow): self.populateForces("blue", self.blueforces_comboBox, blue_forces_files) self.populateSlotSelection() + self.blue_forces_label.setText(attackers_text) + self.red_forces_label.setText(defenders_text) self.background_label.setPixmap(QtGui.QPixmap(self.m.assets_dir + "/background.PNG")) self.statusbar.setStyleSheet( "QStatusBar{padding-left:5px;color:black;font-weight:bold;}") @@ -50,15 +78,15 @@ class Window(QMainWindow, Ui_MainWindow): def connectSignalsSlots(self): - # self.action_Exit.triggered.connect(self.close) self.action_generateMission.triggered.connect(self.generateMissionAction) self.action_scenarioSelected.triggered.connect(self.scenarioChanged) + self.action_defensiveModeChanged.triggered.connect(self.defensiveModeChanged) def populateScenarios(self): os.chdir(self.m.scenarios_dir) path = os.getcwd() dir_list = os.listdir(path) - print("Looking for mission files in '", path, "' :") + logger.info("Looking for mission files in " + path) for filename in dir_list: if filename.endswith(".miz"): @@ -70,7 +98,7 @@ class Window(QMainWindow, Ui_MainWindow): os.chdir(self.m.forces_dir + "/" + side) path = os.getcwd() dir_list = os.listdir(path) - print("Looking for " + side + " Forces files in '", os.getcwd(), "' :") + logger.info("Looking for " + side + " Forces files in '" + path) for filename in dir_list: if filename.endswith(".miz"): @@ -82,65 +110,71 @@ class Window(QMainWindow, Ui_MainWindow): for type in RotorOpsUnits.client_helos: self.slot_template_comboBox.addItem(type.id) + def defensiveModeChanged(self): + if self.defense_checkBox.isChecked(): + self.red_forces_label.setText(attackers_text) + self.blue_forces_label.setText(defenders_text) + else: + self.red_forces_label.setText(defenders_text) + self.blue_forces_label.setText(attackers_text) + def scenarioChanged(self): - try: - os.chdir(self.m.scenarios_dir) - filename = scenarios[self.scenario_comboBox.currentIndex()] - source_mission = dcs.mission.Mission() - source_mission.load_file(filename) - zones = source_mission.triggers.zones() - conflict_zones = 0 - staging_zones = 0 - conflict_zone_size_sum = 0 - conflict_zone_distance_sum = 0 - spawn_zones = 0 - conflict_zone_positions = [] - #friendly_airports = source_mission.getCoalitionAirports("blue") - #enemy_airports = source_mission.getCoalitionAirports("red") - friendly_airports = True - enemy_airports = True + os.chdir(self.m.scenarios_dir) + filename = scenarios[self.scenario_comboBox.currentIndex()] + source_mission = dcs.mission.Mission() + source_mission.load_file(filename) + zones = source_mission.triggers.zones() + conflict_zones = 0 + staging_zones = 0 + conflict_zone_size_sum = 0 + conflict_zone_distance_sum = 0 + spawn_zones = 0 + conflict_zone_positions = [] + #friendly_airports = source_mission.getCoalitionAirports("blue") + #enemy_airports = source_mission.getCoalitionAirports("red") + friendly_airports = True + enemy_airports = True - ## TODO: we should be creating a new instance of RotorOpsMission each time scenario is changed so we can access all methods and vars + for zone in zones: + if zone.name == "STAGING": + staging_zones += 1 + if zone.name == "ALPHA" or zone.name == "BRAVO" or zone.name == "CHARLIE" or zone.name == "DELTA": + conflict_zones += 1 + conflict_zone_size_sum += zone.radius + conflict_zone_positions.append(zone.position) + if zone.name.rfind("_SPAWN") > 0: + spawn_zones += 1 + if conflict_zones > 1: + for index, position in enumerate(conflict_zone_positions): + if index > 0: + conflict_zone_distance_sum += RotorOpsUtils.getDistance(conflict_zone_positions[index], conflict_zone_positions[index - 1]) - for zone in zones: - if zone.name == "STAGING": - staging_zones += 1 - if zone.name == "ALPHA" or zone.name == "BRAVO" or zone.name == "CHARLIE" or zone.name == "DELTA": - conflict_zones += 1 - conflict_zone_size_sum += zone.radius - conflict_zone_positions.append(zone.position) - if zone.name.rfind("_SPAWN") > 0: - spawn_zones += 1 - if conflict_zones > 1: - for index, position in enumerate(conflict_zone_positions): - if index > 0: - conflict_zone_distance_sum += RotorOpsUtils.getDistance(conflict_zone_positions[index], conflict_zone_positions[index - 1]) + def validateTemplate(): + valid = True + if len(staging_zones) < 1: + valid = False + if len(conflict_zones) < 1: + valid = False + if not friendly_airports: + valid = False + if not enemy_airports: + valid = False + return valid - def validateTemplate(): - valid = True - if len(staging_zones) < 1: - valid = False - if len(conflict_zones) < 1: - valid = False - if not friendly_airports: - valid = False - if not enemy_airports: - valid = False - return valid - - if conflict_zones and staging_zones : - average_zone_size = conflict_zone_size_sum / conflict_zones - self.description_textBrowser.setText( - "Map: " + source_mission.terrain.name + "\n" + - "Conflict Zones: " + str(conflict_zones) + "\n" + - "Average Zone Size " + str(math.floor(average_zone_size)) + "m \n" + - "Infantry Spawn Zones: " + str(spawn_zones) + "\n" + - "Approx Distance: " + str(math.floor(RotorOpsUtils.convertMeterToNM(conflict_zone_distance_sum))) + "nm \n" - #"Validity Check:" + str(validateTemplate()) - ) - except: - self.description_textBrowser.setText("File error occured.") + if conflict_zones and staging_zones : + average_zone_size = conflict_zone_size_sum / conflict_zones + self.description_textBrowser.setText( + "Map: " + source_mission.terrain.name + "\n" + + "Conflict Zones: " + str(conflict_zones) + "\n" + + "Average Zone Size " + str(math.floor(average_zone_size)) + "m \n" + + "Infantry Spawn Zones: " + str(spawn_zones) + "\n" + + "Approx Distance: " + str(math.floor(RotorOpsUtils.convertMeterToNM(conflict_zone_distance_sum))) + "nm \n" + #"Validity Check:" + str(validateTemplate()) + + "\n== BRIEFING ==\n\n" + + source_mission.description_text() + ) + #self.description_textBrowser.setText("File error occured.") def generateMissionAction(self): @@ -168,19 +202,22 @@ class Window(QMainWindow, Ui_MainWindow): "zone_protect_sams": self.zone_sams_checkBox.isChecked(), "zone_farps": self.farp_buttonGroup.checkedButton().objectName(), "inf_spawn_msgs": self.inf_spawn_voiceovers_checkBox.isChecked(), + "e_transport_helos": self.e_transport_helos_spinBox.value(), + "transport_drop_qty": self.troop_drop_spinBox.value(), + "smoke_pickup_zones": self.smoke_pickup_zone_checkBox.isChecked(), } os.chdir(self.m.home_dir + '/Generator') n = ROps.RotorOpsMission() result = n.generateMission(data) - print("Generating mission with options:") - print(str(data)) + logger.info("Generating mission with options:") + logger.info(str(data)) # generate the mission #result = self.m.generateMission(data) #display results if result["success"]: - print(result["filename"] + "' successfully generated in " + result["directory"]) + logger.info(result["filename"] + "' successfully generated in " + result["directory"]) self.statusbar.showMessage(result["filename"] + "' successfully generated in " + result["directory"], 10000) msg = QMessageBox() msg.setWindowTitle("Mission Generated") @@ -199,7 +236,7 @@ class Window(QMainWindow, Ui_MainWindow): ) x = msg.exec_() elif not result["success"]: - print(result["failure_msg"]) + logger.warning(result["failure_msg"]) msg = QMessageBox() msg.setWindowTitle("Error") msg.setText(result["failure_msg"]) diff --git a/Generator/MissionGeneratorUI.py b/Generator/MissionGeneratorUI.py index a318da0..fafade2 100644 --- a/Generator/MissionGeneratorUI.py +++ b/Generator/MissionGeneratorUI.py @@ -48,7 +48,7 @@ class Ui_MainWindow(object): "padding: 4px;") self.generateButton.setObjectName("generateButton") self.description_textBrowser = QtWidgets.QTextBrowser(self.centralwidget) - self.description_textBrowser.setGeometry(QtCore.QRect(710, 20, 331, 131)) + self.description_textBrowser.setGeometry(QtCore.QRect(670, 30, 501, 131)) font = QtGui.QFont() font.setPointSize(9) self.description_textBrowser.setFont(font) @@ -57,23 +57,23 @@ class Ui_MainWindow(object): self.blueforces_comboBox = QtWidgets.QComboBox(self.centralwidget) self.blueforces_comboBox.setGeometry(QtCore.QRect(790, 230, 291, 31)) self.blueforces_comboBox.setObjectName("blueforces_comboBox") - self.scenario_label_2 = QtWidgets.QLabel(self.centralwidget) - self.scenario_label_2.setGeometry(QtCore.QRect(690, 180, 141, 31)) + self.blue_forces_label = QtWidgets.QLabel(self.centralwidget) + self.blue_forces_label.setGeometry(QtCore.QRect(690, 180, 241, 31)) font = QtGui.QFont() font.setPointSize(12) - self.scenario_label_2.setFont(font) - self.scenario_label_2.setObjectName("scenario_label_2") - self.scenario_label_3 = QtWidgets.QLabel(self.centralwidget) - self.scenario_label_3.setGeometry(QtCore.QRect(60, 180, 141, 31)) + self.blue_forces_label.setFont(font) + self.blue_forces_label.setObjectName("blue_forces_label") + self.red_forces_label = QtWidgets.QLabel(self.centralwidget) + self.red_forces_label.setGeometry(QtCore.QRect(60, 180, 261, 31)) font = QtGui.QFont() font.setPointSize(12) - self.scenario_label_3.setFont(font) - self.scenario_label_3.setObjectName("scenario_label_3") + self.red_forces_label.setFont(font) + self.red_forces_label.setObjectName("red_forces_label") self.redforces_comboBox = QtWidgets.QComboBox(self.centralwidget) self.redforces_comboBox.setGeometry(QtCore.QRect(170, 230, 291, 31)) self.redforces_comboBox.setObjectName("redforces_comboBox") self.background_label = QtWidgets.QLabel(self.centralwidget) - self.background_label.setGeometry(QtCore.QRect(-40, 440, 801, 371)) + self.background_label.setGeometry(QtCore.QRect(-40, 490, 801, 371)) self.background_label.setAutoFillBackground(False) self.background_label.setStyleSheet("") self.background_label.setText("") @@ -113,7 +113,7 @@ class Ui_MainWindow(object): self.scenario_label_4.setAlignment(QtCore.Qt.AlignCenter) self.scenario_label_4.setObjectName("scenario_label_4") self.game_status_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.game_status_checkBox.setGeometry(QtCore.QRect(810, 790, 191, 16)) + self.game_status_checkBox.setGeometry(QtCore.QRect(810, 760, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.game_status_checkBox.setFont(font) @@ -121,7 +121,7 @@ class Ui_MainWindow(object): self.game_status_checkBox.setTristate(False) self.game_status_checkBox.setObjectName("game_status_checkBox") self.voiceovers_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.voiceovers_checkBox.setGeometry(QtCore.QRect(810, 820, 191, 16)) + self.voiceovers_checkBox.setGeometry(QtCore.QRect(810, 790, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.voiceovers_checkBox.setFont(font) @@ -150,13 +150,14 @@ class Ui_MainWindow(object): self.tankers_checkBox.setChecked(True) self.tankers_checkBox.setObjectName("tankers_checkBox") self.apcs_spawn_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.apcs_spawn_checkBox.setGeometry(QtCore.QRect(470, 400, 251, 31)) + self.apcs_spawn_checkBox.setGeometry(QtCore.QRect(450, 420, 251, 31)) font = QtGui.QFont() font.setPointSize(10) self.apcs_spawn_checkBox.setFont(font) + self.apcs_spawn_checkBox.setChecked(True) self.apcs_spawn_checkBox.setObjectName("apcs_spawn_checkBox") self.inf_spawn_spinBox = QtWidgets.QSpinBox(self.centralwidget) - self.inf_spawn_spinBox.setGeometry(QtCore.QRect(680, 360, 71, 31)) + self.inf_spawn_spinBox.setGeometry(QtCore.QRect(670, 340, 51, 31)) font = QtGui.QFont() font.setPointSize(12) self.inf_spawn_spinBox.setFont(font) @@ -176,7 +177,7 @@ class Ui_MainWindow(object): self.forces_hint_label_2.setAlignment(QtCore.Qt.AlignCenter) self.forces_hint_label_2.setObjectName("forces_hint_label_2") self.label = QtWidgets.QLabel(self.centralwidget) - self.label.setGeometry(QtCore.QRect(470, 360, 191, 31)) + self.label.setGeometry(QtCore.QRect(450, 340, 211, 21)) font = QtGui.QFont() font.setPointSize(10) self.label.setFont(font) @@ -190,14 +191,8 @@ class Ui_MainWindow(object): font.setPointSize(11) self.label_2.setFont(font) self.label_2.setObjectName("label_2") - self.scenario_label_6 = QtWidgets.QLabel(self.centralwidget) - self.scenario_label_6.setGeometry(QtCore.QRect(470, 320, 141, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.scenario_label_6.setFont(font) - self.scenario_label_6.setObjectName("scenario_label_6") self.force_offroad_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.force_offroad_checkBox.setGeometry(QtCore.QRect(810, 760, 191, 16)) + self.force_offroad_checkBox.setGeometry(QtCore.QRect(810, 820, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.force_offroad_checkBox.setFont(font) @@ -247,15 +242,15 @@ class Ui_MainWindow(object): self.zone_sams_checkBox.setFont(font) self.zone_sams_checkBox.setObjectName("zone_sams_checkBox") self.scenario_label_9 = QtWidgets.QLabel(self.centralwidget) - self.scenario_label_9.setGeometry(QtCore.QRect(740, 490, 171, 31)) + self.scenario_label_9.setGeometry(QtCore.QRect(810, 450, 171, 31)) font = QtGui.QFont() font.setPointSize(10) self.scenario_label_9.setFont(font) self.scenario_label_9.setObjectName("scenario_label_9") self.inf_spawn_voiceovers_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.inf_spawn_voiceovers_checkBox.setGeometry(QtCore.QRect(470, 430, 251, 31)) + self.inf_spawn_voiceovers_checkBox.setGeometry(QtCore.QRect(810, 720, 251, 31)) font = QtGui.QFont() - font.setPointSize(10) + font.setPointSize(9) self.inf_spawn_voiceovers_checkBox.setFont(font) self.inf_spawn_voiceovers_checkBox.setChecked(True) self.inf_spawn_voiceovers_checkBox.setObjectName("inf_spawn_voiceovers_checkBox") @@ -287,14 +282,51 @@ class Ui_MainWindow(object): self.version_label.setGeometry(QtCore.QRect(920, 840, 241, 21)) self.version_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.version_label.setObjectName("version_label") + self.scenario_label_10 = QtWidgets.QLabel(self.centralwidget) + self.scenario_label_10.setGeometry(QtCore.QRect(140, 410, 241, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.scenario_label_10.setFont(font) + self.scenario_label_10.setObjectName("scenario_label_10") + self.e_transport_helos_spinBox = QtWidgets.QSpinBox(self.centralwidget) + self.e_transport_helos_spinBox.setGeometry(QtCore.QRect(70, 410, 51, 31)) + font = QtGui.QFont() + font.setPointSize(12) + self.e_transport_helos_spinBox.setFont(font) + self.e_transport_helos_spinBox.setMinimum(0) + self.e_transport_helos_spinBox.setMaximum(8) + self.e_transport_helos_spinBox.setProperty("value", 1) + self.e_transport_helos_spinBox.setObjectName("e_transport_helos_spinBox") + self.label_3 = QtWidgets.QLabel(self.centralwidget) + self.label_3.setGeometry(QtCore.QRect(450, 380, 191, 31)) + font = QtGui.QFont() + font.setPointSize(10) + self.label_3.setFont(font) + self.label_3.setObjectName("label_3") + self.troop_drop_spinBox = QtWidgets.QSpinBox(self.centralwidget) + self.troop_drop_spinBox.setGeometry(QtCore.QRect(670, 380, 51, 31)) + font = QtGui.QFont() + font.setPointSize(12) + self.troop_drop_spinBox.setFont(font) + self.troop_drop_spinBox.setMinimum(0) + self.troop_drop_spinBox.setMaximum(10) + self.troop_drop_spinBox.setProperty("value", 4) + self.troop_drop_spinBox.setObjectName("troop_drop_spinBox") + self.smoke_pickup_zone_checkBox = QtWidgets.QCheckBox(self.centralwidget) + self.smoke_pickup_zone_checkBox.setGeometry(QtCore.QRect(810, 690, 251, 31)) + font = QtGui.QFont() + font.setPointSize(9) + self.smoke_pickup_zone_checkBox.setFont(font) + self.smoke_pickup_zone_checkBox.setChecked(True) + self.smoke_pickup_zone_checkBox.setObjectName("smoke_pickup_zone_checkBox") self.background_label.raise_() self.scenario_comboBox.raise_() self.scenario_label.raise_() self.generateButton.raise_() self.description_textBrowser.raise_() self.blueforces_comboBox.raise_() - self.scenario_label_2.raise_() - self.scenario_label_3.raise_() + self.blue_forces_label.raise_() + self.red_forces_label.raise_() self.redforces_comboBox.raise_() self.scenario_hint_label.raise_() self.forces_hint_label.raise_() @@ -313,7 +345,6 @@ class Ui_MainWindow(object): self.label.raise_() self.slot_template_comboBox.raise_() self.label_2.raise_() - self.scenario_label_6.raise_() self.force_offroad_checkBox.raise_() self.defense_checkBox.raise_() self.e_attack_helos_spinBox.raise_() @@ -327,6 +358,11 @@ class Ui_MainWindow(object): self.farp_gunits.raise_() self.farp_always.raise_() self.version_label.raise_() + self.scenario_label_10.raise_() + self.e_transport_helos_spinBox.raise_() + self.label_3.raise_() + self.troop_drop_spinBox.raise_() + self.smoke_pickup_zone_checkBox.raise_() MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1209, 26)) @@ -344,10 +380,13 @@ class Ui_MainWindow(object): self.action_blueforcesSelected.setObjectName("action_blueforcesSelected") self.action_redforcesSelected = QtWidgets.QAction(MainWindow) self.action_redforcesSelected.setObjectName("action_redforcesSelected") + self.action_defensiveModeChanged = QtWidgets.QAction(MainWindow) + self.action_defensiveModeChanged.setObjectName("action_defensiveModeChanged") self.retranslateUi(MainWindow) self.generateButton.clicked.connect(self.action_generateMission.trigger) self.scenario_comboBox.currentIndexChanged['int'].connect(self.action_scenarioSelected.trigger) + self.defense_checkBox.stateChanged['int'].connect(self.action_defensiveModeChanged.trigger) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -357,13 +396,13 @@ class Ui_MainWindow(object): self.scenario_label.setText(_translate("MainWindow", "Scenario Template:")) self.generateButton.setText(_translate("MainWindow", "Generate Mission")) self.description_textBrowser.setHtml(_translate("MainWindow", "\n" -"
\n" -"Provide close air support for our convoys as we take back Las Vegas from the enemy!
")) +"\n" +"Provide close air support for our convoys as we take back Las Vegas from the enemy!