fixes to frontline attack; frontline CAP WIP

This commit is contained in:
Vasyl Horbachenko 2018-07-17 02:14:46 +03:00 committed by Vasyl Horbachenko
parent 820820eb92
commit 932bec2f84
22 changed files with 297 additions and 63 deletions

View File

@ -73,6 +73,8 @@ PRICES = {
An_30M: 13,
Yak_40: 13,
S_3B_Tanker: 13,
IL_78M: 13,
KC_135: 13,
A_50: 8,
E_3A: 8,
@ -167,6 +169,11 @@ UNIT_BY_TASK = {
C_130,
],
Refueling: [
IL_78M,
KC_135,
],
AWACS: [E_3A, A_50, ],
PinpointStrike: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
@ -251,6 +258,7 @@ UNIT_BY_COUNTRY = {
L_39ZA,
IL_76MD,
IL_78M,
An_26B,
An_30M,
Yak_40,
@ -290,6 +298,7 @@ UNIT_BY_COUNTRY = {
A_10C,
AV8BNA,
KC_135,
S_3B_Tanker,
C_130,
E_3A,
@ -450,7 +459,11 @@ def unitdict_split(unit_dict: UnitsDict, count: int):
def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict:
return list(unitdict_split(unit_dict, total_count))[0]
groups = list(unitdict_split(unit_dict, total_count))
if len(groups) > 0:
return groups[0]
else:
return {}
def _validate_db():

View File

@ -1,5 +1,6 @@
from .event import *
from .frontlineattack import *
from .frontlinepatrol import *
from .intercept import *
from .baseattack import *
from .navalintercept import *

View File

@ -16,7 +16,7 @@ class BaseAttackEvent(Event):
STRENGTH_RECOVERY = 0.55
def __str__(self):
return "Attack from {} to {}".format(self.from_cp, self.to_cp)
return "Base attack from {} to {}".format(self.from_cp, self.to_cp)
def is_successfull(self, debriefing: Debriefing):
alive_attackers = sum([v for k, v in debriefing.alive_units[self.attacker_name].items() if db.unit_task(k) == PinpointStrike])

View File

@ -16,7 +16,7 @@ class FrontlineAttackEvent(Event):
ATTACKER_AMOUNT_FACTOR = 0.4
ATTACKER_DEFENDER_FACTOR = 0.7
STRENGTH_INFLUENCE = 0.3
SUCCESS_MIN_TARGETS = 3
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.25
defenders = None # type: db.ArmorDict
@ -35,9 +35,9 @@ class FrontlineAttackEvent(Event):
destroyed_targets += count
if self.from_cp.captured:
return float(destroyed_targets) >= min(self.SUCCESS_MIN_TARGETS, total_targets)
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
else:
return float(destroyed_targets) < min(self.SUCCESS_MIN_TARGETS, total_targets)
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE
def commit(self, debriefing: Debriefing):
super(FrontlineAttackEvent, self).commit(debriefing)

View File

@ -0,0 +1,72 @@
import math
import random
from dcs.task import *
from dcs.vehicles import AirDefence
from game import *
from game.event import *
from game.operation.frontlinepatrol import FrontlinePatrolOperation
from userdata.debriefing import Debriefing
class FrontlinePatrolEvent(Event):
ESCORT_FACTOR = 0.5
STRENGTH_INFLUENCE = 0.3
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.6
cas = None # type: db.PlaneDict
escort = None # type: db.PlaneDict
@property
def threat_description(self):
return "{} aircraft + ? CAS".format(self.to_cp.base.scramble_count(self.game.settings.multiplier * self.ESCORT_FACTOR, CAP))
def __str__(self):
return "Frontline CAP from {} at {}".format(self.from_cp, self.to_cp)
def is_successfull(self, debriefing: Debriefing):
total_targets = sum(self.cas.values())
destroyed_targets = 0
for unit, count in debriefing.destroyed_units[self.defender_name].items():
if unit in self.cas:
destroyed_targets += count
if self.from_cp.captured:
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
else:
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE
def commit(self, debriefing: Debriefing):
super(FrontlinePatrolEvent, self).commit(debriefing)
if self.from_cp.captured:
if self.is_successfull(debriefing):
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE)
else:
if self.is_successfull(debriefing):
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
else:
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
def skip(self):
pass
def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict):
self.cas = self.to_cp.base.scramble_cas(self.game.settings.multiplier)
self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR)
op = FrontlinePatrolOperation(game=self.game,
attacker_name=self.attacker_name,
defender_name=self.defender_name,
attacker_clients={},
defender_clients=clients,
from_cp=self.from_cp,
to_cp=self.to_cp)
op.setup(cas=self.cas,
escort=self.escort,
interceptors=interceptors)
self.operation = op

