diff --git a/game/operation/operation.py b/game/operation/operation.py index ecc82e51..66eddb78 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -14,7 +14,7 @@ from dcs.translation import String from dcs.triggers import TriggerStart from dcs.unittype import UnitType -from gen import Conflict, VisualGenerator +from gen import Conflict, VisualGenerator, FlightType from gen.aircraft import AIRCRAFT_DATA, AircraftConflictGenerator, FlightData from gen.airfields import AIRFIELD_DATA from gen.airsupportgen import AirSupport, AirSupportConflictGenerator @@ -259,6 +259,181 @@ class Operation: 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) + + kneeboard_generator = KneeboardGenerator(self.current_mission) + for dynamic_runway in groundobjectgen.runways.values(): + self.briefinggen.add_dynamic_runway(dynamic_runway) + + for tanker in airsupportgen.air_support.tankers: + self.briefinggen.add_tanker(tanker) + kneeboard_generator.add_tanker(tanker) + 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: + self.briefinggen.add_awacs(awacs) + kneeboard_generator.add_awacs(awacs) + luaData["AWACs"][awacs.callsign] = { + "dcsGroupName": awacs.dcsGroupName, + "callsign": awacs.callsign, + "radio": awacs.freq.mhz + } + + for jtac in jtacs: + self.briefinggen.add_jtac(jtac) + kneeboard_generator.add_jtac(jtac) + 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: + self.briefinggen.add_flight(flight) + kneeboard_generator.add_flight(flight) + if flight.friendly and flight.flight_type in [FlightType.ANTISHIP, FlightType.DEAD, FlightType.SEAD, FlightType.STRIKE]: + flightType = flight.flight_type.name + flightTarget = flight.targetPoint + 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} + } + + + self.briefinggen.generate() + kneeboard_generator.generate() + + + # 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 +""" + # 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 listOfPluginsScripts = [] plugin_file_path = Path("./resources/scripts/plugins/__plugins.lst") @@ -296,37 +471,6 @@ class Operation: 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") diff --git a/gen/aircraft.py b/gen/aircraft.py index cbb028fe..08491d42 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -238,11 +238,14 @@ class FlightData: #: Map of radio frequencies to their assigned radio and channel, if any. frequency_to_channel_map: Dict[RadioFrequency, ChannelAssignment] + #: Data concerning the target of a CAS/Strike/SEAD flight, or None else + targetPoint = None + def __init__(self, flight_type: FlightType, units: List[FlyingUnit], size: int, friendly: bool, departure_delay: int, departure: RunwayData, arrival: RunwayData, divert: Optional[RunwayData], waypoints: List[FlightWaypoint], - intra_flight_channel: RadioFrequency) -> None: + intra_flight_channel: RadioFrequency, targetPoint: Optional) -> None: self.flight_type = flight_type self.units = units self.size = size @@ -255,6 +258,7 @@ class FlightData: self.intra_flight_channel = intra_flight_channel self.frequency_to_channel_map = {} self.callsign = create_group_callsign_from_unit(self.units[0]) + self.targetPoint = targetPoint @property def client_units(self) -> List[FlyingUnit]: @@ -779,7 +783,8 @@ class AircraftConflictGenerator: divert=None, # Waypoints are added later, after they've had their TOTs set. waypoints=[], - intra_flight_channel=channel + intra_flight_channel=channel, + targetPoint=flight.targetPoint, )) # Special case so Su 33 carrier take off diff --git a/gen/airsupportgen.py b/gen/airsupportgen.py index 8a98dba7..97aeea1f 100644 --- a/gen/airsupportgen.py +++ b/gen/airsupportgen.py @@ -30,6 +30,7 @@ AWACS_ALT = 13000 @dataclass class AwacsInfo: """AWACS information for the kneeboard.""" + dcsGroupName: str callsign: str freq: RadioFrequency @@ -37,6 +38,7 @@ class AwacsInfo: @dataclass class TankerInfo: """Tanker information for the kneeboard.""" + dcsGroupName: str callsign: str variant: str freq: RadioFrequency @@ -116,7 +118,7 @@ class AirSupportConflictGenerator: tanker_group.points[0].tasks.append(SetInvisibleCommand(True)) tanker_group.points[0].tasks.append(SetImmortalCommand(True)) - self.air_support.tankers.append(TankerInfo(callsign, variant, freq, tacan)) + self.air_support.tankers.append(TankerInfo(str(tanker_group.name), callsign, variant, freq, tacan)) if is_awacs_enabled: try: @@ -138,6 +140,6 @@ class AirSupportConflictGenerator: awacs_flight.points[0].tasks.append(SetImmortalCommand(True)) self.air_support.awacs.append(AwacsInfo( - callsign_for_support_unit(awacs_flight), freq)) + str(awacs_flight.name), callsign_for_support_unit(awacs_flight), freq)) except: print("No AWACS for faction") \ No newline at end of file diff --git a/gen/armor.py b/gen/armor.py index 426dc05a..b6133b6b 100644 --- a/gen/armor.py +++ b/gen/armor.py @@ -54,6 +54,7 @@ RANDOM_OFFSET_ATTACK = 250 @dataclass(frozen=True) class JtacInfo: """JTAC information.""" + dcsGroupName: str unit_name: str callsign: str region: str @@ -158,7 +159,7 @@ class GroundConflictGenerator: frontline = f"Frontline {self.conflict.from_cp.name}/{self.conflict.to_cp.name}" # Note: Will need to change if we ever add ground based JTAC. callsign = callsign_for_support_unit(jtac) - self.jtacs.append(JtacInfo(n, callsign, frontline, str(code))) + self.jtacs.append(JtacInfo(str(jtac.name), n, callsign, frontline, str(code))) def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading): diff --git a/gen/flights/ai_flight_planner.py b/gen/flights/ai_flight_planner.py index 09be3773..561f359c 100644 --- a/gen/flights/ai_flight_planner.py +++ b/gen/flights/ai_flight_planner.py @@ -205,6 +205,7 @@ class PackageBuilder: airfield, aircraft = assignment flight = Flight(aircraft, plan.num_aircraft, airfield, plan.task) self.package.add_flight(flight) + flight.targetPoint = location return True def build(self) -> Package: @@ -217,7 +218,7 @@ class PackageBuilder: for flight in flights: self.global_inventory.return_from_flight(flight) self.package.remove_flight(flight) - + flight.targetPoint = None class ObjectiveFinder: """Identifies potential objectives for the mission planner.""" diff --git a/gen/flights/flight.py b/gen/flights/flight.py index 0c972723..cef0987d 100644 --- a/gen/flights/flight.py +++ b/gen/flights/flight.py @@ -132,6 +132,7 @@ class Flight: preset_loadout_name = "" start_type = "Runway" group = False # Contains DCS Mission group data after mission has been generated + targetPoint = None # Contains either None or a Strike/SEAD target point location # How long before this flight should take off scheduled_in = 0