mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Added missing generation of AI BAI flights. Player flight groups are now generated as single-ship groups to support the Pretense missions for all players. Moved repetitive code in PretenseFlightGroupSpawner to insert_into_pretense() method. Disabled spawning of air assault statics by PretenseFlightGroupConfigurator since they are unnecessary in Pretense.
This commit is contained in:
parent
cc3bef7937
commit
c6a8673b5e
@ -22,11 +22,11 @@ from game.coalition import Coalition
|
|||||||
from game.data.weapons import WeaponType
|
from game.data.weapons import WeaponType
|
||||||
from game.dcs.aircrafttype import AircraftType
|
from game.dcs.aircrafttype import AircraftType
|
||||||
from game.missiongenerator.aircraft.flightdata import FlightData
|
from game.missiongenerator.aircraft.flightdata import FlightData
|
||||||
from game.missiongenerator.aircraft.flightgroupconfigurator import (
|
|
||||||
FlightGroupConfigurator,
|
|
||||||
)
|
|
||||||
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
|
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
|
||||||
from game.missiongenerator.missiondata import MissionData
|
from game.missiongenerator.missiondata import MissionData
|
||||||
|
from game.pretense.pretenseflightgroupconfigurator import (
|
||||||
|
PretenseFlightGroupConfigurator,
|
||||||
|
)
|
||||||
from game.radio.radios import RadioRegistry
|
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
|
||||||
@ -51,13 +51,15 @@ if TYPE_CHECKING:
|
|||||||
PRETENSE_SQUADRON_DEF_RETRIES = 100
|
PRETENSE_SQUADRON_DEF_RETRIES = 100
|
||||||
PRETENSE_SEAD_FLIGHTS_PER_CP = 2
|
PRETENSE_SEAD_FLIGHTS_PER_CP = 2
|
||||||
PRETENSE_CAS_FLIGHTS_PER_CP = 2
|
PRETENSE_CAS_FLIGHTS_PER_CP = 2
|
||||||
|
PRETENSE_BAI_FLIGHTS_PER_CP = 2
|
||||||
PRETENSE_STRIKE_FLIGHTS_PER_CP = 2
|
PRETENSE_STRIKE_FLIGHTS_PER_CP = 2
|
||||||
PRETENSE_BARCAP_FLIGHTS_PER_CP = 2
|
PRETENSE_BARCAP_FLIGHTS_PER_CP = 2
|
||||||
PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2
|
PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2
|
||||||
PRETENSE_AI_AWACS_PER_FLIGHT = 1
|
PRETENSE_AI_AWACS_PER_FLIGHT = 1
|
||||||
PRETENSE_AI_TANKERS_PER_FLIGHT = 1
|
PRETENSE_AI_TANKERS_PER_FLIGHT = 1
|
||||||
PRETENSE_AI_CARGO_PLANES_PER_SIDE = 8
|
PRETENSE_AI_CARGO_PLANES_PER_SIDE = 8
|
||||||
PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT = 2
|
PRETENSE_PLAYER_AIRCRAFT_PER_FLIGHT = 1
|
||||||
|
PRETENSE_PLAYER_FLIGHTS_PER_TYPE = 2
|
||||||
|
|
||||||
|
|
||||||
class PretenseAircraftGenerator:
|
class PretenseAircraftGenerator:
|
||||||
@ -287,6 +289,7 @@ class PretenseAircraftGenerator:
|
|||||||
"""
|
"""
|
||||||
num_of_sead = 0
|
num_of_sead = 0
|
||||||
num_of_cas = 0
|
num_of_cas = 0
|
||||||
|
num_of_bai = 0
|
||||||
num_of_strike = 0
|
num_of_strike = 0
|
||||||
num_of_cap = 0
|
num_of_cap = 0
|
||||||
|
|
||||||
@ -299,6 +302,7 @@ class PretenseAircraftGenerator:
|
|||||||
|
|
||||||
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
|
squadron.populate_for_turn_0(False)
|
||||||
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
|
aircraft_per_flight = 1
|
||||||
@ -328,11 +332,17 @@ class PretenseAircraftGenerator:
|
|||||||
num_of_sead += 1
|
num_of_sead += 1
|
||||||
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
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
|
||||||
) and num_of_cas < PRETENSE_CAS_FLIGHTS_PER_CP:
|
) 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
|
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
|
elif (
|
||||||
|
FlightType.BAI in mission_types
|
||||||
|
) and num_of_bai < PRETENSE_BAI_FLIGHTS_PER_CP:
|
||||||
|
flight_type = FlightType.BAI
|
||||||
|
num_of_bai += 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
|
||||||
@ -421,6 +431,7 @@ class PretenseAircraftGenerator:
|
|||||||
if squadron is not None:
|
if squadron is not None:
|
||||||
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
|
squadron.populate_for_turn_0(False)
|
||||||
package = Package(cp, squadron.flight_db, auto_asap=False)
|
package = Package(cp, squadron.flight_db, auto_asap=False)
|
||||||
flight = Flight(
|
flight = Flight(
|
||||||
package,
|
package,
|
||||||
@ -461,6 +472,7 @@ class PretenseAircraftGenerator:
|
|||||||
if squadron is not None:
|
if squadron is not None:
|
||||||
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
|
squadron.populate_for_turn_0(False)
|
||||||
package = Package(cp, squadron.flight_db, auto_asap=False)
|
package = Package(cp, squadron.flight_db, auto_asap=False)
|
||||||
flight = Flight(
|
flight = Flight(
|
||||||
package,
|
package,
|
||||||
@ -501,6 +513,7 @@ class PretenseAircraftGenerator:
|
|||||||
if squadron is not None:
|
if squadron is not None:
|
||||||
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.owned_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
squadron.untasked_aircraft += PRETENSE_AI_AIRCRAFT_PER_FLIGHT
|
||||||
|
squadron.populate_for_turn_0(False)
|
||||||
package = Package(cp, squadron.flight_db, auto_asap=False)
|
package = Package(cp, squadron.flight_db, auto_asap=False)
|
||||||
flight = Flight(
|
flight = Flight(
|
||||||
package,
|
package,
|
||||||
@ -548,38 +561,39 @@ class PretenseAircraftGenerator:
|
|||||||
if not cp.can_operate(aircraft_type):
|
if not cp.can_operate(aircraft_type):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
squadron = self.generate_pretense_squadron_for(
|
for i in range(PRETENSE_PLAYER_FLIGHTS_PER_TYPE):
|
||||||
aircraft_type,
|
squadron = self.generate_pretense_squadron_for(
|
||||||
cp,
|
aircraft_type,
|
||||||
coalition,
|
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 roster_pilot in flight.roster.pilots:
|
|
||||||
if roster_pilot is not None:
|
|
||||||
roster_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}"
|
|
||||||
)
|
)
|
||||||
|
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 roster_pilot in flight.roster.pilots:
|
||||||
|
if roster_pilot is not None:
|
||||||
|
roster_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)
|
package.add_flight(flight)
|
||||||
flight.state = WaitingForStart(
|
flight.state = WaitingForStart(
|
||||||
flight, self.game.settings, self.game.conditions.start_time
|
flight, self.game.settings, self.game.conditions.start_time
|
||||||
)
|
)
|
||||||
ato.add_package(package)
|
ato.add_package(package)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -747,86 +761,62 @@ class PretenseAircraftGenerator:
|
|||||||
self.ground_spawns,
|
self.ground_spawns,
|
||||||
self.mission_data,
|
self.mission_data,
|
||||||
).create_flight_group()
|
).create_flight_group()
|
||||||
if flight.flight_type in [
|
if flight.flight_type == FlightType.CAS:
|
||||||
FlightType.REFUELING,
|
for conflict in self.game.theater.conflicts():
|
||||||
FlightType.AEWC,
|
flight.package.target = conflict
|
||||||
]:
|
break
|
||||||
self.flights.append(
|
elif (
|
||||||
FlightGroupConfigurator(
|
flight.flight_type == FlightType.STRIKE
|
||||||
flight,
|
or flight.flight_type == FlightType.BAI
|
||||||
group,
|
):
|
||||||
self.game,
|
for cp in self.game.theater.closest_opposing_control_points():
|
||||||
self.mission,
|
if cp.coalition == flight.coalition:
|
||||||
self.time,
|
continue
|
||||||
self.radio_registry,
|
for mission_target in cp.ground_objects:
|
||||||
self.tacan_registy,
|
flight.package.target = mission_target
|
||||||
self.laser_code_registry,
|
elif (
|
||||||
self.mission_data,
|
flight.flight_type == FlightType.OCA_RUNWAY
|
||||||
dynamic_runways,
|
or flight.flight_type == FlightType.OCA_AIRCRAFT
|
||||||
self.use_client,
|
):
|
||||||
).configure()
|
for cp in self.game.theater.controlpoints:
|
||||||
)
|
if cp.coalition == flight.coalition or not isinstance(cp, Airfield):
|
||||||
else:
|
continue
|
||||||
if flight.client_count > 0:
|
flight.package.target = cp
|
||||||
if flight.flight_type == FlightType.CAS:
|
elif flight.flight_type == FlightType.DEAD:
|
||||||
for conflict in self.game.theater.conflicts():
|
for cp in self.game.theater.controlpoints:
|
||||||
flight.package.target = conflict
|
if cp.coalition == flight.coalition:
|
||||||
break
|
continue
|
||||||
elif (
|
for ground_object in cp.ground_objects:
|
||||||
flight.flight_type == FlightType.STRIKE
|
is_ewr = isinstance(ground_object, EwrGroundObject)
|
||||||
or flight.flight_type == FlightType.BAI
|
is_sam = isinstance(ground_object, SamGroundObject)
|
||||||
):
|
|
||||||
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:
|
if is_ewr or is_sam:
|
||||||
flight.package.target = ground_object
|
flight.package.target = ground_object
|
||||||
elif flight.flight_type == FlightType.AIR_ASSAULT:
|
elif flight.flight_type == FlightType.AIR_ASSAULT:
|
||||||
for cp in self.game.theater.closest_opposing_control_points():
|
for cp in self.game.theater.closest_opposing_control_points():
|
||||||
if cp.coalition == flight.coalition:
|
if cp.coalition == flight.coalition:
|
||||||
continue
|
continue
|
||||||
if flight.is_hercules:
|
if flight.is_hercules:
|
||||||
if cp.coalition == flight.coalition or not isinstance(
|
if cp.coalition == flight.coalition or not isinstance(cp, Airfield):
|
||||||
cp, Airfield
|
continue
|
||||||
):
|
flight.package.target = cp
|
||||||
continue
|
|
||||||
flight.package.target = cp
|
|
||||||
|
|
||||||
FlightGroupConfigurator(
|
logging.info(
|
||||||
flight,
|
f"Configuring flight {group.name} {flight.squadron.aircraft} {flight.flight_type}, number of players: {flight.client_count}"
|
||||||
group,
|
)
|
||||||
self.game,
|
PretenseFlightGroupConfigurator(
|
||||||
self.mission,
|
flight,
|
||||||
self.time,
|
group,
|
||||||
self.radio_registry,
|
self.game,
|
||||||
self.tacan_registy,
|
self.mission,
|
||||||
self.laser_code_registry,
|
self.time,
|
||||||
self.mission_data,
|
self.radio_registry,
|
||||||
dynamic_runways,
|
self.tacan_registy,
|
||||||
self.use_client,
|
self.laser_code_registry,
|
||||||
).configure()
|
self.mission_data,
|
||||||
# for unit in group.units:
|
dynamic_runways,
|
||||||
# unit.set_client()
|
self.use_client,
|
||||||
|
).configure()
|
||||||
|
|
||||||
if self.ewrj:
|
if self.ewrj:
|
||||||
self._track_ewrj_flight(flight, group)
|
self._track_ewrj_flight(flight, group)
|
||||||
|
|||||||
@ -1,48 +1,37 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import random
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Optional, TYPE_CHECKING
|
from typing import Any, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from dcs import Mission
|
from dcs import Mission
|
||||||
from dcs.action import DoScript
|
|
||||||
from dcs.flyingunit import FlyingUnit
|
from dcs.flyingunit import FlyingUnit
|
||||||
from dcs.task import OptReactOnThreat
|
|
||||||
from dcs.translation import String
|
|
||||||
from dcs.triggers import TriggerStart
|
|
||||||
from dcs.unit import Skill
|
from dcs.unit import Skill
|
||||||
from dcs.unitgroup import FlyingGroup
|
from dcs.unitgroup import FlyingGroup
|
||||||
|
|
||||||
from game.ato import Flight, FlightType
|
from game.ato import Flight
|
||||||
from game.callsigns import callsign_for_support_unit
|
from game.missiongenerator.aircraft.flightgroupconfigurator import (
|
||||||
from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum
|
FlightGroupConfigurator,
|
||||||
|
)
|
||||||
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
|
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
|
||||||
from game.missiongenerator.logisticsgenerator import LogisticsGenerator
|
from game.missiongenerator.missiondata import MissionData
|
||||||
from game.missiongenerator.missiondata import MissionData, AwacsInfo, TankerInfo
|
from game.radio.radios import RadioRegistry
|
||||||
from game.radio.radios import RadioFrequency, RadioRegistry
|
|
||||||
from game.radio.tacan import (
|
from game.radio.tacan import (
|
||||||
TacanBand,
|
|
||||||
TacanRegistry,
|
TacanRegistry,
|
||||||
TacanUsage,
|
|
||||||
OutOfTacanChannelsError,
|
|
||||||
)
|
)
|
||||||
from game.runways import RunwayData
|
from game.runways import RunwayData
|
||||||
from game.squadrons import Pilot
|
from game.squadrons import Pilot
|
||||||
from .aircraftbehavior import AircraftBehavior
|
from game.missiongenerator.aircraft.aircraftbehavior import AircraftBehavior
|
||||||
from .aircraftpainter import AircraftPainter
|
from game.missiongenerator.aircraft.aircraftpainter import AircraftPainter
|
||||||
from .flightdata import FlightData
|
from game.missiongenerator.aircraft.flightdata import FlightData
|
||||||
from .waypoints import WaypointGenerator
|
from game.missiongenerator.aircraft.waypoints import WaypointGenerator
|
||||||
from ...ato.flightplans.aewc import AewcFlightPlan
|
from game.theater import Fob
|
||||||
from ...ato.flightplans.packagerefueling import PackageRefuelingFlightPlan
|
|
||||||
from ...ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan
|
|
||||||
from ...theater import Fob
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
|
|
||||||
|
|
||||||
class FlightGroupConfigurator:
|
class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
flight: Flight,
|
flight: Flight,
|
||||||
@ -57,6 +46,20 @@ class FlightGroupConfigurator:
|
|||||||
dynamic_runways: dict[str, RunwayData],
|
dynamic_runways: dict[str, RunwayData],
|
||||||
use_client: bool,
|
use_client: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
super().__init__(
|
||||||
|
flight,
|
||||||
|
group,
|
||||||
|
game,
|
||||||
|
mission,
|
||||||
|
time,
|
||||||
|
radio_registry,
|
||||||
|
tacan_registry,
|
||||||
|
laser_code_registry,
|
||||||
|
mission_data,
|
||||||
|
dynamic_runways,
|
||||||
|
use_client,
|
||||||
|
)
|
||||||
|
|
||||||
self.flight = flight
|
self.flight = flight
|
||||||
self.group = group
|
self.group = group
|
||||||
self.game = game
|
self.game = game
|
||||||
@ -87,20 +90,6 @@ class FlightGroupConfigurator:
|
|||||||
self.game.theater, self.game.conditions, self.dynamic_runways
|
self.game.theater, self.game.conditions, self.dynamic_runways
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.flight.flight_type in [
|
|
||||||
FlightType.TRANSPORT,
|
|
||||||
FlightType.AIR_ASSAULT,
|
|
||||||
] and self.game.settings.plugin_option("ctld"):
|
|
||||||
transfer = None
|
|
||||||
if self.flight.flight_type == FlightType.TRANSPORT:
|
|
||||||
coalition = self.game.coalition_for(player=self.flight.blue)
|
|
||||||
transfer = coalition.transfers.transfer_for_flight(self.flight)
|
|
||||||
self.mission_data.logistics.append(
|
|
||||||
LogisticsGenerator(
|
|
||||||
self.flight, self.group, self.mission, self.game.settings, transfer
|
|
||||||
).generate_logistics()
|
|
||||||
)
|
|
||||||
|
|
||||||
mission_start_time, waypoints = WaypointGenerator(
|
mission_start_time, waypoints = WaypointGenerator(
|
||||||
self.flight,
|
self.flight,
|
||||||
self.group,
|
self.group,
|
||||||
@ -147,154 +136,3 @@ class FlightGroupConfigurator:
|
|||||||
custom_name=self.flight.custom_name,
|
custom_name=self.flight.custom_name,
|
||||||
laser_codes=laser_codes,
|
laser_codes=laser_codes,
|
||||||
)
|
)
|
||||||
|
|
||||||
def configure_flight_member(
|
|
||||||
self, unit: FlyingUnit, pilot: Optional[Pilot], laser_codes: list[Optional[int]]
|
|
||||||
) -> None:
|
|
||||||
player = pilot is not None and pilot.player
|
|
||||||
self.set_skill(unit, pilot)
|
|
||||||
if self.flight.loadout.has_weapon_of_type(WeaponTypeEnum.TGP) and player:
|
|
||||||
laser_codes.append(self.laser_code_registry.get_next_laser_code())
|
|
||||||
else:
|
|
||||||
laser_codes.append(None)
|
|
||||||
settings = self.flight.coalition.game.settings
|
|
||||||
if not player or not settings.plugins.get("ewrj"):
|
|
||||||
return
|
|
||||||
jammer_required = settings.plugin_option("ewrj.ecm_required")
|
|
||||||
if jammer_required:
|
|
||||||
ecm = WeaponTypeEnum.JAMMER
|
|
||||||
if not self.flight.loadout.has_weapon_of_type(ecm):
|
|
||||||
return
|
|
||||||
ewrj_menu_trigger = TriggerStart(comment=f"EWRJ-{unit.name}")
|
|
||||||
ewrj_menu_trigger.add_action(DoScript(String(f'EWJamming("{unit.name}")')))
|
|
||||||
self.mission.triggerrules.triggers.append(ewrj_menu_trigger)
|
|
||||||
self.group.points[0].tasks[0] = OptReactOnThreat(
|
|
||||||
OptReactOnThreat.Values.PassiveDefense
|
|
||||||
)
|
|
||||||
|
|
||||||
def setup_radios(self) -> RadioFrequency:
|
|
||||||
freq = self.flight.frequency
|
|
||||||
if freq is None and (freq := self.flight.package.frequency) is None:
|
|
||||||
freq = self.radio_registry.alloc_uhf()
|
|
||||||
self.flight.package.frequency = freq
|
|
||||||
if freq not in self.radio_registry.allocated_channels:
|
|
||||||
self.radio_registry.reserve(freq)
|
|
||||||
|
|
||||||
if self.flight.flight_type in {FlightType.AEWC, FlightType.REFUELING}:
|
|
||||||
self.register_air_support(freq)
|
|
||||||
elif self.flight.client_count and self.flight.squadron.radio_presets:
|
|
||||||
freq = self.flight.squadron.radio_presets["intra_flight"][0]
|
|
||||||
elif self.flight.frequency is None and self.flight.client_count:
|
|
||||||
freq = self.flight.unit_type.alloc_flight_radio(self.radio_registry)
|
|
||||||
|
|
||||||
self.group.set_frequency(freq.mhz)
|
|
||||||
return freq
|
|
||||||
|
|
||||||
def register_air_support(self, channel: RadioFrequency) -> None:
|
|
||||||
callsign = callsign_for_support_unit(self.group)
|
|
||||||
if isinstance(self.flight.flight_plan, AewcFlightPlan):
|
|
||||||
self.mission_data.awacs.append(
|
|
||||||
AwacsInfo(
|
|
||||||
group_name=str(self.group.name),
|
|
||||||
callsign=callsign,
|
|
||||||
freq=channel,
|
|
||||||
depature_location=self.flight.departure.name,
|
|
||||||
start_time=self.flight.flight_plan.patrol_start_time,
|
|
||||||
end_time=self.flight.flight_plan.patrol_end_time,
|
|
||||||
blue=self.flight.departure.captured,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif isinstance(
|
|
||||||
self.flight.flight_plan, TheaterRefuelingFlightPlan
|
|
||||||
) or isinstance(self.flight.flight_plan, PackageRefuelingFlightPlan):
|
|
||||||
tacan = self.flight.tacan
|
|
||||||
if tacan is None and self.flight.squadron.aircraft.dcs_unit_type.tacan:
|
|
||||||
try:
|
|
||||||
tacan = self.tacan_registry.alloc_for_band(
|
|
||||||
TacanBand.Y, TacanUsage.AirToAir
|
|
||||||
)
|
|
||||||
except OutOfTacanChannelsError:
|
|
||||||
tacan = random.choice(list(self.tacan_registry.allocated_channels))
|
|
||||||
else:
|
|
||||||
tacan = self.flight.tacan
|
|
||||||
self.mission_data.tankers.append(
|
|
||||||
TankerInfo(
|
|
||||||
group_name=str(self.group.name),
|
|
||||||
callsign=callsign,
|
|
||||||
variant=self.flight.unit_type.name,
|
|
||||||
freq=channel,
|
|
||||||
tacan=tacan,
|
|
||||||
start_time=self.flight.flight_plan.patrol_start_time,
|
|
||||||
end_time=self.flight.flight_plan.patrol_end_time,
|
|
||||||
blue=self.flight.departure.captured,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_skill(self, unit: FlyingUnit, pilot: Optional[Pilot]) -> None:
|
|
||||||
if pilot is None or not pilot.player:
|
|
||||||
unit.skill = self.skill_level_for(unit, pilot)
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.use_client or "Pilot #1" not in unit.name:
|
|
||||||
unit.set_client()
|
|
||||||
else:
|
|
||||||
unit.set_player()
|
|
||||||
|
|
||||||
def skill_level_for(self, unit: FlyingUnit, pilot: Optional[Pilot]) -> Skill:
|
|
||||||
if self.flight.squadron.player:
|
|
||||||
base_skill = Skill(self.game.settings.player_skill)
|
|
||||||
else:
|
|
||||||
base_skill = Skill(self.game.settings.enemy_skill)
|
|
||||||
|
|
||||||
if pilot is None:
|
|
||||||
logging.error(f"Cannot determine skill level: {unit.name} has not pilot")
|
|
||||||
return base_skill
|
|
||||||
|
|
||||||
levels = [
|
|
||||||
Skill.Average,
|
|
||||||
Skill.Good,
|
|
||||||
Skill.High,
|
|
||||||
Skill.Excellent,
|
|
||||||
]
|
|
||||||
current_level = levels.index(base_skill)
|
|
||||||
missions_for_skill_increase = 4
|
|
||||||
increase = pilot.record.missions_flown // missions_for_skill_increase
|
|
||||||
capped_increase = min(current_level + increase, len(levels) - 1)
|
|
||||||
|
|
||||||
if self.game.settings.ai_pilot_levelling:
|
|
||||||
new_level = capped_increase
|
|
||||||
else:
|
|
||||||
new_level = current_level
|
|
||||||
|
|
||||||
return levels[new_level]
|
|
||||||
|
|
||||||
def setup_props(self) -> None:
|
|
||||||
for prop_id, value in self.flight.props.items():
|
|
||||||
for unit in self.group.units:
|
|
||||||
unit.set_property(prop_id, value)
|
|
||||||
|
|
||||||
def setup_payload(self) -> None:
|
|
||||||
for p in self.group.units:
|
|
||||||
p.pylons.clear()
|
|
||||||
|
|
||||||
loadout = self.flight.loadout
|
|
||||||
if self.game.settings.restrict_weapons_by_date:
|
|
||||||
loadout = loadout.degrade_for_date(self.flight.unit_type, self.game.date)
|
|
||||||
|
|
||||||
for pylon_number, weapon in loadout.pylons.items():
|
|
||||||
if weapon is None:
|
|
||||||
continue
|
|
||||||
pylon = Pylon.for_aircraft(self.flight.unit_type, pylon_number)
|
|
||||||
pylon.equip(self.group, weapon)
|
|
||||||
|
|
||||||
def setup_fuel(self) -> None:
|
|
||||||
fuel = self.flight.state.estimate_fuel()
|
|
||||||
if fuel < 0:
|
|
||||||
logging.warning(
|
|
||||||
f"Flight {self.flight} is estimated to have no fuel at mission start. "
|
|
||||||
"This estimate does not account for external fuel tanks. Setting "
|
|
||||||
"starting fuel to 100kg."
|
|
||||||
)
|
|
||||||
fuel = 100
|
|
||||||
for unit, pilot in zip(self.group.units, self.flight.roster.pilots):
|
|
||||||
unit.fuel = fuel
|
|
||||||
|
|||||||
@ -68,6 +68,22 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
self.ground_spawns = ground_spawns
|
self.ground_spawns = ground_spawns
|
||||||
self.mission_data = mission_data
|
self.mission_data = mission_data
|
||||||
|
|
||||||
|
def insert_into_pretense(self, name: str) -> None:
|
||||||
|
cp = self.flight.departure
|
||||||
|
is_player = True
|
||||||
|
cp_side = (
|
||||||
|
2
|
||||||
|
if self.flight.coalition
|
||||||
|
== self.flight.coalition.game.coalition_for(is_player)
|
||||||
|
else 1
|
||||||
|
)
|
||||||
|
cp_name_trimmed = "".join([i for i in cp.name.lower() if i.isalnum()])
|
||||||
|
|
||||||
|
if self.flight.client_count == 0:
|
||||||
|
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
||||||
|
self.flight.flight_type
|
||||||
|
].append(name)
|
||||||
|
|
||||||
def generate_flight_at_departure(self) -> FlyingGroup[Any]:
|
def generate_flight_at_departure(self) -> FlyingGroup[Any]:
|
||||||
cp = self.flight.departure
|
cp = self.flight.departure
|
||||||
name = namegen.next_pretense_aircraft_name(cp, self.flight)
|
name = namegen.next_pretense_aircraft_name(cp, self.flight)
|
||||||
@ -82,10 +98,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if self.start_type is StartType.IN_FLIGHT:
|
if self.start_type is StartType.IN_FLIGHT:
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
|
||||||
self.flight.flight_type
|
|
||||||
].append(name)
|
|
||||||
group = self._generate_over_departure(name, cp)
|
group = self._generate_over_departure(name, cp)
|
||||||
return group
|
return group
|
||||||
elif isinstance(cp, NavalControlPoint):
|
elif isinstance(cp, NavalControlPoint):
|
||||||
@ -96,10 +109,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
f"Carrier group {carrier_group} is a "
|
f"Carrier group {carrier_group} is a "
|
||||||
f"{carrier_group.__class__.__name__}, expected a ShipGroup"
|
f"{carrier_group.__class__.__name__}, expected a ShipGroup"
|
||||||
)
|
)
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
|
||||||
self.flight.flight_type
|
|
||||||
].append(name)
|
|
||||||
return self._generate_at_group(name, carrier_group)
|
return self._generate_at_group(name, carrier_group)
|
||||||
elif isinstance(cp, Fob):
|
elif isinstance(cp, Fob):
|
||||||
is_heli = self.flight.squadron.aircraft.helicopter
|
is_heli = self.flight.squadron.aircraft.helicopter
|
||||||
@ -120,33 +130,21 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
f' spawns" setting is currently disabled.'
|
f' spawns" setting is currently disabled.'
|
||||||
)
|
)
|
||||||
if cp.has_helipads and (is_heli or is_vtol):
|
if cp.has_helipads and (is_heli or is_vtol):
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][
|
|
||||||
cp_name_trimmed
|
|
||||||
][self.flight.flight_type].append(name)
|
|
||||||
pad_group = self._generate_at_cp_helipad(name, cp)
|
pad_group = self._generate_at_cp_helipad(name, cp)
|
||||||
if pad_group is not None:
|
if pad_group is not None:
|
||||||
return pad_group
|
return pad_group
|
||||||
if cp.has_ground_spawns and (self.flight.client_count > 0 or is_heli):
|
if cp.has_ground_spawns and (self.flight.client_count > 0 or is_heli):
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][
|
|
||||||
cp_name_trimmed
|
|
||||||
][self.flight.flight_type].append(name)
|
|
||||||
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
||||||
if pad_group is not None:
|
if pad_group is not None:
|
||||||
return pad_group
|
return pad_group
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
|
||||||
self.flight.flight_type
|
|
||||||
].append(name)
|
|
||||||
return self._generate_over_departure(name, cp)
|
return self._generate_over_departure(name, cp)
|
||||||
elif isinstance(cp, Airfield):
|
elif isinstance(cp, Airfield):
|
||||||
is_heli = self.flight.squadron.aircraft.helicopter
|
is_heli = self.flight.squadron.aircraft.helicopter
|
||||||
if cp.has_helipads and is_heli:
|
if cp.has_helipads and is_heli:
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][
|
|
||||||
cp_name_trimmed
|
|
||||||
][self.flight.flight_type].append(name)
|
|
||||||
pad_group = self._generate_at_cp_helipad(name, cp)
|
pad_group = self._generate_at_cp_helipad(name, cp)
|
||||||
if pad_group is not None:
|
if pad_group is not None:
|
||||||
return pad_group
|
return pad_group
|
||||||
@ -157,17 +155,11 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
>= self.flight.count
|
>= self.flight.count
|
||||||
and (self.flight.client_count > 0 or is_heli)
|
and (self.flight.client_count > 0 or is_heli)
|
||||||
):
|
):
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][
|
|
||||||
cp_name_trimmed
|
|
||||||
][self.flight.flight_type].append(name)
|
|
||||||
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
pad_group = self._generate_at_cp_ground_spawn(name, cp)
|
||||||
if pad_group is not None:
|
if pad_group is not None:
|
||||||
return pad_group
|
return pad_group
|
||||||
if self.flight.client_count == 0:
|
self.insert_into_pretense(name)
|
||||||
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
|
|
||||||
self.flight.flight_type
|
|
||||||
].append(name)
|
|
||||||
return self._generate_at_airfield(name, cp)
|
return self._generate_at_airfield(name, cp)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
@ -186,22 +178,14 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
|
|||||||
"No room on runway or parking slots. Starting from the air."
|
"No room on runway or parking slots. Starting from the air."
|
||||||
)
|
)
|
||||||
self.flight.start_type = StartType.IN_FLIGHT
|
self.flight.start_type = StartType.IN_FLIGHT
|
||||||
|
self.insert_into_pretense(name)
|
||||||
group = self._generate_over_departure(name, cp)
|
group = self._generate_over_departure(name, cp)
|
||||||
return group
|
return group
|
||||||
|
|
||||||
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)
|
||||||
is_player = True
|
|
||||||
cp_side = (
|
|
||||||
2
|
|
||||||
if self.flight.coalition
|
|
||||||
== self.flight.coalition.game.coalition_for(is_player)
|
|
||||||
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))
|
||||||
@ -223,9 +207,7 @@ 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.insert_into_pretense(name)
|
||||||
self.flight.flight_type
|
|
||||||
].append(name)
|
|
||||||
group = self.mission.flight_group(
|
group = self.mission.flight_group(
|
||||||
country=self.country,
|
country=self.country,
|
||||||
name=name,
|
name=name,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user