mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add carrier support to kneeboards.
This commit is contained in:
parent
a9e65cc83d
commit
d02a3a0d3f
@ -80,7 +80,13 @@ class Operation:
|
||||
self.visualgen = VisualGenerator(mission, conflict, self.game)
|
||||
self.envgen = EnviromentGenerator(mission, conflict, self.game)
|
||||
self.forcedoptionsgen = ForcedOptionsGenerator(mission, conflict, self.game)
|
||||
self.groundobjectgen = GroundObjectsGenerator(mission, conflict, self.game)
|
||||
self.groundobjectgen = GroundObjectsGenerator(
|
||||
mission,
|
||||
conflict,
|
||||
self.game,
|
||||
self.radio_registry,
|
||||
self.tacan_registry
|
||||
)
|
||||
self.briefinggen = BriefingGenerator(mission, conflict, self.game)
|
||||
|
||||
def prepare(self, terrain: Terrain, is_quick: bool):
|
||||
@ -136,15 +142,6 @@ class Operation:
|
||||
for frequency in unique_beacon_frequencies:
|
||||
self.radio_registry.reserve(frequency)
|
||||
|
||||
# Generate meteo
|
||||
if self.environment_settings is None:
|
||||
self.environment_settings = self.envgen.generate()
|
||||
else:
|
||||
self.envgen.load(self.environment_settings)
|
||||
|
||||
# Generate ground object first
|
||||
self.groundobjectgen.generate()
|
||||
|
||||
for airfield, data in AIRFIELD_DATA.items():
|
||||
if data.theater == self.game.theater.terrain.name:
|
||||
self.radio_registry.reserve(data.atc.hf)
|
||||
@ -154,6 +151,15 @@ class Operation:
|
||||
# No need to reserve ILS or TACAN because those are in the
|
||||
# beacon list.
|
||||
|
||||
# Generate meteo
|
||||
if self.environment_settings is None:
|
||||
self.environment_settings = self.envgen.generate()
|
||||
else:
|
||||
self.envgen.load(self.environment_settings)
|
||||
|
||||
# Generate ground object first
|
||||
self.groundobjectgen.generate()
|
||||
|
||||
# Generate destroyed units
|
||||
for d in self.game.get_destroyed_units():
|
||||
try:
|
||||
@ -185,7 +191,12 @@ class Operation:
|
||||
else:
|
||||
country = self.current_mission.country(self.game.enemy_country)
|
||||
if cp.id in self.game.planners.keys():
|
||||
self.airgen.generate_flights(cp, country, self.game.planners[cp.id])
|
||||
self.airgen.generate_flights(
|
||||
cp,
|
||||
country,
|
||||
self.game.planners[cp.id],
|
||||
self.groundobjectgen.runways
|
||||
)
|
||||
|
||||
# Generate ground units on frontline everywhere
|
||||
self.game.jtacs = []
|
||||
@ -309,27 +320,16 @@ class Operation:
|
||||
last_channel = flight.num_radio_channels(radio_id)
|
||||
channel_alloc = iter(range(first_channel, last_channel + 1))
|
||||
|
||||
# TODO: Fix departure/arrival to support carriers.
|
||||
if flight.departure is not None:
|
||||
try:
|
||||
departure = AIRFIELD_DATA[flight.departure.name]
|
||||
flight.assign_channel(
|
||||
radio_id, next(channel_alloc), departure.atc.uhf)
|
||||
except KeyError:
|
||||
pass
|
||||
flight.assign_channel(radio_id, next(channel_alloc),flight.departure.atc)
|
||||
|
||||
# TODO: If there ever are multiple AWACS, limit to mission relevant.
|
||||
for awacs in self.airsupportgen.air_support.awacs:
|
||||
flight.assign_channel(radio_id, next(channel_alloc), awacs.freq)
|
||||
|
||||
# TODO: Fix departure/arrival to support carriers.
|
||||
if flight.arrival is not None and flight.arrival != flight.departure:
|
||||
try:
|
||||
arrival = AIRFIELD_DATA[flight.arrival.name]
|
||||
flight.assign_channel(
|
||||
radio_id, next(channel_alloc), arrival.atc.uhf)
|
||||
except KeyError:
|
||||
pass
|
||||
if flight.arrival != flight.departure:
|
||||
flight.assign_channel(radio_id, next(channel_alloc),
|
||||
flight.arrival.atc)
|
||||
|
||||
try:
|
||||
# TODO: Skip incompatible tankers.
|
||||
@ -338,12 +338,8 @@ class Operation:
|
||||
radio_id, next(channel_alloc), tanker.freq)
|
||||
|
||||
if flight.divert is not None:
|
||||
try:
|
||||
divert = AIRFIELD_DATA[flight.divert.name]
|
||||
flight.assign_channel(
|
||||
radio_id, next(channel_alloc), divert.atc.uhf)
|
||||
except KeyError:
|
||||
pass
|
||||
flight.assign_channel(radio_id, next(channel_alloc),
|
||||
flight.divert.atc)
|
||||
except StopIteration:
|
||||
# Any remaining channels are nice-to-haves, but not necessary for
|
||||
# the few aircraft with a small number of channels available.
|
||||
|
||||
@ -4,6 +4,7 @@ from typing import Dict, List, Optional, Tuple
|
||||
from game.data.cap_capabilities_db import GUNFIGHTERS
|
||||
from game.settings import Settings
|
||||
from game.utils import nm_to_meter
|
||||
from gen.airfields import RunwayData
|
||||
from gen.flights.ai_flight_planner import FlightPlanner
|
||||
from gen.flights.flight import (
|
||||
Flight,
|
||||
@ -150,15 +151,14 @@ class FlightData:
|
||||
#: List of playable units in the flight.
|
||||
client_units: List[FlyingUnit]
|
||||
|
||||
# TODO: Arrival and departure should not be optional, but carriers don't count.
|
||||
#: Arrival airport.
|
||||
arrival: Optional[Airport]
|
||||
arrival: RunwayData
|
||||
|
||||
#: Departure airport.
|
||||
departure: Optional[Airport]
|
||||
departure: RunwayData
|
||||
|
||||
#: Diver airport.
|
||||
divert: Optional[Airport]
|
||||
divert: Optional[RunwayData]
|
||||
|
||||
#: Waypoints of the flight plan.
|
||||
waypoints: List[FlightWaypoint]
|
||||
@ -169,8 +169,8 @@ class FlightData:
|
||||
#: Map of radio frequencies to their assigned radio and channel, if any.
|
||||
frequency_to_channel_map: Dict[RadioFrequency, ChannelAssignment]
|
||||
|
||||
def __init__(self, client_units: List[FlyingUnit], arrival: Airport,
|
||||
departure: Airport, divert: Optional[Airport],
|
||||
def __init__(self, client_units: List[FlyingUnit], arrival: RunwayData,
|
||||
departure: RunwayData, divert: Optional[RunwayData],
|
||||
waypoints: List[FlightWaypoint],
|
||||
intra_flight_channel: RadioFrequency) -> None:
|
||||
self.client_units = client_units
|
||||
@ -261,8 +261,8 @@ class AircraftConflictGenerator:
|
||||
def _start_type(self) -> StartType:
|
||||
return self.settings.cold_start and StartType.Cold or StartType.Warm
|
||||
|
||||
|
||||
def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task], flight: Flight):
|
||||
def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task],
|
||||
flight: Flight, dynamic_runways: Dict[str, RunwayData]):
|
||||
did_load_loadout = False
|
||||
unit_type = group.units[0].unit_type
|
||||
|
||||
@ -319,10 +319,28 @@ class AircraftConflictGenerator:
|
||||
|
||||
radio_id, channel = self.get_intra_flight_channel(unit_type)
|
||||
group.set_frequency(channel.mhz, radio_id)
|
||||
|
||||
# TODO: Support for different departure/arrival airfields.
|
||||
cp = flight.from_cp
|
||||
fallback_runway = RunwayData(cp.full_name, runway_name="")
|
||||
if cp.cptype == ControlPointType.AIRBASE:
|
||||
# TODO: Implement logic for picking preferred runway.
|
||||
runway = flight.from_cp.airport.runways[0]
|
||||
runway_side = ["", "L", "R"][runway.leftright]
|
||||
runway_name = f"{runway.heading}{runway_side}"
|
||||
departure_runway = RunwayData.for_airfield(
|
||||
flight.from_cp.airport, runway_name)
|
||||
elif cp.is_fleet:
|
||||
departure_runway = dynamic_runways.get(cp.name, fallback_runway)
|
||||
else:
|
||||
logging.warning(f"Unhandled departure control point: {cp.cptype}")
|
||||
departure_runway = fallback_runway
|
||||
|
||||
self.flights.append(FlightData(
|
||||
client_units=clients,
|
||||
departure=flight.from_cp.airport,
|
||||
arrival=flight.from_cp.airport,
|
||||
departure=departure_runway,
|
||||
arrival=departure_runway,
|
||||
# TODO: Support for divert airfields.
|
||||
divert=None,
|
||||
waypoints=flight.points,
|
||||
intra_flight_channel=channel
|
||||
@ -477,8 +495,8 @@ class AircraftConflictGenerator:
|
||||
logging.warning("Pylon not found ! => Pylon" + key + " on " + str(flight.unit_type))
|
||||
|
||||
|
||||
def generate_flights(self, cp, country, flight_planner:FlightPlanner):
|
||||
|
||||
def generate_flights(self, cp, country, flight_planner: FlightPlanner,
|
||||
dynamic_runways: Dict[str, RunwayData]):
|
||||
# Clear pydcs parking slots
|
||||
if cp.airport is not None:
|
||||
logging.info("CLEARING SLOTS @ " + cp.airport.name)
|
||||
@ -497,7 +515,8 @@ class AircraftConflictGenerator:
|
||||
continue
|
||||
logging.info("Generating flight : " + str(flight.unit_type))
|
||||
group = self.generate_planned_flight(cp, country, flight)
|
||||
self.setup_flight_group(group, flight, flight.flight_type)
|
||||
self.setup_flight_group(group, flight, flight.flight_type,
|
||||
dynamic_runways)
|
||||
self.setup_group_activation_trigger(flight, group)
|
||||
|
||||
|
||||
@ -608,19 +627,13 @@ class AircraftConflictGenerator:
|
||||
flight.group = group
|
||||
return group
|
||||
|
||||
def setup_group_as_intercept_flight(self, group, flight):
|
||||
group.points[0].ETA = 0
|
||||
group.late_activation = True
|
||||
self._setup_group(group, Intercept, flight)
|
||||
for point in flight.points:
|
||||
group.add_waypoint(Point(point.x,point.y), point.alt)
|
||||
|
||||
|
||||
def setup_flight_group(self, group, flight, flight_type):
|
||||
def setup_flight_group(self, group, flight, flight_type,
|
||||
dynamic_runways: Dict[str, RunwayData]):
|
||||
|
||||
if flight_type in [FlightType.CAP, FlightType.BARCAP, FlightType.TARCAP, FlightType.INTERCEPTION]:
|
||||
group.task = CAP.name
|
||||
self._setup_group(group, CAP, flight)
|
||||
self._setup_group(group, CAP, flight, dynamic_runways)
|
||||
# group.points[0].tasks.clear()
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(EngageTargets(max_distance=nm_to_meter(50), targets=[Targets.All.Air]))
|
||||
@ -632,7 +645,7 @@ class AircraftConflictGenerator:
|
||||
|
||||
elif flight_type in [FlightType.CAS, FlightType.BAI]:
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS, flight)
|
||||
self._setup_group(group, CAS, flight, dynamic_runways)
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(EngageTargets(max_distance=nm_to_meter(10), targets=[Targets.All.GroundUnits.GroundVehicles]))
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
@ -641,7 +654,7 @@ class AircraftConflictGenerator:
|
||||
group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
elif flight_type in [FlightType.SEAD, FlightType.DEAD]:
|
||||
group.task = SEAD.name
|
||||
self._setup_group(group, SEAD, flight)
|
||||
self._setup_group(group, SEAD, flight, dynamic_runways)
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(NoTask())
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
@ -650,14 +663,14 @@ class AircraftConflictGenerator:
|
||||
group.points[0].tasks.append(OptRTBOnOutOfAmmo(OptRTBOnOutOfAmmo.Values.ASM))
|
||||
elif flight_type in [FlightType.STRIKE]:
|
||||
group.task = PinpointStrike.name
|
||||
self._setup_group(group, GroundAttack, flight)
|
||||
self._setup_group(group, GroundAttack, flight, dynamic_runways)
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
|
||||
group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
elif flight_type in [FlightType.ANTISHIP]:
|
||||
group.task = AntishipStrike.name
|
||||
self._setup_group(group, AntishipStrike, flight)
|
||||
self._setup_group(group, AntishipStrike, flight, dynamic_runways)
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFire))
|
||||
@ -736,23 +749,3 @@ class AircraftConflictGenerator:
|
||||
pt.name = String(point.name)
|
||||
|
||||
self._setup_custom_payload(flight, group)
|
||||
|
||||
|
||||
def setup_group_as_antiship_flight(self, group, flight):
|
||||
group.task = AntishipStrike.name
|
||||
self._setup_group(group, AntishipStrike, flight)
|
||||
|
||||
group.points[0].tasks.clear()
|
||||
group.points[0].tasks.append(AntishipStrikeTaskAction())
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.points[0].tasks.append(OptROE(OptROE.Values.OpenFireWeaponFree))
|
||||
group.points[0].tasks.append(OptRestrictJettison(True))
|
||||
|
||||
for point in flight.points:
|
||||
group.add_waypoint(Point(point.x, point.y), point.alt)
|
||||
|
||||
|
||||
def setup_radio_preset(self, flight, group):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@ -4,8 +4,10 @@ Remove once https://github.com/pydcs/dcs/issues/69 tracks getting the missing
|
||||
data added to pydcs. Until then, missing data can be manually filled in here.
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
import logging
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from pydcs.dcs.terrain.terrain import Airport
|
||||
from .radios import MHz, RadioFrequency
|
||||
from .tacan import TacanBand, TacanChannel
|
||||
|
||||
@ -637,3 +639,39 @@ AIRFIELD_DATA = {
|
||||
atc=AtcData(MHz(3, 775), MHz(118, 50), MHz(38, 450), MHz(250, 50)),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class RunwayData:
|
||||
airfield_name: str
|
||||
runway_name: str
|
||||
atc: Optional[RadioFrequency] = None
|
||||
tacan: Optional[TacanChannel] = None
|
||||
ils: Optional[RadioFrequency] = None
|
||||
icls: Optional[int] = None
|
||||
|
||||
@classmethod
|
||||
def for_airfield(cls, airport: Airport, runway: str) -> "RunwayData":
|
||||
"""Creates RunwayData for the given runway of an airfield.
|
||||
|
||||
Args:
|
||||
airport: The airfield the runway belongs to.
|
||||
runway: Identifier of the runway to use. e.g. "030" or "200L".
|
||||
"""
|
||||
atc: Optional[RadioFrequency] = None
|
||||
tacan: Optional[TacanChannel] = None
|
||||
ils: Optional[RadioFrequency] = None
|
||||
try:
|
||||
airfield = AIRFIELD_DATA[airport.name]
|
||||
atc = airfield.atc.uhf
|
||||
tacan = airfield.tacan
|
||||
ils = airfield.ils_freq(runway)
|
||||
except KeyError:
|
||||
logging.warning(f"No airfield data for {airport.name}")
|
||||
return cls(
|
||||
airport.name,
|
||||
runway,
|
||||
atc,
|
||||
tacan,
|
||||
ils
|
||||
)
|
||||
|
||||
@ -1,13 +1,19 @@
|
||||
import logging
|
||||
|
||||
from game import db
|
||||
from game.data.building_data import FORTIFICATION_UNITS_ID, FORTIFICATION_UNITS
|
||||
from game.db import unit_type_from_name
|
||||
from pydcs.dcs.mission import *
|
||||
from pydcs.dcs.statics import *
|
||||
from pydcs.dcs.task import (
|
||||
ActivateBeaconCommand,
|
||||
ActivateICLSCommand,
|
||||
OptAlarmState,
|
||||
)
|
||||
from pydcs.dcs.unit import Ship, Vehicle
|
||||
from pydcs.dcs.unitgroup import StaticGroup
|
||||
from .airfields import RunwayData
|
||||
from .conflictgen import *
|
||||
from .naming import *
|
||||
|
||||
from dcs.mission import *
|
||||
from dcs.statics import *
|
||||
from .radios import RadioRegistry
|
||||
from .tacan import TacanBand, TacanRegistry
|
||||
|
||||
FARP_FRONTLINE_DISTANCE = 10000
|
||||
AA_CP_MIN_DISTANCE = 40000
|
||||
@ -16,10 +22,15 @@ AA_CP_MIN_DISTANCE = 40000
|
||||
class GroundObjectsGenerator:
|
||||
FARP_CAPACITY = 4
|
||||
|
||||
def __init__(self, mission: Mission, conflict: Conflict, game):
|
||||
def __init__(self, mission: Mission, conflict: Conflict, game,
|
||||
radio_registry: RadioRegistry, tacan_registry: TacanRegistry):
|
||||
self.m = mission
|
||||
self.conflict = conflict
|
||||
self.game = game
|
||||
self.radio_registry = radio_registry
|
||||
self.tacan_registry = tacan_registry
|
||||
self.icls_alloc = iter(range(1, 21))
|
||||
self.runways: Dict[str, RunwayData] = {}
|
||||
|
||||
def generate_farps(self, number_of_units=1) -> typing.Collection[StaticGroup]:
|
||||
if self.conflict.is_vector:
|
||||
@ -103,6 +114,8 @@ class GroundObjectsGenerator:
|
||||
utype = db.upgrade_to_supercarrier(utype, cp.name)
|
||||
|
||||
sg = self.m.ship_group(side, g.name, utype, position=g.position, heading=g.units[0].heading)
|
||||
atc_channel = self.radio_registry.alloc_uhf()
|
||||
sg.set_frequency(atc_channel.hertz)
|
||||
sg.units[0].name = self.m.string(g.units[0].name)
|
||||
|
||||
for i, u in enumerate(g.units):
|
||||
@ -111,6 +124,8 @@ class GroundObjectsGenerator:
|
||||
ship.position.x = u.position.x
|
||||
ship.position.y = u.position.y
|
||||
ship.heading = u.heading
|
||||
# TODO: Verify.
|
||||
ship.set_frequency(atc_channel.hertz)
|
||||
sg.add_unit(ship)
|
||||
|
||||
# Find carrier direction (In the wind)
|
||||
@ -125,10 +140,57 @@ class GroundObjectsGenerator:
|
||||
attempt = attempt + 1
|
||||
|
||||
# Set UP TACAN and ICLS
|
||||
modeChannel = "X" if not cp.tacanY else "Y"
|
||||
sg.points[0].tasks.append(ActivateBeaconCommand(channel=cp.tacanN, modechannel=modeChannel, callsign=cp.tacanI, unit_id=sg.units[0].id, aa=False))
|
||||
if ground_object.dcs_identifier == "CARRIER" and hasattr(cp, "icls"):
|
||||
sg.points[0].tasks.append(ActivateICLSCommand(cp.icls, unit_id=sg.units[0].id))
|
||||
tacan = self.tacan_registry.alloc_for_band(TacanBand.X)
|
||||
icls_channel = next(self.icls_alloc)
|
||||
# TODO: Assign these properly.
|
||||
if ground_object.dcs_identifier == "CARRIER":
|
||||
tacan_callsign = random.choice([
|
||||
"STE",
|
||||
"CVN",
|
||||
"CVH",
|
||||
"CCV",
|
||||
"ACC",
|
||||
"ARC",
|
||||
"GER",
|
||||
"ABR",
|
||||
"LIN",
|
||||
"TRU",
|
||||
])
|
||||
else:
|
||||
tacan_callsign = random.choice([
|
||||
"LHD",
|
||||
"LHA",
|
||||
"LHB",
|
||||
"LHC",
|
||||
"LHD",
|
||||
"LDS",
|
||||
])
|
||||
sg.points[0].tasks.append(ActivateBeaconCommand(
|
||||
channel=tacan.number,
|
||||
modechannel=tacan.band.value,
|
||||
callsign=tacan_callsign,
|
||||
unit_id=sg.units[0].id,
|
||||
aa=False
|
||||
))
|
||||
sg.points[0].tasks.append(ActivateICLSCommand(
|
||||
icls_channel,
|
||||
unit_id=sg.units[0].id
|
||||
))
|
||||
# TODO: Make unit name usable.
|
||||
# This relies on one control point mapping exactly
|
||||
# to one LHA, carrier, or other usable "runway".
|
||||
# This isn't wholly true, since the DD escorts of
|
||||
# the carrier group are valid for helicopters, but
|
||||
# they aren't exposed as such to the game. Should
|
||||
# clean this up so that's possible. We can't use the
|
||||
# unit name since it's an arbitrary ID.
|
||||
self.runways[cp.name] = RunwayData(
|
||||
cp.name,
|
||||
"N/A",
|
||||
atc=atc_channel,
|
||||
tacan=tacan,
|
||||
icls=icls_channel,
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
|
||||
@ -31,11 +31,10 @@ from PIL import Image, ImageDraw, ImageFont
|
||||
from tabulate import tabulate
|
||||
|
||||
from pydcs.dcs.mission import Mission
|
||||
from pydcs.dcs.terrain.terrain import Airport
|
||||
from pydcs.dcs.unittype import FlyingType
|
||||
from . import units
|
||||
from .aircraft import FlightData
|
||||
from .airfields import AIRFIELD_DATA
|
||||
from .airfields import RunwayData
|
||||
from .airsupportgen import AwacsInfo, TankerInfo
|
||||
from .radios import RadioFrequency
|
||||
|
||||
@ -135,7 +134,7 @@ class BriefingPage(KneeboardPage):
|
||||
self.airfield_info_row("Departure", self.flight.departure),
|
||||
self.airfield_info_row("Arrival", self.flight.arrival),
|
||||
self.airfield_info_row("Divert", self.flight.divert),
|
||||
], headers=["", "Airbase", "ATC", "TCN", "ILS", "RWY"])
|
||||
], headers=["", "Airbase", "ATC", "TCN", "I(C)LS", "RWY"])
|
||||
|
||||
writer.heading("Flight Plan")
|
||||
flight_plan = []
|
||||
@ -176,41 +175,30 @@ class BriefingPage(KneeboardPage):
|
||||
writer.write(path)
|
||||
|
||||
def airfield_info_row(self, row_title: str,
|
||||
airfield: Optional[Airport]) -> List[str]:
|
||||
runway: Optional[RunwayData]) -> List[str]:
|
||||
"""Creates a table row for a given airfield.
|
||||
|
||||
Args:
|
||||
row_title: Purpose of the airfield. e.g. "Departure", "Arrival" or
|
||||
"Divert".
|
||||
airfield: The airfield described by this row.
|
||||
runway: The runway described by this row.
|
||||
|
||||
Returns:
|
||||
A list of strings to be used as a row of the airfield table.
|
||||
"""
|
||||
if airfield is None:
|
||||
if runway is None:
|
||||
return [row_title, "", "", "", "", ""]
|
||||
|
||||
# TODO: Implement logic for picking preferred runway.
|
||||
runway = airfield.runways[0]
|
||||
runway_side = ["", "L", "R"][runway.leftright]
|
||||
runway_text = f"{runway.heading}{runway_side}"
|
||||
|
||||
try:
|
||||
extra_data = AIRFIELD_DATA[airfield.name]
|
||||
atc = self.format_frequency(extra_data.atc.uhf)
|
||||
tacan = extra_data.tacan or ""
|
||||
ils = extra_data.ils_freq(runway) or ""
|
||||
except KeyError:
|
||||
atc = ""
|
||||
ils = ""
|
||||
tacan = ""
|
||||
atc = ""
|
||||
if runway.atc is not None:
|
||||
atc = self.format_frequency(runway.atc)
|
||||
return [
|
||||
row_title,
|
||||
airfield.name,
|
||||
runway.airfield_name,
|
||||
atc,
|
||||
tacan,
|
||||
ils,
|
||||
runway_text,
|
||||
runway.tacan or "",
|
||||
runway.ils or runway.icls or "",
|
||||
runway.runway_name,
|
||||
]
|
||||
|
||||
def format_frequency(self, frequency: RadioFrequency) -> str:
|
||||
|
||||
@ -30,6 +30,6 @@ for t, uts in db.UNIT_BY_TASK.items():
|
||||
altitude=10000
|
||||
)
|
||||
g.task = t.name
|
||||
airgen._setup_group(g, t, 0)
|
||||
airgen._setup_group(g, t, 0, {})
|
||||
|
||||
mis.save("loadout_test.miz")
|
||||
|
||||
@ -27,7 +27,6 @@ class ControlPoint:
|
||||
full_name = None # type: str
|
||||
base = None # type: theater.base.Base
|
||||
at = None # type: db.StartPosition
|
||||
icls = 1
|
||||
allow_sea_units = True
|
||||
|
||||
connected_points = None # type: typing.List[ControlPoint]
|
||||
@ -38,7 +37,6 @@ class ControlPoint:
|
||||
frontline_offset = 0.0
|
||||
cptype: ControlPointType = None
|
||||
|
||||
ICLS_counter = 1
|
||||
alt = 0
|
||||
|
||||
def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: float,
|
||||
@ -63,10 +61,6 @@ class ControlPoint:
|
||||
self.base = theater.base.Base()
|
||||
self.cptype = cptype
|
||||
self.stances = {}
|
||||
self.tacanY = False
|
||||
self.tacanN = None
|
||||
self.tacanI = "TAC"
|
||||
self.icls = 0
|
||||
self.airport = None
|
||||
|
||||
@classmethod
|
||||
@ -81,11 +75,6 @@ class ControlPoint:
|
||||
import theater.conflicttheater
|
||||
cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1,
|
||||
has_frontline=False, cptype=ControlPointType.AIRCRAFT_CARRIER_GROUP)
|
||||
cp.tacanY = False
|
||||
cp.tacanN = random.randint(26, 49)
|
||||
cp.tacanI = random.choice(["STE", "CVN", "CVH", "CCV", "ACC", "ARC", "GER", "ABR", "LIN", "TRU"])
|
||||
ControlPoint.ICLS_counter = ControlPoint.ICLS_counter + 1
|
||||
cp.icls = ControlPoint.ICLS_counter
|
||||
return cp
|
||||
|
||||
@classmethod
|
||||
@ -93,9 +82,6 @@ class ControlPoint:
|
||||
import theater.conflicttheater
|
||||
cp = cls(id, name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1,
|
||||
has_frontline=False, cptype=ControlPointType.LHA_GROUP)
|
||||
cp.tacanY = False
|
||||
cp.tacanN = random.randint(1,25)
|
||||
cp.tacanI = random.choice(["LHD", "LHA", "LHB", "LHC", "LHD", "LDS"])
|
||||
return cp
|
||||
|
||||
@property
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user