Merge pull request #19 from spencershepard/feature/progressive_farps_and_logistics

Feature/progressive farps and logistics
This commit is contained in:
spencershepard 2022-02-06 09:29:15 -08:00 committed by GitHub
commit 3299d937d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 550 additions and 130 deletions

Binary file not shown.

View File

@ -13,6 +13,9 @@ from PyQt5.QtWidgets import (
from PyQt5 import QtGui
from MissionGeneratorUI import Ui_MainWindow
maj_version = 0
minor_version = 3
version_string = str(maj_version) + "." + str(minor_version)
scenarios = []
red_forces_files = []
blue_forces_files = []
@ -43,6 +46,8 @@ class Window(QMainWindow, Ui_MainWindow):
self.statusbar.setStyleSheet(
"QStatusBar{padding-left:5px;color:black;font-weight:bold;}")
self.version_label.setText("Version " + version_string)
def connectSignalsSlots(self):
# self.action_Exit.triggered.connect(self.close)
@ -155,14 +160,14 @@ class Window(QMainWindow, Ui_MainWindow):
"crates": self.logistics_crates_checkBox.isChecked(),
"f_awacs": self.awacs_checkBox.isChecked(),
"f_tankers": self.tankers_checkBox.isChecked(),
"smoke_zone": self.smoke_checkBox.isChecked(),
"voiceovers": self.voiceovers_checkBox.isChecked(),
"force_offroad": self.force_offroad_checkBox.isChecked(),
"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(),
"zone_farps": self.farp_buttonGroup.checkedButton().objectName(),
"inf_spawn_msgs": self.inf_spawn_voiceovers_checkBox.isChecked(),
}
os.chdir(self.m.home_dir + '/Generator')
n = ROps.RotorOpsMission()

View File

