mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Track airlift cargo kills.
https://github.com/Khopa/dcs_liberation/issues/825
This commit is contained in:
parent
e474748f4d
commit
29b70b3247
@ -22,7 +22,14 @@ from dcs.unittype import FlyingType, UnitType
|
||||
|
||||
from game import db
|
||||
from game.theater import Airfield, ControlPoint
|
||||
from game.unitmap import Building, ConvoyUnit, FrontLineUnit, GroundObjectUnit, UnitMap
|
||||
from game.unitmap import (
|
||||
AirliftUnit,
|
||||
Building,
|
||||
ConvoyUnit,
|
||||
FrontLineUnit,
|
||||
GroundObjectUnit,
|
||||
UnitMap,
|
||||
)
|
||||
from gen.flights.flight import Flight
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -63,6 +70,9 @@ class GroundLosses:
|
||||
player_convoy: List[ConvoyUnit] = field(default_factory=list)
|
||||
enemy_convoy: List[ConvoyUnit] = field(default_factory=list)
|
||||
|
||||
player_airlifts: List[AirliftUnit] = field(default_factory=list)
|
||||
enemy_airlifts: List[AirliftUnit] = field(default_factory=list)
|
||||
|
||||
player_ground_objects: List[GroundObjectUnit] = field(default_factory=list)
|
||||
enemy_ground_objects: List[GroundObjectUnit] = field(default_factory=list)
|
||||
|
||||
@ -128,6 +138,11 @@ class Debriefing:
|
||||
yield from self.ground_losses.player_convoy
|
||||
yield from self.ground_losses.enemy_convoy
|
||||
|
||||
@property
|
||||
def airlift_losses(self) -> Iterator[AirliftUnit]:
|
||||
yield from self.ground_losses.player_airlifts
|
||||
yield from self.ground_losses.enemy_airlifts
|
||||
|
||||
@property
|
||||
def ground_object_losses(self) -> Iterator[GroundObjectUnit]:
|
||||
yield from self.ground_losses.player_ground_objects
|
||||
@ -166,6 +181,16 @@ class Debriefing:
|
||||
losses_by_type[loss.unit_type] += 1
|
||||
return losses_by_type
|
||||
|
||||
def airlift_losses_by_type(self, player: bool) -> Dict[Type[UnitType], int]:
|
||||
losses_by_type: Dict[Type[UnitType], int] = defaultdict(int)
|
||||
if player:
|
||||
losses = self.ground_losses.player_airlifts
|
||||
else:
|
||||
losses = self.ground_losses.enemy_airlifts
|
||||
for loss in losses:
|
||||
losses_by_type[loss.unit_type] += 1
|
||||
return losses_by_type
|
||||
|
||||
def building_losses_by_type(self, player: bool) -> Dict[str, int]:
|
||||
losses_by_type: Dict[str, int] = defaultdict(int)
|
||||
if player:
|
||||
@ -250,6 +275,15 @@ class Debriefing:
|
||||
"have no effect. This may be normal behavior."
|
||||
)
|
||||
|
||||
for unit_name in self.state_data.killed_aircraft:
|
||||
airlift_unit = self.unit_map.airlift_unit(unit_name)
|
||||
if airlift_unit is not None:
|
||||
if airlift_unit.transfer.player:
|
||||
losses.player_airlifts.append(airlift_unit)
|
||||
else:
|
||||
losses.enemy_airlifts.append(airlift_unit)
|
||||
continue
|
||||
|
||||
return losses
|
||||
|
||||
@property
|
||||
|
||||
@ -172,6 +172,23 @@ class Event:
|
||||
logging.info(f"{unit_type} destroyed in {convoy_name}")
|
||||
convoy.kill_unit(unit_type)
|
||||
|
||||
@staticmethod
|
||||
def commit_airlift_losses(debriefing: Debriefing) -> None:
|
||||
for loss in debriefing.airlift_losses:
|
||||
unit_type = loss.unit_type
|
||||
transfer = loss.transfer
|
||||
available = loss.transfer.units.get(unit_type, 0)
|
||||
airlift_name = f"airlift from {transfer.origin} to {transfer.destination}"
|
||||
if available <= 0:
|
||||
logging.error(
|
||||
f"Found killed {unit_type} in {airlift_name} but that airlift has "
|
||||
"none available."
|
||||
)
|
||||
continue
|
||||
|
||||
logging.info(f"{unit_type} destroyed in {airlift_name}")
|
||||
transfer.kill_unit(unit_type)
|
||||
|
||||
@staticmethod
|
||||
def commit_ground_object_losses(debriefing: Debriefing) -> None:
|
||||
for loss in debriefing.ground_object_losses:
|
||||
@ -205,6 +222,7 @@ class Event:
|
||||
self.commit_air_losses(debriefing)
|
||||
self.commit_front_line_losses(debriefing)
|
||||
self.commit_convoy_losses(debriefing)
|
||||
self.commit_airlift_losses(debriefing)
|
||||
self.commit_ground_object_losses(debriefing)
|
||||
self.commit_building_losses(debriefing)
|
||||
self.commit_damaged_runways(debriefing)
|
||||
|
||||
@ -78,6 +78,17 @@ class AirliftOrder(TransferOrder):
|
||||
def description(self) -> str:
|
||||
return "Airlift"
|
||||
|
||||
def iter_units(self) -> Iterator[Type[VehicleType]]:
|
||||
for unit_type, count in self.units.items():
|
||||
for _ in range(count):
|
||||
yield unit_type
|
||||
|
||||
def kill_unit(self, unit_type: Type[VehicleType]) -> None:
|
||||
if unit_type in self.units:
|
||||
self.units[unit_type] -= 1
|
||||
return
|
||||
raise KeyError
|
||||
|
||||
|
||||
class Convoy(MissionTarget):
|
||||
def __init__(self, origin: ControlPoint, destination: ControlPoint) -> None:
|
||||
|
||||
@ -9,7 +9,7 @@ from dcs.unittype import VehicleType
|
||||
from game import db
|
||||
from game.theater import Airfield, ControlPoint, TheaterGroundObject
|
||||
from game.theater.theatergroundobject import BuildingGroundObject
|
||||
from game.transfers import Convoy, RoadTransferOrder
|
||||
from game.transfers import AirliftOrder, Convoy
|
||||
from gen.flights.flight import Flight
|
||||
|
||||
|
||||
@ -32,6 +32,12 @@ class ConvoyUnit:
|
||||
convoy: Convoy
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AirliftUnit:
|
||||
unit_type: Type[VehicleType]
|
||||
transfer: AirliftOrder
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Building:
|
||||
ground_object: BuildingGroundObject
|
||||
@ -45,6 +51,7 @@ class UnitMap:
|
||||
self.ground_object_units: Dict[str, GroundObjectUnit] = {}
|
||||
self.buildings: Dict[str, Building] = {}
|
||||
self.convoys: Dict[str, ConvoyUnit] = {}
|
||||
self.airlifts: Dict[str, AirliftUnit] = {}
|
||||
|
||||
def add_aircraft(self, group: FlyingGroup, flight: Flight) -> None:
|
||||
for unit in group.units:
|
||||
@ -54,6 +61,8 @@ class UnitMap:
|
||||
if name in self.aircraft:
|
||||
raise RuntimeError(f"Duplicate unit name: {name}")
|
||||
self.aircraft[name] = flight
|
||||
if flight.cargo is not None:
|
||||
self.add_airlift_units(group, flight.cargo)
|
||||
|
||||
def flight(self, unit_name: str) -> Optional[Flight]:
|
||||
return self.aircraft.get(unit_name, None)
|
||||
@ -140,6 +149,21 @@ class UnitMap:
|
||||
def convoy_unit(self, name: str) -> Optional[ConvoyUnit]:
|
||||
return self.convoys.get(name, None)
|
||||
|
||||
def add_airlift_units(self, group: FlyingGroup, airlift: AirliftOrder) -> None:
|
||||
for transport, cargo_type in zip(group.units, airlift.iter_units()):
|
||||
# The actual name is a String (the pydcs translatable string), which
|
||||
# doesn't define __eq__.
|
||||
name = str(transport.name)
|
||||
if name in self.airlifts:
|
||||
raise RuntimeError(f"Duplicate airlift unit: {name}")
|
||||
unit_type = db.unit_type_from_name(transport.type)
|
||||
if unit_type is None:
|
||||
raise RuntimeError(f"Unknown unit type: {transport.type}")
|
||||
self.airlifts[name] = AirliftUnit(cargo_type, airlift)
|
||||
|
||||
def airlift_unit(self, name: str) -> Optional[AirliftUnit]:
|
||||
return self.airlifts.get(name, None)
|
||||
|
||||
def add_building(self, ground_object: BuildingGroundObject, group: Group) -> None:
|
||||
# The actual name is a String (the pydcs translatable string), which
|
||||
# doesn't define __eq__.
|
||||
|
||||
@ -83,6 +83,17 @@ class QDebriefingWindow(QDialog):
|
||||
except AttributeError:
|
||||
logging.exception(f"Issue adding {unit_type} to debriefing information")
|
||||
|
||||
airlift_losses = self.debriefing.airlift_losses_by_type(player=True)
|
||||
for unit_type, count in airlift_losses.items():
|
||||
try:
|
||||
lostUnitsLayout.addWidget(
|
||||
QLabel(f"{db.unit_type_name(unit_type)} from airlift"), row, 0
|
||||
)
|
||||
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
logging.exception(f"Issue adding {unit_type} to debriefing information")
|
||||
|
||||
building_losses = self.debriefing.building_losses_by_type(player=True)
|
||||
for building, count in building_losses.items():
|
||||
try:
|
||||
@ -135,6 +146,17 @@ class QDebriefingWindow(QDialog):
|
||||
except AttributeError:
|
||||
logging.exception(f"Issue adding {unit_type} to debriefing information")
|
||||
|
||||
airlift_losses = self.debriefing.airlift_losses_by_type(player=False)
|
||||
for unit_type, count in airlift_losses.items():
|
||||
try:
|
||||
lostUnitsLayout.addWidget(
|
||||
QLabel(f"{db.unit_type_name(unit_type)} from airlift"), row, 0
|
||||
)
|
||||
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
logging.exception(f"Issue adding {unit_type} to debriefing information")
|
||||
|
||||
building_losses = self.debriefing.building_losses_by_type(player=False)
|
||||
for building, count in building_losses.items():
|
||||
try:
|
||||
|
||||
@ -151,16 +151,19 @@ class QWaitingForMissionResultWindow(QDialog):
|
||||
updateLayout.addWidget(QLabel("<b>Convoy units destroyed</b>"), 2, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(list(debriefing.convoy_losses)))), 2, 1)
|
||||
|
||||
updateLayout.addWidget(QLabel("<b>Other ground units destroyed</b>"), 3, 0)
|
||||
updateLayout.addWidget(QLabel("<b>Airlift cargo destroyed</b>"), 3, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(list(debriefing.airlift_losses)))), 3, 1)
|
||||
|
||||
updateLayout.addWidget(QLabel("<b>Other ground units destroyed</b>"), 4, 0)
|
||||
updateLayout.addWidget(
|
||||
QLabel(str(len(list(debriefing.ground_object_losses)))), 3, 1
|
||||
QLabel(str(len(list(debriefing.ground_object_losses)))), 4, 1
|
||||
)
|
||||
|
||||
updateLayout.addWidget(QLabel("<b>Buildings destroyed</b>"), 4, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(list(debriefing.building_losses)))), 4, 1)
|
||||
updateLayout.addWidget(QLabel("<b>Buildings destroyed</b>"), 5, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(list(debriefing.building_losses)))), 5, 1)
|
||||
|
||||
updateLayout.addWidget(QLabel("<b>Base Capture Events</b>"), 5, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 5, 1)
|
||||
updateLayout.addWidget(QLabel("<b>Base Capture Events</b>"), 6, 0)
|
||||
updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 6, 1)
|
||||
|
||||
# Clear previous content of the window
|
||||
for i in reversed(range(self.gridLayout.count())):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user