mirror of
https://github.com/spencershepard/RotorOps.git
synced 2025-11-10 15:45:30 +00:00
Merge pull request #17 from spencershepard/feature/zone-protect-sams
This commit is contained in:
commit
bcaff119ad
BIN
Generator/Forces/red/RED Default Armor.miz
Normal file
BIN
Generator/Forces/red/RED Default Armor.miz
Normal file
Binary file not shown.
@ -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_()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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"))
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1140</width>
|
||||
<height>826</height>
|
||||
<width>1209</width>
|
||||
<height>900</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
@ -75,8 +75,8 @@
|
||||
<widget class="QPushButton" name="generateButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>940</x>
|
||||
<y>720</y>
|
||||
<x>1020</x>
|
||||
<y>790</y>
|
||||
<width>141</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
@ -183,8 +183,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QLabel" name="background_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>430</y>
|
||||
<x>-30</x>
|
||||
<y>490</y>
|
||||
<width>801</width>
|
||||
<height>371</height>
|
||||
</rect>
|
||||
@ -312,8 +312,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="game_status_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>510</y>
|
||||
<x>1000</x>
|
||||
<y>590</y>
|
||||
<width>191</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
@ -339,8 +339,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="voiceovers_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>570</y>
|
||||
<x>1000</x>
|
||||
<y>650</y>
|
||||
<width>191</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
@ -363,8 +363,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="logistics_crates_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>320</y>
|
||||
<x>970</x>
|
||||
<y>390</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -384,8 +384,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="awacs_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>350</y>
|
||||
<x>970</x>
|
||||
<y>420</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -401,12 +401,15 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="text">
|
||||
<string>Friendly AWACS</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="tankers_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>380</y>
|
||||
<x>970</x>
|
||||
<y>450</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -419,11 +422,14 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="text">
|
||||
<string>Friendly Tankers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="apcs_spawn_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>470</x>
|
||||
<x>500</x>
|
||||
<y>400</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
@ -441,106 +447,10 @@ p, li { white-space: pre-wrap; }
|
||||
<string>APCs Spawn Infantry</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="enemy_transport_checkBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>320</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Not yet implemented.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Transport Helicopters</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="enemy_attack_helos_checkBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>350</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Not yet implemented.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Attack Helicopters</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="enemy_fighters_checkBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>380</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Not yet implemented.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Fighter Planes</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="enemy_attack_planes_checkBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>410</y>
|
||||
<width>251</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Not yet implemented.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Ground Attack Planes</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="inf_spawn_spinBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>680</x>
|
||||
<x>710</x>
|
||||
<y>360</y>
|
||||
<width>71</width>
|
||||
<height>31</height>
|
||||
@ -567,8 +477,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="smoke_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>540</y>
|
||||
<x>1000</x>
|
||||
<y>620</y>
|
||||
<width>191</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
@ -628,7 +538,7 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>470</x>
|
||||
<x>500</x>
|
||||
<y>360</y>
|
||||
<width>191</width>
|
||||
<height>31</height>
|
||||
@ -646,8 +556,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QComboBox" name="slot_template_comboBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>790</x>
|
||||
<y>630</y>
|
||||
<x>870</x>
|
||||
<y>700</y>
|
||||
<width>291</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -659,8 +569,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>650</x>
|
||||
<y>630</y>
|
||||
<x>750</x>
|
||||
<y>700</y>
|
||||
<width>111</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
@ -677,7 +587,7 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QLabel" name="scenario_label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>470</x>
|
||||
<x>500</x>
|
||||
<y>320</y>
|
||||
<width>141</width>
|
||||
<height>31</height>
|
||||
@ -695,8 +605,8 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QCheckBox" name="force_offroad_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>910</x>
|
||||
<y>480</y>
|
||||
<x>1000</x>
|
||||
<y>560</y>
|
||||
<width>191</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
@ -737,6 +647,117 @@ p, li { white-space: pre-wrap; }
|
||||
<string>Defensive Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="e_attack_helos_spinBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>330</y>
|
||||
<width>51</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Approximate number of enemy attack helicopter group spawns.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="scenario_label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>330</y>
|
||||
<width>231</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Attack Helicopters</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="scenario_label_8">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>370</y>
|
||||
<width>231</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enemy Attack Planes</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="e_attack_planes_spinBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>370</y>
|
||||
<width>51</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Approximate number of enemy attack plane group spawns.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="zone_sams_checkBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>970</x>
|
||||
<y>480</y>
|
||||
<width>201</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Inactive conflict zones will be protected by SAMs. When a zone is cleared, SAMs at next active zone will be destroyed.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Inactive Zone SAMs</string>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>background_label</zorder>
|
||||
<zorder>scenario_comboBox</zorder>
|
||||
<zorder>scenario_label</zorder>
|
||||
@ -757,10 +778,6 @@ p, li { white-space: pre-wrap; }
|
||||
<zorder>awacs_checkBox</zorder>
|
||||
<zorder>tankers_checkBox</zorder>
|
||||
<zorder>apcs_spawn_checkBox</zorder>
|
||||
<zorder>enemy_transport_checkBox</zorder>
|
||||
<zorder>enemy_attack_helos_checkBox</zorder>
|
||||
<zorder>enemy_fighters_checkBox</zorder>
|
||||
<zorder>enemy_attack_planes_checkBox</zorder>
|
||||
<zorder>inf_spawn_spinBox</zorder>
|
||||
<zorder>smoke_checkBox</zorder>
|
||||
<zorder>scenario_label_5</zorder>
|
||||
@ -771,13 +788,18 @@ p, li { white-space: pre-wrap; }
|
||||
<zorder>scenario_label_6</zorder>
|
||||
<zorder>force_offroad_checkBox</zorder>
|
||||
<zorder>defense_checkBox</zorder>
|
||||
<zorder>e_attack_helos_spinBox</zorder>
|
||||
<zorder>scenario_label_7</zorder>
|
||||
<zorder>scenario_label_8</zorder>
|
||||
<zorder>e_attack_planes_spinBox</zorder>
|
||||
<zorder>zone_sams_checkBox</zorder>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1140</width>
|
||||
<width>1209</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
|
||||
@ -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,
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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.
|
||||
|
||||
|
||||
5
Generator/build command.txt
Normal file
5
Generator/build command.txt
Normal file
@ -0,0 +1,5 @@
|
||||
#build UI files
|
||||
pyuic5 -x MissionGeneratorUI.ui -o MissionGeneratorUI.py
|
||||
|
||||
#build exe
|
||||
pyinstaller MissionGenerator.spec --distpath ..\ -i='assets\icon.ico'
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
39
RotorOps.lua
39
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
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
BIN
sound/convoy_forward_base.ogg
Normal file
BIN
sound/convoy_forward_base.ogg
Normal file
Binary file not shown.
BIN
sound/downed_pilot.ogg
Normal file
BIN
sound/downed_pilot.ogg
Normal file
Binary file not shown.
BIN
sound/embedded/enemy_attack_choppers.ogg
Normal file
BIN
sound/embedded/enemy_attack_choppers.ogg
Normal file
Binary file not shown.
BIN
sound/embedded/enemy_attack_planes.ogg
Normal file
BIN
sound/embedded/enemy_attack_planes.ogg
Normal file
Binary file not shown.
BIN
sound/embedded/enemy_chopper_inbound.ogg
Normal file
BIN
sound/embedded/enemy_chopper_inbound.ogg
Normal file
Binary file not shown.
BIN
sound/embedded/enemy_fighters_inbound.ogg
Normal file
BIN
sound/embedded/enemy_fighters_inbound.ogg
Normal file
Binary file not shown.
BIN
sound/forward_base_established.ogg
Normal file
BIN
sound/forward_base_established.ogg
Normal file
Binary file not shown.
BIN
sound/friendly_awacs_available.ogg
Normal file
BIN
sound/friendly_awacs_available.ogg
Normal file
Binary file not shown.
BIN
sound/friendly_bombing_run_avail.ogg
Normal file
BIN
sound/friendly_bombing_run_avail.ogg
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user