@ -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(-30, 490, 801, 371))
self.background_label.setGeometry(QtCore.QRect(-40, 440, 801, 371))
self.background_label.setAutoFillBackground(False)
self.background_label.setStyleSheet("")
self.background_label.setText("")
@ -93,7 +93,7 @@ class Ui_MainWindow(object):
font.setPointSize(12)
self.blueqty_spinBox.setFont(font)
self.blueqty_spinBox.setMinimum(0)
self.blueqty_spinBox.setMaximum(50)
self.blueqty_spinBox.setMaximum(8)
self.blueqty_spinBox.setProperty("value", 3)
self.blueqty_spinBox.setObjectName("blueqty_spinBox")
self.redqty_spinBox = QtWidgets.QSpinBox(self.centralwidget)
@ -102,7 +102,7 @@ class Ui_MainWindow(object):
font.setPointSize(12)
self.redqty_spinBox.setFont(font)
self.redqty_spinBox.setMinimum(0)
self.redqty_spinBox.setMaximum(50)
self.redqty_spinBox.setMaximum(8)
self.redqty_spinBox.setProperty("value", 2)
self.redqty_spinBox.setObjectName("redqty_spinBox")
self.scenario_label_4 = QtWidgets.QLabel(self.centralwidget)
@ -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(1000, 590, 191, 16))
self.game_status_checkBox.setGeometry(QtCore.QRect(810, 790, 191, 16))
font = QtGui.QFont()
font.setPointSize(9)
self.game_status_checkBox.setFont(font)
@ -121,20 +121,21 @@ 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(1000, 650, 191, 16))
self.voiceovers_checkBox.setGeometry(QtCore.QRect(810, 820, 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(970, 390, 251, 31))
self.logistics_crates_checkBox.setGeometry(QtCore.QRect(920, 320, 251, 31))
font = QtGui.QFont()
font.setPointSize(11)
self.logistics_crates_checkBox.setFont(font)
self.logistics_crates_checkBox.setChecked(True)
self.logistics_crates_checkBox.setObjectName("logistics_crates_checkBox")
self.awacs_checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.awacs_checkBox.setGeometry(QtCore.QRect(970, 420, 251, 31))
self.awacs_checkBox.setGeometry(QtCore.QRect(920, 350, 251, 31))
font = QtGui.QFont()
font.setPointSize(11)
self.awacs_checkBox.setFont(font)
@ -142,34 +143,27 @@ class Ui_MainWindow(object):
self.awacs_checkBox.setChecked(True)
self.awacs_checkBox.setObjectName("awacs_checkBox")
self.tankers_checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.tankers_checkBox.setGeometry(QtCore.QRect(970, 450, 251, 31))
self.tankers_checkBox.setGeometry(QtCore.QRect(920, 380, 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(500, 400, 251, 31))
self.apcs_spawn_checkBox.setGeometry(QtCore.QRect(470, 400, 251, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.apcs_spawn_checkBox.setFont(font)
self.apcs_spawn_checkBox.setObjectName("apcs_spawn_checkBox")
self.inf_spawn_spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.inf_spawn_spinBox.setGeometry(QtCore.QRect(710, 360, 71, 31))
self.inf_spawn_spinBox.setGeometry(QtCore.QRect(680, 360, 71, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.inf_spawn_spinBox.setFont(font)
self.inf_spawn_spinBox.setMinimum(0)
self.inf_spawn_spinBox.setMaximum(50)
self.inf_spawn_spinBox.setMaximum(20)
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(1000, 620, 191, 16))
font = QtGui.QFont()
font.setPointSize(9)
self.smoke_checkBox.setFont(font)
self.smoke_checkBox.setChecked(True)
self.smoke_checkBox.setObjectName("smoke_checkBox")
self.scenario_label_5 = QtWidgets.QLabel(self.centralwidget)
self.scenario_label_5.setGeometry(QtCore.QRect(50, 260, 101, 31))
font = QtGui.QFont()
@ -182,28 +176,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(500, 360, 191, 31))
self.label.setGeometry(QtCore.QRect(470, 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(870, 700, 291, 31))
self.slot_template_comboBox.setGeometry(QtCore.QRect(870, 640, 291, 31))
self.slot_template_comboBox.setObjectName("slot_template_comboBox")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(750, 700, 111, 31))
self.label_2.setGeometry(QtCore.QRect(750, 640, 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(500, 320, 141, 31))
self.scenario_label_6.setGeometry(QtCore.QRect(470, 320, 141, 31))
font = QtGui.QFont()
font.setPointSize(11)
self.scenario_label_6.setFont(font)
self.scenario_label_6.setObjectName("scenario_label_6")
self.force_offroad_checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.force_offroad_checkBox.setGeometry(QtCore.QRect(1000, 560, 191, 16))
self.force_offroad_checkBox.setGeometry(QtCore.QRect(810, 760, 191, 16))
font = QtGui.QFont()
font.setPointSize(9)
self.force_offroad_checkBox.setFont(font)
@ -222,17 +216,17 @@ class Ui_MainWindow(object):
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.setMaximum(8)
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))
self.scenario_label_7.setGeometry(QtCore.QRect(140, 330, 211, 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))
self.scenario_label_8.setGeometry(QtCore.QRect(140, 370, 201, 31))
font = QtGui.QFont()
font.setPointSize(11)
self.scenario_label_8.setFont(font)
@ -243,15 +237,56 @@ class Ui_MainWindow(object):
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.setMaximum(8)
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))
self.zone_sams_checkBox.setGeometry(QtCore.QRect(920, 410, 201, 31))
font = QtGui.QFont()
font.setPointSize(11)
self.zone_sams_checkBox.setFont(font)
self.zone_sams_checkBox.setObjectName("zone_sams_checkBox")
self.scenario_label_9 = QtWidgets.QLabel(self.centralwidget)
self.scenario_label_9.setGeometry(QtCore.QRect(740, 490, 171, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.scenario_label_9.setFont(font)
self.scenario_label_9.setObjectName("scenario_label_9")
self.inf_spawn_voiceovers_checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.inf_spawn_voiceovers_checkBox.setGeometry(QtCore.QRect(470, 430, 251, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.inf_spawn_voiceovers_checkBox.setFont(font)
self.inf_spawn_voiceovers_checkBox.setChecked(True)
self.inf_spawn_voiceovers_checkBox.setObjectName("inf_spawn_voiceovers_checkBox")
self.farp_never = QtWidgets.QRadioButton(self.centralwidget)
self.farp_never.setGeometry(QtCore.QRect(950, 500, 95, 20))
font = QtGui.QFont()
font.setPointSize(9)
self.farp_never.setFont(font)
self.farp_never.setObjectName("farp_never")
self.farp_buttonGroup = QtWidgets.QButtonGroup(MainWindow)
self.farp_buttonGroup.setObjectName("farp_buttonGroup")
self.farp_buttonGroup.addButton(self.farp_never)
self.farp_gunits = QtWidgets.QRadioButton(self.centralwidget)
self.farp_gunits.setGeometry(QtCore.QRect(950, 530, 221, 21))
font = QtGui.QFont()
font.setPointSize(9)
self.farp_gunits.setFont(font)
self.farp_gunits.setChecked(True)
self.farp_gunits.setObjectName("farp_gunits")
self.farp_buttonGroup.addButton(self.farp_gunits)
self.farp_always = QtWidgets.QRadioButton(self.centralwidget)
self.farp_always.setGeometry(QtCore.QRect(950, 560, 221, 21))
font = QtGui.QFont()
font.setPointSize(9)
self.farp_always.setFont(font)
self.farp_always.setObjectName("farp_always")
self.farp_buttonGroup.addButton(self.farp_always)
self.version_label = QtWidgets.QLabel(self.centralwidget)
self.version_label.setGeometry(QtCore.QRect(920, 840, 241, 21))
self.version_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.version_label.setObjectName("version_label")
self.background_label.raise_()
self.scenario_comboBox.raise_()
self.scenario_label.raise_()
@ -273,7 +308,6 @@ class Ui_MainWindow(object):
self.tankers_checkBox.raise_()
self.apcs_spawn_checkBox.raise_()
self.inf_spawn_spinBox.raise_()
self.smoke_checkBox.raise_()
self.scenario_label_5.raise_()
self.forces_hint_label_2.raise_()
self.label.raise_()
@ -287,6 +321,12 @@ class Ui_MainWindow(object):
self.scenario_label_8.raise_()
self.e_attack_planes_spinBox.raise_()
self.zone_sams_checkBox.raise_()
self.scenario_label_9.raise_()
self.inf_spawn_voiceovers_checkBox.raise_()
self.farp_never.raise_()
self.farp_gunits.raise_()
self.farp_always.raise_()
self.version_label.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1209, 26))
@ -334,15 +374,13 @@ class Ui_MainWindow(object):
self.game_status_checkBox.setText(_translate("MainWindow", "Game Status Display"))
self.voiceovers_checkBox.setStatusTip(_translate("MainWindow", "Voiceovers from the ground commander. Helps keep focus on the active zone."))
self.voiceovers_checkBox.setText(_translate("MainWindow", "Voiceovers"))
self.logistics_crates_checkBox.setStatusTip(_translate("MainWindow", "Enable CTLD logistics crates for building ground units and air defenses."))
self.logistics_crates_checkBox.setText(_translate("MainWindow", "Logistics Crates"))
self.logistics_crates_checkBox.setStatusTip(_translate("MainWindow", "Enable CTLD logistics crates for building ground units and air defenses. Pickup logistics containers to create new logistics sites."))
self.logistics_crates_checkBox.setText(_translate("MainWindow", "Logistics"))
self.awacs_checkBox.setText(_translate("MainWindow", "Friendly AWACS"))
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.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"))
self.scenario_label_5.setText(_translate("MainWindow", "Groups Per Zone"))
self.forces_hint_label_2.setText(_translate("MainWindow", "Forces templates are .miz files in \'Generator/Forces\'"))
self.label.setText(_translate("MainWindow", "Infantry Groups per zone:"))
@ -358,6 +396,16 @@ class Ui_MainWindow(object):
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.scenario_label_9.setText(_translate("MainWindow", "Zone FARP Conditions:"))
self.inf_spawn_voiceovers_checkBox.setStatusTip(_translate("MainWindow", "Friendly/enemy APCs will drop infantry when reaching a new conflict zone."))
self.inf_spawn_voiceovers_checkBox.setText(_translate("MainWindow", "Voiceovers on Infantry Spawn"))
self.farp_never.setStatusTip(_translate("MainWindow", "Never spawn FARPs in defeated conflict zones."))
self.farp_never.setText(_translate("MainWindow", "Never"))
self.farp_gunits.setStatusTip(_translate("MainWindow", "Only spawn FARPs in defeated conflict zones if we have sufficient ground units remaining."))
self.farp_gunits.setText(_translate("MainWindow", "20% Ground Units Remaining"))
self.farp_always.setStatusTip(_translate("MainWindow", "Always spawn a FARP in defeated conflict zones."))
self.farp_always.setText(_translate("MainWindow", "Always"))
self.version_label.setText(_translate("MainWindow", "Version string"))
self.action_generateMission.setText(_translate("MainWindow", "_generateMission"))
self.action_scenarioSelected.setText(_translate("MainWindow", "_scenarioSelected"))
self.action_blueforcesSelected.setText(_translate("MainWindow", "_blueforcesSelected"))

View File

@ -183,8 +183,8 @@ p, li { white-space: pre-wrap; }
<widget class="QLabel" name="background_label">
<property name="geometry">
<rect>
<x>-30</x>
<y>490</y>
<x>-40</x>
<y>440</y>
<width>801</width>
<height>371</height>
</rect>
@ -255,7 +255,7 @@ p, li { white-space: pre-wrap; }
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>8</number>
</property>
<property name="value">
<number>3</number>
@ -282,7 +282,7 @@ p, li { white-space: pre-wrap; }
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>8</number>
</property>
<property name="value">
<number>2</number>
@ -312,8 +312,8 @@ p, li { white-space: pre-wrap; }
<widget class="QCheckBox" name="game_status_checkBox">
<property name="geometry">
<rect>
<x>1000</x>
<y>590</y>
<x>810</x>
<y>790</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>1000</x>
<y>650</y>
<x>810</x>
<y>820</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>970</x>
<y>390</y>
<x>920</x>
<y>320</y>
<width>251</width>
<height>31</height>
</rect>
@ -375,17 +375,20 @@ p, li { white-space: pre-wrap; }
</font>
</property>
<property name="statusTip">
<string>Enable CTLD logistics crates for building ground units and air defenses.</string>
<string>Enable CTLD logistics crates for building ground units and air defenses. Pickup logistics containers to create new logistics sites.</string>
</property>
<property name="text">
<string>Logistics Crates</string>
<string>Logistics</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QCheckBox" name="awacs_checkBox">
<property name="geometry">
<rect>
<x>970</x>
<y>420</y>
<x>920</x>
<y>350</y>
<width>251</width>
<height>31</height>
</rect>
@ -408,8 +411,8 @@ p, li { white-space: pre-wrap; }
<widget class="QCheckBox" name="tankers_checkBox">
<property name="geometry">
<rect>
<x>970</x>
<y>450</y>
<x>920</x>
<y>380</y>
<width>251</width>
<height>31</height>
</rect>
@ -429,7 +432,7 @@ p, li { white-space: pre-wrap; }
<widget class="QCheckBox" name="apcs_spawn_checkBox">
<property name="geometry">
<rect>
<x>500</x>
<x>470</x>
<y>400</y>
<width>251</width>
<height>31</height>
@ -450,7 +453,7 @@ p, li { white-space: pre-wrap; }
<widget class="QSpinBox" name="inf_spawn_spinBox">
<property name="geometry">
<rect>
<x>710</x>
<x>680</x>
<y>360</y>
<width>71</width>
<height>31</height>
@ -468,36 +471,12 @@ p, li { white-space: pre-wrap; }
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>20</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
<widget class="QCheckBox" name="smoke_checkBox">
<property name="geometry">
<rect>
<x>1000</x>
<y>620</y>
<width>191</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="statusTip">
<string>Not yet implemented.</string>
</property>
<property name="text">
<string>Smoke Active Zone</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="scenario_label_5">
<property name="geometry">
<rect>
@ -538,7 +517,7 @@ p, li { white-space: pre-wrap; }
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>500</x>
<x>470</x>
<y>360</y>
<width>191</width>
<height>31</height>
@ -557,7 +536,7 @@ p, li { white-space: pre-wrap; }
<property name="geometry">
<rect>
<x>870</x>
<y>700</y>
<y>640</y>
<width>291</width>
<height>31</height>
</rect>
@ -570,7 +549,7 @@ p, li { white-space: pre-wrap; }
<property name="geometry">
<rect>
<x>750</x>
<y>700</y>
<y>640</y>
<width>111</width>
<height>31</height>
</rect>
@ -587,7 +566,7 @@ p, li { white-space: pre-wrap; }
<widget class="QLabel" name="scenario_label_6">
<property name="geometry">
<rect>
<x>500</x>
<x>470</x>
<y>320</y>
<width>141</width>
<height>31</height>
@ -605,8 +584,8 @@ p, li { white-space: pre-wrap; }
<widget class="QCheckBox" name="force_offroad_checkBox">
<property name="geometry">
<rect>
<x>1000</x>
<y>560</y>
<x>810</x>
<y>760</y>
<width>191</width>
<height>16</height>
</rect>
@ -668,7 +647,7 @@ p, li { white-space: pre-wrap; }
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>8</number>
</property>
<property name="value">
<number>2</number>
@ -679,7 +658,7 @@ p, li { white-space: pre-wrap; }
<rect>
<x>140</x>
<y>330</y>
<width>231</width>
<width>211</width>
<height>31</height>
</rect>
</property>
@ -697,7 +676,7 @@ p, li { white-space: pre-wrap; }
<rect>
<x>140</x>
<y>370</y>
<width>231</width>
<width>201</width>
<height>31</height>
</rect>
</property>
@ -731,7 +710,7 @@ p, li { white-space: pre-wrap; }
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>8</number>
</property>
<property name="value">
<number>1</number>
@ -740,8 +719,8 @@ p, li { white-space: pre-wrap; }
<widget class="QCheckBox" name="zone_sams_checkBox">
<property name="geometry">
<rect>
<x>970</x>
<y>480</y>
<x>920</x>
<y>410</y>
<width>201</width>
<height>31</height>
</rect>
@ -758,6 +737,139 @@ p, li { white-space: pre-wrap; }
<string>Inactive Zone SAMs</string>
</property>
</widget>
<widget class="QLabel" name="scenario_label_9">
<property name="geometry">
<rect>
<x>740</x>
<y>490</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Zone FARP Conditions:</string>
</property>
</widget>
<widget class="QCheckBox" name="inf_spawn_voiceovers_checkBox">
<property name="geometry">
<rect>
<x>470</x>
<y>430</y>
<width>251</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="statusTip">
<string>Friendly/enemy APCs will drop infantry when reaching a new conflict zone.</string>
</property>
<property name="text">
<string>Voiceovers on Infantry Spawn</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QRadioButton" name="farp_never">
<property name="geometry">
<rect>
<x>950</x>
<y>500</y>
<width>95</width>
<height>20</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="statusTip">
<string>Never spawn FARPs in defeated conflict zones.</string>
</property>
<property name="text">
<string>Never</string>
</property>
<attribute name="buttonGroup">
<string notr="true">farp_buttonGroup</string>
</attribute>
</widget>
<widget class="QRadioButton" name="farp_gunits">
<property name="geometry">
<rect>
<x>950</x>
<y>530</y>
<width>221</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="statusTip">
<string>Only spawn FARPs in defeated conflict zones if we have sufficient ground units remaining.</string>
</property>
<property name="text">
<string>20% Ground Units Remaining</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">farp_buttonGroup</string>
</attribute>
</widget>
<widget class="QRadioButton" name="farp_always">
<property name="geometry">
<rect>
<x>950</x>
<y>560</y>
<width>221</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="statusTip">
<string>Always spawn a FARP in defeated conflict zones.</string>
</property>
<property name="text">
<string>Always</string>
</property>
<attribute name="buttonGroup">
<string notr="true">farp_buttonGroup</string>
</attribute>
</widget>
<widget class="QLabel" name="version_label">
<property name="geometry">
<rect>
<x>920</x>
<y>840</y>
<width>241</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Version string</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<zorder>background_label</zorder>
<zorder>scenario_comboBox</zorder>
<zorder>scenario_label</zorder>
@ -779,7 +891,6 @@ p, li { white-space: pre-wrap; }
<zorder>tankers_checkBox</zorder>
<zorder>apcs_spawn_checkBox</zorder>
<zorder>inf_spawn_spinBox</zorder>
<zorder>smoke_checkBox</zorder>
<zorder>scenario_label_5</zorder>
<zorder>forces_hint_label_2</zorder>
<zorder>label</zorder>
@ -793,6 +904,12 @@ p, li { white-space: pre-wrap; }
<zorder>scenario_label_8</zorder>
<zorder>e_attack_planes_spinBox</zorder>
<zorder>zone_sams_checkBox</zorder>
<zorder>scenario_label_9</zorder>
<zorder>inf_spawn_voiceovers_checkBox</zorder>
<zorder>farp_never</zorder>
<zorder>farp_gunits</zorder>
<zorder>farp_always</zorder>
<zorder>version_label</zorder>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
@ -865,4 +982,7 @@ p, li { white-space: pre-wrap; }
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="farp_buttonGroup"/>
</buttongroups>
</ui>

116
Generator/RotorOpsGroups.py Normal file
View File

@ -0,0 +1,116 @@
from dcs.countries import Russia, USA
import dcs.unit as unit
from dcs.mission import Mission
import dcs.mapping as mapping
import dcs.ships
import dcs.vehicles
import dcs.statics
import dcs.unit
import random
class VehicleTemplate:
class USA:
@staticmethod
def invisible_farp(mission, country, position, heading, name, late_activation):
farp = mission.farp(country, name, position, hidden=False, dead=False, farp_type=dcs.unit.InvisibleFARP)
vg = mission.vehicle_group_platoon(
country,
name,
[
dcs.vehicles.Unarmed.M_818,
dcs.vehicles.AirDefence.Vulcan,
dcs.vehicles.Unarmed.Ural_375
],
position.point_from_heading(45, 7),
heading=random.randint(0, 359),
formation=dcs.unitgroup.VehicleGroup.Formation.Star,
)
vg.late_activation = late_activation
return vg
@staticmethod
def logistics_site(mission, country, position, heading, prefix=""):
farp = mission.farp(country, "Logistics FARP", position, hidden=False, dead=False, farp_type=dcs.unit.InvisibleFARP)
sg = mission.static_group(
country,
prefix + " Logistics",
dcs.statics.Fortification.TV_tower,
position.point_from_heading(heading, 80),
heading
)
dist_from_center = 30
for i in range(1,4):
u = mission.static("logistic" + str(i), dcs.statics.Cargo.Iso_container_small)
u.position = position.point_from_heading(heading + 90, dist_from_center + (i * 15))
u.heading = 10
sg.add_unit(u)
for i in range(5,8):
u = mission.static("logistic" + str(i), dcs.statics.Cargo.Iso_container_small)
u.position = position.point_from_heading(heading + 270, dist_from_center + (i * 15))
u.heading = 10
sg.add_unit(u)
a_pos = position.point_from_heading(heading + 180, dist_from_center)
u = mission.static("Ammo Dump", dcs.statics.Fortification.FARP_Ammo_Dump_Coating)
u.position = a_pos.point_from_heading(heading + 90, 1)
u.heading = heading
sg.add_unit(u)
u = mission.static("FARP Tent", dcs.statics.Fortification.FARP_Tent)
u.position = a_pos.point_from_heading(heading + 90, dist_from_center + 20)
u.heading = heading
sg.add_unit(u)
u = mission.static("Fuel Depot", dcs.statics.Fortification.FARP_Fuel_Depot)
u.position = a_pos.point_from_heading(heading + 90, dist_from_center + 40)
u.heading = heading
sg.add_unit(u)
return sg
@staticmethod
def sa6_site(mission, country, position, heading, prefix="", skill=unit.Skill.Average):
vg = mission.vehicle_group(
country,
prefix + "SA6 site",
dcs.vehicles.AirDefence.Kub_1S91_str,
position,
heading
)
u = mission.vehicle("Launcher 1", dcs.vehicles.AirDefence.Kub_2P25_ln)
u.position = position.point_from_heading(heading + 140, 30)
u.heading = heading
vg.add_unit(u)
u = mission.vehicle("Launcher 2", dcs.vehicles.AirDefence.Kub_2P25_ln)
u.position = position.point_from_heading(heading + 210, 30)
u.heading = heading
vg.add_unit(u)
u = mission.vehicle("Rearm Truck", dcs.vehicles.Unarmed.Ural_375)
u.position = position.point_from_heading(heading + 0, 40)
u.heading = heading
vg.add_unit(u)
for u in vg.units:
u.skill = skill
return vg

View File

@ -3,6 +3,8 @@ from tokenize import String
import dcs
import os
import random
import RotorOpsGroups
import RotorOpsUnits
import time
@ -119,9 +121,6 @@ class RotorOpsMission:
elif zone.name.rfind("SPAWN") >= 0:
self.addZone(self.spawn_zones, self.RotorOpsZone(zone.name, None, zone.position, zone.radius))
#add files and triggers necessary for RotorOps.lua script
self.addResources(self.sound_directory, self.script_directory)
self.scriptTriggerSetup(options)
blue_zones = self.staging_zones
red_zones = self.conflict_zones
@ -137,16 +136,21 @@ class RotorOpsMission:
self.m.terrain.airports[airport_name].set_blue()
#Add red ground units
#Populate Red zones with ground units
for zone_name in red_zones:
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:
#Add blue FARPS
if options["zone_farps"] != "farp_never" and not options["defending"]:
RotorOpsGroups.VehicleTemplate.USA.invisible_farp(self.m, self.m.country('USA'),
red_zones[zone_name].position,
180, zone_name + " FARP", late_activation=True)
if options["zone_protect_sams"]:
self.m.vehicle_group(
self.m.country('Russia'),
zone_name + " Protection SAM NOAI",
"Static " + zone_name + " Protection SAM",
random.choice(RotorOpsUnits.e_zone_sams),
red_zones[zone_name].position,
heading=random.randint(0, 359),
@ -154,17 +158,28 @@ class RotorOpsMission:
formation=dcs.unitgroup.VehicleGroup.Formation.Star
)
#Add blue ground units
#Populate Blue zones with 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(
#add logistics sites
if options["crates"] and zone_name in self.staging_zones:
RotorOpsGroups.VehicleTemplate.USA.logistics_site(self.m, self.m.country('USA'),
blue_zones[zone_name].position,
180, zone_name)
if options["zone_protect_sams"] and options["defending"]:
vg = self.m.vehicle_group(
self.m.country('USA'),
zone_name + " Protection SAM NOAI",
"Static " + zone_name + " Protection SAM",
random.choice(RotorOpsUnits.e_zone_sams),
blue_zones[zone_name].position,
heading=random.randint(0, 359),
@ -172,6 +187,8 @@ class RotorOpsMission:
formation=dcs.unitgroup.VehicleGroup.Formation.Star
)
#Add player slots
if options["slots"] == "Multiple Slots":
self.addMultiplayerHelos()
@ -187,6 +204,10 @@ class RotorOpsMission:
self.m.map.position = self.m.terrain.airports[self.getCoalitionAirports("blue")[0]].position
self.m.map.zoom = 100000
#add files and triggers necessary for RotorOps.lua script
self.addResources(self.sound_directory, self.script_directory)
self.scriptTriggerSetup(options)
#Save the mission file
print(self.m.triggers.zones())
os.chdir(self.output_dir)
@ -414,7 +435,7 @@ class RotorOpsMission:
helo,
airport=enemy_airport,
maintask=dcs.task.CAS,
start_type=dcs.mission.StartType.Warm,
start_type=dcs.mission.StartType.Cold,
group_size=2)
zone_attack(afg, helo)
@ -424,7 +445,7 @@ class RotorOpsMission:
russia, "Enemy Attack Planes", plane["type"],
airport=enemy_airport,
maintask=dcs.task.CAS,
start_type=dcs.mission.StartType.Warm,
start_type=dcs.mission.StartType.Cold,
group_size=2)
zone_attack(afg, plane)
@ -450,6 +471,7 @@ class RotorOpsMission:
"RotorOps.force_offroad = " + lb("force_offroad") + "\n\n" +
"RotorOps.voice_overs = " + lb("voiceovers") + "\n\n" +
"RotorOps.zone_status_display = " + lb("game_display") + "\n\n" +
"RotorOps.inf_spawn_messages = " + lb("inf_spawn_msgs") + "\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(trig)
@ -473,23 +495,50 @@ class RotorOpsMission:
trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.startConflict(100)")))
self.m.triggerrules.triggers.append(trig)
#Add all zone-based triggers
#Add generic zone-based triggers
for index, zone_name in enumerate(self.conflict_zones):
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 protection SAMs
if options["zone_protect_sams"]:
for index, zone_name in enumerate(self.conflict_zones):
z_sams_trig = dcs.triggers.TriggerOnce(comment="Deactivate " + zone_name + " SAMs")
z_sams_trig.actions.append(dcs.action.DoScript(dcs.action.String("Group.destroy(Group.getByName('" + zone_name + " Protection SAM'))")))
self.m.triggerrules.triggers.append(z_sams_trig)
#Zone FARPS always
if options["zone_farps"] == "farp_always" and not options["defending"] and index > 0:
for index, zone_name in enumerate(self.conflict_zones):
if index > 0:
previous_zone = list(self.conflict_zones)[index - 1]
if not self.m.country("USA").find_group(previous_zone + " FARP"):
continue
z_farps_trig = dcs.triggers.TriggerOnce(comment="Activate " + previous_zone + " FARP")
z_farps_trig.rules.append(dcs.condition.FlagEquals(game_flag, index + 1))
z_farps_trig.actions.append(dcs.action.ActivateGroup(self.m.country("USA").find_group(previous_zone + " FARP").id))
self.m.triggerrules.triggers.append(z_farps_trig)
#Zone FARPS conditional on staged units remaining
if options["zone_farps"] == "farp_gunits":
for index, zone_name in enumerate(self.conflict_zones):
if index > 0:
previous_zone = list(self.conflict_zones)[index - 1]
if not self.m.country("USA").find_group(previous_zone + " FARP"):
continue
z_farps_trig = dcs.triggers.TriggerOnce(comment= "Activate " + previous_zone + " FARP")
z_farps_trig.rules.append(dcs.condition.FlagEquals(game_flag, index + 1))
z_farps_trig.rules.append(dcs.condition.FlagIsMore(111, 20))
z_farps_trig.actions.append(dcs.action.DoScript(dcs.action.String("--The 100 flag indicates which zone is active. The 111 flag value is the percentage of staged units remaining")))
z_farps_trig.actions.append(
dcs.action.ActivateGroup(self.m.country("USA").find_group(previous_zone + " FARP").id))
self.m.triggerrules.triggers.append(z_farps_trig)
#Add attack helos triggers
for index in range(options["e_attack_helos"]):
random_zone_obj = random.choice(list(self.conflict_zones.items()))

View File

@ -21,6 +21,7 @@ Optional:
Tips:
-Position the center of conflict zones over an open area, as this position may be used to spawn units.
-Position the center of staging zones over an open area of at least 1000 x 1000ft to provide space for logistics 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.

Binary file not shown.

View File

@ -1,6 +1,6 @@
RotorOps = {}
RotorOps.version = "1.2.4"
local debug = false
RotorOps.version = "1.2.5"
local debug = true
---[[ROTOROPS OPTIONS]]---
@ -20,13 +20,14 @@ RotorOps.inf_spawns_avail = 0 --this is the number of infantry group spawn event
RotorOps.inf_spawn_chance = 25 -- 0-100 the chance of spawning infantry in an active zone spawn zone, per 'assessUnitsInZone' loop (10 seconds)
RotorOps.inf_spawn_trigger_percent = 70 --infantry has a chance of spawning if the percentage of defenders remaining in zone is less than this value
RotorOps.inf_spawns_per_zone = 3 --number of infantry groups to spawn per zone
RotorOps.inf_spawn_messages = true --voiceovers and messages for infantry spawns
--RotorOps settings that are safe to change only before calling setupConflict()
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
RotorOps.exclude_ai_group_name = "Static" --include this somewhere in a group name to exclude the group from being tasked in the active zone
---[[END OF OPTIONS]]---
@ -49,6 +50,7 @@ RotorOps.ai_defending_vehicle_groups = {}
RotorOps.ai_attacking_vehicle_groups = {}
RotorOps.ai_tasks = {}
RotorOps.defending = false
RotorOps.staged_units_flag = 111
trigger.action.outText("ROTOR OPS STARTED: "..RotorOps.version, 5)
env.info("ROTOR OPS STARTED: "..RotorOps.version)
@ -58,10 +60,14 @@ RotorOps.eventHandler = {}
local commandDB = {}
local game_message_buffer = {}
local active_zone_initial_defenders
local initial_stage_units
local apcs = {} --table to keep track of infantry vehicles
local low_units_message_fired = false
local inf_spawn_zones = {}
local cooldown = {
["attack_helo_msg"] = 0,
["attack_plane_msg"] = 0,
}
RotorOps.gameMsgs = {
@ -144,6 +150,20 @@ RotorOps.gameMsgs = {
attack_planes = {
{'ENEMY ATTACK PLANES INBOUND!', 'enemy_attack_planes.ogg'},
},
attack_helos_prep = {
{'ENEMY ATTACK HELICOPTERS PREPARING FOR TAKEOFF!', 'e_attack_helicopters_preparing.ogg'},
},
attack_planes_prep = {
{'ENEMY ATTACK PLANES PREPARING FOR TAKEOFF!', 'e_attack_planes_preparing.ogg'},
},
infantry_spawned = {
{'ENEMY CONTACTS IN THE OPEN!', 'e_infantry_spawn1.ogg'},
{'ENEMY TROOPS LEAVING COVER!', 'e_infantry_spawn2.ogg'},
{'VISUAL ON ENEMY INFANTRY!', 'e_infantry_spawn3.ogg'},
{'ENEMY CONTACTS IN THE ACTIVE!', 'e_infantry_spawn4.ogg'},
{'ENEMY TROOPS IN THE ACTIVE!', 'e_infantry_spawn5.ogg'},
{'VISUAL ON ENEMY TROOPS!', 'e_infantry_spawn6.ogg'},
},
}
@ -154,15 +174,53 @@ local sound_effects = {
["troop_dropoff"] = {'troops_unload_thanks.ogg', 'troops_unload_everybody_off.ogg', 'troops_unload_get_off.ogg', 'troops_unload_here_we_go.ogg', 'troops_unload_moving_out.ogg',},
}
function RotorOps.getTime()
return timer.getAbsTime() - timer.getTime0() --time since mission started
end
function RotorOps.eventHandler:onEvent(event)
if (world.event.S_EVENT_ENGINE_STARTUP == event.id) then --play some sound files when a player starts engines
local initaitor = event.initiator:getGroup():getID()
if RotorOps.defending then
trigger.action.outSoundForGroup(initaitor , RotorOps.gameMsgs.enemy_pushing[RotorOps.active_zone_index + 1][2])
else
trigger.action.outSoundForGroup(initaitor , RotorOps.gameMsgs.push[RotorOps.active_zone_index + 1][2])
---ENGINE STARTUP EVENTS
if (world.event.S_EVENT_ENGINE_STARTUP == event.id) then --play some sound files when a player starts engines
local initiator = event.initiator:getGroup():getID()
if #event.initiator:getGroup():getUnits() == 1 then --if there are no other units in the player flight group (preventing duplicated messages for ai wingman flights)
if RotorOps.defending then
trigger.action.outSoundForGroup(initiator , RotorOps.gameMsgs.enemy_pushing[RotorOps.active_zone_index + 1][2])
else
trigger.action.outSoundForGroup(initiator , RotorOps.gameMsgs.push[RotorOps.active_zone_index + 1][2])
end
end
end
---TAKEOFF EVENTS
if (world.event.S_EVENT_TAKEOFF == event.id) then
local initiator_name = event.initiator:getGroup():getName()
if (initiator_name == "Enemy Attack Helicopters") then
--we use flights of two aircraft which triggers two events, but we only want to use one event so we use a cooldown timer
if ((RotorOps.getTime() - cooldown["attack_helo_msg"]) > 90) then
RotorOps.gameMsg(RotorOps.gameMsgs.attack_helos)
cooldown["attack_helo_msg"] = RotorOps.getTime()
else
env.warning("RotorOps attack helo message skipped")
end
end
if initiator_name == "Enemy Attack Planes" then
if ((RotorOps.getTime() - cooldown["attack_plane_msg"]) > 90) then
RotorOps.gameMsg(RotorOps.gameMsgs.attack_planes)
cooldown["attack_plane_msg"] = RotorOps.getTime()
else
env.warning("RotorOps attack plane message skipped")
end
end
end
end
@ -507,7 +565,12 @@ function RotorOps.chargeEnemy(vars)
if vars.zone then ---mist getUnitsInZones method
local units_in_zone = mist.getUnitsInZones(mist.makeUnitTable({'[red][vehicle]'}), {vars.zone}, "spherical")
local units_in_zone
if enemy_coal == 1 then
units_in_zone = mist.getUnitsInZones(mist.makeUnitTable({'[red][vehicle]'}), {vars.zone}, "spherical")
elseif enemy_coal == 2 then
units_in_zone = mist.getUnitsInZones(mist.makeUnitTable({'[blue][vehicle]'}), {vars.zone}, "spherical")
end
local closest_dist = 10000
local closest_unit
for index, unit in pairs(units_in_zone) do
@ -872,6 +935,19 @@ function RotorOps.assessUnitsInZone(var)
end
end
--update staged units remaining flag
local staged_units_remaining = {}
for index, unit in pairs(RotorOps.staged_units) do
if unit:isExist() then
staged_units_remaining[#staged_units_remaining + 1] = unit
end
end
local percent_staged_remain = 0
percent_staged_remain = math.floor((#staged_units_remaining / #RotorOps.staged_units) * 100)
trigger.action.setUserFlag(RotorOps.staged_units_flag, percent_staged_remain)
debugMsg("Staged units remaining: "..percent_staged_remain.."%")
--is the game finished?
if all_zones_clear then
if RotorOps.defending == true then
@ -957,7 +1033,7 @@ function RotorOps.assessUnitsInZone(var)
else
ctld.spawnGroupAtTrigger("red", 5, zone, 1000)
end
RotorOps.gameMsg(RotorOps.gameMsgs.infantry_spawned, math.random(1, #RotorOps.gameMsgs.infantry_spawned))
RotorOps.inf_spawns_avail = RotorOps.inf_spawns_avail - 1
env.info("ROTOR OPS: Spawned infantry. "..RotorOps.inf_spawns_avail.." spawns remaining in "..zone)
end
@ -1126,6 +1202,11 @@ function RotorOps.setupCTLD()
ctld.numberOfTroops = 24 --max loading size
ctld.maximumSearchDistance = 4000 -- max distance for troops to search for enemy
ctld.maximumMoveDistance = 0 -- max distance for troops to move from drop point if no enemy is nearby
ctld.maximumDistanceLogistic = 300
ctld.minimumHoverHeight = 5.0 -- Lowest allowable height for crate hover
ctld.maximumHoverHeight = 15.0 -- Highest allowable height for crate hover
ctld.maxDistanceFromCrate = 7 -- Maximum distance from from crate for hover
ctld.hoverTime = 5 -- Time to hold hover above a crate for loading in seconds
ctld.unitLoadLimits = {
-- Remove the -- below to turn on options
@ -1269,12 +1350,12 @@ end
function RotorOps.spawnAttackHelos()
RotorOps.triggerSpawn("Enemy Attack Helicopters", RotorOps.gameMsgs.attack_helos)
RotorOps.triggerSpawn("Enemy Attack Helicopters", RotorOps.gameMsgs.attack_helos_prep)
end
function RotorOps.spawnAttackPlanes()
RotorOps.triggerSpawn("Enemy Attack Planes", RotorOps.gameMsgs.attack_planes)
RotorOps.triggerSpawn("Enemy Attack Planes", RotorOps.gameMsgs.attack_planes_prep)
end

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.