diff --git a/changelog.md b/changelog.md index 2bfe1b3b..6f59fdb1 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,7 @@ Saves from 11.x are not compatible with 12.0.0. ## Features/Improvements +* **[Campaign]** Removed deprecated settings for generating persistent and invulnerable AWACs and tankers. * **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3. ## Fixes diff --git a/game/missiongenerator/airsupportgenerator.py b/game/missiongenerator/airsupportgenerator.py deleted file mode 100644 index 468196d4..00000000 --- a/game/missiongenerator/airsupportgenerator.py +++ /dev/null @@ -1,210 +0,0 @@ -from __future__ import annotations - -import logging -from typing import List, TYPE_CHECKING, Tuple, Type - -from dcs.mission import Mission, StartType -from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135, PlaneType -from dcs.task import ( - AWACS, - ActivateBeaconCommand, - MainTask, - Refueling, - SetImmortalCommand, - SetInvisibleCommand, -) -from dcs.unittype import UnitType - -from game.ato import FlightType -from game.callsigns import callsign_for_support_unit -from game.naming import namegen -from game.radio.radios import RadioRegistry -from game.radio.tacan import TacanBand, TacanRegistry, TacanUsage -from game.utils import Heading -from .airconflictdescription import AirConflictDescription -from .missiondata import AwacsInfo, MissionData, TankerInfo - -if TYPE_CHECKING: - from game import Game - -TANKER_DISTANCE = 15000 -TANKER_ALT = 4572 -TANKER_HEADING_OFFSET = 45 - -AWACS_DISTANCE = 150000 -AWACS_ALT = 13000 - - -class AirSupportGenerator: - def __init__( - self, - mission: Mission, - conflict: AirConflictDescription, - game: Game, - radio_registry: RadioRegistry, - tacan_registry: TacanRegistry, - mission_data: MissionData, - ) -> None: - self.mission = mission - self.conflict = conflict - self.game = game - self.radio_registry = radio_registry - self.tacan_registry = tacan_registry - self.mission_data = mission_data - - @classmethod - def support_tasks(cls) -> List[Type[MainTask]]: - return [Refueling, AWACS] - - @staticmethod - def _get_tanker_params(unit_type: Type[UnitType]) -> Tuple[int, int]: - if unit_type is KC130: - return TANKER_ALT - 500, 596 - elif unit_type is KC_135: - return TANKER_ALT, 770 - elif unit_type is KC135MPRS: - return TANKER_ALT + 500, 596 - return TANKER_ALT, 574 - - def generate(self) -> None: - player_cp = ( - self.conflict.blue_cp - if self.conflict.blue_cp.captured - else self.conflict.red_cp - ) - - country = self.mission.country(self.game.blue.country_name) - - if not self.game.settings.disable_legacy_tanker: - fallback_tanker_number = 0 - - for i, tanker_unit_type in enumerate( - self.game.faction_for(player=True).tankers - ): - unit_type = tanker_unit_type.dcs_unit_type - if not issubclass(unit_type, PlaneType): - logging.warning(f"Refueling aircraft {unit_type} must be a plane") - continue - - # TODO: Make loiter altitude a property of the unit type. - alt, airspeed = self._get_tanker_params(tanker_unit_type.dcs_unit_type) - freq = self.radio_registry.alloc_uhf() - tacan = self.tacan_registry.alloc_for_band( - TacanBand.Y, TacanUsage.AirToAir - ) - tanker_heading = Heading.from_degrees( - self.conflict.red_cp.position.heading_between_point( - self.conflict.blue_cp.position - ) - + TANKER_HEADING_OFFSET * i - ) - tanker_position = player_cp.position.point_from_heading( - tanker_heading.degrees, TANKER_DISTANCE - ) - tanker_group = self.mission.refuel_flight( - country=country, - name=namegen.next_tanker_name(country, tanker_unit_type), - airport=None, - plane_type=unit_type, - position=tanker_position, - altitude=alt, - race_distance=58000, - frequency=freq.mhz, - start_type=StartType.Warm, - speed=airspeed, - tacanchannel=str(tacan), - ) - tanker_group.set_frequency(freq.mhz) - - callsign = callsign_for_support_unit(tanker_group) - tacan_callsign = { - "Texaco": "TEX", - "Arco": "ARC", - "Shell": "SHL", - }.get(callsign) - if tacan_callsign is None: - # The dict above is all the callsigns currently in the game, but - # non-Western countries don't use the callsigns and instead just - # use numbers. It's possible that none of those nations have - # TACAN compatible refueling aircraft, but fallback just in - # case. - tacan_callsign = f"TK{fallback_tanker_number}" - fallback_tanker_number += 1 - - if tanker_unit_type != IL_78M: - # Override PyDCS tacan channel. - tanker_group.points[0].tasks.pop() - tanker_group.points[0].tasks.append( - ActivateBeaconCommand( - tacan.number, - tacan.band.value, - tacan_callsign, - True, - tanker_group.units[0].id, - True, - ) - ) - - tanker_group.points[0].tasks.append(SetInvisibleCommand(True)) - tanker_group.points[0].tasks.append(SetImmortalCommand(True)) - - self.mission_data.tankers.append( - TankerInfo( - group_name=str(tanker_group.name), - callsign=callsign, - variant=tanker_unit_type.display_name, - freq=freq, - tacan=tacan, - start_time=None, - end_time=None, - blue=True, - ) - ) - - if not self.game.settings.disable_legacy_aewc: - possible_awacs = [ - a - for a in self.game.faction_for(player=True).aircrafts - if a.capable_of(FlightType.AEWC) - ] - - if not possible_awacs: - logging.warning("No AWACS for faction") - return - - awacs_unit = possible_awacs[0] - freq = self.radio_registry.alloc_uhf() - - unit_type = awacs_unit.dcs_unit_type - if not issubclass(unit_type, PlaneType): - logging.warning(f"AWACS aircraft {unit_type} must be a plane") - return - - awacs_flight = self.mission.awacs_flight( - country=country, - name=namegen.next_awacs_name(country), - plane_type=unit_type, - altitude=AWACS_ALT, - airport=None, - position=self.conflict.center.random_point_within( - AWACS_DISTANCE, AWACS_DISTANCE - ), - frequency=freq.mhz, - start_type=StartType.Warm, - ) - awacs_flight.set_frequency(freq.mhz) - - awacs_flight.points[0].tasks.append(SetInvisibleCommand(True)) - awacs_flight.points[0].tasks.append(SetImmortalCommand(True)) - - self.mission_data.awacs.append( - AwacsInfo( - group_name=str(awacs_flight.name), - callsign=callsign_for_support_unit(awacs_flight), - freq=freq, - depature_location=None, - start_time=None, - end_time=None, - blue=True, - ) - ) diff --git a/game/missiongenerator/briefinggenerator.py b/game/missiongenerator/briefinggenerator.py index e456d04b..e7c459c3 100644 --- a/game/missiongenerator/briefinggenerator.py +++ b/game/missiongenerator/briefinggenerator.py @@ -16,7 +16,7 @@ from game.radio.radios import RadioFrequency from game.runways import RunwayData from game.theater import ControlPoint, FrontLine from .aircraft.flightdata import FlightData -from .airsupportgenerator import AwacsInfo, TankerInfo +from .missiondata import AwacsInfo, TankerInfo from .flotgenerator import JtacInfo if TYPE_CHECKING: diff --git a/game/missiongenerator/kneeboard.py b/game/missiongenerator/kneeboard.py index b9de7d64..366fd020 100644 --- a/game/missiongenerator/kneeboard.py +++ b/game/missiongenerator/kneeboard.py @@ -46,7 +46,7 @@ from game.theater.bullseye import Bullseye from game.utils import Distance, UnitSystem, meters, mps, pounds from game.weather.weather import Weather from .aircraft.flightdata import FlightData -from .airsupportgenerator import AwacsInfo, TankerInfo +from .missiondata import AwacsInfo, TankerInfo from .briefinggenerator import CommInfo, JtacInfo, MissionInfoGenerator from ..ato import Package diff --git a/game/missiongenerator/missiongenerator.py b/game/missiongenerator/missiongenerator.py index 75d00669..513b98b0 100644 --- a/game/missiongenerator/missiongenerator.py +++ b/game/missiongenerator/missiongenerator.py @@ -24,7 +24,6 @@ from game.theater import Airfield from game.theater.bullseye import Bullseye from game.unitmap import UnitMap from .airconflictdescription import AirConflictDescription -from .airsupportgenerator import AirSupportGenerator from .briefinggenerator import BriefingGenerator, MissionInfoGenerator from .cargoshipgenerator import CargoShipGenerator from .convoygenerator import ConvoyGenerator @@ -240,17 +239,6 @@ class MissionGenerator: def generate_air_units(self, tgo_generator: TgoGenerator) -> None: """Generate the air units for the Operation""" - # Air Support (Tanker & Awacs) - air_support_generator = AirSupportGenerator( - self.mission, - AirConflictDescription.for_theater(self.game.theater), - self.game, - self.radio_registry, - self.tacan_registry, - self.mission_data, - ) - air_support_generator.generate() - # Generate Aircraft Activity on the map aircraft_generator = AircraftGenerator( self.mission, @@ -260,7 +248,7 @@ class MissionGenerator: self.radio_registry, self.tacan_registry, self.unit_map, - mission_data=air_support_generator.mission_data, + mission_data=self.mission_data, helipads=tgo_generator.helipads, ) @@ -286,7 +274,7 @@ class MissionGenerator: if not flight.client_units: continue flight.aircraft_type.assign_channels_for_flight( - flight, air_support_generator.mission_data + flight, self.mission_data ) self.mission_data.briefing_data = aircraft_generator.briefing_data diff --git a/game/settings/settings.py b/game/settings/settings.py index e75abdfe..95231eb6 100644 --- a/game/settings/settings.py +++ b/game/settings/settings.py @@ -173,30 +173,6 @@ class Settings: "extremely incomplete so does not affect all weapons." ), ) - disable_legacy_aewc: bool = boolean_option( - "Spawn invulnerable, always-available AEW&C aircraft (deprecated)", - page=CAMPAIGN_MANAGEMENT_PAGE, - section=GENERAL_SECTION, - default=True, - invert=True, - detail=( - "If checked, an invulnerable friendly AEW&C aircraft that begins the " - "mission on station will be be spawned. This behavior will be removed in a " - "future release." - ), - ) - disable_legacy_tanker: bool = boolean_option( - "Spawn invulnerable, always-available tanker aircraft (deprecated)", - page=CAMPAIGN_MANAGEMENT_PAGE, - section=GENERAL_SECTION, - default=True, - invert=True, - detail=( - "If checked, an invulnerable friendly tanker aircraft that begins the " - "mission on station will be be spawned. This behavior will be removed in a " - "future release." - ), - ) # Pilots and Squadrons ai_pilot_levelling: bool = boolean_option( "Allow AI pilot leveling",