Mission planning polishing.

This commit is contained in:
Khopa 2020-06-22 21:31:25 +02:00
parent fe02df27a2
commit 56cf6bdaa4
15 changed files with 124 additions and 91 deletions

View File

@ -59,7 +59,7 @@
* **[Maps/Campaign]** Now using Vasiani airbase instead of Soganlung airport in Caucasus campaigns (more parking slot)
* **[Info Panel]** Message displayed on base capture event stated that the enemy captured an airbase, while it was the player who captured it.
* **[Map View]** Graphical glitch on map when one building of an objective was destroyed, but not the others
* **[Mission Planner]** The list of flights was not updated on departure time change.
# 2.0 RC 6

View File

@ -659,8 +659,8 @@ class FlightPlanner:
ascend = FlightWaypoint(pos_ascend.x, pos_ascend.y, self.doctrine["PATTERN_ALTITUDE"])
ascend.name = "ASCEND"
ascend.alt_type = "RADIO"
ascend.description = "Ascend to alt [" + str(meter_to_feet(self.doctrine["PATTERN_ALTITUDE"])) + " ft AGL], then proceed to next waypoint"
ascend.pretty_name = "Ascend to alt [" + str(meter_to_feet(self.doctrine["PATTERN_ALTITUDE"])) + " ft AGL]"
ascend.description = "Ascend"
ascend.pretty_name = "Ascend"
ascend.waypoint_type = FlightWaypointType.ASCEND_POINT
return ascend
@ -676,8 +676,8 @@ class FlightPlanner:
descend = FlightWaypoint(descend.x, descend.y, self.doctrine["PATTERN_ALTITUDE"])
descend.name = "DESCEND"
descend.alt_type = "RADIO"
descend.description = "Descend to pattern alt [" + str(meter_to_feet(self.doctrine["PATTERN_ALTITUDE"])) + " ft AGL], contact tower, and land"
descend.pretty_name = "Descend to pattern alt [" + str(meter_to_feet(self.doctrine["PATTERN_ALTITUDE"])) + " ft AGL]"
descend.description = "Descend to pattern alt"
descend.pretty_name = "Descend to pattern alt"
descend.waypoint_type = FlightWaypointType.DESCENT_POINT
return descend

View File

@ -1,19 +1,17 @@
import logging
import os
import sys
from shutil import copyfile
import dcs
from PySide2 import QtWidgets
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QSplashScreen
from dcs import installation
from qt_ui import uiconstants
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow
from qt_ui.windows.preferences.QLiberationFirstStartWindow import QLiberationFirstStartWindow
from userdata import persistency, logging as logging_module, liberation_install
from userdata import liberation_install, persistency, logging_config
if __name__ == "__main__":
@ -24,8 +22,8 @@ if __name__ == "__main__":
app.setStyleSheet(stylesheet.read())
# Logging setup
VERSION_STRING = "2.0RC6"
logging_module.setup_version_string(VERSION_STRING)
VERSION_STRING = "2.0RC7"
logging_config.init_logging(VERSION_STRING)
# Inject custom payload in pydcs framework
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
@ -80,6 +78,7 @@ if __name__ == "__main__":
logging.info("QT App terminated with status code : " + str(qt_execution_code))
logging.info("Attempt to restore original mission scripting file")
liberation_install.restore_original_mission_scripting()
sys.exit(qt_execution_code)
logging.info("QT process exited with code : " + str(qt_execution_code))
sys.exit(0)

View File

@ -9,7 +9,6 @@ import qt_ui.uiconstants as CONST
from game import db, Game
from gen import namegen
from theater import start_generator, persiangulf, nevada, caucasus, ConflictTheater, normandy, thechannel
from userdata.logging import version_string
class NewGameWizard(QtWidgets.QWizard):
@ -109,7 +108,7 @@ class NewGameWizard(QtWidgets.QWizard):
game.budget = int(game.budget * multiplier)
game.settings.multiplier = multiplier
game.settings.sams = True
game.settings.version = version_string()
game.settings.version = "2.0RC7"
if midgame:
game.budget = game.budget * 4 * len(list(conflicttheater.conflicts()))

