diff --git a/gen/aircraft.py b/gen/aircraft.py index 8e2e1687..b9472b00 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -120,10 +120,13 @@ class AircraftConflictGenerator: group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)) if unit_type in helicopters.helicopter_map.values(): - print(unit_type) group.set_frequency(127.5) else: - group.set_frequency(251.0) + if unit_type not in [P_51D_30_NA, P_51D, SpitfireLFMkIX, SpitfireLFMkIXCW, FW_190A8, FW_190D9, Bf_109K_4]: + group.set_frequency(251.0) + else: + # WW2 + group.set_frequency(124.0) def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None, start_type = None) -> FlyingGroup: assert count > 0 diff --git a/qt_ui/uiconstants.py b/qt_ui/uiconstants.py index 12173ea8..532898da 100644 --- a/qt_ui/uiconstants.py +++ b/qt_ui/uiconstants.py @@ -50,6 +50,7 @@ def load_icons(): ICONS["Terrain_Caucasus"] = QPixmap("./resources/ui/terrain_caucasus.gif") ICONS["Terrain_Persian_Gulf"] = QPixmap("./resources/ui/terrain_pg.gif") ICONS["Terrain_Nevada"] = QPixmap("./resources/ui/terrain_nevada.gif") + ICONS["Terrain_Normandy"] = QPixmap("./resources/ui/terrain_normandy.gif") ICONS["Dawn"] = QPixmap("./resources/ui/daytime/dawn.png") ICONS["Day"] = QPixmap("./resources/ui/daytime/day.png") diff --git a/qt_ui/windows/QNewGameWizard.py b/qt_ui/windows/QNewGameWizard.py index 11f9c3fc..6354b79f 100644 --- a/qt_ui/windows/QNewGameWizard.py +++ b/qt_ui/windows/QNewGameWizard.py @@ -7,7 +7,7 @@ from dcs.task import CAP, CAS import qt_ui.uiconstants as CONST from game import db, Game -from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater +from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy from userdata.logging import version_string @@ -36,6 +36,7 @@ class NewGameWizard(QtWidgets.QWizard): isTerrainNttr = self.field("isTerrainNttr") isTerrainCaucasusSmall = self.field("isTerrainCaucasusSmall") isIranianCampaignTheater = self.field("isIranianCampaignTheater") + isTerrainNormandy = self.field("isTerrainNormandy") timePeriod = db.TIME_PERIODS[list(db.TIME_PERIODS.keys())[self.field("timePeriod")]] sams = self.field("sams") midGame = self.field("midGame") @@ -52,6 +53,8 @@ class NewGameWizard(QtWidgets.QWizard): conflicttheater = caucasus.WesternGeorgia() elif isIranianCampaignTheater: conflicttheater = persiangulf.IranianCampaign() + elif isTerrainNormandy: + conflicttheater = normandy.NormandyTheater() else: conflicttheater = caucasus.CaucasusTheater() @@ -212,6 +215,8 @@ class TheaterConfiguration(QtWidgets.QWizardPage): terrainIran.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Persian_Gulf"])) terrainNttr = QtWidgets.QRadioButton("Nevada - Full") terrainNttr.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Nevada"])) + terrainNormandy = QtWidgets.QRadioButton("Normandy") + terrainNormandy.setIcon(QtGui.QIcon(CONST.ICONS["Terrain_Normandy"])) terrainCaucasus.setChecked(True) # Time Period @@ -229,6 +234,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage): self.registerField('isTerrainPg', terrainPg) self.registerField('isIranianCampaignTheater', terrainIran) self.registerField('isTerrainNttr', terrainNttr) + self.registerField('isTerrainNormandy', terrainNormandy) self.registerField('timePeriod', timePeriodSelect) # Build layout @@ -238,6 +244,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage): terrainGroupLayout.addWidget(terrainPg) terrainGroupLayout.addWidget(terrainIran) terrainGroupLayout.addWidget(terrainNttr) + terrainGroupLayout.addWidget(terrainNormandy) terrainGroup.setLayout(terrainGroupLayout) timeGroupLayout = QtWidgets.QGridLayout() diff --git a/resources/ui/terrain_normandy.gif b/resources/ui/terrain_normandy.gif new file mode 100644 index 00000000..33686f05 Binary files /dev/null and b/resources/ui/terrain_normandy.gif differ diff --git a/theater/normandy.py b/theater/normandy.py new file mode 100644 index 00000000..938995c4 --- /dev/null +++ b/theater/normandy.py @@ -0,0 +1,37 @@ +from dcs.terrain import normandy + +from .conflicttheater import * +from .landmap import * + + +class NormandyTheater(ConflictTheater): + terrain = dcs.terrain.Normandy() + overview_image = "normandy.gif" + reference_points = {(normandy.Needs_Oar_Point.position.x, normandy.Needs_Oar_Point.position.y): (-50, -500), + (normandy.Evreux.position.x, normandy.Evreux.position.y): (970, 250)} + landmap = load_landmap("resources\\normandylandmap.p") + daytime_map = { + "dawn": (6, 8), + "day": (10, 17), + "dusk": (17, 18), + "night": (0, 5), + } + + st_pierre = ControlPoint.from_airport(normandy.Saint_Pierre_du_Mont, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM) + maupertus = ControlPoint.from_airport(normandy.Maupertus, LAND, SIZE_SMALL, IMPORTANCE_LOW) + azeville = ControlPoint.from_airport(normandy.Azeville, LAND, SIZE_SMALL, IMPORTANCE_LOW) + lessay = ControlPoint.from_airport(normandy.Lessay, LAND, SIZE_SMALL, IMPORTANCE_LOW) + meautis = ControlPoint.from_airport(normandy.Meautis, LAND, SIZE_SMALL, IMPORTANCE_LOW) + chippelle = ControlPoint.from_airport(normandy.Chippelle, LAND, SIZE_SMALL, IMPORTANCE_LOW) + + def __init__(self): + super(NormandyTheater, self).__init__() + + self.add_controlpoint(self.st_pierre, connected_to=[self.chippelle]) + self.add_controlpoint(self.maupertus, connected_to=[self.azeville]) + self.add_controlpoint(self.azeville, connected_to=[self.meautis, self.maupertus]) + self.add_controlpoint(self.lessay, connected_to=[self.meautis]) + self.add_controlpoint(self.meautis, connected_to=[self.chippelle, self.lessay, self.azeville]) + self.add_controlpoint(self.chippelle, connected_to=[self.st_pierre, self.meautis]) + + self.st_pierre.captured = True diff --git a/theater/start_generator.py b/theater/start_generator.py index a77a2946..55c810a2 100644 --- a/theater/start_generator.py +++ b/theater/start_generator.py @@ -57,89 +57,105 @@ def generate_groundobjects(theater: ConflictTheater, game): with open("resources/groundobject_templates.p", "rb") as f: tpls = pickle.load(f) - def find_location(on_ground, near, theater, min, max, others) -> typing.Optional[Point]: - point = None - for _ in range(1000): - p = near.random_point_within(max, min) - if on_ground and theater.is_on_land(p): - point = p - elif not on_ground and theater.is_in_sea(p): - point = p - - if point: - for angle in range(0, 360, 45): - p = point.point_from_heading(angle, 2500) - if on_ground and not theater.is_on_land(p): - point = None - break - elif not on_ground and not theater.is_in_sea(p): - point = None - break - - - if point: - for other in others: - if other.position.distance_to_point(point) < 10000: - point = None - break - - if point: - return point - - return None - group_id = 0 for cp in theater.controlpoints: + group_id = generate_cp_ground_points(cp, theater, game, group_id, tpls) - # Reset cp ground objects - cp.ground_objects = [] +def find_location(on_ground, near, theater, min, max, others) -> typing.Optional[Point]: + """ + Find a valid ground object location + :param on_ground: Whether it should be on ground or on sea (True = on ground) + :param near: Point + :param theater: Theater object + :param min: Minimal range from point + :param max: Max range from point + :param others: Other already existing ground objects + :return: + """ + point = None + for _ in range(1000): + p = near.random_point_within(max, min) + if on_ground and theater.is_on_land(p): + point = p + elif not on_ground and theater.is_in_sea(p): + point = p - if cp.is_global: - continue + if point: + for angle in range(0, 360, 45): + p = point.point_from_heading(angle, 2500) + if on_ground and not theater.is_on_land(p): + point = None + break + elif not on_ground and not theater.is_in_sea(p): + point = None + break + if point: + for other in others: + if other.position.distance_to_point(point) < 10000: + point = None + break + if point: + return point + return None - if not cp.has_frontline: - continue - amount = random.randrange(1, 11) - for i in range(0, amount): - available_categories = list(tpls) - if i >= amount - 1: - tpl_category = "aa" +def generate_cp_ground_points(cp: ControlPoint, theater, game, group_id, templates): + """ + Generate inital ground objects and AA site for given control point + :param cp: Control point to initialize + :param theater: Theater + :param game: Game object + :param group_id: Group id + :param templates: Ground object templates + :return: True if something was generated + """ + # Reset cp ground objects + cp.ground_objects = [] + + if cp.is_global: + return False + + amount = random.randrange(1, 11) + for i in range(0, amount): + available_categories = list(templates) + if i >= amount - 1: + tpl_category = "aa" + else: + if random.randint(0, 1) == 1: + tpl_category = random.choice(available_categories) else: - if random.randint(0,1) == 1: - tpl_category = random.choice(available_categories) + tpl_category = "aa" + + tpl = random.choice(list(templates[tpl_category].values())) + + point = find_location(tpl_category != "oil", cp.position, theater, 10000, 40000, cp.ground_objects) + + if point is None: + print("Couldn't find point for {}".format(cp)) + continue + + object_id = 0 + group_id = group_id + 1 + + logging.info("generated {} for {}".format(tpl_category, cp)) + for object in tpl: + object_id += 1 + + g = TheaterGroundObject() + g.group_id = group_id + g.object_id = object_id + g.cp_id = cp.id + + g.dcs_identifier = object["type"] + g.heading = object["heading"] + g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y) + + if g.dcs_identifier == "AA": + if cp.captured: + faction = game.player_name else: - tpl_category = "aa" + faction = game.enemy_name + generate_anti_air_group(game, cp, g, faction) - tpl = random.choice(list(tpls[tpl_category].values())) - - point = find_location(tpl_category != "oil", cp.position, theater, 10000, 40000, cp.ground_objects) - - if point is None: - print("Couldn't find point for {}".format(cp)) - continue - - group_id += 1 - object_id = 0 - - logging.info("generated {} for {}".format(tpl_category, cp)) - for object in tpl: - object_id += 1 - - g = TheaterGroundObject() - g.group_id = group_id - g.object_id = object_id - g.cp_id = cp.id - - g.dcs_identifier = object["type"] - g.heading = object["heading"] - g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y) - - if g.dcs_identifier == "AA": - if cp.captured: - faction = game.player_name - else: - faction = game.enemy_name - generate_anti_air_group(game, cp, g, faction) - - cp.ground_objects.append(g) + cp.ground_objects.append(g) + return group_id \ No newline at end of file