Пример #1
0
    def scene_create_lines_for_cp(self, cp: ControlPoint, playerColor, enemyColor):
        scene = self.scene()
        pos = self._transform_point(cp.position)
        for connected_cp in cp.connected_points:
            pos2 = self._transform_point(connected_cp.position)
            if not cp.captured:
                color = CONST.COLORS["dark_"+enemyColor]
            elif cp.captured:
                color = CONST.COLORS["dark_"+playerColor]
            else:
                color = CONST.COLORS["dark_"+enemyColor]

            pen = QPen(brush=color)
            pen.setColor(color)
            pen.setWidth(6)
            if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
                if not cp.captured:
                    scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen)
                else:
                    posx, h = Conflict.frontline_position(self.game.theater, cp, connected_cp)
                    pos2 = self._transform_point(posx)
                    scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen)

                    p1 = point_from_heading(pos2[0], pos2[1], h+180, 25)
                    p2 = point_from_heading(pos2[0], pos2[1], h, 25)
                    frontline_pen = QPen(brush=CONST.COLORS["bright_red"])
                    frontline_pen.setColor(CONST.COLORS["orange"])
                    frontline_pen.setWidth(8)
                    scene.addLine(p1[0], p1[1], p2[0], p2[1], pen=frontline_pen)

            else:
                scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen)
Пример #2
0
 def _generate_ground_conflicts(cls) -> None:
     """For each frontline in the Operation, generate the ground conflicts and JTACs"""
     cls.jtacs = []
     for front_line in cls.game.theater.conflicts():
         player_cp = front_line.blue_cp
         enemy_cp = front_line.red_cp
         conflict = Conflict.frontline_cas_conflict(
             cls.game.player_faction.name,
             cls.game.enemy_faction.name,
             cls.current_mission.country(cls.game.player_country),
             cls.current_mission.country(cls.game.enemy_country),
             front_line,
             cls.game.theater,
         )
         # Generate frontline ops
         player_gp = cls.game.ground_planners[player_cp.id].units_per_cp[
             enemy_cp.id]
         enemy_gp = cls.game.ground_planners[enemy_cp.id].units_per_cp[
             player_cp.id]
         ground_conflict_gen = GroundConflictGenerator(
             cls.current_mission,
             conflict,
             cls.game,
             player_gp,
             enemy_gp,
             player_cp.stances[enemy_cp.id],
             cls.unit_map,
         )
         ground_conflict_gen.generate()
         cls.jtacs.extend(ground_conflict_gen.jtacs)
Пример #3
0
 def conflicts(cls) -> Iterable[Conflict]:
     assert cls.game
     for frontline in cls.game.theater.conflicts():
         yield Conflict(cls.game.theater, frontline.control_point_a,
                        frontline.control_point_b, cls.game.player_name,
                        cls.game.enemy_name, cls.game.player_country,
                        cls.game.enemy_country, frontline.position)
Пример #4
0
    def front_lines(self) -> Iterator[FrontLine]:
        """Iterates over all active front lines in the theater."""
        for cp in self.friendly_control_points():
            for connected in cp.connected_points:
                if connected.is_friendly(self.is_player):
                    continue

                if Conflict.has_frontline_between(cp, connected):
                    yield FrontLine(cp, connected, self.game.theater)
Пример #5
0
 def _frontline_vector(self, from_cp: ControlPoint, to_cp: ControlPoint):
     # Cache mechanism to avoid performing frontline vector computation on every frame
     key = str(from_cp.id) + "_" + str(to_cp.id)
     if key in self.frontline_vector_cache:
         return self.frontline_vector_cache[key]
     else:
         frontline = Conflict.frontline_vector(from_cp, to_cp, self.game.theater)
         self.frontline_vector_cache[key] = frontline
         return frontline