View File

@ -18,3 +18,9 @@ class QFlightItem(QStandardItem):
self.setText("["+str(self.flight.flight_type.name[:6])+"] "
+ str(self.flight.count) + " x " + db.unit_type_name(self.flight.unit_type)
+ " in " + str(self.flight.scheduled_in) + " minutes")
def update(self, flight):
self.flight = flight
self.setText("[" + str(self.flight.flight_type.name[:6]) + "] "
+ str(self.flight.count) + " x " + db.unit_type_name(self.flight.unit_type)
+ " in " + str(self.flight.scheduled_in) + " minutes")

View File

@ -16,7 +16,7 @@ class QMissionPlanning(QDialog):
super(QMissionPlanning, self).__init__()
self.game = game
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setMinimumSize(800, 420)
self.setMinimumSize(1000, 420)
self.setModal(True)
self.setWindowTitle("Mission Preparation")
self.setWindowIcon(EVENT_ICONS["strike"])
@ -42,9 +42,11 @@ class QMissionPlanning(QDialog):
self.planned_flight_view.selectionModel().selectionChanged.connect(self.on_flight_selection_change)
if len(self.planned_flight_view.flight_planner.flights) > 0:
self.flight_planner = QFlightPlanner(self.planned_flight_view.flight_planner.flights[0], self.game, self.planned_flight_view.flight_planner)
self.flight_planner = QFlightPlanner(self.planned_flight_view.flight_planner.flights[0], self.game, self.planned_flight_view.flight_planner, 0)
self.flight_planner.on_planned_flight_changed.connect(self.update_planned_flight_view)
else:
self.flight_planner = QFlightPlanner(None, self.game, self.planned_flight_view.flight_planner)
self.flight_planner = QFlightPlanner(None, self.game, self.planned_flight_view.flight_planner, 0)
self.flight_planner.on_planned_flight_changed.connect(self.update_planned_flight_view)
self.add_flight_button = QPushButton("Add Flight")
self.add_flight_button.clicked.connect(self.on_add_flight)
@ -88,7 +90,7 @@ class QMissionPlanning(QDialog):
print("On flight selection change")
index = self.planned_flight_view.selectionModel().currentIndex().row()
self.planned_flight_view.repaint();
self.planned_flight_view.repaint()
if self.flight_planner is not None:
self.flight_planner.clearTabs()
@ -97,9 +99,12 @@ class QMissionPlanning(QDialog):
flight = self.planner.flights[index]
except IndexError:
flight = None
self.flight_planner = QFlightPlanner(flight, self.game, self.planner)
self.flight_planner = QFlightPlanner(flight, self.game, self.planner, self.flight_planner.currentIndex())
self.flight_planner.on_planned_flight_changed.connect(self.update_planned_flight_view)
self.layout.addWidget(self.flight_planner, 0, 1)
def update_planned_flight_view(self):
self.planned_flight_view.update_content()
def on_add_flight(self):
possible_aircraft_type = list(self.selected_cp.base.aircraft.keys())

View File

@ -12,14 +12,21 @@ class QPlannedFlightsView(QListView):
super(QPlannedFlightsView, self).__init__()
self.model = QStandardItemModel(self)
self.setModel(self.model)
self.flightitems = []
self.setIconSize(QSize(91, 24))
self.setSelectionBehavior(QAbstractItemView.SelectItems)
if flight_planner:
self.set_flight_planner(flight_planner)
def update_content(self, row=0):
def update_content(self):
for i, f in enumerate(self.flight_planner.flights):
self.model.appendRow(QFlightItem(f))
self.flightitems[i].update(f)
def setup_content(self, row=0):
for i, f in enumerate(self.flight_planner.flights):
item = QFlightItem(f)
self.model.appendRow(item)
self.flightitems.append(item)
self.setSelectedFlight(row)
self.repaint()
@ -38,4 +45,4 @@ class QPlannedFlightsView(QListView):
self.clear_layout()
self.flight_planner = flight_planner
if self.flight_planner:
self.update_content(row)
self.setup_content(row)

