Added configuration constants for flights generated for Pretense. Fixed a bug which caused only one squadron per CP to be generated. Will now not generate Pretense cargo flights from Retribution off-map spawns, but instead will generate own air spawn points for them. Added a helper function initialize_pretense_data_structures().

This commit is contained in:
MetalStormGhost 2023-09-17 11:21:43 +03:00
parent d0ff363bb5
commit aa641e1ff6
4 changed files with 92 additions and 32 deletions

View File

@ -11,6 +11,7 @@ from .ibuilder import IBuilder
from .planningerror import PlanningError from .planningerror import PlanningError
from .standard import StandardFlightPlan, StandardLayout from .standard import StandardFlightPlan, StandardLayout
from .waypointbuilder import WaypointBuilder from .waypointbuilder import WaypointBuilder
from ...theater import OffMapSpawn
if TYPE_CHECKING: if TYPE_CHECKING:
from ..flightwaypoint import FlightWaypoint from ..flightwaypoint import FlightWaypoint
@ -48,6 +49,8 @@ class Builder(IBuilder[PretenseCargoFlightPlan, FerryLayout]):
heading_from_flot = 0.0 heading_from_flot = 0.0
offmap_transport_cp_id = self.flight.departure.id offmap_transport_cp_id = self.flight.departure.id
for front_line_cp in self.coalition.game.theater.controlpoints: for front_line_cp in self.coalition.game.theater.controlpoints:
if isinstance(front_line_cp, OffMapSpawn):
continue
for front_line in self.coalition.game.theater.conflicts(): for front_line in self.coalition.game.theater.conflicts():
if front_line_cp.captured == self.flight.coalition.player: if front_line_cp.captured == self.flight.coalition.player:
if ( if (

View File

@ -27,6 +27,7 @@ from game.radio.radios import RadioRegistry
from game.radio.tacan import TacanRegistry from game.radio.tacan import TacanRegistry
from game.runways import RunwayData from game.runways import RunwayData
from game.settings import Settings from game.settings import Settings
from game.squadrons import AirWing
from game.theater.controlpoint import ( from game.theater.controlpoint import (
ControlPoint, ControlPoint,
OffMapSpawn, OffMapSpawn,
@ -42,6 +43,13 @@ if TYPE_CHECKING:
PRETENSE_SQUADRON_DEF_RETRIES = 100 PRETENSE_SQUADRON_DEF_RETRIES = 100
PRETENSE_SEAD_FLIGHTS_PER_CP = 1
PRETENSE_CAS_FLIGHTS_PER_CP = 1
PRETENSE_STRIKE_FLIGHTS_PER_CP = 1
PRETENSE_BARCAP_FLIGHTS_PER_CP = 1
PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2
PRETENSE_AI_AWACS_PER_FLIGHT = 1
PRETENSE_AI_TANKERS_PER_FLIGHT = 1
class PretenseAircraftGenerator: class PretenseAircraftGenerator:
@ -108,6 +116,8 @@ class PretenseAircraftGenerator:
fixed_wing=True, fixed_wing_stol=True, rotary_wing=False fixed_wing=True, fixed_wing_stol=True, rotary_wing=False
) )
for front_line_cp in self.game.theater.controlpoints: for front_line_cp in self.game.theater.controlpoints:
if isinstance(front_line_cp, OffMapSpawn):
continue
for front_line in self.game.theater.conflicts(): for front_line in self.game.theater.conflicts():
if front_line_cp.captured == cp.captured: if front_line_cp.captured == cp.captured:
if ( if (
@ -124,7 +134,7 @@ class PretenseAircraftGenerator:
return self.game.theater.find_control_point_by_id(offmap_transport_cp_id) return self.game.theater.find_control_point_by_id(offmap_transport_cp_id)
def should_generate_pretense_transports( def should_generate_pretense_transports(
self, cp: ControlPoint self, air_wing: AirWing
) -> tuple[bool, bool]: ) -> tuple[bool, bool]:
""" """
Returns a tuple of booleans, telling whether transport helicopter and aircraft Returns a tuple of booleans, telling whether transport helicopter and aircraft
@ -136,17 +146,16 @@ class PretenseAircraftGenerator:
""" """
autogenerate_transport_helicopter_squadron = True autogenerate_transport_helicopter_squadron = True
autogenerate_cargo_plane_squadron = True autogenerate_cargo_plane_squadron = True
for aircraft_type in cp.coalition.air_wing.squadrons: for aircraft_type in air_wing.squadrons:
for squadron in cp.coalition.air_wing.squadrons[aircraft_type]: for squadron in air_wing.squadrons[aircraft_type]:
mission_types = squadron.auto_assignable_mission_types
if squadron.aircraft.helicopter and ( if squadron.aircraft.helicopter and (
FlightType.TRANSPORT in mission_types squadron.aircraft.capable_of(FlightType.TRANSPORT)
or FlightType.AIR_ASSAULT in mission_types or squadron.aircraft.capable_of(FlightType.AIR_ASSAULT)
): ):
autogenerate_transport_helicopter_squadron = False autogenerate_transport_helicopter_squadron = False
elif not squadron.aircraft.helicopter and ( elif not squadron.aircraft.helicopter and (
FlightType.TRANSPORT in mission_types squadron.aircraft.capable_of(FlightType.TRANSPORT)
or FlightType.AIR_ASSAULT in mission_types or squadron.aircraft.capable_of(FlightType.AIR_ASSAULT)
): ):
autogenerate_cargo_plane_squadron = False autogenerate_cargo_plane_squadron = False
return ( return (
@ -181,7 +190,7 @@ class PretenseAircraftGenerator:
f"Generating a squadron definition for fixed-wing {fixed_wing} squadron at {cp}" f"Generating a squadron definition for fixed-wing {fixed_wing} squadron at {cp}"
) )
for retries in range(num_retries): for retries in range(num_retries):
if squadron_def is None or fixed_wing != squadron_def.aircraft.helicopter: if squadron_def is None or fixed_wing == squadron_def.aircraft.helicopter:
squadron_def = ( squadron_def = (
cp.coalition.air_wing.squadron_def_generator.generate_for_task( cp.coalition.air_wing.squadron_def_generator.generate_for_task(
flight_type, cp flight_type, cp
@ -200,7 +209,8 @@ class PretenseAircraftGenerator:
cp.coalition, cp.coalition,
self.game, self.game,
) )
cp.coalition.air_wing.squadrons[squadron.aircraft] = list() if squadron.aircraft not in cp.coalition.air_wing.squadrons:
cp.coalition.air_wing.squadrons[squadron.aircraft] = list()
cp.coalition.air_wing.add_squadron(squadron) cp.coalition.air_wing.add_squadron(squadron)
return return
@ -229,10 +239,11 @@ class PretenseAircraftGenerator:
if isinstance(squadron.location, OffMapSpawn): if isinstance(squadron.location, OffMapSpawn):
continue continue
squadron.owned_aircraft += 1 squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
squadron.untasked_aircraft += 1 squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
package = Package(cp, squadron.flight_db, auto_asap=False) package = Package(cp, squadron.flight_db, auto_asap=False)
mission_types = squadron.auto_assignable_mission_types mission_types = squadron.auto_assignable_mission_types
aircraft_per_flight = 1
if squadron.aircraft.helicopter and ( if squadron.aircraft.helicopter and (
FlightType.TRANSPORT in mission_types FlightType.TRANSPORT in mission_types
or FlightType.AIR_ASSAULT in mission_types or FlightType.AIR_ASSAULT in mission_types
@ -247,39 +258,54 @@ class PretenseAircraftGenerator:
FlightType.SEAD in mission_types FlightType.SEAD in mission_types
or FlightType.SEAD_SWEEP in mission_types or FlightType.SEAD_SWEEP in mission_types
or FlightType.SEAD_ESCORT in mission_types or FlightType.SEAD_ESCORT in mission_types
) and num_of_sead < 2: ) and num_of_sead < PRETENSE_SEAD_FLIGHTS_PER_CP:
flight_type = FlightType.SEAD flight_type = FlightType.SEAD
num_of_sead += 1 num_of_sead += 1
elif FlightType.DEAD in mission_types and num_of_sead < 2: aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
elif (
FlightType.DEAD in mission_types
and num_of_sead < PRETENSE_SEAD_FLIGHTS_PER_CP
):
flight_type = FlightType.DEAD flight_type = FlightType.DEAD
num_of_sead += 1 num_of_sead += 1
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
elif ( elif (
FlightType.CAS in mission_types or FlightType.BAI in mission_types FlightType.CAS in mission_types or FlightType.BAI in mission_types
) and num_of_cas < 2: ) and num_of_cas < PRETENSE_CAS_FLIGHTS_PER_CP:
flight_type = FlightType.CAS flight_type = FlightType.CAS
num_of_cas += 1 num_of_cas += 1
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
elif ( elif (
FlightType.STRIKE in mission_types FlightType.STRIKE in mission_types
or FlightType.OCA_RUNWAY in mission_types or FlightType.OCA_RUNWAY in mission_types
or FlightType.OCA_AIRCRAFT in mission_types or FlightType.OCA_AIRCRAFT in mission_types
) and num_of_strike < 2: ) and num_of_strike < PRETENSE_STRIKE_FLIGHTS_PER_CP:
flight_type = FlightType.STRIKE flight_type = FlightType.STRIKE
num_of_strike += 1 num_of_strike += 1
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
elif ( elif (
FlightType.BARCAP in mission_types FlightType.BARCAP in mission_types
or FlightType.TARCAP in mission_types or FlightType.TARCAP in mission_types
or FlightType.ESCORT in mission_types or FlightType.ESCORT in mission_types
) and num_of_cap < 2: ) and num_of_cap < PRETENSE_BARCAP_FLIGHTS_PER_CP:
flight_type = FlightType.BARCAP flight_type = FlightType.BARCAP
num_of_cap += 1 num_of_cap += 1
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
elif FlightType.AEWC in mission_types:
aircraft_per_flight = PRETENSE_AI_AWACS_PER_FLIGHT
elif FlightType.REFUELING in mission_types:
aircraft_per_flight = PRETENSE_AI_TANKERS_PER_FLIGHT
else: else:
flight_type = random.choice(list(mission_types)) flight_type = random.choice(list(mission_types))
print(
f"Generating flight of {aircraft_per_flight} for {flight_type}: {squadron.aircraft}"
)
if flight_type == FlightType.TRANSPORT: if flight_type == FlightType.TRANSPORT:
flight = Flight( flight = Flight(
package, package,
squadron, squadron,
1, aircraft_per_flight,
FlightType.PRETENSE_CARGO, FlightType.PRETENSE_CARGO,
StartType.IN_FLIGHT, StartType.IN_FLIGHT,
divert=cp, divert=cp,
@ -288,7 +314,12 @@ class PretenseAircraftGenerator:
flight.state = Navigating(flight, self.game.settings, waypoint_index=1) flight.state = Navigating(flight, self.game.settings, waypoint_index=1)
else: else:
flight = Flight( flight = Flight(
package, squadron, 1, flight_type, StartType.COLD, divert=cp package,
squadron,
aircraft_per_flight,
flight_type,
StartType.COLD,
divert=cp,
) )
package.add_flight(flight) package.add_flight(flight)
flight.state = WaitingForStart( flight.state = WaitingForStart(
@ -296,7 +327,34 @@ class PretenseAircraftGenerator:
) )
ato.add_package(package) ato.add_package(package)
return return
def initialize_pretense_data_structures(
self, cp: ControlPoint, flight: Flight
) -> None:
"""
Ensures that the data structures used to pass flight group information
to the Pretense init script lua are initialized for use in
PretenseFlightGroupSpawner and PretenseLuaGenerator.
Args:
cp: Control point to generate aircraft for.
flight: The current flight being generated.
"""
flight_type = flight.flight_type.name
cp_side = 2 if cp.captured else 1
cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()])
if cp_name_trimmed not in flight.coalition.game.pretense_air[cp_side]:
flight.coalition.game.pretense_air[cp_side][cp_name_trimmed] = {}
if (
flight_type
not in flight.coalition.game.pretense_air[cp_side][cp_name_trimmed]
):
flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
flight_type
] = list()
return
def generate_flights( def generate_flights(
self, self,
@ -319,7 +377,7 @@ class PretenseAircraftGenerator:
( (
autogenerate_transport_helicopter_squadron, autogenerate_transport_helicopter_squadron,
autogenerate_cargo_plane_squadron, autogenerate_cargo_plane_squadron,
) = self.should_generate_pretense_transports(cp) ) = self.should_generate_pretense_transports(cp.coalition.air_wing)
if autogenerate_transport_helicopter_squadron: if autogenerate_transport_helicopter_squadron:
self.generate_pretense_transport_squadron( self.generate_pretense_transport_squadron(
@ -345,6 +403,8 @@ class PretenseAircraftGenerator:
if not package.flights: if not package.flights:
continue continue
for flight in package.flights: for flight in package.flights:
self.initialize_pretense_data_structures(cp, flight)
if flight.alive: if flight.alive:
if not flight.squadron.location.runway_is_operational(): if not flight.squadron.location.runway_is_operational():
logging.warning( logging.warning(

View File

@ -75,16 +75,6 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
name = namegen.next_pretense_aircraft_name(cp, self.flight) name = namegen.next_pretense_aircraft_name(cp, self.flight)
cp_side = 2 if cp.captured else 1 cp_side = 2 if cp.captured else 1
cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()])
flight_type = self.flight.flight_type.name
if cp_name_trimmed not in self.flight.coalition.game.pretense_air[cp_side]:
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed] = {}
if (
flight_type
not in self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed]
):
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
flight_type
] = list()
try: try:
if self.start_type is StartType.IN_FLIGHT: if self.start_type is StartType.IN_FLIGHT:
@ -171,6 +161,10 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
def generate_mid_mission(self) -> FlyingGroup[Any]: def generate_mid_mission(self) -> FlyingGroup[Any]:
assert isinstance(self.flight.state, InFlight) assert isinstance(self.flight.state, InFlight)
name = namegen.next_pretense_aircraft_name(self.flight.departure, self.flight) name = namegen.next_pretense_aircraft_name(self.flight.departure, self.flight)
cp_side = 2 if self.flight.departure.captured else 1
cp_name_trimmed = "".join(
[i for i in self.flight.departure.name.lower() if i.isalnum()]
)
speed = self.flight.state.estimate_speed() speed = self.flight.state.estimate_speed()
pos = self.flight.state.estimate_position() pos = self.flight.state.estimate_position()
pos += Vector2(random.randint(100, 1000), random.randint(100, 1000)) pos += Vector2(random.randint(100, 1000), random.randint(100, 1000))
@ -192,6 +186,9 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
alt = self.mission_data.cp_stack[cp] alt = self.mission_data.cp_stack[cp]
self.mission_data.cp_stack[cp] += STACK_SEPARATION self.mission_data.cp_stack[cp] += STACK_SEPARATION
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type.name
].append(name)
group = self.mission.flight_group( group = self.mission.flight_group(
country=self.country, country=self.country,
name=name, name=name,

View File

@ -361,7 +361,7 @@ class PretenseLuaGenerator(LuaGenerator):
continue continue
cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()]) cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()])
for mission_type in self.game.pretense_air[cp_side][cp_name_trimmed]: for mission_type in self.game.pretense_air[cp_side][cp_name_trimmed]:
if mission_type == FlightType.TRANSPORT.name: if mission_type == FlightType.PRETENSE_CARGO.name:
for air_group in self.game.pretense_air[cp_side][ for air_group in self.game.pretense_air[cp_side][
cp_name_trimmed cp_name_trimmed
][mission_type]: ][mission_type]: