mirror of
https://github.com/spencershepard/RotorOps.git
synced 2025-11-10 15:45:30 +00:00
Merge pull request #25 from spencershepard/feature/imports
Feature/imports
This commit is contained in:
commit
93f09d1e49
BIN
Generator/Forces/blue/BLUE Greece Armor (Mr Nobody).miz
Normal file
BIN
Generator/Forces/blue/BLUE Greece Armor (Mr Nobody).miz
Normal file
Binary file not shown.
BIN
Generator/Forces/blue/BLUE Iran Armor (Mr Nobody).miz
Normal file
BIN
Generator/Forces/blue/BLUE Iran Armor (Mr Nobody).miz
Normal file
Binary file not shown.
BIN
Generator/Forces/blue/BLUE Turkey Armor (Mr Nobody).miz
Normal file
BIN
Generator/Forces/blue/BLUE Turkey Armor (Mr Nobody).miz
Normal file
Binary file not shown.
BIN
Generator/Forces/blue/BLUE UK Armor (Mr Nobody).miz
Normal file
BIN
Generator/Forces/blue/BLUE UK Armor (Mr Nobody).miz
Normal file
Binary file not shown.
Binary file not shown.
BIN
Generator/Forces/red/RED Greece Armor (Mr Nobody).miz
Normal file
BIN
Generator/Forces/red/RED Greece Armor (Mr Nobody).miz
Normal file
Binary file not shown.
BIN
Generator/Forces/red/RED Iran Armor & Infantry (Mr Nobody).miz
Normal file
BIN
Generator/Forces/red/RED Iran Armor & Infantry (Mr Nobody).miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FARP_DEFAULT_ZONE.miz
Normal file
BIN
Generator/Imports/FARP_DEFAULT_ZONE.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FARP_MINIMUM_ROADSIDE_INVULNERABLE.miz
Normal file
BIN
Generator/Imports/FARP_MINIMUM_ROADSIDE_INVULNERABLE.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FARP_MINIMUM_ROADSIDE_STATICS.miz
Normal file
BIN
Generator/Imports/FARP_MINIMUM_ROADSIDE_STATICS.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FARP_MOBILE_ROADSIDE_INVULNERABLE.miz
Normal file
BIN
Generator/Imports/FARP_MOBILE_ROADSIDE_INVULNERABLE.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FARP_MOBILE_ROADSIDE_STATICS.miz
Normal file
BIN
Generator/Imports/FARP_MOBILE_ROADSIDE_STATICS.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FOB_16_SPWN_WIDE.miz
Normal file
BIN
Generator/Imports/FOB_16_SPWN_WIDE.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/FOB_8_SPWN.miz
Normal file
BIN
Generator/Imports/FOB_8_SPWN.miz
Normal file
Binary file not shown.
17
Generator/Imports/How to use imports.txt
Normal file
17
Generator/Imports/How to use imports.txt
Normal file
@ -0,0 +1,17 @@
|
||||
You can put .miz files in this folder to be copied into the generated mission at marker points. This feature is currently very 'alpha' and may produce errors. Currently, this doesn't work for ship groups or plane groups.
|
||||
|
||||
1) Make an empty mission on Cauacasus.
|
||||
|
||||
2) Place units/objects on the map.
|
||||
|
||||
3) Make one unit group name: 'ANCHOR' This will represent the point of insertion into the target mission.
|
||||
|
||||
4) In a Scenario template, place a static object (flag, etc) and call it "IMPORT-[filename of .miz created in first step]" Country should be CJTF Red, CJTF Blue, or UN Peacekeepers.
|
||||
|
||||
5) Change the unit name of the object created in the previous step. This unit name might be used for spawn names, so you should call the unit name something like "North Base" so players know where they'll be spawning when choosing a slot.
|
||||
|
||||
|
||||
Tips:
|
||||
-You can change the heading of the imported group by changing the heading of the insertion object.
|
||||
-For multiple imports of the same template, the import object group name should end with '-01' or '-whatever'.
|
||||
|
||||
BIN
Generator/Imports/MARKET_PLACE.miz
Normal file
BIN
Generator/Imports/MARKET_PLACE.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/STAGING_LOGISTIC_HUB.miz
Normal file
BIN
Generator/Imports/STAGING_LOGISTIC_HUB.miz
Normal file
Binary file not shown.
BIN
Generator/Imports/VILLA_GRIMM.miz
Normal file
BIN
Generator/Imports/VILLA_GRIMM.miz
Normal file
Binary file not shown.
@ -6,6 +6,7 @@ import RotorOpsMission as ROps
|
||||
import RotorOpsUtils
|
||||
import RotorOpsUnits
|
||||
import logging
|
||||
import json
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QDialog, QMainWindow, QMessageBox
|
||||
@ -28,7 +29,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
||||
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
||||
msg = QMessageBox()
|
||||
msg.setWindowTitle("Uncaught exception")
|
||||
msg.setText("Oops, there was a problem. Please check the log file or post it in the RotorOps discord where some helpful people will have a look.")
|
||||
msg.setText("Oops, there was a problem. Please check the log file for more details or post it in the RotorOps discord where some helpful people will have a look. \n\n" + str(exc_value))
|
||||
x = msg.exec_()
|
||||
|
||||
|
||||
@ -36,7 +37,7 @@ sys.excepthook = handle_exception
|
||||
|
||||
|
||||
maj_version = 0
|
||||
minor_version = 4
|
||||
minor_version = 6
|
||||
version_string = str(maj_version) + "." + str(minor_version)
|
||||
scenarios = []
|
||||
red_forces_files = []
|
||||
@ -109,6 +110,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.slot_template_comboBox.addItem("Multiple Slots")
|
||||
for type in RotorOpsUnits.client_helos:
|
||||
self.slot_template_comboBox.addItem(type.id)
|
||||
self.slot_template_comboBox.addItem("None")
|
||||
|
||||
def defensiveModeChanged(self):
|
||||
if self.defense_checkBox.isChecked():
|
||||
@ -118,6 +120,49 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.red_forces_label.setText(defenders_text)
|
||||
self.blue_forces_label.setText(attackers_text)
|
||||
|
||||
self.applyScenarioConfig()
|
||||
|
||||
def loadScenarioConfig(self, filename):
|
||||
try:
|
||||
j = open(filename)
|
||||
config = json.load(j)
|
||||
j.close()
|
||||
return config
|
||||
except:
|
||||
return None
|
||||
|
||||
def lockedSlot(self):
|
||||
return self.slot_template_comboBox.findText("Locked to Scenario")
|
||||
|
||||
def clearScenarioConfig(self):
|
||||
# reset default states
|
||||
self.defense_checkBox.setEnabled(True)
|
||||
if self.lockedSlot():
|
||||
self.slot_template_comboBox.removeItem(self.lockedSlot())
|
||||
|
||||
self.slot_template_comboBox.setEnabled(True)
|
||||
self.slot_template_comboBox.setCurrentIndex(0)
|
||||
|
||||
def applyScenarioConfig(self):
|
||||
|
||||
if not self.config:
|
||||
return
|
||||
|
||||
if self.config['defense']['allowed'] == False:
|
||||
self.defense_checkBox.setChecked(False)
|
||||
self.defense_checkBox.setEnabled(False)
|
||||
elif self.config['offense']['allowed'] == False:
|
||||
self.defense_checkBox.setChecked(True)
|
||||
self.defense_checkBox.setEnabled(False)
|
||||
|
||||
if self.config['defense']['player_spawn'] == "fixed":
|
||||
self.slot_template_comboBox.addItem("Locked to Scenario")
|
||||
self.slot_template_comboBox.setCurrentIndex(self.lockedSlot())
|
||||
self.slot_template_comboBox.setEnabled(False)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def scenarioChanged(self):
|
||||
os.chdir(self.m.scenarios_dir)
|
||||
@ -136,6 +181,14 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
friendly_airports = True
|
||||
enemy_airports = True
|
||||
|
||||
self.clearScenarioConfig()
|
||||
config_filename = filename.removesuffix(".miz") + ".json"
|
||||
self.config = self.loadScenarioConfig(config_filename)
|
||||
if self.config:
|
||||
self.applyScenarioConfig()
|
||||
self.m.setConfig(self.config)
|
||||
|
||||
|
||||
for zone in zones:
|
||||
if zone.name == "STAGING":
|
||||
staging_zones += 1
|
||||
@ -174,7 +227,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
+ "\n== BRIEFING ==\n\n"
|
||||
+ source_mission.description_text()
|
||||
)
|
||||
#self.description_textBrowser.setText("File error occured.")
|
||||
|
||||
|
||||
def generateMissionAction(self):
|
||||
|
||||
@ -597,6 +597,9 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="defense_checkBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>60</x>
|
||||
@ -613,6 +616,9 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="text">
|
||||
<string>Defensive Mode</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="e_attack_helos_spinBox">
|
||||
<property name="geometry">
|
||||
|
||||
157
Generator/RotorOpsConflict.py
Normal file
157
Generator/RotorOpsConflict.py
Normal file
@ -0,0 +1,157 @@
|
||||
import dcs
|
||||
import random
|
||||
|
||||
jtf_red = "Combined Joint Task Forces Red"
|
||||
jtf_blue = "Combined Joint Task Forces Blue"
|
||||
|
||||
|
||||
def triggerSetup(rops, options):
|
||||
# get the boolean value from ui option and convert to lua string
|
||||
def lb(var):
|
||||
return str(options[var]).lower()
|
||||
|
||||
game_flag = 100
|
||||
# Add the first trigger
|
||||
trig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Scripts")
|
||||
trig.rules.append(dcs.condition.TimeAfter(1))
|
||||
trig.actions.append(dcs.action.DoScriptFile(rops.scripts["mist_4_4_90.lua"]))
|
||||
trig.actions.append(dcs.action.DoScriptFile(rops.scripts["Splash_Damage_2_0.lua"]))
|
||||
trig.actions.append(dcs.action.DoScriptFile(rops.scripts["CTLD.lua"]))
|
||||
trig.actions.append(dcs.action.DoScriptFile(rops.scripts["RotorOps.lua"]))
|
||||
script = ""
|
||||
script = ("--OPTIONS HERE!\n\n" +
|
||||
"RotorOps.CTLD_crates = " + lb("crates") + "\n\n" +
|
||||
"RotorOps.CTLD_sound_effects = true\n\n" +
|
||||
"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")
|
||||
if not options["smoke_pickup_zones"]:
|
||||
script = script + 'RotorOps.pickup_zone_smoke = "none"\n\n'
|
||||
trig.actions.append(dcs.action.DoScript(dcs.action.String((script))))
|
||||
rops.m.triggerrules.triggers.append(trig)
|
||||
|
||||
# Add the second trigger
|
||||
trig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Zones")
|
||||
trig.rules.append(dcs.condition.TimeAfter(2))
|
||||
for s_zone in rops.staging_zones:
|
||||
trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.stagingZone('" + s_zone + "')")))
|
||||
for c_zone in rops.conflict_zones:
|
||||
zone_flag = rops.conflict_zones[c_zone].flag
|
||||
trig.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.setupConflict('" + str(game_flag) + "')")))
|
||||
|
||||
rops.m.triggerrules.triggers.append(trig)
|
||||
|
||||
# Add the third trigger
|
||||
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)")))
|
||||
rops.m.triggerrules.triggers.append(trig)
|
||||
|
||||
# Add generic zone-based triggers
|
||||
for index, zone_name in enumerate(rops.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!")))
|
||||
rops.m.triggerrules.triggers.append(z_active_trig)
|
||||
|
||||
# Zone protection SAMs
|
||||
if options["zone_protect_sams"]:
|
||||
for index, zone_name in enumerate(rops.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'))")))
|
||||
rops.m.triggerrules.triggers.append(z_sams_trig)
|
||||
|
||||
# Zone FARPS always
|
||||
if options["zone_farps"] == "farp_always" and not options["defending"]:
|
||||
for index, zone_name in enumerate(rops.conflict_zones):
|
||||
if index > 0:
|
||||
previous_zone = list(rops.conflict_zones)[index - 1]
|
||||
if not rops.m.country(jtf_blue).find_group(previous_zone + " FARP Static"):
|
||||
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(rops.m.country(jtf_blue).find_group(previous_zone + " FARP Static").id))
|
||||
# z_farps_trig.actions.append(dcs.action.SoundToAll(str(rops.res_map['forward_base_established.ogg'])))
|
||||
z_farps_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"RotorOps.farpEstablished(" + str(index) + ")")))
|
||||
rops.m.triggerrules.triggers.append(z_farps_trig)
|
||||
|
||||
# Zone FARPS conditional on staged units remaining
|
||||
if options["zone_farps"] == "farp_gunits" and not options["defending"]:
|
||||
for index, zone_name in enumerate(rops.conflict_zones):
|
||||
if index > 0:
|
||||
previous_zone = list(rops.conflict_zones)[index - 1]
|
||||
if not rops.m.country(jtf_blue).find_group(previous_zone + " FARP Static"):
|
||||
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(rops.m.country(jtf_blue).find_group(previous_zone + " FARP Static").id))
|
||||
# z_farps_trig.actions.append(dcs.action.SoundToAll(str(rops.res_map['forward_base_established.ogg'])))
|
||||
z_farps_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"RotorOps.farpEstablished(" + str(index) + ")")))
|
||||
rops.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(rops.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 " + str(
|
||||
zone.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()")))
|
||||
rops.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(rops.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 " + str(
|
||||
zone.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()")))
|
||||
rops.m.triggerrules.triggers.append(z_weak_trig)
|
||||
|
||||
# Add transport helos triggers
|
||||
for index in range(options["e_transport_helos"]):
|
||||
random_zone_index = random.randrange(1, len(rops.conflict_zones))
|
||||
random_zone_obj = list(rops.conflict_zones.items())[random_zone_index]
|
||||
zone = random_zone_obj[1]
|
||||
z_weak_trig = dcs.triggers.TriggerOnce(comment=zone.name + " Transport Helo")
|
||||
z_weak_trig.rules.append(dcs.condition.FlagEquals(game_flag, random_zone_index + 1))
|
||||
z_weak_trig.rules.append(dcs.condition.FlagIsLess(zone.flag, random.randrange(20, 100)))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"---Flag " + str(game_flag) + " value represents the index of the active zone. ")))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("---Flag " + str(
|
||||
zone.flag) + " value represents the percentage of defending ground units remaining in zone. ")))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(
|
||||
dcs.action.String("RotorOps.spawnTranspHelos(8," + str(options["transport_drop_qty"]) + ")")))
|
||||
rops.m.triggerrules.triggers.append(z_weak_trig)
|
||||
|
||||
# Add game won/lost triggers
|
||||
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")))
|
||||
rops.m.triggerrules.triggers.append(trig)
|
||||
|
||||
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")))
|
||||
rops.m.triggerrules.triggers.append(trig)
|
||||
@ -25,7 +25,7 @@ class VehicleTemplate:
|
||||
dcs.vehicles.Unarmed.M_818,
|
||||
dcs.vehicles.AirDefence.Vulcan,
|
||||
dcs.vehicles.Unarmed.Ural_375,
|
||||
dcs.vehicles.Unarmed.M978_HEMTT_Tanker
|
||||
dcs.vehicles.Unarmed.M978_HEMTT_Tanker,
|
||||
],
|
||||
position.point_from_heading(45, 7),
|
||||
heading=random.randint(0, 359),
|
||||
|
||||
236
Generator/RotorOpsImport.py
Normal file
236
Generator/RotorOpsImport.py
Normal file
@ -0,0 +1,236 @@
|
||||
import math
|
||||
import dcs
|
||||
from MissionGenerator import logger
|
||||
|
||||
|
||||
class ImportObjects:
|
||||
|
||||
def __init__(self, mizfile, source_point=None, source_heading=0):
|
||||
self.pad_unit = True #todo: use this to hold a unit for helicopter placement on ships ie flight_group_from_unit
|
||||
logger.info("Importing objects from " + mizfile)
|
||||
self.source_mission = dcs.mission.Mission()
|
||||
self.source_mission.load_file(mizfile)
|
||||
self.source_heading = source_heading
|
||||
if source_point:
|
||||
self.source_point = source_point
|
||||
else:
|
||||
self.source_point = dcs.Point(self.source_mission.terrain.bullseye_blue["x"], self.source_mission.terrain.bullseye_blue["y"])
|
||||
self.statics = []
|
||||
self.vehicles = []
|
||||
self.helicopters = []
|
||||
|
||||
self.extractUnits()
|
||||
|
||||
def getStatics(self):
|
||||
return self.statics
|
||||
|
||||
def getVehicles(self):
|
||||
return self.vehicles
|
||||
|
||||
def getHelicopters(self):
|
||||
return self.helicopters
|
||||
|
||||
def copyAll(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
return self.copyStatics(mission, dest_country_name, dest_name, dest_point, dest_heading), \
|
||||
self.copyVehicles(mission, dest_country_name, dest_name, dest_point, dest_heading), \
|
||||
self.copyHelicopters(mission, dest_country_name, dest_name, dest_point, dest_heading)
|
||||
|
||||
|
||||
def anchorByGroupName(self, group_name):
|
||||
group = self.source_mission.find_group(group_name)
|
||||
if group:
|
||||
self.source_point = group.units[0].position
|
||||
self.source_heading = group.units[0].heading
|
||||
else:
|
||||
logger.warning("Unable to find group for anchor.")
|
||||
raise Exception(
|
||||
"Import template file error: " + self.mizfile + " does not contain a group called " + group_name)
|
||||
|
||||
def extractUnits(self):
|
||||
|
||||
for side in "red", "blue", "neutrals":
|
||||
coalition = self.source_mission.coalition.get(side)
|
||||
for country_name in coalition.countries:
|
||||
|
||||
group_types = [coalition.countries[country_name].static_group, coalition.countries[country_name].vehicle_group, coalition.countries[country_name].helicopter_group, coalition.countries[country_name].plane_group,
|
||||
coalition.countries[country_name].ship_group]
|
||||
|
||||
for index, group_type in enumerate(group_types):
|
||||
for group in group_type:
|
||||
|
||||
if index == 0: # Statics
|
||||
self.statics.append(group)
|
||||
elif index == 1: # Vehicles
|
||||
self.vehicles.append(group)
|
||||
elif index == 2: # Helicopters
|
||||
self.helicopters.append(group)
|
||||
elif index == 3:
|
||||
logger.warn(group.name + ": Planes not available for import")
|
||||
elif index == 4:
|
||||
logger.warn(group.name + ": Ships not available for import")
|
||||
|
||||
|
||||
def copyStatics(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
logger.info("Copying " + str(len(self.statics)) + " static objects as " + dest_name)
|
||||
new_groups = []
|
||||
|
||||
if not dest_point:
|
||||
dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||
|
||||
#Statics
|
||||
statics_copy = self.statics.copy()
|
||||
for group in statics_copy:
|
||||
|
||||
self.groupToPoint(group, self.source_point, dest_point, self.source_heading, dest_heading)
|
||||
|
||||
|
||||
class temp(dcs.unittype.StaticType):
|
||||
id = group.units[0].type
|
||||
name = group.units[0].name
|
||||
shape_name = group.units[0].shape_name
|
||||
rate = group.units[0].rate
|
||||
can_cargo = group.units[0].can_cargo
|
||||
mass = group.units[0].mass
|
||||
|
||||
|
||||
ng = mission.static_group(mission.country(dest_country_name),
|
||||
dest_name + " " + group.name,
|
||||
temp,
|
||||
group.units[0].position,
|
||||
group.units[0].heading,
|
||||
hidden=False)
|
||||
ng.units[0].name = group.units[0].name
|
||||
new_groups.append(ng)
|
||||
|
||||
# if ng.units[0].type == "Invisible FARP":
|
||||
# self.pad_unit = ng
|
||||
|
||||
return new_groups
|
||||
|
||||
|
||||
|
||||
|
||||
def copyVehicles(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
logger.info("Copying " + str(len(self.vehicles)) + " vehicle groups as " + dest_name)
|
||||
new_groups = []
|
||||
|
||||
if not dest_point:
|
||||
dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||
|
||||
vehicles_copy = self.vehicles
|
||||
for group in vehicles_copy:
|
||||
|
||||
self.groupToPoint(group, self.source_point, dest_point, self.source_heading, dest_heading)
|
||||
|
||||
for i, unit in enumerate(group.units):
|
||||
if i == 0:
|
||||
ng = mission.vehicle_group(mission.country(dest_country_name),
|
||||
dest_name + " " + group.name,
|
||||
dcs.vehicles.vehicle_map[group.units[0].type],
|
||||
group.units[0].position,
|
||||
group.units[0].heading)
|
||||
|
||||
new_groups.append(ng) # will this hold units we add later?
|
||||
|
||||
else:
|
||||
|
||||
u = mission.vehicle(dest_name + " " + group.units[i].name, dcs.vehicles.vehicle_map[group.units[i].type])
|
||||
u.position = group.units[i].position
|
||||
u.heading = group.units[i].heading
|
||||
ng.add_unit(u)
|
||||
|
||||
return new_groups
|
||||
|
||||
|
||||
def copyHelicopters(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
logger.info("Copying " + str(len(self.helicopters)) + " helicopters as " + dest_name)
|
||||
new_groups = []
|
||||
|
||||
if not dest_point:
|
||||
dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||
|
||||
helicopters_copy = self.helicopters.copy()
|
||||
for group in helicopters_copy:
|
||||
|
||||
self.groupToPoint(group, self.source_point, dest_point, self.source_heading, dest_heading)
|
||||
|
||||
if self.pad_unit:
|
||||
if group.units[0].skill == dcs.unit.Skill.Client or group.units[0].skill == dcs.unit.Skill.Player:
|
||||
|
||||
# we'll create a new FARP for each helicopter. we've tried adding the flight group to an existing FARP, but they stack on top of each other
|
||||
# trying to move the units into position after adding the flight group moves the 2D graphic of the helicopter, but the unit marker remains stacked on top
|
||||
# of the unit marker in ME
|
||||
# farp = mission.country(country_name).find_group(self.pad_unit.name)
|
||||
|
||||
farp = mission.farp(mission.country(dest_country_name), dest_name + " " + group.name + " Pad", group.units[0].position, hidden=True, dead=False,
|
||||
farp_type=dcs.unit.InvisibleFARP)
|
||||
|
||||
|
||||
|
||||
ng = mission.flight_group_from_unit(mission.country(dest_country_name),
|
||||
dest_name + " " + group.name,
|
||||
dcs.helicopters.helicopter_map[group.units[0].type],
|
||||
farp,
|
||||
group_size=1)
|
||||
|
||||
ng.points[0].action = dcs.point.PointAction.FromGroundArea
|
||||
ng.points[0].type = "TakeOffGround"
|
||||
ng.units[0].heading = group.units[0].heading
|
||||
ng.units[0].skill = group.units[0].skill
|
||||
ng.units[0].livery_id = group.units[0].livery_id
|
||||
ng.units[0].pylons = group.units[0].pylons
|
||||
|
||||
new_groups.append(ng)
|
||||
else:
|
||||
logger.warn("No pad unit (ie FARP, carrier) found, so can't add helicopters.")
|
||||
|
||||
return new_groups
|
||||
|
||||
|
||||
def copyVehiclesAsGroup(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
logger.info("Copying " + str(len(self.vehicles)) + " vehicle groups as single group name: " + dest_name)
|
||||
new_group = None
|
||||
|
||||
if not dest_point:
|
||||
dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||
|
||||
unit_count = 0
|
||||
vehicles_copy = self.vehicles.copy()
|
||||
for group in vehicles_copy:
|
||||
self.groupToPoint(group, self.source_point, dest_point, self.source_heading, dest_heading)
|
||||
for i, unit in enumerate(group.units):
|
||||
|
||||
if unit_count == 0:
|
||||
print("Group:" + group.name)
|
||||
new_group = mission.vehicle_group(mission.country(dest_country_name),
|
||||
dest_name,
|
||||
dcs.vehicles.vehicle_map[group.units[0].type],
|
||||
group.units[0].position,
|
||||
group.units[0].heading)
|
||||
unit_count = unit_count + 1
|
||||
|
||||
else:
|
||||
|
||||
print("Unit:" + group.units[i].name)
|
||||
u = mission.vehicle(dest_name + " " + group.units[i].name, dcs.vehicles.vehicle_map[group.units[i].type])
|
||||
u.position = group.units[i].position
|
||||
u.heading = group.units[i].heading
|
||||
new_group.add_unit(u)
|
||||
|
||||
unit_count = unit_count + 1
|
||||
print("Made a group with units: " + str(unit_count))
|
||||
print("group actually has units: " + str(len(new_group.units)))
|
||||
|
||||
return new_group
|
||||
|
||||
|
||||
@staticmethod
|
||||
def groupToPoint(group, src_point, dest_point, src_heading=0, dest_heading=0):
|
||||
for unit in group.units:
|
||||
heading_to_unit = dcs.mapping.heading_between_points(src_point.x, src_point.y, unit.position.x,
|
||||
unit.position.y)
|
||||
new_heading_to_unit = dest_heading + heading_to_unit
|
||||
unit_distance = src_point.distance_to_point(unit.position)
|
||||
unit.position = dest_point.point_from_heading(new_heading_to_unit, unit_distance)
|
||||
unit.heading = unit.heading + dest_heading
|
||||
return group
|
||||
@ -6,10 +6,14 @@ import random
|
||||
|
||||
import RotorOpsGroups
|
||||
import RotorOpsUnits
|
||||
import RotorOpsUtils
|
||||
import RotorOpsConflict
|
||||
from RotorOpsImport import ImportObjects
|
||||
import time
|
||||
from MissionGenerator import logger
|
||||
|
||||
|
||||
jtf_red = "Combined Joint Task Forces Red"
|
||||
jtf_blue = "Combined Joint Task Forces Blue"
|
||||
|
||||
class RotorOpsMission:
|
||||
|
||||
@ -23,12 +27,14 @@ class RotorOpsMission:
|
||||
self.sound_directory = self.home_dir + "\sound\embedded"
|
||||
self.output_dir = self.home_dir + "\Generator\Output"
|
||||
self.assets_dir = self.home_dir + "\Generator/assets"
|
||||
self.imports_dir = self.home_dir + "\Generator\Imports"
|
||||
|
||||
self.conflict_zones = {}
|
||||
self.staging_zones = {}
|
||||
self.spawn_zones = {}
|
||||
self.scripts = {}
|
||||
self.res_map = {}
|
||||
self.config = None
|
||||
|
||||
class RotorOpsZone:
|
||||
def __init__(self, name: str, flag: int, position: dcs.point, size: int):
|
||||
@ -37,9 +43,13 @@ class RotorOpsMission:
|
||||
self.position = position
|
||||
self.size = size
|
||||
|
||||
|
||||
def getMission(self):
|
||||
return self.m
|
||||
|
||||
def setConfig(self,config):
|
||||
self.config = config
|
||||
|
||||
def addZone(self, zone_dict, zone: RotorOpsZone):
|
||||
zone_dict[zone.name] = zone
|
||||
|
||||
@ -119,7 +129,12 @@ class RotorOpsMission:
|
||||
|
||||
self.m.load_file(options["scenario_filename"])
|
||||
|
||||
if not self.m.country("Combined Joint Task Forces Red") or not self.m.country("Combined Joint Task Forces Blue"):
|
||||
self.importObjects()
|
||||
|
||||
#todo: test
|
||||
self.m.coalition.get("neutrals").add_country(dcs.countries.UnitedNationsPeacekeepers())
|
||||
|
||||
if not self.m.country(jtf_red) or not self.m.country(jtf_blue) or not self.m.country(dcs.countries.UnitedNationsPeacekeepers.name):
|
||||
failure_msg = "You must include a CombinedJointTaskForcesBlue and CombinedJointTaskForcesRed unit in the scenario template. See the instructions in " + self.scenarios_dir
|
||||
return {"success": False, "failure_msg": failure_msg}
|
||||
|
||||
@ -129,12 +144,13 @@ class RotorOpsMission:
|
||||
# Add coalitions (we may be able to add CJTF here instead of requiring templates to have objects of those coalitions)
|
||||
self.m.coalition.get("red").add_country(dcs.countries.Russia())
|
||||
self.m.coalition.get("blue").add_country(dcs.countries.USA())
|
||||
# blue = self.m.coalition.get("blue")
|
||||
# blue.add_country(dcs.countries.CombinedJointTaskForcesBlue())
|
||||
|
||||
self.m.add_picture_blue(self.assets_dir + '/briefing1.png')
|
||||
self.m.add_picture_blue(self.assets_dir + '/briefing2.png')
|
||||
|
||||
|
||||
|
||||
# add zones to target mission
|
||||
zone_names = ["ALPHA", "BRAVO", "CHARLIE", "DELTA"]
|
||||
zone_flag = 101
|
||||
@ -163,20 +179,49 @@ class RotorOpsMission:
|
||||
|
||||
|
||||
#Populate Red zones with ground units
|
||||
|
||||
for zone_name in red_zones:
|
||||
if red_forces["vehicles"]:
|
||||
self.addGroundGroups(red_zones[zone_name], self.m.country('Combined Joint Task Forces Red'), red_forces["vehicles"], options["red_quantity"])
|
||||
self.addGroundGroups(red_zones[zone_name], self.m.country(jtf_red), red_forces["vehicles"], options["red_quantity"])
|
||||
|
||||
#Add red FARPS
|
||||
|
||||
if options["zone_farps"] != "farp_never" and not options["defending"]:
|
||||
RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.zone_farp(self.m, self.m.country('Combined Joint Task Forces Blue'),
|
||||
self.m.country('Combined Joint Task Forces Blue'),
|
||||
red_zones[zone_name].position,
|
||||
180, zone_name + " FARP", late_activation=True)
|
||||
# RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.zone_farp(self.m, self.m.country(jtf_blue),
|
||||
# self.m.country(jtf_blue),
|
||||
# red_zones[zone_name].position,
|
||||
# 180, zone_name + " FARP", late_activation=True)
|
||||
|
||||
#new_statics, new_vehicles, new_helicopters = i.copyAll(self.m, dcs.countries.UnitedNationsPeacekeepers.name, zone_name, red_zones[zone_name].position)
|
||||
|
||||
farp_flag = self.m.find_group(zone_name)
|
||||
|
||||
if farp_flag:
|
||||
farp_position = farp_flag.units[0].position
|
||||
farp_heading = farp_flag.units[0].heading
|
||||
else:
|
||||
farp_position = red_zones[zone_name].position
|
||||
farp_heading = 0
|
||||
|
||||
farp = self.m.farp(self.m.country(jtf_blue), zone_name + " FARP", farp_position,
|
||||
hidden=False, dead=False,
|
||||
farp_type=dcs.unit.InvisibleFARP)
|
||||
|
||||
os.chdir(self.imports_dir)
|
||||
if self.config and self.config["zone_farp_file"]:
|
||||
filename = self.config["zone_farp_file"]
|
||||
else:
|
||||
filename = "FARP_DEFAULT_ZONE.miz"
|
||||
i = ImportObjects(filename)
|
||||
i.anchorByGroupName("ANCHOR")
|
||||
farp_group = i.copyVehiclesAsGroup(self.m, jtf_blue, zone_name + " FARP Static", farp_position, farp_heading)
|
||||
farp_group.late_activation = True
|
||||
|
||||
|
||||
|
||||
if options["zone_protect_sams"]:
|
||||
self.m.vehicle_group(
|
||||
self.m.country('Combined Joint Task Forces Red'),
|
||||
self.m.country(jtf_red),
|
||||
"Static " + zone_name + " Protection SAM",
|
||||
random.choice(RotorOpsUnits.e_zone_sams),
|
||||
red_zones[zone_name].position,
|
||||
@ -190,20 +235,35 @@ class RotorOpsMission:
|
||||
#Populate Blue zones with ground units
|
||||
for zone_name in blue_zones:
|
||||
if blue_forces["vehicles"]:
|
||||
self.addGroundGroups(blue_zones[zone_name], self.m.country('Combined Joint Task Forces Blue'), blue_forces["vehicles"],
|
||||
self.addGroundGroups(blue_zones[zone_name], self.m.country(jtf_blue), blue_forces["vehicles"],
|
||||
options["blue_quantity"])
|
||||
#Add blue FARPS
|
||||
if options["zone_farps"] != "farp_never" and options["defending"]:
|
||||
RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.zone_farp(self.m, self.m.country('Combined Joint Task Forces Blue'),
|
||||
self.m.country('Combined Joint Task Forces Blue'),
|
||||
RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.zone_farp(self.m, self.m.country(jtf_blue),
|
||||
self.m.country(jtf_blue),
|
||||
blue_zones[zone_name].position,
|
||||
180, zone_name + " FARP", late_activation=False)
|
||||
|
||||
#add logistics sites
|
||||
if options["crates"] and zone_name in self.staging_zones:
|
||||
RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.logistics_site(self.m, self.m.country('Combined Joint Task Forces Blue'),
|
||||
blue_zones[zone_name].position,
|
||||
180, zone_name)
|
||||
# RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.logistics_site(self.m, self.m.country(jtf_blue),
|
||||
# blue_zones[zone_name].position,
|
||||
# 180, zone_name)
|
||||
os.chdir(self.imports_dir)
|
||||
staging_flag = self.m.find_group(zone_name)
|
||||
if staging_flag:
|
||||
staging_position = staging_flag.units[0].position
|
||||
staging_heading = staging_flag.units[0].heading
|
||||
else:
|
||||
staging_position = blue_zones[zone_name].position
|
||||
staging_heading = 0
|
||||
i = ImportObjects("STAGING_LOGISTIC_HUB.miz")
|
||||
i.anchorByGroupName("ANCHOR")
|
||||
i.copyAll(self.m, jtf_blue, "Staging Logistics Zone",
|
||||
staging_position, staging_heading)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -211,7 +271,7 @@ class RotorOpsMission:
|
||||
|
||||
if options["zone_protect_sams"] and options["defending"]:
|
||||
vg = self.m.vehicle_group(
|
||||
self.m.country('Combined Joint Task Forces Blue'),
|
||||
self.m.country(jtf_blue),
|
||||
"Static " + zone_name + " Protection SAM",
|
||||
random.choice(RotorOpsUnits.e_zone_sams),
|
||||
blue_zones[zone_name].position,
|
||||
@ -222,7 +282,8 @@ class RotorOpsMission:
|
||||
|
||||
|
||||
#Add player slots
|
||||
self.addPlayerHelos(options)
|
||||
if options["slots"] != "Locked to Scenario" and options["slots"] != "None":
|
||||
self.addPlayerHelos(options)
|
||||
|
||||
#Add AI Flights
|
||||
self.addFlights(options, red_forces, blue_forces)
|
||||
@ -233,7 +294,8 @@ class RotorOpsMission:
|
||||
|
||||
#add files and triggers necessary for RotorOps.lua script
|
||||
self.addResources(self.sound_directory, self.script_directory)
|
||||
self.scriptTriggerSetup(options)
|
||||
RotorOpsConflict.triggerSetup(self, options)
|
||||
|
||||
|
||||
#Save the mission file
|
||||
os.chdir(self.output_dir)
|
||||
@ -284,10 +346,11 @@ class RotorOpsMission:
|
||||
if len(airport.free_parking_slots(aircraft)) >= group_size:
|
||||
if not (aircraft.id in dcs.planes.plane_map and len(airport.runways) == 0):
|
||||
return airport
|
||||
for airport in alt_airports:
|
||||
if len(airport.free_parking_slots(aircraft)) >= group_size:
|
||||
if not (aircraft.id in dcs.planes.plane_map and len(airport.runways) == 0):
|
||||
return airport
|
||||
if alt_airports:
|
||||
for airport in alt_airports:
|
||||
if len(airport.free_parking_slots(aircraft)) >= group_size:
|
||||
if not (aircraft.id in dcs.planes.plane_map and len(airport.runways) == 0):
|
||||
return airport
|
||||
|
||||
logger.warn("No parking available for " + aircraft.id)
|
||||
return None
|
||||
@ -309,8 +372,8 @@ class RotorOpsMission:
|
||||
for airport in red_airports:
|
||||
self.m.terrain.airports[airport.name].set_blue()
|
||||
|
||||
combinedJointTaskForcesBlue = self.m.country("Combined Joint Task Forces Blue")
|
||||
combinedJointTaskForcesRed = self.m.country("Combined Joint Task Forces Red")
|
||||
combinedJointTaskForcesBlue = self.m.country(jtf_blue)
|
||||
combinedJointTaskForcesRed = self.m.country(jtf_red)
|
||||
|
||||
|
||||
#Swap ships
|
||||
@ -393,13 +456,13 @@ class RotorOpsMission:
|
||||
client_helos = [dcs.helicopters.helicopter_map[helicopter]]
|
||||
|
||||
#find friendly carriers and farps
|
||||
carrier = self.m.country("Combined Joint Task Forces Blue").find_ship_group(name="HELO_CARRIER")
|
||||
carrier = self.m.country(jtf_blue).find_ship_group(name="HELO_CARRIER")
|
||||
if not carrier:
|
||||
carrier = self.m.country("Combined Joint Task Forces Blue").find_ship_group(name="HELO_CARRIER_1")
|
||||
carrier = self.m.country(jtf_blue).find_ship_group(name="HELO_CARRIER_1")
|
||||
|
||||
farp = self.m.country("Combined Joint Task Forces Blue").find_static_group("HELO_FARP")
|
||||
farp = self.m.country(jtf_blue).find_static_group("HELO_FARP")
|
||||
if not farp:
|
||||
farp = self.m.country("Combined Joint Task Forces Blue").find_static_group("HELO_FARP_1")
|
||||
farp = self.m.country(jtf_blue).find_static_group("HELO_FARP_1")
|
||||
|
||||
friendly_airports, primary_f_airport = self.getCoalitionAirports("blue")
|
||||
|
||||
@ -410,10 +473,10 @@ class RotorOpsMission:
|
||||
|
||||
for helotype in client_helos:
|
||||
if carrier:
|
||||
fg = self.m.flight_group_from_unit(self.m.country('Combined Joint Task Forces Blue'), "CARRIER " + helotype.id, helotype, carrier,
|
||||
fg = self.m.flight_group_from_unit(self.m.country(jtf_blue), "CARRIER " + helotype.id, helotype, carrier,
|
||||
dcs.task.CAS, group_size=group_size)
|
||||
elif farp:
|
||||
fg = self.m.flight_group_from_unit(self.m.country('Combined Joint Task Forces Blue'), "FARP " + helotype.id, helotype, farp,
|
||||
fg = self.m.flight_group_from_unit(self.m.country(jtf_blue), "FARP " + helotype.id, helotype, farp,
|
||||
dcs.task.CAS, group_size=group_size)
|
||||
|
||||
#invisible farps need manual unit placement for multiple units
|
||||
@ -423,7 +486,7 @@ class RotorOpsMission:
|
||||
fg.units[0].position = fg.units[0].position.point_from_heading(heading, 30)
|
||||
heading += 90
|
||||
else:
|
||||
fg = self.m.flight_group_from_airport(self.m.country('Combined Joint Task Forces Blue'), primary_f_airport.name + " " + helotype.id, helotype,
|
||||
fg = self.m.flight_group_from_airport(self.m.country(jtf_blue), primary_f_airport.name + " " + helotype.id, helotype,
|
||||
self.getParking(primary_f_airport, helotype), group_size=group_size)
|
||||
fg.units[0].set_client()
|
||||
fg.load_task_default_loadout(dcs.task.CAS)
|
||||
@ -459,13 +522,13 @@ class RotorOpsMission:
|
||||
enemy_airports, primary_e_airport = self.getCoalitionAirports("red")
|
||||
|
||||
#find enemy carriers and farps
|
||||
carrier = self.m.country("Combined Joint Task Forces Red").find_ship_group(name="HELO_CARRIER")
|
||||
carrier = self.m.country(jtf_red).find_ship_group(name="HELO_CARRIER")
|
||||
if not carrier:
|
||||
carrier = self.m.country("Combined Joint Task Forces Red").find_ship_group(name="HELO_CARRIER_1")
|
||||
carrier = self.m.country(jtf_red).find_ship_group(name="HELO_CARRIER_1")
|
||||
|
||||
farp = self.m.country("Combined Joint Task Forces Red").find_static_group("HELO_FARP")
|
||||
farp = self.m.country(jtf_red).find_static_group("HELO_FARP")
|
||||
if not farp:
|
||||
farp = self.m.country("Combined Joint Task Forces Red").find_static_group("HELO_FARP_1")
|
||||
farp = self.m.country(jtf_red).find_static_group("HELO_FARP_1")
|
||||
|
||||
e_airport_heading = dcs.mapping.heading_between_points(
|
||||
friendly_airports[0].position.x, friendly_airports[0].position.y, enemy_airports[0].position.x, primary_e_airport.position.y
|
||||
@ -502,7 +565,7 @@ class RotorOpsMission:
|
||||
awacs_escort = self.m.escort_flight(
|
||||
combinedJointTaskForcesBlue, "AWACS Escort",
|
||||
plane_type,
|
||||
airport=self.getParking(primary_f_airport, plane_type, friendly_airports),
|
||||
airport=self.getParking(primary_f_airport, plane_type, friendly_airports, group_size=2),
|
||||
group_to_escort=awacs,
|
||||
group_size=2)
|
||||
|
||||
@ -695,149 +758,33 @@ class RotorOpsMission:
|
||||
unit.pylons = source_helo.pylons
|
||||
unit.livery_id = source_helo.livery_id
|
||||
|
||||
def scriptTriggerSetup(self, options):
|
||||
|
||||
#get the boolean value from ui option and convert to lua string
|
||||
def lb(var):
|
||||
return str(options[var]).lower()
|
||||
|
||||
game_flag = 100
|
||||
#Add the first trigger
|
||||
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"]))
|
||||
script = ""
|
||||
script = ("--OPTIONS HERE!\n\n" +
|
||||
"RotorOps.CTLD_crates = " + lb("crates") + "\n\n" +
|
||||
"RotorOps.CTLD_sound_effects = true\n\n" +
|
||||
"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")
|
||||
if not options["smoke_pickup_zones"]:
|
||||
script = script + 'RotorOps.pickup_zone_smoke = "none"\n\n'
|
||||
trig.actions.append(dcs.action.DoScript(dcs.action.String((script))))
|
||||
self.m.triggerrules.triggers.append(trig)
|
||||
|
||||
#Add the second trigger
|
||||
trig = dcs.triggers.TriggerOnce(comment="RotorOps Setup Zones")
|
||||
trig.rules.append(dcs.condition.TimeAfter(2))
|
||||
for s_zone in self.staging_zones:
|
||||
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
|
||||
trig.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.setupConflict('" + str(game_flag) + "')")))
|
||||
|
||||
self.m.triggerrules.triggers.append(trig)
|
||||
|
||||
#Add the third trigger
|
||||
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 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!")))
|
||||
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"]:
|
||||
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("Combined Joint Task Forces Blue").find_group(previous_zone + " FARP Static"):
|
||||
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("Combined Joint Task Forces Blue").find_group(previous_zone + " FARP Static").id))
|
||||
#z_farps_trig.actions.append(dcs.action.SoundToAll(str(self.res_map['forward_base_established.ogg'])))
|
||||
z_farps_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"RotorOps.farpEstablished(" + str(index) + ")")))
|
||||
self.m.triggerrules.triggers.append(z_farps_trig)
|
||||
|
||||
|
||||
#Zone FARPS conditional on staged units remaining
|
||||
if options["zone_farps"] == "farp_gunits" and not options["defending"]:
|
||||
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("Combined Joint Task Forces Blue").find_group(previous_zone + " FARP Static"):
|
||||
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("Combined Joint Task Forces Blue").find_group(previous_zone + " FARP Static").id))
|
||||
#z_farps_trig.actions.append(dcs.action.SoundToAll(str(self.res_map['forward_base_established.ogg'])))
|
||||
z_farps_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"RotorOps.farpEstablished(" + str(index) + ")")))
|
||||
self.m.triggerrules.triggers.append(z_farps_trig)
|
||||
|
||||
def importObjects(self):
|
||||
os.chdir(self.imports_dir)
|
||||
logger.info("Looking for import .miz files in '" + os.getcwd())
|
||||
|
||||
for side in "red", "blue", "neutrals":
|
||||
coalition = self.m.coalition.get(side)
|
||||
for country_name in coalition.countries:
|
||||
for group in self.m.country(country_name).static_group:
|
||||
prefix = "IMPORT-"
|
||||
if group.name.find(prefix) == 0:
|
||||
if group.units[0].name.find('IMPORT-') == 0:
|
||||
logger.error(
|
||||
group.units[0].name + " IMPORT group's unit name cannot start with 'IMPORT'. Check the scenario template.")
|
||||
raise Exception("Scenario file error: " + group.units[0].name + " IMPORT group's unit name cannot start with 'IMPORT'")
|
||||
|
||||
# trim the groupname to our filename convention
|
||||
filename = group.name.removeprefix(prefix)
|
||||
i = filename.find('-')
|
||||
if i > 8:
|
||||
filename = filename[0:i]
|
||||
print(filename)
|
||||
|
||||
|
||||
#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 " + str(zone.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 " + str(zone.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 transport helos triggers
|
||||
for index in range(options["e_transport_helos"]):
|
||||
random_zone_index = random.randrange(1, len(self.conflict_zones))
|
||||
random_zone_obj = list(self.conflict_zones.items())[random_zone_index]
|
||||
zone = random_zone_obj[1]
|
||||
z_weak_trig = dcs.triggers.TriggerOnce(comment=zone.name + " Transport Helo")
|
||||
z_weak_trig.rules.append(dcs.condition.FlagEquals(game_flag, random_zone_index + 1))
|
||||
z_weak_trig.rules.append(dcs.condition.FlagIsLess(zone.flag, random.randrange(20, 100)))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String(
|
||||
"---Flag " + str(game_flag) + " value represents the index of the active zone. ")))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("---Flag " + str(zone.flag) + " value represents the percentage of defending ground units remaining in zone. ")))
|
||||
z_weak_trig.actions.append(dcs.action.DoScript(dcs.action.String("RotorOps.spawnTranspHelos(8," + str(options["transport_drop_qty"]) + ")")))
|
||||
self.m.triggerrules.triggers.append(z_weak_trig)
|
||||
|
||||
#Add game won/lost triggers
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
filename = filename + ".miz"
|
||||
i = ImportObjects(filename)
|
||||
i.anchorByGroupName("ANCHOR")
|
||||
new_statics, new_vehicles, new_helicopters = i.copyAll(self.m, country_name, group.units[0].name, group.units[0].position, group.units[0].heading)
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import math
|
||||
import dcs
|
||||
from MissionGenerator import logger
|
||||
|
||||
|
||||
def getDistance(point1=dcs.Point, point2=dcs.Point):
|
||||
@ -15,3 +16,167 @@ def getDistance(point1=dcs.Point, point2=dcs.Point):
|
||||
def convertMeterToNM(meters=int):
|
||||
nm = meters / 1852
|
||||
return nm
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# class ImportObjects:
|
||||
#
|
||||
# def __init__(self, mizfile, source_point=None, source_heading=0):
|
||||
# self.pad_unit = None
|
||||
# logger.info("Importing objects from " + mizfile)
|
||||
# self.source_mission = dcs.mission.Mission()
|
||||
# self.source_mission.load_file(mizfile)
|
||||
# self.source_heading = source_heading
|
||||
# if source_point:
|
||||
# self.source_point = source_point
|
||||
# else:
|
||||
# self.source_point = dcs.Point(self.source_mission.terrain.bullseye_blue["x"], self.source_mission.terrain.bullseye_blue["y"])
|
||||
#
|
||||
#
|
||||
# def anchorByGroupName(self, group_name):
|
||||
# group = self.source_mission.find_group(group_name)
|
||||
# if group:
|
||||
# self.source_point = group.units[0].position
|
||||
# self.source_heading = group.units[0].heading
|
||||
# else:
|
||||
# logger.warning("Unable to find group for anchor.")
|
||||
#
|
||||
#
|
||||
# def copyTo(self, mission, dest_country_name, dest_name, dest_point=None, dest_heading=0):
|
||||
# logger.info("Copying objects as " + dest_name)
|
||||
#
|
||||
# if not dest_point:
|
||||
# dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||
#
|
||||
# for side in "red", "blue", "neutrals":
|
||||
# coalition = self.source_mission.coalition.get(side)
|
||||
# for country_name in coalition.countries:
|
||||
#
|
||||
# group_types = [coalition.countries[country_name].static_group, coalition.countries[country_name].vehicle_group, coalition.countries[country_name].helicopter_group, coalition.countries[country_name].plane_group,
|
||||
# coalition.countries[country_name].ship_group]
|
||||
#
|
||||
#
|
||||
#
|
||||
# for index, group_type in enumerate(group_types):
|
||||
# for group in group_type:
|
||||
# self.groupToPoint(group, self.source_point, dest_point, self.source_heading, dest_heading)
|
||||
#
|
||||
# # add the country to the destination mission if it doesn't exist already
|
||||
# # if not mission.country(country_name):
|
||||
# # print(country_name + " not found in destination mission")
|
||||
# # for index, c in enumerate(dcs.countries.country_dict):
|
||||
# # if dcs.countries.country_dict[c].name == country_name:
|
||||
# #
|
||||
# # mission.coalition.get(side).add_country(dcs.countries.country_dict[c]())
|
||||
# # print(country_name + " added to " + side)
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# if index == 0: # Statics
|
||||
# type_name = group.units[0].type
|
||||
# type_maps = [dcs.statics.cargo_map, dcs.statics.warehouse_map, dcs.statics.groundobject_map, dcs.statics.fortification_map]
|
||||
# classed = False
|
||||
# for type_map in type_maps:
|
||||
# if type_name in type_map:
|
||||
# classed = True
|
||||
# unit_type = type_map[type_name]
|
||||
# ng = mission.static_group(mission.country(dest_country_name),
|
||||
# group.name,
|
||||
# unit_type,
|
||||
# group.units[0].position,
|
||||
# group.units[0].heading,
|
||||
# hidden=False)
|
||||
#
|
||||
#
|
||||
#
|
||||
# if not classed:
|
||||
# print("No pydcs class for " + type_name)
|
||||
#
|
||||
#
|
||||
# class temp(dcs.unittype.StaticType):
|
||||
# id = group.units[0].type
|
||||
# name = group.units[0].name
|
||||
# shape_name = group.units[0].shape_name
|
||||
# rate = group.units[0].rate
|
||||
#
|
||||
#
|
||||
# ng = mission.static_group(mission.country(dest_country_name),
|
||||
# group.name,
|
||||
# temp,
|
||||
# group.units[0].position,
|
||||
# group.units[0].heading,
|
||||
# hidden=False)
|
||||
#
|
||||
# if ng.units[0].type == "Invisible FARP":
|
||||
# self.pad_unit = ng
|
||||
#
|
||||
# elif index == 1: # Vehicles
|
||||
#
|
||||
# for i, unit in enumerate(group.units):
|
||||
# if i == 0:
|
||||
# ng = mission.vehicle_group(mission.country(dest_country_name),
|
||||
# group.name,
|
||||
# dcs.vehicles.vehicle_map[group.units[0].type],
|
||||
# group.units[0].position,
|
||||
# group.units[0].heading)
|
||||
#
|
||||
#
|
||||
# else:
|
||||
#
|
||||
# u = mission.vehicle(group.units[i].name, dcs.vehicles.vehicle_map[group.units[i].type])
|
||||
# u.position = group.units[i].position
|
||||
# u.heading = group.units[i].heading
|
||||
# ng.add_unit(u)
|
||||
#
|
||||
# mission.country(dest_country_name).add_vehicle_group(ng)
|
||||
#
|
||||
#
|
||||
# elif index == 2: # Helicopters
|
||||
# if self.pad_unit:
|
||||
# if group.units[0].skill == dcs.unit.Skill.Client or group.units[0].skill == dcs.unit.Skill.Player:
|
||||
#
|
||||
# # we'll create a new FARP for each helicopter. we've tried adding the flight group to an existing FARP, but they stack on top of each other
|
||||
# # trying to move the units into position after adding the flight group moves the 2D graphic of the helicopter, but the unit marker remains stacked on top
|
||||
# # of the unit marker in ME
|
||||
# # farp = mission.country(country_name).find_group(self.pad_unit.name)
|
||||
#
|
||||
# farp = mission.farp(mission.country(country_name), dest_name + " " + group.name + " Pad", group.units[0].position, hidden=True, dead=False,
|
||||
# farp_type=dcs.unit.InvisibleFARP)
|
||||
#
|
||||
#
|
||||
#
|
||||
# ng = mission.flight_group_from_unit(mission.country(dest_country_name),
|
||||
# dest_name + " " + group.name,
|
||||
# dcs.helicopters.helicopter_map[group.units[0].type],
|
||||
# farp,
|
||||
# group_size=1)
|
||||
#
|
||||
# ng.points[0].action = dcs.point.PointAction.FromGroundArea
|
||||
# ng.points[0].type = "TakeOffGround"
|
||||
# ng.units[0].heading = group.units[0].heading
|
||||
# ng.units[0].skill = group.units[0].skill
|
||||
# ng.units[0].livery_id = group.units[0].livery_id
|
||||
# ng.units[0].pylons = group.units[0].pylons
|
||||
# else:
|
||||
# logger.warn("No pad unit (ie FARP, carrier) found, so can't add helicopters.")
|
||||
#
|
||||
# elif index == 3:
|
||||
# #mission.country(country).add_plane_group(group)
|
||||
# print("not yet avail")
|
||||
# elif index == 4:
|
||||
# #mission.country(country).add_ship_group(group)
|
||||
# print("not yet avail")
|
||||
#
|
||||
#
|
||||
# @staticmethod
|
||||
# def groupToPoint(group, src_point, dest_point, src_heading=0, dest_heading=0):
|
||||
# for unit in group.units:
|
||||
# heading_to_unit = dcs.mapping.heading_between_points(src_point.x, src_point.y, unit.position.x,
|
||||
# unit.position.y)
|
||||
# new_heading_to_unit = dest_heading + heading_to_unit
|
||||
# unit_distance = src_point.distance_to_point(unit.position)
|
||||
# unit.position = dest_point.point_from_heading(new_heading_to_unit, unit_distance)
|
||||
# unit.heading = unit.heading + dest_heading
|
||||
# return group
|
||||
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,3 +39,8 @@ Tips:
|
||||
-In "Defense" or with "Swap sides" option, USA and Russia ships, helicopters, planes, and ground units will swap countries. Static objects may not. Test it out.
|
||||
-Turn off or limit civilian road traffic.
|
||||
-Pay attention to rivers and bridges, as a far away bridge crossing may break routing if it's the only way across. See the testing notes above.
|
||||
|
||||
v0.6:
|
||||
You can now control the FARP spawning location and heading by adding a static object (such as a mark flag) with group name 'ALPHA' etc. Same for staging area logistics site..but the group name should be 'STAGING'. Change the object heading to better align with roads or map objects. The flags for these must be CJTFB country.
|
||||
|
||||
You can dynamically insert complex arangements of objects such as large bases with multiplayer spawns. See the 'Imports' folder for more details.
|
||||
|
||||
Binary file not shown.
38
README.md
38
README.md
@ -1,9 +1,12 @@
|
||||

