diff --git a/qt_ui/main.py b/qt_ui/main.py
index 2acc3b6b..688b7d00 100644
--- a/qt_ui/main.py
+++ b/qt_ui/main.py
@@ -1,17 +1,31 @@
+import logging
+import os
import sys
from time import sleep
+import dcs
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QLabel, QSplashScreen
from qt_ui import uiconstants
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow
-from userdata import persistency
+from userdata import persistency, logging as logging_module
+
if __name__ == "__main__":
+ assert len(sys.argv) >= 3, "__init__.py should be started with two mandatory arguments: %UserProfile% location and application version"
+
+ persistency.setup(sys.argv[1])
+ dcs.planes.FlyingType.payload_dirs = [
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads")]
+
+ VERSION_STRING = sys.argv[2]
+ logging_module.setup_version_string(VERSION_STRING)
+ logging.info("Using {} as userdata folder".format(persistency.base_path()))
+
app = QApplication(sys.argv)
# Splash screen setup
@@ -38,4 +52,5 @@ if __name__ == "__main__":
window.show()
splash.finish(window)
- sys.exit(app.exec_())
\ No newline at end of file
+ sys.exit(app.exec_())
+
diff --git a/qt_ui/widgets/map/QMapControlPoint.py b/qt_ui/widgets/map/QMapControlPoint.py
index a3ac9630..9d930443 100644
--- a/qt_ui/widgets/map/QMapControlPoint.py
+++ b/qt_ui/widgets/map/QMapControlPoint.py
@@ -52,7 +52,12 @@ class QMapControlPoint(QGraphicsRectItem):
self.update()
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent):
- openBaseMenu = QAction("Open base menu")
+
+ if self.model.captured:
+ openBaseMenu = QAction("Open base menu")
+ else:
+ openBaseMenu = QAction("Open intel menu")
+
openBaseMenu.triggered.connect(self.openBaseMenu)
menu = QMenu("Menu", self.parent)
diff --git a/qt_ui/widgets/map/QMapEvent.py b/qt_ui/widgets/map/QMapEvent.py
index 11e9f83d..745dbf67 100644
--- a/qt_ui/widgets/map/QMapEvent.py
+++ b/qt_ui/widgets/map/QMapEvent.py
@@ -15,7 +15,6 @@ class QMapEvent(QGraphicsRectItem):
self.parent = parent
self.setAcceptHoverEvents(True)
self.setZValue(2)
- print(x,y,w,h)
self.setToolTip(str(self.gameEvent))
def paint(self, painter, option, widget=None):
@@ -31,7 +30,6 @@ class QMapEvent(QGraphicsRectItem):
painter.setBrush(CONST.COLORS["red"])
painter.drawRect(option.rect)
- print(option.rect)
painter.drawPixmap(option.rect, CONST.EVENT_ICONS[self.gameEvent.__class__])
painter.restore()
@@ -39,5 +37,5 @@ class QMapEvent(QGraphicsRectItem):
self.openBriefing()
def openBriefing(self):
- self.briefing = QBriefingWindow(self.window(), self.gameEvent)
+ self.briefing = QBriefingWindow(self.gameEvent)
self.briefing.show()
\ No newline at end of file
diff --git a/qt_ui/windows/GameUpdateSignal.py b/qt_ui/windows/GameUpdateSignal.py
index 59bf1e02..86546757 100644
--- a/qt_ui/windows/GameUpdateSignal.py
+++ b/qt_ui/windows/GameUpdateSignal.py
@@ -1,11 +1,22 @@
from PySide2.QtCore import QObject, Signal
+
from game import Game
+from game.event import Event, Debriefing
+
+
+class DebriefingSignal:
+
+ def __init__(self, game, gameEvent, debriefing):
+ self.game = game
+ self.gameEvent = gameEvent
+ self.debriefing = debriefing
class GameUpdateSignal(QObject):
instance = None
gameupdated = Signal(Game)
+ debriefingReceived = Signal(DebriefingSignal)
def __init__(self):
super(GameUpdateSignal, self).__init__()
@@ -14,6 +25,11 @@ class GameUpdateSignal(QObject):
def updateGame(self, game: Game):
self.gameupdated.emit(game)
+ def sendDebriefing(self, game: Game, gameEvent: Event, debriefing: Debriefing):
+ sig = DebriefingSignal(game, gameEvent, debriefing)
+ self.gameupdated.emit(game)
+ self.debriefingReceived.emit(sig)
+
@staticmethod
def get_instance():
return GameUpdateSignal.instance
diff --git a/qt_ui/windows/QBaseMenu.py b/qt_ui/windows/QBaseMenu.py
index 5bf09343..7047c1ce 100644
--- a/qt_ui/windows/QBaseMenu.py
+++ b/qt_ui/windows/QBaseMenu.py
@@ -1,6 +1,7 @@
from PySide2.QtCore import Qt
from PySide2.QtGui import QWindow, QCloseEvent
-from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QFrame, QDialog, QVBoxLayout, QGridLayout, QPushButton
+from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QFrame, QDialog, QVBoxLayout, QGridLayout, QPushButton, \
+ QGroupBox
from dcs.unittype import UnitType
from game.event import UnitsDeliveryEvent
@@ -30,7 +31,7 @@ class QBaseMenu(QDialog):
self.deliveryEvent = self.game.units_delivery_event(self.cp)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
- self.setMinimumSize(200, 200)
+ self.setMinimumSize(300, 200)
self.setModal(True)
self.initUi()
@@ -52,13 +53,22 @@ class QBaseMenu(QDialog):
self.topLayoutWidget.setProperty("style", "baseMenuHeader")
self.topLayoutWidget.setLayout(self.topLayout)
- units = {
- CAP: db.find_unittype(CAP, self.game.player_name),
- Embarking: db.find_unittype(Embarking, self.game.player_name),
- AirDefence: db.find_unittype(AirDefence, self.game.player_name),
- CAS: db.find_unittype(CAS, self.game.player_name),
- PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name),
- }
+ if self.cp.captured:
+ units = {
+ CAP: db.find_unittype(CAP, self.game.player_name),
+ Embarking: db.find_unittype(Embarking, self.game.player_name),
+ CAS: db.find_unittype(CAS, self.game.player_name),
+ PinpointStrike: db.find_unittype(PinpointStrike, self.game.player_name),
+ AirDefence: db.find_unittype(AirDefence, self.game.player_name),
+ }
+ else:
+ units = {
+ CAP: db.find_unittype(CAP, self.game.enemy_name),
+ Embarking: db.find_unittype(Embarking, self.game.enemy_name),
+ AirDefence: db.find_unittype(AirDefence, self.game.enemy_name),
+ CAS: db.find_unittype(CAS, self.game.enemy_name),
+ PinpointStrike: db.find_unittype(PinpointStrike, self.game.enemy_name),
+ }
self.mainLayout = QVBoxLayout()
self.mainLayout.addWidget(self.topLayoutWidget)
@@ -111,8 +121,33 @@ class QBaseMenu(QDialog):
for unit_type in units_column:
add_purchase_row(unit_type)
+ self.mainLayout.addLayout(self.unitLayout)
+ else:
+ intel = QGroupBox("Intel")
+ intelLayout = QVBoxLayout()
+
+ row = 0
+ for task_type in units.keys():
+ units_column = list(set(units[task_type]))
+
+ if sum([self.cp.base.total_units_of_type(u) for u in units_column]) > 0:
+
+ group = QGroupBox(db.task_name(task_type))
+ groupLayout = QGridLayout()
+ group.setLayout(groupLayout)
+
+ row = 0
+ for unit_type in units_column:
+ existing_units = self.cp.base.total_units_of_type(unit_type)
+ if existing_units == 0:
+ continue
+ groupLayout.addWidget(QLabel("" + db.unit_type_name(unit_type) + ""), row, 0)
+ groupLayout.addWidget(QLabel(str(existing_units)), row, 1)
+ row += 1
+
+ intelLayout.addWidget(group)
+ self.mainLayout.addLayout(intelLayout)
- self.mainLayout.addLayout(self.unitLayout)
self.setLayout(self.mainLayout)
diff --git a/qt_ui/windows/QBriefingWindow.py b/qt_ui/windows/QBriefingWindow.py
index d8c9d9ca..a577a504 100644
--- a/qt_ui/windows/QBriefingWindow.py
+++ b/qt_ui/windows/QBriefingWindow.py
@@ -7,14 +7,15 @@ from pip._internal.utils import typing
from game.game import AWACS_BUDGET_COST, PinpointStrike, db, Event, FrontlineAttackEvent, FrontlinePatrolEvent, Task, \
UnitType
+from qt_ui.windows.QWaitingForMissionResultWindow import QWaitingForMissionResultWindow
from userdata.persistency import base_path
import qt_ui.uiconstants as CONST
class QBriefingWindow(QDialog):
- def __init__(self, parent, gameEvent: Event):
- super(QBriefingWindow, self).__init__(parent)
+ def __init__(self, gameEvent: Event):
+ super(QBriefingWindow, self).__init__()
self.gameEvent = gameEvent
self.setWindowTitle("Briefing : " + str(gameEvent))
self.setMinimumSize(200,200)
@@ -40,7 +41,7 @@ class QBriefingWindow(QDialog):
self.depart_from = QComboBox()
for cp in [b for b in self.game.theater.controlpoints if b.captured]:
- self.depart_from.addItem(str(cp.name))
+ self.depart_from.addItem(str(cp.name), cp)
self.depart_layout.addWidget(self.depart_from_label)
self.depart_layout.addWidget(self.depart_from)
@@ -91,24 +92,11 @@ class QBriefingWindow(QDialog):
scramble_row(flight_task, t, c, True, row)
row += 1
- # Options
-
-
- """
- header("Ready?")
- self.error_label = label("", columnspan=4)
- self.error_label["fg"] = RED
- Button(self.frame, text="Commit", command=self.start, **STYLES["btn-primary"]).grid(column=0, row=row,
- sticky=E, padx=5,
- pady=(10, 10))
- Button(self.frame, text="Back", command=self.dismiss, **STYLES["btn-warning"]).grid(column=3, row=row,
- sticky=E, padx=5,
- pady=(10, 10))"""
-
self.action_layout = QHBoxLayout()
self.commit_button = QPushButton("Commit")
- self.back_button = QPushButton("Commit")
+ self.back_button = QPushButton("Cancel")
self.commit_button.clicked.connect(self.start)
+ self.back_button.clicked.connect(self.close)
self.action_layout.addWidget(self.commit_button)
self.action_layout.addWidget(self.back_button)
@@ -169,7 +157,6 @@ class QBriefingWindow(QDialog):
def debriefing_directory_location(self) -> str:
return os.path.join(base_path(), "liberation_debriefings")
-
def start(self):
if self.awacs_checkbox.isChecked() == 1:
@@ -185,6 +172,11 @@ class QBriefingWindow(QDialog):
ca_slots = 0
self.gameEvent.ca_slots = ca_slots
+
+ # Resolve Departure CP
+ self.gameEvent.departure_cp = self.depart_from.itemData(self.depart_from.currentIndex())
+
+
flights = {k: {} for k in self.gameEvent.tasks} # type: db.TaskForceDict
units_scramble_counts = {} # type: typing.Dict[typing.Type[UnitType], int]
tasks_scramble_counts = {} # type: typing.Dict[typing.Type[Task], int]
@@ -243,11 +235,12 @@ class QBriefingWindow(QDialog):
self.gameEvent.player_defending(flights)
- self.gameEvent.departure_cp = self.gameEvent.from_cp
self.game.initiate_event(self.gameEvent)
- # EventResultsMenu(self.window, self.parent, self.game, self.gameEvent).display()
+ waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game)
+ waiting.show()
+ self.close()
def showErrorMessage(self, text):
about = QMessageBox()
diff --git a/qt_ui/windows/QDebriefingWindow.py b/qt_ui/windows/QDebriefingWindow.py
index 7b3919c7..af57ade5 100644
--- a/qt_ui/windows/QDebriefingWindow.py
+++ b/qt_ui/windows/QDebriefingWindow.py
@@ -1,17 +1,82 @@
-from PySide2.QtGui import QWindow
-from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget
+import os
+
+from PySide2 import QtCore
+from PySide2.QtGui import QMovie
+from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton
+
+from game.game import Event, db, Game
+from userdata.debriefing import wait_for_debriefing, Debriefing
+from userdata.persistency import base_path
-class QDebriefingWindow(QWindow):
+class QDebriefingWindow(QDialog):
- def __init__(self, parent):
- super(QDebriefingWindow, self).__init__(parent)
- self.initUi()
+ def __init__(self, debriefing: Debriefing, gameEvent: Event, game: Game):
+ super(QDebriefingWindow, self).__init__()
- def initUi(self):
- layout = QHBoxLayout()
- layout.addWidget(QLabel("TODO : This will be the debriefing menu"))
+ self.setModal(True)
+ self.setWindowTitle("Debriefing")
+ self.setMinimumSize(300, 200)
- central_widget = QWidget()
- central_widget.setLayout(layout)
- self.setCentralWidget(central_widget)
\ No newline at end of file
+ self.game = game
+ self.gameEvent = gameEvent
+ self.debriefing = debriefing
+
+ self.player_losses = debriefing.destroyed_units.get(self.game.player_country, {})
+ self.enemy_losses = debriefing.destroyed_units.get(self.game.enemy_country, {})
+
+ self.initUI()
+
+ def initUI(self):
+
+ self.layout = QVBoxLayout()
+
+ # Result
+
+ if self.gameEvent.is_successfull(self.debriefing):
+ title = QLabel("Operation Succesfull !")
+ title.setProperty("style", "title-success")
+ else:
+ title = QLabel("Operation failed !")
+ title.setProperty("style", "title-danger")
+ self.layout.addWidget(title)
+
+ # Player lost units
+ lostUnits = QGroupBox(self.game.player_country + "'s lost units :")
+ lostUnitsLayout = QGridLayout()
+ lostUnits.setLayout(lostUnitsLayout)
+
+ row = 0
+ for unit_type, count in self.player_losses.items():
+ lostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
+ lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
+ row += 1
+
+ self.layout.addWidget(lostUnits)
+
+ # Enemy lost units
+ enemylostUnits = QGroupBox(self.game.enemy_country + "'s lost units :")
+ enemylostUnitsLayout = QGridLayout()
+ enemylostUnits.setLayout(enemylostUnitsLayout)
+
+ row = 0
+ if self.debriefing.destroyed_objects:
+ enemylostUnitsLayout.addWidget(QLabel("Ground assets"), row, 0)
+ enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1)
+ row += 1
+
+ for unit_type, count in self.enemy_losses.items():
+ if count == 0:
+ continue
+ enemylostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
+ enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
+ row += 1
+
+ self.layout.addWidget(enemylostUnits)
+
+ # confirm button
+ okay = QPushButton("Okay")
+ okay.clicked.connect(self.close)
+ self.layout.addWidget(okay)
+
+ self.setLayout(self.layout)
diff --git a/qt_ui/windows/QLiberationWindow.py b/qt_ui/windows/QLiberationWindow.py
index 6b1f8856..c8f7e68f 100644
--- a/qt_ui/windows/QLiberationWindow.py
+++ b/qt_ui/windows/QLiberationWindow.py
@@ -8,7 +8,8 @@ from game import Game
from qt_ui.uiconstants import URLS
from qt_ui.widgets.QTopPanel import QTopPanel
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
-from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
+from qt_ui.windows.GameUpdateSignal import GameUpdateSignal, DebriefingSignal
+from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
from qt_ui.windows.QNewGameWizard import NewGameWizard
from userdata import persistency
@@ -52,6 +53,7 @@ class QLiberationWindow(QMainWindow):
def connectSignals(self):
GameUpdateSignal.get_instance().gameupdated.connect(self.setGame)
+ GameUpdateSignal.get_instance().debriefingReceived.connect(self.onDebriefing)
def initActions(self):
self.newGameAction = QAction("New Game", self)
@@ -154,3 +156,8 @@ class QLiberationWindow(QMainWindow):
about.setText(text)
print(about.textFormat())
about.exec_()
+
+ def onDebriefing(self, debrief: DebriefingSignal):
+ print("On Debriefing")
+ self.debriefing = QDebriefingWindow(debrief.debriefing, debrief.gameEvent, debrief.game)
+ self.debriefing.show()
diff --git a/qt_ui/windows/QWaitingForMissionResultWindow.py b/qt_ui/windows/QWaitingForMissionResultWindow.py
new file mode 100644
index 00000000..b80e8506
--- /dev/null
+++ b/qt_ui/windows/QWaitingForMissionResultWindow.py
@@ -0,0 +1,61 @@
+import os
+
+from PySide2 import QtCore
+from PySide2.QtGui import QMovie
+from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout
+
+from game.game import Event, Game
+from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
+from userdata.debriefing import wait_for_debriefing, Debriefing
+from userdata.persistency import base_path
+
+
+class QWaitingForMissionResultWindow(QDialog):
+
+ def __init__(self, gameEvent: Event, game: Game):
+ super(QWaitingForMissionResultWindow, self).__init__()
+ self.setModal(True)
+ self.gameEvent = gameEvent
+ self.game = game
+ self.setWindowTitle("Waiting for mission completion.")
+ self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False)
+
+ self.initUi()
+ wait_for_debriefing(lambda debriefing: self.process_debriefing(debriefing))
+
+ def initUi(self):
+ self.layout = QVBoxLayout()
+ self.layout.addWidget(QLabel("You are clear for takeoff !"))
+ self.layout.addWidget(QLabel("In DCS open and play the mission : "))
+ self.layout.addWidget(QLabel("liberation_nextturn"))
+ self.layout.addWidget(QLabel("or"))
+ self.layout.addWidget(QLabel("liberation_nextturn_quick"))
+ self.layout.addWidget(QLabel("Then save the debriefing to the folder :"))
+ self.layout.addWidget(QLabel(self.debriefing_directory_location()))
+
+ progress = QLabel("")
+ progress.setAlignment(QtCore.Qt.AlignCenter)
+ progressBar = QMovie("./resources/ui/loader.gif")
+ progress.setMovie(progressBar)
+ self.layout.addWidget(progress)
+ progressBar.start()
+
+ self.setLayout(self.layout)
+
+ def process_debriefing(self, debriefing: Debriefing):
+
+ print("DEBRIEFING !!")
+
+ debriefing.calculate_units(regular_mission=self.gameEvent.operation.regular_mission,
+ quick_mission=self.gameEvent.operation.quick_mission,
+ player_country=self.game.player_country,
+ enemy_country=self.game.enemy_country)
+
+ self.game.finish_event(event=self.gameEvent, debriefing=debriefing)
+ self.game.pass_turn(ignored_cps=[self.gameEvent.to_cp, ])
+
+ GameUpdateSignal.get_instance().sendDebriefing(self.game, self.gameEvent, debriefing)
+ self.close()
+
+ def debriefing_directory_location(self) -> str:
+ return os.path.join(base_path(), "liberation_debriefings")
diff --git a/resources/ui/loader.gif b/resources/ui/loader.gif
new file mode 100644
index 00000000..47adbf03
Binary files /dev/null and b/resources/ui/loader.gif differ
diff --git a/userdata/debriefing.py b/userdata/debriefing.py
index 4d50f596..5648684b 100644
--- a/userdata/debriefing.py
+++ b/userdata/debriefing.py
@@ -139,7 +139,7 @@ class Debriefing:
for unit in group.units:
if unit.id in self._dead_units:
unit_type = db.unit_type_of(unit)
- logging.info("debriefing: found dead unit {} ({}, {})".format(str(unit.name), unit.id, unit_type))
+ logging.info("debriefing: found dead unit {} ({}, {}) for country {}".format(str(unit.name), unit.id, unit_type, country_name))
assert country_name
assert unit_type