diff --git a/game/ato/flight.py b/game/ato/flight.py index 4e19d7e3..44042788 100644 --- a/game/ato/flight.py +++ b/game/ato/flight.py @@ -80,6 +80,8 @@ class Flight(SidcDescribable, RadioFrequencyContainer, TacanContainer): self.tacan = channel self.tcn_name = callsign + self.initialize_fuel() + # Only used by transport missions. self.cargo = cargo @@ -204,19 +206,19 @@ class Flight(SidcDescribable, RadioFrequencyContainer, TacanContainer): self.roster.clear() self.squadron.claim_inventory(-self.count) - def max_takeoff_fuel(self) -> Optional[float]: - # Special case so Su 33 and C101 can take off + def initialize_fuel(self) -> None: unit_type = self.unit_type.dcs_unit_type + self.fuel = unit_type.fuel_max + # Special cases where we want less fuel for takeoff if unit_type == Su_33: if self.flight_type.is_air_to_air: - return Su_33.fuel_max / 2.2 + self.fuel = Su_33.fuel_max / 2.2 else: - return Su_33.fuel_max * 0.8 + self.fuel = Su_33.fuel_max * 0.8 elif unit_type in {C_101EB, C_101CC}: - return unit_type.fuel_max * 0.5 + self.fuel = unit_type.fuel_max * 0.5 elif unit_type == Hercules: - return unit_type.fuel_max * 0.75 - return None + self.fuel = unit_type.fuel_max * 0.75 def __repr__(self) -> str: return self.__str__() diff --git a/game/ato/flightstate/flightstate.py b/game/ato/flightstate/flightstate.py index 262e56b4..73ad7624 100644 --- a/game/ato/flightstate/flightstate.py +++ b/game/ato/flightstate/flightstate.py @@ -82,9 +82,7 @@ class FlightState(ABC): def estimate_fuel(self) -> float: """Returns the estimated remaining fuel **in kilograms**.""" - if (max_takeoff_fuel := self.flight.max_takeoff_fuel()) is not None: - return max_takeoff_fuel - return self.flight.unit_type.dcs_unit_type.fuel_max + return self.flight.fuel @property @abstractmethod diff --git a/game/dcs/aircrafttype.py b/game/dcs/aircrafttype.py index 3d6789fe..85d01a38 100644 --- a/game/dcs/aircrafttype.py +++ b/game/dcs/aircrafttype.py @@ -200,6 +200,10 @@ class AircraftType(UnitType[Type[FlyingType]]): def helicopter(self) -> bool: return self.dcs_unit_type.helicopter + @property + def max_fuel(self) -> float: + return self.dcs_unit_type.fuel_max + @cached_property def max_speed(self) -> Speed: return kph(self.dcs_unit_type.max_speed) diff --git a/game/migrator.py b/game/migrator.py index c5f40c79..c22ed0f3 100644 --- a/game/migrator.py +++ b/game/migrator.py @@ -76,3 +76,4 @@ class Migrator: try_set_attr(f, "frequency") try_set_attr(f, "tacan") try_set_attr(f, "tcn_name") + try_set_attr(f, "fuel", f.unit_type.max_fuel) diff --git a/game/missiongenerator/aircraft/flightgroupconfigurator.py b/game/missiongenerator/aircraft/flightgroupconfigurator.py index 2e166179..78ce52d4 100644 --- a/game/missiongenerator/aircraft/flightgroupconfigurator.py +++ b/game/missiongenerator/aircraft/flightgroupconfigurator.py @@ -249,12 +249,4 @@ class FlightGroupConfigurator: ) fuel = 100 for unit, pilot in zip(self.group.units, self.flight.roster.pilots): - if pilot is not None and pilot.player: - unit.fuel = fuel - elif (max_takeoff_fuel := self.flight.max_takeoff_fuel()) is not None: - unit.fuel = max_takeoff_fuel - else: - # pydcs arbitrarily reduces the fuel of in-flight spawns by 10%. We do - # our own tracking, so undo that. - # https://github.com/pydcs/dcs/commit/303a81a8e0c778599fe136dd22cb2ae8123639a6 - unit.fuel = self.flight.unit_type.dcs_unit_type.fuel_max + unit.fuel = fuel diff --git a/qt_ui/windows/mission/flight/payload/QFlightPayloadTab.py b/qt_ui/windows/mission/flight/payload/QFlightPayloadTab.py index b9177383..2f4e50a9 100644 --- a/qt_ui/windows/mission/flight/payload/QFlightPayloadTab.py +++ b/qt_ui/windows/mission/flight/payload/QFlightPayloadTab.py @@ -3,9 +3,12 @@ from PySide2.QtWidgets import ( QComboBox, QFrame, QLabel, + QHBoxLayout, QVBoxLayout, QScrollArea, QWidget, + QSpinBox, + QSlider, ) from game import Game @@ -28,6 +31,70 @@ class DcsLoadoutSelector(QComboBox): self.setCurrentText(flight.loadout.name) +class DcsFuelSelector(QHBoxLayout): + LBS2KGS_FACTOR = 0.45359237 + + def __init__(self, flight: Flight) -> None: + super().__init__() + self.flight = flight + self.unit_changing = False + + self.label = QLabel("Internal Fuel Quantity: ") + self.addWidget(self.label) + + self.max_fuel = int(flight.unit_type.dcs_unit_type.fuel_max) + self.fuel = QSlider(Qt.Horizontal) + self.fuel.setRange(0, self.max_fuel) + self.fuel.setValue(min(round(self.flight.fuel), self.max_fuel)) + self.fuel.valueChanged.connect(self.on_fuel_change) + self.addWidget(self.fuel, 1) + + self.fuel_spinner = QSpinBox() + self.fuel_spinner.setRange(0, self.max_fuel) + self.fuel_spinner.setValue(self.fuel.value()) + self.fuel_spinner.valueChanged.connect(self.update_fuel_slider) + self.addWidget(self.fuel_spinner) + + self.unit = QComboBox() + self.unit.insertItems(0, ["kg", "lbs"]) + self.unit.currentIndexChanged.connect(self.on_unit_change) + self.unit.setCurrentIndex(1) + self.addWidget(self.unit) + + def on_fuel_change(self, value: int) -> None: + self.flight.fuel = value + if self.unit.currentIndex() == 0: + self.fuel_spinner.setValue(value) + elif self.unit.currentIndex() == 1 and not self.unit_changing: + self.fuel_spinner.setValue(self.kg2lbs(value)) + + def update_fuel_slider(self, value: int) -> None: + if self.unit_changing: + return + if self.unit.currentIndex() == 0: + self.fuel.setValue(value) + elif self.unit.currentIndex() == 1: + self.unit_changing = True + self.fuel.setValue(self.lbs2kg(value)) + self.unit_changing = False + + def on_unit_change(self, index: int) -> None: + self.unit_changing = True + if index == 0: + self.fuel_spinner.setMaximum(self.max_fuel) + self.fuel_spinner.setValue(self.fuel.value()) + elif index == 1: + self.fuel_spinner.setMaximum(self.kg2lbs(self.max_fuel)) + self.fuel_spinner.setValue(self.kg2lbs(self.fuel.value())) + self.unit_changing = False + + def kg2lbs(self, value: int) -> int: + return round(value / self.LBS2KGS_FACTOR) + + def lbs2kg(self, value: int) -> int: + return round(value * self.LBS2KGS_FACTOR) + + class QFlightPayloadTab(QFrame): def __init__(self, flight: Flight, game: Game): super(QFlightPayloadTab, self).__init__() @@ -48,12 +115,15 @@ class QFlightPayloadTab(QFrame): self.property_editor = QWidget() self.property_editor.setLayout(PropertyEditor(self.flight)) self.scroll_area.setWidget(self.property_editor) - layout.addWidget(self.scroll_area) + + self.fuel_selector = DcsFuelSelector(flight) + layout.addLayout(self.fuel_selector) + self.loadout_selector = DcsLoadoutSelector(flight) self.loadout_selector.currentIndexChanged.connect(self.on_new_loadout) layout.addWidget(self.loadout_selector) - layout.addWidget(self.payload_editor) + layout.addWidget(self.payload_editor, stretch=1) layout.addWidget(docsText) self.setLayout(layout)