View File

@ -5,6 +5,7 @@ import math
from dcs.task import *
from dcs.vehicles import *
from gen.conflictgen import Conflict
from userdata.debriefing import Debriefing
from theater import *
@ -23,7 +24,7 @@ COMMISION_LIMITS_FACTORS = {
COMMISION_AMOUNTS_SCALE = 1.5
COMMISION_AMOUNTS_FACTORS = {
PinpointStrike: 2,
PinpointStrike: 6,
CAS: 1,
CAP: 2,
AirDefence: 0.3,
@ -31,6 +32,7 @@ COMMISION_AMOUNTS_FACTORS = {
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 25
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2
PLAYER_BASEATTACK_THRESHOLD = 0.2
"""
Various events probabilities. First key is player probabilty, second is enemy probability.
@ -47,8 +49,9 @@ Events:
"""
EVENT_PROBABILITIES = {
BaseAttackEvent: [100, 10],
InterceptEvent: [25, 10],
FrontlineAttackEvent: [100, 0],
FrontlinePatrolEvent: [1000, 0],
InterceptEvent: [25, 10],
InsurgentAttackEvent: [0, 10],
NavalInterceptEvent: [25, 10],
AntiAAStrikeEvent: [25, 10],
@ -65,7 +68,7 @@ ENEMY_BASE_STRENGTH_RECOVERY = 0.05
AWACS_BUDGET_COST = 4
# Initial budget value
PLAYER_BUDGET_INITIAL = 120
PLAYER_BUDGET_INITIAL = 170
# Base post-turn bonus value
PLAYER_BUDGET_BASE = 10
# Bonus multiplier logarithm base
@ -112,11 +115,18 @@ class Game:
continue
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
if event_class == FrontlineAttackEvent or event_class == InfantryTransportEvent or event_class == FrontlinePatrolEvent:
if not Conflict.has_frontline_between(player_cp, enemy_cp):
continue
if self._roll(player_probability, player_cp.base.strength):
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
pass
else:
self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self))
if event_class == BaseAttackEvent and enemy_cp.base.strength > PLAYER_BASEATTACK_THRESHOLD:
pass
else:
self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self))
elif self._roll(enemy_probability, enemy_cp.base.strength):
if event_class in enemy_generated_types:
continue

View File

@ -6,7 +6,7 @@ from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.awacsgen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict

View File

@ -6,7 +6,7 @@ from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.awacsgen import *
from gen.airsupportgen import *
from gen.visualgen import *
from .operation import Operation
@ -60,7 +60,7 @@ class BaseAttackOperation(Operation):
self.airgen.generate_defense(self.intercept, clients=self.defender_clients, at=self.defenders_starting_position)
self.airgen.generate_cas_strikegroup(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position)
self.airgen.generate_strikegroup_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
self.airgen.generate_attackers_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
self.visualgen.generate_target_smokes(self.to_cp)
super(BaseAttackOperation, self).generate()

View File

@ -8,7 +8,7 @@ from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.awacsgen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict

View File

