mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import inspect
|
|
from dataclasses import dataclass
|
|
from typing import Dict, Iterator, Set, Tuple, Type, Union, cast
|
|
|
|
from dcs.unitgroup import FlyingGroup
|
|
from dcs.unittype import FlyingType
|
|
|
|
|
|
PydcsWeapon = Dict[str, Union[int, str]]
|
|
PydcsWeaponAssignment = Tuple[int, PydcsWeapon]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Weapon:
|
|
"""Wraps a pydcs weapon dict in a hashable type."""
|
|
|
|
cls_id: str
|
|
name: str
|
|
weight: int
|
|
|
|
@property
|
|
def as_pydcs(self) -> PydcsWeapon:
|
|
return {
|
|
"clsid": self.cls_id,
|
|
"name": self.name,
|
|
"weight": self.weight,
|
|
}
|
|
|
|
@classmethod
|
|
def from_pydcs(cls, weapon_data: PydcsWeapon) -> Weapon:
|
|
return cls(
|
|
cast(str, weapon_data["clsid"]),
|
|
cast(str, weapon_data["name"]),
|
|
cast(int, weapon_data["weight"])
|
|
)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Pylon:
|
|
number: int
|
|
allowed: Set[Weapon]
|
|
|
|
def can_equip(self, weapon: Weapon) -> bool:
|
|
return weapon in self.allowed
|
|
|
|
def equip(self, group: FlyingGroup, weapon: Weapon) -> None:
|
|
if not self.can_equip(weapon):
|
|
raise ValueError(f"Pylon {self.number} cannot equip {weapon.name}")
|
|
group.load_pylon(self.make_pydcs_assignment(weapon), self.number)
|
|
|
|
def make_pydcs_assignment(self, weapon: Weapon) -> PydcsWeaponAssignment:
|
|
return self.number, weapon.as_pydcs
|
|
|
|
@classmethod
|
|
def for_aircraft(cls, aircraft: Type[FlyingType], number: int) -> Pylon:
|
|
# In pydcs these are all arbitrary inner classes of the aircraft type.
|
|
# The only way to identify them is by their name.
|
|
pylons = [v for v in aircraft.__dict__.values() if
|
|
inspect.isclass(v) and v.__name__.startswith("Pylon")]
|
|
|
|
# And that Pylon class has members with irrelevant names that have
|
|
# values of (pylon number, allowed weapon).
|
|
allowed = set()
|
|
for pylon in pylons:
|
|
for key, value in pylon.__dict__.items():
|
|
if key.startswith("__"):
|
|
continue
|
|
pylon_number, weapon = value
|
|
if pylon_number != number:
|
|
continue
|
|
allowed.add(Weapon.from_pydcs(weapon))
|
|
|
|
return cls(number, allowed)
|
|
|
|
@classmethod
|
|
def iter_pylons(cls, aircraft: Type[FlyingType]) -> Iterator[Pylon]:
|
|
for pylon in sorted(list(aircraft.pylons)):
|
|
yield cls.for_aircraft(aircraft, pylon)
|