View File

@ -1,3 +1,4 @@
from PySide2.QtCore import Signal
from PySide2.QtWidgets import QTabWidget, QFrame, QGridLayout, QLabel
from gen.flights.flight import Flight
@ -9,17 +10,25 @@ from qt_ui.windows.mission.flight.waypoints.QFlightWaypointTab import QFlightWay
class QFlightPlanner(QTabWidget):
def __init__(self, flight: Flight, game: Game, planner):
on_planned_flight_changed = Signal()
def __init__(self, flight: Flight, game: Game, planner, selected_tab):
super(QFlightPlanner, self).__init__()
print(selected_tab)
self.tabCount = 0
if flight:
self.general_settings_tab = QGeneralFlightSettingsTab(flight, game, planner)
self.general_settings_tab.on_flight_settings_changed.connect(lambda: self.on_planned_flight_changed.emit())
self.payload_tab = QFlightPayloadTab(flight, game)
self.waypoint_tab = QFlightWaypointTab(game, flight)
self.waypoint_tab.on_flight_changed.connect(lambda: self.on_planned_flight_changed.emit())
self.addTab(self.general_settings_tab, "General Flight settings")
self.addTab(self.payload_tab, "Payload")
self.addTab(self.waypoint_tab, "Waypoints")
self.tabCount = 3
self.setCurrentIndex(selected_tab)
else:
tabError = QFrame()
l = QGridLayout()

View File

@ -24,5 +24,7 @@ class QFlightDepartureEditor(QGroupBox):
layout.addWidget(self.minutes)
self.setLayout(layout)
self.changed = self.departure_delta.valueChanged
def change_scheduled(self):
self.flight.scheduled_in = int(self.departure_delta.value())

View File

@ -1,7 +1,8 @@
from PySide2.QtCore import Signal
from PySide2.QtWidgets import QFrame, QGridLayout, QVBoxLayout
from gen.flights.flight import Flight
from game import Game
from gen.flights.flight import Flight
from qt_ui.windows.mission.flight.settings.QFlightDepartureEditor import QFlightDepartureEditor
from qt_ui.windows.mission.flight.settings.QFlightSlotEditor import QFlightSlotEditor
from qt_ui.windows.mission.flight.settings.QFlightStartType import QFlightStartType
@ -9,6 +10,7 @@ from qt_ui.windows.mission.flight.settings.QFlightTypeTaskInfo import QFlightTyp
class QGeneralFlightSettingsTab(QFrame):
on_flight_settings_changed = Signal()
def __init__(self, flight: Flight, game: Game, planner):
super(QGeneralFlightSettingsTab, self).__init__()
@ -19,18 +21,19 @@ class QGeneralFlightSettingsTab(QFrame):
def init_ui(self):
layout = QGridLayout()
self.flight_info = QFlightTypeTaskInfo(self.flight)
self.flight_departure = QFlightDepartureEditor(self.flight)
self.flight_slots = QFlightSlotEditor(self.flight, self.game, self.planner)
self.flight_start_type = QFlightStartType(self.flight)
layout.addWidget(self.flight_info, 0, 0)
layout.addWidget(self.flight_departure, 1, 0)
layout.addWidget(self.flight_slots, 2, 0)
layout.addWidget(self.flight_start_type, 3, 0)
flight_info = QFlightTypeTaskInfo(self.flight)
flight_departure = QFlightDepartureEditor(self.flight)
flight_slots = QFlightSlotEditor(self.flight, self.game, self.planner)
flight_start_type = QFlightStartType(self.flight)
layout.addWidget(flight_info, 0, 0)
layout.addWidget(flight_departure, 1, 0)
layout.addWidget(flight_slots, 2, 0)
layout.addWidget(flight_start_type, 3, 0)
vstretch = QVBoxLayout()
vstretch.addStretch()
layout.addLayout(vstretch, 3, 0)
self.setLayout(layout)
self.flight_start_type.setEnabled(self.flight.client_count > 0)
self.flight_slots.changed.connect(lambda: self.flight_start_type.setEnabled(self.flight.client_count > 0))
flight_start_type.setEnabled(self.flight.client_count > 0)
flight_slots.changed.connect(lambda: flight_start_type.setEnabled(self.flight.client_count > 0))
flight_departure.changed.connect(lambda: self.on_flight_settings_changed.emit())