@ -0,0 +1,53 @@
from itertools import zip_longest
from dcs.terrain import Terrain
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import Operation
MAX_DISTANCE_BETWEEN_GROUPS = 12000
class FrontlinePatrolOperation(Operation):
cas = None # type: db.PlaneDict
escort = None # type: db.PlaneDict
interceptors = None # type: db.PlaneDict
def setup(self, cas: db.PlaneDict, escort: db.PlaneDict, interceptors: db.PlaneDict):
self.cas = cas
self.escort = escort
self.interceptors = interceptors
def prepare(self, terrain: Terrain, is_quick: bool):
super(FrontlinePatrolOperation, self).prepare(terrain, is_quick)
self.defenders_starting_position = None
conflict = Conflict.frontline_cap_conflict(
attacker=self.mission.country(self.attacker_name),
defender=self.mission.country(self.defender_name),
from_cp=self.from_cp,
to_cp=self.to_cp,
theater=self.game.theater
)
self.initialize(mission=self.mission,
conflict=conflict)
def generate(self):
self.airgen.generate_defenders_cas(self.cas, {}, self.defenders_starting_position)
self.airgen.generate_defenders_escort(self.escort, {}, self.defenders_starting_position)
self.airgen.generate_patrol(self.interceptors, self.defender_clients, self.attackers_starting_position)
# todo: generate armor
super(FrontlinePatrolOperation, self).generate()

View File

@ -6,7 +6,7 @@ from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.awacsgen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict

View File

@ -6,7 +6,7 @@ from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.awacsgen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict

View File

@ -52,7 +52,7 @@ class InterceptOperation(Operation):
self.attackers_starting_position = ship
self.airgen.generate_transport(self.transport, self.to_cp.at)
self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients)
self.airgen.generate_defenders_escort(self.escort, clients=self.defender_clients)
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position)
super(InterceptOperation, self).generate()

View File

@ -18,7 +18,7 @@ class Operation:
extra_aagen = None # type: ExtraAAConflictGenerator
shipgen = None # type: ShipGenerator
triggersgen = None # type: TriggersGenerator
awacsgen = None # type: AWACSConflictGenerator
awacsgen = None # type: AirSupportConflictGenerator
visualgen = None # type: VisualGenerator
envgen = None # type: EnvironmentGenerator
@ -52,7 +52,7 @@ class Operation:
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings)
self.aagen = AAConflictGenerator(mission, conflict)
self.shipgen = ShipGenerator(mission, conflict)
self.awacsgen = AWACSConflictGenerator(mission, conflict, self.game)
self.awacsgen = AirSupportConflictGenerator(mission, conflict, self.game)
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
self.visualgen = VisualGenerator(mission, conflict, self.game)
self.envgen = EnviromentGenerator(mission, conflict, self.game)
@ -78,9 +78,7 @@ class Operation:
def generate(self):
self.visualgen.generate()
if self.is_awacs_enabled:
self.awacsgen.generate()
self.awacsgen.generate(self.is_awacs_enabled)
self.extra_aagen.generate()
self.triggersgen.generate(self.is_quick, self.trigger_radius)

View File

@ -1,7 +1,7 @@
from .aaa import *
from .aircraft import *
from .armor import *
from .awacsgen import *
from .airsupportgen import *
from .conflictgen import *
from .shipgen import *
from .visualgen import *

View File