Пример #6
0
    def generate_frontline_cap(self, flight, ally_cp, enemy_cp):
        """
        Generate a cap flight for the frontline between ally_cp and enemy cp in order to ensure air superiority and
        protect friendly CAP airbase
        :param flight: Flight to setup
        :param ally_cp: CP to protect
        :param enemy_cp: Enemy connected cp
        """
        flight.flight_type = FlightType.CAP
        patrol_alt = random.randint(self.doctrine["PATROL_ALT_RANGE"][0],
                                    self.doctrine["PATROL_ALT_RANGE"][1])

        # Find targets waypoints
        ingress, heading, distance = Conflict.frontline_vector(
            ally_cp, enemy_cp, self.game.theater)
        center = ingress.point_from_heading(heading, distance / 2)
        orbit_center = center.point_from_heading(
            heading - 90, random.randint(nm_to_meter(6), nm_to_meter(15)))

        combat_width = distance / 2
        if combat_width > 500000:
            combat_width = 500000
        if combat_width < 35000:
            combat_width = 35000

        radius = combat_width * 1.25
        orbit0p = orbit_center.point_from_heading(heading, radius)
        orbit1p = orbit_center.point_from_heading(heading + 180, radius)

        # Create points
        ascend = self.generate_ascend_point(flight.from_cp)
        flight.points.append(ascend)

        orbit0 = FlightWaypoint(orbit0p.x, orbit0p.y, patrol_alt)
        orbit0.name = "ORBIT 0"
        orbit0.description = "Standby between this point and the next one"
        orbit0.pretty_name = "Race-track start"
        orbit0.waypoint_type = FlightWaypointType.PATROL_TRACK
        flight.points.append(orbit0)

        orbit1 = FlightWaypoint(orbit1p.x, orbit1p.y, patrol_alt)
        orbit1.name = "ORBIT 1"
        orbit1.description = "Standby between this point and the previous one"
        orbit1.pretty_name = "Race-track end"
        orbit1.waypoint_type = FlightWaypointType.PATROL
        flight.points.append(orbit1)

        # Note : Targets of a PATROL TRACK waypoints are the points to be defended
        orbit0.targets.append(flight.from_cp)
        orbit0.targets.append(center)

        descend = self.generate_descend_point(flight.from_cp)
        flight.points.append(descend)

        rtb = self.generate_rtb_waypoint(flight.from_cp)
        flight.points.append(rtb)
Пример #7
0
    def generate_cas(self, flight, from_cp, location):
        """
        Generate a CAS flight at a given location
        :param flight: Flight to setup
        :param location: Location of the CAS targets
        """
        is_helo = hasattr(flight.unit_type,
                          "helicopter") and flight.unit_type.helicopter
        cap_alt = 1000
        flight.points = []
        flight.flight_type = FlightType.CAS

        ingress, heading, distance = Conflict.frontline_vector(
            from_cp, location, self.game.theater)
        center = ingress.point_from_heading(heading, distance / 2)
        egress = ingress.point_from_heading(heading, distance)

        ascend = self.generate_ascend_point(flight.from_cp)
        if is_helo:
            cap_alt = 500
            ascend.alt = 500
        flight.points.append(ascend)

        ingress_point = FlightWaypoint(ingress.x, ingress.y, cap_alt)
        ingress_point.alt_type = "RADIO"
        ingress_point.name = "INGRESS"
        ingress_point.pretty_name = "INGRESS"
        ingress_point.description = "Ingress into CAS area"
        ingress_point.waypoint_type = FlightWaypointType.INGRESS_CAS
        flight.points.append(ingress_point)

        center_point = FlightWaypoint(center.x, center.y, cap_alt)
        center_point.alt_type = "RADIO"
        center_point.description = "Provide CAS"
        center_point.name = "CAS"
        center_point.pretty_name = "CAS"
        center_point.waypoint_type = FlightWaypointType.CAS
        flight.points.append(center_point)

        egress_point = FlightWaypoint(egress.x, egress.y, cap_alt)
        egress_point.alt_type = "RADIO"
        egress_point.description = "Egress from CAS area"
        egress_point.name = "EGRESS"
        egress_point.pretty_name = "EGRESS"
        egress_point.waypoint_type = FlightWaypointType.EGRESS
        flight.points.append(egress_point)

        descend = self.generate_descend_point(flight.from_cp)
        if is_helo:
            descend.alt = 300
        flight.points.append(descend)

        rtb = self.generate_rtb_waypoint(flight.from_cp)
        flight.points.append(rtb)
