From e86fc60b4180e08f4f5f67c77b14619cea61308e Mon Sep 17 00:00:00 2001 From: Raffson Date: Sun, 9 Jul 2023 15:12:20 +0200 Subject: [PATCH] Spawn idle aircraft at helipads Applicable for helicopters at airbases & both helicopters and LHA-capable aircraft at FOBs --- changelog.md | 1 + game/ato/flight.py | 6 ++- .../aircraft/aircraftgenerator.py | 15 ++++--- .../aircraft/flightgroupspawner.py | 39 ++++++++++++++----- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/changelog.md b/changelog.md index 205da693..6a29b85f 100644 --- a/changelog.md +++ b/changelog.md @@ -52,6 +52,7 @@ * **[New Game Wizard]** Automatically invert factions when 'Invert Map' is selected. * **[Flight Plans]** Added "SEAD Sweep" flight plan, which basically reintroduces the legacy "SEAD Escort" flight plan where the flight will engage whatever it can find without actually escorting the primary flight. * **[Flight Plans]** Added SEAD capability to F-16A MLU and SEAD Escort & SEAD to F-16A. +* **[Mission Generation]** Spawn unused helicopters or LHA-capable aircraft at helipads at FOBs ## Fixes * **[New Game Wizard]** Settings would not persist when going back to a previous page (obsolete due to overhaul). diff --git a/game/ato/flight.py b/game/ato/flight.py index 54bbe498..a7670f76 100644 --- a/game/ato/flight.py +++ b/game/ato/flight.py @@ -172,9 +172,13 @@ class Flight(SidcDescribable, RadioFrequencyContainer, TacanContainer): def unit_type(self) -> AircraftType: return self.squadron.aircraft + @property + def is_lha(self) -> bool: + return self.unit_type.lha_capable + @property def is_helo(self) -> bool: - return self.unit_type.dcs_unit_type.helicopter + return self.unit_type.helicopter @property def is_hercules(self) -> bool: diff --git a/game/missiongenerator/aircraft/aircraftgenerator.py b/game/missiongenerator/aircraft/aircraftgenerator.py index 5389fb08..d4c9042c 100644 --- a/game/missiongenerator/aircraft/aircraftgenerator.py +++ b/game/missiongenerator/aircraft/aircraftgenerator.py @@ -29,6 +29,7 @@ from game.settings import Settings from game.theater.controlpoint import ( Airfield, ControlPoint, + Fob, ) from game.unitmap import UnitMap from .aircraftpainter import AircraftPainter @@ -156,10 +157,11 @@ class AircraftGenerator: self, player_country: Country, enemy_country: Country ) -> None: for control_point in self.game.theater.controlpoints: - if not isinstance(control_point, Airfield): + if not ( + isinstance(control_point, Airfield) or isinstance(control_point, Fob) + ): continue - faction = self.game.coalition_for(control_point.captured).faction if control_point.captured: country = player_country else: @@ -173,7 +175,9 @@ class AircraftGenerator: break def _spawn_unused_for(self, squadron: Squadron, country: Country) -> None: - assert isinstance(squadron.location, Airfield) + assert isinstance(squadron.location, Airfield) or isinstance( + squadron.location, Fob + ) for _ in range(squadron.untasked_aircraft): # Creating a flight even those this isn't a fragged mission lets us # reuse the existing debriefing code. @@ -198,8 +202,9 @@ class AircraftGenerator: self.ground_spawns, self.mission_data, ).create_idle_aircraft() - AircraftPainter(flight, group).apply_livery() - self.unit_map.add_aircraft(group, flight) + if group: + AircraftPainter(flight, group).apply_livery() + self.unit_map.add_aircraft(group, flight) def create_and_configure_flight( self, flight: Flight, country: Country, dynamic_runways: Dict[str, RunwayData] diff --git a/game/missiongenerator/aircraft/flightgroupspawner.py b/game/missiongenerator/aircraft/flightgroupspawner.py index 73b09ac6..a647d3c2 100644 --- a/game/missiongenerator/aircraft/flightgroupspawner.py +++ b/game/missiongenerator/aircraft/flightgroupspawner.py @@ -10,7 +10,13 @@ from dcs.planes import F_14A, Su_33 from dcs.point import PointAction from dcs.ships import KUZNECOW from dcs.terrain import NoParkingSlotError -from dcs.unitgroup import FlyingGroup, ShipGroup, StaticGroup +from dcs.unitgroup import ( + FlyingGroup, + ShipGroup, + StaticGroup, + HelicopterGroup, + PlaneGroup, +) from game.ato import Flight from game.ato.flightstate import InFlight @@ -91,15 +97,24 @@ class FlightGroupSpawner: self.flight.group_id = grp.id return grp - def create_idle_aircraft(self) -> FlyingGroup[Any]: - assert isinstance(self.flight.squadron.location, Airfield) - airfield = self.flight.squadron.location - group = self._generate_at_airfield( - name=namegen.next_aircraft_name(self.country, self.flight), - airfield=airfield, - ) - - group.uncontrolled = True + def create_idle_aircraft(self) -> Optional[FlyingGroup[Any]]: + group = None + if ( + self.flight.is_helo + or self.flight.is_lha + and isinstance(self.flight.squadron.location, Fob) + ): + group = self._generate_at_cp_helipad( + name=namegen.next_aircraft_name(self.country, self.flight), + cp=self.flight.squadron.location, + ) + elif isinstance(self.flight.squadron.location, Airfield): + group = self._generate_at_airfield( + name=namegen.next_aircraft_name(self.country, self.flight), + airfield=self.flight.squadron.location, + ) + if group: + group.uncontrolled = True return group @property @@ -330,6 +345,10 @@ class FlightGroupSpawner: if isinstance(cp, Airfield): return self._generate_at_airfield(name, cp) else: + if isinstance(group, HelicopterGroup): + self.country.helicopter_group.remove(group) + elif isinstance(group, PlaneGroup): + self.country.plane_group.remove(group) return None return group