@ -243,13 +243,35 @@ class AircraftConflictGenerator:
waypoint = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
if self.conflict.is_vector:
group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_ALTITUDE)
group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_AIRSPEED)
group.task = CAS.name
self._setup_group(group, CAS, client_count)
self.escort_targets.append((group, group.points.index(waypoint)))
self._rtb_for(group, self.conflict.from_cp, at)
def generate_defenders_cas(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
assert len(self.escort_targets) == 0
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.defenders_side, flying_type),
side=self.conflict.defenders_side,
unit_type=flying_type,
count=count,
client_count=client_count,
at=at and at or self._group_point(self.conflict.air_defenders_location))
pos = self.conflict.air_defenders_location.point_from_heading(self.conflict.heading-90, CAP_CAS_DISTANCE)
waypoint = group.add_waypoint(pos, CAS_ALTITUDE, WARM_START_AIRSPEED)
if self.conflict.is_vector:
group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_AIRSPEED)
group.task = CAS.name
self._setup_group(group, CAS, client_count)
self.escort_targets.append((group, group.points.index(waypoint)))
self._rtb_for(group, self.conflict.to_cp, at)
def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None):
assert len(self.escort_targets) == 0
@ -271,7 +293,7 @@ class AircraftConflictGenerator:
self.escort_targets.append((group, group.points.index(wayp)))
self._rtb_for(group, self.conflict.from_cp, at)
def generate_strikegroup_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
def generate_attackers_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for g in self._generate_escort(
side=self.conflict.attackers_side,
units=attackers,
@ -281,7 +303,7 @@ class AircraftConflictGenerator:
should_orbit=True):
self._rtb_for(g, self.conflict.from_cp, at)
def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
def generate_defenders_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for g in self._generate_escort(
side=self.conflict.defenders_side,
units=escort,
@ -308,6 +330,24 @@ class AircraftConflictGenerator:
self._setup_group(group, CAP, client_count)
self._rtb_for(group, self.conflict.to_cp, at)
def generate_patrol(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_side, flying_type),
side=self.conflict.attackers_side,
unit_type=flying_type,
count=count,
client_count=client_count,
at=at and at or self._group_point(self.conflict.air_attackers_location))
waypoint = group.add_waypoint(self.conflict.position, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
if self.conflict.is_vector:
group.add_waypoint(self.conflict.tail, WARM_START_ALTITUDE, WARM_START_AIRSPEED)
group.task = CAP.name
self._setup_group(group, CAP, client_count)
self._rtb_for(group, self.conflict.from_cp, at)
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
assert len(self.escort_targets) == 0

50
gen/airsupportgen.py Normal file
View File

@ -0,0 +1,50 @@
from game import db
from .conflictgen import *
from .naming import *
from dcs.mission import *
from dcs.unitgroup import *
from dcs.unittype import *
from dcs.task import *
from dcs.terrain.terrain import NoParkingSlotError
TANKER_DISTANCE = 15000
TANKER_ALT = 10000
AWACS_DISTANCE = 150000
AWACS_ALT = 10000
class AirSupportConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game):
self.mission = mission
self.conflict = conflict
self.game = game
def generate(self, is_awacs_enabled):
tanker_unit = db.find_unittype(Refueling, self.conflict.attackers_side.name)[0]
tanker_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position)
tanker_position = self.conflict.from_cp.position.point_from_heading(tanker_heading, TANKER_DISTANCE)
self.mission.refuel_flight(
country=self.mission.country(self.game.player),
name=namegen.next_tanker_name(self.mission.country(self.game.player)),
airport=None,
plane_type=tanker_unit,
position=tanker_position,
altitude=TANKER_ALT,
frequency=140,
start_type=StartType.Warm,
)
if is_awacs_enabled:
awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side.name)[0]
self.mission.awacs_flight(
country=self.mission.country(self.game.player),
name=namegen.next_awacs_name(self.mission.country(self.game.player),),
plane_type=awacs_unit,
altitude=AWACS_ALT,
airport=None,
position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE),
frequency=251,
start_type=StartType.Warm,
)

View File

@ -1,32 +0,0 @@
from game import db
from .conflictgen import *
from .naming import *
from dcs.mission import *
from dcs.unitgroup import *
from dcs.unittype import *
from dcs.task import *
from dcs.terrain.terrain import NoParkingSlotError
AWACS_DISTANCE = 150000
AWACS_ALT = 10000
class AWACSConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game):
self.mission = mission
self.conflict = conflict
self.game = game
def generate(self):
plane = db.find_unittype(AWACS, self.conflict.attackers_side.name)[0]
self.mission.awacs_flight(
country=self.mission.country(self.game.player),
name=namegen.next_awacs_name(self.mission.country(self.game.player),),
plane_type=plane,
altitude=AWACS_ALT,
airport=None,
position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE),
frequency=251
)

