mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Handle game over.
The contents are completely uninteresting, but at least it's visible. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/978.
This commit is contained in:
parent
8f0ca08b89
commit
9d43eb8f03
@ -7,6 +7,7 @@ Saves from 7.x are not compatible with 8.0.
|
||||
* **[Engine]** Support for DCS 2.8.6.41066, including the new Sinai map.
|
||||
* **[UI]** Limited size of overfull airbase display and added scrollbar.
|
||||
* **[UI]** Moved air wing and transfer menus to the toolbar to improve UI fit on low resolution displays.
|
||||
* **[UI]** Added basic game over dialog.
|
||||
|
||||
## Fixes
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import logging
|
||||
import math
|
||||
from collections.abc import Iterator
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from enum import Enum
|
||||
from typing import Any, List, TYPE_CHECKING, Type, Union, cast
|
||||
|
||||
from dcs.countries import Switzerland, USAFAggressors, UnitedNationsPeacekeepers
|
||||
@ -37,6 +36,7 @@ from .theater.theatergroundobject import (
|
||||
)
|
||||
from .theater.transitnetwork import TransitNetwork, TransitNetworkBuilder
|
||||
from .timeofday import TimeOfDay
|
||||
from .turnstate import TurnState
|
||||
from .weather.conditions import Conditions
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -81,12 +81,6 @@ AWACS_BUDGET_COST = 4
|
||||
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
||||
|
||||
|
||||
class TurnState(Enum):
|
||||
WIN = 0
|
||||
LOSS = 1
|
||||
CONTINUE = 2
|
||||
|
||||
|
||||
class Game:
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
9
game/turnstate.py
Normal file
9
game/turnstate.py
Normal file
@ -0,0 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class TurnState(Enum):
|
||||
WIN = 0
|
||||
LOSS = 1
|
||||
CONTINUE = 2
|
||||
28
qt_ui/cheatcontext.py
Normal file
28
qt_ui/cheatcontext.py
Normal file
@ -0,0 +1,28 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from game.server import EventStream
|
||||
from game.turnstate import TurnState
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.windows.gameoverdialog import GameOverDialog
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from game.sim import GameUpdateEvents
|
||||
|
||||
|
||||
@contextmanager
|
||||
def game_state_modifying_cheat_context(game: Game) -> Iterator[GameUpdateEvents]:
|
||||
with EventStream.event_context() as events:
|
||||
yield events
|
||||
|
||||
state = game.check_win_loss()
|
||||
if state is not TurnState.CONTINUE:
|
||||
dialog = GameOverDialog(won=state is TurnState.WIN)
|
||||
dialog.exec()
|
||||
else:
|
||||
game.initialize_turn(events)
|
||||
GameUpdateSignal.get_instance().updateGame(game)
|
||||
@ -24,6 +24,7 @@ from game.persistence import SaveManager
|
||||
from game.server import EventStream, GameContext
|
||||
from game.server.dependencies import QtCallbacks, QtContext
|
||||
from game.theater import ControlPoint, MissionTarget, TheaterGroundObject
|
||||
from game.turnstate import TurnState
|
||||
from qt_ui import liberation_install
|
||||
from qt_ui.dialogs import Dialog
|
||||
from qt_ui.models import GameModel
|
||||
@ -39,6 +40,7 @@ from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.windows.PendingTransfersDialog import PendingTransfersDialog
|
||||
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
|
||||
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
|
||||
from qt_ui.windows.gameoverdialog import GameOverDialog
|
||||
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
||||
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
|
||||
from qt_ui.windows.logs.QLogsWindow import QLogsWindow
|
||||
@ -559,8 +561,13 @@ class QLiberationWindow(QMainWindow):
|
||||
logging.info("On Debriefing")
|
||||
self.debriefing = QDebriefingWindow(debrief)
|
||||
self.debriefing.exec()
|
||||
self.game.pass_turn()
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
|
||||
state = self.game.check_win_loss()
|
||||
if state is not TurnState.CONTINUE:
|
||||
GameOverDialog(won=state is TurnState.WIN, parent=self).exec()
|
||||
else:
|
||||
self.game.pass_turn()
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
|
||||
def open_tgo_info_dialog(self, tgo: TheaterGroundObject) -> None:
|
||||
QGroundObjectMenu(self, tgo, tgo.control_point, self.game).show()
|
||||
|
||||
@ -9,19 +9,17 @@ from PySide6.QtWidgets import (
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from dcs.ships import Stennis, KUZNECOW
|
||||
|
||||
from game import Game
|
||||
from game.ato.flighttype import FlightType
|
||||
from game.config import RUNWAY_REPAIR_COST
|
||||
from game.server import EventStream
|
||||
from game.sim import GameUpdateEvents
|
||||
from game.theater import (
|
||||
AMMO_DEPOT_FRONTLINE_UNIT_CONTRIBUTION,
|
||||
ControlPoint,
|
||||
ControlPointType,
|
||||
FREE_FRONTLINE_UNIT_SUPPLY,
|
||||
)
|
||||
from qt_ui.cheatcontext import game_state_modifying_cheat_context
|
||||
from qt_ui.dialogs import Dialog
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.uiconstants import EVENT_ICONS
|
||||
@ -119,13 +117,11 @@ class QBaseMenu2(QDialog):
|
||||
return self.game_model.game.settings.enable_base_capture_cheat
|
||||
|
||||
def cheat_capture(self) -> None:
|
||||
events = GameUpdateEvents()
|
||||
self.cp.capture(self.game_model.game, events, for_player=not self.cp.captured)
|
||||
# Reinitialized ground planners and the like. The ATO needs to be reset because
|
||||
# missions planned against the flipped base are no longer valid.
|
||||
self.game_model.game.initialize_turn(events)
|
||||
EventStream.put_nowait(events)
|
||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
||||
with game_state_modifying_cheat_context(self.game_model.game) as events:
|
||||
self.cp.capture(
|
||||
self.game_model.game, events, for_player=not self.cp.captured
|
||||
)
|
||||
self.close()
|
||||
|
||||
@property
|
||||
def has_transfer_destinations(self) -> bool:
|
||||
|
||||
@ -3,10 +3,8 @@ from collections.abc import Callable
|
||||
from PySide6.QtWidgets import QGroupBox, QLabel, QPushButton, QVBoxLayout
|
||||
|
||||
from game import Game
|
||||
from game.server import EventStream
|
||||
from game.sim.gameupdateevents import GameUpdateEvents
|
||||
from game.theater import ControlPoint
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.cheatcontext import game_state_modifying_cheat_context
|
||||
from qt_ui.windows.basemenu.ground_forces.QGroundForcesStrategySelector import (
|
||||
QGroundForcesStrategySelector,
|
||||
)
|
||||
@ -52,15 +50,12 @@ class QGroundForcesStrategy(QGroupBox):
|
||||
self.setLayout(layout)
|
||||
|
||||
def cheat_alter_front_line(self, enemy_point: ControlPoint, advance: bool) -> None:
|
||||
amount = 0.2
|
||||
if not advance:
|
||||
amount *= -1
|
||||
self.cp.base.affect_strength(amount)
|
||||
enemy_point.base.affect_strength(-amount)
|
||||
front_line = self.cp.front_line_with(enemy_point)
|
||||
front_line.update_position()
|
||||
events = GameUpdateEvents().update_front_line(front_line)
|
||||
# Clear the ATO to replan missions affected by the front line.
|
||||
self.game.initialize_turn(events)
|
||||
EventStream.put_nowait(events)
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
with game_state_modifying_cheat_context(self.game) as events:
|
||||
amount = 0.2
|
||||
if not advance:
|
||||
amount *= -1
|
||||
self.cp.base.affect_strength(amount)
|
||||
enemy_point.base.affect_strength(-amount)
|
||||
front_line = self.cp.front_line_with(enemy_point)
|
||||
front_line.update_position()
|
||||
events.update_front_line(front_line)
|
||||
|
||||
43
qt_ui/windows/gameoverdialog.py
Normal file
43
qt_ui/windows/gameoverdialog.py
Normal file
@ -0,0 +1,43 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
QVBoxLayout,
|
||||
QLabel,
|
||||
QHBoxLayout,
|
||||
QPushButton,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from qt_ui.windows.newgame.QNewGameWizard import NewGameWizard
|
||||
|
||||
|
||||
class GameOverDialog(QDialog):
|
||||
def __init__(self, won: bool, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
self.setModal(True)
|
||||
self.setWindowTitle("Game Over")
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
layout.addWidget(
|
||||
QLabel(
|
||||
f"<strong>You {'won' if won else 'lost'}!</strong><br />"
|
||||
"<br />"
|
||||
"Click below to start a new game."
|
||||
)
|
||||
)
|
||||
button_row = QHBoxLayout()
|
||||
layout.addLayout(button_row)
|
||||
|
||||
button_row.addStretch()
|
||||
|
||||
new_game = QPushButton("New Game")
|
||||
new_game.clicked.connect(self.on_new_game)
|
||||
button_row.addWidget(new_game)
|
||||
|
||||
def on_new_game(self) -> None:
|
||||
wizard = NewGameWizard(self)
|
||||
wizard.show()
|
||||
wizard.accepted.connect(self.accept)
|
||||
@ -95,6 +95,7 @@ def wrap_label_text(text: str, width: int = 100) -> str:
|
||||
class NewGameWizard(QtWidgets.QWizard):
|
||||
def __init__(self, parent=None):
|
||||
super(NewGameWizard, self).__init__(parent)
|
||||
self.setModal(True)
|
||||
|
||||
# The wizard should probably be refactored to edit this directly, but for now we
|
||||
# just create a Settings object so that we can load the player's preserved
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user