diff --git a/changelog.md b/changelog.md index e3776b32..de50acec 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,12 @@ +# 2.4.1 + +## Fixes + +* **[Units]** Fixed syntax error with the SH-60B payload file. +* **[Culling]** Missile sites generate reasonably sized non-cull zones rather than 100km ones. +* **[UI]** Budget display is also now rounded to 2 decimal places. +* **[UI]** Fixed some areas where the old, non-pretty name was displayed to users. + # 2.4.0 Saves from 2.3 are not compatible with 2.4. diff --git a/game/game.py b/game/game.py index 59bca268..2ec47e4d 100644 --- a/game/game.py +++ b/game/game.py @@ -96,6 +96,9 @@ class Game: self.ground_planners: Dict[int, GroundPlanner] = {} self.informations = [] self.informations.append(Information("Game Start", "-" * 40, 0)) + # Culling Zones are for areas around points of interest that contain things we may not wish to cull. + self.__culling_zones: List[Point] = [] + # Culling Points are for individual theater ground objects that we don't wish to cull. self.__culling_points: List[Point] = [] self.__destroyed_units: List[str] = [] self.savepath = "" @@ -378,6 +381,7 @@ class Game: Compute the current conflict center position(s), mainly used for culling calculation :return: List of points of interests """ + zones = [] points = [] # By default, use the existing frontline conflict position @@ -385,23 +389,23 @@ class Game: position = Conflict.frontline_position(front_line.control_point_a, front_line.control_point_b, self.theater) - points.append(position[0]) - points.append(front_line.control_point_a.position) - points.append(front_line.control_point_b.position) + zones.append(position[0]) + zones.append(front_line.control_point_a.position) + zones.append(front_line.control_point_b.position) for cp in self.theater.controlpoints: # Don't cull missile sites - their range is long enough to make them # easily culled despite being a threat. for tgo in cp.ground_objects: if isinstance(tgo, MissileSiteGroundObject): - points.append(cp.position) + points.append(tgo.position) # If do_not_cull_carrier is enabled, add carriers as culling point if self.settings.perf_do_not_cull_carrier: if cp.is_carrier or cp.is_lha: - points.append(cp.position) + zones.append(cp.position) # If there is no conflict take the center point between the two nearest opposing bases - if len(points) == 0: + if len(zones) == 0: cpoint = None min_distance = sys.maxsize for cp in self.theater.player_points(): @@ -410,13 +414,13 @@ class Game: if d < min_distance: min_distance = d cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2) - points.append(cp.position) - points.append(cp2.position) + zones.append(cp.position) + zones.append(cp2.position) break if cpoint is not None: break if cpoint is not None: - points.append(cpoint) + zones.append(cpoint) packages = itertools.chain(self.blue_ato.packages, self.red_ato.packages) @@ -428,13 +432,14 @@ class Game: # are only interesting if there are enemies in the area, and if # there are they won't be culled because of the enemy's mission. continue - points.append(package.target.position) + zones.append(package.target.position) # 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)) + if len(zones) == 0: + zones.append(Point(0, 0)) + self.__culling_zones = zones self.__culling_points = points def add_destroyed_units(self, data): @@ -454,11 +459,21 @@ class Game: 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: + for z in self.__culling_zones: + if z.distance_to_point(pos) < self.settings.perf_culling_distance * 1000: + return False + for p in self.__culling_points: + if p.distance_to_point(pos) < 2500: return False return True + def get_culling_zones(self): + """ + Check culling points + :return: List of culling zones + """ + return self.__culling_zones + def get_culling_points(self): """ Check culling points diff --git a/qt_ui/widgets/QBudgetBox.py b/qt_ui/widgets/QBudgetBox.py index 67ef04a5..c8ba24dd 100644 --- a/qt_ui/widgets/QBudgetBox.py +++ b/qt_ui/widgets/QBudgetBox.py @@ -35,7 +35,7 @@ class QBudgetBox(QGroupBox): :param budget: Current money available :param reward: Planned reward for next turn """ - self.money_amount.setText(str(budget) + "M (+" + str(round(reward,2)) + "M)") + self.money_amount.setText(str(round(budget,2)) + "M (+" + str(round(reward,2)) + "M)") def setGame(self, game): if game is None: diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index fc7d09b6..1f171843 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -268,13 +268,20 @@ class QLiberationMap(QGraphicsView): def display_culling(self, scene: QGraphicsScene) -> None: """Draws the culling distance rings on the map""" culling_points = self.game_model.game.get_culling_points() + culling_zones = self.game_model.game.get_culling_zones() culling_distance = self.game_model.game.settings.perf_culling_distance for point in culling_points: - culling_distance_point = Point(point.x + culling_distance*1000, point.y + culling_distance*1000) + culling_distance_point = Point(point.x + 2500, point.y + 2500) distance_point = self._transform_point(culling_distance_point) transformed = self._transform_point(point) radius = distance_point[0] - transformed[0] scene.addEllipse(transformed[0]-radius, transformed[1]-radius, 2*radius, 2*radius, CONST.COLORS["transparent"], CONST.COLORS["light_green_transparent"]) + for zone in culling_zones: + culling_distance_zone = Point(zone.x + culling_distance*1000, zone.y + culling_distance*1000) + distance_zone = self._transform_point(culling_distance_zone) + transformed = self._transform_point(zone) + radius = distance_zone[0] - transformed[0] + scene.addEllipse(transformed[0]-radius, transformed[1]-radius, 2*radius, 2*radius, CONST.COLORS["transparent"], CONST.COLORS["light_green_transparent"]) def draw_shapely_poly(self, scene: QGraphicsScene, poly: Polygon, pen: QPen, brush: QBrush) -> Optional[QPolygonF]: diff --git a/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py b/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py index 6d46b35b..16aa2a90 100644 --- a/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py +++ b/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py @@ -11,6 +11,8 @@ from game.theater import ControlPoint, TheaterGroundObject from qt_ui.dialogs import Dialog from qt_ui.uiconstants import VEHICLES_ICONS from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu +from game import db +from dcs import vehicles class QBaseDefenseGroupInfo(QGroupBox): @@ -71,7 +73,11 @@ class QBaseDefenseGroupInfo(QGroupBox): icon.setText("" + k[:8] + "") icon.setProperty("style", "icon-armor") self.unit_layout.addWidget(icon, i, 0) - self.unit_layout.addWidget(QLabel(str(v) + " x " + "" + k + ""), i, 1) + unit_display_name = k + unit_type = vehicles.vehicle_map.get(k) + if unit_type is not None: + unit_display_name = db.unit_get_expanded_info(self.game.enemy_country, unit_type, 'name') + self.unit_layout.addWidget(QLabel(str(v) + " x " + "" + unit_display_name + ""), i, 1) i = i + 1 if len(unit_dict.items()) == 0: diff --git a/qt_ui/windows/groundobject/QGroundObjectMenu.py b/qt_ui/windows/groundobject/QGroundObjectMenu.py index 1341eb39..d979c657 100644 --- a/qt_ui/windows/groundobject/QGroundObjectMenu.py +++ b/qt_ui/windows/groundobject/QGroundObjectMenu.py @@ -29,6 +29,7 @@ from qt_ui.uiconstants import EVENT_ICONS from qt_ui.widgets.QBudgetBox import QBudgetBox from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.groundobject.QBuildingInfo import QBuildingInfo +from dcs import vehicles class QGroundObjectMenu(QDialog): @@ -101,7 +102,11 @@ class QGroundObjectMenu(QDialog): if not hasattr(g, "units_losts"): g.units_losts = [] for u in g.units: - self.intelLayout.addWidget(QLabel("Unit #" + str(u.id) + " - " + str(u.type) + ""), i, 0) + unit_display_name = u.type + unit_type = vehicles.vehicle_map.get(u.type) + if unit_type is not None: + unit_display_name = db.unit_get_expanded_info(self.game.enemy_country, unit_type, 'name') + self.intelLayout.addWidget(QLabel("Unit #" + str(u.id) + " - " + str(unit_display_name) + ""), i, 0) i = i + 1 for u in g.units_losts: diff --git a/resources/customized_payloads/SH-60B.lua b/resources/customized_payloads/SH-60B.lua index 22ff5907..6af4a956 100644 --- a/resources/customized_payloads/SH-60B.lua +++ b/resources/customized_payloads/SH-60B.lua @@ -13,6 +13,7 @@ local unitPayloads = { [1] = 30, }, }, + }, ["unitType"] = "SH-60B", } return unitPayloads diff --git a/resources/scripts/MissionScripting.original.lua b/resources/scripts/MissionScripting.original.lua index 86f9cda2..29dcd2fe 100644 --- a/resources/scripts/MissionScripting.original.lua +++ b/resources/scripts/MissionScripting.original.lua @@ -3,7 +3,7 @@ dofile('Scripts/ScriptingSystem.lua') --Sanitize Mission Scripting environment ---This makes unavailable some unsecure functions. +--This makes unavailable some unsecure functions. --Mission downloaded from server to client may contain potentialy harmful lua code that may use these functions. --You can remove the code below and make availble these functions at your own risk. diff --git a/resources/units/unit_info_text.json b/resources/units/unit_info_text.json index d158ff0a..11349ea0 100644 --- a/resources/units/unit_info_text.json +++ b/resources/units/unit_info_text.json @@ -962,7 +962,7 @@ }], "AAA Bofors 40mm": [{ "default": { - "name": "Bofors 40 mm gun", + "name": "Bofors 40 mm Gun", "country-of-origin": "Sweden", "manufacturer": "Bofors", "role": "Anti-Aircraft Gun", @@ -1101,7 +1101,7 @@ }], "APC M2A1": [{ "default": { - "name": "M2A1 Half-track", + "name": "M2A1 Half-Track", "country-of-origin": "USA", "manufacturer": "White Motor Company", "role": "Armoured Personnel Carrier",