mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Remove the old map.
This commit is contained in:
parent
acd3e87996
commit
30f6220c3e
@ -23,7 +23,7 @@ Saves from 2.5 are not compatible with 3.0.
|
|||||||
* **[Flight Planner]** Automatic ATO generation for the player's coalition can now be disabled in the settings.
|
* **[Flight Planner]** Automatic ATO generation for the player's coalition can now be disabled in the settings.
|
||||||
* **[Payloads]** AI flights for most air to ground mission types (CAS excluded) will have their guns emptied to prevent strafing fully armed and operational battle stations. Gun-reliant airframes like A-10s and warbirds will keep their bullets.
|
* **[Payloads]** AI flights for most air to ground mission types (CAS excluded) will have their guns emptied to prevent strafing fully armed and operational battle stations. Gun-reliant airframes like A-10s and warbirds will keep their bullets.
|
||||||
* **[Kneeboard]** ATC table overflow alleviated by wrapping long airfield names and splitting ATC frequency and channel into separate rows.
|
* **[Kneeboard]** ATC table overflow alleviated by wrapping long airfield names and splitting ATC frequency and channel into separate rows.
|
||||||
* **[UI]** Added new web based map UI. This is mostly functional but many of the old display options are a WIP. Revert to the old map with --old-map.
|
* **[UI]** Overhauled the map implementation. Now uses satellite imagery instead of low res map images. Display options have moved from the toolbar to panels in the map.
|
||||||
* **[UI]** Campaigns generated for an older or newer version of the game will now be marked as incompatible. They can still be played, but bugs may be present.
|
* **[UI]** Campaigns generated for an older or newer version of the game will now be marked as incompatible. They can still be played, but bugs may be present.
|
||||||
* **[UI]** DCS loadouts are now selectable in the loadout setup menu.
|
* **[UI]** DCS loadouts are now selectable in the loadout setup menu.
|
||||||
* **[UI]** Added global aircraft inventory view under Air Wing dialog.
|
* **[UI]** Added global aircraft inventory view under Air Wing dialog.
|
||||||
|
|||||||
@ -1,128 +0,0 @@
|
|||||||
"""Visibility options for the game map."""
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import Iterator, Optional, Union
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DisplayRule:
|
|
||||||
name: str
|
|
||||||
_value: bool
|
|
||||||
debug_only: bool = field(default=False)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def menu_text(self) -> str:
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def value(self) -> bool:
|
|
||||||
return self._value
|
|
||||||
|
|
||||||
@value.setter
|
|
||||||
def value(self, value: bool) -> None:
|
|
||||||
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
|
|
||||||
|
|
||||||
self._value = value
|
|
||||||
if QLiberationMap.instance is not None:
|
|
||||||
QLiberationMap.instance.reload_scene()
|
|
||||||
QLiberationMap.instance.update()
|
|
||||||
|
|
||||||
def __bool__(self) -> bool:
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
class DisplayGroup:
|
|
||||||
def __init__(self, name: Optional[str], debug_only: bool = False) -> None:
|
|
||||||
self.name = name
|
|
||||||
self.debug_only = debug_only
|
|
||||||
|
|
||||||
def __iter__(self) -> Iterator[DisplayRule]:
|
|
||||||
# Python 3.6 enforces that __dict__ is order preserving by default.
|
|
||||||
for value in self.__dict__.values():
|
|
||||||
if isinstance(value, DisplayRule):
|
|
||||||
yield value
|
|
||||||
|
|
||||||
|
|
||||||
class FlightPathOptions(DisplayGroup):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super().__init__("Flight Paths")
|
|
||||||
self.hide = DisplayRule("Hide Flight Paths", False)
|
|
||||||
self.only_selected = DisplayRule("Show Selected Flight Path", False)
|
|
||||||
self.all = DisplayRule("Show All Flight Paths", True)
|
|
||||||
|
|
||||||
|
|
||||||
class ThreatZoneOptions(DisplayGroup):
|
|
||||||
def __init__(self, coalition_name: str) -> None:
|
|
||||||
super().__init__(f"{coalition_name} Threat Zones")
|
|
||||||
self.none = DisplayRule(f"Hide {coalition_name.lower()} threat zones", True)
|
|
||||||
self.all = DisplayRule(
|
|
||||||
f"Show full {coalition_name.lower()} threat zones", False
|
|
||||||
)
|
|
||||||
self.aircraft = DisplayRule(
|
|
||||||
f"Show {coalition_name.lower()} aircraft threat tones", False
|
|
||||||
)
|
|
||||||
self.air_defenses = DisplayRule(
|
|
||||||
f"Show {coalition_name.lower()} air defenses threat zones", False
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class NavMeshOptions(DisplayGroup):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super().__init__("Navmeshes", debug_only=True)
|
|
||||||
self.hide = DisplayRule("DEBUG Hide Navmeshes", True)
|
|
||||||
self.blue_navmesh = DisplayRule("DEBUG Show blue navmesh", False)
|
|
||||||
self.red_navmesh = DisplayRule("DEBUG Show red navmesh", False)
|
|
||||||
|
|
||||||
|
|
||||||
class PathDebugFactionOptions(DisplayGroup):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super().__init__("Faction for path debugging", debug_only=True)
|
|
||||||
self.blue = DisplayRule("Debug blue paths", True)
|
|
||||||
self.red = DisplayRule("Debug red paths", False)
|
|
||||||
|
|
||||||
|
|
||||||
class PathDebugOptions(DisplayGroup):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super().__init__("Shortest paths", debug_only=True)
|
|
||||||
self.hide = DisplayRule("DEBUG Hide paths", True)
|
|
||||||
self.shortest_path = DisplayRule("DEBUG Show shortest path", False)
|
|
||||||
self.barcap = DisplayRule("DEBUG Show BARCAP plan", False)
|
|
||||||
self.cas = DisplayRule("DEBUG Show CAS plan", False)
|
|
||||||
self.sweep = DisplayRule("DEBUG Show fighter sweep plan", False)
|
|
||||||
self.strike = DisplayRule("DEBUG Show strike plan", False)
|
|
||||||
self.tarcap = DisplayRule("DEBUG Show TARCAP plan", False)
|
|
||||||
|
|
||||||
|
|
||||||
class DisplayOptions:
|
|
||||||
ground_objects = DisplayRule("Ground Objects", True)
|
|
||||||
control_points = DisplayRule("Control Points", True)
|
|
||||||
lines = DisplayRule("Lines", True)
|
|
||||||
sam_ranges = DisplayRule("Ally SAM Threat Range", False)
|
|
||||||
enemy_sam_ranges = DisplayRule("Enemy SAM Threat Range", True)
|
|
||||||
detection_range = DisplayRule("SAM Detection Range", False)
|
|
||||||
map_poly = DisplayRule("Map Polygon Debug Mode", False)
|
|
||||||
waypoint_info = DisplayRule("Waypoint Information", True)
|
|
||||||
culling = DisplayRule("Display Culling Zones", False)
|
|
||||||
actual_frontline_pos = DisplayRule("Display Actual Frontline Location", False)
|
|
||||||
patrol_engagement_range = DisplayRule(
|
|
||||||
"Display selected patrol engagement range", True
|
|
||||||
)
|
|
||||||
flight_paths = FlightPathOptions()
|
|
||||||
blue_threat_zones = ThreatZoneOptions("Blue")
|
|
||||||
red_threat_zones = ThreatZoneOptions("Red")
|
|
||||||
navmeshes = NavMeshOptions()
|
|
||||||
path_debug_faction = PathDebugFactionOptions()
|
|
||||||
path_debug = PathDebugOptions()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def menu_items(cls) -> Iterator[Union[DisplayGroup, DisplayRule]]:
|
|
||||||
debug = False # Set to True to enable debug options.
|
|
||||||
# Python 3.6 enforces that __dict__ is order preserving by default.
|
|
||||||
for value in cls.__dict__.values():
|
|
||||||
if isinstance(value, DisplayRule):
|
|
||||||
if value.debug_only and not debug:
|
|
||||||
continue
|
|
||||||
yield value
|
|
||||||
elif isinstance(value, DisplayGroup):
|
|
||||||
if value.debug_only and not debug:
|
|
||||||
continue
|
|
||||||
yield value
|
|
||||||
@ -57,7 +57,7 @@ def inject_custom_payloads(user_path: Path) -> None:
|
|||||||
PayloadDirectories.set_preferred(user_path / "MissionEditor" / "UnitPayloads")
|
PayloadDirectories.set_preferred(user_path / "MissionEditor" / "UnitPayloads")
|
||||||
|
|
||||||
|
|
||||||
def run_ui(game: Optional[Game], new_map: bool) -> None:
|
def run_ui(game: Optional[Game]) -> None:
|
||||||
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens
|
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ def run_ui(game: Optional[Game], new_map: bool) -> None:
|
|||||||
GameUpdateSignal()
|
GameUpdateSignal()
|
||||||
|
|
||||||
# Start window
|
# Start window
|
||||||
window = QLiberationWindow(game, new_map)
|
window = QLiberationWindow(game)
|
||||||
window.showMaximized()
|
window.showMaximized()
|
||||||
splash.finish(window)
|
splash.finish(window)
|
||||||
qt_execution_code = app.exec_()
|
qt_execution_code = app.exec_()
|
||||||
@ -139,16 +139,8 @@ def parse_args() -> argparse.Namespace:
|
|||||||
help="Emits a warning for weapons without date or fallback information.",
|
help="Emits a warning for weapons without date or fallback information.",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--new-map", help="Deprecated. Does nothing.")
|
||||||
"--new-map",
|
parser.add_argument("--old-map", help="Deprecated. Does nothing.")
|
||||||
action="store_true",
|
|
||||||
default=True,
|
|
||||||
help="Use the new map. Functional but missing many display options.",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"--old-map", dest="new_map", action="store_false", help="Use the old map."
|
|
||||||
)
|
|
||||||
|
|
||||||
new_game = subparsers.add_parser("new-game")
|
new_game = subparsers.add_parser("new-game")
|
||||||
|
|
||||||
@ -267,7 +259,7 @@ def main():
|
|||||||
args.cheats,
|
args.cheats,
|
||||||
)
|
)
|
||||||
|
|
||||||
run_ui(game, args.new_map)
|
run_ui(game)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from PySide2.QtGui import QColor, QFont, QPixmap
|
from PySide2.QtGui import QPixmap
|
||||||
|
|
||||||
from game.theater.theatergroundobject import NAME_BY_CATEGORY
|
from game.theater.theatergroundobject import NAME_BY_CATEGORY
|
||||||
from .liberation_theme import get_theme_icons
|
from .liberation_theme import get_theme_icons
|
||||||
@ -16,51 +16,6 @@ URLS: Dict[str, str] = {
|
|||||||
LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"]
|
LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"]
|
||||||
SKILL_OPTIONS = ["Average", "Good", "High", "Excellent"]
|
SKILL_OPTIONS = ["Average", "Good", "High", "Excellent"]
|
||||||
|
|
||||||
FONT_SIZE = 8
|
|
||||||
FONT_NAME = "Arial"
|
|
||||||
# FONT = QFont("Arial", 12, weight=5, italic=True)
|
|
||||||
FONT_PRIMARY = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=False)
|
|
||||||
FONT_PRIMARY_I = QFont(FONT_NAME, FONT_SIZE, weight=5, italic=True)
|
|
||||||
FONT_PRIMARY_B = QFont(FONT_NAME, FONT_SIZE, weight=75, italic=False)
|
|
||||||
FONT_MAP = QFont(FONT_NAME, 10, weight=75, italic=False)
|
|
||||||
|
|
||||||
COLORS: Dict[str, QColor] = {
|
|
||||||
"white": QColor(255, 255, 255),
|
|
||||||
"white_transparent": QColor(255, 255, 255, 35),
|
|
||||||
"light_red": QColor(231, 92, 83, 90),
|
|
||||||
"red": QColor(200, 80, 80),
|
|
||||||
"dark_red": QColor(140, 20, 20),
|
|
||||||
"red_transparent": QColor(227, 32, 0, 20),
|
|
||||||
"transparent": QColor(255, 255, 255, 0),
|
|
||||||
"light_blue": QColor(105, 182, 240, 90),
|
|
||||||
"blue": QColor(0, 132, 255),
|
|
||||||
"dark_blue": QColor(45, 62, 80),
|
|
||||||
"sea_blue": QColor(52, 68, 85),
|
|
||||||
"sea_blue_transparent": QColor(52, 68, 85, 150),
|
|
||||||
"blue_transparent": QColor(0, 132, 255, 20),
|
|
||||||
"purple": QColor(187, 137, 255),
|
|
||||||
"yellow": QColor(238, 225, 123),
|
|
||||||
"bright_red": QColor(150, 80, 80),
|
|
||||||
"super_red": QColor(227, 32, 0),
|
|
||||||
"green": QColor(128, 186, 128),
|
|
||||||
"light_green": QColor(223, 255, 173),
|
|
||||||
"light_green_transparent": QColor(180, 255, 140, 50),
|
|
||||||
"bright_green": QColor(64, 200, 64),
|
|
||||||
"black": QColor(0, 0, 0),
|
|
||||||
"black_transparent": QColor(0, 0, 0, 5),
|
|
||||||
"orange": QColor(254, 125, 10),
|
|
||||||
"night_overlay": QColor(12, 20, 69),
|
|
||||||
"dawn_dust_overlay": QColor(46, 38, 85),
|
|
||||||
"grey": QColor(150, 150, 150),
|
|
||||||
"grey_transparent": QColor(150, 150, 150, 150),
|
|
||||||
"dark_grey": QColor(75, 75, 75),
|
|
||||||
"dark_grey_transparent": QColor(75, 75, 75, 150),
|
|
||||||
"dark_dark_grey": QColor(48, 48, 48),
|
|
||||||
"dark_dark_grey_transparent": QColor(48, 48, 48, 150),
|
|
||||||
}
|
|
||||||
|
|
||||||
CP_SIZE = 12
|
|
||||||
|
|
||||||
AIRCRAFT_BANNERS: Dict[str, QPixmap] = {}
|
AIRCRAFT_BANNERS: Dict[str, QPixmap] = {}
|
||||||
AIRCRAFT_ICONS: Dict[str, QPixmap] = {}
|
AIRCRAFT_ICONS: Dict[str, QPixmap] = {}
|
||||||
VEHICLE_BANNERS: Dict[str, QPixmap] = {}
|
VEHICLE_BANNERS: Dict[str, QPixmap] = {}
|
||||||
@ -138,17 +93,6 @@ def load_icons():
|
|||||||
"./resources/ui/misc/" + get_theme_icons() + "/ordnance_icon.png"
|
"./resources/ui/misc/" + get_theme_icons() + "/ordnance_icon.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
ICONS["target"] = QPixmap("./resources/ui/ground_assets/target.png")
|
|
||||||
ICONS["cleared"] = QPixmap("./resources/ui/ground_assets/cleared.png")
|
|
||||||
for category in NAME_BY_CATEGORY.keys():
|
|
||||||
ICONS[category] = QPixmap("./resources/ui/ground_assets/" + category + ".png")
|
|
||||||
ICONS[category + "_blue"] = QPixmap(
|
|
||||||
"./resources/ui/ground_assets/" + category + "_blue.png"
|
|
||||||
)
|
|
||||||
ICONS["destroyed"] = QPixmap("./resources/ui/ground_assets/destroyed.png")
|
|
||||||
ICONS["nothreat"] = QPixmap("./resources/ui/ground_assets/nothreat.png")
|
|
||||||
ICONS["nothreat_blue"] = QPixmap("./resources/ui/ground_assets/nothreat_blue.png")
|
|
||||||
|
|
||||||
ICONS["Generator"] = QPixmap(
|
ICONS["Generator"] = QPixmap(
|
||||||
"./resources/ui/misc/" + get_theme_icons() + "/generator.png"
|
"./resources/ui/misc/" + get_theme_icons() + "/generator.png"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
from PySide2 import QtCore, QtGui, QtWidgets
|
from PySide2 import QtCore, QtGui
|
||||||
from PySide2.QtWidgets import QCalendarWidget
|
from PySide2.QtWidgets import QCalendarWidget
|
||||||
|
|
||||||
from qt_ui.uiconstants import COLORS
|
|
||||||
|
|
||||||
|
|
||||||
class QLiberationCalendar(QCalendarWidget):
|
class QLiberationCalendar(QCalendarWidget):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -29,7 +27,7 @@ class QLiberationCalendar(QCalendarWidget):
|
|||||||
painter.save()
|
painter.save()
|
||||||
painter.fillRect(rect, QtGui.QColor("#D3D3D3"))
|
painter.fillRect(rect, QtGui.QColor("#D3D3D3"))
|
||||||
painter.setPen(QtCore.Qt.NoPen)
|
painter.setPen(QtCore.Qt.NoPen)
|
||||||
painter.setBrush(QtGui.QColor(COLORS["sea_blue"]))
|
painter.setBrush(QtGui.QColor(52, 68, 85))
|
||||||
r = QtCore.QRect(
|
r = QtCore.QRect(
|
||||||
QtCore.QPoint(), min(rect.width(), rect.height()) * QtCore.QSize(1, 1)
|
QtCore.QPoint(), min(rect.width(), rect.height()) * QtCore.QSize(1, 1)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,117 +0,0 @@
|
|||||||
"""Common base for objects drawn on the game map."""
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
|
||||||
from PySide2.QtGui import QPen
|
|
||||||
from PySide2.QtWidgets import (
|
|
||||||
QAction,
|
|
||||||
QGraphicsLineItem,
|
|
||||||
QGraphicsSceneContextMenuEvent,
|
|
||||||
QGraphicsSceneHoverEvent,
|
|
||||||
QGraphicsSceneMouseEvent,
|
|
||||||
QMenu,
|
|
||||||
)
|
|
||||||
|
|
||||||
import qt_ui.uiconstants as const
|
|
||||||
from game.theater import FrontLine
|
|
||||||
from qt_ui.dialogs import Dialog
|
|
||||||
from qt_ui.models import GameModel
|
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
|
||||||
from qt_ui.windows.mission.QPackageDialog import QNewPackageDialog
|
|
||||||
|
|
||||||
|
|
||||||
class QFrontLine(QGraphicsLineItem):
|
|
||||||
"""Base class for objects drawn on the game map.
|
|
||||||
|
|
||||||
Game map objects have an on_click behavior that triggers on left click, and
|
|
||||||
change the mouse cursor on hover.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
x1: float,
|
|
||||||
y1: float,
|
|
||||||
x2: float,
|
|
||||||
y2: float,
|
|
||||||
mission_target: FrontLine,
|
|
||||||
game_model: GameModel,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x1, y1, x2, y2)
|
|
||||||
self.mission_target = mission_target
|
|
||||||
self.game_model = game_model
|
|
||||||
self.new_package_dialog: Optional[QNewPackageDialog] = None
|
|
||||||
self.setAcceptHoverEvents(True)
|
|
||||||
|
|
||||||
pen = QPen(brush=const.COLORS["bright_red"])
|
|
||||||
pen.setColor(const.COLORS["orange"])
|
|
||||||
pen.setWidth(8)
|
|
||||||
self.setPen(pen)
|
|
||||||
|
|
||||||
def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
|
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
|
||||||
|
|
||||||
def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
|
|
||||||
if event.button() == Qt.LeftButton:
|
|
||||||
self.on_click()
|
|
||||||
|
|
||||||
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None:
|
|
||||||
menu = QMenu("Menu")
|
|
||||||
|
|
||||||
object_details_action = QAction(self.object_dialog_text)
|
|
||||||
object_details_action.triggered.connect(self.on_click)
|
|
||||||
menu.addAction(object_details_action)
|
|
||||||
|
|
||||||
new_package_action = QAction(f"New package")
|
|
||||||
new_package_action.triggered.connect(self.open_new_package_dialog)
|
|
||||||
menu.addAction(new_package_action)
|
|
||||||
|
|
||||||
if self.game_model.game.settings.enable_frontline_cheats:
|
|
||||||
cheat_forward = QAction(f"CHEAT: Advance Frontline")
|
|
||||||
cheat_forward.triggered.connect(self.cheat_forward)
|
|
||||||
menu.addAction(cheat_forward)
|
|
||||||
|
|
||||||
cheat_backward = QAction(f"CHEAT: Retreat Frontline")
|
|
||||||
cheat_backward.triggered.connect(self.cheat_backward)
|
|
||||||
menu.addAction(cheat_backward)
|
|
||||||
|
|
||||||
menu.exec_(event.screenPos())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def object_dialog_text(self) -> str:
|
|
||||||
"""Text to for the object's dialog in the context menu.
|
|
||||||
|
|
||||||
Right clicking a map object will open a context menu and the first item
|
|
||||||
will open the details dialog for this object. This menu action has the
|
|
||||||
same behavior as the on_click event.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
The text that should be displayed for the menu item.
|
|
||||||
"""
|
|
||||||
return "Details"
|
|
||||||
|
|
||||||
def on_click(self) -> None:
|
|
||||||
"""The action to take when this map object is left-clicked.
|
|
||||||
|
|
||||||
Typically this should open a details view of the object.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def open_new_package_dialog(self) -> None:
|
|
||||||
"""Opens the dialog for planning a new mission package."""
|
|
||||||
Dialog.open_new_package_dialog(self.mission_target)
|
|
||||||
|
|
||||||
def cheat_forward(self) -> None:
|
|
||||||
self.mission_target.blue_cp.base.affect_strength(0.1)
|
|
||||||
self.mission_target.red_cp.base.affect_strength(-0.1)
|
|
||||||
# Clear the ATO to replan missions affected by the front line.
|
|
||||||
self.game_model.game.reset_ato()
|
|
||||||
self.game_model.game.initialize_turn()
|
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
|
||||||
|
|
||||||
def cheat_backward(self) -> None:
|
|
||||||
self.mission_target.blue_cp.base.affect_strength(-0.1)
|
|
||||||
self.mission_target.red_cp.base.affect_strength(0.1)
|
|
||||||
# Clear the ATO to replan missions affected by the front line.
|
|
||||||
self.game_model.game.reset_ato()
|
|
||||||
self.game_model.game.initialize_turn()
|
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
|||||||
from PySide2.QtWidgets import QGraphicsScene, QGraphicsSceneMouseEvent
|
|
||||||
|
|
||||||
import qt_ui.uiconstants as CONST
|
|
||||||
|
|
||||||
|
|
||||||
class QLiberationScene(QGraphicsScene):
|
|
||||||
def __init__(self, parent):
|
|
||||||
super().__init__(parent)
|
|
||||||
item = self.addText(
|
|
||||||
'Go to "File/New Game" to setup a new campaign or go to "File/Open" to load an existing save game.',
|
|
||||||
CONST.FONT_PRIMARY,
|
|
||||||
)
|
|
||||||
item.setDefaultTextColor(CONST.COLORS["white"])
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
|
|
||||||
super(QLiberationScene, self).mouseMoveEvent(event)
|
|
||||||
self.parent().sceneMouseMovedEvent(event)
|
|
||||||
|
|
||||||
def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
|
|
||||||
super(QLiberationScene, self).mousePressEvent(event)
|
|
||||||
self.parent().sceneMousePressEvent(event)
|
|
||||||
@ -1,125 +0,0 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from PySide2.QtGui import QColor, QPainter
|
|
||||||
from PySide2.QtWidgets import QAction, QMenu
|
|
||||||
|
|
||||||
import qt_ui.uiconstants as const
|
|
||||||
from game.theater import ControlPoint, NavalControlPoint
|
|
||||||
from qt_ui.models import GameModel
|
|
||||||
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
|
|
||||||
from .QMapObject import QMapObject
|
|
||||||
from ...displayoptions import DisplayOptions
|
|
||||||
from ...windows.GameUpdateSignal import GameUpdateSignal
|
|
||||||
|
|
||||||
|
|
||||||
class QMapControlPoint(QMapObject):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
parent,
|
|
||||||
x: float,
|
|
||||||
y: float,
|
|
||||||
w: float,
|
|
||||||
h: float,
|
|
||||||
control_point: ControlPoint,
|
|
||||||
game_model: GameModel,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x, y, w, h, mission_target=control_point)
|
|
||||||
self.game_model = game_model
|
|
||||||
self.control_point = control_point
|
|
||||||
self.parent = parent
|
|
||||||
self.setZValue(1)
|
|
||||||
self.setToolTip(self.control_point.name)
|
|
||||||
self.base_details_dialog: Optional[QBaseMenu2] = None
|
|
||||||
self.capture_action = QAction(f"CHEAT: Capture {self.control_point.name}")
|
|
||||||
self.capture_action.triggered.connect(self.cheat_capture)
|
|
||||||
|
|
||||||
self.move_action = QAction("Move")
|
|
||||||
self.move_action.triggered.connect(self.move)
|
|
||||||
|
|
||||||
self.cancel_move_action = QAction("Cancel Move")
|
|
||||||
self.cancel_move_action.triggered.connect(self.cancel_move)
|
|
||||||
|
|
||||||
def paint(self, painter, option, widget=None) -> None:
|
|
||||||
if DisplayOptions.control_points:
|
|
||||||
painter.save()
|
|
||||||
painter.setRenderHint(QPainter.Antialiasing)
|
|
||||||
painter.setBrush(self.brush_color)
|
|
||||||
painter.setPen(self.pen_color)
|
|
||||||
|
|
||||||
if not self.control_point.runway_is_operational():
|
|
||||||
painter.setBrush(const.COLORS["black"])
|
|
||||||
painter.setPen(self.brush_color)
|
|
||||||
|
|
||||||
r = option.rect
|
|
||||||
painter.drawEllipse(r.x(), r.y(), r.width(), r.height())
|
|
||||||
# TODO: Draw sunk carriers differently.
|
|
||||||
# Either don't draw them at all, or perhaps use a sunk ship icon.
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def brush_color(self) -> QColor:
|
|
||||||
if self.control_point.captured:
|
|
||||||
return const.COLORS["blue"]
|
|
||||||
else:
|
|
||||||
return const.COLORS["super_red"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pen_color(self) -> QColor:
|
|
||||||
return const.COLORS["white"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def object_dialog_text(self) -> str:
|
|
||||||
if self.control_point.captured:
|
|
||||||
return "Open base menu"
|
|
||||||
else:
|
|
||||||
return "Open intel menu"
|
|
||||||
|
|
||||||
def on_click(self) -> None:
|
|
||||||
self.base_details_dialog = QBaseMenu2(
|
|
||||||
self.window(), self.control_point, self.game_model
|
|
||||||
)
|
|
||||||
self.base_details_dialog.show()
|
|
||||||
|
|
||||||
def add_context_menu_actions(self, menu: QMenu) -> None:
|
|
||||||
|
|
||||||
if self.control_point.moveable and self.control_point.captured:
|
|
||||||
menu.addAction(self.move_action)
|
|
||||||
if self.control_point.target_position is not None:
|
|
||||||
menu.addAction(self.cancel_move_action)
|
|
||||||
|
|
||||||
if self.control_point.is_fleet:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.control_point.captured:
|
|
||||||
return
|
|
||||||
|
|
||||||
for connected in self.control_point.connected_points:
|
|
||||||
if (
|
|
||||||
connected.captured
|
|
||||||
and self.game_model.game.settings.enable_base_capture_cheat
|
|
||||||
):
|
|
||||||
menu.addAction(self.capture_action)
|
|
||||||
break
|
|
||||||
|
|
||||||
def cheat_capture(self) -> None:
|
|
||||||
self.control_point.capture(self.game_model.game, for_player=True)
|
|
||||||
# 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.reset_ato()
|
|
||||||
self.game_model.game.initialize_turn()
|
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
|
||||||
|
|
||||||
def move(self):
|
|
||||||
self.parent.setSelectedUnit(self)
|
|
||||||
|
|
||||||
def cancel_move(self):
|
|
||||||
self.control_point.target_position = None
|
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
|
||||||
|
|
||||||
def open_new_package_dialog(self) -> None:
|
|
||||||
"""Extends the default packagedialog to redirect to base menu for red air base."""
|
|
||||||
is_navy = isinstance(self.control_point, NavalControlPoint)
|
|
||||||
if self.control_point.captured or is_navy:
|
|
||||||
super().open_new_package_dialog()
|
|
||||||
return
|
|
||||||
self.on_click()
|
|
||||||
@ -1,167 +0,0 @@
|
|||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from PySide2.QtCore import QRect
|
|
||||||
from PySide2.QtGui import QBrush
|
|
||||||
from PySide2.QtWidgets import QGraphicsItem
|
|
||||||
|
|
||||||
import qt_ui.uiconstants as const
|
|
||||||
from game import Game
|
|
||||||
from game.data.building_data import FORTIFICATION_BUILDINGS
|
|
||||||
from game.db import REWARDS
|
|
||||||
from game.theater import ControlPoint, TheaterGroundObject
|
|
||||||
from game.theater.theatergroundobject import (
|
|
||||||
MissileSiteGroundObject,
|
|
||||||
CoastalSiteGroundObject,
|
|
||||||
)
|
|
||||||
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
|
||||||
from .QMapObject import QMapObject
|
|
||||||
from ...displayoptions import DisplayOptions
|
|
||||||
|
|
||||||
|
|
||||||
class QMapGroundObject(QMapObject):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
parent,
|
|
||||||
x: float,
|
|
||||||
y: float,
|
|
||||||
w: float,
|
|
||||||
h: float,
|
|
||||||
control_point: ControlPoint,
|
|
||||||
ground_object: TheaterGroundObject,
|
|
||||||
game: Game,
|
|
||||||
buildings: Optional[List[TheaterGroundObject]] = None,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x, y, w, h, mission_target=ground_object)
|
|
||||||
self.ground_object = ground_object
|
|
||||||
self.control_point = control_point
|
|
||||||
self.parent = parent
|
|
||||||
self.game = game
|
|
||||||
self.setZValue(2)
|
|
||||||
self.buildings = buildings if buildings is not None else []
|
|
||||||
self.setFlag(QGraphicsItem.ItemIgnoresTransformations, False)
|
|
||||||
self.ground_object_dialog: Optional[QGroundObjectMenu] = None
|
|
||||||
self.setToolTip(self.tooltip)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tooltip(self) -> str:
|
|
||||||
lines = [
|
|
||||||
f"[{self.ground_object.obj_name}]",
|
|
||||||
f"${self.production_per_turn} per turn",
|
|
||||||
]
|
|
||||||
if self.ground_object.groups:
|
|
||||||
units = {}
|
|
||||||
for g in self.ground_object.groups:
|
|
||||||
for u in g.units:
|
|
||||||
if u.type in units:
|
|
||||||
units[u.type] = units[u.type] + 1
|
|
||||||
else:
|
|
||||||
units[u.type] = 1
|
|
||||||
|
|
||||||
for unit in units.keys():
|
|
||||||
lines.append(f"{unit} x {units[unit]}")
|
|
||||||
else:
|
|
||||||
for building in self.buildings:
|
|
||||||
if not building.is_dead:
|
|
||||||
lines.append(f"{building.dcs_identifier}")
|
|
||||||
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def production_per_turn(self) -> int:
|
|
||||||
production = 0
|
|
||||||
for building in self.buildings:
|
|
||||||
if building.is_dead:
|
|
||||||
continue
|
|
||||||
if building.category in REWARDS.keys():
|
|
||||||
production += REWARDS[building.category]
|
|
||||||
return production
|
|
||||||
|
|
||||||
def paint(self, painter, option, widget=None) -> None:
|
|
||||||
player_icons = "_blue"
|
|
||||||
enemy_icons = ""
|
|
||||||
|
|
||||||
if DisplayOptions.ground_objects:
|
|
||||||
painter.save()
|
|
||||||
|
|
||||||
cat = self.ground_object.category
|
|
||||||
|
|
||||||
rect = QRect(
|
|
||||||
option.rect.x() + 2,
|
|
||||||
option.rect.y(),
|
|
||||||
option.rect.width() - 2,
|
|
||||||
option.rect.height(),
|
|
||||||
)
|
|
||||||
|
|
||||||
is_dead = self.ground_object.is_dead
|
|
||||||
for building in self.buildings:
|
|
||||||
if not building.is_dead:
|
|
||||||
is_dead = False
|
|
||||||
break
|
|
||||||
|
|
||||||
if cat == "aa":
|
|
||||||
has_threat = False
|
|
||||||
for group in self.ground_object.groups:
|
|
||||||
if self.ground_object.threat_range(group).distance_in_meters > 0:
|
|
||||||
has_threat = True
|
|
||||||
|
|
||||||
if not is_dead and not self.control_point.captured:
|
|
||||||
if cat == "aa" and not has_threat:
|
|
||||||
painter.drawPixmap(rect, const.ICONS["nothreat" + enemy_icons])
|
|
||||||
else:
|
|
||||||
painter.drawPixmap(rect, const.ICONS[cat + enemy_icons])
|
|
||||||
elif not is_dead:
|
|
||||||
if cat == "aa" and not has_threat:
|
|
||||||
painter.drawPixmap(rect, const.ICONS["nothreat" + player_icons])
|
|
||||||
else:
|
|
||||||
painter.drawPixmap(rect, const.ICONS[cat + player_icons])
|
|
||||||
else:
|
|
||||||
painter.drawPixmap(rect, const.ICONS["destroyed"])
|
|
||||||
|
|
||||||
self.draw_health_gauge(painter, option)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
def draw_health_gauge(self, painter, option) -> None:
|
|
||||||
units_alive = 0
|
|
||||||
units_dead = 0
|
|
||||||
|
|
||||||
if len(self.ground_object.groups) == 0:
|
|
||||||
for building in self.buildings:
|
|
||||||
if building.dcs_identifier in FORTIFICATION_BUILDINGS:
|
|
||||||
continue
|
|
||||||
if building.is_dead:
|
|
||||||
units_dead += 1
|
|
||||||
else:
|
|
||||||
units_alive += 1
|
|
||||||
|
|
||||||
for g in self.ground_object.groups:
|
|
||||||
units_alive += len(g.units)
|
|
||||||
if hasattr(g, "units_losts"):
|
|
||||||
units_dead += len(g.units_losts)
|
|
||||||
|
|
||||||
if units_dead + units_alive > 0:
|
|
||||||
ratio = float(units_alive) / (float(units_dead) + float(units_alive))
|
|
||||||
bar_height = ratio * option.rect.height()
|
|
||||||
painter.fillRect(
|
|
||||||
option.rect.x(),
|
|
||||||
option.rect.y(),
|
|
||||||
2,
|
|
||||||
option.rect.height(),
|
|
||||||
QBrush(const.COLORS["dark_red"]),
|
|
||||||
)
|
|
||||||
painter.fillRect(
|
|
||||||
option.rect.x(),
|
|
||||||
option.rect.y(),
|
|
||||||
2,
|
|
||||||
bar_height,
|
|
||||||
QBrush(const.COLORS["green"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_click(self) -> None:
|
|
||||||
self.ground_object_dialog = QGroundObjectMenu(
|
|
||||||
self.window(),
|
|
||||||
self.ground_object,
|
|
||||||
self.buildings,
|
|
||||||
self.control_point,
|
|
||||||
self.game,
|
|
||||||
)
|
|
||||||
self.ground_object_dialog.show()
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
"""Common base for objects drawn on the game map."""
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
|
||||||
from PySide2.QtWidgets import (
|
|
||||||
QAction,
|
|
||||||
QGraphicsRectItem,
|
|
||||||
QGraphicsSceneContextMenuEvent,
|
|
||||||
QGraphicsSceneHoverEvent,
|
|
||||||
QGraphicsSceneMouseEvent,
|
|
||||||
QMenu,
|
|
||||||
)
|
|
||||||
|
|
||||||
from qt_ui.dialogs import Dialog
|
|
||||||
from qt_ui.windows.mission.QPackageDialog import QNewPackageDialog
|
|
||||||
from game.theater.missiontarget import MissionTarget
|
|
||||||
|
|
||||||
|
|
||||||
class QMapObject(QGraphicsRectItem):
|
|
||||||
"""Base class for objects drawn on the game map.
|
|
||||||
|
|
||||||
Game map objects have an on_click behavior that triggers on left click, and
|
|
||||||
change the mouse cursor on hover.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self, x: float, y: float, w: float, h: float, mission_target: MissionTarget
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x, y, w, h)
|
|
||||||
self.mission_target = mission_target
|
|
||||||
self.new_package_dialog: Optional[QNewPackageDialog] = None
|
|
||||||
self.setAcceptHoverEvents(True)
|
|
||||||
|
|
||||||
def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
|
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
|
||||||
|
|
||||||
def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
|
|
||||||
if event.button() == Qt.LeftButton:
|
|
||||||
self.on_click()
|
|
||||||
|
|
||||||
def add_context_menu_actions(self, menu: QMenu) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None:
|
|
||||||
menu = QMenu("Menu", self.parent)
|
|
||||||
|
|
||||||
object_details_action = QAction(self.object_dialog_text)
|
|
||||||
object_details_action.triggered.connect(self.on_click)
|
|
||||||
menu.addAction(object_details_action)
|
|
||||||
|
|
||||||
# Not all locations have valid objectives. Off-map spawns, for example,
|
|
||||||
# have no mission types.
|
|
||||||
if list(self.mission_target.mission_types(for_player=True)):
|
|
||||||
new_package_action = QAction(f"New package")
|
|
||||||
new_package_action.triggered.connect(self.open_new_package_dialog)
|
|
||||||
menu.addAction(new_package_action)
|
|
||||||
|
|
||||||
self.add_context_menu_actions(menu)
|
|
||||||
|
|
||||||
menu.exec_(event.screenPos())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def object_dialog_text(self) -> str:
|
|
||||||
"""Text to for the object's dialog in the context menu.
|
|
||||||
|
|
||||||
Right clicking a map object will open a context menu and the first item
|
|
||||||
will open the details dialog for this object. This menu action has the
|
|
||||||
same behavior as the on_click event.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
The text that should be displayed for the menu item.
|
|
||||||
"""
|
|
||||||
return "Details"
|
|
||||||
|
|
||||||
def on_click(self) -> None:
|
|
||||||
"""The action to take when this map object is left-clicked.
|
|
||||||
|
|
||||||
Typically this should open a details view of the object.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def open_new_package_dialog(self) -> None:
|
|
||||||
"""Opens the dialog for planning a new mission package."""
|
|
||||||
Dialog.open_new_package_dialog(self.mission_target)
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
|
||||||
from PySide2.QtGui import QColor, QPen
|
|
||||||
from PySide2.QtWidgets import (
|
|
||||||
QGraphicsItem,
|
|
||||||
QGraphicsLineItem,
|
|
||||||
)
|
|
||||||
|
|
||||||
from game.theater import ControlPoint
|
|
||||||
from game.transfers import CargoShip
|
|
||||||
from qt_ui.uiconstants import COLORS
|
|
||||||
|
|
||||||
|
|
||||||
class ShippingLaneSegment(QGraphicsLineItem):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
x0: float,
|
|
||||||
y0: float,
|
|
||||||
x1: float,
|
|
||||||
y1: float,
|
|
||||||
control_point_a: ControlPoint,
|
|
||||||
control_point_b: ControlPoint,
|
|
||||||
ships: List[CargoShip],
|
|
||||||
parent: Optional[QGraphicsItem] = None,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x0, y0, x1, y1, parent)
|
|
||||||
self.control_point_a = control_point_a
|
|
||||||
self.control_point_b = control_point_b
|
|
||||||
self.ships = ships
|
|
||||||
self.setPen(self.make_pen())
|
|
||||||
self.setToolTip(self.make_tooltip())
|
|
||||||
self.setAcceptHoverEvents(True)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def has_ships(self) -> bool:
|
|
||||||
return bool(self.ships)
|
|
||||||
|
|
||||||
def make_tooltip(self) -> str:
|
|
||||||
if not self.has_ships:
|
|
||||||
return "No ships present in this shipping lane."
|
|
||||||
|
|
||||||
ships = []
|
|
||||||
for ship in self.ships:
|
|
||||||
units = "units" if ship.size > 1 else "unit"
|
|
||||||
ships.append(
|
|
||||||
f"{ship.size} {units} transferring from {ship.origin} to "
|
|
||||||
f"{ship.destination}."
|
|
||||||
)
|
|
||||||
return "\n".join(ships)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def line_color(self) -> QColor:
|
|
||||||
if self.control_point_a.captured:
|
|
||||||
return COLORS["dark_blue"]
|
|
||||||
else:
|
|
||||||
return COLORS["dark_red"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def line_style(self) -> Qt.PenStyle:
|
|
||||||
if self.has_ships:
|
|
||||||
return Qt.PenStyle.SolidLine
|
|
||||||
return Qt.PenStyle.DotLine
|
|
||||||
|
|
||||||
def make_pen(self) -> QPen:
|
|
||||||
pen = QPen(brush=self.line_color)
|
|
||||||
pen.setColor(self.line_color)
|
|
||||||
pen.setStyle(self.line_style)
|
|
||||||
pen.setWidth(2)
|
|
||||||
return pen
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
from functools import cached_property
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
|
||||||
from PySide2.QtGui import QColor, QPen
|
|
||||||
from PySide2.QtWidgets import (
|
|
||||||
QGraphicsItem,
|
|
||||||
QGraphicsLineItem,
|
|
||||||
)
|
|
||||||
|
|
||||||
from game.theater import ControlPoint
|
|
||||||
from game.transfers import Convoy
|
|
||||||
from qt_ui.uiconstants import COLORS
|
|
||||||
|
|
||||||
|
|
||||||
class SupplyRouteSegment(QGraphicsLineItem):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
x0: float,
|
|
||||||
y0: float,
|
|
||||||
x1: float,
|
|
||||||
y1: float,
|
|
||||||
control_point_a: ControlPoint,
|
|
||||||
control_point_b: ControlPoint,
|
|
||||||
convoys: List[Convoy],
|
|
||||||
parent: Optional[QGraphicsItem] = None,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(x0, y0, x1, y1, parent)
|
|
||||||
self.control_point_a = control_point_a
|
|
||||||
self.control_point_b = control_point_b
|
|
||||||
self.convoys = convoys
|
|
||||||
self.setPen(self.make_pen())
|
|
||||||
self.setToolTip(self.make_tooltip())
|
|
||||||
self.setAcceptHoverEvents(True)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def has_convoys(self) -> bool:
|
|
||||||
return bool(self.convoys)
|
|
||||||
|
|
||||||
def make_tooltip(self) -> str:
|
|
||||||
if not self.has_convoys:
|
|
||||||
return "No convoys present on this supply route."
|
|
||||||
|
|
||||||
convoys = []
|
|
||||||
for convoy in self.convoys:
|
|
||||||
units = "units" if convoy.size > 1 else "unit"
|
|
||||||
convoys.append(
|
|
||||||
f"{convoy.size} {units} transferring from {convoy.origin} to "
|
|
||||||
f"{convoy.destination}"
|
|
||||||
)
|
|
||||||
return "\n".join(convoys)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def line_color(self) -> QColor:
|
|
||||||
if self.control_point_a.front_is_active(self.control_point_b):
|
|
||||||
return COLORS["red"]
|
|
||||||
elif self.control_point_a.captured:
|
|
||||||
return COLORS["dark_blue"]
|
|
||||||
else:
|
|
||||||
return COLORS["dark_red"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def line_style(self) -> Qt.PenStyle:
|
|
||||||
if (
|
|
||||||
self.control_point_a.front_is_active(self.control_point_b)
|
|
||||||
or self.has_convoys
|
|
||||||
):
|
|
||||||
return Qt.PenStyle.SolidLine
|
|
||||||
return Qt.PenStyle.DotLine
|
|
||||||
|
|
||||||
def make_pen(self) -> QPen:
|
|
||||||
pen = QPen(brush=self.line_color)
|
|
||||||
pen.setColor(self.line_color)
|
|
||||||
pen.setStyle(self.line_style)
|
|
||||||
pen.setWidth(6)
|
|
||||||
return pen
|
|
||||||
@ -36,6 +36,8 @@ from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
|||||||
LeafletLatLon = list[float]
|
LeafletLatLon = list[float]
|
||||||
LeafletPoly = list[LeafletLatLon]
|
LeafletPoly = list[LeafletLatLon]
|
||||||
|
|
||||||
|
MAX_SHIP_DISTANCE = nautical_miles(80)
|
||||||
|
|
||||||
# **EVERY PROPERTY NEEDS A NOTIFY SIGNAL**
|
# **EVERY PROPERTY NEEDS A NOTIFY SIGNAL**
|
||||||
#
|
#
|
||||||
# https://bugreports.qt.io/browse/PYSIDE-1426
|
# https://bugreports.qt.io/browse/PYSIDE-1426
|
||||||
|
|||||||
@ -22,12 +22,11 @@ from game import Game, VERSION, persistency
|
|||||||
from game.debriefing import Debriefing
|
from game.debriefing import Debriefing
|
||||||
from qt_ui import liberation_install
|
from qt_ui import liberation_install
|
||||||
from qt_ui.dialogs import Dialog
|
from qt_ui.dialogs import Dialog
|
||||||
from qt_ui.displayoptions import DisplayGroup, DisplayOptions, DisplayRule
|
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.uiconstants import URLS
|
from qt_ui.uiconstants import URLS
|
||||||
from qt_ui.widgets.QTopPanel import QTopPanel
|
from qt_ui.widgets.QTopPanel import QTopPanel
|
||||||
from qt_ui.widgets.ato import QAirTaskingOrderPanel
|
from qt_ui.widgets.ato import QAirTaskingOrderPanel
|
||||||
from qt_ui.widgets.map.QLiberationMap import LeafletMap, QLiberationMap, LiberationMap
|
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
|
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
|
||||||
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
|
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
|
||||||
@ -38,7 +37,7 @@ from qt_ui.windows.preferences.QLiberationPreferencesWindow import (
|
|||||||
|
|
||||||
|
|
||||||
class QLiberationWindow(QMainWindow):
|
class QLiberationWindow(QMainWindow):
|
||||||
def __init__(self, game: Optional[Game], new_map: bool) -> None:
|
def __init__(self, game: Optional[Game]) -> None:
|
||||||
super(QLiberationWindow, self).__init__()
|
super(QLiberationWindow, self).__init__()
|
||||||
|
|
||||||
self.game = game
|
self.game = game
|
||||||
@ -46,7 +45,7 @@ class QLiberationWindow(QMainWindow):
|
|||||||
Dialog.set_game(self.game_model)
|
Dialog.set_game(self.game_model)
|
||||||
self.ato_panel = QAirTaskingOrderPanel(self.game_model)
|
self.ato_panel = QAirTaskingOrderPanel(self.game_model)
|
||||||
self.info_panel = QInfoPanel(self.game)
|
self.info_panel = QInfoPanel(self.game)
|
||||||
self.liberation_map: LiberationMap = self.create_map(new_map)
|
self.liberation_map = QLiberationMap(self.game_model, self)
|
||||||
|
|
||||||
self.setGeometry(300, 100, 270, 100)
|
self.setGeometry(300, 100, 270, 100)
|
||||||
self.setWindowTitle(f"DCS Liberation - v{VERSION}")
|
self.setWindowTitle(f"DCS Liberation - v{VERSION}")
|
||||||
@ -174,30 +173,6 @@ class QLiberationWindow(QMainWindow):
|
|||||||
file_menu.addSeparator()
|
file_menu.addSeparator()
|
||||||
file_menu.addAction("E&xit", self.close)
|
file_menu.addAction("E&xit", self.close)
|
||||||
|
|
||||||
displayMenu = self.menu.addMenu("&Display")
|
|
||||||
|
|
||||||
last_was_group = False
|
|
||||||
for item in DisplayOptions.menu_items():
|
|
||||||
if isinstance(item, DisplayRule):
|
|
||||||
if last_was_group:
|
|
||||||
displayMenu.addSeparator()
|
|
||||||
self.display_bar.addSeparator()
|
|
||||||
action = self.make_display_rule_action(item)
|
|
||||||
displayMenu.addAction(action)
|
|
||||||
if action.icon():
|
|
||||||
self.display_bar.addAction(action)
|
|
||||||
last_was_group = False
|
|
||||||
elif isinstance(item, DisplayGroup):
|
|
||||||
displayMenu.addSeparator()
|
|
||||||
self.display_bar.addSeparator()
|
|
||||||
group = QActionGroup(displayMenu)
|
|
||||||
for display_rule in item:
|
|
||||||
action = self.make_display_rule_action(display_rule, group)
|
|
||||||
displayMenu.addAction(action)
|
|
||||||
if action.icon():
|
|
||||||
self.display_bar.addAction(action)
|
|
||||||
last_was_group = True
|
|
||||||
|
|
||||||
help_menu = self.menu.addMenu("&Help")
|
help_menu = self.menu.addMenu("&Help")
|
||||||
help_menu.addAction(self.openDiscordAction)
|
help_menu.addAction(self.openDiscordAction)
|
||||||
help_menu.addAction(self.openGithubAction)
|
help_menu.addAction(self.openGithubAction)
|
||||||
@ -284,11 +259,6 @@ class QLiberationWindow(QMainWindow):
|
|||||||
self.game = game
|
self.game = game
|
||||||
GameUpdateSignal.get_instance().game_loaded.emit(self.game)
|
GameUpdateSignal.get_instance().game_loaded.emit(self.game)
|
||||||
|
|
||||||
def create_map(self, new_map: bool) -> LiberationMap:
|
|
||||||
if new_map:
|
|
||||||
return LeafletMap(self.game_model, self)
|
|
||||||
return QLiberationMap(self.game_model)
|
|
||||||
|
|
||||||
def setGame(self, game: Optional[Game]):
|
def setGame(self, game: Optional[Game]):
|
||||||
try:
|
try:
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user