diff --git a/game/game.py b/game/game.py index c90e91bf..1315e516 100644 --- a/game/game.py +++ b/game/game.py @@ -72,6 +72,7 @@ class Game: self.ground_planners = {} self.informations = [] self.informations.append(Information("Game Start", "-" * 40, 0)) + self.__culling_points = self.compute_conflicts_position() @property @@ -187,6 +188,7 @@ class Game: return 1 def pass_turn(self, no_action=False, ignored_cps: typing.Collection[ControlPoint] = None): + logging.info("Pass turn") self.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0)) self.turn = self.turn + 1 @@ -202,7 +204,7 @@ class Game: self._enemy_reinforcement() self._budget_player() - if not no_action: + if not no_action and self.turn > 1: for cp in self.theater.player_points(): cp.base.affect_strength(+PLAYER_BASE_STRENGTH_RECOVERY) else: @@ -221,6 +223,7 @@ class Game: self.game_stats.update(self) # Plan flights & combat for next turn + self.__culling_points = self.compute_conflicts_position() self.planners = {} self.ground_planners = {} for cp in self.theater.controlpoints: @@ -326,3 +329,49 @@ class Game: """ self.current_group_id += 1 return self.current_group_id + + def compute_conflicts_position(self): + """ + Compute the current conflict center position(s), mainly used for culling calculation + :return: List of points of interests + """ + points = [] + + # By default, use the existing frontline conflict position + for conflict in self.theater.conflicts(): + points.append(Conflict.frontline_position(self.theater, conflict[0], conflict[1])[0]) + + # If there is no conflict take the center point between the two nearest opposing bases + if len(points) == 0: + cpoint = None + min_distance = sys.maxsize + for cp in self.theater.player_points(): + for cp2 in self.theater.enemy_points(): + d = cp.position.distance_to_point(cp2.position) + if d < min_distance: + min_distance = d + cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2) + if cpoint is not None: + points.append(cpoint) + + # Else 0,0, since we need a default value + # (in this case this means the whole map is owned by the same player, so it is not an issue) + if len(points) == 0: + points.append(Point(0, 0)) + + return points + + def position_culled(self, pos): + """ + Check if unit can be generated at given position depending on culling performance settings + :param pos: Position you are tryng to spawn stuff at + :return: True if units can not be added at given position + """ + if self.settings.perf_culling == False: + return False + else: + for c in self.__culling_points: + if c.distance_to_point(pos) < self.settings.perf_culling_distance * 1000: + return False + return True + diff --git a/game/settings.py b/game/settings.py index c2f2de91..e29d7374 100644 --- a/game/settings.py +++ b/game/settings.py @@ -25,4 +25,8 @@ class Settings: perf_infantry = True perf_ai_parking_start = True + # Performance culling + perf_culling = False + perf_culling_distance = 0 + diff --git a/gen/aircraft.py b/gen/aircraft.py index 81a1ce8f..6bd8f8ac 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -230,6 +230,11 @@ class AircraftConflictGenerator: def generate_flights(self, cp, country, flight_planner:FlightPlanner): for flight in flight_planner.flights: + + if flight.client_count == 0 and self.game.position_culled(flight.from_cp.position): + logging.info("Flight not generated : culled") + continue + group = self.generate_planned_flight(cp, country, flight) if flight.flight_type == FlightType.INTERCEPTION: self.setup_group_as_intercept_flight(group, flight) diff --git a/gen/groundobjectsgen.py b/gen/groundobjectsgen.py index 050f1f2c..a09a836c 100644 --- a/gen/groundobjectsgen.py +++ b/gen/groundobjectsgen.py @@ -61,9 +61,12 @@ class GroundObjectsGenerator: for ground_object in cp.ground_objects: if ground_object.dcs_identifier == "AA": + + if self.game.position_culled(ground_object.position): + continue + for g in ground_object.groups: if len(g.units) > 0: - utype = unit_type_from_name(g.units[0].type) if not ground_object.sea_object: @@ -125,6 +128,10 @@ class GroundObjectsGenerator: sg.points[0].tasks.append(ActivateICLSCommand(cp.icls, unit_id=sg.units[0].id)) else: + + if self.game.position_culled(ground_object.position): + continue + static_type = None if ground_object.dcs_identifier in warehouse_map: static_type = warehouse_map[ground_object.dcs_identifier] @@ -160,34 +167,4 @@ class GroundObjectsGenerator: dead=ground_object.is_dead, ) - logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id)) - - -def farp_aa(mission_obj, country, name, position: mapping.Point): - """ - Add AAA to a FARP :) - :param mission_obj: - :param country: - :param name: - :param position: - :return: - """ - vg = unitgroup.VehicleGroup(mission_obj.next_group_id(), mission_obj.string(name)) - - units = [ - AirDefence.SPAAA_ZSU_23_4_Shilka, - AirDefence.AAA_ZU_23_Closed, - ] - - v = mission_obj.vehicle(name + "_AAA", random.choice(units)) - v.position.x = position.x - random.randint(5, 30) - v.position.y = position.y - random.randint(5, 30) - v.heading = random.randint(0, 359) - vg.add_unit(v) - - wp = vg.add_waypoint(vg.units[0].position, PointAction.OffRoad, 0) - wp.ETA_locked = True - - country.add_vehicle_group(vg) - return vg - + logging.info("generated {}object identifier {} with mission id {}".format("dead " if ground_object.is_dead else "", group.name, group.id)) \ No newline at end of file diff --git a/qt_ui/windows/settings/QSettingsWindow.py b/qt_ui/windows/settings/QSettingsWindow.py index 7a9b7565..a0b9e33b 100644 --- a/qt_ui/windows/settings/QSettingsWindow.py +++ b/qt_ui/windows/settings/QSettingsWindow.py @@ -1,13 +1,14 @@ from PySide2.QtCore import QSize, Qt, QItemSelectionModel, QPoint from PySide2.QtGui import QStandardItemModel, QStandardItem from PySide2.QtWidgets import QLabel, QDialog, QGridLayout, QListView, QStackedLayout, QComboBox, QWidget, \ - QAbstractItemView, QPushButton, QGroupBox, QCheckBox, QVBoxLayout + QAbstractItemView, QPushButton, QGroupBox, QCheckBox, QVBoxLayout, QSpinBox from dcs.forcedoptions import ForcedOptions import qt_ui.uiconstants as CONST from game.game import Game from game.infos.information import Information from qt_ui.windows.GameUpdateSignal import GameUpdateSignal +from qt_ui.windows.finances.QFinancesMenu import QHorizontalSeparationLine class QSettingsWindow(QDialog): @@ -199,6 +200,16 @@ class QSettingsWindow(QDialog): self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start) self.ai_parking_start.toggled.connect(self.applySettings) + self.culling = QCheckBox() + self.culling.setChecked(self.game.settings.perf_culling) + self.culling.toggled.connect(self.applySettings) + + self.culling_distance = QSpinBox() + self.culling_distance.setMinimum(50) + self.culling_distance.setMaximum(10000) + self.culling_distance.setValue(self.game.settings.perf_culling_distance) + self.culling_distance.valueChanged.connect(self.applySettings()) + self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0) self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight) self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0) @@ -212,6 +223,12 @@ class QSettingsWindow(QDialog): self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0) self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight) + self.performanceLayout.addWidget(QHorizontalSeparationLine(), 6, 0, 1, 2) + self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 7, 0) + self.performanceLayout.addWidget(self.culling, 7, 1, alignment=Qt.AlignRight) + self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 8, 0) + self.performanceLayout.addWidget(self.culling_distance, 8, 1, alignment=Qt.AlignRight) + self.generatorLayout.addWidget(self.gameplay) self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience.")) self.generatorLayout.addWidget(self.performance) @@ -277,6 +294,9 @@ class QSettingsWindow(QDialog): self.game.settings.perf_infantry = self.infantry.isChecked() self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked() + self.game.settings.perf_culling = self.culling.isChecked() + self.game.settings.perf_culling_distance = int(self.culling_distance.value()) + GameUpdateSignal.get_instance().updateGame(self.game) def onSelectionChanged(self): diff --git a/resources/ui/units/aircrafts/Bf 109 K-4_24.jpg b/resources/ui/units/aircrafts/Bf-109K-4_24.jpg similarity index 100% rename from resources/ui/units/aircrafts/Bf 109 K-4_24.jpg rename to resources/ui/units/aircrafts/Bf-109K-4_24.jpg diff --git a/resources/ui/units/aircrafts/Fw 190 A-8_24.jpg b/resources/ui/units/aircrafts/FW-190A8_24.jpg similarity index 100% rename from resources/ui/units/aircrafts/Fw 190 A-8_24.jpg rename to resources/ui/units/aircrafts/FW-190A8_24.jpg diff --git a/resources/ui/units/aircrafts/Fw 190 D-9_24.jpg b/resources/ui/units/aircrafts/FW-190D9_24.jpg similarity index 100% rename from resources/ui/units/aircrafts/Fw 190 D-9_24.jpg rename to resources/ui/units/aircrafts/FW-190D9_24.jpg diff --git a/resources/ui/units/aircrafts/P-51D-30-NA_24.jpg b/resources/ui/units/aircrafts/P-51D-30-NA_24.jpg new file mode 100644 index 00000000..a8601eab Binary files /dev/null and b/resources/ui/units/aircrafts/P-51D-30-NA_24.jpg differ diff --git a/resources/ui/units/aircrafts/Spitfire LF Mk. IX_24.jpg b/resources/ui/units/aircrafts/SpitfireLFMkIXCW_24.jpg similarity index 100% rename from resources/ui/units/aircrafts/Spitfire LF Mk. IX_24.jpg rename to resources/ui/units/aircrafts/SpitfireLFMkIXCW_24.jpg diff --git a/resources/ui/units/aircrafts/SpitfireLFMkIX_24.jpg b/resources/ui/units/aircrafts/SpitfireLFMkIX_24.jpg new file mode 100644 index 00000000..b2b5e77f Binary files /dev/null and b/resources/ui/units/aircrafts/SpitfireLFMkIX_24.jpg differ diff --git a/theater/conflicttheater.py b/theater/conflicttheater.py index ddd11dc1..621f106a 100644 --- a/theater/conflicttheater.py +++ b/theater/conflicttheater.py @@ -1,12 +1,10 @@ import typing -import itertools import dcs from dcs.mapping import Point -from .landmap import Landmap, poly_contains from .controlpoint import ControlPoint -from .theatergroundobject import TheaterGroundObject +from .landmap import poly_contains SIZE_TINY = 150 SIZE_SMALL = 600 @@ -66,7 +64,7 @@ class ConflictTheater: self.land_poly = self.land_poly.difference(geometry.Polygon(x)) """ - def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []): + def add_controlpoint(self, point: ControlPoint, connected_to: [ControlPoint] = []): for connected_point in connected_to: point.connect(to=connected_point) @@ -118,3 +116,5 @@ class ConflictTheater: def enemy_points(self) -> typing.Collection[ControlPoint]: return [point for point in self.controlpoints if not point.captured] + + diff --git a/theater/persiangulf.py b/theater/persiangulf.py index c69b3353..f7465d7d 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -52,30 +52,30 @@ class PersianGulfTheater(ConflictTheater): self.east_carrier = ControlPoint.carrier("East carrier", Point(59514.324335475, 28165.517980635)) self.add_controlpoint(self.liwa, connected_to=[self.al_dhafra]) - self.add_controlpoint(self.al_dhafra, connected_to=[self.liwa, self.sir_abu_nuayr, self.al_maktoum, self.al_ain]) + self.add_controlpoint(self.al_dhafra, connected_to=[self.liwa, self.al_maktoum, self.al_ain]) self.add_controlpoint(self.al_ain, connected_to=[self.al_dhafra, self.al_maktoum]) - self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.sir_abu_nuayr, self.al_ain]) + self.add_controlpoint(self.al_maktoum, connected_to=[self.al_dhafra, self.al_minhad, self.al_ain]) self.add_controlpoint(self.al_minhad, connected_to=[self.al_maktoum, self.dubai]) self.add_controlpoint(self.dubai, connected_to=[self.al_minhad, self.sharjah, self.fujairah]) self.add_controlpoint(self.sharjah, connected_to=[self.dubai, self.ras_al_khaimah]) self.add_controlpoint(self.ras_al_khaimah, connected_to=[self.sharjah, self.khasab]) self.add_controlpoint(self.fujairah, connected_to=[self.dubai, self.khasab]) - self.add_controlpoint(self.khasab, connected_to=[self.ras_al_khaimah, self.fujairah, self.tunb_island]) + self.add_controlpoint(self.khasab, connected_to=[self.ras_al_khaimah, self.fujairah]) - self.add_controlpoint(self.sir_abu_nuayr, connected_to=[self.al_dhafra, self.al_maktoum, self.sirri]) - self.add_controlpoint(self.sirri, connected_to=[self.sir_abu_nuayr, self.abu_musa]) - self.add_controlpoint(self.abu_musa, connected_to=[self.sirri, self.sir_abu_nuayr]) - self.add_controlpoint(self.tunb_kochak, connected_to=[self.sirri, self.abu_musa, self.tunb_island]) + self.add_controlpoint(self.sir_abu_nuayr, connected_to=[]) + self.add_controlpoint(self.sirri, connected_to=[]) + self.add_controlpoint(self.abu_musa, connected_to=[]) + self.add_controlpoint(self.tunb_kochak, connected_to=[]) - self.add_controlpoint(self.tunb_island, connected_to=[self.khasab, self.qeshm, self.tunb_kochak]) - self.add_controlpoint(self.bandar_lengeh, connected_to=[self.tunb_island, self.lar, self.qeshm]) - self.add_controlpoint(self.qeshm, connected_to=[self.bandar_lengeh, self.havadarya, self.tunb_island]) + self.add_controlpoint(self.tunb_island, connected_to=[]) + self.add_controlpoint(self.bandar_lengeh, connected_to=[self.lar, self.qeshm]) + self.add_controlpoint(self.qeshm, connected_to=[self.bandar_lengeh, self.havadarya]) self.add_controlpoint(self.havadarya, connected_to=[self.lar, self.qeshm, self.bandar_abbas]) self.add_controlpoint(self.bandar_abbas, connected_to=[self.havadarya, self.kerman]) self.add_controlpoint(self.shiraz, connected_to=[self.lar, self.kerman]) self.add_controlpoint(self.kerman, connected_to=[self.lar, self.shiraz, self.bandar_abbas]) - self.add_controlpoint(self.lar, connected_to=[self.bandar_lengeh, self.havadarya, self.shiraz, self.kerman]) + self.add_controlpoint(self.lar, connected_to=[self.havadarya, self.shiraz, self.kerman]) self.add_controlpoint(self.west_carrier) self.add_controlpoint(self.east_carrier) diff --git a/theater/start_generator.py b/theater/start_generator.py index 63587e9d..c2598a28 100644 --- a/theater/start_generator.py +++ b/theater/start_generator.py @@ -5,7 +5,7 @@ import typing import logging from game.data.building_data import DEFAULT_AVAILABLE_BUILDINGS -from gen import namegen +from gen import namegen, TheaterGroundObject from gen.defenses.armor_group_generator import generate_armor_group from gen.fleet.ship_group_generator import generate_carrier_group, generate_lha_group, generate_ship_group from gen.missiles.missiles_group_generator import generate_missile_group