Merge branch 'dcs-retribution:dev' into vietnamwarvessels

This commit is contained in:
Astro-739
2024-12-15 03:30:46 +01:00
committed by GitHub
6 changed files with 273 additions and 81 deletions

View File

@@ -32,7 +32,9 @@
* **[Mission Generation]** Ability to choose whether player flights can spawn on the sixpack or not
* **[Options]** New options in Mission Generator section: Limit AI radio callouts & Suppress AI radio callouts.
* **[Options]** New option to use the combat landing flag in the landing waypoint task for helicopters.
* **[UI/UX]** Sync package waypoints when primary flight's waypoints are updated and recreate other flights within the package to ensure JOIN, INGRESS & SPLIT are synced
* **[UI/UX]** Sync package waypoints when primary flight's waypoints are updated and recreate other flights within the package to ensure JOIN, INGRESS & SPLIT are synced
* **[UI/UX]** Allow changing loadout on flight creation
* **[UI]** Display TOT for all waypoints in the flight plan
## Fixes
* **[UI/UX]** A-10A flights can be edited again

View File

@@ -1,6 +1,6 @@
from typing import Optional, Type
from PySide6.QtCore import Qt, Signal
from PySide6.QtCore import Qt, Signal, QEvent
from PySide6.QtWidgets import (
QComboBox,
QDialog,
@@ -10,12 +10,15 @@ from PySide6.QtWidgets import (
QVBoxLayout,
QLineEdit,
QHBoxLayout,
QStyledItemDelegate,
QToolTip,
)
from dcs.unittype import FlyingType
from game import Game
from game.ato.flight import Flight
from game.ato.flightroster import FlightRoster
from game.ato.loadouts import Loadout
from game.ato.package import Package
from game.ato.starttype import StartType
from game.squadrons.squadron import Squadron
@@ -85,6 +88,15 @@ class QFlightCreator(QDialog):
self.update_max_size(self.squadron_selector.aircraft_available)
layout.addLayout(QLabeledWidget("Size:", self.flight_size_spinner))
hbox = QHBoxLayout()
self.loadout_selector = QComboBox()
self.loadout_selector.setMaximumWidth(250)
self.loadout_selector.setItemDelegate(LoadoutDelegate(self.loadout_selector))
self._init_loadout_selector()
hbox.addWidget(QLabel("Loadout:"))
hbox.addWidget(self.loadout_selector)
layout.addLayout(hbox)
required_start_type = None
squadron = self.squadron_selector.currentData()
if squadron is None:
@@ -206,6 +218,7 @@ class QFlightCreator(QDialog):
member.assign_tgp_laser_code(
self.game.laser_code_registry.alloc_laser_code()
)
member.loadout = self.current_loadout()
# noinspection PyUnresolvedReferences
self.created.emit(flight)
@@ -217,8 +230,9 @@ class QFlightCreator(QDialog):
self.task_selector.currentData(), new_aircraft
)
self.divert.change_aircraft(new_aircraft)
self.roster_editor.pilots_changed.emit()
if self.aircraft_selector.currentData() is not None:
self._init_loadout_selector()
def on_departure_changed(self, departure: ControlPoint) -> None:
if isinstance(departure, OffMapSpawn):
@@ -290,3 +304,38 @@ class QFlightCreator(QDialog):
start_type = self.game.settings.default_start_type
self.start_type.setCurrentText(start_type.value)
def current_loadout(self) -> Loadout:
loadout = self.loadout_selector.currentData()
if loadout is None:
return Loadout.empty_loadout()
return loadout
def _init_loadout_selector(self):
self.loadout_selector.clear()
ac_type = self.aircraft_selector.currentData()
if ac_type is None:
return
for loadout in Loadout.iter_for_aircraft(ac_type):
self.loadout_selector.addItem(loadout.name, loadout)
for loadout in Loadout.default_loadout_names_for(
self.task_selector.currentData()
):
index = self.loadout_selector.findText(loadout)
if index != -1:
self.loadout_selector.setCurrentIndex(index)
break
class LoadoutDelegate(QStyledItemDelegate):
def helpEvent(self, event, view, option, index):
if event.type() == QEvent.ToolTip:
loadout = index.data(Qt.UserRole)
if loadout:
max_pylon = max(loadout.pylons.keys(), default=0)
pylons_info = "\n".join(
f"Pylon {pylon}: {loadout.pylons.get(pylon, 'Clean')}"
for pylon in range(1, max_pylon + 1)
)
QToolTip.showText(event.globalPos(), pylons_info, view)
return True

View File

