mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
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:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user