Make EWR sites purchasable.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/968
This commit is contained in:
Dan Albert 2021-05-31 16:32:43 -07:00
parent 45919200c4
commit 8604faffe6
6 changed files with 111 additions and 24 deletions

View File

@ -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.

View File

@ -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__(

View File

@ -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)

View File

@ -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

View File

@ -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(

View File

@ -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)