mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Track pilot deaths.
https://github.com/dcs-liberation/dcs_liberation/issues/276
This commit is contained in:
parent
8b8e018521
commit
cd6de191d1
@ -30,6 +30,7 @@ from game.unitmap import (
|
|||||||
FrontLineUnit,
|
FrontLineUnit,
|
||||||
GroundObjectUnit,
|
GroundObjectUnit,
|
||||||
UnitMap,
|
UnitMap,
|
||||||
|
FlyingUnit,
|
||||||
)
|
)
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight
|
||||||
|
|
||||||
@ -41,24 +42,24 @@ DEBRIEFING_LOG_EXTENSION = "log"
|
|||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class AirLosses:
|
class AirLosses:
|
||||||
player: List[Flight]
|
player: List[FlyingUnit]
|
||||||
enemy: List[Flight]
|
enemy: List[FlyingUnit]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def losses(self) -> Iterator[Flight]:
|
def losses(self) -> Iterator[FlyingUnit]:
|
||||||
return itertools.chain(self.player, self.enemy)
|
return itertools.chain(self.player, self.enemy)
|
||||||
|
|
||||||
def by_type(self, player: bool) -> Dict[Type[FlyingType], int]:
|
def by_type(self, player: bool) -> Dict[Type[FlyingType], int]:
|
||||||
losses_by_type: Dict[Type[FlyingType], int] = defaultdict(int)
|
losses_by_type: Dict[Type[FlyingType], int] = defaultdict(int)
|
||||||
losses = self.player if player else self.enemy
|
losses = self.player if player else self.enemy
|
||||||
for loss in losses:
|
for loss in losses:
|
||||||
losses_by_type[loss.unit_type] += 1
|
losses_by_type[loss.flight.unit_type] += 1
|
||||||
return losses_by_type
|
return losses_by_type
|
||||||
|
|
||||||
def surviving_flight_members(self, flight: Flight) -> int:
|
def surviving_flight_members(self, flight: Flight) -> int:
|
||||||
losses = 0
|
losses = 0
|
||||||
for loss in self.losses:
|
for loss in self.losses:
|
||||||
if loss == flight:
|
if loss.flight == flight:
|
||||||
losses += 1
|
losses += 1
|
||||||
return flight.count - losses
|
return flight.count - losses
|
||||||
|
|
||||||
@ -239,14 +240,14 @@ class Debriefing:
|
|||||||
player_losses = []
|
player_losses = []
|
||||||
enemy_losses = []
|
enemy_losses = []
|
||||||
for unit_name in self.state_data.killed_aircraft:
|
for unit_name in self.state_data.killed_aircraft:
|
||||||
flight = self.unit_map.flight(unit_name)
|
aircraft = self.unit_map.flight(unit_name)
|
||||||
if flight is None:
|
if aircraft is None:
|
||||||
logging.error(f"Could not find Flight matching {unit_name}")
|
logging.error(f"Could not find Flight matching {unit_name}")
|
||||||
continue
|
continue
|
||||||
if flight.departure.captured:
|
if aircraft.flight.departure.captured:
|
||||||
player_losses.append(flight)
|
player_losses.append(aircraft)
|
||||||
else:
|
else:
|
||||||
enemy_losses.append(flight)
|
enemy_losses.append(aircraft)
|
||||||
return AirLosses(player_losses, enemy_losses)
|
return AirLosses(player_losses, enemy_losses)
|
||||||
|
|
||||||
def dead_ground_units(self) -> GroundLosses:
|
def dead_ground_units(self) -> GroundLosses:
|
||||||
|
|||||||
@ -123,8 +123,9 @@ class Event:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def commit_air_losses(debriefing: Debriefing) -> None:
|
def commit_air_losses(debriefing: Debriefing) -> None:
|
||||||
for loss in debriefing.air_losses.losses:
|
for loss in debriefing.air_losses.losses:
|
||||||
aircraft = loss.unit_type
|
loss.pilot.alive = False
|
||||||
cp = loss.departure
|
aircraft = loss.flight.unit_type
|
||||||
|
cp = loss.flight.departure
|
||||||
available = cp.base.total_units_of_type(aircraft)
|
available = cp.base.total_units_of_type(aircraft)
|
||||||
if available <= 0:
|
if available <= 0:
|
||||||
logging.error(
|
logging.error(
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class Squadron:
|
|||||||
player: bool
|
player: bool
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
self.available_pilots = list(self.pilots)
|
self.available_pilots = list(self.active_pilots)
|
||||||
|
|
||||||
def claim_available_pilot(self) -> Optional[Pilot]:
|
def claim_available_pilot(self) -> Optional[Pilot]:
|
||||||
if not self.available_pilots:
|
if not self.available_pilots:
|
||||||
@ -78,7 +78,7 @@ class Squadron:
|
|||||||
self.available_pilots.extend(new_pilots)
|
self.available_pilots.extend(new_pilots)
|
||||||
|
|
||||||
def return_all_pilots(self) -> None:
|
def return_all_pilots(self) -> None:
|
||||||
self.available_pilots = list(self.pilots)
|
self.available_pilots = list(self.active_pilots)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def faker(self) -> Faker:
|
def faker(self) -> Faker:
|
||||||
|
|||||||
@ -7,12 +7,19 @@ from dcs.unitgroup import FlyingGroup, Group, VehicleGroup
|
|||||||
from dcs.unittype import VehicleType
|
from dcs.unittype import VehicleType
|
||||||
|
|
||||||
from game import db
|
from game import db
|
||||||
|
from game.squadrons import Pilot
|
||||||
from game.theater import Airfield, ControlPoint, TheaterGroundObject
|
from game.theater import Airfield, ControlPoint, TheaterGroundObject
|
||||||
from game.theater.theatergroundobject import BuildingGroundObject, SceneryGroundObject
|
from game.theater.theatergroundobject import BuildingGroundObject, SceneryGroundObject
|
||||||
from game.transfers import CargoShip, Convoy, TransferOrder
|
from game.transfers import CargoShip, Convoy, TransferOrder
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class FlyingUnit:
|
||||||
|
flight: Flight
|
||||||
|
pilot: Pilot
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class FrontLineUnit:
|
class FrontLineUnit:
|
||||||
unit_type: Type[VehicleType]
|
unit_type: Type[VehicleType]
|
||||||
@ -45,7 +52,7 @@ class Building:
|
|||||||
|
|
||||||
class UnitMap:
|
class UnitMap:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.aircraft: Dict[str, Flight] = {}
|
self.aircraft: Dict[str, FlyingUnit] = {}
|
||||||
self.airfields: Dict[str, Airfield] = {}
|
self.airfields: Dict[str, Airfield] = {}
|
||||||
self.front_line_units: Dict[str, FrontLineUnit] = {}
|
self.front_line_units: Dict[str, FrontLineUnit] = {}
|
||||||
self.ground_object_units: Dict[str, GroundObjectUnit] = {}
|
self.ground_object_units: Dict[str, GroundObjectUnit] = {}
|
||||||
@ -55,17 +62,19 @@ class UnitMap:
|
|||||||
self.airlifts: Dict[str, AirliftUnit] = {}
|
self.airlifts: Dict[str, AirliftUnit] = {}
|
||||||
|
|
||||||
def add_aircraft(self, group: FlyingGroup, flight: Flight) -> None:
|
def add_aircraft(self, group: FlyingGroup, flight: Flight) -> None:
|
||||||
for unit in group.units:
|
for pilot, unit in zip(flight.pilots, group.units):
|
||||||
# The actual name is a String (the pydcs translatable string), which
|
# The actual name is a String (the pydcs translatable string), which
|
||||||
# doesn't define __eq__.
|
# doesn't define __eq__.
|
||||||
name = str(unit.name)
|
name = str(unit.name)
|
||||||
if name in self.aircraft:
|
if name in self.aircraft:
|
||||||
raise RuntimeError(f"Duplicate unit name: {name}")
|
raise RuntimeError(f"Duplicate unit name: {name}")
|
||||||
self.aircraft[name] = flight
|
if pilot is None:
|
||||||
|
raise ValueError(f"{name} has no pilot assigned")
|
||||||
|
self.aircraft[name] = FlyingUnit(flight, pilot)
|
||||||
if flight.cargo is not None:
|
if flight.cargo is not None:
|
||||||
self.add_airlift_units(group, flight.cargo)
|
self.add_airlift_units(group, flight.cargo)
|
||||||
|
|
||||||
def flight(self, unit_name: str) -> Optional[Flight]:
|
def flight(self, unit_name: str) -> Optional[FlyingUnit]:
|
||||||
return self.aircraft.get(unit_name, None)
|
return self.aircraft.get(unit_name, None)
|
||||||
|
|
||||||
def add_airfield(self, airfield: Airfield) -> None:
|
def add_airfield(self, airfield: Airfield) -> None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user