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:
MetalStormGhost 2023-09-23 16:17:36 +03:00
parent cc3bef7937
commit c6a8673b5e
3 changed files with 156 additions and 346 deletions

View File

@ -22,11 +22,11 @@ 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,
)
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
from game.missiongenerator.missiondata import MissionData
from game.pretense.pretenseflightgroupconfigurator import (
PretenseFlightGroupConfigurator,
)
from game.radio.radios import RadioRegistry
from game.radio.tacan import TacanRegistry
from game.runways import RunwayData
@ -51,13 +51,15 @@ if TYPE_CHECKING:
PRETENSE_SQUADRON_DEF_RETRIES = 100
PRETENSE_SEAD_FLIGHTS_PER_CP = 2
PRETENSE_CAS_FLIGHTS_PER_CP = 2
PRETENSE_BAI_FLIGHTS_PER_CP = 2
PRETENSE_STRIKE_FLIGHTS_PER_CP = 2
PRETENSE_BARCAP_FLIGHTS_PER_CP = 2
PRETENSE_AI_AIRCRAFT_PER_FLIGHT = 2
PRETENSE_AI_AWACS_PER_FLIGHT = 1
PRETENSE_AI_TANKERS_PER_FLIGHT = 1
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:
@ -287,6 +289,7 @@ class PretenseAircraftGenerator:
"""
num_of_sead = 0
num_of_cas = 0
num_of_bai = 0
num_of_strike = 0
num_of_cap = 0
@ -299,6 +302,7 @@ class PretenseAircraftGenerator:
squadron.owned_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)
mission_types = squadron.auto_assignable_mission_types
aircraft_per_flight = 1
@ -328,11 +332,17 @@ class PretenseAircraftGenerator:
num_of_sead += 1
aircraft_per_flight = PRETENSE_AI_AIRCRAFT_PER_FLIGHT
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:
flight_type = FlightType.CAS
num_of_cas += 1
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 (
FlightType.STRIKE in mission_types
or FlightType.OCA_RUNWAY in mission_types
@ -421,6 +431,7 @@ class PretenseAircraftGenerator:
if squadron is not None:
squadron.owned_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)
flight = Flight(
package,
@ -461,6 +472,7 @@ class PretenseAircraftGenerator:
if squadron is not None:
squadron.owned_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)
flight = Flight(
package,
@ -501,6 +513,7 @@ class PretenseAircraftGenerator:
if squadron is not None:
squadron.owned_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)
flight = Flight(
package,
@ -548,38 +561,39 @@ class PretenseAircraftGenerator:
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 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}"
for i in range(PRETENSE_PLAYER_FLIGHTS_PER_TYPE):
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 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)
flight.state = WaitingForStart(
flight, self.game.settings, self.game.conditions.start_time
)
ato.add_package(package)
package.add_flight(flight)
flight.state = WaitingForStart(
flight, self.game.settings, self.game.conditions.start_time
)
ato.add_package(package)
return
@ -747,86 +761,62 @@ class PretenseAircraftGenerator:
self.ground_spawns,
self.mission_data,
).create_flight_group()
if flight.flight_type in [
FlightType.REFUELING,
FlightType.AEWC,
]:
self.flights.append(
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()
)
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 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
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()
logging.info(
f"Configuring flight {group.name} {flight.squadron.aircraft} {flight.flight_type}, number of players: {flight.client_count}"
)
PretenseFlightGroupConfigurator(
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()
if self.ewrj:
self._track_ewrj_flight(flight, group)

View File

@ -1,48 +1,37 @@
from __future__ import annotations
import logging
import random
from datetime import datetime
from typing import Any, Optional, TYPE_CHECKING
from dcs import Mission
from dcs.action import DoScript
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.unitgroup import FlyingGroup
from game.ato import Flight, FlightType
from game.callsigns import callsign_for_support_unit
from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum
from game.ato import Flight
from game.missiongenerator.aircraft.flightgroupconfigurator import (
FlightGroupConfigurator,
)
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
from game.missiongenerator.logisticsgenerator import LogisticsGenerator
from game.missiongenerator.missiondata import MissionData, AwacsInfo, TankerInfo
from game.radio.radios import RadioFrequency, RadioRegistry
from game.missiongenerator.missiondata import MissionData
from game.radio.radios import RadioRegistry
from game.radio.tacan import (
TacanBand,
TacanRegistry,
TacanUsage,
OutOfTacanChannelsError,
)
from game.runways import RunwayData
from game.squadrons import Pilot
from .aircraftbehavior import AircraftBehavior
from .aircraftpainter import AircraftPainter
from .flightdata import FlightData
from .waypoints import WaypointGenerator
from ...ato.flightplans.aewc import AewcFlightPlan
from ...ato.flightplans.packagerefueling import PackageRefuelingFlightPlan
from ...ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan
from ...theater import Fob
from game.missiongenerator.aircraft.aircraftbehavior import AircraftBehavior
from game.missiongenerator.aircraft.aircraftpainter import AircraftPainter
from game.missiongenerator.aircraft.flightdata import FlightData
from game.missiongenerator.aircraft.waypoints import WaypointGenerator
from game.theater import Fob
if TYPE_CHECKING:
from game import Game
class FlightGroupConfigurator:
class PretenseFlightGroupConfigurator(FlightGroupConfigurator):
def __init__(
self,
flight: Flight,
@ -57,6 +46,20 @@ class FlightGroupConfigurator:
dynamic_runways: dict[str, RunwayData],
use_client: bool,
) -> 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.group = group
self.game = game
@ -87,20 +90,6 @@ class FlightGroupConfigurator:
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(
self.flight,
self.group,
@ -147,154 +136,3 @@ class FlightGroupConfigurator:
custom_name=self.flight.custom_name,
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

View File

@ -68,6 +68,22 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
self.ground_spawns = ground_spawns
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]:
cp = self.flight.departure
name = namegen.next_pretense_aircraft_name(cp, self.flight)
@ -82,10 +98,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
try:
if self.start_type is StartType.IN_FLIGHT:
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type
].append(name)
self.insert_into_pretense(name)
group = self._generate_over_departure(name, cp)
return group
elif isinstance(cp, NavalControlPoint):
@ -96,10 +109,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
f"Carrier group {carrier_group} is a "
f"{carrier_group.__class__.__name__}, expected a ShipGroup"
)
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type
].append(name)
self.insert_into_pretense(name)
return self._generate_at_group(name, carrier_group)
elif isinstance(cp, Fob):
is_heli = self.flight.squadron.aircraft.helicopter
@ -120,33 +130,21 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
f' spawns" setting is currently disabled.'
)
if cp.has_helipads and (is_heli or is_vtol):
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][
cp_name_trimmed
][self.flight.flight_type].append(name)
self.insert_into_pretense(name)
pad_group = self._generate_at_cp_helipad(name, cp)
if pad_group is not None:
return pad_group
if cp.has_ground_spawns and (self.flight.client_count > 0 or is_heli):
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][
cp_name_trimmed
][self.flight.flight_type].append(name)
self.insert_into_pretense(name)
pad_group = self._generate_at_cp_ground_spawn(name, cp)
if pad_group is not None:
return pad_group
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type
].append(name)
self.insert_into_pretense(name)
return self._generate_over_departure(name, cp)
elif isinstance(cp, Airfield):
is_heli = self.flight.squadron.aircraft.helicopter
if cp.has_helipads and is_heli:
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][
cp_name_trimmed
][self.flight.flight_type].append(name)
self.insert_into_pretense(name)
pad_group = self._generate_at_cp_helipad(name, cp)
if pad_group is not None:
return pad_group
@ -157,17 +155,11 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
>= self.flight.count
and (self.flight.client_count > 0 or is_heli)
):
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][
cp_name_trimmed
][self.flight.flight_type].append(name)
self.insert_into_pretense(name)
pad_group = self._generate_at_cp_ground_spawn(name, cp)
if pad_group is not None:
return pad_group
if self.flight.client_count == 0:
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type
].append(name)
self.insert_into_pretense(name)
return self._generate_at_airfield(name, cp)
else:
raise NotImplementedError(
@ -186,22 +178,14 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
"No room on runway or parking slots. Starting from the air."
)
self.flight.start_type = StartType.IN_FLIGHT
self.insert_into_pretense(name)
group = self._generate_over_departure(name, cp)
return group
def generate_mid_mission(self) -> FlyingGroup[Any]:
assert isinstance(self.flight.state, InFlight)
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()
pos = self.flight.state.estimate_position()
pos += Vector2(random.randint(100, 1000), random.randint(100, 1000))
@ -223,9 +207,7 @@ class PretenseFlightGroupSpawner(FlightGroupSpawner):
alt = self.mission_data.cp_stack[cp]
self.mission_data.cp_stack[cp] += STACK_SEPARATION
self.flight.coalition.game.pretense_air[cp_side][cp_name_trimmed][
self.flight.flight_type
].append(name)
self.insert_into_pretense(name)
group = self.mission.flight_group(
country=self.country,
name=name,