mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Implemented generating player slots in the Pretense campaign.
This commit is contained in:
parent
95bac8ec17
commit
946d578ffb
@ -9,6 +9,7 @@ from typing import Any, Dict, List, TYPE_CHECKING, Tuple, Optional
|
||||
from dcs import Point
|
||||
from dcs.country import Country
|
||||
from dcs.mission import Mission
|
||||
from dcs.terrain import NoParkingSlotError
|
||||
from dcs.unitgroup import FlyingGroup, StaticGroup
|
||||
|
||||
from game.ato.airtaaskingorder import AirTaskingOrder
|
||||
@ -19,6 +20,7 @@ from game.ato.package import Package
|
||||
from game.ato.starttype import StartType
|
||||
from game.coalition import Coalition
|
||||
from game.data.weapons import WeaponType
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.missiongenerator.aircraft.flightdata import FlightData
|
||||
from game.missiongenerator.aircraft.flightgroupconfigurator import (
|
||||
FlightGroupConfigurator,
|
||||
@ -36,6 +38,7 @@ from game.theater.controlpoint import (
|
||||
ParkingType,
|
||||
Airfield,
|
||||
)
|
||||
from game.theater.theatergroundobject import EwrGroundObject, SamGroundObject
|
||||
from game.unitmap import UnitMap
|
||||
from game.squadrons import Squadron
|
||||
|
||||
@ -51,6 +54,7 @@ PRETENSE_BARCAP_FLIGHTS_PER_CP = 1
|
||||
PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2
|
||||
PRETENSE_AI_AWACS_PER_FLIGHT = 1
|
||||
PRETENSE_AI_TANKERS_PER_FLIGHT = 1
|
||||
PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT = 2
|
||||
|
||||
|
||||
class PretenseAircraftGenerator:
|
||||
@ -214,6 +218,49 @@ class PretenseAircraftGenerator:
|
||||
coalition.air_wing.add_squadron(squadron)
|
||||
return squadron
|
||||
|
||||
def generate_pretense_squadron_for(
|
||||
self,
|
||||
aircraft_type: AircraftType,
|
||||
cp: ControlPoint,
|
||||
coalition: Coalition,
|
||||
) -> Optional[Squadron]:
|
||||
"""
|
||||
Generates a Pretense squadron from the faction squadron definitions for the designated
|
||||
AircraftType. Use FlightType AIR_ASSAULT
|
||||
for Pretense supply helicopters and TRANSPORT for off-map cargo plane squadrons.
|
||||
"""
|
||||
|
||||
squadron_def = coalition.air_wing.squadron_def_generator.generate_for_aircraft(
|
||||
aircraft_type
|
||||
)
|
||||
flight_type = random.choice(list(squadron_def.auto_assignable_mission_types))
|
||||
if flight_type == FlightType.ESCORT and aircraft_type.helicopter:
|
||||
flight_type = FlightType.CAS
|
||||
if flight_type in (
|
||||
FlightType.INTERCEPTION,
|
||||
FlightType.ESCORT,
|
||||
FlightType.SWEEP,
|
||||
):
|
||||
flight_type = FlightType.BARCAP
|
||||
if flight_type in (FlightType.SEAD_ESCORT, FlightType.SEAD_SWEEP):
|
||||
flight_type = FlightType.SEAD
|
||||
if flight_type == FlightType.ANTISHIP:
|
||||
flight_type = FlightType.STRIKE
|
||||
if flight_type == FlightType.TRANSPORT:
|
||||
flight_type = FlightType.AIR_ASSAULT
|
||||
squadron = Squadron.create_from(
|
||||
squadron_def,
|
||||
flight_type,
|
||||
2,
|
||||
cp,
|
||||
coalition,
|
||||
self.game,
|
||||
)
|
||||
if squadron.aircraft not in coalition.air_wing.squadrons:
|
||||
coalition.air_wing.squadrons[squadron.aircraft] = list()
|
||||
coalition.air_wing.add_squadron(squadron)
|
||||
return squadron
|
||||
|
||||
def generate_pretense_aircraft(
|
||||
self, cp: ControlPoint, ato: AirTaskingOrder
|
||||
) -> None:
|
||||
@ -462,6 +509,68 @@ class PretenseAircraftGenerator:
|
||||
ato.add_package(package)
|
||||
return
|
||||
|
||||
def generate_pretense_aircraft_for_players(
|
||||
self, cp: ControlPoint, coalition: Coalition, ato: AirTaskingOrder
|
||||
) -> None:
|
||||
"""
|
||||
Plans and generates player piloted aircraft groups/packages for Pretense.
|
||||
|
||||
Aircraft generation is done by walking the control points which will be made into
|
||||
Pretense "zones" and spawning flights for different missions.
|
||||
After the flight is generated the package is added to the ATO so the flights
|
||||
can be configured.
|
||||
|
||||
Args:
|
||||
cp: Control point to generate aircraft for.
|
||||
coalition: Coalition to generate aircraft for.
|
||||
ato: The ATO to generate aircraft for.
|
||||
"""
|
||||
|
||||
aircraft_per_flight = PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT
|
||||
random_aircraft_list = list(coalition.faction.aircraft)
|
||||
random.shuffle(random_aircraft_list)
|
||||
for aircraft_type in random_aircraft_list:
|
||||
# Don't generate any player flights for non-flyable types (obviously)
|
||||
if not aircraft_type.flyable:
|
||||
continue
|
||||
if not cp.can_operate(aircraft_type):
|
||||
continue
|
||||
|
||||
squadron = self.generate_pretense_squadron_for(
|
||||
aircraft_type,
|
||||
cp,
|
||||
coalition,
|
||||
)
|
||||
if squadron is not None:
|
||||
squadron.owned_aircraft += PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT
|
||||
squadron.untasked_aircraft += PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT
|
||||
squadron.populate_for_turn_0(False)
|
||||
for pilot in squadron.pilot_pool:
|
||||
pilot.player = True
|
||||
package = Package(cp, squadron.flight_db, auto_asap=False)
|
||||
flight = Flight(
|
||||
package,
|
||||
squadron,
|
||||
aircraft_per_flight,
|
||||
squadron.primary_task,
|
||||
StartType.COLD,
|
||||
divert=cp,
|
||||
)
|
||||
for pilot in flight.roster.pilots:
|
||||
if pilot is not None:
|
||||
pilot.player = True
|
||||
print(
|
||||
f"Generated flight for {squadron.primary_task} flying {squadron.aircraft.name} at {squadron.location.name}. Pilot client count: {flight.client_count}"
|
||||
)
|
||||
|
||||
package.add_flight(flight)
|
||||
flight.state = WaitingForStart(
|
||||
flight, self.game.settings, self.game.conditions.start_time
|
||||
)
|
||||
ato.add_package(package)
|
||||
|
||||
return
|
||||
|
||||
def initialize_pretense_data_structures(self, cp: ControlPoint) -> None:
|
||||
"""
|
||||
Ensures that the data structures used to pass flight group information
|
||||
@ -531,6 +640,7 @@ class PretenseAircraftGenerator:
|
||||
"""
|
||||
self.initialize_pretense_data_structures(cp)
|
||||
|
||||
is_player = True
|
||||
if country == cp.coalition.faction.country:
|
||||
offmap_transport_cp = self.find_pretense_cargo_plane_cp(cp)
|
||||
|
||||
@ -558,7 +668,6 @@ class PretenseAircraftGenerator:
|
||||
|
||||
self.generate_pretense_aircraft(cp, ato)
|
||||
else:
|
||||
is_player = True
|
||||
coalition = (
|
||||
self.game.coalition_for(is_player)
|
||||
if country == self.game.coalition_for(is_player).faction.country
|
||||
@ -566,6 +675,11 @@ class PretenseAircraftGenerator:
|
||||
)
|
||||
self.generate_pretense_aircraft_for_other_side(cp, coalition, ato)
|
||||
|
||||
if country == self.game.coalition_for(is_player).faction.country:
|
||||
if not isinstance(cp, OffMapSpawn):
|
||||
coalition = self.game.coalition_for(is_player)
|
||||
self.generate_pretense_aircraft_for_players(cp, coalition, ato)
|
||||
|
||||
self._reserve_frequencies_and_tacan(ato)
|
||||
|
||||
def generate_packages(
|
||||
@ -590,10 +704,15 @@ class PretenseAircraftGenerator:
|
||||
)
|
||||
flight.return_pilots_and_aircraft()
|
||||
continue
|
||||
logging.info(f"Generating flight: {flight.unit_type}")
|
||||
group = self.create_and_configure_flight(
|
||||
flight, country, dynamic_runways
|
||||
logging.info(
|
||||
f"Generating flight: {flight.unit_type} for {flight.flight_type.name}"
|
||||
)
|
||||
try:
|
||||
group = self.create_and_configure_flight(
|
||||
flight, country, dynamic_runways
|
||||
)
|
||||
except NoParkingSlotError:
|
||||
return
|
||||
self.unit_map.add_aircraft(group, flight)
|
||||
|
||||
def create_and_configure_flight(
|
||||
@ -632,6 +751,67 @@ class PretenseAircraftGenerator:
|
||||
self.use_client,
|
||||
).configure()
|
||||
)
|
||||
else:
|
||||
if flight.client_count > 0:
|
||||
if flight.flight_type == FlightType.CAS:
|
||||
for conflict in self.game.theater.conflicts():
|
||||
flight.package.target = conflict
|
||||
break
|
||||
elif (
|
||||
flight.flight_type == FlightType.STRIKE
|
||||
or flight.flight_type == FlightType.BAI
|
||||
):
|
||||
for cp in self.game.theater.closest_opposing_control_points():
|
||||
if cp.coalition == flight.coalition:
|
||||
continue
|
||||
for mission_target in cp.ground_objects:
|
||||
flight.package.target = mission_target
|
||||
elif (
|
||||
flight.flight_type == FlightType.OCA_RUNWAY
|
||||
or flight.flight_type == FlightType.OCA_AIRCRAFT
|
||||
):
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.coalition == flight.coalition or not isinstance(
|
||||
cp, Airfield
|
||||
):
|
||||
continue
|
||||
flight.package.target = cp
|
||||
elif flight.flight_type == FlightType.DEAD:
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.coalition == flight.coalition:
|
||||
continue
|
||||
for ground_object in cp.ground_objects:
|
||||
is_ewr = isinstance(ground_object, EwrGroundObject)
|
||||
is_sam = isinstance(ground_object, SamGroundObject)
|
||||
|
||||
if is_ewr or is_sam:
|
||||
flight.package.target = ground_object
|
||||
elif flight.flight_type == FlightType.AIR_ASSAULT:
|
||||
for cp in self.game.theater.closest_opposing_control_points():
|
||||
if cp.coalition == flight.coalition:
|
||||
continue
|
||||
if flight.is_hercules:
|
||||
if cp.coalition == flight.coalition or not isinstance(
|
||||
cp, Airfield
|
||||
):
|
||||
continue
|
||||
flight.package.target = cp
|
||||
|
||||
FlightGroupConfigurator(
|
||||
flight,
|
||||
group,
|
||||
self.game,
|
||||
self.mission,
|
||||
self.time,
|
||||
self.radio_registry,
|
||||
self.tacan_registy,
|
||||
self.laser_code_registry,
|
||||
self.mission_data,
|
||||
dynamic_runways,
|
||||
self.use_client,
|
||||
).configure()
|
||||
# for unit in group.units:
|
||||
# unit.set_client()
|
||||
|
||||
if self.ewrj:
|
||||
self._track_ewrj_flight(flight, group)
|
||||
|
||||
@ -82,9 +82,10 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
||||
|
||||
try:
|
||||
if self.start_type is StartType.IN_FLIGHT:
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
if self.flight.client_count == 0:
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
group = self._generate_over_departure(name, cp)
|
||||
return group
|
||||
elif isinstance(cp, NavalControlPoint):
|
||||
@ -95,9 +96,10 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
||||
f"Carrier group {carrier_group} is a "
|
||||
f"{carrier_group.__class__.__name__}, expected a ShipGroup"
|
||||
)
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
if self.flight.client_count == 0:
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
return self._generate_at_group(name, carrier_group)
|
||||
elif isinstance(cp, Fob):
|
||||
is_heli = self.flight.squadron.aircraft.helicopter
|
||||
@ -125,9 +127,10 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
||||
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
||||
if pad_group is not None:
|
||||
return pad_group
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
if self.flight.client_count == 0:
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
return self._generate_over_departure(name, cp)
|
||||
elif isinstance(cp, Airfield):
|
||||
is_heli = self.flight.squadron.aircraft.helicopter
|
||||
@ -145,9 +148,10 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
||||
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
||||
if pad_group is not None:
|
||||
return pad_group
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
if self.flight.client_count == 0:
|
||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||
self.flight.flight_type.name
|
||||
].append(name)
|
||||
return self._generate_at_airfield(name, cp)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
@ -155,12 +159,19 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
||||
)
|
||||
except NoParkingSlotError:
|
||||
# Generated when there is no place on Runway or on Parking Slots
|
||||
logging.warning(
|
||||
"No room on runway or parking slots. Starting from the air."
|
||||
)
|
||||
self.flight.start_type = StartType.IN_FLIGHT
|
||||
group = self._generate_over_departure(name, cp)
|
||||
return group
|
||||
if self.flight.client_count > 0:
|
||||
# Don't generate player airstarts
|
||||
logging.warning(
|
||||
"No room on runway or parking slots. Not generating a player air-start."
|
||||
)
|
||||
raise NoParkingSlotError
|
||||
else:
|
||||
logging.warning(
|
||||
"No room on runway or parking slots. Starting from the air."
|
||||
)
|
||||
self.flight.start_type = StartType.IN_FLIGHT
|
||||
group = self._generate_over_departure(name, cp)
|
||||
return group
|
||||
|
||||
def generate_mid_mission(self) -> FlyingGroup[Any]:
|
||||
assert isinstance(self.flight.state, InFlight)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user