View File

@ -1,7 +1,8 @@
from PySide2.QtCore import QItemSelectionModel, QPoint, Qt
from PySide2.QtGui import QStandardItemModel
from PySide2.QtWidgets import QListView, QTableView, QHeaderView
from PySide2.QtCore import QItemSelectionModel, QPoint
from PySide2.QtGui import QStandardItemModel, QStandardItem
from PySide2.QtWidgets import QTableView, QHeaderView
from game.utils import meter_to_feet
from gen.flights.flight import Flight, FlightWaypoint
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointItem import QWaypointItem
@ -13,7 +14,11 @@ class QFlightWaypointList(QTableView):
self.model = QStandardItemModel(self)
self.setModel(self.model)
self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.model.setHorizontalHeaderLabels(["Name"])
self.model.setHorizontalHeaderLabels(["Name", "Alt"])
header = self.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.flight = flight
if len(self.flight.points) > 0:
@ -28,10 +33,14 @@ class QFlightWaypointList(QTableView):
def update_list(self):
self.model.clear()
self.model.setHorizontalHeaderLabels(["Name", "Alt"])
takeoff = FlightWaypoint(self.flight.from_cp.position.x, self.flight.from_cp.position.y, 0)
takeoff.description = "Take Off"
takeoff.name = takeoff.pretty_name = "Take Off from " + self.flight.from_cp.name
self.model.appendRow(QWaypointItem(takeoff, 0))
self.model.setItem(0, 1, QStandardItem("0 ft AGL"))
for i, point in enumerate(self.flight.points):
self.model.appendRow(QWaypointItem(point, i + 1))
self.model.insertRow(self.model.rowCount())
self.model.setItem(self.model.rowCount()-1, 0, QWaypointItem(point, i + 1))
self.model.setItem(self.model.rowCount()-1, 1, QStandardItem(str(meter_to_feet(point.alt)) + " ft " + str(["AGL" if point.alt_type == "RADIO" else "MSL"][0])))
self.selectionModel().setCurrentIndex(self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select)

View File