Пример #8
0
 def air_conflict(cls) -> Conflict:
     assert cls.game
     player_cp, enemy_cp = cls.game.theater.closest_opposing_control_points(
     )
     mid_point = player_cp.position.point_from_heading(
         player_cp.position.heading_between_point(enemy_cp.position),
         player_cp.position.distance_to_point(enemy_cp.position) / 2)
     return Conflict(cls.game.theater, player_cp, enemy_cp,
                     cls.game.player_name, cls.game.enemy_name,
                     cls.game.player_country, cls.game.enemy_country,
                     mid_point)
 def draw_actual_frontline(self, frontline: FrontLine,
                           scene: QGraphicsScene, pen: QPen) -> None:
     self.draw_bezier_frontline(scene, pen, frontline)
     vector = Conflict.frontline_vector(frontline.control_point_a,
                                        frontline.control_point_b,
                                        self.game.theater)
     left_pos = self._transform_point(vector[0])
     right_pos = self._transform_point(vector[0].point_from_heading(
         vector[1], vector[2]))
     scene.addItem(
         QFrontLine(left_pos[0], left_pos[1], right_pos[0], right_pos[1],
                    frontline, self.game_model))
Пример #10
0
    def for_faction(cls, game: Game, player: bool) -> ThreatZones:
        """Generates the threat zones projected by the given coalition.

        Args:
            game: The game to generate the threat zone for.
            player: True if the coalition projecting the threat zone belongs to
            the player.

        Returns:
            The threat zones projected by the given coalition. If the threat
            zone belongs to the player, it is the zone that will be avoided by
            the enemy and vice versa.
        """
        air_threats = []
        air_defenses = []
        for control_point in game.theater.controlpoints:
            if control_point.captured != player:
                continue
            if control_point.runway_is_operational():
                point = ShapelyPoint(control_point.position.x,
                                     control_point.position.y)
                cap_threat_range = cls.barcap_threat_range(game, control_point)
                air_threats.append(point.buffer(cap_threat_range.meters))

            for tgo in control_point.ground_objects:
                for group in tgo.groups:
                    threat_range = tgo.threat_range(group)
                    # Any system with a shorter range than this is not worth
                    # even avoiding.
                    if threat_range > nautical_miles(3):
                        point = ShapelyPoint(tgo.position.x, tgo.position.y)
                        threat_zone = point.buffer(threat_range.meters)
                        air_defenses.append(threat_zone)

        for front_line in game.theater.conflicts(player):
            vector = Conflict.frontline_vector(front_line.control_point_a,
                                               front_line.control_point_b,
                                               game.theater)

            start = vector[0]
            end = vector[0].point_from_heading(vector[1], vector[2])

            line = LineString([
                ShapelyPoint(start.x, start.y),
                ShapelyPoint(end.x, end.y),
            ])
            doctrine = game.faction_for(player).doctrine
            air_threats.append(
                line.buffer(doctrine.cap_engagement_range.meters))

        return cls(airbases=unary_union(air_threats),
                   air_defenses=unary_union(air_defenses))