View File

@ -20,6 +20,7 @@ AIR_DISTANCE = 40000
CAPTURE_AIR_ATTACKERS_DISTANCE = 25000
CAPTURE_AIR_DEFENDERS_DISTANCE = 60000
CAP_CAS_DISTANCE = 10000
GROUND_INTERCEPT_SPREAD = 5000
GROUND_DISTANCE_FACTOR = 1
@ -261,8 +262,11 @@ class Conflict:
@classmethod
def frontline_cap_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
assert cls.has_frontline_between(from_cp, to_cp)
position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater)
defenders_distance = random.randint(distance/3, distance)
attack_position = position.point_from_heading(heading, randint(0, int(distance)))
attackers_position = attack_position.point_from_heading(heading - 90, AIR_DISTANCE)
defenders_position = attack_position.point_from_heading(heading + 90, CAP_CAS_DISTANCE)
return cls(
position=position,
@ -273,10 +277,8 @@ class Conflict:
to_cp=to_cp,
attackers_side=attacker,
defenders_side=defender,
ground_attackers_location=None,
ground_defenders_location=None,
air_attackers_location=position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE),
air_defenders_location=position.point_from_heading(heading, max(AIR_DISTANCE, defenders_distance)),
air_attackers_location=attackers_position,
air_defenders_location=defenders_position,
)
@classmethod

View File

@ -15,6 +15,10 @@ class NameGenerator:
self.number += 1
return "awacs|{}|{}|0|".format(country.id, self.number)
def next_tanker_name(self, country):
self.number += 1
return "tanker|{}|{}|0|".format(country.id, self.number)
def next_carrier_name(self, country):
self.number += 1
return "carrier|{}|{}|0|".format(country.id, self.number)

View File

@ -73,7 +73,7 @@ class TriggersGenerator:
for country in coalition.countries.values():
if coalition_name == player_coalition:
for plane_group in country.plane_group + country.helicopter_group:
if plane_group.task == AWACS.name:
if plane_group.task == AWACS.name or plane_group.task == Refueling.name:
continue
regroup_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position)

View File

@ -1,9 +1,22 @@
from dcs.helicopters import helicopter_map
from ui.eventresultsmenu import *
from game import *
from game.event import *
UNITTYPES_FOR_EVENTS = {
FrontlineAttackEvent: CAS,
FrontlinePatrolEvent: CAP,
InterceptEvent: CAP,
InsurgentAttackEvent: CAS,
NavalInterceptEvent: CAS,
AntiAAStrikeEvent: CAS,
InfantryTransportEvent: Embarking,
}
class EventMenu(Menu):
aircraft_scramble_entries = None # type: typing.Dict[PlaneType , Entry]
aircraft_client_entries = None # type: typing.Dict[PlaneType, Entry]
@ -87,7 +100,14 @@ class EventMenu(Menu):
Label(self.frame, text="Client slots").grid(row=row, column=3, columnspan=2)
row += 1
filter_to = UNITTYPES_FOR_EVENTS[self.event.__class__]
for unit_type, count in self.base.aircraft.items():
if filter_to and db.unit_task(unit_type) != filter_to:
continue
if unit_type in helicopter_map and self.event.__class__ != InsurgentAttackEvent:
continue
scrable_row(unit_type, count)
if not self.base.total_planes:
@ -193,6 +213,9 @@ class EventMenu(Menu):
elif type(self.event) is FrontlineAttackEvent:
e = self.event # type: FrontlineAttackEvent
e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is FrontlinePatrolEvent:
e = self.event # type: FrontlinePatrolEvent
e.player_attacking(interceptors=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is NavalInterceptEvent:
e = self.event # type: NavalInterceptEvent