@ -1,16 +1,20 @@
from PySide2.QtCore import Signal
from PySide2.QtWidgets import QFrame, QGridLayout, QLabel, QPushButton, QVBoxLayout
from gen.flights.flight import Flight, FlightWaypoint, FlightWaypointType
from game import Game
from gen.flights.flight import Flight
from qt_ui.windows.mission.flight.generator.QCAPMissionGenerator import QCAPMissionGenerator
from qt_ui.windows.mission.flight.generator.QCASMissionGenerator import QCASMissionGenerator
from qt_ui.windows.mission.flight.generator.QSEADMissionGenerator import QSEADMissionGenerator
from qt_ui.windows.mission.flight.generator.QSTRIKEMissionGenerator import QSTRIKEMissionGenerator
from qt_ui.windows.mission.flight.waypoints.QFlightWaypointList import QFlightWaypointList
from qt_ui.windows.mission.flight.waypoints.QPredefinedWaypointSelectionWindow import QPredefinedWaypointSelectionWindow
from game import Game
class QFlightWaypointTab(QFrame):
on_flight_changed = Signal()
def __init__(self, game: Game, flight: Flight):
super(QFlightWaypointTab, self).__init__()
self.flight = flight
@ -73,39 +77,53 @@ class QFlightWaypointTab(QFrame):
if wpt > 0:
del self.flight.points[wpt-1]
self.flight_waypoint_list.update_list()
self.on_change()
def on_fast_waypoint(self):
self.subwindow = QPredefinedWaypointSelectionWindow(self.game, self.flight, self.flight_waypoint_list)
self.subwindow.finished.connect(self.on_change)
self.subwindow.show()
def on_ascend_waypoint(self):
ascend = self.planner.generate_ascend_point(self.flight.from_cp)
self.flight.points.append(ascend)
self.flight_waypoint_list.update_list()
self.on_change()
def on_rtb_waypoint(self):
rtb = self.planner.generate_rtb_waypoint(self.flight.from_cp)
self.flight.points.append(rtb)
self.flight_waypoint_list.update_list()
self.on_change()
def on_descend_waypoint(self):
descend = self.planner.generate_descend_point(self.flight.from_cp)
self.flight.points.append(descend)
self.flight_waypoint_list.update_list()
self.on_change()
def on_cas_generator(self):
self.subwindow = QCASMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
self.subwindow.finished.connect(self.on_change)
self.subwindow.show()
def on_cap_generator(self):
self.subwindow = QCAPMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
self.subwindow.finished.connect(self.on_change)
self.subwindow.show()
def on_sead_generator(self):
self.subwindow = QSEADMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
self.subwindow.finished.connect(self.on_change)
self.subwindow.show()
def on_strike_generator(self):
self.subwindow = QSTRIKEMissionGenerator(self.game, self.flight, self.flight_waypoint_list)
self.subwindow.finished.connect(self.on_change)
self.subwindow.show()
def on_change(self):
self.flight_waypoint_list.update_list()
self.on_flight_changed.emit()

View File

@ -208,7 +208,7 @@ class QSettingsWindow(QDialog):
self.culling_distance.setMinimum(50)
self.culling_distance.setMaximum(10000)
self.culling_distance.setValue(self.game.settings.perf_culling_distance)
self.culling_distance.valueChanged.connect(self.applySettings())
self.culling_distance.valueChanged.connect(self.applySettings)
self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)

View File

@ -1,49 +0,0 @@
import logging
import traceback
import sys
from io import StringIO
from tkinter import *
from tkinter.scrolledtext import *
_version_string = None
class ShowLogsException(Exception):
pass
def _error_prompt(oops=True):
tk = Tk()
if oops:
Label(tk, text="Oops, something went wrong.").grid(row=0)
Label(tk, text="Please send following text to the developer:").grid(row=1)
text = ScrolledText(tk)
text.insert("0.0", log_stream.getvalue())
text.grid(row=2, sticky=NSEW)
tk.focus()
def _handle_exception(self, exception: BaseException, *args):
logging.exception(exception)
_error_prompt(isinstance(exception, ShowLogsException))
def setup_version_string(str):
global _version_string
_version_string = str
def version_string():
return _version_string
if "--stdout" in sys.argv:
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
else:
log_stream = StringIO()
logging.basicConfig(stream=log_stream, level=logging.INFO)
Tk.report_callback_exception = _handle_exception
logging.info("DCS Liberation {}".format(_version_string))

View File

@ -0,0 +1,25 @@
import logging
import os
from logging.handlers import RotatingFileHandler
def init_logging(version_string):
if not os.path.isdir("./logs"):
os.mkdir("logs")
logger = logging.getLogger()
formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
handler = RotatingFileHandler('./logs/liberation.log', 'a', 5000000, 1)
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
logger.addHandler(handler)
logger.info("DCS Liberation {}".format(version_string))