diff --git a/game/event/frontlineattack.py b/game/event/frontlineattack.py index 9cd787d5..5b344247 100644 --- a/game/event/frontlineattack.py +++ b/game/event/frontlineattack.py @@ -38,20 +38,7 @@ class FrontlineAttackEvent(Event): return "Frontline attack" def is_successfull(self, debriefing: Debriefing): - - if self.game.player_name == self.attacker_name: - attacker_country = self.game.player_country - defender_country = self.game.enemy_country - else: - attacker_country = self.game.enemy_country - defender_country = self.game.player_country - - # TODO : Rework - #alive_attackers = sum([v for k, v in debriefing.alive_units.get(attacker_country, {}).items() if db.unit_task(k) == PinpointStrike]) - #alive_defenders = sum([v for k, v in debriefing.alive_units.get(defender_country, {}).items() if db.unit_task(k) == PinpointStrike]) - #attackers_success = (float(alive_attackers) / (alive_defenders + 0.01)) > self.SUCCESS_FACTOR attackers_success = True - if self.from_cp.captured: return attackers_success else: @@ -65,46 +52,20 @@ 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" - op = FrontlineAttackOperation(game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, from_cp=self.from_cp, departure_cp=self.departure_cp, to_cp=self.to_cp) - - defenders = self.to_cp.base.assemble_attack() - max_attackers = int(math.ceil(sum(defenders.values()) * self.ATTACKER_DEFENDER_FACTOR)) - attackers = db.unitdict_restrict_count(self.from_cp.base.assemble_attack(), max_attackers) - op.setup(defenders=defenders, - attackers=attackers, - strikegroup=flights[CAS], - escort=flights[CAP], - interceptors=assigned_units_from(self.to_cp.base.scramble_interceptors(1))) - self.operation = op def player_defending(self, flights: db.TaskForceDict): - # assert CAP in flights and len(flights) == 1, "Invalid flights" - op = FrontlineAttackOperation(game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, from_cp=self.from_cp, departure_cp=self.departure_cp, to_cp=self.to_cp) - - defenders = self.to_cp.base.assemble_attack() - - max_attackers = int(math.ceil(sum(defenders.values()))) - attackers = db.unitdict_restrict_count(self.from_cp.base.assemble_attack(), max_attackers) - - op.setup(defenders=defenders, - attackers=attackers, - strikegroup=assigned_units_from(self.from_cp.base.scramble_cas(1)), - escort=assigned_units_from(self.from_cp.base.scramble_sweep(1)), - interceptors=flights[CAP]) - self.operation = op diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index 53dc2d63..902ff6c9 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -14,19 +14,6 @@ class FrontlineAttackOperation(Operation): attackers = None # type: db.ArmorDict defenders = None # type: db.ArmorDict - def setup(self, - defenders: db.ArmorDict, - attackers: db.ArmorDict, - strikegroup: db.AssignedUnitsDict, - escort: db.AssignedUnitsDict, - interceptors: db.AssignedUnitsDict): - self.strikegroup = strikegroup - self.escort = escort - self.interceptors = interceptors - - self.defenders = defenders - self.attackers = attackers - def prepare(self, terrain: Terrain, is_quick: bool): super(FrontlineAttackOperation, self).prepare(terrain, is_quick) if self.defender_name == self.game.player_name: diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index 80cce076..2e763071 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -15,7 +15,6 @@ from game.event import UnitsDeliveryEvent, Event, ControlPointType from gen import Conflict from qt_ui.widgets.map.QLiberationScene import QLiberationScene from qt_ui.widgets.map.QMapControlPoint import QMapControlPoint -from qt_ui.widgets.map.QMapEvent import QMapEvent from qt_ui.widgets.map.QMapGroundObject import QMapGroundObject from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from theater import ControlPoint diff --git a/qt_ui/widgets/map/QMapEvent.py b/qt_ui/widgets/map/QMapEvent.py deleted file mode 100644 index 5e24f35e..00000000 --- a/qt_ui/widgets/map/QMapEvent.py +++ /dev/null @@ -1,56 +0,0 @@ -from PySide2.QtGui import QPen, Qt -from PySide2.QtWidgets import QGraphicsRectItem, QGraphicsSceneMouseEvent, QGraphicsSceneHoverEvent - -import qt_ui.uiconstants as CONST -from game.event import Event, UnitsDeliveryEvent -from qt_ui.windows.QBriefingWindow import QBriefingWindow - - -class QMapEvent(QGraphicsRectItem): - - def __init__(self, parent, x: float, y: float, w: float, h: float, gameEvent: Event): - super(QMapEvent, self).__init__(x, y, w, h) - self.gameEvent = gameEvent - self.parent = parent - self.setAcceptHoverEvents(True) - self.setZValue(2) - self.setToolTip(str(self.gameEvent)) - self.playable = not isinstance(self.gameEvent, UnitsDeliveryEvent) - - - - def paint(self, painter, option, widget=None): - - playerColor = self.game.get_player_color() - enemyColor = self.game.get_enemy_color() - - if self.parent.get_display_rule("events"): - painter.save() - - if self.gameEvent.is_player_attacking: - painter.setPen(QPen(brush=CONST.COLORS[playerColor])) - painter.setBrush(CONST.COLORS[playerColor]) - else: - painter.setPen(QPen(brush=CONST.COLORS[enemyColor])) - painter.setBrush(CONST.COLORS[enemyColor]) - - if self.isUnderMouse() and self.playable: - painter.setBrush(CONST.COLORS["white"]) - - painter.drawRect(option.rect) - painter.drawPixmap(option.rect, CONST.EVENT_ICONS[self.gameEvent.__class__]) - painter.restore() - - def mousePressEvent(self, event:QGraphicsSceneMouseEvent): - if self.parent.get_display_rule("events"): - self.openBriefing() - - def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent): - self.update() - if self.playable: - self.setCursor(Qt.PointingHandCursor) - - def openBriefing(self): - if self.playable: - self.briefing = QBriefingWindow(self.gameEvent) - self.briefing.show() \ No newline at end of file diff --git a/qt_ui/windows/QBriefingWindow.py b/qt_ui/windows/QBriefingWindow.py deleted file mode 100644 index 7b4eec33..00000000 --- a/qt_ui/windows/QBriefingWindow.py +++ /dev/null @@ -1,283 +0,0 @@ -import os - -from PySide2.QtGui import QWindow -from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QDialog, QVBoxLayout, QGridLayout, QGroupBox, QCheckBox, \ - QSpinBox, QPushButton, QMessageBox, QComboBox -from pip._internal.utils import typing - -from game.game import AWACS_BUDGET_COST, PinpointStrike, db, Event, FrontlineAttackEvent, 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, gameEvent: Event): - super(QBriefingWindow, self).__init__() - self.gameEvent = gameEvent - self.setWindowTitle("Briefing : " + str(gameEvent)) - self.setMinimumSize(200,200) - self.setWindowIcon(CONST.EVENT_ICONS[self.gameEvent.__class__]) - self.setModal(True) - self.game = self.gameEvent.game - - if self.gameEvent.attacker_name == self.game.player_name: - self.base = self.gameEvent.from_cp.base - self.playerFromCp = self.gameEvent.from_cp - else: - self.base = self.gameEvent.to_cp.base - self.playerFromCp = self.gameEvent.to_cp - - self.scramble_entries = {k: {} for k in self.gameEvent.tasks} - self.initUi() - - def initUi(self): - - self.layout = QVBoxLayout() - - self.depart_box = QGroupBox("Departure") - self.depart_layout = QHBoxLayout() - self.depart_box.setLayout(self.depart_layout) - self.depart_from_label = QLabel("Depart from : ") - self.depart_from = QComboBox() - - for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]): - self.depart_from.addItem(str(cp.name), cp) - if cp.name == self.playerFromCp.name: - self.depart_from.setCurrentIndex(i) - - self.depart_from.currentTextChanged.connect(self.on_departure_cp_changed) - self.depart_layout.addWidget(self.depart_from_label) - self.depart_layout.addWidget(self.depart_from) - - # Mission Description - self.gridLayout = QGridLayout() - self.initUnitRows() - self.scramble_box = QGroupBox("Units") - self.scramble_box.setLayout(self.gridLayout) - - self.action_layout = QHBoxLayout() - self.commit_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) - - self.support_box = self.initSupportBox() - self.layout.addWidget(QLabel("

