Loadout implementation cleanup.

Loadout selection no longer has two (disagreeing) implementations. What
the UI shows is now what the miz will have.

We now store the chosen layout in the Flight *always*, not just for
custom loadouts. This means that we do loadout lookups at the start of
each turn, but the data is cached in pydcs.

Era-specific loadout degradation is still done at generation (and
presentation) time. This is so that players can toggle that option and
have it affect the *current* turn, rather than the next one.
This commit is contained in:
Dan Albert
2021-05-17 01:01:11 -07:00
parent 6ca175345f
commit 0e3bc1ce43
7 changed files with 190 additions and 286 deletions

View File

@@ -1,8 +1,9 @@
from PySide2.QtWidgets import QFrame, QGridLayout, QLabel
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QFrame, QLabel, QVBoxLayout
from game import Game
from gen.flights.flight import Flight
from gen.flights.loadouts import Loadout
from qt_ui.windows.mission.flight.payload.QLoadoutEditor import QLoadoutEditor
@@ -11,10 +12,8 @@ class QFlightPayloadTab(QFrame):
super(QFlightPayloadTab, self).__init__()
self.flight = flight
self.payload_editor = QLoadoutEditor(flight, game)
self.init_ui()
def init_ui(self):
layout = QGridLayout()
layout = QVBoxLayout()
# Docs Link
docsText = QLabel(
@@ -23,7 +22,15 @@ class QFlightPayloadTab(QFrame):
docsText.setAlignment(Qt.AlignCenter)
docsText.setOpenExternalLinks(True)
self.payload_editor.toggled.connect(self.on_custom_toggled)
layout.addWidget(self.payload_editor)
layout.addWidget(docsText)
self.setLayout(layout)
def on_custom_toggled(self, use_custom: bool) -> None:
if use_custom:
self.flight.loadout = self.flight.loadout.derive_custom("Custom")
else:
self.flight.loadout = Loadout.default_for(self.flight)
self.payload_editor.reset_pylons()

View File

@@ -18,11 +18,9 @@ class QLoadoutEditor(QGroupBox):
self.flight = flight
self.game = game
self.setCheckable(True)
self.setChecked(flight.use_custom_loadout)
self.setChecked(flight.loadout.is_custom)
self.toggled.connect(self.on_toggle)
hboxLayout = QVBoxLayout(self)
vbox = QVBoxLayout(self)
layout = QGridLayout(self)
for i, pylon in enumerate(Pylon.iter_pylons(self.flight.unit_type)):
@@ -31,16 +29,15 @@ class QLoadoutEditor(QGroupBox):
layout.addWidget(label, i, 0)
layout.addWidget(QPylonEditor(game, flight, pylon), i, 1)
hboxLayout.addLayout(layout)
hboxLayout.addStretch()
self.setLayout(hboxLayout)
vbox.addLayout(layout)
vbox.addStretch()
self.setLayout(vbox)
if not self.isChecked():
for i in self.findChildren(QPylonEditor):
i.default_loadout()
for i in self.findChildren(QPylonEditor):
i.set_from(self.flight.loadout)
def on_toggle(self):
def reset_pylons(self) -> None:
self.flight.use_custom_loadout = self.isChecked()
if not self.isChecked():
for i in self.findChildren(QPylonEditor):
i.default_loadout()
i.set_from(self.flight.loadout)

View File

@@ -4,10 +4,10 @@ from typing import Optional
from PySide2.QtWidgets import QComboBox
from game import Game, db
from game import Game
from game.data.weapons import Pylon, Weapon
from gen.flights.flight import Flight
from dcs import weapons_data
from gen.flights.loadouts import Loadout
class QPylonEditor(QComboBox):
@@ -17,7 +17,7 @@ class QPylonEditor(QComboBox):
self.pylon = pylon
self.game = game
current = self.flight.loadout.get(self.pylon.number)
current = self.flight.loadout.pylons.get(self.pylon.number)
self.addItem("None", None)
if self.game.settings.restrict_weapons_by_date:
@@ -34,57 +34,29 @@ class QPylonEditor(QComboBox):
def on_pylon_change(self):
selected: Optional[Weapon] = self.currentData()
self.flight.loadout[self.pylon.number] = selected
self.flight.loadout.pylons[self.pylon.number] = selected
if selected is None:
logging.debug(f"Pylon {self.pylon.number} emptied")
else:
logging.debug(f"Pylon {self.pylon.number} changed to {selected.name}")
def default_loadout(self) -> None:
self.flight.unit_type.load_payloads()
self.setCurrentText("None")
pylon_default_weapon = None
historical_weapon = None
loadout = None
# Iterate through each possible payload type for a given aircraft.
# Some aircraft have custom loadouts that in aren't the standard set.
for payload_override in db.EXPANDED_TASK_PAYLOAD_OVERRIDE.get(
self.flight.flight_type.name
):
if loadout is None:
loadout = self.flight.unit_type.loadout_by_name(payload_override)
if loadout is not None:
for i in loadout:
if i[0] == self.pylon.number:
pylon_default_weapon = i[1]["clsid"]
# TODO: Handle removed pylons better.
if pylon_default_weapon == "<CLEAN>":
pylon_default_weapon = None
if pylon_default_weapon is not None:
if self.game.settings.restrict_weapons_by_date:
orig_weapon = Weapon.from_clsid(pylon_default_weapon)
if not orig_weapon.available_on(self.game.date):
for fallback in orig_weapon.fallbacks:
if historical_weapon is None:
if not self.pylon.can_equip(fallback):
continue
if not fallback.available_on(self.game.date):
continue
historical_weapon = fallback
else:
historical_weapon = orig_weapon
if historical_weapon is not None:
self.setCurrentText(
weapons_data.weapon_ids.get(historical_weapon.cls_id).get(
"name"
)
)
else:
weapon = weapons_data.weapon_ids.get(pylon_default_weapon)
if weapon is not None:
self.setCurrentText(
weapons_data.weapon_ids.get(pylon_default_weapon).get("name")
)
else:
self.setCurrentText(pylon_default_weapon)
def weapon_from_loadout(self, loadout: Loadout) -> Optional[Weapon]:
weapon = loadout.pylons.get(self.pylon.number)
if weapon is None:
return None
# TODO: Handle removed pylons better.
if weapon.cls_id == "<CLEAN>":
return None
return weapon
def matching_weapon_name(self, loadout: Loadout) -> str:
if self.game.settings.restrict_weapons_by_date:
loadout = loadout.degrade_for_date(self.flight.unit_type, self.game.date)
weapon = self.weapon_from_loadout(loadout)
if weapon is None:
return ""
return weapon.name
def set_from(self, loadout: Loadout) -> None:
self.setCurrentText(self.matching_weapon_name(loadout))