mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
AEW&C kneeboard + actually do AEW&C (#922)
* AEW&C will now do AEW&C * AEW&C gets a frequency * AEW&C is added to kneeboard (Frequency, Depature, Depature Time, Arrival Time)
This commit is contained in:
parent
0f07b2c095
commit
260358c5fb
@ -166,6 +166,7 @@ class Operation:
|
|||||||
airgen: AircraftConflictGenerator,
|
airgen: AircraftConflictGenerator,
|
||||||
):
|
):
|
||||||
"""Generates subscribed MissionInfoGenerator objects (currently kneeboards and briefings)"""
|
"""Generates subscribed MissionInfoGenerator objects (currently kneeboards and briefings)"""
|
||||||
|
|
||||||
gens: List[MissionInfoGenerator] = [
|
gens: List[MissionInfoGenerator] = [
|
||||||
KneeboardGenerator(cls.current_mission, cls.game),
|
KneeboardGenerator(cls.current_mission, cls.game),
|
||||||
BriefingGenerator(cls.current_mission, cls.game),
|
BriefingGenerator(cls.current_mission, cls.game),
|
||||||
@ -177,9 +178,8 @@ class Operation:
|
|||||||
for tanker in airsupportgen.air_support.tankers:
|
for tanker in airsupportgen.air_support.tankers:
|
||||||
gen.add_tanker(tanker)
|
gen.add_tanker(tanker)
|
||||||
|
|
||||||
if cls.player_awacs_enabled:
|
for aewc in airsupportgen.air_support.awacs:
|
||||||
for awacs in airsupportgen.air_support.awacs:
|
gen.add_awacs(aewc)
|
||||||
gen.add_awacs(awacs)
|
|
||||||
|
|
||||||
for jtac in jtacs:
|
for jtac in jtacs:
|
||||||
gen.add_jtac(jtac)
|
gen.add_jtac(jtac)
|
||||||
@ -378,7 +378,9 @@ class Operation:
|
|||||||
cls.game,
|
cls.game,
|
||||||
cls.radio_registry,
|
cls.radio_registry,
|
||||||
cls.unit_map,
|
cls.unit_map,
|
||||||
|
air_support=cls.airsupportgen.air_support,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.airgen.clear_parking_slots()
|
cls.airgen.clear_parking_slots()
|
||||||
|
|
||||||
cls.airgen.generate_flights(
|
cls.airgen.generate_flights(
|
||||||
|
|||||||
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from typing import Dict, List, Optional, TYPE_CHECKING, Type, Union
|
from typing import Dict, List, Optional, TYPE_CHECKING, Type, Union
|
||||||
@ -67,6 +67,8 @@ from dcs.task import (
|
|||||||
Targets,
|
Targets,
|
||||||
Task,
|
Task,
|
||||||
WeaponType,
|
WeaponType,
|
||||||
|
AWACSTaskAction,
|
||||||
|
SetFrequencyCommand,
|
||||||
)
|
)
|
||||||
from dcs.terrain.terrain import Airport, NoParkingSlotError
|
from dcs.terrain.terrain import Airport, NoParkingSlotError
|
||||||
from dcs.triggers import Event, TriggerOnce, TriggerRule
|
from dcs.triggers import Event, TriggerOnce, TriggerRule
|
||||||
@ -88,7 +90,6 @@ from game.theater.controlpoint import (
|
|||||||
from game.theater.theatergroundobject import TheaterGroundObject
|
from game.theater.theatergroundobject import TheaterGroundObject
|
||||||
from game.unitmap import UnitMap
|
from game.unitmap import UnitMap
|
||||||
from game.utils import Distance, meters, nautical_miles
|
from game.utils import Distance, meters, nautical_miles
|
||||||
from gen.airsupportgen import AirSupport
|
|
||||||
from gen.ato import AirTaskingOrder, Package
|
from gen.ato import AirTaskingOrder, Package
|
||||||
from gen.callsigns import create_group_callsign_from_unit
|
from gen.callsigns import create_group_callsign_from_unit
|
||||||
from gen.flights.flight import (
|
from gen.flights.flight import (
|
||||||
@ -104,9 +105,12 @@ from .flights.flightplan import (
|
|||||||
LoiterFlightPlan,
|
LoiterFlightPlan,
|
||||||
PatrollingFlightPlan,
|
PatrollingFlightPlan,
|
||||||
SweepFlightPlan,
|
SweepFlightPlan,
|
||||||
|
AwacsFlightPlan,
|
||||||
)
|
)
|
||||||
from .flights.traveltime import GroundSpeed, TotEstimator
|
from .flights.traveltime import GroundSpeed, TotEstimator
|
||||||
from .naming import namegen
|
from .naming import namegen
|
||||||
|
from .airsupportgen import AirSupport, AwacsInfo
|
||||||
|
from .callsigns import callsign_for_support_unit
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
@ -666,6 +670,7 @@ class AircraftConflictGenerator:
|
|||||||
game: Game,
|
game: Game,
|
||||||
radio_registry: RadioRegistry,
|
radio_registry: RadioRegistry,
|
||||||
unit_map: UnitMap,
|
unit_map: UnitMap,
|
||||||
|
air_support: AirSupport,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.m = mission
|
self.m = mission
|
||||||
self.game = game
|
self.game = game
|
||||||
@ -673,6 +678,7 @@ class AircraftConflictGenerator:
|
|||||||
self.radio_registry = radio_registry
|
self.radio_registry = radio_registry
|
||||||
self.unit_map = unit_map
|
self.unit_map = unit_map
|
||||||
self.flights: List[FlightData] = []
|
self.flights: List[FlightData] = []
|
||||||
|
self.air_support = air_support
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def use_client(self) -> bool:
|
def use_client(self) -> bool:
|
||||||
@ -787,7 +793,10 @@ class AircraftConflictGenerator:
|
|||||||
OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)
|
OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)
|
||||||
)
|
)
|
||||||
|
|
||||||
channel = self.get_intra_flight_channel(unit_type)
|
if flight.flight_type == FlightType.AEWC:
|
||||||
|
channel = self.radio_registry.alloc_uhf()
|
||||||
|
else:
|
||||||
|
channel = self.get_intra_flight_channel(unit_type)
|
||||||
group.set_frequency(channel.mhz)
|
group.set_frequency(channel.mhz)
|
||||||
|
|
||||||
divert = None
|
divert = None
|
||||||
@ -824,6 +833,20 @@ class AircraftConflictGenerator:
|
|||||||
if unit_type in [Su_33, C_101EB, C_101CC]:
|
if unit_type in [Su_33, C_101EB, C_101CC]:
|
||||||
self.set_reduced_fuel(flight, group, unit_type)
|
self.set_reduced_fuel(flight, group, unit_type)
|
||||||
|
|
||||||
|
if isinstance(flight.flight_plan, AwacsFlightPlan):
|
||||||
|
callsign = callsign_for_support_unit(group)
|
||||||
|
|
||||||
|
self.air_support.awacs.append(
|
||||||
|
AwacsInfo(
|
||||||
|
dcsGroupName=str(group.name),
|
||||||
|
callsign=callsign,
|
||||||
|
freq=channel,
|
||||||
|
depature_location=flight.departure.name,
|
||||||
|
end_time=flight.flight_plan.mission_departure_time,
|
||||||
|
start_time=flight.flight_plan.mission_start_time,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _generate_at_airport(
|
def _generate_at_airport(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
@ -1356,7 +1379,16 @@ class AircraftConflictGenerator:
|
|||||||
dynamic_runways: Dict[str, RunwayData],
|
dynamic_runways: Dict[str, RunwayData],
|
||||||
) -> None:
|
) -> None:
|
||||||
group.task = AWACS.name
|
group.task = AWACS.name
|
||||||
|
|
||||||
|
if not isinstance(flight.flight_plan, AwacsFlightPlan):
|
||||||
|
logging.error(
|
||||||
|
f"Cannot configure AEW&C tasks for {flight} because it does not have an AEW&C flight plan."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
self._setup_group(group, AWACS, package, flight, dynamic_runways)
|
self._setup_group(group, AWACS, package, flight, dynamic_runways)
|
||||||
|
|
||||||
|
# Awacs task action
|
||||||
self.configure_behavior(
|
self.configure_behavior(
|
||||||
group,
|
group,
|
||||||
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
||||||
@ -1364,6 +1396,8 @@ class AircraftConflictGenerator:
|
|||||||
restrict_jettison=True,
|
restrict_jettison=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
group.points[0].tasks.append(AWACSTaskAction())
|
||||||
|
|
||||||
def configure_escort(
|
def configure_escort(
|
||||||
self,
|
self,
|
||||||
group: FlyingGroup,
|
group: FlyingGroup,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List, Type, Tuple
|
from datetime import timedelta
|
||||||
|
from typing import List, Type, Tuple, Optional
|
||||||
|
|
||||||
from dcs.mission import Mission, StartType
|
from dcs.mission import Mission, StartType
|
||||||
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135
|
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135
|
||||||
@ -37,6 +38,9 @@ class AwacsInfo:
|
|||||||
dcsGroupName: str
|
dcsGroupName: str
|
||||||
callsign: str
|
callsign: str
|
||||||
freq: RadioFrequency
|
freq: RadioFrequency
|
||||||
|
depature_location: Optional[str]
|
||||||
|
start_time: Optional[timedelta]
|
||||||
|
end_time: Optional[timedelta]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -192,9 +196,12 @@ class AirSupportConflictGenerator:
|
|||||||
|
|
||||||
self.air_support.awacs.append(
|
self.air_support.awacs.append(
|
||||||
AwacsInfo(
|
AwacsInfo(
|
||||||
str(awacs_flight.name),
|
dcsGroupName=str(awacs_flight.name),
|
||||||
callsign_for_support_unit(awacs_flight),
|
callsign=callsign_for_support_unit(awacs_flight),
|
||||||
freq,
|
freq=freq,
|
||||||
|
depature_location=None,
|
||||||
|
start_time=None,
|
||||||
|
end_time=None,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from .ground_forces.combat_stance import CombatStance
|
|||||||
from .radios import RadioFrequency
|
from .radios import RadioFrequency
|
||||||
from .runways import RunwayData
|
from .runways import RunwayData
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
|
|
||||||
|
|||||||
@ -713,6 +713,10 @@ class AwacsFlightPlan(LoiterFlightPlan):
|
|||||||
if self.divert is not None:
|
if self.divert is not None:
|
||||||
yield self.divert
|
yield self.divert
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mission_start_time(self) -> Optional[timedelta]:
|
||||||
|
return self.takeoff_time()
|
||||||
|
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
if waypoint == self.hold:
|
if waypoint == self.hold:
|
||||||
return self.package.time_over_target
|
return self.package.time_over_target
|
||||||
|
|||||||
@ -41,6 +41,7 @@ from .flights.flight import FlightWaypoint, FlightWaypointType
|
|||||||
from .radios import RadioFrequency
|
from .radios import RadioFrequency
|
||||||
from .runways import RunwayData
|
from .runways import RunwayData
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
|
|
||||||
@ -285,6 +286,34 @@ class BriefingPage(KneeboardPage):
|
|||||||
["Bingo", "Joker"],
|
["Bingo", "Joker"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# AEW&C
|
||||||
|
writer.heading("AEW&C")
|
||||||
|
aewc_ladder = []
|
||||||
|
|
||||||
|
for single_aewc in self.awacs:
|
||||||
|
|
||||||
|
if single_aewc.depature_location is None:
|
||||||
|
dep = "-"
|
||||||
|
arr = "-"
|
||||||
|
else:
|
||||||
|
dep = self._format_time(single_aewc.start_time)
|
||||||
|
arr = self._format_time(single_aewc.end_time)
|
||||||
|
|
||||||
|
aewc_ladder.append(
|
||||||
|
[
|
||||||
|
str(single_aewc.callsign),
|
||||||
|
str(single_aewc.freq),
|
||||||
|
str(single_aewc.depature_location),
|
||||||
|
str(dep),
|
||||||
|
str(arr),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
writer.table(
|
||||||
|
aewc_ladder,
|
||||||
|
headers=["Callsign", "FREQ", "Depature", "ETD", "ETA"],
|
||||||
|
)
|
||||||
|
|
||||||
# Package Section
|
# Package Section
|
||||||
writer.heading("Comm ladder")
|
writer.heading("Comm ladder")
|
||||||
comm_ladder = []
|
comm_ladder = []
|
||||||
@ -293,10 +322,6 @@ class BriefingPage(KneeboardPage):
|
|||||||
[comm.name, "", "", "", self.format_frequency(comm.freq)]
|
[comm.name, "", "", "", self.format_frequency(comm.freq)]
|
||||||
)
|
)
|
||||||
|
|
||||||
for a in self.awacs:
|
|
||||||
comm_ladder.append(
|
|
||||||
[a.callsign, "AWACS", "", "", self.format_frequency(a.freq)]
|
|
||||||
)
|
|
||||||
for tanker in self.tankers:
|
for tanker in self.tankers:
|
||||||
comm_ladder.append(
|
comm_ladder.append(
|
||||||
[
|
[
|
||||||
@ -365,6 +390,12 @@ class BriefingPage(KneeboardPage):
|
|||||||
channel_name = namer.channel_name(channel.radio_id, channel.channel)
|
channel_name = namer.channel_name(channel.radio_id, channel.channel)
|
||||||
return f"{channel_name} {frequency}"
|
return f"{channel_name} {frequency}"
|
||||||
|
|
||||||
|
def _format_time(self, time: Optional[datetime.timedelta]) -> str:
|
||||||
|
if time is None:
|
||||||
|
return ""
|
||||||
|
local_time = self.start_time + time
|
||||||
|
return local_time.strftime(f"%H:%M:%S")
|
||||||
|
|
||||||
|
|
||||||
class KneeboardGenerator(MissionInfoGenerator):
|
class KneeboardGenerator(MissionInfoGenerator):
|
||||||
"""Creates kneeboard pages for each client flight in the mission."""
|
"""Creates kneeboard pages for each client flight in the mission."""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user