def _generate_groups( self, groups: List[CombatGroup], frontline_vector: Tuple[Point, int, int], is_player: bool, ) -> List[Tuple[VehicleGroup, CombatGroup]]: """Finds valid positions for planned groups and generates a pydcs group for them""" positioned_groups = [] position, heading, combat_width = frontline_vector spawn_heading = ( int(heading_sum(heading, -90)) if is_player else int(heading_sum(heading, 90)) ) country = self.game.player_country if is_player else self.game.enemy_country for group in groups: if group.role == CombatGroupRole.ARTILLERY: distance_from_frontline = ( self.get_artilery_group_distance_from_frontline(group) ) else: distance_from_frontline = random.randint( DISTANCE_FROM_FRONTLINE[group.role][0], DISTANCE_FROM_FRONTLINE[group.role][1], ) final_position = self.get_valid_position_for_group( position, combat_width, distance_from_frontline, heading, spawn_heading ) if final_position is not None: g = self._generate_group( self.mission.country(country), group.units[0], len(group.units), final_position, distance_from_frontline, heading=opposite_heading(spawn_heading), ) if is_player: g.set_skill(self.game.settings.player_skill) else: g.set_skill(self.game.settings.enemy_vehicle_skill) positioned_groups.append((g, group)) if group.role in [CombatGroupRole.APC, CombatGroupRole.IFV]: self.gen_infantry_group_for_group( g, is_player, self.mission.country(country), opposite_heading(spawn_heading), ) else: logging.warning(f"Unable to get valid position for {group}") return positioned_groups
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int, int]: """ Returns a vector for a valid frontline location avoiding exclusion zones. """ center_position, heading = cls.frontline_position(from_cp, to_cp, theater) left_heading = heading_sum(heading, -90) right_heading = heading_sum(heading, 90) left_position = cls.extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), left_heading, theater) right_position = cls.extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), right_heading, theater) distance = int(left_position.distance_to_point(right_position)) return left_position, right_heading, distance
def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int]: frontline = FrontLine(from_cp, to_cp, theater) attack_heading = frontline.attack_heading position = cls.find_ground_position(frontline.position, FRONTLINE_LENGTH, heading_sum(attack_heading, 90), theater) return position, opposite_heading(attack_heading)
def frontline_position(cls, frontline: FrontLine, theater: ConflictTheater) -> Tuple[Point, int]: attack_heading = int(frontline.attack_heading) position = cls.find_ground_position( frontline.position, FRONTLINE_LENGTH, heading_sum(attack_heading, 90), theater, ) if position is None: raise RuntimeError("Could not find front line position") return position, opposite_heading(attack_heading)
def find_retreat_point(self, dcs_group: VehicleGroup, frontline_heading: int, distance: int = RETREAT_DISTANCE) -> Point: """ Find a point to retreat to :param dcs_group: DCS mission group we are searching a retreat point for :param frontline_heading: Heading of the frontline :return: dcs.mapping.Point object with the desired position """ desired_point = dcs_group.points[0].position.point_from_heading( heading_sum(frontline_heading, +180), distance) if self.conflict.theater.is_on_land(desired_point): return desired_point return self.conflict.theater.nearest_land_pos(desired_point)