mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add runway bombing missions.
This allows planning the missions and the missions are functional, but they will have no effect on future turns yet.
This commit is contained in:
parent
63bdbebcaa
commit
9394ed663a
@ -401,16 +401,18 @@ class Airfield(ControlPoint):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||||
yield from super().mission_types(for_player)
|
from gen.flights.flight import FlightType
|
||||||
if self.is_friendly(for_player):
|
if self.is_friendly(for_player):
|
||||||
yield from [
|
yield from [
|
||||||
# TODO: FlightType.INTERCEPTION
|
# TODO: FlightType.INTERCEPTION
|
||||||
# TODO: FlightType.LOGISTICS
|
# TODO: FlightType.LOGISTICS
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
yield from [
|
yield from [
|
||||||
# TODO: FlightType.STRIKE
|
FlightType.RUNWAY_ATTACK,
|
||||||
]
|
# TODO: FlightType.OCA_STRIKE
|
||||||
|
]
|
||||||
|
yield from super().mission_types(for_player)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_aircraft_parking(self) -> int:
|
def total_aircraft_parking(self) -> int:
|
||||||
|
|||||||
@ -41,6 +41,7 @@ from dcs.task import (
|
|||||||
AntishipStrike,
|
AntishipStrike,
|
||||||
AttackGroup,
|
AttackGroup,
|
||||||
Bombing,
|
Bombing,
|
||||||
|
BombingRunway,
|
||||||
CAP,
|
CAP,
|
||||||
CAS,
|
CAS,
|
||||||
ControlledTask,
|
ControlledTask,
|
||||||
@ -55,6 +56,7 @@ from dcs.task import (
|
|||||||
OptReactOnThreat,
|
OptReactOnThreat,
|
||||||
OptRestrictJettison,
|
OptRestrictJettison,
|
||||||
OrbitAction,
|
OrbitAction,
|
||||||
|
RunwayAttack,
|
||||||
SEAD,
|
SEAD,
|
||||||
StartCommand,
|
StartCommand,
|
||||||
Targets,
|
Targets,
|
||||||
@ -1169,6 +1171,18 @@ class AircraftConflictGenerator:
|
|||||||
roe=OptROE.Values.OpenFire,
|
roe=OptROE.Values.OpenFire,
|
||||||
restrict_jettison=True)
|
restrict_jettison=True)
|
||||||
|
|
||||||
|
def configure_runway_attack(
|
||||||
|
self, group: FlyingGroup, package: Package, flight: Flight,
|
||||||
|
dynamic_runways: Dict[str, RunwayData]) -> None:
|
||||||
|
group.task = RunwayAttack.name
|
||||||
|
self._setup_group(group, RunwayAttack, package, flight,
|
||||||
|
dynamic_runways)
|
||||||
|
self.configure_behavior(
|
||||||
|
group,
|
||||||
|
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
||||||
|
roe=OptROE.Values.OpenFire,
|
||||||
|
restrict_jettison=True)
|
||||||
|
|
||||||
def configure_escort(self, group: FlyingGroup, package: Package,
|
def configure_escort(self, group: FlyingGroup, package: Package,
|
||||||
flight: Flight,
|
flight: Flight,
|
||||||
dynamic_runways: Dict[str, RunwayData]) -> None:
|
dynamic_runways: Dict[str, RunwayData]) -> None:
|
||||||
@ -1206,6 +1220,9 @@ class AircraftConflictGenerator:
|
|||||||
self.configure_anti_ship(group, package, flight, dynamic_runways)
|
self.configure_anti_ship(group, package, flight, dynamic_runways)
|
||||||
elif flight_type == FlightType.ESCORT:
|
elif flight_type == FlightType.ESCORT:
|
||||||
self.configure_escort(group, package, flight, dynamic_runways)
|
self.configure_escort(group, package, flight, dynamic_runways)
|
||||||
|
elif flight_type == FlightType.RUNWAY_ATTACK:
|
||||||
|
self.configure_runway_attack(group, package, flight,
|
||||||
|
dynamic_runways)
|
||||||
else:
|
else:
|
||||||
self.configure_unknown_task(group, flight)
|
self.configure_unknown_task(group, flight)
|
||||||
|
|
||||||
@ -1345,6 +1362,7 @@ class PydcsWaypointBuilder:
|
|||||||
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
||||||
|
FlightWaypointType.INGRESS_RUNWAY_BOMBING: RunwayBombingIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_SEAD: SeadIngressBuilder,
|
FlightWaypointType.INGRESS_SEAD: SeadIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_STRIKE: StrikeIngressBuilder,
|
FlightWaypointType.INGRESS_STRIKE: StrikeIngressBuilder,
|
||||||
FlightWaypointType.JOIN: JoinPointBuilder,
|
FlightWaypointType.JOIN: JoinPointBuilder,
|
||||||
@ -1480,6 +1498,22 @@ class DeadIngressBuilder(PydcsWaypointBuilder):
|
|||||||
return waypoint
|
return waypoint
|
||||||
|
|
||||||
|
|
||||||
|
class RunwayBombingIngressBuilder(PydcsWaypointBuilder):
|
||||||
|
def build(self) -> MovingPoint:
|
||||||
|
waypoint = super().build()
|
||||||
|
|
||||||
|
target = self.package.target
|
||||||
|
if not isinstance(target, Airfield):
|
||||||
|
logging.error(
|
||||||
|
"Unexpected target type for runway bombing mission: %s",
|
||||||
|
target.__class__.__name__)
|
||||||
|
return waypoint
|
||||||
|
|
||||||
|
waypoint.tasks.append(
|
||||||
|
BombingRunway(airport_id=target.airport.id, group_attack=True))
|
||||||
|
return waypoint
|
||||||
|
|
||||||
|
|
||||||
class SeadIngressBuilder(PydcsWaypointBuilder):
|
class SeadIngressBuilder(PydcsWaypointBuilder):
|
||||||
def build(self) -> MovingPoint:
|
def build(self) -> MovingPoint:
|
||||||
waypoint = super().build()
|
waypoint = super().build()
|
||||||
|
|||||||
@ -44,6 +44,8 @@ from gen.flights.ai_flight_planner_db import (
|
|||||||
CAP_PREFERRED,
|
CAP_PREFERRED,
|
||||||
CAS_CAPABLE,
|
CAS_CAPABLE,
|
||||||
CAS_PREFERRED,
|
CAS_PREFERRED,
|
||||||
|
RUNWAY_ATTACK_CAPABLE,
|
||||||
|
RUNWAY_ATTACK_PREFERRED,
|
||||||
SEAD_CAPABLE,
|
SEAD_CAPABLE,
|
||||||
SEAD_PREFERRED,
|
SEAD_PREFERRED,
|
||||||
STRIKE_CAPABLE,
|
STRIKE_CAPABLE,
|
||||||
@ -160,6 +162,8 @@ class AircraftAllocator:
|
|||||||
return CAS_PREFERRED
|
return CAS_PREFERRED
|
||||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||||
return SEAD_PREFERRED
|
return SEAD_PREFERRED
|
||||||
|
elif task == FlightType.RUNWAY_ATTACK:
|
||||||
|
return RUNWAY_ATTACK_PREFERRED
|
||||||
elif task == FlightType.STRIKE:
|
elif task == FlightType.STRIKE:
|
||||||
return STRIKE_PREFERRED
|
return STRIKE_PREFERRED
|
||||||
elif task == FlightType.ESCORT:
|
elif task == FlightType.ESCORT:
|
||||||
@ -180,6 +184,8 @@ class AircraftAllocator:
|
|||||||
return CAS_CAPABLE
|
return CAS_CAPABLE
|
||||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||||
return SEAD_CAPABLE
|
return SEAD_CAPABLE
|
||||||
|
elif task == FlightType.RUNWAY_ATTACK:
|
||||||
|
return RUNWAY_ATTACK_CAPABLE
|
||||||
elif task == FlightType.STRIKE:
|
elif task == FlightType.STRIKE:
|
||||||
return STRIKE_CAPABLE
|
return STRIKE_CAPABLE
|
||||||
elif task == FlightType.ESCORT:
|
elif task == FlightType.ESCORT:
|
||||||
|
|||||||
@ -484,6 +484,13 @@ ANTISHIP_PREFERRED = [
|
|||||||
Su_24M,
|
Su_24M,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
RUNWAY_ATTACK_PREFERRED = [
|
||||||
|
JF_17,
|
||||||
|
M_2000C,
|
||||||
|
]
|
||||||
|
|
||||||
|
RUNWAY_ATTACK_CAPABLE = STRIKE_CAPABLE
|
||||||
|
|
||||||
DRONES = [
|
DRONES = [
|
||||||
MQ_9_Reaper,
|
MQ_9_Reaper,
|
||||||
RQ_1A_Predator,
|
RQ_1A_Predator,
|
||||||
|
|||||||
@ -39,6 +39,7 @@ class FlightType(Enum):
|
|||||||
EWAR = 16
|
EWAR = 16
|
||||||
|
|
||||||
SWEEP = 17
|
SWEEP = 17
|
||||||
|
RUNWAY_ATTACK = 18
|
||||||
|
|
||||||
|
|
||||||
class FlightWaypointType(Enum):
|
class FlightWaypointType(Enum):
|
||||||
@ -66,6 +67,7 @@ class FlightWaypointType(Enum):
|
|||||||
INGRESS_SWEEP = 21
|
INGRESS_SWEEP = 21
|
||||||
INGRESS_BAI = 22
|
INGRESS_BAI = 22
|
||||||
DIVERT = 23
|
DIVERT = 23
|
||||||
|
INGRESS_RUNWAY_BOMBING = 24
|
||||||
|
|
||||||
|
|
||||||
class FlightWaypoint:
|
class FlightWaypoint:
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from dcs.unit import Unit
|
|||||||
|
|
||||||
from game.data.doctrine import Doctrine
|
from game.data.doctrine import Doctrine
|
||||||
from game.theater import (
|
from game.theater import (
|
||||||
|
Airfield,
|
||||||
ControlPoint,
|
ControlPoint,
|
||||||
FrontLine,
|
FrontLine,
|
||||||
MissionTarget,
|
MissionTarget,
|
||||||
@ -650,6 +651,8 @@ class FlightPlanBuilder:
|
|||||||
return self.generate_dead(flight, custom_targets)
|
return self.generate_dead(flight, custom_targets)
|
||||||
elif task == FlightType.ESCORT:
|
elif task == FlightType.ESCORT:
|
||||||
return self.generate_escort(flight)
|
return self.generate_escort(flight)
|
||||||
|
elif task == FlightType.RUNWAY_ATTACK:
|
||||||
|
return self.generate_runway_attack(flight)
|
||||||
elif task == FlightType.SEAD:
|
elif task == FlightType.SEAD:
|
||||||
return self.generate_sead(flight, custom_targets)
|
return self.generate_sead(flight, custom_targets)
|
||||||
elif task == FlightType.STRIKE:
|
elif task == FlightType.STRIKE:
|
||||||
@ -713,7 +716,9 @@ class FlightPlanBuilder:
|
|||||||
|
|
||||||
targets.append(StrikeTarget(building.category, building))
|
targets.append(StrikeTarget(building.category, building))
|
||||||
|
|
||||||
return self.strike_flightplan(flight, location, targets)
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_STRIKE,
|
||||||
|
targets)
|
||||||
|
|
||||||
def generate_bai(self, flight: Flight) -> StrikeFlightPlan:
|
def generate_bai(self, flight: Flight) -> StrikeFlightPlan:
|
||||||
"""Generates a BAI flight plan.
|
"""Generates a BAI flight plan.
|
||||||
@ -731,7 +736,8 @@ class FlightPlanBuilder:
|
|||||||
targets.append(
|
targets.append(
|
||||||
StrikeTarget(f"{group.name} at {location.name}", group))
|
StrikeTarget(f"{group.name} at {location.name}", group))
|
||||||
|
|
||||||
return self.strike_flightplan(flight, location, targets)
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_BAI, targets)
|
||||||
|
|
||||||
def generate_anti_ship(self, flight: Flight) -> StrikeFlightPlan:
|
def generate_anti_ship(self, flight: Flight) -> StrikeFlightPlan:
|
||||||
"""Generates an anti-ship flight plan.
|
"""Generates an anti-ship flight plan.
|
||||||
@ -756,7 +762,8 @@ class FlightPlanBuilder:
|
|||||||
targets.append(
|
targets.append(
|
||||||
StrikeTarget(f"{group.name} at {location.name}", group))
|
StrikeTarget(f"{group.name} at {location.name}", group))
|
||||||
|
|
||||||
return self.strike_flightplan(flight, location, targets)
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_BAI, targets)
|
||||||
|
|
||||||
def generate_barcap(self, flight: Flight) -> BarCapFlightPlan:
|
def generate_barcap(self, flight: Flight) -> BarCapFlightPlan:
|
||||||
"""Generate a BARCAP flight at a given location.
|
"""Generate a BARCAP flight at a given location.
|
||||||
@ -942,7 +949,25 @@ class FlightPlanBuilder:
|
|||||||
for target in custom_targets:
|
for target in custom_targets:
|
||||||
targets.append(StrikeTarget(location.name, target))
|
targets.append(StrikeTarget(location.name, target))
|
||||||
|
|
||||||
return self.strike_flightplan(flight, location, targets)
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_DEAD, targets)
|
||||||
|
|
||||||
|
def generate_runway_attack(self, flight: Flight) -> StrikeFlightPlan:
|
||||||
|
"""Generate a runway attack flight plan at a given location.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
flight: The flight to generate the flight plan for.
|
||||||
|
"""
|
||||||
|
location = self.package.target
|
||||||
|
|
||||||
|
if not isinstance(location, Airfield):
|
||||||
|
logging.exception(
|
||||||
|
f"Invalid Objective Location for runway bombing flight "
|
||||||
|
f"{flight=} at {location=}.")
|
||||||
|
raise InvalidObjectiveLocation(flight.flight_type, location)
|
||||||
|
|
||||||
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_RUNWAY_BOMBING)
|
||||||
|
|
||||||
def generate_sead(self, flight: Flight,
|
def generate_sead(self, flight: Flight,
|
||||||
custom_targets: Optional[List[Unit]]) -> StrikeFlightPlan:
|
custom_targets: Optional[List[Unit]]) -> StrikeFlightPlan:
|
||||||
@ -963,7 +988,8 @@ class FlightPlanBuilder:
|
|||||||
for target in custom_targets:
|
for target in custom_targets:
|
||||||
targets.append(StrikeTarget(location.name, target))
|
targets.append(StrikeTarget(location.name, target))
|
||||||
|
|
||||||
return self.strike_flightplan(flight, location, targets)
|
return self.strike_flightplan(flight, location,
|
||||||
|
FlightWaypointType.INGRESS_SEAD, targets)
|
||||||
|
|
||||||
def generate_escort(self, flight: Flight) -> StrikeFlightPlan:
|
def generate_escort(self, flight: Flight) -> StrikeFlightPlan:
|
||||||
assert self.package.waypoints is not None
|
assert self.package.waypoints is not None
|
||||||
@ -1012,7 +1038,8 @@ class FlightPlanBuilder:
|
|||||||
flight=flight,
|
flight=flight,
|
||||||
patrol_duration=self.doctrine.cas_duration,
|
patrol_duration=self.doctrine.cas_duration,
|
||||||
takeoff=builder.takeoff(flight.departure),
|
takeoff=builder.takeoff(flight.departure),
|
||||||
patrol_start=builder.ingress_cas(ingress, location),
|
patrol_start=builder.ingress(FlightWaypointType.INGRESS_CAS,
|
||||||
|
ingress, location),
|
||||||
target=builder.cas(center),
|
target=builder.cas(center),
|
||||||
patrol_end=builder.egress(egress, location),
|
patrol_end=builder.egress(egress, location),
|
||||||
land=builder.land(flight.arrival),
|
land=builder.land(flight.arrival),
|
||||||
@ -1101,23 +1128,11 @@ class FlightPlanBuilder:
|
|||||||
|
|
||||||
def strike_flightplan(
|
def strike_flightplan(
|
||||||
self, flight: Flight, location: MissionTarget,
|
self, flight: Flight, location: MissionTarget,
|
||||||
|
ingress_type: FlightWaypointType,
|
||||||
targets: Optional[List[StrikeTarget]] = None) -> StrikeFlightPlan:
|
targets: Optional[List[StrikeTarget]] = None) -> StrikeFlightPlan:
|
||||||
assert self.package.waypoints is not None
|
assert self.package.waypoints is not None
|
||||||
builder = WaypointBuilder(self.game.conditions, flight, self.doctrine,
|
builder = WaypointBuilder(self.game.conditions, flight, self.doctrine,
|
||||||
targets)
|
targets)
|
||||||
if flight.flight_type is FlightType.SEAD:
|
|
||||||
ingress = builder.ingress_sead(self.package.waypoints.ingress,
|
|
||||||
location)
|
|
||||||
|
|
||||||
elif flight.flight_type is FlightType.DEAD:
|
|
||||||
ingress = builder.ingress_dead(self.package.waypoints.ingress,
|
|
||||||
location)
|
|
||||||
elif flight.flight_type in {FlightType.ANTISHIP, FlightType.BAI}:
|
|
||||||
ingress = builder.ingress_bai(self.package.waypoints.ingress,
|
|
||||||
location)
|
|
||||||
else:
|
|
||||||
ingress = builder.ingress_strike(self.package.waypoints.ingress,
|
|
||||||
location)
|
|
||||||
|
|
||||||
target_waypoints: List[FlightWaypoint] = []
|
target_waypoints: List[FlightWaypoint] = []
|
||||||
if targets is not None:
|
if targets is not None:
|
||||||
@ -1134,7 +1149,8 @@ class FlightPlanBuilder:
|
|||||||
takeoff=builder.takeoff(flight.departure),
|
takeoff=builder.takeoff(flight.departure),
|
||||||
hold=builder.hold(self._hold_point(flight)),
|
hold=builder.hold(self._hold_point(flight)),
|
||||||
join=builder.join(self.package.waypoints.join),
|
join=builder.join(self.package.waypoints.join),
|
||||||
ingress=ingress,
|
ingress=builder.ingress(ingress_type,
|
||||||
|
self.package.waypoints.ingress, location),
|
||||||
targets=target_waypoints,
|
targets=target_waypoints,
|
||||||
egress=builder.egress(self.package.waypoints.egress, location),
|
egress=builder.egress(self.package.waypoints.egress, location),
|
||||||
split=builder.split(self.package.waypoints.split),
|
split=builder.split(self.package.waypoints.split),
|
||||||
|
|||||||
@ -173,38 +173,8 @@ class WaypointBuilder:
|
|||||||
waypoint.name = "SPLIT"
|
waypoint.name = "SPLIT"
|
||||||
return waypoint
|
return waypoint
|
||||||
|
|
||||||
def ingress_cas(self, position: Point,
|
def ingress(self, ingress_type: FlightWaypointType, position: Point,
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
objective: MissionTarget) -> FlightWaypoint:
|
||||||
return self._ingress(FlightWaypointType.INGRESS_CAS, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def ingress_escort(self, position: Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
return self._ingress(FlightWaypointType.INGRESS_ESCORT, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def ingress_bai(self, position: Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
return self._ingress(FlightWaypointType.INGRESS_BAI, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def ingress_dead(self, position:Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
return self._ingress(FlightWaypointType.INGRESS_DEAD, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def ingress_sead(self, position: Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
return self._ingress(FlightWaypointType.INGRESS_SEAD, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def ingress_strike(self, position: Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
return self._ingress(FlightWaypointType.INGRESS_STRIKE, position,
|
|
||||||
objective)
|
|
||||||
|
|
||||||
def _ingress(self, ingress_type: FlightWaypointType, position: Point,
|
|
||||||
objective: MissionTarget) -> FlightWaypoint:
|
|
||||||
waypoint = FlightWaypoint(
|
waypoint = FlightWaypoint(
|
||||||
ingress_type,
|
ingress_type,
|
||||||
position.x,
|
position.x,
|
||||||
@ -415,8 +385,8 @@ class WaypointBuilder:
|
|||||||
# description in gen.aircraft.JoinPointBuilder), so instead we give
|
# description in gen.aircraft.JoinPointBuilder), so instead we give
|
||||||
# the escort flights a flight plan including the ingress point, target
|
# the escort flights a flight plan including the ingress point, target
|
||||||
# area, and egress point.
|
# area, and egress point.
|
||||||
ingress = self._ingress(FlightWaypointType.INGRESS_ESCORT, ingress,
|
ingress = self.ingress(FlightWaypointType.INGRESS_ESCORT, ingress,
|
||||||
target)
|
target)
|
||||||
|
|
||||||
waypoint = FlightWaypoint(
|
waypoint = FlightWaypoint(
|
||||||
FlightWaypointType.TARGET_GROUP_LOC,
|
FlightWaypointType.TARGET_GROUP_LOC,
|
||||||
|
|||||||
@ -1,8 +1,17 @@
|
|||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtGui import QCloseEvent, QPixmap
|
from PySide2.QtGui import QCloseEvent, QPixmap
|
||||||
from PySide2.QtWidgets import QDialog, QGridLayout, QHBoxLayout, QLabel, QWidget
|
from PySide2.QtWidgets import (
|
||||||
|
QDialog,
|
||||||
|
QHBoxLayout,
|
||||||
|
QLabel,
|
||||||
|
QPushButton,
|
||||||
|
QVBoxLayout,
|
||||||
|
QWidget,
|
||||||
|
)
|
||||||
|
|
||||||
from game.theater import ControlPoint, ControlPointType
|
from game.theater import ControlPoint, ControlPointType
|
||||||
|
from gen.flights.flight import FlightType
|
||||||
|
from qt_ui.dialogs import Dialog
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.uiconstants import EVENT_ICONS
|
from qt_ui.uiconstants import EVENT_ICONS
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
@ -20,9 +29,6 @@ class QBaseMenu2(QDialog):
|
|||||||
self.game_model = game_model
|
self.game_model = game_model
|
||||||
self.objectName = "menuDialogue"
|
self.objectName = "menuDialogue"
|
||||||
|
|
||||||
# Widgets
|
|
||||||
self.qbase_menu_tab = QBaseMenuTabs(cp, self.game_model)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
game = self.game_model.game
|
game = self.game_model.game
|
||||||
self.airport = game.theater.terrain.airport_by_id(self.cp.id)
|
self.airport = game.theater.terrain.airport_by_id(self.cp.id)
|
||||||
@ -39,15 +45,11 @@ class QBaseMenu2(QDialog):
|
|||||||
self.setMinimumWidth(800)
|
self.setMinimumWidth(800)
|
||||||
self.setMaximumWidth(800)
|
self.setMaximumWidth(800)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.initUi()
|
|
||||||
|
|
||||||
def initUi(self):
|
|
||||||
self.setWindowTitle(self.cp.name)
|
self.setWindowTitle(self.cp.name)
|
||||||
self.topLayoutWidget = QWidget()
|
|
||||||
self.topLayout = QHBoxLayout()
|
|
||||||
|
|
||||||
self.topLayoutWidget = QWidget()
|
base_menu_header = QWidget()
|
||||||
self.topLayout = QHBoxLayout()
|
top_layout = QHBoxLayout()
|
||||||
|
|
||||||
header = QLabel(self)
|
header = QLabel(self)
|
||||||
header.setGeometry(0, 0, 655, 106)
|
header.setGeometry(0, 0, 655, 106)
|
||||||
@ -57,26 +59,42 @@ class QBaseMenu2(QDialog):
|
|||||||
title = QLabel("<b>" + self.cp.name + "</b>")
|
title = QLabel("<b>" + self.cp.name + "</b>")
|
||||||
title.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
title.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||||
title.setProperty("style", "base-title")
|
title.setProperty("style", "base-title")
|
||||||
unitsPower = QLabel("{} / {} / Runway : {}".format(self.cp.base.total_aircraft, self.cp.base.total_armor,
|
aircraft = self.cp.base.total_aircraft
|
||||||
"Available" if self.cp.has_runway() else "Unavailable"))
|
armor = self.cp.base.total_armor
|
||||||
self.topLayout.addWidget(title)
|
runway_status = "operational" if self.cp.has_runway() else "inoperative"
|
||||||
self.topLayout.addWidget(unitsPower)
|
intel_summary = QLabel("\n".join([
|
||||||
self.topLayout.setAlignment(Qt.AlignTop)
|
f"{aircraft} aircraft",
|
||||||
self.topLayoutWidget.setProperty("style", "baseMenuHeader")
|
f"{armor} ground units",
|
||||||
self.topLayoutWidget.setLayout(self.topLayout)
|
f"Runway {runway_status}"
|
||||||
|
]))
|
||||||
|
top_layout.addWidget(title)
|
||||||
|
top_layout.addWidget(intel_summary)
|
||||||
|
top_layout.setAlignment(Qt.AlignTop)
|
||||||
|
base_menu_header.setProperty("style", "baseMenuHeader")
|
||||||
|
base_menu_header.setLayout(top_layout)
|
||||||
|
|
||||||
self.mainLayout = QGridLayout()
|
main_layout = QVBoxLayout()
|
||||||
self.mainLayout.addWidget(header, 0, 0)
|
main_layout.addWidget(header)
|
||||||
self.mainLayout.addWidget(self.topLayoutWidget, 1, 0)
|
main_layout.addWidget(base_menu_header)
|
||||||
self.mainLayout.addWidget(self.qbase_menu_tab, 2, 0)
|
main_layout.addWidget(QBaseMenuTabs(cp, self.game_model))
|
||||||
totalBudget = QLabel(
|
bottom_row = QHBoxLayout()
|
||||||
|
main_layout.addLayout(bottom_row)
|
||||||
|
|
||||||
|
if FlightType.RUNWAY_ATTACK in self.cp.mission_types(for_player=True):
|
||||||
|
runway_attack_button = QPushButton("Attack airfield")
|
||||||
|
bottom_row.addWidget(runway_attack_button)
|
||||||
|
|
||||||
|
runway_attack_button.setProperty("style", "btn-danger")
|
||||||
|
runway_attack_button.clicked.connect(self.new_package)
|
||||||
|
|
||||||
|
budget_display = QLabel(
|
||||||
QRecruitBehaviour.BUDGET_FORMAT.format(self.game_model.game.budget)
|
QRecruitBehaviour.BUDGET_FORMAT.format(self.game_model.game.budget)
|
||||||
)
|
)
|
||||||
totalBudget.setObjectName("budgetField")
|
budget_display.setObjectName("budgetField")
|
||||||
totalBudget.setAlignment(Qt.AlignRight | Qt.AlignBottom)
|
budget_display.setAlignment(Qt.AlignRight | Qt.AlignBottom)
|
||||||
totalBudget.setProperty("style", "budget-label")
|
budget_display.setProperty("style", "budget-label")
|
||||||
self.mainLayout.addWidget(totalBudget)
|
bottom_row.addWidget(budget_display)
|
||||||
self.setLayout(self.mainLayout)
|
self.setLayout(main_layout)
|
||||||
|
|
||||||
def closeEvent(self, closeEvent:QCloseEvent):
|
def closeEvent(self, closeEvent:QCloseEvent):
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
GameUpdateSignal.get_instance().updateGame(self.game_model.game)
|
||||||
@ -88,3 +106,6 @@ class QBaseMenu2(QDialog):
|
|||||||
return "./resources/ui/lha.png"
|
return "./resources/ui/lha.png"
|
||||||
else:
|
else:
|
||||||
return "./resources/ui/airbase.png"
|
return "./resources/ui/airbase.png"
|
||||||
|
|
||||||
|
def new_package(self) -> None:
|
||||||
|
Dialog.open_new_package_dialog(self.cp, parent=self.window())
|
||||||
|
|||||||
@ -265,6 +265,50 @@ local unitPayloads = {
|
|||||||
[1] = 11,
|
[1] = 11,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[7] = {
|
||||||
|
["name"] = "RUNWAY_ATTACK",
|
||||||
|
["pylons"] = {
|
||||||
|
[1] = {
|
||||||
|
["CLSID"] = "{5CE2FF2A-645A-4197-B48D-8720AC69394F}",
|
||||||
|
["num"] = 9,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
["CLSID"] = "{5CE2FF2A-645A-4197-B48D-8720AC69394F}",
|
||||||
|
["num"] = 1,
|
||||||
|
},
|
||||||
|
[3] = {
|
||||||
|
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||||
|
["num"] = 5,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
|
||||||
|
["num"] = 6,
|
||||||
|
},
|
||||||
|
[5] = {
|
||||||
|
["CLSID"] = "{40EF17B7-F508-45de-8566-6FFECC0C1AB8}",
|
||||||
|
["num"] = 4,
|
||||||
|
},
|
||||||
|
[6] = {
|
||||||
|
["CLSID"] = "{FPU_8A_FUEL_TANK}",
|
||||||
|
["num"] = 7,
|
||||||
|
},
|
||||||
|
[7] = {
|
||||||
|
["CLSID"] = "{FPU_8A_FUEL_TANK}",
|
||||||
|
["num"] = 3,
|
||||||
|
},
|
||||||
|
[8] = {
|
||||||
|
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||||
|
["num"] = 2,
|
||||||
|
},
|
||||||
|
[9] = {
|
||||||
|
["CLSID"] = "{BRU33_2X_MK-82}",
|
||||||
|
["num"] = 8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["tasks"] = {
|
||||||
|
[1] = 34,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
["tasks"] = {
|
["tasks"] = {
|
||||||
},
|
},
|
||||||
|
|||||||
@ -189,6 +189,54 @@ local unitPayloads = {
|
|||||||
[1] = 11,
|
[1] = 11,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[6] = {
|
||||||
|
["name"] = "RUNWAY_ATTACK",
|
||||||
|
["pylons"] = {
|
||||||
|
[1] = {
|
||||||
|
["CLSID"] = "{Eclair}",
|
||||||
|
["num"] = 10,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
["CLSID"] = "{MMagicII}",
|
||||||
|
["num"] = 9,
|
||||||
|
},
|
||||||
|
[3] = {
|
||||||
|
["CLSID"] = "{MMagicII}",
|
||||||
|
["num"] = 1,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 8,
|
||||||
|
},
|
||||||
|
[5] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 2,
|
||||||
|
},
|
||||||
|
[6] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 7,
|
||||||
|
},
|
||||||
|
[7] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 3,
|
||||||
|
},
|
||||||
|
[8] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 4,
|
||||||
|
},
|
||||||
|
[9] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 6,
|
||||||
|
},
|
||||||
|
[10] = {
|
||||||
|
["CLSID"] = "{BLG66_BELOUGA_AC}",
|
||||||
|
["num"] = 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["tasks"] = {
|
||||||
|
[1] = 34,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
["tasks"] = {
|
["tasks"] = {
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user