import random import math from .conflictgen import * from .naming import * from dcs.mission import * DISTANCE_FACTOR = 0.5, 1 EXTRA_AA_MIN_DISTANCE = 50000 EXTRA_AA_MAX_DISTANCE = 150000 EXTRA_AA_POSITION_FROM_CP = 550 def determine_positions(position, heading, num_units, launcher_distance, coverage=90): """ Given a position on the map, array a group of units in a circle a uniform distance from the unit :param position: position of the center unit :param heading: the direction the units should be arranged toward if coverage is not 360 :param num_units: number of units to play on the circle :param launcher_distance: distance the units should be from the center unit :param coverage: 0-360 :return: list of tuples representing each unit location [(pos_x, pos_y, heading), ...] """ if coverage == 360: # one of the positions is shared :'( outer_offset = coverage / num_units else: outer_offset = coverage / (num_units - 1) positions = [] if num_units % 2 == 0: current_offset = heading - ((coverage / (num_units - 1)) / 2) else: current_offset = heading current_offset -= outer_offset * (math.ceil(num_units / 2) - 1) for x in range(1, num_units + 1): positions.append(( position.x + launcher_distance * math.cos(math.radians(current_offset)), position.y + launcher_distance * math.sin(math.radians(current_offset)), current_offset, )) current_offset += outer_offset return positions def aaa_vehicle_group(self, country, name, _type: unittype.VehicleType, position: mapping.Point, heading=0, formation=unitgroup.VehicleGroup.Formation.Line, move_formation: PointAction=PointAction.OffRoad): """ Override the default vehicle group so that our group can contain a mix of units (which is required for advanced SAM sites) For further docstrings, see the built-in function """ vg = unitgroup.VehicleGroup(self.next_group_id(), self.string(name)) heading = randint(0, 359) if _type == AirDefence.SAM_SA_3_S_125_LN_5P73: # 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR num_launchers = 4 # search radar v = self.vehicle( name + " Unit #{nr}".format(nr=1), AirDefence.SAM_SR_P_19, ) v.position.x = position.x v.position.y = position.y v.heading = heading vg.add_unit(v) # track radar v = self.vehicle( name + " Unit #{nr}".format(nr=2), AirDefence.SAM_SA_3_S_125_TR_SNR, ) center_x = position.x + randint(20, 40) center_y = position.y v.position.x = center_x v.position.y = center_y v.heading = heading vg.add_unit(v) plop_positions = determine_positions( position, heading, num_launchers, launcher_distance=100, coverage=180, ) for x in range(0, num_launchers): v = self.vehicle( name + " Unit #{nr}".format(nr=3+x), AirDefence.SAM_SA_3_S_125_LN_5P73, ) v.position.x = plop_positions[x][0] v.position.y = plop_positions[x][1] v.heading = plop_positions[x][2] vg.add_unit(v) elif _type == AirDefence.SAM_SA_6_Kub_LN_2P25: # 6 launchers (360 degree coverage) # 1 S/TR # search/track radar num_launchers = 6 v = self.vehicle( name + " Unit #{nr}".format(nr=1), AirDefence.SAM_SA_6_Kub_STR_9S91, ) v.position.x = position.x v.position.y = position.y v.heading = heading vg.add_unit(v) plop_positions = determine_positions( position, heading, num_launchers, launcher_distance=100, coverage=360, ) for x in range(0, num_launchers): v = self.vehicle( name + " Unit #{nr}".format(nr=1+x), AirDefence.SAM_SA_6_Kub_LN_2P25, ) v.position.x = plop_positions[x][0] v.position.y = plop_positions[x][1] v.heading = plop_positions[x][2] vg.add_unit(v) elif _type == AirDefence.SAM_SA_10_S_300PS_LN_5P85C: # 8 launchers - 4 directions, two in each direction # 1 SR (offset) # 1 TR (center) # search radar num_launchers = 8 v = self.vehicle( name + " Unit #{nr}".format(nr=1), AirDefence.SAM_SA_10_S_300PS_SR_5N66M, ) v.position.x = position.x v.position.y = position.y v.heading = heading vg.add_unit(v) # track radar v = self.vehicle( name + " Unit #{nr}".format(nr=2), AirDefence.SAM_SA_10_S_300PS_TR_30N6, ) center_x = position.x + randint(20, 40) center_y = position.y v.position.x = center_x v.position.y = center_y v.heading = heading vg.add_unit(v) # command center v = self.vehicle( name + " Unit #{nr}".format(nr=3), AirDefence.SAM_SA_10_S_300PS_CP_54K6, ) center_x = position.x + randint(40, 60) center_y = position.y v.position.x = center_x v.position.y = center_y v.heading = heading vg.add_unit(v) plop_positions = determine_positions( position, heading, num_launchers, launcher_distance=150, coverage=360, ) for x in range(0, num_launchers): v = self.vehicle( name + " Unit #{nr}".format(nr=3+x), AirDefence.SAM_SA_10_S_300PS_LN_5P85C, ) v.position.x = plop_positions[x][0] v.position.y = plop_positions[x][1] v.heading = plop_positions[x][2] vg.add_unit(v) elif _type == AirDefence.SAM_SA_10_S_300PS_CP_54K6: # 8 launchers - 4 directions, two in each direction # 1 SR (offset) # 1 TR (center) # search radar num_launchers = 8 v = self.vehicle( name + " Unit #{nr}".format(nr=1), AirDefence.SAM_SA_10_S_300PS_SR_64H6E, ) v.position.x = position.x v.position.y = position.y v.heading = heading vg.add_unit(v) # track radar v = self.vehicle( name + " Unit #{nr}".format(nr=2), AirDefence.SAM_SA_10_S_300PS_TR_30N6, ) center_x = position.x + randint(20, 40) center_y = position.y v.position.x = center_x v.position.y = center_y v.heading = heading vg.add_unit(v) # command center v = self.vehicle( name + " Unit #{nr}".format(nr=3), AirDefence.SAM_SA_10_S_300PS_CP_54K6, ) center_x = position.x + randint(40, 60) center_y = position.y v.position.x = center_x v.position.y = center_y v.heading = heading vg.add_unit(v) plop_positions = determine_positions( position, heading, num_units=num_launchers, launcher_distance=150, coverage=360, ) for x in range(0, num_launchers): v = self.vehicle( name + " Unit #{nr}".format(nr=3+x), AirDefence.SAM_SA_10_S_300PS_LN_5P85D, ) v.position.x = plop_positions[x][0] v.position.y = plop_positions[x][1] v.heading = plop_positions[x][2] vg.add_unit(v) else: v = self.vehicle(name + " Unit #{nr}".format(nr=1), _type) v.position.x = position.x v.position.y = position.y # + (i - 1) * 20 v.heading = heading vg.add_unit(v) wp = vg.add_waypoint(vg.units[0].position, move_formation, 0) wp.ETA_locked = True if _type.eplrs: wp.tasks.append(task.EPLRS(self.next_eplrs("vehicle"))) country.add_vehicle_group(vg) return vg class AAConflictGenerator: def __init__(self, mission: Mission, conflict: Conflict): self.m = mission self.conflict = conflict def generate_at_defenders_location(self, units: db.AirDefenseDict): for unit_type, count in units.items(): for _ in range(count): self.m.vehicle_group( country=self.conflict.defenders_side, name=namegen.next_unit_name(self.conflict.defenders_side, unit_type), _type=unit_type, position=self.conflict.ground_defenders_location.random_point_within(100, 100), group_size=1) def generate(self, units: db.AirDefenseDict): for type, count in units.items(): for _, radial in zip(range(count), self.conflict.radials): distance = randint(self.conflict.size * DISTANCE_FACTOR[0] + 9000, self.conflict.size * DISTANCE_FACTOR[1] + 14000) p = self.conflict.position.point_from_heading(random.choice(self.conflict.radials), distance) self.m.aaa_vehicle_group( country=self.conflict.defenders_side, name=namegen.next_unit_name(self.conflict.defenders_side, type), _type=type, position=p, group_size=1) class ExtraAAConflictGenerator: def __init__(self, mission: Mission, conflict: Conflict, game, player_country: Country, enemy_country: Country): self.mission = mission self.game = game self.conflict = conflict self.player_country = player_country self.enemy_country = enemy_country def generate(self): from theater.conflicttheater import ControlPoint for cp in self.game.theater.controlpoints: if cp.is_global: continue if cp.position.distance_to_point(self.conflict.position) < EXTRA_AA_MIN_DISTANCE: continue if cp.position.distance_to_point(self.conflict.from_cp.position) < EXTRA_AA_MIN_DISTANCE: continue if cp.position.distance_to_point(self.conflict.to_cp.position) < EXTRA_AA_MIN_DISTANCE: continue if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MAX_DISTANCE: continue country_name = cp.captured and self.player_country or self.enemy_country position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP) self.mission.vehicle_group( country=self.mission.country(country_name), name=namegen.next_basedefense_name(), _type=db.EXTRA_AA[country_name], position=position, group_size=1 )