Skip to content

Commit

Permalink
Add per-aircraft datalink configuration.
Browse files Browse the repository at this point in the history
  • Loading branch information
DanAlbert committed Oct 4, 2023
1 parent 1a30ffe commit b1efa8e
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 17 deletions.
6 changes: 6 additions & 0 deletions game/dcs/aircrafttype.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from dcs.unittype import FlyingType

from game.data.units import UnitClass
from game.dcs.datalinkconfig import DatalinkConfig
from game.dcs.lasercodeconfig import LaserCodeConfig
from game.dcs.unittype import UnitType
from game.radio.channels import (
Expand Down Expand Up @@ -206,6 +207,7 @@ class AircraftType(UnitType[Type[FlyingType]]):
has_built_in_target_pod: bool

laser_code_configs: list[LaserCodeConfig]
datalink_config: DatalinkConfig | None

use_f15e_waypoint_names: bool

Expand Down Expand Up @@ -347,6 +349,9 @@ def capable_of(self, task: FlightType) -> bool:
def task_priority(self, task: FlightType) -> int:
return self.task_priorities[task]

def should_alloc_stn(self) -> bool:
return self.datalink_config is not None

Check warning on line 353 in game/dcs/aircrafttype.py

View check run for this annotation

Codecov / codecov/patch

game/dcs/aircrafttype.py#L353

Added line #L353 was not covered by tests

def __setstate__(self, state: dict[str, Any]) -> None:
# Update any existing models with new data on load.
updated = AircraftType.named(state["variant_id"])
Expand Down Expand Up @@ -504,6 +509,7 @@ def _variant_from_dict(
laser_code_configs=[
LaserCodeConfig.from_yaml(d) for d in data.get("laser_codes", [])
],
datalink_config=DatalinkConfig.from_data(data),
use_f15e_waypoint_names=data.get("use_f15e_waypoint_names", False),
)

Expand Down
18 changes: 18 additions & 0 deletions game/dcs/datalinkconfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any


@dataclass(frozen=True)
class DatalinkConfig:
max_team_members: int
max_donors: int

@staticmethod
def from_data(data: dict[str, Any]) -> DatalinkConfig | None:
try:
data = data["datalink"]
except KeyError:
return None
return DatalinkConfig(int(data["max_team_members"]), int(data["max_donors"]))
6 changes: 5 additions & 1 deletion game/missiongenerator/aircraft/aircraftgenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ def create_and_configure_flight(
flight, country, self.mission, self.helipads
).create_flight_group()

stn_prefix: SourceTrackNumberPrefix | None = None

Check warning on line 175 in game/missiongenerator/aircraft/aircraftgenerator.py

View check run for this annotation

Codecov / codecov/patch

game/missiongenerator/aircraft/aircraftgenerator.py#L175

Added line #L175 was not covered by tests
if flight.squadron.aircraft.should_alloc_stn():
stn_prefix = SourceTrackNumberPrefix(next(self.stn_prefix_allocator))

Check warning on line 177 in game/missiongenerator/aircraft/aircraftgenerator.py

View check run for this annotation

Codecov / codecov/patch

game/missiongenerator/aircraft/aircraftgenerator.py#L177

Added line #L177 was not covered by tests

briefing_data = FlightGroupConfigurator(
flight,
group,
Expand All @@ -180,7 +184,7 @@ def create_and_configure_flight(
self.time,
self.radio_registry,
self.tacan_registy,
SourceTrackNumberPrefix(next(self.stn_prefix_allocator)),
stn_prefix,
self.mission_data,
dynamic_runways,
self.use_client,
Expand Down
7 changes: 4 additions & 3 deletions game/missiongenerator/aircraft/flightgroupconfigurator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(
time: datetime,
radio_registry: RadioRegistry,
tacan_registry: TacanRegistry,
stn_prefix: SourceTrackNumberPrefix,
stn_prefix: SourceTrackNumberPrefix | None,
mission_data: MissionData,
dynamic_runways: dict[str, RunwayData],
use_client: bool,
Expand Down Expand Up @@ -70,12 +70,13 @@ def configure(self) -> FlightData:
flight_channel = self.setup_radios()

laser_codes: list[Optional[int]] = []
stns = []
stns: list[SourceTrackNumber] = []

Check warning on line 73 in game/missiongenerator/aircraft/flightgroupconfigurator.py

View check run for this annotation

Codecov / codecov/patch

game/missiongenerator/aircraft/flightgroupconfigurator.py#L73

Added line #L73 was not covered by tests
for idx, (unit, member) in enumerate(
zip(self.group.units, self.flight.iter_members())
):
self.configure_flight_member(unit, member, laser_codes)
stns.append(SourceTrackNumber(self.stn_prefix, idx))
if self.stn_prefix is not None:
stns.append(SourceTrackNumber(self.stn_prefix, idx))

Check warning on line 79 in game/missiongenerator/aircraft/flightgroupconfigurator.py

View check run for this annotation

Codecov / codecov/patch

game/missiongenerator/aircraft/flightgroupconfigurator.py#L79

Added line #L79 was not covered by tests

divert = None
if self.flight.divert is not None:
Expand Down
3 changes: 3 additions & 0 deletions resources/units/aircraft/F-16C_50.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,6 @@ laser_codes:
digit: 1
- id: LaserCode1
digit: 0
datalink:
max_team_members: 8
max_donors: 4
29 changes: 16 additions & 13 deletions resources/units/aircraft/FA-18C_hornet.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
carrier_capable: true
description:
'The F/A-18C Hornet is twin engine, supersonic fighter that is flown
by a single pilot in a "glass cockpit". It combines extreme maneuverability , a
deadly arsenal of weapons, and the ability to operate from an aircraft carrier.
Operated by several nations, this multi-role fighter has been instrumental in conflicts
from 1986 to today.
description: 'The F/A-18C Hornet is twin engine, supersonic fighter that is
flown by a single pilot in a "glass cockpit". It combines extreme
maneuverability , a deadly arsenal of weapons, and the ability to operate from
an aircraft carrier. Operated by several nations, this multi-role fighter has
been instrumental in conflicts from 1986 to today.
The Hornet is equipped with a large suite of sensors that includes a radar, targeting
pod, and a helmet mounted sight. In addition to its internal 20mm cannon, the Hornet
can be armed with a large assortment of unguided bombs and rockets, laser and GPS-guided
bombs, air-to-surface missiles of all sorts, and both radar and infrared-guided
air-to-air missiles.
The Hornet is equipped with a large suite of sensors that includes a radar,
targeting pod, and a helmet mounted sight. In addition to its internal 20mm
cannon, the Hornet can be armed with a large assortment of unguided bombs and
rockets, laser and GPS-guided bombs, air-to-surface missiles of all sorts, and
both radar and infrared-guided air-to-air missiles.
The Hornet is also known for its extreme, slow-speed maneuverability in a dogfight.
Although incredibly deadly, the Hornet is also a very easy aircraft to fly.'
The Hornet is also known for its extreme, slow-speed maneuverability in a
dogfight. Although incredibly deadly, the Hornet is also a very easy aircraft
to fly.'
introduced: 1987
manufacturer: McDonnell Douglas
origin: USA
Expand Down Expand Up @@ -68,3 +68,6 @@ tasks:
SEAD Escort: 160
Strike: 600
TARCAP: 450
datalink:
max_team_members: 4
max_donors: 8
55 changes: 55 additions & 0 deletions tests/dcs/test_datalinkconfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import pytest

from game.dcs.datalinkconfig import DatalinkConfig


def test_from_data_no_data() -> None:
assert DatalinkConfig.from_data({}) is None


def test_from_data_bad_data() -> None:
with pytest.raises(KeyError):
DatalinkConfig.from_data(
{
"datalink": {
"max_team_members": 4,
}
}
)
with pytest.raises(KeyError):
DatalinkConfig.from_data(
{
"datalink": {
"max_donors": 4,
}
}
)
with pytest.raises(ValueError):
DatalinkConfig.from_data(
{
"datalink": {
"max_team_members": 4,
"max_donors": "a",
}
}
)
with pytest.raises(ValueError):
DatalinkConfig.from_data(
{
"datalink": {
"max_team_members": "a",
"max_donors": 4,
}
}
)


def test_from_data() -> None:
assert DatalinkConfig.from_data(
{
"datalink": {
"max_team_members": 4,
"max_donors": 8,
}
}
) == DatalinkConfig(max_team_members=4, max_donors=8)

0 comments on commit b1efa8e

Please sign in to comment.