Restrict transfers to connected bases.

https://github.com/Khopa/dcs_liberation/issues/824
This commit is contained in:
Dan Albert 2021-04-17 17:27:21 -07:00
parent e9ff554f39
commit 65f6a4eddd
4 changed files with 54 additions and 10 deletions

View File

@ -8,7 +8,7 @@ from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from functools import total_ordering from functools import total_ordering
from typing import Any, Dict, Iterator, List, Optional, TYPE_CHECKING, Type from typing import Any, Dict, Iterator, List, Optional, Set, TYPE_CHECKING, Type
from dcs.mapping import Point from dcs.mapping import Point
from dcs.ships import ( from dcs.ships import (
@ -292,6 +292,23 @@ class ControlPoint(MissionTarget, ABC):
def is_global(self): def is_global(self):
return not self.connected_points return not self.connected_points
def transitive_connected_friendly_points(
self, seen: Optional[Set[ControlPoint]] = None
) -> List[ControlPoint]:
if seen is None:
seen = {self}
connected = []
for cp in self.connected_points:
if cp.captured != self.captured:
continue
if cp in seen:
continue
seen.add(cp)
connected.append(cp)
connected.extend(cp.transitive_connected_friendly_points(seen))
return connected
@property @property
def is_carrier(self): def is_carrier(self):
""" """

View File

@ -0,0 +1,23 @@
from __future__ import annotations
from typing import Iterator, List, Optional
from game.theater.controlpoint import ControlPoint
class SupplyRoute:
def __init__(self, control_points: List[ControlPoint]) -> None:
self.control_points = control_points
def __contains__(self, item: ControlPoint) -> bool:
return item in self.control_points
def __iter__(self) -> Iterator[ControlPoint]:
yield from self.control_points
@classmethod
def for_control_point(cls, control_point: ControlPoint) -> Optional[SupplyRoute]:
connected_friendly_points = control_point.transitive_connected_friendly_points()
if not connected_friendly_points:
return None
return SupplyRoute([control_point] + connected_friendly_points)

View File

@ -24,18 +24,18 @@ from dcs.task import PinpointStrike
from dcs.unittype import UnitType from dcs.unittype import UnitType
from game import db from game import db
from game.theater import ControlPoint from game.theater import ControlPoint, SupplyRoute
from game.transfers import RoadTransferOrder from game.transfers import RoadTransferOrder
from qt_ui.models import GameModel from qt_ui.models import GameModel
from qt_ui.widgets.QLabeledWidget import QLabeledWidget from qt_ui.widgets.QLabeledWidget import QLabeledWidget
class TransferDestinationComboBox(QComboBox): class TransferDestinationComboBox(QComboBox):
def __init__(self, game_model: GameModel, origin: ControlPoint) -> None: def __init__(self, origin: ControlPoint) -> None:
super().__init__() super().__init__()
for cp in game_model.game.theater.controlpoints: for cp in SupplyRoute.for_control_point(origin):
if cp != origin and cp.captured and not cp.is_global: if cp != origin and cp.captured:
self.addItem(cp.name, cp) self.addItem(cp.name, cp)
self.model().sort(0) self.model().sort(0)
self.setCurrentIndex(0) self.setCurrentIndex(0)
@ -81,10 +81,10 @@ class UnitTransferList(QFrame):
class TransferDestinationPanel(QVBoxLayout): class TransferDestinationPanel(QVBoxLayout):
def __init__(self, label: str, origin: ControlPoint, game_model: GameModel) -> None: def __init__(self, label: str, origin: ControlPoint) -> None:
super().__init__() super().__init__()
self.source_combo_box = TransferDestinationComboBox(game_model, origin) self.source_combo_box = TransferDestinationComboBox(origin)
self.addLayout(QLabeledWidget(label, self.source_combo_box)) self.addLayout(QLabeledWidget(label, self.source_combo_box))
@property @property
@ -266,7 +266,7 @@ class NewUnitTransferDialog(QDialog):
layout = QVBoxLayout() layout = QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
self.dest_panel = TransferDestinationPanel("Destination:", origin, game_model) self.dest_panel = TransferDestinationPanel("Destination:", origin)
self.dest_panel.changed.connect(self.on_destination_changed) self.dest_panel.changed.connect(self.on_destination_changed)
layout.addLayout(self.dest_panel) layout.addLayout(self.dest_panel)

View File

@ -11,7 +11,7 @@ from PySide2.QtWidgets import (
) )
from game import Game, db from game import Game, db
from game.theater import ControlPoint, ControlPointType from game.theater import ControlPoint, ControlPointType, SupplyRoute
from gen.flights.flight import FlightType from gen.flights.flight import FlightType
from qt_ui.dialogs import Dialog from qt_ui.dialogs import Dialog
from qt_ui.models import GameModel from qt_ui.models import GameModel
@ -89,7 +89,7 @@ class QBaseMenu2(QDialog):
runway_attack_button.setProperty("style", "btn-danger") runway_attack_button.setProperty("style", "btn-danger")
runway_attack_button.clicked.connect(self.new_package) runway_attack_button.clicked.connect(self.new_package)
if self.cp.captured and not self.cp.is_global: if self.cp.captured and self.has_transfer_destinations:
transfer_button = QPushButton("Transfer Units") transfer_button = QPushButton("Transfer Units")
bottom_row.addWidget(transfer_button) bottom_row.addWidget(transfer_button)
transfer_button.clicked.connect(self.open_transfer_dialog) transfer_button.clicked.connect(self.open_transfer_dialog)
@ -103,6 +103,10 @@ class QBaseMenu2(QDialog):
GameUpdateSignal.get_instance().budgetupdated.connect(self.update_budget) GameUpdateSignal.get_instance().budgetupdated.connect(self.update_budget)
self.setLayout(main_layout) self.setLayout(main_layout)
@property
def has_transfer_destinations(self) -> bool:
return SupplyRoute.for_control_point(self.cp) is not None
@property @property
def can_repair_runway(self) -> bool: def can_repair_runway(self) -> bool:
return self.cp.captured and self.cp.runway_can_be_repaired return self.cp.captured and self.cp.runway_can_be_repaired