diff --git a/Generator/Forces/blue/BLUE Default Armor.miz b/Generator/Forces/blue/BLUE Default US Armor.miz similarity index 100% rename from Generator/Forces/blue/BLUE Default Armor.miz rename to Generator/Forces/blue/BLUE Default US Armor.miz diff --git a/Generator/Forces/blue/BLUE Greece Armor (Mr Nobody).miz b/Generator/Forces/blue/BLUE Greece Armor (Mr Nobody).miz new file mode 100644 index 0000000..e3a6485 Binary files /dev/null and b/Generator/Forces/blue/BLUE Greece Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/blue/BLUE Iran Armor (Mr Nobody).miz b/Generator/Forces/blue/BLUE Iran Armor (Mr Nobody).miz new file mode 100644 index 0000000..d9da8ed Binary files /dev/null and b/Generator/Forces/blue/BLUE Iran Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/blue/BLUE Turkey Armor (Mr Nobody).miz b/Generator/Forces/blue/BLUE Turkey Armor (Mr Nobody).miz new file mode 100644 index 0000000..8f2ee4d Binary files /dev/null and b/Generator/Forces/blue/BLUE Turkey Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/blue/BLUE UK Armor (Mr Nobody).miz b/Generator/Forces/blue/BLUE UK Armor (Mr Nobody).miz new file mode 100644 index 0000000..5a88e7d Binary files /dev/null and b/Generator/Forces/blue/BLUE UK Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/blue/BLUE US 1970s Armor & Infantry (Mr Nobody).miz b/Generator/Forces/blue/BLUE US 1970s Armor & Infantry (Mr Nobody).miz new file mode 100644 index 0000000..c5fe727 Binary files /dev/null and b/Generator/Forces/blue/BLUE US 1970s Armor & Infantry (Mr Nobody).miz differ diff --git a/Generator/Forces/red/RED Armor (Hard).miz b/Generator/Forces/red/RED Default Armor (HARD).miz similarity index 100% rename from Generator/Forces/red/RED Armor (Hard).miz rename to Generator/Forces/red/RED Default Armor (HARD).miz diff --git a/Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz b/Generator/Forces/red/RED Default Armor, Infantry & Artillery (MED).miz similarity index 100% rename from Generator/Forces/red/RED Armor, Infantry & Artillery (Med).miz rename to Generator/Forces/red/RED Default Armor, Infantry & Artillery (MED).miz diff --git a/Generator/Forces/red/RED Trucks & Infantry (Easy).miz b/Generator/Forces/red/RED Default Trucks & Infantry (EASY).miz similarity index 100% rename from Generator/Forces/red/RED Trucks & Infantry (Easy).miz rename to Generator/Forces/red/RED Default Trucks & Infantry (EASY).miz diff --git a/Generator/Forces/red/RED Greece Armor (Mr Nobody).miz b/Generator/Forces/red/RED Greece Armor (Mr Nobody).miz new file mode 100644 index 0000000..7fa5bbb Binary files /dev/null and b/Generator/Forces/red/RED Greece Armor (Mr Nobody).miz differ diff --git a/Generator/Forces/red/RED Iran Armor & Infantry (Mr Nobody).miz b/Generator/Forces/red/RED Iran Armor & Infantry (Mr Nobody).miz new file mode 100644 index 0000000..301eba9 Binary files /dev/null and b/Generator/Forces/red/RED Iran Armor & Infantry (Mr Nobody).miz differ diff --git a/Generator/Imports/FARP_DEFAULT_ZONE.miz b/Generator/Imports/FARP_DEFAULT_ZONE.miz new file mode 100644 index 0000000..96bfe5a Binary files /dev/null and b/Generator/Imports/FARP_DEFAULT_ZONE.miz differ diff --git a/Generator/Imports/How to use imports.txt b/Generator/Imports/How to use imports.txt index 413eb51..5634805 100644 --- a/Generator/Imports/How to use imports.txt +++ b/Generator/Imports/How to use imports.txt @@ -1,8 +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. +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]" -Tip: You can change the heading of the imported group by changing the heading of the insertion object. +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'. + diff --git a/Generator/Imports/STAGING_LOGISITIC_HUB.miz b/Generator/Imports/STAGING_LOGISITIC_HUB.miz new file mode 100644 index 0000000..b0497b9 Binary files /dev/null and b/Generator/Imports/STAGING_LOGISITIC_HUB.miz differ diff --git a/Generator/MissionGenerator.py b/Generator/MissionGenerator.py index dd9829a..42bb74d 100644 --- a/Generator/MissionGenerator.py +++ b/Generator/MissionGenerator.py @@ -29,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_() @@ -77,8 +77,6 @@ class Window(QMainWindow, Ui_MainWindow): self.version_label.setText("Version " + version_string) - self.prefs = None # holds json from scenario preference files - def connectSignalsSlots(self): self.action_generateMission.triggered.connect(self.generateMissionAction) @@ -122,21 +120,21 @@ class Window(QMainWindow, Ui_MainWindow): self.red_forces_label.setText(defenders_text) self.blue_forces_label.setText(attackers_text) - self.applyScenarioPrefs() + self.applyScenarioConfig() - def loadScenarioPrefs(self, filename): + def loadScenarioConfig(self, filename): try: j = open(filename) - prefs = json.load(j) + config = json.load(j) j.close() - return prefs + return config except: return None def lockedSlot(self): return self.slot_template_comboBox.findText("Locked to Scenario") - def clearScenarioPrefs(self): + def clearScenarioConfig(self): # reset default states self.defense_checkBox.setEnabled(True) if self.lockedSlot(): @@ -145,16 +143,19 @@ class Window(QMainWindow, Ui_MainWindow): self.slot_template_comboBox.setEnabled(True) self.slot_template_comboBox.setCurrentIndex(0) - def applyScenarioPrefs(self): + def applyScenarioConfig(self): - if self.prefs['defense']['allowed'] == False: + if not self.config: + return + + if self.config['defense']['allowed'] == False: self.defense_checkBox.setChecked(False) self.defense_checkBox.setEnabled(False) - elif self.prefs['offense']['allowed'] == False: + elif self.config['offense']['allowed'] == False: self.defense_checkBox.setChecked(True) self.defense_checkBox.setEnabled(False) - if self.prefs['defense']['player_spawn'] == "fixed": + 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) @@ -180,11 +181,12 @@ class Window(QMainWindow, Ui_MainWindow): friendly_airports = True enemy_airports = True - self.clearScenarioPrefs() - prefs_filename = filename.removesuffix(".miz") + ".json" - self.prefs = self.loadScenarioPrefs(prefs_filename) - if self.prefs: - self.applyScenarioPrefs() + 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: diff --git a/Generator/RotorOpsConflict.py b/Generator/RotorOpsConflict.py new file mode 100644 index 0000000..2b83529 --- /dev/null +++ b/Generator/RotorOpsConflict.py @@ -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) \ No newline at end of file diff --git a/Generator/RotorOpsImport.py b/Generator/RotorOpsImport.py new file mode 100644 index 0000000..4187174 --- /dev/null +++ b/Generator/RotorOpsImport.py @@ -0,0 +1,234 @@ +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.") + + 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 \ No newline at end of file diff --git a/Generator/RotorOpsMission.py b/Generator/RotorOpsMission.py index 1b444f8..9c6a546 100644 --- a/Generator/RotorOpsMission.py +++ b/Generator/RotorOpsMission.py @@ -7,6 +7,8 @@ import random import RotorOpsGroups import RotorOpsUnits import RotorOpsUtils +import RotorOpsConflict +from RotorOpsImport import ImportObjects import time from MissionGenerator import logger @@ -32,6 +34,7 @@ class RotorOpsMission: 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): @@ -44,6 +47,9 @@ class RotorOpsMission: 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 @@ -125,7 +131,10 @@ class RotorOpsMission: self.importObjects() - if not self.m.country(jtf_red) or not self.m.country(jtf_blue): + #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} @@ -135,6 +144,8 @@ 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') @@ -168,16 +179,45 @@ 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(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(jtf_blue), - self.m.country(jtf_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( @@ -206,9 +246,24 @@ class RotorOpsMission: #add logistics sites if options["crates"] and zone_name in self.staging_zones: - RotorOpsGroups.VehicleTemplate.CombinedJointTaskForcesBlue.logistics_site(self.m, self.m.country(jtf_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_LOGISITIC_HUB.miz") + i.anchorByGroupName("ANCHOR") + i.copyAll(self.m, jtf_blue, "Staging Logistics Zone", + staging_position, staging_heading) + + + @@ -239,7 +294,7 @@ 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) # test adding static objects from a .miz #self.addStatics() @@ -705,167 +760,34 @@ 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(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(self.m.country(jtf_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(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(self.m.country(jtf_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) - #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) - - # - # def addStatics(self): - # os.chdir(self.home_dir + "/Generator/Statics") - # logger.info("Looking for .miz files in '" + os.getcwd()) - # dest_point = self.conflict_zones["ALPHA"].position - # grps = RotorOpsUtils.extractUnits.toPoint("test.miz", dest_point, 180) - # for grp in grps: - # self.m.country(jtf_blue).add_vehicle_group(grp) def importObjects(self): os.chdir(self.imports_dir) logger.info("Looking for import .miz files in '" + os.getcwd()) - for group in self.m.country(jtf_blue).static_group: - prefix = "IMPORT-" - if group.name.find(prefix) == 0: - filename = group.name.removeprefix(prefix) + ".miz" - i = RotorOpsUtils.ImportObjects(filename) - i.anchorByGroupName("ANCHOR") - i.copyTo(self.m, group.units[0].name, group.units[0].position, group.units[0].heading) + + 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) + + 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) + diff --git a/Generator/RotorOpsUtils.py b/Generator/RotorOpsUtils.py index ad1a6f2..d78ee69 100644 --- a/Generator/RotorOpsUtils.py +++ b/Generator/RotorOpsUtils.py @@ -18,135 +18,165 @@ def convertMeterToNM(meters=int): return nm - - -class ImportObjects: - - def __init__(self, mizfile, source_point=None, source_heading=0): - 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_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": - 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) - - - 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(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(country_name), - group.name, - temp, - group.units[0].position, - group.units[0].heading, - hidden=False) - - elif index == 1: # Vehicles - - for i, unit in enumerate(group.units): - if i == 0: - ng = mission.vehicle_group(mission.country(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(country_name).add_vehicle_group(ng) - - - elif index == 2: # Helicopters - - if group.units[0].skill == dcs.unit.Skill.Client or group.units[0].skill == dcs.unit.Skill.Player: - - 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(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 - - 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 \ No newline at end of file +# +# +# 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 \ No newline at end of file diff --git a/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz b/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz index e3734cf..d653c7c 100644 Binary files a/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz and b/Generator/Scenarios/Caucasus Conflict - Batumi to Kobuleti (GRIMM).miz differ diff --git a/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz b/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz index 8f0b814..45bbf50 100644 Binary files a/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz and b/Generator/Scenarios/Mariana Conflict - Anderson to Won Pat (GRIMM).miz differ diff --git a/Generator/Scenarios/Mariana Conflict - Rota Landing (Mr Nobody).miz b/Generator/Scenarios/Mariana Conflict - Rota Landing (Mr Nobody).miz index 8d032c6..5f411b0 100644 Binary files a/Generator/Scenarios/Mariana Conflict - Rota Landing (Mr Nobody).miz and b/Generator/Scenarios/Mariana Conflict - Rota Landing (Mr Nobody).miz differ diff --git a/Generator/Scenarios/PG Conflict - Dubai Tour (GRIMM).miz b/Generator/Scenarios/PG Conflict - Dubai Tour (GRIMM).miz index 39550a1..440ef08 100644 Binary files a/Generator/Scenarios/PG Conflict - Dubai Tour (GRIMM).miz and b/Generator/Scenarios/PG Conflict - Dubai Tour (GRIMM).miz differ diff --git a/Generator/Scenarios/PG Conflict - Musandam Valley (Mr Nobody).miz b/Generator/Scenarios/PG Conflict - Musandam Valley (Mr Nobody).miz new file mode 100644 index 0000000..9ca861a Binary files /dev/null and b/Generator/Scenarios/PG Conflict - Musandam Valley (Mr Nobody).miz differ diff --git a/Generator/Scenarios/Syria Conflict - Mount Olympus (Mr Nobody).miz b/Generator/Scenarios/Syria Conflict - Mount Olympus (Mr Nobody).miz new file mode 100644 index 0000000..861b46d Binary files /dev/null and b/Generator/Scenarios/Syria Conflict - Mount Olympus (Mr Nobody).miz differ diff --git a/Generator/Scenarios/_How to create your own scenarios.txt b/Generator/Scenarios/_How to create your own scenarios.txt index fa6dbc3..c06af51 100644 --- a/Generator/Scenarios/_How to create your own scenarios.txt +++ b/Generator/Scenarios/_How to create your own scenarios.txt @@ -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.