|
||||
|
||||
# What is RotorOps?
|
||||
RotorOps is a mission generator and gameplay script for DCS: World. At its heart is a game type called Conflict, which requires helicopter operations to win battles on the ground. This is a fun territory capture game that promotes focus on individual 'conflict zones'.
|
||||
|
||||
At the core of the RotorOps script are AI enhancements that provide a dynamic ground war by causing automatic conflicts between ground forces and a progression of the front line.
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
# Key Features:
|
||||
- Unique helicopter-focused gameplay
|
||||
@ -22,6 +25,7 @@ At the core of the RotorOps script are AI enhancements that provide a dynamic gr
|
||||
|
||||
## Demo Missions
|
||||
RotorOps: Aleppo Under Siege https://www.digitalcombatsimulator.com/en/files/3320079/
|
||||
|
||||
Rota Landing (Mr. Nobody) https://www.digitalcombatsimulator.com/en/files/3320186/
|
||||
|
||||
|
||||
@ -57,25 +61,19 @@ Easily add your own templates for friendly/enemy ground units directly in the DC
|
||||
|
||||
Create your own scenarios for the RotorOps mission generator, using the DCS mission editor.
|
||||
|
||||
### RotorOps Mission Creator Guide:
|
||||
For more detailed information on how the script works, see this wiki:
|
||||
https://github.com/spencershepard/RotorOps/wiki/RotorOps:-Mission-Creator-Guide
|
||||
|
||||
***
|
||||
|
||||
### Get in touch!
|
||||
|
||||
https://discord.gg/HFqjrZV9xD
|
||||
|
||||
### Support Development
|
||||
|
||||
https://www.patreon.com/spencershepard
|
||||
|
||||
### Developers
|
||||
We welcome contributors to this new project! Please get in touch on Discord with new ideas or pickup/create an issue in this repo.
|
||||
|
||||
|
||||
### RotorOps Mission Creator Guide:
|
||||
For more detailed information on how the script works, see this wiki:
|
||||
https://github.com/spencershepard/RotorOps/wiki/RotorOps:-Mission-Creator-Guide
|
||||
|
||||
***
|
||||
### Thanks to
|
||||
RotorOps uses MIST and integrates CTLD:
|
||||
|
||||
https://github.com/mrSkortch/MissionScriptingTools
|
||||
@ -84,4 +82,18 @@ https://github.com/ciribob/DCS-CTLD
|
||||
|
||||
The mission generator would not be possible without PyDCS:
|
||||
|
||||
https://github.com/pydcs/dcs
|
||||
https://github.com/pydcs/dcs
|
||||
|
||||
### Thanks to contributors
|
||||
|
||||
Shagrat: For amazing templates and testing for our FARPs, FOBs, and other mission assets.
|
||||
|
||||
Mr. Nobody: For awesome scenario and forces templates and helping to indroduce the DCS world to RotorOps.
|
||||
|
||||
***
|
||||
|
||||
# Join our Discord!
|
||||
|
||||
Chat about anything RotorOps or join up to fly!
|
||||
|
||||
https://discord.gg/HFqjrZV9xD
|
||||
|
||||
46
RotorOps.lua
46
RotorOps.lua
@ -1,5 +1,5 @@
|
||||
RotorOps = {}
|
||||
RotorOps.version = "1.2.6"
|
||||
RotorOps.version = "1.2.7"
|
||||
local debug = true
|
||||
|
||||
|
||||
@ -345,6 +345,7 @@ end
|
||||
function RotorOps.isUnitInZone(unit, zone_name)
|
||||
local zone = trigger.misc.getZone(zone_name)
|
||||
local distance = getDistance(unit:getPoint(), zone.point)
|
||||
--local distance = mist.utils.get2DDist(unit:getPoint(), zone.point)
|
||||
if distance <= zone.radius then
|
||||
return true
|
||||
else
|
||||
@ -1497,3 +1498,46 @@ function RotorOps.spawnTranspHelos(troops, max_drops)
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- USEFUL PUBLIC 'LUA PREDICATE' FUNCTIONS FOR MISSION EDITOR TRIGGERS
|
||||
|
||||
--determine if any players are above a defined ceiling above ground level. If 'above' parameter is false, function will return true if no players above ceiling
|
||||
function RotorOps.predPlayerMaxAGL(max_agl, above)
|
||||
local players_above_ceiling = 0
|
||||
|
||||
for uName, uData in pairs(mist.DBs.humansByName) do
|
||||
local player_unit = Unit.getByName(uData.unitName)
|
||||
if player_unit then
|
||||
local player_pos = player_unit:getPosition().p
|
||||
local terrain_height = land.getHeight({x = player_pos.x, y = player_pos.z})
|
||||
local player_agl = player_pos.y - terrain_height
|
||||
if player_agl > max_agl then
|
||||
players_above_ceiling = players_above_ceiling + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if players_above_ceiling > 0 then
|
||||
return above
|
||||
else
|
||||
return not above
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--determine if any players are in a zone (not currently working)
|
||||
function RotorOps.predPlayerInZone(zone_name)
|
||||
local players_in_zone = 0
|
||||
for uName, uData in pairs(mist.DBs.humansByName) do
|
||||
local player_unit = Unit.getByName(uData.unitName)
|
||||
if player_unit and RotorOps.isUnitInZone(player_unit, zone_name) then
|
||||
players_in_zone = players_in_zone + 1
|
||||
end
|
||||
end
|
||||
if players_in_zone > 0 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user