@@ -105,8 +105,7 @@ class QLoadoutEditor(QGroupBox):
ac_id = ac_type.id
payloads_folder = payloads_dir()
payload_file = payloads_folder / f"{ac_id}.lua"
if not payloads_folder.exists():
payloads_folder.mkdir()
payloads_folder.mkdir(parents=True, exist_ok=True)
ac_type.payloads[payload_name] = DcsPayload.from_flight_member(
self.flight_member, payload_name
).to_dict()

View File

@@ -1,3 +1,5 @@
from typing import Optional
from PySide6.QtCore import QItemSelectionModel, QPoint, QModelIndex
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
@@ -32,6 +34,7 @@ class AltitudeEditorDelegate(QStyledItemDelegate):
class QFlightWaypointList(QTableView):
def __init__(self, package: Package, flight: Flight):
super().__init__()
self._last_waypoint: Optional[FlightWaypoint] = None
self.package = package
self.flight = flight
@@ -83,7 +86,10 @@ class QFlightWaypointList(QTableView):
self.update(self.currentIndex())
def _add_waypoint_row(
self, row: int, flight: Flight, waypoint: FlightWaypoint
self,
row: int,
flight: Flight,
waypoint: FlightWaypoint,
) -> None:
self.model.insertRow(self.model.rowCount())
@@ -112,18 +118,36 @@ class QFlightWaypointList(QTableView):
name = self.model.item(i, 0).text()
self.flight.flight_plan.waypoints[i].pretty_name = name
def tot_text(self, flight: Flight, waypoint: FlightWaypoint) -> str:
def tot_text(
self,
flight: Flight,
waypoint: FlightWaypoint,
) -> str:
if waypoint.waypoint_type == FlightWaypointType.TAKEOFF:
self.update_last_tot(flight.flight_plan.takeoff_time())
self._last_waypoint = waypoint
return self.takeoff_text(flight)
prefix = ""
time = flight.flight_plan.tot_for_waypoint(waypoint)
if time is None:
prefix = "Depart "
time = flight.flight_plan.depart_time_for_waypoint(waypoint)
if time is None:
if time is None and self._last_waypoint is not None:
prefix = ""
timedelta = flight.flight_plan.travel_time_between_waypoints(
self._last_waypoint, waypoint
)
time = self._last_tot + timedelta
else:
return ""
self.update_last_tot(time)
self._last_waypoint = waypoint
return f"{prefix}{time:%H:%M:%S}"
@staticmethod
def takeoff_text(flight: Flight) -> str:
return f"{flight.flight_plan.takeoff_time():%H:%M:%S}"
def update_last_tot(self, time) -> None:
if time is not None:
self._last_tot = time

View File

