mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Set up JTAC channel assignments.
This commit is contained in:
parent
119d4b9514
commit
8d68c10905
@ -16,11 +16,11 @@ from dcs.triggers import TriggerStart
|
||||
|
||||
from game.plugins import LuaPluginManager
|
||||
from game.theater.theatergroundobject import TheaterGroundObject
|
||||
from gen import Conflict, FlightType, VisualGenerator
|
||||
from gen import Conflict, FlightType, VisualGenerator, AirSupport
|
||||
from gen.aircraft import AircraftConflictGenerator, FlightData
|
||||
from gen.airfields import AIRFIELD_DATA
|
||||
from gen.airsupportgen import AirSupport, AirSupportConflictGenerator
|
||||
from gen.armor import GroundConflictGenerator, JtacInfo
|
||||
from gen.airsupportgen import AirSupportConflictGenerator
|
||||
from gen.armor import GroundConflictGenerator
|
||||
from gen.beacons import load_beacons_for_terrain
|
||||
from gen.briefinggen import BriefingGenerator, MissionInfoGenerator
|
||||
from gen.cargoshipgen import CargoShipGenerator
|
||||
@ -58,8 +58,8 @@ class Operation:
|
||||
enemy_awacs_enabled = True
|
||||
ca_slots = 1
|
||||
unit_map: UnitMap
|
||||
jtacs: List[JtacInfo] = []
|
||||
plugin_scripts: List[str] = []
|
||||
air_support = AirSupport()
|
||||
|
||||
@classmethod
|
||||
def prepare(cls, game: Game) -> None:
|
||||
@ -146,8 +146,7 @@ class Operation:
|
||||
def notify_info_generators(
|
||||
cls,
|
||||
groundobjectgen: GroundObjectsGenerator,
|
||||
airsupportgen: AirSupportConflictGenerator,
|
||||
jtacs: List[JtacInfo],
|
||||
air_support: AirSupport,
|
||||
airgen: AircraftConflictGenerator,
|
||||
) -> None:
|
||||
"""Generates subscribed MissionInfoGenerator objects (currently kneeboards and briefings)"""
|
||||
@ -160,15 +159,15 @@ class Operation:
|
||||
for dynamic_runway in groundobjectgen.runways.values():
|
||||
gen.add_dynamic_runway(dynamic_runway)
|
||||
|
||||
for tanker in airsupportgen.air_support.tankers:
|
||||
for tanker in air_support.tankers:
|
||||
if tanker.blue:
|
||||
gen.add_tanker(tanker)
|
||||
|
||||
for aewc in airsupportgen.air_support.awacs:
|
||||
for aewc in air_support.awacs:
|
||||
if aewc.blue:
|
||||
gen.add_awacs(aewc)
|
||||
|
||||
for jtac in jtacs:
|
||||
for jtac in air_support.jtacs:
|
||||
if jtac.blue:
|
||||
gen.add_jtac(jtac)
|
||||
|
||||
@ -280,6 +279,7 @@ class Operation:
|
||||
@classmethod
|
||||
def generate(cls) -> UnitMap:
|
||||
"""Build the final Mission to be exported"""
|
||||
cls.air_support = AirSupport()
|
||||
cls.create_unit_map()
|
||||
cls.create_radio_registries()
|
||||
# Set mission time and weather conditions.
|
||||
@ -288,10 +288,10 @@ class Operation:
|
||||
cls._generate_transports()
|
||||
cls._generate_destroyed_units()
|
||||
cls._generate_air_units()
|
||||
cls._generate_ground_conflicts()
|
||||
cls.assign_channels_to_flights(
|
||||
cls.airgen.flights, cls.airsupportgen.air_support
|
||||
)
|
||||
cls._generate_ground_conflicts()
|
||||
|
||||
# Triggers
|
||||
triggersgen = TriggersGenerator(cls.current_mission, cls.game)
|
||||
@ -311,7 +311,7 @@ class Operation:
|
||||
if cls.game.settings.perf_smoke_gen:
|
||||
visualgen.generate()
|
||||
|
||||
cls.generate_lua(cls.airgen, cls.airsupportgen, cls.jtacs)
|
||||
cls.generate_lua(cls.airgen, cls.air_support)
|
||||
|
||||
# Inject Plugins Lua Scripts and data
|
||||
cls.plugin_scripts.clear()
|
||||
@ -323,9 +323,7 @@ class Operation:
|
||||
cls.assign_channels_to_flights(
|
||||
cls.airgen.flights, cls.airsupportgen.air_support
|
||||
)
|
||||
cls.notify_info_generators(
|
||||
cls.groundobjectgen, cls.airsupportgen, cls.jtacs, cls.airgen
|
||||
)
|
||||
cls.notify_info_generators(cls.groundobjectgen, cls.air_support, cls.airgen)
|
||||
cls.reset_naming_ids()
|
||||
return cls.unit_map
|
||||
|
||||
@ -341,6 +339,7 @@ class Operation:
|
||||
cls.game,
|
||||
cls.radio_registry,
|
||||
cls.tacan_registry,
|
||||
cls.air_support,
|
||||
)
|
||||
cls.airsupportgen.generate()
|
||||
|
||||
@ -375,7 +374,6 @@ class Operation:
|
||||
@classmethod
|
||||
def _generate_ground_conflicts(cls) -> None:
|
||||
"""For each frontline in the Operation, generate the ground conflicts and JTACs"""
|
||||
cls.jtacs = []
|
||||
for front_line in cls.game.theater.conflicts():
|
||||
player_cp = front_line.blue_cp
|
||||
enemy_cp = front_line.red_cp
|
||||
@ -400,9 +398,9 @@ class Operation:
|
||||
enemy_cp.stances[player_cp.id],
|
||||
cls.unit_map,
|
||||
cls.radio_registry,
|
||||
cls.air_support,
|
||||
)
|
||||
ground_conflict_gen.generate()
|
||||
cls.jtacs.extend(ground_conflict_gen.jtacs)
|
||||
|
||||
@classmethod
|
||||
def _generate_transports(cls) -> None:
|
||||
@ -416,10 +414,7 @@ class Operation:
|
||||
|
||||
@classmethod
|
||||
def generate_lua(
|
||||
cls,
|
||||
airgen: AircraftConflictGenerator,
|
||||
airsupportgen: AirSupportConflictGenerator,
|
||||
jtacs: List[JtacInfo],
|
||||
cls, airgen: AircraftConflictGenerator, air_support: AirSupport
|
||||
) -> None:
|
||||
# TODO: Refactor this
|
||||
luaData = {
|
||||
@ -432,7 +427,7 @@ class Operation:
|
||||
"BlueAA": {},
|
||||
} # type: ignore
|
||||
|
||||
for i, tanker in enumerate(airsupportgen.air_support.tankers):
|
||||
for i, tanker in enumerate(air_support.tankers):
|
||||
luaData["Tankers"][i] = {
|
||||
"dcsGroupName": tanker.group_name,
|
||||
"callsign": tanker.callsign,
|
||||
@ -441,14 +436,14 @@ class Operation:
|
||||
"tacan": str(tanker.tacan.number) + tanker.tacan.band.name,
|
||||
}
|
||||
|
||||
for i, awacs in enumerate(airsupportgen.air_support.awacs):
|
||||
for i, awacs in enumerate(air_support.awacs):
|
||||
luaData["AWACs"][i] = {
|
||||
"dcsGroupName": awacs.group_name,
|
||||
"callsign": awacs.callsign,
|
||||
"radio": awacs.freq.mhz,
|
||||
}
|
||||
|
||||
for i, jtac in enumerate(jtacs):
|
||||
for i, jtac in enumerate(air_support.jtacs):
|
||||
luaData["JTACs"][i] = {
|
||||
"dcsGroupName": jtac.group_name,
|
||||
"callsign": jtac.callsign,
|
||||
|
||||
@ -72,6 +72,9 @@ class CommonRadioChannelAllocator(RadioChannelAllocator):
|
||||
for awacs in air_support.awacs:
|
||||
flight.assign_channel(radio_id, next(channel_alloc), awacs.freq)
|
||||
|
||||
for jtac in air_support.jtacs:
|
||||
flight.assign_channel(radio_id, next(channel_alloc), jtac.freq)
|
||||
|
||||
if flight.arrival != flight.departure and flight.arrival.atc is not None:
|
||||
flight.assign_channel(radio_id, next(channel_alloc), flight.arrival.atc)
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ from game.theater.missiontarget import MissionTarget
|
||||
from game.theater.theatergroundobject import TheaterGroundObject
|
||||
from game.transfers import MultiGroupTransport
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import Distance, Heading, meters, nautical_miles, pairwise
|
||||
from game.utils import Distance, meters, nautical_miles, pairwise
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
from gen.callsigns import create_group_callsign_from_unit
|
||||
from gen.flights.flight import (
|
||||
@ -93,7 +93,7 @@ from gen.flights.flight import (
|
||||
from gen.radios import RadioFrequency, RadioRegistry
|
||||
from gen.runways import RunwayData
|
||||
from gen.tacan import TacanBand, TacanRegistry
|
||||
from .airsupportgen import AirSupport, AwacsInfo, TankerInfo
|
||||
from .airsupport import AirSupport, AwacsInfo, TankerInfo
|
||||
from .callsigns import callsign_for_support_unit
|
||||
from .flights.flightplan import (
|
||||
AwacsFlightPlan,
|
||||
|
||||
55
gen/airsupport.py
Normal file
55
gen/airsupport.py
Normal file
@ -0,0 +1,55 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import timedelta
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from gen import RadioFrequency, TacanChannel
|
||||
|
||||
|
||||
@dataclass
|
||||
class AwacsInfo:
|
||||
"""AWACS information for the kneeboard."""
|
||||
|
||||
group_name: str
|
||||
callsign: str
|
||||
freq: RadioFrequency
|
||||
depature_location: Optional[str]
|
||||
start_time: Optional[timedelta]
|
||||
end_time: Optional[timedelta]
|
||||
blue: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class TankerInfo:
|
||||
"""Tanker information for the kneeboard."""
|
||||
|
||||
group_name: str
|
||||
callsign: str
|
||||
variant: str
|
||||
freq: RadioFrequency
|
||||
tacan: TacanChannel
|
||||
start_time: Optional[timedelta]
|
||||
end_time: Optional[timedelta]
|
||||
blue: bool
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class JtacInfo:
|
||||
"""JTAC information."""
|
||||
|
||||
group_name: str
|
||||
unit_name: str
|
||||
callsign: str
|
||||
region: str
|
||||
code: str
|
||||
blue: bool
|
||||
freq: RadioFrequency
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirSupport:
|
||||
awacs: list[AwacsInfo] = field(default_factory=list)
|
||||
tankers: list[TankerInfo] = field(default_factory=list)
|
||||
jtacs: list[JtacInfo] = field(default_factory=list)
|
||||
@ -1,9 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import timedelta
|
||||
from typing import List, Type, Tuple, Optional, TYPE_CHECKING
|
||||
from typing import List, Type, Tuple, TYPE_CHECKING
|
||||
|
||||
from dcs.mission import Mission, StartType
|
||||
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135, PlaneType
|
||||
@ -18,14 +16,14 @@ from dcs.task import (
|
||||
from dcs.unittype import UnitType
|
||||
|
||||
from game.utils import Heading
|
||||
from .flights.ai_flight_planner_db import AEWC_CAPABLE
|
||||
from .naming import namegen
|
||||
from . import AirSupport
|
||||
from .airsupport import TankerInfo, AwacsInfo
|
||||
from .callsigns import callsign_for_support_unit
|
||||
from .conflictgen import Conflict
|
||||
from .flights.ai_flight_planner_db import AEWC_CAPABLE
|
||||
from .naming import namegen
|
||||
from .radios import RadioFrequency, RadioRegistry
|
||||
from .tacan import TacanBand, TacanChannel, TacanRegistry
|
||||
from .radios import RadioRegistry
|
||||
from .tacan import TacanBand, TacanRegistry
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@ -38,39 +36,6 @@ AWACS_DISTANCE = 150000
|
||||
AWACS_ALT = 13000
|
||||
|
||||
|
||||
@dataclass
|
||||
class AwacsInfo:
|
||||
"""AWACS information for the kneeboard."""
|
||||
|
||||
group_name: str
|
||||
callsign: str
|
||||
freq: RadioFrequency
|
||||
depature_location: Optional[str]
|
||||
start_time: Optional[timedelta]
|
||||
end_time: Optional[timedelta]
|
||||
blue: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class TankerInfo:
|
||||
"""Tanker information for the kneeboard."""
|
||||
|
||||
group_name: str
|
||||
callsign: str
|
||||
variant: str
|
||||
freq: RadioFrequency
|
||||
tacan: TacanChannel
|
||||
start_time: Optional[timedelta]
|
||||
end_time: Optional[timedelta]
|
||||
blue: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirSupport:
|
||||
awacs: List[AwacsInfo] = field(default_factory=list)
|
||||
tankers: List[TankerInfo] = field(default_factory=list)
|
||||
|
||||
|
||||
class AirSupportConflictGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
@ -79,13 +44,14 @@ class AirSupportConflictGenerator:
|
||||
game: Game,
|
||||
radio_registry: RadioRegistry,
|
||||
tacan_registry: TacanRegistry,
|
||||
air_support: AirSupport,
|
||||
) -> None:
|
||||
self.mission = mission
|
||||
self.conflict = conflict
|
||||
self.game = game
|
||||
self.air_support = AirSupport()
|
||||
self.radio_registry = radio_registry
|
||||
self.tacan_registry = tacan_registry
|
||||
self.air_support = air_support
|
||||
|
||||
@classmethod
|
||||
def support_tasks(cls) -> List[Type[MainTask]]:
|
||||
@ -94,12 +60,12 @@ class AirSupportConflictGenerator:
|
||||
@staticmethod
|
||||
def _get_tanker_params(unit_type: Type[UnitType]) -> Tuple[int, int]:
|
||||
if unit_type is KC130:
|
||||
return (TANKER_ALT - 500, 596)
|
||||
return TANKER_ALT - 500, 596
|
||||
elif unit_type is KC_135:
|
||||
return (TANKER_ALT, 770)
|
||||
return TANKER_ALT, 770
|
||||
elif unit_type is KC135MPRS:
|
||||
return (TANKER_ALT + 500, 596)
|
||||
return (TANKER_ALT, 574)
|
||||
return TANKER_ALT + 500, 596
|
||||
return TANKER_ALT, 574
|
||||
|
||||
def generate(self) -> None:
|
||||
player_cp = (
|
||||
|
||||
23
gen/armor.py
23
gen/armor.py
@ -40,6 +40,7 @@ from gen.ground_forces.ai_ground_planner import (
|
||||
CombatGroup,
|
||||
CombatGroupRole,
|
||||
)
|
||||
from .airsupport import AirSupport, JtacInfo
|
||||
from .callsigns import callsign_for_support_unit
|
||||
from .conflictgen import Conflict
|
||||
from .ground_forces.combat_stance import CombatStance
|
||||
@ -67,19 +68,6 @@ RANDOM_OFFSET_ATTACK = 250
|
||||
INFANTRY_GROUP_SIZE = 5
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class JtacInfo:
|
||||
"""JTAC information."""
|
||||
|
||||
group_name: str
|
||||
unit_name: str
|
||||
callsign: str
|
||||
region: str
|
||||
code: str
|
||||
blue: bool
|
||||
freq: RadioFrequency
|
||||
|
||||
|
||||
class GroundConflictGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
@ -92,6 +80,7 @@ class GroundConflictGenerator:
|
||||
enemy_stance: CombatStance,
|
||||
unit_map: UnitMap,
|
||||
radio_registry: RadioRegistry,
|
||||
air_support: AirSupport,
|
||||
) -> None:
|
||||
self.mission = mission
|
||||
self.conflict = conflict
|
||||
@ -102,7 +91,7 @@ class GroundConflictGenerator:
|
||||
self.game = game
|
||||
self.unit_map = unit_map
|
||||
self.radio_registry = radio_registry
|
||||
self.jtacs: List[JtacInfo] = []
|
||||
self.air_support = air_support
|
||||
|
||||
def generate(self) -> None:
|
||||
position = Conflict.frontline_position(
|
||||
@ -151,7 +140,7 @@ class GroundConflictGenerator:
|
||||
# Add JTAC
|
||||
if self.game.blue.faction.has_jtac:
|
||||
n = "JTAC" + str(self.conflict.blue_cp.id) + str(self.conflict.red_cp.id)
|
||||
code = 1688 - len(self.jtacs)
|
||||
code = 1688 - len(self.air_support.jtacs)
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
|
||||
utype = self.game.blue.faction.jtac_unit
|
||||
@ -168,7 +157,7 @@ class GroundConflictGenerator:
|
||||
maintask=AFAC,
|
||||
)
|
||||
jtac.points[0].tasks.append(
|
||||
FAC(callsign=len(self.jtacs) + 1, frequency=int(freq.mhz))
|
||||
FAC(callsign=len(self.air_support.jtacs) + 1, frequency=int(freq.mhz))
|
||||
)
|
||||
jtac.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
jtac.points[0].tasks.append(SetImmortalCommand(True))
|
||||
@ -180,7 +169,7 @@ class GroundConflictGenerator:
|
||||
)
|
||||
# Note: Will need to change if we ever add ground based JTAC.
|
||||
callsign = callsign_for_support_unit(jtac)
|
||||
self.jtacs.append(
|
||||
self.air_support.jtacs.append(
|
||||
JtacInfo(
|
||||
str(jtac.name),
|
||||
n,
|
||||
|
||||
@ -408,6 +408,8 @@ class BriefingPage(KneeboardPage):
|
||||
class SupportPage(KneeboardPage):
|
||||
"""A kneeboard page containing information about support units."""
|
||||
|
||||
JTAC_REGION_MAX_LEN = 25
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
flight: FlightData,
|
||||
@ -490,7 +492,10 @@ class SupportPage(KneeboardPage):
|
||||
jtacs.append(
|
||||
[
|
||||
jtac.callsign,
|
||||
jtac.region,
|
||||
KneeboardPageWriter.wrap_line(
|
||||
jtac.region,
|
||||
self.JTAC_REGION_MAX_LEN,
|
||||
),
|
||||
jtac.code,
|
||||
self.format_frequency(jtac.freq),
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user