{} on {}

".format(self.gameEvent, self.gameEvent.to_cp.name))) - self.layout.addWidget(self.depart_box) - self.layout.addWidget(self.scramble_box) - self.layout.addWidget(self.support_box) - self.layout.addWidget(QLabel("Ready?")) - self.layout.addLayout(self.action_layout) - self.setLayout(self.layout) - - def initUnitRows(self): - - row = 0 - - def header(text, row): - self.gridLayout.addWidget(QLabel("" + text + ""), row, 0, 1, 2) - - def scramble_row(task_type, unit_type, unit_count, client_slots: bool, row: int): - unit_name = QLabel("{} ({})".format(db.unit_type_name(unit_type), unit_count)) - self.gridLayout.addWidget(unit_name, row, 0) - - scramble_entry = QSpinBox() - self.gridLayout.addWidget(scramble_entry, row, 1) - - if client_slots: - client_entry = QSpinBox() - self.gridLayout.addWidget(client_entry, row, 2) - else: - client_entry = None - - self.scramble_entries[task_type][unit_type] = scramble_entry, client_entry - - # Table headers - self.gridLayout.addWidget(QLabel("Amount"), row, 1) - self.gridLayout.addWidget(QLabel("Client slots"), row, 2) - row += 1 - - for flight_task in self.gameEvent.tasks: - header("{}:".format(self.gameEvent.flight_name(flight_task)), row) - row += 1 - - if flight_task == PinpointStrike: - if not self.base.armor: - self.gridLayout.addWidget(QLabel("No units"), row, 1) - row += 1 - for t, c in self.base.armor.items(): - scramble_row(flight_task, t, c, False, row) - row += 1 - else: - if not self.base.aircraft: - self.gridLayout.addWidget(QLabel("No units"), row, 1) - row += 1 - for t, c in self.base.aircraft.items(): - scramble_row(flight_task, t, c, t.flyable, row) - row += 1 - - return self.gridLayout - - def initSupportBox(self): - - self.support_box = QGroupBox("Support") - self.support_layout = QGridLayout() - self.support_box.setLayout(self.support_layout) - - self.awacs_label = QLabel("AWACS ({}m)".format(AWACS_BUDGET_COST)) - self.awacs_checkbox = QCheckBox() - - self.ca_slot_label = QLabel("Combined Arms Slots") - self.ca_slot_entry = QSpinBox() - self.ca_slot_entry.setValue(0) - self.ca_slot_entry.setMinimum(0) - self.ca_slot_entry.setMaximum(32) - - self.support_layout.addWidget(self.awacs_label, 0, 0) - self.support_layout.addWidget(self.awacs_checkbox, 0, 1) - self.support_layout.addWidget(self.ca_slot_label, 1, 0) - self.support_layout.addWidget(self.ca_slot_entry, 1, 1) - return self.support_box - - - def initWaitingForResults(self): - - layout = QVBoxLayout() - - layout.addWidget(QLabel("You are clear for takeoff")) - layout.addWidget(QLabel("In DCS open and play the mission : ")) - layout.addWidget(QLabel("liberation_nextturn")) - layout.addWidget(QLabel("or")) - layout.addWidget(QLabel("liberation_nextturn_quick")) - - layout.addWidget(QLabel("Then save the debriefing to folder :")) - layout.addWidget(QLabel("Then save the debriefing to the folder:")) - layout.addWidget(QLabel("" + self.debriefing_directory_location() + "")) - layout.addWidget(QLabel("Waiting for results...")) - - # layout.addWidget(QLabel("In DCS open and play the mission : ")) - # layout.addWidget(QLabel("You are clear for takeoff")) - - self.setLayout(layout) - - pass - - def debriefing_directory_location(self) -> str: - return os.path.join(base_path(), "liberation_debriefings") - - def start(self): - - if self.awacs_checkbox.isChecked() == 1: - self.gameEvent.is_awacs_enabled = True - self.game.awacs_expense_commit() - else: - self.gameEvent.is_awacs_enabled = False - - ca_slot_entry_value = self.ca_slot_entry.value() - try: - ca_slots = int(ca_slot_entry_value and ca_slot_entry_value or "0") - except: - 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] - tasks_clients_counts = {} # type: typing.Dict[typing.Type[Task], int] - - def dampen_count(unit_type, count: int) -> int: - nonlocal units_scramble_counts - total_count = self.base.total_units_of_type(unit_type) - - total_scrambled = units_scramble_counts.get(unit_type, 0) - dampened_value = count if count + total_scrambled < total_count else total_count - total_scrambled - units_scramble_counts[unit_type] = units_scramble_counts.get(unit_type, 0) + dampened_value - - return dampened_value - - for task_type, dict in self.scramble_entries.items(): - for unit_type, (count_entry, clients_entry) in dict.items(): - try: - count = int(count_entry.value()) - except: - count = 0 - - try: - clients_count = int(clients_entry and clients_entry.value() or 0) - except: - clients_count = 0 - - dampened_count = dampen_count(unit_type, count) - tasks_clients_counts[task_type] = tasks_clients_counts.get(task_type, 0) + clients_count - tasks_scramble_counts[task_type] = tasks_scramble_counts.get(task_type, 0) + dampened_count - - flights[task_type][unit_type] = dampened_count, clients_count - - for task in self.gameEvent.ai_banned_tasks: - if tasks_clients_counts.get(task, 0) == 0 and tasks_scramble_counts.get(task, 0) > 0: - self.showErrorMessage("Need at least one player in flight {}".format(self.gameEvent.flight_name(task))) - return - - for task in self.gameEvent.player_banned_tasks: - if tasks_clients_counts.get(task, 0) != 0: - self.showErrorMessage("Players are not allowed on flight {}".format(self.gameEvent.flight_name(task))) - return - - if self.game.is_player_attack(self.gameEvent): - if isinstance(self.gameEvent, FrontlineAttackEvent): - if self.base.total_armor == 0: - self.showErrorMessage("No ground vehicles available to attack!") - return - - self.gameEvent.player_attacking(flights) - else: - if isinstance(self.gameEvent, FrontlineAttackEvent): - if self.gameEvent.to_cp.base.total_armor == 0: - self.showErrorMessage("No ground vehicles available to defend!") - return - - self.gameEvent.player_defending(flights) - - self.game.initiate_event(self.gameEvent) - - waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game) - waiting.show() - - self.close() - - def showErrorMessage(self, text): - about = QMessageBox() - about.setWindowTitle("Error") - about.setIcon(QMessageBox.Icon.Critical) - about.setText(text) - about.exec_() - - def on_departure_cp_changed(self): - - selectedBase = self.depart_from.itemData(self.depart_from.currentIndex()) - - for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]): - if cp.name == selectedBase.name: - self.base = cp.base - self.playerFromCp = cp - break - - # Clear current selection - self.scramble_entries = {k: {} for k in self.gameEvent.tasks} - - # Clear the grid layout - for i in reversed(range(self.gridLayout.count())): - self.gridLayout.itemAt(i).widget().setParent(None) - - # Rebuild the grid layout, so that it correspond to the newly selected CP - self.initUnitRows() \ No newline at end of file