diff --git a/Generator/Forces/red/RED Default Armor.miz b/Generator/Forces/red/RED Default Armor.miz new file mode 100644 index 0000000..17e12e3 Binary files /dev/null and b/Generator/Forces/red/RED Default Armor.miz differ diff --git a/Generator/MissionGenerator.py b/Generator/MissionGenerator.py index 15883be..242cde4 100644 --- a/Generator/MissionGenerator.py +++ b/Generator/MissionGenerator.py @@ -150,10 +150,8 @@ class Window(QMainWindow, Ui_MainWindow): "blue_quantity": self.blueqty_spinBox.value(), "inf_spawn_qty": self.inf_spawn_spinBox.value(), "apc_spawns_inf": self.apcs_spawn_checkBox.isChecked(), - "e_transport": self.enemy_transport_checkBox.isChecked(), - "e_attack_helos": self.enemy_attack_helos_checkBox.isChecked(), - "e_fighters": self.enemy_fighters_checkBox.isChecked(), - "e_attack_planes": self.enemy_attack_planes_checkBox.isChecked(), + "e_attack_helos": self.e_attack_helos_spinBox.value(), + "e_attack_planes": self.e_attack_planes_spinBox.value(), "crates": self.logistics_crates_checkBox.isChecked(), "f_awacs": self.awacs_checkBox.isChecked(), "f_tankers": self.tankers_checkBox.isChecked(), @@ -163,6 +161,8 @@ class Window(QMainWindow, Ui_MainWindow): "game_display": self.game_status_checkBox.isChecked(), "defending": self.defense_checkBox.isChecked(), "slots": self.slot_template_comboBox.currentText(), + "smoke_zone": self.smoke_checkBox.isChecked(), + "zone_protect_sams": self.zone_sams_checkBox.isChecked(), } os.chdir(self.m.home_dir + '/Generator') n = ROps.RotorOpsMission() @@ -177,22 +177,28 @@ class Window(QMainWindow, Ui_MainWindow): if result["success"]: print(result["filename"] + "' successfully generated in " + result["directory"]) self.statusbar.showMessage(result["filename"] + "' successfully generated in " + result["directory"], 10000) - msg = QMessageBox() - msg.setWindowTitle("Mission Generated") - msg.setText("Awesome, your mission is ready! It's located in this directory: \n" + - self.m.output_dir + "\n" + - "\n" + - "Next, you should use the DCS Mission Editor to fine tune unit placements. Don't be afraid to edit the missions that this generator produces. \n" + - "\n" + - "There are no hidden script changes, everything is visible in the ME. Triggers have been created to help you to add your own actions based on active zone and game status. \n" + - "\n" + - "Units can be changed or moved without issue. Player slots can be changed or moved without issue. \n" + - "\n" + - "Don't forget, you can also create your own templates that can include any mission options, objects, or even scripts. \n" + - "\n" + - "Have fun! \n" - ) - x = msg.exec_() + msg = QMessageBox() + msg.setWindowTitle("Mission Generated") + msg.setText("Awesome, your mission is ready! It's located in this directory: \n" + + self.m.output_dir + "\n" + + "\n" + + "Next, you should use the DCS Mission Editor to fine tune unit placements. Don't be afraid to edit the missions that this generator produces. \n" + + "\n" + + "There are no hidden script changes, everything is visible in the ME. Triggers have been created to help you to add your own actions based on active zone and game status. \n" + + "\n" + + "Units can be changed or moved without issue. Player slots can be changed or moved without issue. \n" + + "\n" + + "Don't forget, you can also create your own templates that can include any mission options, objects, or even scripts. \n" + + "\n" + + "Have fun! \n" + ) + x = msg.exec_() + elif not result["success"]: + print(result["failure_msg"]) + msg = QMessageBox() + msg.setWindowTitle("Error") + msg.setText(result["failure_msg"]) + x = msg.exec_() diff --git a/Generator/MissionGeneratorUI.py b/Generator/MissionGeneratorUI.py index c24a113..d1f8dda 100644 --- a/Generator/MissionGeneratorUI.py +++ b/Generator/MissionGeneratorUI.py @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1140, 826) + MainWindow.resize(1209, 900) font = QtGui.QFont() font.setPointSize(10) MainWindow.setFont(font) @@ -39,7 +39,7 @@ class Ui_MainWindow(object): self.scenario_label.setFont(font) self.scenario_label.setObjectName("scenario_label") self.generateButton = QtWidgets.QPushButton(self.centralwidget) - self.generateButton.setGeometry(QtCore.QRect(940, 720, 141, 41)) + self.generateButton.setGeometry(QtCore.QRect(1020, 790, 141, 41)) self.generateButton.setStyleSheet("background-color: white;\n" "border-style: outset;\n" "border-width: 2px;\n" @@ -73,7 +73,7 @@ class Ui_MainWindow(object): 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(10, 430, 801, 371)) + self.background_label.setGeometry(QtCore.QRect(-30, 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(910, 510, 191, 16)) + self.game_status_checkBox.setGeometry(QtCore.QRect(1000, 590, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.game_status_checkBox.setFont(font) @@ -121,67 +121,41 @@ 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(910, 570, 191, 16)) + self.voiceovers_checkBox.setGeometry(QtCore.QRect(1000, 650, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.voiceovers_checkBox.setFont(font) self.voiceovers_checkBox.setChecked(True) self.voiceovers_checkBox.setObjectName("voiceovers_checkBox") self.logistics_crates_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.logistics_crates_checkBox.setGeometry(QtCore.QRect(910, 320, 251, 31)) + self.logistics_crates_checkBox.setGeometry(QtCore.QRect(970, 390, 251, 31)) font = QtGui.QFont() font.setPointSize(11) self.logistics_crates_checkBox.setFont(font) self.logistics_crates_checkBox.setObjectName("logistics_crates_checkBox") self.awacs_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.awacs_checkBox.setGeometry(QtCore.QRect(910, 350, 251, 31)) + self.awacs_checkBox.setGeometry(QtCore.QRect(970, 420, 251, 31)) font = QtGui.QFont() font.setPointSize(11) self.awacs_checkBox.setFont(font) self.awacs_checkBox.setStatusTip("") + self.awacs_checkBox.setChecked(True) self.awacs_checkBox.setObjectName("awacs_checkBox") self.tankers_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.tankers_checkBox.setGeometry(QtCore.QRect(910, 380, 251, 31)) + self.tankers_checkBox.setGeometry(QtCore.QRect(970, 450, 251, 31)) font = QtGui.QFont() font.setPointSize(11) self.tankers_checkBox.setFont(font) + 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(500, 400, 251, 31)) font = QtGui.QFont() font.setPointSize(10) self.apcs_spawn_checkBox.setFont(font) self.apcs_spawn_checkBox.setObjectName("apcs_spawn_checkBox") - self.enemy_transport_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.enemy_transport_checkBox.setEnabled(False) - self.enemy_transport_checkBox.setGeometry(QtCore.QRect(70, 320, 251, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.enemy_transport_checkBox.setFont(font) - self.enemy_transport_checkBox.setObjectName("enemy_transport_checkBox") - self.enemy_attack_helos_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.enemy_attack_helos_checkBox.setEnabled(True) - self.enemy_attack_helos_checkBox.setGeometry(QtCore.QRect(70, 350, 251, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.enemy_attack_helos_checkBox.setFont(font) - self.enemy_attack_helos_checkBox.setObjectName("enemy_attack_helos_checkBox") - self.enemy_fighters_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.enemy_fighters_checkBox.setEnabled(False) - self.enemy_fighters_checkBox.setGeometry(QtCore.QRect(70, 380, 251, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.enemy_fighters_checkBox.setFont(font) - self.enemy_fighters_checkBox.setObjectName("enemy_fighters_checkBox") - self.enemy_attack_planes_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.enemy_attack_planes_checkBox.setEnabled(True) - self.enemy_attack_planes_checkBox.setGeometry(QtCore.QRect(70, 410, 251, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.enemy_attack_planes_checkBox.setFont(font) - self.enemy_attack_planes_checkBox.setObjectName("enemy_attack_planes_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(710, 360, 71, 31)) font = QtGui.QFont() font.setPointSize(12) self.inf_spawn_spinBox.setFont(font) @@ -190,7 +164,7 @@ class Ui_MainWindow(object): self.inf_spawn_spinBox.setProperty("value", 2) self.inf_spawn_spinBox.setObjectName("inf_spawn_spinBox") self.smoke_checkBox = QtWidgets.QCheckBox(self.centralwidget) - self.smoke_checkBox.setGeometry(QtCore.QRect(910, 540, 191, 16)) + self.smoke_checkBox.setGeometry(QtCore.QRect(1000, 620, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.smoke_checkBox.setFont(font) @@ -208,28 +182,28 @@ 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(500, 360, 191, 31)) font = QtGui.QFont() font.setPointSize(10) self.label.setFont(font) self.label.setObjectName("label") self.slot_template_comboBox = QtWidgets.QComboBox(self.centralwidget) - self.slot_template_comboBox.setGeometry(QtCore.QRect(790, 630, 291, 31)) + self.slot_template_comboBox.setGeometry(QtCore.QRect(870, 700, 291, 31)) self.slot_template_comboBox.setObjectName("slot_template_comboBox") self.label_2 = QtWidgets.QLabel(self.centralwidget) - self.label_2.setGeometry(QtCore.QRect(650, 630, 111, 31)) + self.label_2.setGeometry(QtCore.QRect(750, 700, 111, 31)) font = QtGui.QFont() 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)) + self.scenario_label_6.setGeometry(QtCore.QRect(500, 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(910, 480, 191, 16)) + self.force_offroad_checkBox.setGeometry(QtCore.QRect(1000, 560, 191, 16)) font = QtGui.QFont() font.setPointSize(9) self.force_offroad_checkBox.setFont(font) @@ -242,6 +216,42 @@ class Ui_MainWindow(object): font.setPointSize(11) self.defense_checkBox.setFont(font) self.defense_checkBox.setObjectName("defense_checkBox") + self.e_attack_helos_spinBox = QtWidgets.QSpinBox(self.centralwidget) + self.e_attack_helos_spinBox.setGeometry(QtCore.QRect(70, 330, 51, 31)) + font = QtGui.QFont() + font.setPointSize(12) + self.e_attack_helos_spinBox.setFont(font) + self.e_attack_helos_spinBox.setMinimum(0) + self.e_attack_helos_spinBox.setMaximum(50) + self.e_attack_helos_spinBox.setProperty("value", 2) + self.e_attack_helos_spinBox.setObjectName("e_attack_helos_spinBox") + self.scenario_label_7 = QtWidgets.QLabel(self.centralwidget) + self.scenario_label_7.setGeometry(QtCore.QRect(140, 330, 231, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.scenario_label_7.setFont(font) + self.scenario_label_7.setObjectName("scenario_label_7") + self.scenario_label_8 = QtWidgets.QLabel(self.centralwidget) + self.scenario_label_8.setGeometry(QtCore.QRect(140, 370, 231, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.scenario_label_8.setFont(font) + self.scenario_label_8.setObjectName("scenario_label_8") + self.e_attack_planes_spinBox = QtWidgets.QSpinBox(self.centralwidget) + self.e_attack_planes_spinBox.setGeometry(QtCore.QRect(70, 370, 51, 31)) + font = QtGui.QFont() + font.setPointSize(12) + self.e_attack_planes_spinBox.setFont(font) + self.e_attack_planes_spinBox.setMinimum(0) + self.e_attack_planes_spinBox.setMaximum(50) + self.e_attack_planes_spinBox.setProperty("value", 1) + self.e_attack_planes_spinBox.setObjectName("e_attack_planes_spinBox") + self.zone_sams_checkBox = QtWidgets.QCheckBox(self.centralwidget) + self.zone_sams_checkBox.setGeometry(QtCore.QRect(970, 480, 201, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.zone_sams_checkBox.setFont(font) + self.zone_sams_checkBox.setObjectName("zone_sams_checkBox") self.background_label.raise_() self.scenario_comboBox.raise_() self.scenario_label.raise_() @@ -262,10 +272,6 @@ class Ui_MainWindow(object): self.awacs_checkBox.raise_() self.tankers_checkBox.raise_() self.apcs_spawn_checkBox.raise_() - self.enemy_transport_checkBox.raise_() - self.enemy_attack_helos_checkBox.raise_() - self.enemy_fighters_checkBox.raise_() - self.enemy_attack_planes_checkBox.raise_() self.inf_spawn_spinBox.raise_() self.smoke_checkBox.raise_() self.scenario_label_5.raise_() @@ -276,9 +282,14 @@ class Ui_MainWindow(object): self.scenario_label_6.raise_() self.force_offroad_checkBox.raise_() self.defense_checkBox.raise_() + self.e_attack_helos_spinBox.raise_() + self.scenario_label_7.raise_() + self.scenario_label_8.raise_() + self.e_attack_planes_spinBox.raise_() + self.zone_sams_checkBox.raise_() MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1140, 26)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1209, 26)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) @@ -329,14 +340,6 @@ class Ui_MainWindow(object): self.tankers_checkBox.setText(_translate("MainWindow", "Friendly Tankers")) self.apcs_spawn_checkBox.setStatusTip(_translate("MainWindow", "Friendly/enemy APCs will drop infantry when reaching a new conflict zone.")) self.apcs_spawn_checkBox.setText(_translate("MainWindow", "APCs Spawn Infantry")) - self.enemy_transport_checkBox.setStatusTip(_translate("MainWindow", "Not yet implemented.")) - self.enemy_transport_checkBox.setText(_translate("MainWindow", "Enemy Transport Helicopters")) - self.enemy_attack_helos_checkBox.setStatusTip(_translate("MainWindow", "Not yet implemented.")) - self.enemy_attack_helos_checkBox.setText(_translate("MainWindow", "Enemy Attack Helicopters")) - self.enemy_fighters_checkBox.setStatusTip(_translate("MainWindow", "Not yet implemented.")) - self.enemy_fighters_checkBox.setText(_translate("MainWindow", "Enemy Fighter Planes")) - self.enemy_attack_planes_checkBox.setStatusTip(_translate("MainWindow", "Not yet implemented.")) - self.enemy_attack_planes_checkBox.setText(_translate("MainWindow", "Enemy Ground Attack Planes")) self.inf_spawn_spinBox.setStatusTip(_translate("MainWindow", "This value is multiplied by the number of spawn zones in the mission template.")) self.smoke_checkBox.setStatusTip(_translate("MainWindow", "Not yet implemented.")) self.smoke_checkBox.setText(_translate("MainWindow", "Smoke Active Zone")) @@ -349,6 +352,12 @@ class Ui_MainWindow(object): self.force_offroad_checkBox.setStatusTip(_translate("MainWindow", "May help prevent long travel times or pathfinding issues. Tip: You can change this dynamically from mission triggers.")) self.force_offroad_checkBox.setText(_translate("MainWindow", "Force Offroad")) self.defense_checkBox.setText(_translate("MainWindow", "Defensive Mode")) + self.e_attack_helos_spinBox.setStatusTip(_translate("MainWindow", "Approximate number of enemy attack helicopter group spawns.")) + self.scenario_label_7.setText(_translate("MainWindow", "Enemy Attack Helicopters")) + self.scenario_label_8.setText(_translate("MainWindow", "Enemy Attack Planes")) + self.e_attack_planes_spinBox.setStatusTip(_translate("MainWindow", "Approximate number of enemy attack plane group spawns.")) + self.zone_sams_checkBox.setStatusTip(_translate("MainWindow", "Inactive conflict zones will be protected by SAMs. When a zone is cleared, SAMs at next active zone will be destroyed.")) + self.zone_sams_checkBox.setText(_translate("MainWindow", "Inactive Zone SAMs")) self.action_generateMission.setText(_translate("MainWindow", "_generateMission")) self.action_scenarioSelected.setText(_translate("MainWindow", "_scenarioSelected")) self.action_blueforcesSelected.setText(_translate("MainWindow", "_blueforcesSelected")) diff --git a/Generator/MissionGeneratorUI.ui b/Generator/MissionGeneratorUI.ui index be27f4a..3c32722 100644 --- a/Generator/MissionGeneratorUI.ui +++ b/Generator/MissionGeneratorUI.ui @@ -6,8 +6,8 @@ 0 0 - 1140 - 826 + 1209 + 900 @@ -75,8 +75,8 @@ - 940 - 720 + 1020 + 790 141 41 @@ -183,8 +183,8 @@ p, li { white-space: pre-wrap; } - 10 - 430 + -30 + 490 801 371 @@ -312,8 +312,8 @@ p, li { white-space: pre-wrap; } - 910 - 510 + 1000 + 590 191 16 @@ -339,8 +339,8 @@ p, li { white-space: pre-wrap; } - 910 - 570 + 1000 + 650 191 16 @@ -363,8 +363,8 @@ p, li { white-space: pre-wrap; } - 910 - 320 + 970 + 390 251 31 @@ -384,8 +384,8 @@ p, li { white-space: pre-wrap; } - 910 - 350 + 970 + 420 251 31 @@ -401,12 +401,15 @@ p, li { white-space: pre-wrap; } Friendly AWACS + + true + - 910 - 380 + 970 + 450 251 31 @@ -419,11 +422,14 @@ p, li { white-space: pre-wrap; } Friendly Tankers + + true + - 470 + 500 400 251 31 @@ -441,106 +447,10 @@ p, li { white-space: pre-wrap; } APCs Spawn Infantry - - - false - - - - 70 - 320 - 251 - 31 - - - - - 11 - - - - Not yet implemented. - - - Enemy Transport Helicopters - - - - - true - - - - 70 - 350 - 251 - 31 - - - - - 11 - - - - Not yet implemented. - - - Enemy Attack Helicopters - - - - - false - - - - 70 - 380 - 251 - 31 - - - - - 11 - - - - Not yet implemented. - - - Enemy Fighter Planes - - - - - true - - - - 70 - 410 - 251 - 31 - - - - - 11 - - - - Not yet implemented. - - - Enemy Ground Attack Planes - - - 680 + 710 360 71 31 @@ -567,8 +477,8 @@ p, li { white-space: pre-wrap; } - 910 - 540 + 1000 + 620 191 16 @@ -628,7 +538,7 @@ p, li { white-space: pre-wrap; } - 470 + 500 360 191 31 @@ -646,8 +556,8 @@ p, li { white-space: pre-wrap; } - 790 - 630 + 870 + 700 291 31 @@ -659,8 +569,8 @@ p, li { white-space: pre-wrap; } - 650 - 630 + 750 + 700 111 31 @@ -677,7 +587,7 @@ p, li { white-space: pre-wrap; } - 470 + 500 320 141 31 @@ -695,8 +605,8 @@ p, li { white-space: pre-wrap; } - 910 - 480 + 1000 + 560 191 16 @@ -737,6 +647,117 @@ p, li { white-space: pre-wrap; } Defensive Mode + + + + 70 + 330 + 51 + 31 + + + + + 12 + + + + Approximate number of enemy attack helicopter group spawns. + + + 0 + + + 50 + + + 2 + + + + + + 140 + 330 + 231 + 31 + + + + + 11 + + + + Enemy Attack Helicopters + + + + + + 140 + 370 + 231 + 31 + + + + + 11 + + + + Enemy Attack Planes + + + + + + 70 + 370 + 51 + 31 + + + + + 12 + + + + Approximate number of enemy attack plane group spawns. + + + 0 + + + 50 + + + 1 + + + + + + 970 + 480 + 201 + 31 + + + + + 11 + + + + Inactive conflict zones will be protected by SAMs. When a zone is cleared, SAMs at next active zone will be destroyed. + + + Inactive Zone SAMs + + background_label scenario_comboBox scenario_label @@ -757,10 +778,6 @@ p, li { white-space: pre-wrap; } awacs_checkBox tankers_checkBox apcs_spawn_checkBox - enemy_transport_checkBox - enemy_attack_helos_checkBox - enemy_fighters_checkBox - enemy_attack_planes_checkBox inf_spawn_spinBox smoke_checkBox scenario_label_5 @@ -771,13 +788,18 @@ p, li { white-space: pre-wrap; } scenario_label_6 force_offroad_checkBox defense_checkBox + e_attack_helos_spinBox + scenario_label_7 + scenario_label_8 + e_attack_planes_spinBox + zone_sams_checkBox 0 0 - 1140 + 1209 26 diff --git a/Generator/RotorOpsMission.py b/Generator/RotorOpsMission.py index 937c7f5..0478d58 100644 --- a/Generator/RotorOpsMission.py +++ b/Generator/RotorOpsMission.py @@ -10,16 +10,11 @@ import time class RotorOpsMission: - conflict_zones = {} - staging_zones = {} - spawn_zones = {} - scripts = {} + def __init__(self): self.m = dcs.mission.Mission() - self.old_blue = self.m.coalition.get("blue").dict() - self.old_red = self.m.coalition.get("red").dict() os.chdir("../") self.home_dir = os.getcwd() self.scenarios_dir = self.home_dir + "\Generator\Scenarios" @@ -29,6 +24,11 @@ class RotorOpsMission: self.output_dir = self.home_dir + "\Generator\Output" self.assets_dir = self.home_dir + "\Generator/assets" + self.conflict_zones = {} + self.staging_zones = {} + self.spawn_zones = {} + self.scripts = {} + class RotorOpsZone: def __init__(self, name: str, flag: int, position: dcs.point, size: int): @@ -94,9 +94,9 @@ class RotorOpsMission: self.m.load_file(options["scenario_filename"]) - #Load the default coalitions for simplicity - self.m.coalition.get("blue").load_from_dict(self.m, self.old_blue) - self.m.coalition.get("red").load_from_dict(self.m, self.old_red) + if not self.m.country("Russia") or not self.m.country("USA"): + failure_msg = "You must include a USA and Russia unit in the scenario template. See the instructions in " + self.scenarios_dir + return {"success": False, "failure_msg": failure_msg} red_forces = self.getUnitsFromMiz(options["red_forces_filename"], "red") @@ -142,12 +142,36 @@ class RotorOpsMission: if red_forces: self.addGroundGroups(red_zones[zone_name], self.m.country('Russia'), red_forces, options["red_quantity"]) + if options["zone_protect_sams"]: + for zone_name in red_zones: + self.m.vehicle_group( + self.m.country('Russia'), + zone_name + " Protection SAM NOAI", + random.choice(RotorOpsUnits.e_zone_sams), + red_zones[zone_name].position, + heading=random.randint(0, 359), + group_size=6, + formation=dcs.unitgroup.VehicleGroup.Formation.Star + ) + #Add blue ground units for zone_name in blue_zones: if blue_forces: self.addGroundGroups(blue_zones[zone_name], self.m.country('USA'), blue_forces, options["blue_quantity"]) + if options["zone_protect_sams"]: + for zone_name in blue_zones: + self.m.vehicle_group( + self.m.country('USA'), + zone_name + " Protection SAM NOAI", + random.choice(RotorOpsUnits.e_zone_sams), + blue_zones[zone_name].position, + heading=random.randint(0, 359), + group_size=6, + formation=dcs.unitgroup.VehicleGroup.Formation.Star + ) + #Add player slots if options["slots"] == "Multiple Slots": self.addMultiplayerHelos() @@ -156,6 +180,7 @@ class RotorOpsMission: if helicopter == options["slots"]: self.addSinglePlayerHelos(dcs.helicopters.helicopter_map[helicopter]) + #Add AI Flights self.addFlights(options) #Set the Editor Map View @@ -178,17 +203,19 @@ class RotorOpsMission: if dcs.vehicles.vehicle_map[unit.type]: unit_types.append(dcs.vehicles.vehicle_map[unit.type]) country = self.m.country(_country.name) - pos1 = zone.position.point_from_heading(5, 500) + #pos1 = zone.position.point_from_heading(5, 200) #for i in range(0, quantity): self.m.vehicle_group_platoon( country, zone.name + '-GND ' + str(a+1), unit_types, - pos1.random_point_within(zone.size / 2, 500), + zone.position.random_point_within(zone.size / 1.2, 100), + #pos1.random_point_within(zone.size / 2.5, 100), heading=random.randint(0, 359), formation=dcs.unitgroup.VehicleGroup.Formation.Scattered, ) + def getCoalitionAirports(self, side: str): coalition_airports = [] for airport_name in self.m.terrain.airports: @@ -197,22 +224,72 @@ class RotorOpsMission: coalition_airports.append(airport_name) return coalition_airports + def getParking(self, airport, aircraft): + slot = airport.free_parking_slot(aircraft) + slots = airport.free_parking_slots(aircraft) + if slot: + return airport + else: + print("No parking available for " + aircraft.id + " at " + airport.name) + return None + + #Find parking spots on FARPs and carriers + def getUnitParking(self, aircraft): + return + def addSinglePlayerHelos(self, helotype): + + carrier = self.m.country("USA").find_ship_group(name="HELO_CARRIER") + farp = self.m.country("USA").find_static_group("HELO_FARP") friendly_airports = self.getCoalitionAirports("blue") - for airport_name in friendly_airports: - fg = self.m.flight_group_from_airport(self.m.country('USA'), "Player Helos", helotype, - self.m.terrain.airports[airport_name], group_size=2) - fg.units[0].set_player() + + if carrier: + fg = self.m.flight_group_from_unit(self.m.country('USA'), "CARRIER " + helotype.id, helotype, carrier, dcs.task.CAS, group_size=2) + + elif farp: + fg = self.m.flight_group_from_unit(self.m.country('USA'), "FARP " + helotype.id, helotype, farp, dcs.task.CAS, group_size=2) + fg.units[0].position = fg.units[0].position.point_from_heading(90, 30) + + # invisible farps need manual unit placement for multiple units + if farp.units[0].type == 'Invisible FARP': + fg.points[0].action = dcs.point.PointAction.FromGroundArea + fg.points[0].type = "TakeOffGround" + fg.units[0].position = fg.units[0].position.point_from_heading(0, 30) + + else: + for airport_name in friendly_airports: + fg = self.m.flight_group_from_airport(self.m.country('USA'), airport_name + " " + helotype.id, helotype, + self.getParking(self.m.terrain.airports[airport_name], helotype), group_size=2) + fg.units[0].set_player() + def addMultiplayerHelos(self): + carrier = self.m.country("USA").find_ship_group(name="HELO_CARRIER") + farp = self.m.country("USA").find_static_group("HELO_FARP") friendly_airports = self.getCoalitionAirports("blue") - for airport_name in friendly_airports: - for helotype in RotorOpsUnits.client_helos: - fg = self.m.flight_group_from_airport(self.m.country('USA'), airport_name + " " + helotype.id, helotype, - self.m.terrain.airports[airport_name], group_size=1) - fg.units[0].set_client() + + heading = 0 + for helotype in RotorOpsUnits.client_helos: + if carrier: + fg = self.m.flight_group_from_unit(self.m.country('USA'), "CARRIER " + helotype.id, helotype, carrier, + dcs.task.CAS, group_size=1) + elif farp: + fg = self.m.flight_group_from_unit(self.m.country('USA'), "FARP " + helotype.id, helotype, farp, + dcs.task.CAS, group_size=1) + + #invisible farps need manual unit placement for multiple units + if farp.units[0].type == 'Invisible FARP': + fg.points[0].action = dcs.point.PointAction.FromGroundArea + fg.points[0].type = "TakeOffGround" + fg.units[0].position = fg.units[0].position.point_from_heading(heading, 30) + heading += 90 + else: + for airport_name in friendly_airports: + fg = self.m.flight_group_from_airport(self.m.country('USA'), airport_name + " " + helotype.id, helotype, + self.getParking(self.m.terrain.airports[airport_name], helotype), group_size=1) + fg.units[0].set_client() class TrainingScenario(): @@ -239,6 +316,8 @@ class RotorOpsMission: int(friendly_airport.position.x), int(friendly_airport.position.y - 100 * 1000), int(friendly_airport.position.x - 100 * 1000), int(friendly_airport.position.y)) + + if options["f_awacs"]: awacs_name = "AWACS" awacs_freq = 266 @@ -247,13 +326,20 @@ class RotorOpsMission: usa, awacs_name, plane_type=dcs.planes.E_3A, - airport=None, + airport=self.getParking(friendly_airport, dcs.planes.E_3A), position=pos, race_distance=race_dist, heading=heading, altitude=random.randrange(4000, 5500, 100), frequency=awacs_freq) - awacs_escort = self.m.escort_flight(usa, "AWACS Escort", dcs.countries.USA.Plane.F_15C, None, awacs, group_size=2) + awacs_escort = self.m.escort_flight( + usa, "AWACS Escort", + dcs.countries.USA.Plane.F_15C, + airport=self.getParking(friendly_airport, dcs.countries.USA.Plane.F_15C), + group_to_escort=awacs, + group_size=2) awacs_escort.load_loadout("Combat Air Patrol") #not working for f-15 + + #add text to mission briefing with radio freq briefing = self.m.description_text() + "\n\n" + awacs_name + " " + str(awacs_freq) + ".00 " + "\n" self.m.set_description_text(briefing) @@ -269,21 +355,30 @@ class RotorOpsMission: usa, t1_name, dcs.planes.KC130, - airport=None, + airport=self.getParking(friendly_airport, dcs.planes.KC130), position=pos, - race_distance=race_dist, heading=heading, - altitude=random.randrange(4000, 5500, 100), speed=750, frequency=t1_freq, tacanchannel=t1_tac) + race_distance=race_dist, + heading=heading, + altitude=random.randrange(4000, 5500, 100), + start_type=dcs.mission.StartType.Warm, + speed=750, + frequency=t1_freq, + tacanchannel=t1_tac) pos, heading, race_dist = self.TrainingScenario.random_orbit(orbit_rect) refuel_rod = self.m.refuel_flight( usa, t2_name, dcs.planes.KC_135, - airport=None, + airport=self.getParking(friendly_airport, dcs.planes.KC_135), position=pos, race_distance=race_dist, heading=heading, - altitude=random.randrange(4000, 5500, 100), frequency=t2_freq, tacanchannel=t2_tac) + altitude=random.randrange(4000, 5500, 100), + start_type=dcs.mission.StartType.Warm, + frequency=t2_freq, + tacanchannel=t2_tac) + #add text to mission briefing briefing = self.m.description_text() + "\n\n" + t1_name + " " + str(t1_freq) + ".00 " + t1_tac + "\n" + t2_name + " " + str(t2_freq) + ".00 " + t2_tac + "\n" self.m.set_description_text(briefing) @@ -309,6 +404,8 @@ class RotorOpsMission: fg.add_runway_waypoint(enemy_airport) fg.land_at(enemy_airport) + + if options["e_attack_helos"]: helo = random.choice(RotorOpsUnits.e_attack_helos) afg = self.m.flight_group_from_airport( @@ -340,13 +437,13 @@ class RotorOpsMission: game_flag = 100 #Add the first trigger - mytrig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Scripts") - mytrig.rules.append(dcs.condition.TimeAfter(1)) - mytrig.actions.append(dcs.action.DoScriptFile(self.scripts["mist_4_4_90.lua"])) - mytrig.actions.append(dcs.action.DoScriptFile(self.scripts["Splash_Damage_2_0.lua"])) - mytrig.actions.append(dcs.action.DoScriptFile(self.scripts["CTLD.lua"])) - mytrig.actions.append(dcs.action.DoScriptFile(self.scripts["RotorOps.lua"])) - mytrig.actions.append(dcs.action.DoScript(dcs.action.String(( + trig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Scripts") + trig.rules.append(dcs.condition.TimeAfter(1)) + trig.actions.append(dcs.action.DoScriptFile(self.scripts["mist_4_4_90.lua"])) + trig.actions.append(dcs.action.DoScriptFile(self.scripts["Splash_Damage_2_0.lua"])) + trig.actions.append(dcs.action.DoScriptFile(self.scripts["CTLD.lua"])) + trig.actions.append(dcs.action.DoScriptFile(self.scripts["RotorOps.lua"])) + trig.actions.append(dcs.action.DoScript(dcs.action.String(( "--OPTIONS HERE!\n\n" + "RotorOps.CTLD_crates = " + lb("crates") + "\n\n" + "RotorOps.CTLD_sound_effects = true\n\n" + @@ -355,53 +452,75 @@ class RotorOpsMission: "RotorOps.zone_status_display = " + lb("game_display") + "\n\n" + "RotorOps.inf_spawns_per_zone = " + lb("inf_spawn_qty") + "\n\n" + "RotorOps.apcs_spawn_infantry = " + lb("apc_spawns_inf") + " \n\n")))) - self.m.triggerrules.triggers.append(mytrig) + self.m.triggerrules.triggers.append(trig) #Add the second trigger - mytrig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Zones") - mytrig.rules.append(dcs.condition.TimeAfter(2)) + trig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Zones") + trig.rules.append(dcs.condition.TimeAfter(2)) for s_zone in self.staging_zones: - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.stagingZone('" + s_zone + "')"))) + trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.stagingZone('" + s_zone + "')"))) for c_zone in self.conflict_zones: zone_flag = self.conflict_zones[c_zone].flag - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.addZone('" + c_zone + "'," + str(zone_flag) + ")"))) + trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.addZone('" + c_zone + "'," + str(zone_flag) + ")"))) - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.setupConflict('" + str(game_flag) + "')"))) + trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.setupConflict('" + str(game_flag) + "')"))) - self.m.triggerrules.triggers.append(mytrig) + self.m.triggerrules.triggers.append(trig) #Add the third trigger - mytrig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict Start") - mytrig.rules.append(dcs.condition.TimeAfter(10)) - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.startConflict(100)"))) - self.m.triggerrules.triggers.append(mytrig) + trig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict Start") + trig.rules.append(dcs.condition.TimeAfter(10)) + trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.startConflict(100)"))) + self.m.triggerrules.triggers.append(trig) #Add all zone-based triggers - for index, c_zone in enumerate(self.conflict_zones): + for index, zone_name in enumerate(self.conflict_zones): - z_active_trig = dcs.triggers.TriggerOnce(comment= c_zone + " Active") + z_active_trig = dcs.triggers.TriggerOnce(comment= zone_name + " Active") z_active_trig.rules.append(dcs.condition.FlagEquals(game_flag, index + 1)) z_active_trig.actions.append(dcs.action.DoScript(dcs.action.String("--Add any action you want here!"))) + #Smoke action not working + # if options["smoke_zone"]: + # z_active_trig.actions.append(dcs.action.Smoke(zone=zone_name, density=1, preset=1)) + # if index > 0: + # previous_zone = list(self.conflict_zones)[index - 1] + # z_active_trig.actions.append(dcs.action.Smoke(zone=previous_zone, density=1, preset=0)) + #Zone protection SAMs + if options["zone_protect_sams"]: + z_active_trig.actions.append(dcs.action.DoScript(dcs.action.String("Group.destroy(Group.getByName('" + zone_name + " Protection SAM'))"))) self.m.triggerrules.triggers.append(z_active_trig) - zone_flag = self.conflict_zones[c_zone].flag - z_weak_trig = dcs.triggers.TriggerOnce(comment= c_zone + " Weak") - z_weak_trig.rules.append(dcs.condition.FlagIsMore(zone_flag, 10)) - z_weak_trig.rules.append(dcs.condition.FlagIsLess(zone_flag, random.randrange(20, 80))) - z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("--Add any action you want here!\n\n--Flag value represents the percentage of defending ground units remaining. "))) - if options["e_attack_helos"]: - z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("mist.respawnGroup('Enemy Attack Helicopters', true)"))) + #Add attack helos triggers + for index in range(options["e_attack_helos"]): + random_zone_obj = random.choice(list(self.conflict_zones.items())) + zone = random_zone_obj[1] + z_weak_trig = dcs.triggers.TriggerOnce(comment=zone.name + " Attack Helo") + z_weak_trig.rules.append(dcs.condition.FlagIsMore(zone.flag, 1)) + z_weak_trig.rules.append(dcs.condition.FlagIsLess(zone.flag, random.randrange(20, 90))) + z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("---Flag value represents the percentage of defending ground units remaining in zone. "))) + z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.spawnAttackHelos()"))) + self.m.triggerrules.triggers.append(z_weak_trig) + + #Add attack plane triggers + for index in range(options["e_attack_planes"]): + random_zone_obj = random.choice(list(self.conflict_zones.items())) + zone = random_zone_obj[1] + z_weak_trig = dcs.triggers.TriggerOnce(comment=zone.name + " Attack Plane") + z_weak_trig.rules.append(dcs.condition.FlagIsMore(zone.flag, 1)) + z_weak_trig.rules.append(dcs.condition.FlagIsLess(zone.flag, random.randrange(20, 90))) + z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("---Flag value represents the percentage of defending ground units remaining in zone. "))) + z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.spawnAttackPlanes()"))) self.m.triggerrules.triggers.append(z_weak_trig) #Add game won/lost triggers - mytrig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict WON") - mytrig.rules.append(dcs.condition.FlagEquals(game_flag, 99)) - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("---Add an action you want to happen when the game is WON"))) - self.m.triggerrules.triggers.append(mytrig) + trig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict WON") + trig.rules.append(dcs.condition.FlagEquals(game_flag, 99)) + trig.actions.append(dcs.action.DoScript(dcs.action.String("---Add an action you want to happen when the game is WON"))) + self.m.triggerrules.triggers.append(trig) - mytrig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict LOST") - mytrig.rules.append(dcs.condition.FlagEquals(game_flag, 98)) - mytrig.actions.append(dcs.action.DoScript(dcs.action.String("---Add an action you want to happen when the game is LOST"))) - self.m.triggerrules.triggers.append(mytrig) + trig = dcs.triggers.TriggerOnce(comment="RotorOps Conflict LOST") + trig.rules.append(dcs.condition.FlagEquals(game_flag, 98)) + trig.actions.append(dcs.action.DoScript(dcs.action.String("---Add an action you want to happen when the game is LOST"))) + self.m.triggerrules.triggers.append(trig) diff --git a/Generator/RotorOpsUnits.py b/Generator/RotorOpsUnits.py index 9c79331..837d793 100644 --- a/Generator/RotorOpsUnits.py +++ b/Generator/RotorOpsUnits.py @@ -23,5 +23,8 @@ e_attack_planes = [ #{'type': dcs.planes.Su_34, 'loadout': "APU-8 Vikhr-M*2,Kh-25ML,R-73*2,SPPU-22*2,Mercury LLTV Pod,MPS-410"}, #{'type': dcs.planes.Su_25, 'loadout': "RKB-250*8,R-60M*2"}, {'type': dcs.planes.A_10C, 'loadout': ""} +] +e_zone_sams = [ + dcs.vehicles.AirDefence.Strela_10M3, ] \ No newline at end of file diff --git a/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz b/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz index bdff90b..78a8300 100644 Binary files a/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz and b/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz differ diff --git a/Generator/Scenarios/Caucasus Conflict - Nalchik to Beslan (GRIMM).miz b/Generator/Scenarios/Caucasus Conflict - Nalchik to Beslan (GRIMM).miz index 3272359..693096c 100644 Binary files a/Generator/Scenarios/Caucasus Conflict - Nalchik to Beslan (GRIMM).miz and b/Generator/Scenarios/Caucasus Conflict - Nalchik to Beslan (GRIMM).miz differ diff --git a/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz b/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz index ab75887..544c62c 100644 Binary files a/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz and b/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz differ diff --git a/Generator/Scenarios/Nevada Conflict - Vegas Tour (GRIMM).miz b/Generator/Scenarios/Nevada Conflict - Vegas Tour (GRIMM).miz index 941380f..4a47022 100644 Binary files a/Generator/Scenarios/Nevada Conflict - Vegas Tour (GRIMM).miz and b/Generator/Scenarios/Nevada Conflict - Vegas Tour (GRIMM).miz differ diff --git a/Generator/Scenarios/PG Conflict - Abu Dhabi to Ras (GRIMM).miz b/Generator/Scenarios/PG Conflict - Abu Dhabi to Ras (GRIMM).miz index ef54d1f..e1e6964 100644 Binary files a/Generator/Scenarios/PG Conflict - Abu Dhabi to Ras (GRIMM).miz and b/Generator/Scenarios/PG Conflict - Abu Dhabi to Ras (GRIMM).miz differ diff --git a/Generator/Scenarios/Syria Conflict - Aleppo Tour (GRIMM).miz b/Generator/Scenarios/Syria Conflict - Aleppo Tour (GRIMM).miz index d936511..940a2af 100644 Binary files a/Generator/Scenarios/Syria Conflict - Aleppo Tour (GRIMM).miz and b/Generator/Scenarios/Syria Conflict - Aleppo Tour (GRIMM).miz differ diff --git a/Generator/Scenarios/_How to create your own scenarios.txt b/Generator/Scenarios/_How to create your own scenarios.txt index f343852..24b9f90 100644 --- a/Generator/Scenarios/_How to create your own scenarios.txt +++ b/Generator/Scenarios/_How to create your own scenarios.txt @@ -1,20 +1,35 @@ -You can add your own scenarios in this directory and they will appear in the mission generator. +You can add your own scenarios in this directory and they will appear in the mission generator. See the other scenario .miz files for examples of what to include in your template. + A scenario .miz file MUST have: 1) Between 1-4 trigger zones called "ALPHA", "BRAVO", "CHARLIE", "DELTA" 2) At least one trigger zone with a name that starts with "STAGING". -3) A blue airport (recommend somewhere near your staging zone). -4) A red airport (recommend somewhere near your last conflict zone). +3) A blue airport (recommend somewhere near/on-side your staging zone). +4) A red airport (recommend somewhere near/on-side your last conflict zone). +5) At least one Russian unit or static object. Anything will work, even a cow. You can set "HIDDEN ON MAP". +6) At least one USA unit or static object. See previous point. + + Optional: -You can add smaller infantry spawning zones inside conflict zones. Add near buildings to simulate infantry hiding within. Name them like "ALPHA_SPAWN", "ALPHA_SPAWN_2, etc. +7) USA FARP called "HELO_FARP" for automatic player placement. +8) USA Carrier called "HELO_CARRIER" for automatic player placement. +9) Infantry spawn zones inside conflict zones. Add near buildings to simulate infantry hiding within. Name trigger zones like "ALPHA_SPAWN", "ALPHA_SPAWN_2, etc. + + Tips: +-Position the center of conflict zones over an open area, as this position may be used to spawn units. -The conflict game type can be played with blue forces on defense. In this mode the last conflict zone is the only troop pickup zone. -Design your template so that it can be played in normal 'attacking' mode or 'defending' the conflict zone from enemy ground units starting from the staging zone. -Keep the zones fairly close together, both for helicopter and ground unit travel times. -You can place static objects and units in a scenario template. -You can change mission briefing and other mission options in the template. -Drop your templates in the RotorOps Discord if you'd like to have them added in a release for everyone. Maintain a similar naming convention and be sure to credit yourself in the .miz name. --Airfields can be captured with ground units. You might consider placing conflict zones over neutral airfields and adding unarmed client slots. +-Airfields can be captured with ground units. You might consider placing conflict zones over neutral airfields for a rearming area, or perhaps unarmed client slots. +-Player/client slots are placed in this priority order: Carrier named "HELO_CARRIER", FARP named "HELO_FARP", and the blue airfield. +-Friendly AWACs and tankers will be placed at the blue airport if parking is available, otherwise they will start in the air. +-Enemy helicopters and planes will spawn at the red airport. +-Late activation FARPs might be useful for rearming far from the player spawn point. + diff --git a/Generator/build command.txt b/Generator/build command.txt new file mode 100644 index 0000000..20fdd10 --- /dev/null +++ b/Generator/build command.txt @@ -0,0 +1,5 @@ +#build UI files +pyuic5 -x MissionGeneratorUI.ui -o MissionGeneratorUI.py + +#build exe +pyinstaller MissionGenerator.spec --distpath ..\ -i='assets\icon.ico' \ No newline at end of file diff --git a/Mission Templates/RotorOps_template_Caucasus.miz b/Mission Templates/RotorOps_template_Caucasus.miz deleted file mode 100644 index 841ab03..0000000 Binary files a/Mission Templates/RotorOps_template_Caucasus.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_Mariana.miz b/Mission Templates/RotorOps_template_Mariana.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_Mariana.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_Nevada.miz b/Mission Templates/RotorOps_template_Nevada.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_Nevada.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_Normandy.miz b/Mission Templates/RotorOps_template_Normandy.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_Normandy.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_Persian_Gulf.miz b/Mission Templates/RotorOps_template_Persian_Gulf.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_Persian_Gulf.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_Syria.miz b/Mission Templates/RotorOps_template_Syria.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_Syria.miz and /dev/null differ diff --git a/Mission Templates/RotorOps_template_The_Channel.miz b/Mission Templates/RotorOps_template_The_Channel.miz deleted file mode 100644 index 2a0edd8..0000000 Binary files a/Mission Templates/RotorOps_template_The_Channel.miz and /dev/null differ diff --git a/MissionGenerator.exe b/MissionGenerator.exe index fb73efe..9c893ff 100644 Binary files a/MissionGenerator.exe and b/MissionGenerator.exe differ diff --git a/RotorOps.lua b/RotorOps.lua index b297c16..0e433e8 100644 --- a/RotorOps.lua +++ b/RotorOps.lua @@ -1,6 +1,6 @@ RotorOps = {} -RotorOps.version = "1.2.3" -local debug = true +RotorOps.version = "1.2.4" +local debug = false ---[[ROTOROPS OPTIONS]]--- @@ -23,7 +23,7 @@ RotorOps.inf_spawns_per_zone = 3 --number of infantry groups to spawn per zone --RotorOps settings that are safe to change only before calling setupConflict() -RotorOps.transports = {'UH-1H', 'Mi-8MT', 'Mi-24P', 'SA342M', 'SA342L', 'SA342Mistral'} --players flying these will have ctld transport access +RotorOps.transports = {'UH-1H', 'Mi-8MT', 'Mi-24P', 'SA342M', 'SA342L', 'SA342Mistral', 'UH-60L'} --players flying these will have ctld transport access RotorOps.CTLD_crates = false RotorOps.CTLD_sound_effects = true --sound effects for troop pickup/dropoffs RotorOps.exclude_ai_group_name = "noai" --include this somewhere in a group name to exclude the group from being tasked in the active zone @@ -138,6 +138,13 @@ RotorOps.gameMsgs = { {'ENEMY TOOK CHARLIE!', 'enemy_destroying_us.ogg'}, {'ENEMY TOOK DELTA!', 'enemy_destroying_us.ogg'}, }, + attack_helos = { + {'ENEMY ATTACK HELICOPTERS INBOUND!', 'enemy_attack_choppers.ogg'}, + }, + attack_planes = { + {'ENEMY ATTACK PLANES INBOUND!', 'enemy_attack_planes.ogg'}, + }, + } @@ -1243,6 +1250,32 @@ function RotorOps.startConflict() end +function RotorOps.triggerSpawn(groupName, msg) + local group = Group.getByName(groupName) + if group and group:isExist() == true and #group:getUnits() > 0 and group:getUnits()[1]:getLife() > 1 and group:getUnits()[1]:isActive() then + env.info("RotorOps tried to respawn "..groupName.." but it's already active.") + else + local new_group = mist.respawnGroup(groupName, true) + if new_group then + RotorOps.gameMsg(msg) + env.info("RotorOps spawned "..groupName) + return new_group + end + end + + return nil + +end + + +function RotorOps.spawnAttackHelos() + RotorOps.triggerSpawn("Enemy Attack Helicopters", RotorOps.gameMsgs.attack_helos) +end + + +function RotorOps.spawnAttackPlanes() + RotorOps.triggerSpawn("Enemy Attack Planes", RotorOps.gameMsgs.attack_planes) +end diff --git a/Splash_Damage_2_0.lua b/Splash_Damage_2_0.lua index ea02520..1e2719a 100644 --- a/Splash_Damage_2_0.lua +++ b/Splash_Damage_2_0.lua @@ -438,6 +438,7 @@ end if (script_enable == 1) then gameMsg("SPLASH DAMAGE 2 SCRIPT RUNNING") + env.info("SPLASH DAMAGE 2 SCRIPT RUNNING") timer.scheduleFunction(function() protectedCall(track_wpns) return timer.getTime() + refreshRate diff --git a/sound/convoy_forward_base.ogg b/sound/convoy_forward_base.ogg new file mode 100644 index 0000000..56108e6 Binary files /dev/null and b/sound/convoy_forward_base.ogg differ diff --git a/sound/downed_pilot.ogg b/sound/downed_pilot.ogg new file mode 100644 index 0000000..c62b587 Binary files /dev/null and b/sound/downed_pilot.ogg differ diff --git a/sound/embedded/enemy_attack_choppers.ogg b/sound/embedded/enemy_attack_choppers.ogg new file mode 100644 index 0000000..b875c57 Binary files /dev/null and b/sound/embedded/enemy_attack_choppers.ogg differ diff --git a/sound/embedded/enemy_attack_planes.ogg b/sound/embedded/enemy_attack_planes.ogg new file mode 100644 index 0000000..8fba8b8 Binary files /dev/null and b/sound/embedded/enemy_attack_planes.ogg differ diff --git a/sound/embedded/enemy_chopper_inbound.ogg b/sound/embedded/enemy_chopper_inbound.ogg new file mode 100644 index 0000000..e14c1b4 Binary files /dev/null and b/sound/embedded/enemy_chopper_inbound.ogg differ diff --git a/sound/embedded/enemy_fighters_inbound.ogg b/sound/embedded/enemy_fighters_inbound.ogg new file mode 100644 index 0000000..cc1cd09 Binary files /dev/null and b/sound/embedded/enemy_fighters_inbound.ogg differ diff --git a/sound/forward_base_established.ogg b/sound/forward_base_established.ogg new file mode 100644 index 0000000..f49cbae Binary files /dev/null and b/sound/forward_base_established.ogg differ diff --git a/sound/friendly_awacs_available.ogg b/sound/friendly_awacs_available.ogg new file mode 100644 index 0000000..993ac4d Binary files /dev/null and b/sound/friendly_awacs_available.ogg differ diff --git a/sound/friendly_bombing_run_avail.ogg b/sound/friendly_bombing_run_avail.ogg new file mode 100644 index 0000000..9d08c13 Binary files /dev/null and b/sound/friendly_bombing_run_avail.ogg differ