Merge branch 'develop' into helipads

# Conflicts:
#	game/game.py
#	resources/campaigns/golan_heights_lite.miz
This commit is contained in:
Khopa
2021-06-26 18:00:36 +02:00
182 changed files with 1613 additions and 2146 deletions

View File

@@ -29,7 +29,7 @@ from game.radio.channels import (
ViggenRadioChannelAllocator,
NoOpChannelAllocator,
)
from game.utils import Speed, kph
from game.utils import Distance, Speed, feet, kph, knots
if TYPE_CHECKING:
from gen.aircraft import FlightData
@@ -90,11 +90,34 @@ class RadioConfig:
}[config.get("namer", "default")]
@dataclass(frozen=True)
class PatrolConfig:
altitude: Optional[Distance]
speed: Optional[Speed]
@classmethod
def from_data(cls, data: dict[str, Any]) -> PatrolConfig:
altitude = data.get("altitude", None)
speed = data.get("altitude", None)
return PatrolConfig(
feet(altitude) if altitude is not None else None,
knots(speed) if speed is not None else None,
)
@dataclass(frozen=True)
class AircraftType(UnitType[FlyingType]):
carrier_capable: bool
lha_capable: bool
always_keeps_gun: bool
# If true, the aircraft does not use the guns as the last resort weapons, but as a main weapon.
# It'll RTB when it doesn't have gun ammo left.
gunfighter: bool
max_group_size: int
patrol_altitude: Optional[Distance]
patrol_speed: Optional[Speed]
intra_flight_radio: Optional[Radio]
channel_allocator: Optional[RadioChannelAllocator]
channel_namer: Type[ChannelNamer]
@@ -146,6 +169,12 @@ class AircraftType(UnitType[FlyingType]):
def channel_name(self, radio_id: int, channel_id: int) -> str:
return self.channel_namer.channel_name(radio_id, channel_id)
def __setstate__(self, state: dict[str, Any]) -> None:
# Update any existing models with new data on load.
updated = AircraftType.named(state["name"])
state.update(updated.__dict__)
self.__dict__.update(state)
@classmethod
def register(cls, aircraft_type: AircraftType) -> None:
cls._by_name[aircraft_type.name] = aircraft_type
@@ -159,6 +188,8 @@ class AircraftType(UnitType[FlyingType]):
@classmethod
def for_dcs_type(cls, dcs_unit_type: Type[FlyingType]) -> Iterator[AircraftType]:
if not cls._loaded:
cls._load_all()
yield from cls._by_unit_type[dcs_unit_type]
@staticmethod
@@ -189,6 +220,7 @@ class AircraftType(UnitType[FlyingType]):
raise KeyError(f"Missing required price field: {data_path}") from ex
radio_config = RadioConfig.from_data(data.get("radios", {}))
patrol_config = PatrolConfig.from_data(data.get("patrol", {}))
try:
introduction = data["introduced"]
@@ -210,6 +242,10 @@ class AircraftType(UnitType[FlyingType]):
carrier_capable=data.get("carrier_capable", False),
lha_capable=data.get("lha_capable", False),
always_keeps_gun=data.get("always_keeps_gun", False),
gunfighter=data.get("gunfighter", False),
max_group_size=data.get("max_group_size", aircraft.group_size_max),
patrol_altitude=patrol_config.altitude,
patrol_speed=patrol_config.speed,
intra_flight_radio=radio_config.intra_flight,
channel_allocator=radio_config.channel_allocator,
channel_namer=radio_config.channel_namer,

View File

@@ -45,6 +45,8 @@ class GroundUnitType(UnitType[VehicleType]):
@classmethod
def for_dcs_type(cls, dcs_unit_type: Type[VehicleType]) -> Iterator[GroundUnitType]:
if not cls._loaded:
cls._load_all()
yield from cls._by_unit_type[dcs_unit_type]
@staticmethod