diff --git a/game/event/frontlineattack.py b/game/event/frontlineattack.py index 4d4ed434..d9ec1359 100644 --- a/game/event/frontlineattack.py +++ b/game/event/frontlineattack.py @@ -76,7 +76,7 @@ class FrontlineAttackEvent(Event): self.to_cp.base.affect_strength(-0.1) def player_attacking(self, flights: db.TaskForceDict): - assert CAS in flights and CAP in flights and len(flights) == 2, "Invalid flights" + # assert CAS in flights and CAP in flights and len(flights) == 2, "Invalid flights" op = FrontlineAttackOperation(game=self.game, attacker_name=self.attacker_name, @@ -97,7 +97,7 @@ class FrontlineAttackEvent(Event): self.operation = op def player_defending(self, flights: db.TaskForceDict): - assert CAP in flights and len(flights) == 1, "Invalid flights" + # assert CAP in flights and len(flights) == 1, "Invalid flights" op = FrontlineAttackOperation(game=self.game, attacker_name=self.attacker_name, diff --git a/game/game.py b/game/game.py index 7aba517e..68b7e8ac 100644 --- a/game/game.py +++ b/game/game.py @@ -307,8 +307,6 @@ class Game: self.events = [] # type: typing.List[Event] self._generate_events() - #self._generate_globalinterceptions() - # Update statistics self.game_stats.update(self) diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index b9efa8e7..d687fc95 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -47,11 +47,11 @@ class FrontlineAttackOperation(Operation): conflict=conflict) def generate(self): - if self.is_player_attack: - self.prepare_carriers(db.unitdict_from(self.strikegroup)) + #if self.is_player_attack: + # self.prepare_carriers(db.unitdict_from(self.strikegroup)) # ground units - self.armorgen.generate_vec(self.attackers, self.defenders) + # self.armorgen.generate_vec(self.attackers, self.defenders) ## strike group w/ heli support #planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map.values()} diff --git a/game/operation/operation.py b/game/operation/operation.py index aa5e2524..d0fb5aaa 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -149,16 +149,13 @@ class Operation: self.airgen.generate_flights(cp, country, self.game.planners[cp.id]) # Generate ground units on frontline everywhere - for cp in self.game.theater.controlpoints: - if cp.captured: - for cp_enn in cp.connected_points: - if not cp_enn.captured: - conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name, - self.current_mission.country(self.attacker_country), - self.current_mission.country(self.defender_country), - cp, cp_enn, self.game.theater) - armorgen = ArmorConflictGenerator(self.current_mission, conflict) - armorgen.generate_vec(cp.base.armor, cp_enn.base.armor) + for player_cp, enemy_cp in self.game.theater.conflicts(True): + conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name, + self.current_mission.country(self.attacker_country), + self.current_mission.country(self.defender_country), + player_cp, enemy_cp, self.game.theater) + armorgen = ArmorConflictGenerator(self.current_mission, conflict) + armorgen.generate_vec(player_cp.base.armor, enemy_cp.base.armor) #Setup combined arms parameters self.current_mission.groundControl.pilot_can_control_vehicles = self.ca_slots > 0 diff --git a/gen/aircraft.py b/gen/aircraft.py index 0684290b..904b7ece 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -328,7 +328,7 @@ class AircraftConflictGenerator: def setup_group_as_cas_flight(self, group, flight): group.task = CAS.name - self._setup_group(group, CAS, 0) + self._setup_group(group, CAS, flight.client_count) group.points[0].tasks.clear() group.points[0].tasks.append(CASTaskAction()) diff --git a/gen/armor.py b/gen/armor.py index e835b18d..354b3f24 100644 --- a/gen/armor.py +++ b/gen/armor.py @@ -64,6 +64,10 @@ class ArmorConflictGenerator: wayp.tasks = [] def _generate_fight_at(self, attackers: db.ArmorDict, defenders: db.ArmorDict, position: Point): + + print(attackers) + print(defenders) + if attackers: attack_pos = position.point_from_heading(self.conflict.heading - 90, FIGHT_DISTANCE) attack_dest = position.point_from_heading(self.conflict.heading + 90, FIGHT_DISTANCE * 2) diff --git a/qt_ui/widgets/QTopPanel.py b/qt_ui/widgets/QTopPanel.py index cf02b625..bd0e3936 100644 --- a/qt_ui/widgets/QTopPanel.py +++ b/qt_ui/widgets/QTopPanel.py @@ -1,8 +1,8 @@ -from PySide2.QtWidgets import QFrame, QHBoxLayout, QPushButton, QVBoxLayout, QMessageBox, QGridLayout +from PySide2.QtWidgets import QFrame, QHBoxLayout, QPushButton, QVBoxLayout from game import Game from qt_ui.widgets.QBudgetBox import QBudgetBox -from qt_ui.widgets.QStatsWindow import QStatsWindow +from qt_ui.windows.stats.QStatsWindow import QStatsWindow from qt_ui.widgets.QTurnCounter import QTurnCounter import qt_ui.uiconstants as CONST diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index 2e0dc7a8..a7c1d280 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -66,7 +66,7 @@ class QLiberationMap(QGraphicsView): scene.clear() self.addBackground() - self.add_game_events() + #self.add_game_events() for cp in self.game.theater.controlpoints: diff --git a/qt_ui/windows/mission/QMissionPlanning.py b/qt_ui/windows/mission/QMissionPlanning.py index ee126413..4310765d 100644 --- a/qt_ui/windows/mission/QMissionPlanning.py +++ b/qt_ui/windows/mission/QMissionPlanning.py @@ -1,6 +1,9 @@ from PySide2.QtCore import Qt, Slot, QItemSelectionModel, QPoint -from PySide2.QtWidgets import QDialog, QGridLayout, QScrollArea, QVBoxLayout +from PySide2.QtWidgets import QDialog, QGridLayout, QScrollArea, QVBoxLayout, QPushButton from game import Game +from game.event import StrikeEvent, InsurgentAttackEvent, FrontlineAttackEvent, CAP, CAS +from qt_ui.uiconstants import EVENT_ICONS +from qt_ui.windows.QWaitingForMissionResultWindow import QWaitingForMissionResultWindow from qt_ui.windows.mission.QPlannedFlightsView import QPlannedFlightsView from qt_ui.windows.mission.QChooseAirbase import QChooseAirbase from qt_ui.windows.mission.flight.QFlightPlanner import QFlightPlanner @@ -15,6 +18,7 @@ class QMissionPlanning(QDialog): self.setMinimumSize(750, 350) self.setModal(True) self.setWindowTitle("Mission Preparation") + self.setWindowIcon(EVENT_ICONS[StrikeEvent]) self.init_ui() print("DONE") @@ -37,12 +41,16 @@ class QMissionPlanning(QDialog): self.flight_planner = QFlightPlanner(self.planned_flight_view.flight_planner.flights[0], self.game) + self.mission_start_button = QPushButton("Take Off") + self.mission_start_button.setProperty("style", "start-button") + self.mission_start_button.clicked.connect(self.on_start) self.left_bar_layout.addWidget(self.select_airbase) self.left_bar_layout.addWidget(self.planned_flight_view) self.layout.addLayout(self.left_bar_layout, 0, 0) self.layout.addWidget(self.flight_planner, 0, 1) + self.layout.addWidget(self.mission_start_button, 1, 1, alignment=Qt.AlignRight) self.setLayout(self.layout) @@ -61,3 +69,31 @@ class QMissionPlanning(QDialog): self.flight_planner = QFlightPlanner(flight, self.game) self.layout.addWidget(self.flight_planner,0 ,1) + + def on_start(self): + + for event in self.game.events: + if isinstance(event, FrontlineAttackEvent) and event.is_player_attacking: + self.gameEvent = event + + #if self.awacs_checkbox.isChecked() == 1: + # self.gameEvent.is_awacs_enabled = True + # self.game.awacs_expense_commit() + #else: + # self.gameEvent.is_awacs_enabled = False + self.gameEvent.is_awacs_enabled = False + self.gameEvent.ca_slots = 1 + self.gameEvent.departure_cp = self.game.theater.controlpoints[0] + + if self.game.is_player_attack(self.gameEvent): + self.gameEvent.player_attacking({CAS:{}, CAP:{}}) + else: + self.gameEvent.player_defending({CAS: {}, CAP: {}}) + self.gameEvent.depart_from = self.game.theater.controlpoints[0] + + self.game.initiate_event(self.gameEvent) + waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game) + waiting.show() + self.close() + + diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointItem.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointItem.py new file mode 100644 index 00000000..9f35e147 --- /dev/null +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointItem.py @@ -0,0 +1,12 @@ +from typing import List + +from PySide2.QtGui import QStandardItem + + +class QWaypointItem(QStandardItem): + + def __init__(self, point: List[int]): + super(QWaypointItem, self).__init__() + + self.setText("X: " + str(int(point[0])) + "; Y: " + str(int(point[1])) + "; Alt: " + str(int(point[2])) + "m") + diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py new file mode 100644 index 00000000..5d8dbad9 --- /dev/null +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -0,0 +1,18 @@ +from PySide2.QtGui import QStandardItemModel +from PySide2.QtWidgets import QListView + +from gen.flights.flight import Flight +from qt_ui.windows.mission.flight.waypoints.QFlightWaypointItem import QWaypointItem + + +class QFlightWaypointList(QListView): + + def __init__(self, flight: Flight): + super(QFlightWaypointList, self).__init__() + self.model = QStandardItemModel(self) + self.setModel(self.model) + self.flight = flight + + self.model.appendRow(QWaypointItem([flight.from_cp.position.x, flight.from_cp.position.y, 0])) + for i, point in enumerate(self.flight.points): + self.model.appendRow(QWaypointItem(point)) \ No newline at end of file diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py index 9325d7b7..42498c9a 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointTab.py @@ -1,6 +1,7 @@ from PySide2.QtWidgets import QFrame, QGridLayout, QLabel from gen.flights.flight import Flight +from qt_ui.windows.mission.flight.waypoints.QFlightWaypointList import QFlightWaypointList class QFlightWaypointTab(QFrame): @@ -12,5 +13,6 @@ class QFlightWaypointTab(QFrame): def init_ui(self): layout = QGridLayout() - layout.addWidget(QLabel("Coming in two weeks")) + self.flight_waypoint_list = QFlightWaypointList(self.flight) + layout.addWidget(self.flight_waypoint_list) self.setLayout(layout) diff --git a/qt_ui/widgets/QStatsWindow.py b/qt_ui/windows/stats/QAircraftChart.py similarity index 76% rename from qt_ui/widgets/QStatsWindow.py rename to qt_ui/windows/stats/QAircraftChart.py index 19d1254f..e1c4db14 100644 --- a/qt_ui/widgets/QStatsWindow.py +++ b/qt_ui/windows/stats/QAircraftChart.py @@ -1,25 +1,15 @@ -from PySide2 import QtCharts +from PySide2.QtCharts import QtCharts from PySide2.QtCore import QPoint, Qt from PySide2.QtGui import QPainter -from PySide2.QtWidgets import QDialog, QGridLayout -from PySide2.QtCharts import QtCharts - -import qt_ui.uiconstants as CONST -from game.game import Game +from PySide2.QtWidgets import QFrame, QGridLayout +from game import Game -class QStatsWindow(QDialog): +class QAircraftChart(QFrame): def __init__(self, game: Game): - super(QStatsWindow, self).__init__() - + super(QAircraftChart, self).__init__() self.game = game - - self.setModal(True) - self.setWindowTitle("Stats") - self.setWindowIcon(CONST.ICONS["Statistics"]) - self.setMinimumSize(600, 250) - self.initUi() def initUi(self): @@ -34,13 +24,13 @@ class QStatsWindow(QDialog): self.alliedAircraftSerie = QtCharts.QLineSeries() self.alliedAircraftSerie.setName("Allied aircraft count") - for a,i in enumerate(self.alliedAircraft): + for a, i in enumerate(self.alliedAircraft): self.alliedAircraftSerie.append(QPoint(a, i)) self.enemyAircraftSerie = QtCharts.QLineSeries() self.enemyAircraftSerie.setColor(Qt.red) self.enemyAircraftSerie.setName("Enemy aircraft count") - for a,i in enumerate(self.enemyAircraft): + for a, i in enumerate(self.enemyAircraft): self.enemyAircraftSerie.append(QPoint(a, i)) self.chart = QtCharts.QChart() @@ -56,4 +46,3 @@ class QStatsWindow(QDialog): self.chartView.setRenderHint(QPainter.Antialiasing) self.layout.addWidget(self.chartView, 0, 0) - diff --git a/qt_ui/windows/stats/QArmorChart.py b/qt_ui/windows/stats/QArmorChart.py new file mode 100644 index 00000000..cf008ab5 --- /dev/null +++ b/qt_ui/windows/stats/QArmorChart.py @@ -0,0 +1,48 @@ +from PySide2.QtCharts import QtCharts +from PySide2.QtCore import QPoint, Qt +from PySide2.QtGui import QPainter +from PySide2.QtWidgets import QFrame, QGridLayout +from game import Game + + +class QArmorChart(QFrame): + + def __init__(self, game: Game): + super(QArmorChart, self).__init__() + self.game = game + self.initUi() + + def initUi(self): + self.layout = QGridLayout() + self.generateUnitCharts() + self.setLayout(self.layout) + + def generateUnitCharts(self): + + self.alliedArmor = [d.allied_units.vehicles_count for d in self.game.game_stats.data_per_turn] + self.enemyArmor = [d.enemy_units.vehicles_count for d in self.game.game_stats.data_per_turn] + + self.alliedArmorSerie = QtCharts.QLineSeries() + self.alliedArmorSerie.setName("Allied vehicle count") + for a, i in enumerate(self.alliedArmor): + self.alliedArmorSerie.append(QPoint(a, i)) + + self.enemyArmorSerie = QtCharts.QLineSeries() + self.enemyArmorSerie.setColor(Qt.red) + self.enemyArmorSerie.setName("Enemy vehicle count") + for a, i in enumerate(self.enemyArmor): + self.enemyArmorSerie.append(QPoint(a, i)) + + self.chart = QtCharts.QChart() + self.chart.addSeries(self.alliedArmorSerie) + self.chart.addSeries(self.enemyArmorSerie) + self.chart.setTitle("Combat vehicles over time") + + self.chart.createDefaultAxes() + self.chart.axisX().setRange(0, len(self.alliedArmor)) + self.chart.axisY().setRange(0, max(max(self.alliedArmor), max(self.enemyArmor)) + 10) + + self.chartView = QtCharts.QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.layout.addWidget(self.chartView, 0, 0) diff --git a/qt_ui/windows/stats/QStatsWindow.py b/qt_ui/windows/stats/QStatsWindow.py new file mode 100644 index 00000000..a7cf34de --- /dev/null +++ b/qt_ui/windows/stats/QStatsWindow.py @@ -0,0 +1,27 @@ +from PySide2.QtWidgets import QDialog, QGridLayout, QTabWidget + +import qt_ui.uiconstants as CONST +from game.game import Game +from qt_ui.windows.stats.QAircraftChart import QAircraftChart +from qt_ui.windows.stats.QArmorChart import QArmorChart + + +class QStatsWindow(QDialog): + + def __init__(self, game: Game): + super(QStatsWindow, self).__init__() + + self.game = game + self.setModal(True) + self.setWindowTitle("Stats") + self.setWindowIcon(CONST.ICONS["Statistics"]) + self.setMinimumSize(600, 250) + + self.layout = QGridLayout() + self.aircraft_charts = QAircraftChart(self.game) + self.armor_charts = QArmorChart(self.game) + self.tabview = QTabWidget() + self.tabview.addTab(self.aircraft_charts, "Aircraft") + self.tabview.addTab(self.armor_charts, "Armor") + self.layout.addWidget(self.tabview, 0, 0) + self.setLayout(self.layout) diff --git a/resources/stylesheets/style.css b/resources/stylesheets/style.css index 8b1b0764..e04dc6bb 100644 --- a/resources/stylesheets/style.css +++ b/resources/stylesheets/style.css @@ -38,6 +38,21 @@ QPushButton[style="btn-success"]:hover{ cursor: pointer; } +QPushButton[style="start-button"]{ + background-color:#699245; + color: white; + cursor:pointer; + padding: 15px 15px 15px 15px; + border-radius:5px; +} + +QPushButton[style="start-button"]:hover{ + background-color:#8ABC5A; + padding: 15px 15px 15px 15px; + border-radius:5px; + cursor: pointer; +} + QPushButton[style="btn-danger"]{ background-color:#9E3232; color: white;