Add BAI planning against supply routes.

This currently is only supported for player flights. I have no idea how
to create an AI flight plan that won't just get them killed. AI-only BAI
missions against supply routes will warn the player on mission creation.
This commit is contained in:
Dan Albert
2021-04-19 23:09:39 -07:00
parent 2b06d8a096
commit 3f16c0378a
5 changed files with 238 additions and 2 deletions

View File

@@ -16,6 +16,8 @@ import qt_ui.uiconstants as CONST
from game import Game
from game.event.airwar import AirWarEvent
from gen.ato import Package
from gen.flights.flight import FlightType
from gen.flights.flightplan import ConvoyInterdictionFlightPlan
from gen.flights.traveltime import TotEstimator
from qt_ui.models import GameModel
from qt_ui.widgets.QBudgetBox import QBudgetBox
@@ -199,6 +201,36 @@ class QTopPanel(QFrame):
)
return result == QMessageBox.Yes
def ato_has_ai_convoy_interdiction(self) -> bool:
for package in self.game.blue_ato.packages:
for flight in package.flights:
if (
isinstance(flight.flight_plan, ConvoyInterdictionFlightPlan)
and not flight.client_count
):
return True
return False
def confirm_ai_convoy_interdiction_launch(self) -> bool:
result = QMessageBox.question(
self,
"Continue with AI convoy interdiction missions?",
(
"AI only convoy interdiction missions were planned. AI behavior for "
"these missions has not been developed so they will probably get "
"themselves killed. Continuing is not recommended.<br />"
"<br />"
"To remove AI convoy interdiction missions, delete any BAI flights "
"that are planned against supply route objectives.<br />"
"<br />"
"Click 'Yes' to continue with AI only convoy interdiction missions."
"<br /><br />Click 'No' to cancel and revise your flight planning."
),
QMessageBox.No,
QMessageBox.Yes,
)
return result == QMessageBox.Yes
def confirm_negative_start_time(self, negative_starts: List[Package]) -> bool:
formatted = "<br />".join(
[f"{p.primary_task} {p.target.name}" for p in negative_starts]
@@ -241,6 +273,12 @@ class QTopPanel(QFrame):
if not self.ato_has_clients() and not self.confirm_no_client_launch():
return
if (
self.ato_has_ai_convoy_interdiction()
and not self.confirm_ai_convoy_interdiction_launch()
):
return
negative_starts = self.negative_start_packages()
if negative_starts:
if not self.confirm_negative_start_time(negative_starts):

View File

@@ -3,10 +3,19 @@ from typing import List, Optional
from PySide2.QtCore import Qt
from PySide2.QtGui import QColor, QPen
from PySide2.QtWidgets import QGraphicsItem, QGraphicsLineItem
from PySide2.QtWidgets import (
QAction,
QGraphicsItem,
QGraphicsLineItem,
QGraphicsSceneContextMenuEvent,
QGraphicsSceneHoverEvent,
QMenu,
)
from game.theater import ControlPoint
from game.theater.supplyroutes import SupplyRouteLink
from game.transfers import RoadTransferOrder
from qt_ui.dialogs import Dialog
from qt_ui.uiconstants import COLORS
@@ -28,6 +37,7 @@ class SupplyRouteSegment(QGraphicsLineItem):
self.convoys = convoys
self.setPen(self.make_pen())
self.setToolTip(self.make_tooltip())
self.setAcceptHoverEvents(True)
@cached_property
def convoy_size(self) -> int:
@@ -71,3 +81,33 @@ class SupplyRouteSegment(QGraphicsLineItem):
@property
def has_convoys(self) -> bool:
return bool(self.convoys)
@property
def targetable(self) -> bool:
return self.convoys and not self.control_point_a.captured
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None:
# Can only plan missions against enemy supply routes that have convoys.
if not self.targetable:
super().contextMenuEvent(event)
return
menu = QMenu("Menu")
new_package_action = QAction(f"New package")
new_package_action.triggered.connect(self.open_new_package_dialog)
menu.addAction(new_package_action)
menu.exec_(event.screenPos())
def open_new_package_dialog(self) -> None:
"""Opens the dialog for planning a new mission package."""
Dialog.open_new_package_dialog(
SupplyRouteLink(self.control_point_a, self.control_point_b)
)
def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
if self.targetable:
self.setCursor(Qt.PointingHandCursor)
else:
super().hoverEnterEvent(event)