From 8604faffe6b80aac059d3f6ae8a14252e2bee725 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Mon, 31 May 2021 16:32:43 -0700 Subject: [PATCH] Make EWR sites purchasable. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/968 --- changelog.md | 1 + game/theater/theatergroundobject.py | 32 +++++++ gen/sam/airdefensegroupgenerator.py | 2 + gen/sam/ewr_group_generator.py | 4 +- gen/sam/ewrs.py | 13 ++- .../windows/groundobject/QGroundObjectMenu.py | 83 ++++++++++++++----- 6 files changed, 111 insertions(+), 24 deletions(-) diff --git a/changelog.md b/changelog.md index f0358c0f..cec651b4 100644 --- a/changelog.md +++ b/changelog.md @@ -45,6 +45,7 @@ Saves from 2.5 are not compatible with 3.0. * **[Campaign AI]** Auto planner will no longer attempt to plan missions for which the faction has no compatible aircraft. * **[Campaign AI]** Stop purchasing aircraft after the first unaffordable package to attempt to complete more packages rather than filling airfields with cheap escorts that will never be used. * **[Campaign]** Fixed bug where offshore strike locations were being used to spawn ship objectives. +* **[Campaign]** EWR sites are now purchasable. * **[Flight Planner]** AI strike flight plans now include the correct target actions for building groups. * **[Flight Planner]** AI BAI/DEAD/SEAD flights now have tasks to attack all groups at the target location, not just the primary group (for multi-group SAM sites). * **[Flight Planner]** Fixed some contexts where damaged runways would be used. Destroying a carrier will no longer break the game. diff --git a/game/theater/theatergroundobject.py b/game/theater/theatergroundobject.py index 99d4a9cf..85a2097c 100644 --- a/game/theater/theatergroundobject.py +++ b/game/theater/theatergroundobject.py @@ -197,6 +197,10 @@ class TheaterGroundObject(MissionTarget): def capturable(self) -> bool: raise NotImplementedError + @property + def purchasable(self) -> bool: + raise NotImplementedError + class BuildingGroundObject(TheaterGroundObject): def __init__( @@ -262,6 +266,10 @@ class BuildingGroundObject(TheaterGroundObject): def capturable(self) -> bool: return True + @property + def purchasable(self) -> bool: + return False + class SceneryGroundObject(BuildingGroundObject): def __init__( @@ -337,6 +345,10 @@ class NavalGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return False + class GenericCarrierGroundObject(NavalGroundObject): @property @@ -405,6 +417,10 @@ class MissileSiteGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return False + class CoastalSiteGroundObject(TheaterGroundObject): def __init__( @@ -430,6 +446,10 @@ class CoastalSiteGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return False + # TODO: Differentiate types. # This type gets used both for AA sites (SAM, AAA, or SHORAD). These should each @@ -513,6 +533,10 @@ class SamGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return True + class VehicleGroupGroundObject(TheaterGroundObject): def __init__( @@ -537,6 +561,10 @@ class VehicleGroupGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return True + class EwrGroundObject(TheaterGroundObject): def __init__( @@ -577,6 +605,10 @@ class EwrGroundObject(TheaterGroundObject): def capturable(self) -> bool: return False + @property + def purchasable(self) -> bool: + return True + class ShipGroundObject(NavalGroundObject): def __init__( diff --git a/gen/sam/airdefensegroupgenerator.py b/gen/sam/airdefensegroupgenerator.py index 3a25a2dd..a62a5f11 100644 --- a/gen/sam/airdefensegroupgenerator.py +++ b/gen/sam/airdefensegroupgenerator.py @@ -21,6 +21,8 @@ class AirDefenseGroupGenerator(GroupGenerator, ABC): This is the base for all SAM group generators """ + price: int + def __init__(self, game: Game, ground_object: SamGroundObject) -> None: ground_object.skynet_capable = True super().__init__(game, ground_object) diff --git a/gen/sam/ewr_group_generator.py b/gen/sam/ewr_group_generator.py index e576f5a8..81ede492 100644 --- a/gen/sam/ewr_group_generator.py +++ b/gen/sam/ewr_group_generator.py @@ -17,8 +17,8 @@ from gen.sam.ewrs import ( SnowDriftGenerator, StraightFlushGenerator, TallRackGenerator, + EwrGenerator, ) -from gen.sam.group_generator import GroupGenerator EWR_MAP = { "BoxSpringGenerator": BoxSpringGenerator, @@ -36,7 +36,7 @@ EWR_MAP = { def get_faction_possible_ewrs_generator( faction: Faction, -) -> List[Type[GroupGenerator]]: +) -> List[Type[EwrGenerator]]: """ Return the list of possible EWR generators for the given faction :param faction: Faction name to search units for diff --git a/gen/sam/ewrs.py b/gen/sam/ewrs.py index d69f2de7..0c529cf8 100644 --- a/gen/sam/ewrs.py +++ b/gen/sam/ewrs.py @@ -5,9 +5,16 @@ from gen.sam.group_generator import GroupGenerator class EwrGenerator(GroupGenerator): - @property - def unit_type(self) -> VehicleType: - raise NotImplementedError + unit_type: VehicleType + + @classmethod + def name(cls) -> str: + return cls.unit_type.name + + @staticmethod + def price() -> int: + # TODO: Differentiate sites. + return 20 def generate(self) -> None: self.add_unit( diff --git a/qt_ui/windows/groundobject/QGroundObjectMenu.py b/qt_ui/windows/groundobject/QGroundObjectMenu.py index 258f3456..9df4b454 100644 --- a/qt_ui/windows/groundobject/QGroundObjectMenu.py +++ b/qt_ui/windows/groundobject/QGroundObjectMenu.py @@ -25,8 +25,11 @@ from game.theater.theatergroundobject import ( NavalGroundObject, VehicleGroupGroundObject, SamGroundObject, + EwrGroundObject, + BuildingGroundObject, ) from gen.defenses.armor_group_generator import generate_armor_group_of_type_and_size +from gen.sam.ewr_group_generator import get_faction_possible_ewrs_generator from gen.sam.sam_group_generator import get_faction_possible_sams_generator from qt_ui.uiconstants import EVENT_ICONS from qt_ui.widgets.QBudgetBox import QBudgetBox @@ -36,9 +39,6 @@ from dcs import vehicles class QGroundObjectMenu(QDialog): - - changed = QtCore.Signal() - def __init__( self, parent, @@ -74,12 +74,12 @@ class QGroundObjectMenu(QDialog): self.doLayout() - if self.ground_object.dcs_identifier == "AA": - self.mainLayout.addWidget(self.intelBox) - else: + if isinstance(self.ground_object, BuildingGroundObject): self.mainLayout.addWidget(self.buildingBox) if self.cp.captured: self.mainLayout.addWidget(self.financesBox) + else: + self.mainLayout.addWidget(self.intelBox) self.actionLayout = QHBoxLayout() @@ -91,12 +91,12 @@ class QGroundObjectMenu(QDialog): self.buy_replace.clicked.connect(self.buy_group) self.buy_replace.setProperty("style", "btn-success") - if not isinstance(self.ground_object, NavalGroundObject): + if self.ground_object.purchasable: if self.total_value > 0: self.actionLayout.addWidget(self.sell_all_button) self.actionLayout.addWidget(self.buy_replace) - if self.cp.captured and self.ground_object.dcs_identifier == "AA": + if self.cp.captured and self.ground_object.purchasable: self.mainLayout.addLayout(self.actionLayout) self.setLayout(self.mainLayout) @@ -200,23 +200,21 @@ class QGroundObjectMenu(QDialog): self.actionLayout.setParent(None) self.doLayout() - if self.ground_object.dcs_identifier == "AA": - self.mainLayout.addWidget(self.intelBox) - else: + if isinstance(self.ground_object, BuildingGroundObject): self.mainLayout.addWidget(self.buildingBox) + else: + self.mainLayout.addWidget(self.intelBox) self.actionLayout = QHBoxLayout() if self.total_value > 0: self.actionLayout.addWidget(self.sell_all_button) self.actionLayout.addWidget(self.buy_replace) - if self.cp.captured and self.ground_object.dcs_identifier == "AA": + if self.cp.captured and self.ground_object.purchasable: self.mainLayout.addLayout(self.actionLayout) - except Exception as e: - print(e) + logging.exception(e) self.update_total_value() - self.changed.emit() def update_total_value(self): total_value = 0 @@ -248,7 +246,6 @@ class QGroundObjectMenu(QDialog): logging.info("Repaired unit : " + str(unit.id) + " " + str(unit.type)) self.do_refresh_layout() - self.changed.emit() def sell_all(self): self.update_total_value() @@ -298,9 +295,6 @@ class QBuyGroupForGroundObjectDialog(QDialog): self.buySamBox = QGroupBox("Buy SAM site :") self.buyArmorBox = QGroupBox("Buy defensive position :") - self.init_ui() - - def init_ui(self): faction = self.game.player_faction # Sams @@ -321,6 +315,30 @@ class QBuyGroupForGroundObjectDialog(QDialog): self.buySamButton.clicked.connect(self.buySam) + # EWRs + + buy_ewr_box = QGroupBox("Buy EWR:") + buy_ewr_layout = QGridLayout() + buy_ewr_box.setLayout(buy_ewr_layout) + + buy_ewr_layout.addWidget(QLabel("Radar type:"), 0, 0, Qt.AlignLeft) + + self.ewr_selector = QComboBox() + buy_ewr_layout.addWidget(self.ewr_selector, 0, 1, alignment=Qt.AlignRight) + ewr_types = get_faction_possible_ewrs_generator(faction) + for ewr_type in ewr_types: + self.ewr_selector.addItem( + f"{ewr_type.name()} [${ewr_type.price()}M]", ewr_type + ) + self.ewr_selector.currentIndexChanged.connect(self.on_ewr_selection_changed) + + self.buy_ewr_button = QPushButton("Buy") + self.buy_ewr_button.clicked.connect(self.buy_ewr) + buy_ewr_layout.addWidget(self.buy_ewr_button, 1, 1, alignment=Qt.AlignRight) + stretch = QVBoxLayout() + stretch.addStretch() + buy_ewr_layout.addLayout(stretch, 2, 0) + # Armored units armored_units = db.find_unittype( @@ -363,12 +381,15 @@ class QBuyGroupForGroundObjectDialog(QDialog): self.mainLayout.addWidget(self.buySamBox) elif isinstance(self.ground_object, VehicleGroupGroundObject): self.mainLayout.addWidget(self.buyArmorBox) + elif isinstance(self.ground_object, EwrGroundObject): + self.mainLayout.addWidget(buy_ewr_box) self.setLayout(self.mainLayout) try: self.samComboChanged(0) self.armorComboChanged(0) + self.on_ewr_selection_changed(0) except: pass @@ -381,6 +402,12 @@ class QBuyGroupForGroundObjectDialog(QDialog): + "M]" ) + def on_ewr_selection_changed(self, index): + ewr = self.ewr_selector.itemData(index) + self.buy_ewr_button.setText( + f"Buy [${ewr.price()}M][-${self.current_group_value}M]" + ) + def armorComboChanged(self, index): self.buyArmorButton.setText( "Buy [$" @@ -446,6 +473,24 @@ class QBuyGroupForGroundObjectDialog(QDialog): self.changed.emit() self.close() + def buy_ewr(self): + ewr_generator = self.ewr_selector.itemData(self.ewr_selector.currentIndex()) + price = ewr_generator.price() - self.current_group_value + if price > self.game.budget: + self.error_money() + return + else: + self.game.budget -= price + + generator = ewr_generator(self.game, self.ground_object) + generator.generate() + self.ground_object.groups = [generator.vg] + + GameUpdateSignal.get_instance().updateBudget(self.game) + + self.changed.emit() + self.close() + def error_money(self): msg = QMessageBox() msg.setIcon(QMessageBox.Information)