@@ -35,6 +35,7 @@ class QFactionUnits(QScrollArea):
self.parent = parent
self.faction = faction
self._create_checkboxes(show_jtac)
self.show_jtac = show_jtac
def _add_checkboxes(
self,
@@ -214,7 +215,7 @@ class QFactionUnits(QScrollArea):
self.faction = faction
self.content = QWidget()
self.setWidget(self.content)
self._create_checkboxes()
self._create_checkboxes(self.show_jtac)
self.update()
if self.parent:
self.parent.update()

View File

@@ -2,28 +2,29 @@ local unitPayloads = {
["name"] = "AV8BNA",
["payloads"] = {
[1] = {
["name"] = "STRIKE",
["displayName"] = "Retribution OCA/Runway",
["name"] = "Retribution OCA/Runway",
["pylons"] = {
[1] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 8,
},
[3] = {
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1,
},
[4] = {
[3] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 7,
},
[5] = {
[4] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 6,
},
[5] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 3,
@@ -38,26 +39,27 @@ local unitPayloads = {
},
},
[2] = {
["name"] = "SEAD",
["displayName"] = "Retribution SEAD Escort",
["name"] = "Retribution SEAD Escort",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{LAU_7_AGM_122_SIDEARM}",
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 2,
},
[4] = {
["CLSID"] = "{LAU_7_AGM_122_SIDEARM}",
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 7,
},
[5] = {
["CLSID"] = "{ALQ_164_RF_Jammer}",
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[6] = {
@@ -74,39 +76,36 @@ local unitPayloads = {
},
},
[3] = {
["name"] = "CAS",
["displayName"] = "Retribution DEAD",
["name"] = "Retribution DEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[3] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 2,
["num"] = 6,
},
[4] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 7,
["num"] = 3,
},
[5] = {
["CLSID"] = "{GAU_12_Equalizer}",
["num"] = 4,
},
[6] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[7] = {
["CLSID"] = "{LAU-131 - 7 AGR-20 M282}",
["num"] = 6,
[6] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 7,
},
[8] = {
["CLSID"] = "{LAU-131 - 7 AGR-20 M282}",
["num"] = 3,
[7] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 2,
},
},
["tasks"] = {
@@ -114,27 +113,36 @@ local unitPayloads = {
},
},
[4] = {
["name"] = "CAP",
["displayName"] = "Retribution BAI",
["name"] = "Retribution BAI",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{AIM-9M-ON-ADAPTER}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{AIM-9M-ON-ADAPTER}",
["CLSID"] = "{BRU-70A_3*GBU-54}",
["num"] = 7,
},
[4] = {
["CLSID"] = "{BRU-70A_2*GBU-54_RIGHT}",
["num"] = 6,
},
[5] = {
["CLSID"] = "{GAU_12_Equalizer}",
["num"] = 4,
["CLSID"] = "{BRU-70A_2*GBU-54_LEFT}",
["num"] = 3,
},
[6] = {
["CLSID"] = "{BRU-70A_3*GBU-54}",
["num"] = 2,
},
[7] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
},
["tasks"] = {
@@ -142,7 +150,8 @@ local unitPayloads = {
},
},
[5] = {
["name"] = "INTERCEPT",
["displayName"] = "Retribution OCA/Aircraft",
["name"] = "Retribution OCA/Aircraft",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
@@ -153,16 +162,24 @@ local unitPayloads = {
["num"] = 1,
},
[3] = {
["CLSID"] = "{AIM-9M-ON-ADAPTER}",
["num"] = 2,
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[4] = {
["CLSID"] = "{AIM-9M-ON-ADAPTER}",
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 7,
},
[5] = {
["CLSID"] = "{GAU_12_Equalizer}",
["num"] = 4,
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 6,
},
[6] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 2,
},
},
["tasks"] = {
@@ -170,14 +187,52 @@ local unitPayloads = {
},
},
[6] = {
["name"] = "ANTISHIP",
["displayName"] = "Retribution CAS",
["name"] = "Retribution CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[2] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 3,
},
[3] = {
["CLSID"] = "LAU_117_AGM_65F",
["num"] = 6,
},
[4] = {
["CLSID"] = "{BRU-70A_2*GBU-54_LEFT}",
["num"] = 7,
},
[5] = {
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{BRU-70A_2*GBU-54_RIGHT}",
["num"] = 2,
},
},
["tasks"] = {
[1] = 31,
},
},
[7] = {
["displayName"] = "Retribution SEAD Sweep",
["name"] = "Retribution SEAD Sweep",
["pylons"] = {
[1] = {
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[3] = {
@@ -205,45 +260,107 @@ local unitPayloads = {
[1] = 31,
},
},
[7] = {
["displayName"] = "Retribution OCA/Runway",
["name"] = "Retribution OCA/Runway",
[8] = {
["displayName"] = "Retribution Strike",
["name"] = "Retribution Strike",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[3] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1,
},
[5] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 6,
},
[6] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 7,
},
[7] = {
["CLSID"] = "{GBU_32_V_2B}",
["num"] = 2,
},
},
["tasks"] = {
[1] = 31,
},
},
[9] = {
["displayName"] = "Retribution Anti-ship",
["name"] = "Retribution Anti-ship",
["pylons"] = {
[1] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F16A4DE0-116C-4A71-97F0-2CF85B0313EC}",
["num"] = 7,
},
[4] = {
["CLSID"] = "{F16A4DE0-116C-4A71-97F0-2CF85B0313EC}",
["num"] = 6,
},
[5] = {
["CLSID"] = "{A111396E-D3E8-4b9c-8AC9-2432489304D5}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{F16A4DE0-116C-4A71-97F0-2CF85B0313EC}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{F16A4DE0-116C-4A71-97F0-2CF85B0313EC}",
["num"] = 2,
},
},
["tasks"] = {
[1] = 31,
},
},
[10] = {
["displayName"] = "Retribution SEAD",
["name"] = "Retribution SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 8,
},
[2] = {
["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}",
["num"] = 7,
["CLSID"] = "{AGM_122_SIDEARM}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{BRU-42_2*Mk-83_RIGHT}",
["num"] = 6,
["CLSID"] = "{LAU_7_AGM_122_SIDEARM}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{LAU_7_AGM_122_SIDEARM}",
["num"] = 7,
},
[5] = {
["CLSID"] = "{ALQ_164_RF_Jammer}",
["num"] = 5,
},
[5] = {
["CLSID"] = "{GAU_12_Equalizer}",
["num"] = 4,
},
[6] = {
["CLSID"] = "{BRU-42_2*Mk-83_LEFT}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{7A44FF09-527C-4B7E-B42B-3F111CFE50FB}",
["num"] = 2,
},
[8] = {
["CLSID"] = "{6CEB49FC-DED8-4DED-B053-E1F033FF72D3}",
["num"] = 1,
},
},
["tasks"] = {
[1] = 34,
[1] = 31,
},
},
},