def _create_radio_registry(cls, unique_map_frequencies: Set[RadioFrequency]) -> None: cls.radio_registry = RadioRegistry() for data in AIRFIELD_DATA.values(): if data.theater == cls.game.theater.terrain.name and data.atc: unique_map_frequencies.add(data.atc.hf) unique_map_frequencies.add(data.atc.vhf_fm) unique_map_frequencies.add(data.atc.vhf_am) unique_map_frequencies.add(data.atc.uhf)
def generate(self): # Dedup beacon/radio frequencies, since some maps have some frequencies # used multiple times. beacons = load_beacons_for_terrain(self.game.theater.terrain.name) unique_map_frequencies: Set[RadioFrequency] = set() for beacon in beacons: unique_map_frequencies.add(beacon.frequency) if beacon.is_tacan: if beacon.channel is None: logging.error( f"TACAN beacon has no channel: {beacon.callsign}") else: self.tacan_registry.reserve(beacon.tacan_channel) for airfield, data in AIRFIELD_DATA.items(): if data.theater == self.game.theater.terrain.name: unique_map_frequencies.add(data.atc.hf) unique_map_frequencies.add(data.atc.vhf_fm) unique_map_frequencies.add(data.atc.vhf_am) unique_map_frequencies.add(data.atc.uhf) # No need to reserve ILS or TACAN because those are in the # beacon list. for frequency in unique_map_frequencies: self.radio_registry.reserve(frequency) # Generate meteo if self.environment_settings is None: self.environment_settings = self.envgen.generate() else: self.envgen.load(self.environment_settings) # Generate ground object first self.groundobjectgen.generate() # Generate destroyed units for d in self.game.get_destroyed_units(): try: utype = db.unit_type_from_name(d["type"]) except KeyError: continue pos = Point(d["x"], d["z"]) if utype is not None and not self.game.position_culled( pos) and self.game.settings.perf_destroyed_units: self.current_mission.static_group( country=self.current_mission.country( self.game.player_country), name="", _type=utype, hidden=True, position=pos, heading=d["orientation"], dead=True, ) # Air Support (Tanker & Awacs) self.airsupportgen.generate(self.is_awacs_enabled) # Generate Activity on the map for cp in self.game.theater.controlpoints: side = cp.captured if side: country = self.current_mission.country( self.game.player_country) else: country = self.current_mission.country(self.game.enemy_country) if cp.id in self.game.planners.keys(): self.airgen.generate_flights(cp, country, self.game.planners[cp.id], self.groundobjectgen.runways) # Generate ground units on frontline everywhere jtacs: List[JtacInfo] = [] for player_cp, enemy_cp in self.game.theater.conflicts(True): conflict = Conflict.frontline_cas_conflict( self.attacker_name, self.defender_name, self.current_mission.country(self.attacker_country), self.current_mission.country(self.defender_country), player_cp, enemy_cp, self.game.theater) # Generate frontline ops player_gp = self.game.ground_planners[player_cp.id].units_per_cp[ enemy_cp.id] enemy_gp = self.game.ground_planners[enemy_cp.id].units_per_cp[ player_cp.id] groundConflictGen = GroundConflictGenerator( self.current_mission, conflict, self.game, player_gp, enemy_gp, player_cp.stances[enemy_cp.id]) groundConflictGen.generate() jtacs.extend(groundConflictGen.jtacs) # Setup combined arms parameters self.current_mission.groundControl.pilot_can_control_vehicles = self.ca_slots > 0 if self.game.player_country in [ country.name for country in self.current_mission.coalition["blue"].countries.values() ]: self.current_mission.groundControl.blue_tactical_commander = self.ca_slots else: self.current_mission.groundControl.red_tactical_commander = self.ca_slots # Triggers if self.game.is_player_attack(self.conflict.attackers_country): cp = self.conflict.from_cp else: cp = self.conflict.to_cp self.triggersgen.generate() # Options self.forcedoptionsgen.generate() # Generate Visuals Smoke Effects if self.game.settings.perf_smoke_gen: self.visualgen.generate() # Inject Plugins Lua Scripts listOfPluginsScripts = [] plugin_file_path = Path("./resources/scripts/plugins/__plugins.lst") if plugin_file_path.exists(): for line in plugin_file_path.read_text().splitlines(): name = line.strip() if not name.startswith('#'): trigger = TriggerStart(comment="Load " + name) listOfPluginsScripts.append(name) fileref = self.current_mission.map_resource.add_resource_file( "./resources/scripts/plugins/" + name) trigger.add_action(DoScriptFile(fileref)) self.current_mission.triggerrules.triggers.append(trigger) else: logging.info( f"Not loading plugins, {plugin_file_path} does not exist") # Inject Mist Script if not done already in the plugins if not "mist.lua" in listOfPluginsScripts and not "mist_4_3_74.lua" in listOfPluginsScripts: # don't load the script twice trigger = TriggerStart(comment="Load Mist Lua framework") fileref = self.current_mission.map_resource.add_resource_file( "./resources/scripts/mist_4_3_74.lua") trigger.add_action(DoScriptFile(fileref)) self.current_mission.triggerrules.triggers.append(trigger) # Inject JSON library if not done already in the plugins if not "json.lua" in listOfPluginsScripts: # don't load the script twice trigger = TriggerStart(comment="Load JSON Lua library") fileref = self.current_mission.map_resource.add_resource_file( "./resources/scripts/json.lua") trigger.add_action(DoScriptFile(fileref)) self.current_mission.triggerrules.triggers.append(trigger) # Inject Ciribob's JTACAutoLase if not done already in the plugins if not "JTACAutoLase.lua" in listOfPluginsScripts: # don't load the script twice trigger = TriggerStart(comment="Load JTACAutoLase.lua script") fileref = self.current_mission.map_resource.add_resource_file( "./resources/scripts/JTACAutoLase.lua") trigger.add_action(DoScriptFile(fileref)) self.current_mission.triggerrules.triggers.append(trigger) # set a LUA table with data from Liberation that we want to set # at the moment it contains Liberation's install path, and an overridable definition for the JTACAutoLase function # later, we'll add data about the units and points having been generated, in order to facilitate the configuration of the plugin lua scripts state_location = "[[" + os.path.abspath("state.json") + "]]" lua = """ -- setting configuration table env.info("DCSLiberation|: setting configuration table") -- all data in this table is overridable. dcsLiberation = {} -- the base location for state.json; if non-existent, it'll be replaced with LIBERATION_EXPORT_DIR, TEMP, or DCS working directory dcsLiberation.installPath=""" + state_location + """ -- you can override dcsLiberation.JTACAutoLase to make it use your own function ; it will be called with these parameters : ({jtac.unit_name}, {jtac.code}, {smoke}, 'vehicle') for all JTACs if ctld then dcsLiberation.JTACAutoLase=ctld.JTACAutoLase elseif JTACAutoLase then dcsLiberation.JTACAutoLase=JTACAutoLase end -- later, we'll add more data to the table --dcsLiberation.POIs = {} --dcsLiberation.BASEs = {} --dcsLiberation.JTACs = {} """ trigger = TriggerStart(comment="Set DCS Liberation data") trigger.add_action(DoScript(String(lua))) self.current_mission.triggerrules.triggers.append(trigger) # Inject DCS-Liberation script if not done already in the plugins if not "dcs_liberation.lua" in listOfPluginsScripts: # don't load the script twice trigger = TriggerStart(comment="Load DCS Liberation script") fileref = self.current_mission.map_resource.add_resource_file( "./resources/scripts/dcs_liberation.lua") trigger.add_action(DoScriptFile(fileref)) self.current_mission.triggerrules.triggers.append(trigger) # add a configuration for JTACAutoLase and start lasing for all JTACs smoke = "true" if hasattr(self.game.settings, "jtac_smoke_on"): if not self.game.settings.jtac_smoke_on: smoke = "false" lua = """ -- setting and starting JTACs env.info("DCSLiberation|: setting and starting JTACs") """ for jtac in jtacs: lua += f"if dcsLiberation.JTACAutoLase then dcsLiberation.JTACAutoLase('{jtac.unit_name}', {jtac.code}, {smoke}, 'vehicle') end\n" trigger = TriggerStart(comment="Start JTACs") trigger.add_action(DoScript(String(lua))) self.current_mission.triggerrules.triggers.append(trigger) self.assign_channels_to_flights() kneeboard_generator = KneeboardGenerator(self.current_mission) for dynamic_runway in self.groundobjectgen.runways.values(): self.briefinggen.add_dynamic_runway(dynamic_runway) for tanker in self.airsupportgen.air_support.tankers: self.briefinggen.add_tanker(tanker) kneeboard_generator.add_tanker(tanker) if self.is_awacs_enabled: for awacs in self.airsupportgen.air_support.awacs: self.briefinggen.add_awacs(awacs) kneeboard_generator.add_awacs(awacs) for jtac in jtacs: self.briefinggen.add_jtac(jtac) kneeboard_generator.add_jtac(jtac) for flight in self.airgen.flights: self.briefinggen.add_flight(flight) kneeboard_generator.add_flight(flight) self.briefinggen.generate() kneeboard_generator.generate()
def generate(self): radio_registry = RadioRegistry() tacan_registry = TacanRegistry() # Dedup beacon/radio frequencies, since some maps have some frequencies # used multiple times. beacons = load_beacons_for_terrain(self.game.theater.terrain.name) unique_map_frequencies: Set[RadioFrequency] = set() for beacon in beacons: unique_map_frequencies.add(beacon.frequency) if beacon.is_tacan: if beacon.channel is None: logging.error( f"TACAN beacon has no channel: {beacon.callsign}") else: tacan_registry.reserve(beacon.tacan_channel) for airfield, data in AIRFIELD_DATA.items(): if data.theater == self.game.theater.terrain.name: unique_map_frequencies.add(data.atc.hf) unique_map_frequencies.add(data.atc.vhf_fm) unique_map_frequencies.add(data.atc.vhf_am) unique_map_frequencies.add(data.atc.uhf) # No need to reserve ILS or TACAN because those are in the # beacon list. for frequency in unique_map_frequencies: radio_registry.reserve(frequency) # Set mission time and weather conditions. EnvironmentGenerator(self.current_mission, self.game.conditions).generate() # Generate ground object first groundobjectgen = GroundObjectsGenerator(self.current_mission, self.conflict, self.game, radio_registry, tacan_registry) groundobjectgen.generate() # Generate destroyed units for d in self.game.get_destroyed_units(): try: utype = db.unit_type_from_name(d["type"]) except KeyError: continue pos = Point(d["x"], d["z"]) if utype is not None and not self.game.position_culled( pos) and self.game.settings.perf_destroyed_units: self.current_mission.static_group( country=self.current_mission.country( self.game.player_country), name="", _type=utype, hidden=True, position=pos, heading=d["orientation"], dead=True, ) # Air Support (Tanker & Awacs) airsupportgen = AirSupportConflictGenerator(self.current_mission, self.conflict, self.game, radio_registry, tacan_registry) airsupportgen.generate(self.is_awacs_enabled) # Generate Activity on the map airgen = AircraftConflictGenerator(self.current_mission, self.conflict, self.game.settings, self.game, radio_registry) airgen.generate_flights( self.current_mission.country(self.game.player_country), self.game.blue_ato, groundobjectgen.runways) airgen.generate_flights( self.current_mission.country(self.game.enemy_country), self.game.red_ato, groundobjectgen.runways) # Generate ground units on frontline everywhere jtacs: List[JtacInfo] = [] for front_line in self.game.theater.conflicts(True): player_cp = front_line.control_point_a enemy_cp = front_line.control_point_b conflict = Conflict.frontline_cas_conflict( self.attacker_name, self.defender_name, self.current_mission.country(self.attacker_country), self.current_mission.country(self.defender_country), player_cp, enemy_cp, self.game.theater) # Generate frontline ops player_gp = self.game.ground_planners[player_cp.id].units_per_cp[ enemy_cp.id] enemy_gp = self.game.ground_planners[enemy_cp.id].units_per_cp[ player_cp.id] groundConflictGen = GroundConflictGenerator( self.current_mission, conflict, self.game, player_gp, enemy_gp, player_cp.stances[enemy_cp.id]) groundConflictGen.generate() jtacs.extend(groundConflictGen.jtacs) # Setup combined arms parameters self.current_mission.groundControl.pilot_can_control_vehicles = self.ca_slots > 0 if self.game.player_country in [ country.name for country in self.current_mission.coalition["blue"].countries.values() ]: self.current_mission.groundControl.blue_tactical_commander = self.ca_slots else: self.current_mission.groundControl.red_tactical_commander = self.ca_slots # Triggers triggersgen = TriggersGenerator(self.current_mission, self.conflict, self.game) triggersgen.generate() # Options forcedoptionsgen = ForcedOptionsGenerator(self.current_mission, self.conflict, self.game) forcedoptionsgen.generate() # Generate Visuals Smoke Effects visualgen = VisualGenerator(self.current_mission, self.conflict, self.game) if self.game.settings.perf_smoke_gen: visualgen.generate() luaData = {} luaData["AircraftCarriers"] = {} luaData["Tankers"] = {} luaData["AWACs"] = {} luaData["JTACs"] = {} luaData["TargetPoints"] = {} self.assign_channels_to_flights(airgen.flights, airsupportgen.air_support) for tanker in airsupportgen.air_support.tankers: luaData["Tankers"][tanker.callsign] = { "dcsGroupName": tanker.dcsGroupName, "callsign": tanker.callsign, "variant": tanker.variant, "radio": tanker.freq.mhz, "tacan": str(tanker.tacan.number) + tanker.tacan.band.name } if self.is_awacs_enabled: for awacs in airsupportgen.air_support.awacs: luaData["AWACs"][awacs.callsign] = { "dcsGroupName": awacs.dcsGroupName, "callsign": awacs.callsign, "radio": awacs.freq.mhz } for jtac in jtacs: luaData["JTACs"][jtac.callsign] = { "dcsGroupName": jtac.dcsGroupName, "callsign": jtac.callsign, "zone": jtac.region, "dcsUnit": jtac.unit_name, "laserCode": jtac.code } for flight in airgen.flights: if flight.friendly and flight.flight_type in [ FlightType.ANTISHIP, FlightType.DEAD, FlightType.SEAD, FlightType.STRIKE ]: flightType = flight.flight_type.name flightTarget = flight.package.target if flightTarget: flightTargetName = None flightTargetType = None if hasattr(flightTarget, 'obj_name'): flightTargetName = flightTarget.obj_name flightTargetType = flightType + f" TGT ({flightTarget.category})" elif hasattr(flightTarget, 'name'): flightTargetName = flightTarget.name flightTargetType = flightType + " TGT (Airbase)" luaData["TargetPoints"][flightTargetName] = { "name": flightTargetName, "type": flightTargetType, "position": { "x": flightTarget.position.x, "y": flightTarget.position.y } } # set a LUA table with data from Liberation that we want to set # at the moment it contains Liberation's install path, and an overridable definition for the JTACAutoLase function # later, we'll add data about the units and points having been generated, in order to facilitate the configuration of the plugin lua scripts state_location = "[[" + os.path.abspath(".") + "]]" lua = """ -- setting configuration table env.info("DCSLiberation|: setting configuration table") -- all data in this table is overridable. dcsLiberation = {} -- the base location for state.json; if non-existent, it'll be replaced with LIBERATION_EXPORT_DIR, TEMP, or DCS working directory dcsLiberation.installPath=""" + state_location + """ """ # Process the tankers lua += """ -- list the tankers generated by Liberation dcsLiberation.Tankers = { """ for key in luaData["Tankers"]: data = luaData["Tankers"][key] dcsGroupName = data["dcsGroupName"] callsign = data["callsign"] variant = data["variant"] tacan = data["tacan"] radio = data["radio"] lua += f" {{dcsGroupName='{dcsGroupName}', callsign='{callsign}', variant='{variant}', tacan='{tacan}', radio='{radio}' }}, \n" #lua += f" {{name='{dcsGroupName}', description='{callsign} ({variant})', information='Tacan:{tacan} Radio:{radio}' }}, \n" lua += "}" # Process the AWACSes lua += """ -- list the AWACs generated by Liberation dcsLiberation.AWACs = { """ for key in luaData["AWACs"]: data = luaData["AWACs"][key] dcsGroupName = data["dcsGroupName"] callsign = data["callsign"] radio = data["radio"] lua += f" {{dcsGroupName='{dcsGroupName}', callsign='{callsign}', radio='{radio}' }}, \n" #lua += f" {{name='{dcsGroupName}', description='{callsign} (AWACS)', information='Radio:{radio}' }}, \n" lua += "}" # Process the JTACs lua += """ -- list the JTACs generated by Liberation dcsLiberation.JTACs = { """ for key in luaData["JTACs"]: data = luaData["JTACs"][key] dcsGroupName = data["dcsGroupName"] callsign = data["callsign"] zone = data["zone"] laserCode = data["laserCode"] dcsUnit = data["dcsUnit"] lua += f" {{dcsGroupName='{dcsGroupName}', callsign='{callsign}', zone='{zone}', laserCode='{laserCode}', dcsUnit='{dcsUnit}' }}, \n" #lua += f" {{name='{dcsGroupName}', description='JTAC {callsign} ', information='Laser:{laserCode}', jtac={laserCode} }}, \n" lua += "}" # Process the Target Points lua += """ -- list the target points generated by Liberation dcsLiberation.TargetPoints = { """ for key in luaData["TargetPoints"]: data = luaData["TargetPoints"][key] name = data["name"] pointType = data["type"] positionX = data["position"]["x"] positionY = data["position"]["y"] lua += f" {{name='{name}', pointType='{pointType}', positionX='{positionX}', positionY='{positionY}' }}, \n" #lua += f" {{name='{pointType} {name}', point{{x={positionX}, z={positionY} }} }}, \n" lua += "}" lua += """ -- list the airbases generated by Liberation -- dcsLiberation.Airbases = {} -- list the aircraft carriers generated by Liberation -- dcsLiberation.Carriers = {} -- later, we'll add more data to the table """ trigger = TriggerStart(comment="Set DCS Liberation data") trigger.add_action(DoScript(String(lua))) self.current_mission.triggerrules.triggers.append(trigger) # Inject Plugins Lua Scripts and data for plugin in LuaPluginManager.plugins(): if plugin.enabled: plugin.inject_scripts(self) plugin.inject_configuration(self) self.assign_channels_to_flights(airgen.flights, airsupportgen.air_support) self.notify_info_generators(groundobjectgen, airsupportgen, jtacs, airgen)