Eclipse/Druss99 31c80dfd02 refactor of previous commits
refactor to enum

typing and many other fixes

fix tests

attempt to fix some typescript

more typescript fixes

more typescript test fixes

revert all API changes

update to pydcs

mypy fixes

Use properties to check if player is blue/red/neutral

update requirements.txt

black -_-

bump pydcs and fix mypy

add opponent property

bump pydcs
2025-10-19 19:34:38 +02:00

113 lines
3.3 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from datetime import timedelta
from typing import Optional, TYPE_CHECKING
from dcs.flyingunit import FlyingUnit
from game.callsigns import create_group_callsign_from_unit
from game.squadrons import Squadron
if TYPE_CHECKING:
from game.ato import FlightType, FlightWaypoint, Package
from game.dcs.aircrafttype import AircraftType
from game.radio.radios import RadioFrequency
from game.runways import RunwayData
from game.theater.player import Player
@dataclass(frozen=True)
class ChannelAssignment:
radio_id: int
channel: int
@dataclass
class FlightData:
"""Details of a planned flight."""
#: The package that the flight belongs to.
package: Package
flight_type: FlightType
aircraft_type: AircraftType
squadron: Squadron
#: All units in the flight.
units: list[FlyingUnit]
#: Total number of aircraft in the flight.
size: int
#: True if this flight belongs to the player's coalition.
friendly: Player
#: Number of seconds after mission start the flight is set to depart.
departure_delay: timedelta
#: Arrival airport.
arrival: RunwayData
#: Departure airport.
departure: RunwayData
#: Diver airport.
divert: Optional[RunwayData]
#: Waypoints of the flight plan.
waypoints: list[FlightWaypoint]
#: Radio frequency for intra-flight communications.
intra_flight_channel: RadioFrequency
#: Bingo fuel value in lbs.
bingo_fuel: Optional[int]
joker_fuel: Optional[int]
laser_codes: list[Optional[int]]
custom_name: Optional[str]
callsign: str = field(init=False)
#: Map of radio frequencies to their assigned radio and channel, if any.
frequency_to_channel_map: dict[RadioFrequency, ChannelAssignment] = field(
init=False, default_factory=dict
)
def __post_init__(self) -> None:
self.callsign = create_group_callsign_from_unit(self.units[0])
@property
def client_units(self) -> list[FlyingUnit]:
"""List of playable units in the flight."""
return [u for u in self.units if u.is_human()]
def num_radio_channels(self, radio_id: int) -> int:
"""Returns the number of preset channels for the given radio."""
# Note: pydcs only initializes the radio presets for client slots.
return self.client_units[0].num_radio_channels(radio_id)
def channel_for(self, frequency: RadioFrequency) -> Optional[ChannelAssignment]:
"""Returns the radio and channel number for the given frequency."""
return self.frequency_to_channel_map.get(frequency, None)
def assign_channel(
self, radio_id: int, channel_id: int, frequency: RadioFrequency
) -> None:
"""Assigns a preset radio channel to the given frequency."""
for unit in self.client_units:
unit.set_radio_channel_preset(radio_id, channel_id, frequency.mhz)
# One frequency could be bound to multiple channels. Prefer the first,
# since with the current implementation it will be the lowest numbered
# channel.
if frequency not in self.frequency_to_channel_map:
self.frequency_to_channel_map[frequency] = ChannelAssignment(
radio_id, channel_id
)