Пример #11
0
 def air_conflict(cls) -> Conflict:
     assert cls.game
     player_cp, enemy_cp = cls.game.theater.closest_opposing_control_points(
     )
     mid_point = player_cp.position.point_from_heading(
         player_cp.position.heading_between_point(enemy_cp.position),
         player_cp.position.distance_to_point(enemy_cp.position) / 2,
     )
     return Conflict(
         cls.game.theater,
         FrontLine(player_cp, enemy_cp),
         cls.game.player_faction.name,
         cls.game.enemy_faction.name,
         cls.current_mission.country(cls.game.player_country),
         cls.current_mission.country(cls.game.enemy_country),
         mid_point,
     )
 def scene_create_lines_for_cp(self, cp: ControlPoint, playerColor,
                               enemyColor):
     scene = self.scene()
     for connected_cp in cp.connected_points:
         pos2 = self._transform_point(connected_cp.position)
         if not cp.captured:
             color = CONST.COLORS["dark_" + enemyColor]
         else:
             color = CONST.COLORS["dark_" + playerColor]
         pen = QPen(brush=color)
         pen.setColor(color)
         pen.setWidth(6)
         frontline = FrontLine(cp, connected_cp, self.game.theater)
         if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(
                 cp, connected_cp):
             if DisplayOptions.actual_frontline_pos:
                 self.draw_actual_frontline(frontline, scene, pen)
             else:
                 self.draw_frontline_approximation(frontline, scene, pen)
         else:
             self.draw_bezier_frontline(scene, pen, frontline)
    def find_possible_waypoints(self):

        self.wpts = []
        model = QStandardItemModel()
        i = 0

        def add_model_item(i, model, name, wpt):
            item = QStandardItem(name)
            model.setItem(i, 0, item)
            self.wpts.append(wpt)
            return i + 1

        if self.include_frontlines:
            for cp in self.game.theater.controlpoints:
                if cp.captured:
                    enemy_cp = [
                        ecp for ecp in cp.connected_points
                        if ecp.captured != cp.captured
                    ]
                    for ecp in enemy_cp:
                        pos = Conflict.frontline_position(
                            cp, ecp, self.game.theater)[0]
                        wpt = FlightWaypoint(
                            FlightWaypointType.CUSTOM,
                            pos.x,
                            pos.y,
                            Distance.from_meters(800),
                        )
                        wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
                        wpt.alt_type = "RADIO"
                        wpt.pretty_name = wpt.name
                        wpt.description = "Frontline"
                        i = add_model_item(i, model, wpt.pretty_name, wpt)

        if self.include_targets:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy
                        and not cp.captured) or (self.include_friendly
                                                 and cp.captured):
                    for ground_object in cp.ground_objects:
                        if not ground_object.is_dead and isinstance(
                                ground_object, BuildingGroundObject):
                            wpt = FlightWaypoint(
                                FlightWaypointType.CUSTOM,
                                ground_object.position.x,
                                ground_object.position.y,
                                Distance.from_meters(0),
                            )
                            wpt.alt_type = "RADIO"
                            wpt.name = ground_object.waypoint_name
                            wpt.pretty_name = wpt.name
                            wpt.obj_name = ground_object.obj_name
                            wpt.targets.append(ground_object)
                            if cp.captured:
                                wpt.description = "Friendly Building"
                            else:
                                wpt.description = "Enemy Building"
                            i = add_model_item(i, model, wpt.pretty_name, wpt)

        if self.include_units:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy
                        and not cp.captured) or (self.include_friendly
                                                 and cp.captured):
                    for ground_object in cp.ground_objects:
                        if (not ground_object.is_dead
                                and ground_object.dcs_identifier == "AA"):
                            for g in ground_object.groups:
                                for j, u in enumerate(g.units):
                                    wpt = FlightWaypoint(
                                        FlightWaypointType.CUSTOM,
                                        u.position.x,
                                        u.position.y,
                                        Distance.from_meters(0),
                                    )
                                    wpt.alt_type = "RADIO"
                                    wpt.name = wpt.name = (
                                        "[" + str(ground_object.obj_name) +
                                        "] : " + u.type + " #" + str(j))
                                    wpt.pretty_name = wpt.name
                                    wpt.targets.append(u)
                                    wpt.obj_name = ground_object.obj_name
                                    wpt.waypoint_type = FlightWaypointType.CUSTOM
                                    if cp.captured:
                                        wpt.description = "Friendly unit : " + u.type
                                    else:
                                        wpt.description = "Enemy unit : " + u.type
                                    i = add_model_item(i, model,
                                                       wpt.pretty_name, wpt)

        if self.include_airbases:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy
                        and not cp.captured) or (self.include_friendly
                                                 and cp.captured):
                    wpt = FlightWaypoint(
                        FlightWaypointType.CUSTOM,
                        cp.position.x,
                        cp.position.y,
                        Distance.from_meters(0),
                    )
                    wpt.alt_type = "RADIO"
                    wpt.name = cp.name
                    if cp.captured:
                        wpt.description = ("Position of " + cp.name +
                                           " [Friendly Airbase]")
                    else:
                        wpt.description = "Position of " + cp.name + " [Enemy Airbase]"

                    if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
                        wpt.pretty_name = cp.name + " (Aircraft Carrier Group)"
                    elif cp.cptype == ControlPointType.LHA_GROUP:
                        wpt.pretty_name = cp.name + " (LHA Group)"
                    else:
                        wpt.pretty_name = cp.name + " (Airbase)"

                    i = add_model_item(i, model, wpt.pretty_name, wpt)

        self.setModel(model)
    def find_possible_waypoints(self):

        self.wpts = []
        model = QStandardItemModel()
        i = 0

        def add_model_item(i, model, name, wpt):
            print(name)
            item = QStandardItem(name)
            model.setItem(i, 0, item)
            self.wpts.append(wpt)
            return i + 1

        if self.include_frontlines:
            for cp in self.game.theater.controlpoints:
                if cp.captured:
                    enemy_cp = [ecp for ecp in cp.connected_points if ecp.captured != cp.captured]
                    for ecp in enemy_cp:
                        pos = Conflict.frontline_position(self.game.theater, cp, ecp)[0]
                        wpt = FlightWaypoint(
                            FlightWaypointType.CUSTOM,
                            pos.x,
                            pos.y,
                            800)
                        wpt.name = "Frontline " + cp.name + "/" + ecp.name + " [CAS]"
                        wpt.alt_type = "RADIO"
                        wpt.pretty_name = wpt.name
                        wpt.description = "Frontline"
                        wpt.data = [cp, ecp]
                        wpt.category = PredefinedWaypointCategory.FRONTLINE
                        i = add_model_item(i, model, wpt.pretty_name, wpt)

        if self.include_targets:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
                    for ground_object in cp.ground_objects:
                        if not ground_object.is_dead and not ground_object.dcs_identifier == "AA":
                            wpt = FlightWaypoint(
                                FlightWaypointType.CUSTOM,
                                ground_object.position.x,
                                ground_object.position.y,
                                0
                            )
                            wpt.alt_type = "RADIO"
                            wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + ground_object.category + " #" + str(ground_object.object_id)
                            wpt.pretty_name = wpt.name
                            wpt.obj_name = ground_object.obj_name
                            wpt.targets.append(ground_object)
                            wpt.data = ground_object
                            if cp.captured:
                                wpt.description = "Friendly Building"
                                wpt.category = PredefinedWaypointCategory.ALLY_BUILDING
                            else:
                                wpt.description = "Enemy Building"
                                wpt.category = PredefinedWaypointCategory.ENEMY_BUILDING
                            i = add_model_item(i, model, wpt.pretty_name, wpt)

        if self.include_units:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
                    for ground_object in cp.ground_objects:
                        if not ground_object.is_dead and ground_object.dcs_identifier == "AA":
                            for g in ground_object.groups:
                                for j, u in enumerate(g.units):
                                    wpt = FlightWaypoint(
                                        FlightWaypointType.CUSTOM,
                                        u.position.x,
                                        u.position.y,
                                        0
                                    )
                                    wpt.alt_type = "RADIO"
                                    wpt.name = wpt.name = "[" + str(ground_object.obj_name) + "] : " + u.type + " #" + str(j)
                                    wpt.pretty_name = wpt.name
                                    wpt.targets.append(u)
                                    wpt.data = u
                                    wpt.obj_name = ground_object.obj_name
                                    wpt.waypoint_type = FlightWaypointType.CUSTOM
                                    if cp.captured:
                                        wpt.description = "Friendly unit : " + u.type
                                        wpt.category = PredefinedWaypointCategory.ALLY_UNIT
                                    else:
                                        wpt.description = "Enemy unit : " + u.type
                                        wpt.category = PredefinedWaypointCategory.ENEMY_UNIT
                                    i = add_model_item(i, model, wpt.pretty_name, wpt)

        if self.include_airbases:
            for cp in self.game.theater.controlpoints:
                if (self.include_enemy and not cp.captured) or (self.include_friendly and cp.captured):
                    wpt = FlightWaypoint(
                        FlightWaypointType.CUSTOM,
                        cp.position.x,
                        cp.position.y,
                        0
                    )
                    wpt.alt_type = "RADIO"
                    wpt.name = cp.name
                    wpt.data = cp
                    if cp.captured:
                        wpt.description = "Position of " + cp.name + " [Friendly Airbase]"
                        wpt.category = PredefinedWaypointCategory.ALLY_CP
                    else:
                        wpt.description = "Position of " + cp.name + " [Enemy Airbase]"
                        wpt.category = PredefinedWaypointCategory.ENEMY_CP

                    if cp.cptype == ControlPointType.AIRCRAFT_CARRIER_GROUP:
                        wpt.pretty_name = cp.name + " (Aircraft Carrier Group)"
                    elif cp.cptype == ControlPointType.LHA_GROUP:
                        wpt.pretty_name = cp.name + " (LHA Group)"
                    else:
                        wpt.pretty_name = cp.name + " (Airbase)"

                    i = add_model_item(i, model, wpt.pretty_name, wpt)

        self.setModel(model)
Пример #15
0
    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)