From a918914431f4b181e21c42000a287acfdd6ed110 Mon Sep 17 00:00:00 2001 From: Vasyl Horbachenko Date: Sun, 9 Sep 2018 20:21:07 +0300 Subject: [PATCH] dont limit aircraft to predefined role; better scrambling screen --- game/db.py | 1 + game/event/baseattack.py | 43 +++-- game/event/event.py | 19 +++ game/event/frontlineattack.py | 24 ++- game/event/frontlinepatrol.py | 24 ++- game/event/infantrytransport.py | 18 ++- game/event/insurgentattack.py | 16 +- game/event/intercept.py | 32 ++-- game/event/navalintercept.py | 33 ++-- game/event/strike.py | 31 +++- game/game.py | 4 +- game/operation/baseattack.py | 22 +-- game/operation/frontlineattack.py | 8 +- game/operation/frontlinepatrol.py | 21 ++- game/operation/infantrytransport.py | 12 +- game/operation/insurgentattack.py | 8 +- game/operation/intercept.py | 14 +- game/operation/navalintercept.py | 16 +- game/operation/operation.py | 22 ++- game/operation/strike.py | 29 ++-- game/settings.py | 2 +- gen/aircraft.py | 2 +- gen/heli.py | 5 + theater/theatergroundobject.py | 4 + ui/eventmenu.py | 242 ++++++++-------------------- 25 files changed, 332 insertions(+), 320 deletions(-) create mode 100644 gen/heli.py diff --git a/game/db.py b/game/db.py index 374b58d8..4303bc10 100644 --- a/game/db.py +++ b/game/db.py @@ -1,4 +1,5 @@ import typing +import enum from dcs.vehicles import * from dcs.unitgroup import * diff --git a/game/event/baseattack.py b/game/event/baseattack.py index a85b4640..dc356f0c 100644 --- a/game/event/baseattack.py +++ b/game/event/baseattack.py @@ -1,13 +1,16 @@ +import typing import math import random from dcs.task import * +from dcs.unittype import UnitType from game import db from game.operation.baseattack import BaseAttackOperation from userdata.debriefing import Debriefing -from .event import Event +from .event import * +from ..operation.operation import flight_dict_from class BaseAttackEvent(Event): @@ -18,6 +21,18 @@ class BaseAttackEvent(Event): def __str__(self): return "Base attack" + @property + def tasks(self): + return [CAP, CAS, PinpointStrike] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAP: + return "Escort flight" + elif for_task == CAS: + return "CAS flight" + elif for_task == PinpointStrike: + return "Ground attack" + 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]) alive_defenders = sum([v for k, v in debriefing.alive_units[self.defender_name].items() if db.unit_task(k) == PinpointStrike]) @@ -45,7 +60,9 @@ class BaseAttackEvent(Event): if not self.is_player_attacking and self.to_cp.captured: self.to_cp.captured = False - def player_defending(self, interceptors: db.PlaneDict, clients: db.PlaneDict): + def player_defending(self, flights: ScrambledFlightsDict): + assert len(flights) == 1 and flights[CAP], "Invalid scrambled flights" + cas = self.from_cp.base.scramble_cas(self.game.settings.multiplier) escort = self.from_cp.base.scramble_sweep(self.game.settings.multiplier) attackers = self.from_cp.base.armor @@ -53,36 +70,34 @@ class BaseAttackEvent(Event): op = BaseAttackOperation(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=cas, - escort=escort, + op.setup(cas=flight_dict_from(cas), + escort=flight_dict_from(escort), + intercept=flights[CAP], attack=attackers, - intercept=interceptors, defense=self.to_cp.base.armor, aa=self.to_cp.base.aa) self.operation = op - def player_attacking(self, cas: db.PlaneDict, escort: db.PlaneDict, armor: db.ArmorDict, clients: db.PlaneDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAP] and flights[CAS] and flights[PinpointStrike] and len(flights) == 3, "Invalid flights" + op = BaseAttackOperation(game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp) defenders = self.to_cp.base.scramble_sweep(self.game.settings.multiplier) defenders.update(self.to_cp.base.scramble_cas(self.game.settings.multiplier)) - op.setup(cas=cas, - escort=escort, - attack=armor, - intercept=defenders, + op.setup(cas=flights[CAS], + escort=flights[CAP], + attack=flights[PinpointStrike], + intercept=flight_dict_from(defenders), defense=self.to_cp.base.armor, aa=self.to_cp.base.assemble_aa()) diff --git a/game/event/event.py b/game/event/event.py index 374d5903..c5bb75b8 100644 --- a/game/event/event.py +++ b/game/event/event.py @@ -1,16 +1,22 @@ +import typing import logging +from dcs.unittype import UnitType +from dcs.task import Task from dcs.unittype import UnitType from game import * from theater import * from gen.environmentgen import EnvironmentSettings +from game.operation.operation import flight_dict_from, dict_from_flight from userdata.debriefing import Debriefing from userdata import persistency DIFFICULTY_LOG_BASE = 1.1 +ScrambledFlightsDict = typing.Dict[typing.Type[Task], typing.Dict[typing.Type[UnitType], typing.Tuple[int, int]]] + class Event: silent = False @@ -44,12 +50,25 @@ class Event: def threat_description(self) -> str: return "" + def flight_name(self, for_task: typing.Type[Task]) -> str: + return "Flight" + + @property + def tasks(self) -> typing.Collection[Task]: + return [] + def bonus(self) -> int: return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE) def is_successfull(self, debriefing: Debriefing) -> bool: return self.operation.is_successfull(debriefing) + def player_attacking(self, flights: ScrambledFlightsDict): + pass + + def player_defending(self, flights: ScrambledFlightsDict): + pass + def generate(self): self.operation.is_awacs_enabled = self.is_awacs_enabled diff --git a/game/event/frontlineattack.py b/game/event/frontlineattack.py index 91d4beed..8a32b704 100644 --- a/game/event/frontlineattack.py +++ b/game/event/frontlineattack.py @@ -24,6 +24,21 @@ class FrontlineAttackEvent(Event): def threat_description(self): return "{} vehicles".format(self.to_cp.base.assemble_count()) + @property + def tasks(self) -> typing.Collection[typing.Type[Task]]: + if self.is_player_attacking: + return [CAS, PinpointStrike] + else: + return [CAP, PinpointStrike] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAS: + return "CAS flight" + elif for_task == CAP: + return "CAP flight" + elif for_task == PinpointStrike: + return "Ground attack" + def __str__(self): return "Frontline attack" @@ -54,20 +69,21 @@ class FrontlineAttackEvent(Event): if self.to_cp.captured: self.to_cp.base.affect_strength(-0.1) - def player_attacking(self, armor: db.ArmorDict, strikegroup: db.PlaneDict, clients: db.PlaneDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAS] and flights[PinpointStrike] and len(flights) == 2, "Invalid flights" + self.defenders = self.to_cp.base.assemble_attack() op = FrontlineAttackOperation(game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp) + armor = dict_from_flight(flights[PinpointStrike]) op.setup(target=self.defenders, attackers=db.unitdict_restrict_count(armor, sum(self.defenders.values())), - strikegroup=strikegroup) + strikegroup=flights[CAS]) self.operation = op diff --git a/game/event/frontlinepatrol.py b/game/event/frontlinepatrol.py index 9e0d2a7c..3f1acef0 100644 --- a/game/event/frontlinepatrol.py +++ b/game/event/frontlinepatrol.py @@ -22,6 +22,16 @@ class FrontlinePatrolEvent(Event): def threat_description(self): return "{} aircraft + ? CAS".format(self.to_cp.base.scramble_count(self.game.settings.multiplier * self.ESCORT_FACTOR, CAP)) + @property + def tasks(self): + return [CAP, PinpointStrike] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAP: + return "CAP flight" + elif for_task == PinpointStrike: + return "Ground attack" + def __str__(self): return "Frontline CAP" @@ -65,23 +75,23 @@ class FrontlinePatrolEvent(Event): def skip(self): pass - def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict, armor: db.ArmorDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAP] and flights[PinpointStrike] and len(flights) == 2, "Invalid flights" + 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=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp) defenders = self.to_cp.base.assemble_attack() - op.setup(cas=self.cas, - escort=self.escort, - interceptors=interceptors, - armor_attackers=db.unitdict_restrict_count(armor, sum(defenders.values())), + op.setup(cas=flight_dict_from(self.cas), + escort=flight_dict_from(self.escort), + interceptors=flights[CAP], + armor_attackers=db.unitdict_restrict_count(dict_from_flight(flights[PinpointStrike]), sum(defenders.values())), armor_defenders=defenders) self.operation = op diff --git a/game/event/infantrytransport.py b/game/event/infantrytransport.py index fb180513..4ca7ee9a 100644 --- a/game/event/infantrytransport.py +++ b/game/event/infantrytransport.py @@ -9,7 +9,7 @@ from game.operation.infantrytransport import InfantryTransportOperation from theater.conflicttheater import * from userdata.debriefing import Debriefing -from .event import Event +from .event import * class InfantryTransportEvent(Event): @@ -18,6 +18,14 @@ class InfantryTransportEvent(Event): def __str__(self): return "Frontline transport troops" + @property + def tasks(self): + return [Embarking] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == Embarking: + return "Transport flight" + def is_successfull(self, debriefing: Debriefing): return True @@ -29,19 +37,19 @@ class InfantryTransportEvent(Event): else: self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) - def player_attacking(self, transport: db.HeliDict, clients: db.HeliDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[Embarking] and len(flights) == 1, "Invalid flights" + op = InfantryTransportOperation( game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp ) air_defense = db.find_unittype(AirDefence, self.defender_name)[0] - op.setup(transport=transport, + op.setup(transport=flights[Embarking], aa={air_defense: 2}) self.operation = op diff --git a/game/event/insurgentattack.py b/game/event/insurgentattack.py index 4353541d..38fe5876 100644 --- a/game/event/insurgentattack.py +++ b/game/event/insurgentattack.py @@ -18,6 +18,14 @@ class InsurgentAttackEvent(Event): def threat_description(self): return "" + @property + def tasks(self): + return [CAS] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAS: + return "Ground intercept flight" + def __str__(self): return "Destroy insurgents" @@ -30,7 +38,9 @@ class InsurgentAttackEvent(Event): else: return not attackers_success - def player_defending(self, strikegroup: db.PlaneDict, clients: db.PlaneDict): + def player_defending(self, flights: ScrambledFlightsDict): + assert flights[CAS] and len(flights) == 1, "Invalid flights" + suitable_unittypes = db.find_unittype(Reconnaissance, self.attacker_name) random.shuffle(suitable_unittypes) unittypes = suitable_unittypes[:self.TARGET_VARIETY] @@ -40,12 +50,10 @@ class InsurgentAttackEvent(Event): op = InsurgentAttackOperation(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(target=self.targets, - strikegroup=strikegroup) + strikegroup=flights[CAS]) self.operation = op diff --git a/game/event/intercept.py b/game/event/intercept.py index b3d63da1..24f77cc0 100644 --- a/game/event/intercept.py +++ b/game/event/intercept.py @@ -9,7 +9,7 @@ from game.operation.intercept import InterceptOperation from theater.conflicttheater import * from userdata.debriefing import Debriefing -from .event import Event +from .event import * class InterceptEvent(Event): @@ -22,6 +22,17 @@ class InterceptEvent(Event): def __str__(self): return "Air Intercept" + @property + def tasks(self): + return [CAP] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAP: + if self.is_player_attacking: + return "Intercept flight" + else: + return "Escort flight" + def _enemy_scramble_multiplier(self) -> float: is_global = self.from_cp.is_global or self.to_cp.is_global return self.game.settings.multiplier * is_global and 0.5 or 1 @@ -57,7 +68,9 @@ class InterceptEvent(Event): if self.to_cp.captured: self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) - def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAP] and len(flights) == 1, "Invalid flights" + escort = self.to_cp.base.scramble_sweep(self._enemy_scramble_multiplier()) self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name)) @@ -67,20 +80,17 @@ class InterceptEvent(Event): op = InterceptOperation(game=self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp) - op.setup(escort=escort, + op.setup(escort=flight_dict_from(escort), transport={self.transport_unit: 1}, airdefense={airdefense_unit: self.AIRDEFENSE_COUNT}, - interceptors=interceptors) + interceptors=flights[CAP]) self.operation = op - def player_defending(self, escort: db.PlaneDict, clients: db.PlaneDict): - # TODO: even not quick mission is too quick + def player_defending(self, flights: ScrambledFlightsDict): interceptors = self.from_cp.base.scramble_interceptors(self.game.settings.multiplier) self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name)) @@ -89,14 +99,12 @@ class InterceptEvent(Event): op = InterceptOperation(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(escort=escort, + op.setup(escort=flights[CAP], transport={self.transport_unit: 1}, - interceptors=interceptors, + interceptors=flight_dict_from(interceptors), airdefense={}) self.operation = op diff --git a/game/event/navalintercept.py b/game/event/navalintercept.py index 75e253b4..a1366f46 100644 --- a/game/event/navalintercept.py +++ b/game/event/navalintercept.py @@ -9,7 +9,7 @@ from game import db from game.operation.navalintercept import NavalInterceptionOperation from userdata.debriefing import Debriefing -from .event import Event +from .event import * class NavalInterceptEvent(Event): @@ -26,6 +26,19 @@ class NavalInterceptEvent(Event): def __str__(self) -> str: return "Naval intercept" + @property + def tasks(self): + if self.is_player_attacking: + return [CAS] + else: + return [CAP] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAS: + return "Naval intercept flight" + elif for_task == CAP: + return "CAP flight" + @property def threat_description(self): s = "{} ship(s)".format(self._targets_count()) @@ -64,7 +77,9 @@ class NavalInterceptEvent(Event): if self.to_cp.captured: self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) - def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAS] and len(flights) == 1, "Invalid flights" + self.targets = { random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(), } @@ -73,19 +88,19 @@ class NavalInterceptEvent(Event): self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp ) - op.setup(strikegroup=strikegroup, + op.setup(strikegroup=flights[CAS], interceptors={}, targets=self.targets) self.operation = op - def player_defending(self, interceptors: db.PlaneDict, clients: db.PlaneDict): + def player_defending(self, flights: ScrambledFlightsDict): + assert flights[CAP] and len(flights) == 1, "Invalid flights" + self.targets = { random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(), } @@ -94,15 +109,13 @@ class NavalInterceptEvent(Event): 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 ) strikegroup = self.from_cp.base.scramble_cas(self.game.settings.multiplier) - op.setup(strikegroup=strikegroup, - interceptors=interceptors, + op.setup(strikegroup=flight_dict_from(strikegroup), + interceptors=flights[CAP], targets=self.targets) self.operation = op diff --git a/game/event/strike.py b/game/event/strike.py index 2767b6e3..9c65353d 100644 --- a/game/event/strike.py +++ b/game/event/strike.py @@ -9,7 +9,7 @@ from game.operation.strike import StrikeOperation from theater.conflicttheater import * from userdata.debriefing import Debriefing -from .event import Event +from .event import * class StrikeEvent(Event): @@ -22,25 +22,40 @@ class StrikeEvent(Event): def is_successfull(self, debriefing: Debriefing): return True + @property + def tasks(self): + if self.is_player_attacking: + return [CAP, CAS] + else: + return [CAP] + + def flight_name(self, for_task: typing.Type[Task]) -> str: + if for_task == CAP: + if self.is_player_attacking: + return "Escort flight" + else: + return "CAP flight" + elif for_task == CAS: + return "Strike flight" + def commit(self, debriefing: Debriefing): super(StrikeEvent, self).commit(debriefing) self.to_cp.base.affect_strength(-self.SINGLE_OBJECT_STRENGTH_INFLUENCE * len(debriefing.destroyed_objects)) - def player_attacking(self, strikegroup: db.PlaneDict, escort: db.PlaneDict, clients: db.PlaneDict): + def player_attacking(self, flights: ScrambledFlightsDict): + assert flights[CAP] and flights[CAS] and len(flights) == 2, "Invalid flights" + op = StrikeOperation( self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, from_cp=self.from_cp, to_cp=self.to_cp ) interceptors = self.to_cp.base.scramble_interceptors(self.game.settings.multiplier) - - op.setup(strikegroup=strikegroup, - escort=escort, - interceptors=interceptors) + op.setup(strikegroup=flights[CAS], + escort=flights[CAP], + interceptors=flight_dict_from(interceptors)) self.operation = op diff --git a/game/game.py b/game/game.py index 3046b644..9bac3b9f 100644 --- a/game/game.py +++ b/game/game.py @@ -120,7 +120,7 @@ class Game: if not Conflict.has_frontline_between(player_cp, enemy_cp): continue - if self._roll(player_probability, player_cp.base.strength): + if player_probability == 100 or self._roll(player_probability, player_cp.base.strength): if event_class == NavalInterceptEvent and enemy_cp.radials == LAND: pass else: @@ -131,7 +131,7 @@ class Game: 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): + elif enemy_probability == 100 or self._roll(enemy_probability, enemy_cp.base.strength): if event_class in enemy_generated_types: continue diff --git a/game/operation/baseattack.py b/game/operation/baseattack.py index 58bc195e..dcb6d7d9 100644 --- a/game/operation/baseattack.py +++ b/game/operation/baseattack.py @@ -9,13 +9,13 @@ from gen.triggergen import * from gen.airsupportgen import * from gen.visualgen import * -from .operation import Operation +from .operation import * class BaseAttackOperation(Operation): - cas = None # type: db.PlaneDict - escort = None # type: db.PlaneDict - intercept = None # type: db.PlaneDict + cas = None # type: FlightDict + escort = None # type: FlightDict + intercept = None # type: FlightDict attack = None # type: db.ArmorDict defense = None # type: db.ArmorDict aa = None # type: db.AirDefenseDict @@ -23,10 +23,10 @@ class BaseAttackOperation(Operation): trigger_radius = TRIGGER_RADIUS_SMALL def setup(self, - cas: db.PlaneDict, - escort: db.PlaneDict, - attack: db.ArmorDict, - intercept: db.PlaneDict, + cas: FlightDict, + escort: FlightDict, + attack: FlightDict, + intercept: FlightDict, defense: db.ArmorDict, aa: db.AirDefenseDict): self.cas = cas @@ -57,10 +57,10 @@ class BaseAttackOperation(Operation): self.armorgen.generate(self.attack, self.defense) self.aagen.generate(self.aa) - self.airgen.generate_defense(self.intercept, clients=self.defender_clients, at=self.defenders_starting_position) + self.airgen.generate_defense(*flight_arguments(self.intercept), at=self.defenders_starting_position) - self.airgen.generate_cas_strikegroup(self.cas, 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.airgen.generate_cas_strikegroup(*flight_arguments(self.cas), at=self.attackers_starting_position) + self.airgen.generate_attackers_escort(*flight_arguments(self.escort), at=self.attackers_starting_position) self.visualgen.generate_target_smokes(self.to_cp) diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index cd43f951..0a2a289b 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -12,21 +12,21 @@ from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict -from .operation import Operation +from .operation import * MAX_DISTANCE_BETWEEN_GROUPS = 12000 class FrontlineAttackOperation(Operation): + strikegroup = None # type: FlightDict attackers = None # type: db.ArmorDict - strikegroup = None # type: db.PlaneDict target = None # type: db.ArmorDict def setup(self, target: db.ArmorDict, attackers: db.ArmorDict, - strikegroup: db.PlaneDict): + strikegroup: FlightDict): self.strikegroup = strikegroup self.target = target self.attackers = attackers @@ -50,7 +50,7 @@ class FrontlineAttackOperation(Operation): def generate(self): self.armorgen.generate_vec(self.attackers, self.target) - self.airgen.generate_cas_strikegroup(self.strikegroup, clients=self.attacker_clients, at=self.attackers_starting_position) + self.airgen.generate_cas_strikegroup(*flight_arguments(self.strikegroup), at=self.attackers_starting_position) self.briefinggen.title = "Frontline CAS" self.briefinggen.description = "Provide CAS for the ground forces attacking enemy lines. Operation will be considered successful if total number of enemy units will be lower than your own by a factor of 1.5 (i.e. with 12 units from both sides, enemy forces need to be reduced to at least 8), meaning that you (and, probably, your wingmans) should concentrate on destroying the enemy units. Target base strength will be lowered as a result. Be advised that your flight will not attack anything until you explicitly tell them so by comms menu." diff --git a/game/operation/frontlinepatrol.py b/game/operation/frontlinepatrol.py index 2aa9c38f..09f2bb1d 100644 --- a/game/operation/frontlinepatrol.py +++ b/game/operation/frontlinepatrol.py @@ -12,21 +12,26 @@ from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict -from .operation import Operation +from .operation import * MAX_DISTANCE_BETWEEN_GROUPS = 12000 class FrontlinePatrolOperation(Operation): - cas = None # type: db.PlaneDict - escort = None # type: db.PlaneDict - interceptors = None # type: db.PlaneDict + cas = None # type: FlightDict + escort = None # type: FlightDict + interceptors = None # type: FlightDict armor_attackers = None # type: db.ArmorDict armor_defenders = None # type: db.ArmorDict - def setup(self, cas: db.PlaneDict, escort: db.PlaneDict, interceptors: db.PlaneDict, armor_attackers: db.ArmorDict, armor_defenders: db.ArmorDict): + def setup(self, + cas: FlightDict, + escort: FlightDict, + interceptors: FlightDict, + armor_attackers: db.ArmorDict, + armor_defenders: db.ArmorDict): self.cas = cas self.escort = escort self.interceptors = interceptors @@ -50,9 +55,9 @@ class FrontlinePatrolOperation(Operation): 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_migcap(self.interceptors, self.attacker_clients, self.attackers_starting_position) + self.airgen.generate_defenders_cas(*flight_arguments(self.cas), at=self.defenders_starting_position) + self.airgen.generate_defenders_escort(*flight_arguments(self.escort), at=self.defenders_starting_position) + self.airgen.generate_migcap(*flight_arguments(self.interceptors), at=self.attackers_starting_position) self.armorgen.generate_vec(self.armor_attackers, self.armor_defenders) diff --git a/game/operation/infantrytransport.py b/game/operation/infantrytransport.py index 32d8da0d..bdf588b0 100644 --- a/game/operation/infantrytransport.py +++ b/game/operation/infantrytransport.py @@ -10,14 +10,14 @@ from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict -from .operation import Operation +from .operation import * class InfantryTransportOperation(Operation): - transport = None # type: db.HeliDict + transport = None # type: FlightDict aa = None # type: db.AirDefenseDict - def setup(self, transport: db.HeliDict, aa: db.AirDefenseDict): + def setup(self, transport: FlightDict, aa: db.AirDefenseDict): self.transport = transport self.aa = aa @@ -36,11 +36,7 @@ class InfantryTransportOperation(Operation): conflict=conflict) def generate(self): - self.airgen.generate_passenger_transport( - helis=self.transport, - clients=self.attacker_clients, - at=self.attackers_starting_position - ) + self.airgen.generate_passenger_transport(*flight_arguments(self.transport), at=self.attackers_starting_position) self.armorgen.generate_passengers(count=6) self.aagen.generate_at_defenders_location(self.aa) diff --git a/game/operation/insurgentattack.py b/game/operation/insurgentattack.py index c528949a..dc4988eb 100644 --- a/game/operation/insurgentattack.py +++ b/game/operation/insurgentattack.py @@ -10,16 +10,16 @@ from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict -from .operation import Operation +from .operation import * class InsurgentAttackOperation(Operation): - strikegroup = None # type: db.PlaneDict + strikegroup = None # type: FlightDict target = None # type: db.ArmorDict def setup(self, target: db.ArmorDict, - strikegroup: db.PlaneDict): + strikegroup: FlightDict): self.strikegroup = strikegroup self.target = target @@ -38,7 +38,7 @@ class InsurgentAttackOperation(Operation): conflict=conflict) def generate(self): - self.airgen.generate_defense(self.strikegroup, self.defender_clients, self.defenders_starting_position) + self.airgen.generate_defense(*flight_arguments(self.strikegroup), at=self.defenders_starting_position) self.armorgen.generate(self.target, {}) self.briefinggen.title = "Destroy insurgents" diff --git a/game/operation/intercept.py b/game/operation/intercept.py index 2985a733..9ff5cd02 100644 --- a/game/operation/intercept.py +++ b/game/operation/intercept.py @@ -1,22 +1,22 @@ from dcs.terrain import Terrain from gen import * -from .operation import Operation +from .operation import * class InterceptOperation(Operation): - escort = None # type: db.PlaneDict + escort = None # type: FlightDict transport = None # type: db.PlaneDict - interceptors = None # type: db.PlaneDict + interceptors = None # type: FlightDict airdefense = None # type: db.AirDefenseDict trigger_radius = TRIGGER_RADIUS_LARGE def setup(self, - escort: db.PlaneDict, + escort: FlightDict, transport: db.PlaneDict, airdefense: db.AirDefenseDict, - interceptors: db.PlaneDict): + interceptors: FlightDict): self.escort = escort self.transport = transport self.airdefense = airdefense @@ -52,9 +52,9 @@ class InterceptOperation(Operation): self.attackers_starting_position = ship self.airgen.generate_transport(self.transport, self.to_cp.at) - self.airgen.generate_defenders_escort(self.escort, clients=self.defender_clients) + self.airgen.generate_defenders_escort(*flight_arguments(self.escort), at=self.defenders_starting_position) - self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position) + self.airgen.generate_interception(*flight_arguments(self.interceptors), at=self.attackers_starting_position) self.briefinggen.title = "Air Intercept" self.briefinggen.description = "Intercept enemy supply transport aircraft. Escort will also be present if there are available planes on the base. Operation will be considered successful if most of the targets are destroyed, lowering targets strength as a result" diff --git a/game/operation/navalintercept.py b/game/operation/navalintercept.py index aa710a58..6c9e5954 100644 --- a/game/operation/navalintercept.py +++ b/game/operation/navalintercept.py @@ -1,18 +1,18 @@ from dcs.terrain import Terrain from gen import * -from .operation import Operation +from .operation import * class NavalInterceptionOperation(Operation): - strikegroup = None # type: db.PlaneDict - interceptors = None # type: db.PlaneDict + strikegroup = None # type: FlightDict + interceptors = None # type: FlightDict targets = None # type: db.ShipDict trigger_radius = TRIGGER_RADIUS_LARGE def setup(self, - strikegroup: db.PlaneDict, - interceptors: db.PlaneDict, + strikegroup: FlightDict, + interceptors: FlightDict, targets: db.ShipDict): self.strikegroup = strikegroup self.interceptors = interceptors @@ -37,16 +37,14 @@ class NavalInterceptionOperation(Operation): target_groups = self.shipgen.generate_cargo(units=self.targets) self.airgen.generate_ship_strikegroup( - attackers=self.strikegroup, - clients=self.attacker_clients, + *flight_arguments(self.strikegroup), target_groups=target_groups, at=self.attackers_starting_position ) if self.interceptors: self.airgen.generate_defense( - defenders=self.interceptors, - clients=self.defender_clients, + *flight_arguments(self.interceptors), at=self.defenders_starting_position ) diff --git a/game/operation/operation.py b/game/operation/operation.py index 1fd70910..9edb3eae 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -1,11 +1,27 @@ -from dcs.terrain import Terrain +import typing + from dcs.lua.parse import loads +from dcs.unittype import UnitType from userdata.debriefing import * from theater import * from gen import * +FlightDict = typing.Dict[typing.Type[UnitType], typing.Tuple[int, int]] + + +def flight_arguments(fd: FlightDict) -> typing.Tuple[db.PlaneDict, db.PlaneDict]: + return {k: v1 for k, (v1, v2) in fd.items()}, {k: v2 for k, (v1, v2) in fd.items()}, + + +def flight_dict_from(d: db.PlaneDict) -> FlightDict: + return {k: (v, 0) for k, v in d.items()} + + +def dict_from_flight(fd: FlightDict) -> db.Dict: + return {k: v1 for k, (v1, v2) in fd.items()} + class Operation: attackers_starting_position = None # type: db.StartingPosition @@ -33,15 +49,11 @@ class Operation: game, attacker_name: str, defender_name: str, - attacker_clients: db.PlaneDict, - defender_clients: db.PlaneDict, from_cp: ControlPoint, to_cp: ControlPoint = None): self.game = game self.attacker_name = attacker_name self.defender_name = defender_name - self.attacker_clients = attacker_clients - self.defender_clients = defender_clients self.from_cp = from_cp self.to_cp = to_cp self.is_quick = False diff --git a/game/operation/strike.py b/game/operation/strike.py index 430235e0..48252b0c 100644 --- a/game/operation/strike.py +++ b/game/operation/strike.py @@ -10,18 +10,18 @@ from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict -from .operation import Operation +from .operation import * class StrikeOperation(Operation): - strikegroup = None # type: db.PlaneDict - escort = None # type: db.PlaneDict - interceptors = None # type: db.PlaneDict + strikegroup = None # type: FlightDict + escort = None # type: FlightDict + interceptors = None # type: FlightDict def setup(self, - strikegroup: db.PlaneDict, - escort: db.PlaneDict, - interceptors: db.PlaneDict): + strikegroup: FlightDict, + escort: FlightDict, + interceptors: FlightDict): self.strikegroup = strikegroup self.escort = escort self.interceptors = interceptors @@ -49,10 +49,10 @@ class StrikeOperation(Operation): category_counters = {} # type: typing.Dict[str, int] processed_groups = [] for object in self.to_cp.ground_objects: - if object.group_id in processed_groups: + if object.group_identifier in processed_groups: continue - processed_groups.append(object.group_id) + processed_groups.append(object.group_identifier) category_counters[object.category] = category_counters.get(object.category, 0) + 1 markpoint_name = "{}{}".format(object.name_abbrev, category_counters[object.category]) @@ -61,18 +61,13 @@ class StrikeOperation(Operation): targets.sort(key=lambda x: self.from_cp.position.distance_to_point(x[1])) - self.airgen.generate_ground_attack_strikegroup(strikegroup=self.strikegroup, + self.airgen.generate_ground_attack_strikegroup(*flight_arguments(self.strikegroup), targets=targets, - 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.airgen.generate_attackers_escort(*flight_arguments(self.escort), at=self.attackers_starting_position) - self.airgen.generate_barcap(patrol=self.interceptors, - clients={}, - at=self.defenders_starting_position) + self.airgen.generate_barcap(*flight_arguments(self.interceptors), at=self.defenders_starting_position) self.briefinggen.title = "Strike" self.briefinggen.description = "Destroy infrastructure assets and military supplies in the region. Each building destroyed will lower targets strength." diff --git a/game/settings.py b/game/settings.py index ad4fb239..0b91e164 100644 --- a/game/settings.py +++ b/game/settings.py @@ -2,7 +2,7 @@ class Settings: player_skill = "Good" enemy_skill = "Average" - only_player_takeoff = False + only_player_takeoff = True night_disabled = False multiplier = 1 sams = True diff --git a/gen/aircraft.py b/gen/aircraft.py index 12fa911d..e9244f85 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -265,7 +265,7 @@ class AircraftConflictGenerator: self.escort_targets.append((group, group.points.index(waypoint))) self._rtb_for(group, self.conflict.from_cp, at) - def generate_ground_attack_strikegroup(self, strikegroup: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], clients: db.PlaneDict, at: db.StartingPosition = None): + def generate_ground_attack_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition = None): assert len(self.escort_targets) == 0 for flying_type, count, client_count in self._split_to_groups(strikegroup, clients): diff --git a/gen/heli.py b/gen/heli.py new file mode 100644 index 00000000..dc4968c5 --- /dev/null +++ b/gen/heli.py @@ -0,0 +1,5 @@ +from .aircraft import * + + +class HelicopterConflictGenerator(AircraftConflictGenerator): + pass diff --git a/theater/theatergroundobject.py b/theater/theatergroundobject.py index 83a11fc4..1dc30230 100644 --- a/theater/theatergroundobject.py +++ b/theater/theatergroundobject.py @@ -41,6 +41,10 @@ class TheaterGroundObject: def string_identifier(self): return "{}|{}|{}|{}".format(self.category, self.cp_id, self.group_id, self.object_id) + @property + def group_identifier(self) -> str: + return "{}|{}".format(self.category, self.group_id) + @property def name_abbrev(self) -> str: return ABBREV_NAME[self.category] diff --git a/ui/eventmenu.py b/ui/eventmenu.py index 55076591..a7893cd9 100644 --- a/ui/eventmenu.py +++ b/ui/eventmenu.py @@ -7,27 +7,9 @@ from game.event import * from .styles import STYLES, RED -UNITTYPES_FOR_EVENTS = { - FrontlineAttackEvent: [[CAS, PinpointStrike], [CAP]], - FrontlinePatrolEvent: [[CAP, PinpointStrike], [CAP]], - BaseAttackEvent: [[CAP, CAS, PinpointStrike], [CAP, CAS, PinpointStrike]], - StrikeEvent: [[CAP, CAS], [CAP]], - InterceptEvent: [[CAP], [CAP]], - InsurgentAttackEvent: [[CAS], [CAP]], - NavalInterceptEvent: [[CAS], [CAP]], - InfantryTransportEvent: [[Embarking], [CAP]], -} - -AI_BAN_FOR_EVENTS = { - InfantryTransportEvent: [Embarking], - StrikeEvent: [CAS], -} - - class EventMenu(Menu): - aircraft_scramble_entries = None # type: typing.Dict[PlaneType , Entry] - aircraft_client_entries = None # type: typing.Dict[PlaneType, Entry] - armor_scramble_entries = None # type: typing.Dict[VehicleType, Entry] + scramble_entries = None # type: typing.Dict[typing.Type[Task], typing.Dict[typing.Type[UnitType], typing.Tuple[Entry, Entry]]] + error_label = None # type: Label awacs = None # type: IntVar @@ -35,9 +17,7 @@ class EventMenu(Menu): super(EventMenu, self).__init__(window, parent, game) self.event = event - self.aircraft_scramble_entries = {} - self.armor_scramble_entries = {} - self.aircraft_client_entries = {} + self.scramble_entries = {k: {} for k in self.event.tasks} if self.event.attacker_name == self.game.player: self.base = self.event.from_cp.base @@ -68,32 +48,24 @@ class EventMenu(Menu): return new_label - def scrable_row(unit_type, unit_count): + def scrable_row(task_type, unit_type, unit_count, client_slots: bool): nonlocal row Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count), **STYLES["widget"]).grid(row=row, sticky=W) scramble_entry = Entry(self.frame, width=2) scramble_entry.grid(column=1, row=row, sticky=E, padx=5) scramble_entry.insert(0, "0") - self.aircraft_scramble_entries[unit_type] = scramble_entry - Button(self.frame, text="+", command=self.scramble_half(True, unit_type), **STYLES["btn-primary"]).grid(column=2, row=row) + Button(self.frame, text="+", command=self.scramble_half(task_type, unit_type), **STYLES["btn-primary"]).grid(column=2, row=row) - client_entry = Entry(self.frame, width=2) - client_entry.grid(column=3, row=row, sticky=E, padx=5) - client_entry.insert(0, "0") - self.aircraft_client_entries[unit_type] = client_entry - Button(self.frame, text="+", command=self.client_one(unit_type), **STYLES["btn-primary"]).grid(column=4, row=row) + if client_slots: + client_entry = Entry(self.frame, width=2) + client_entry.grid(column=3, row=row, sticky=E, padx=5) + client_entry.insert(0, "0") + Button(self.frame, text="+", command=self.client_one(task_type, unit_type), **STYLES["btn-primary"]).grid(column=4, row=row) + else: + client_entry = None - row += 1 - - def scramble_armor_row(unit_type, unit_count): - nonlocal row - Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count), **STYLES["widget"]).grid(row=row, sticky=W) - scramble_entry = Entry(self.frame, width=2) - scramble_entry.insert(0, "0") - scramble_entry.grid(column=1, row=row, sticky=E, padx=5) - self.armor_scramble_entries[unit_type] = scramble_entry - Button(self.frame, text="+", command=self.scramble_half(False, unit_type),**STYLES["btn-primary"]).grid(column=2, row=row) + self.scramble_entries[task_type][unit_type] = scramble_entry, client_entry row += 1 @@ -108,84 +80,53 @@ class EventMenu(Menu): Label(self.frame, text="{}. {}".format(self.event, threat_descr), **STYLES["mission-preview"]).grid(row=row, column=0, columnspan=5, sticky=S+EW, padx=5, pady=5) row += 1 - header("Aircraft :") + Label(self.frame, text="Amount", **STYLES["widget"]).grid(row=row, column=1, columnspan=2) + Label(self.frame, text="Client slots", **STYLES["widget"]).grid(row=row, column=3, columnspan=2) + row += 1 - if self.base.aircraft: - Label(self.frame, text="Amount", **STYLES["widget"]).grid(row=row, column=1, columnspan=2) - Label(self.frame, text="Client slots", **STYLES["widget"]).grid(row=row, column=3, columnspan=2) - row += 1 + for flight_task in self.event.tasks: + header("{}:".format(self.event.flight_name(flight_task))) + if flight_task == PinpointStrike: + if not self.base.armor: + label("No units") + for t, c in self.base.armor.items(): + scrable_row(flight_task, t, c, client_slots=False) + else: + if not self.base.aircraft: + label("No units") + for t, c in self.base.aircraft.items(): + scrable_row(flight_task, t, c, client_slots=True) - filter_attackers_index = 0 if self.game.is_player_attack(self.event) else 1 - filter_to = UNITTYPES_FOR_EVENTS[self.event.__class__][filter_attackers_index] - for unit_type, count in self.base.aircraft.items(): - if filter_to and db.unit_task(unit_type) not in 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: - label("None", sticky=W) - - header("Armor :") - armor_counter = 0 - for unit_type, count in self.base.armor.items(): - if filter_to and db.unit_task(unit_type) not in filter_to: - continue - scramble_armor_row(unit_type, count) - armor_counter += 1 - - if not self.base.total_armor or armor_counter == 0: - label("None", sticky=W) - - header("Support :") + header("Support:") # Options awacs_enabled = self.game.budget >= AWACS_BUDGET_COST and NORMAL or DISABLED Checkbutton(self.frame, var=self.awacs, state=awacs_enabled, **STYLES["radiobutton"]).grid(row=row, column=0, sticky=E) Label(self.frame, text="AWACS ({}m)".format(AWACS_BUDGET_COST), **STYLES["widget"]).grid(row=row, column=3, sticky=W, padx=5, pady=5) row += 1 - header("Ready ?") + header("Ready?") self.error_label = label("") self.error_label["fg"] = RED Button(self.frame, text="Commit", command=self.start, **STYLES["btn-primary"]).grid(column=0, row=row, sticky=E, padx=5, pady=(10,10)) Button(self.frame, text="Back", command=self.dismiss, **STYLES["btn-warning"]).grid(column=3, row=row, sticky=E, padx=5, pady=(10,10)) row += 1 - def _scrambled_aircraft_count(self, unit_type: UnitType) -> int: - value = self.aircraft_scramble_entries[unit_type].get() - if value and int(value) > 0: - return min(int(value), self.base.aircraft[unit_type]) - return 0 - - def _scrambled_armor_count(self, unit_type: UnitType) -> int: - value = self.armor_scramble_entries[unit_type].get() - if value and int(value) > 0: - return min(int(value), self.base.armor[unit_type]) - return 0 - - def scramble_half(self, aircraft: bool, unit_type: UnitType) -> typing.Callable: + def scramble_half(self, task: typing.Type[UnitType], unit_type: UnitType) -> typing.Callable: def action(): - entry = None # type: Entry - total_count = 0 - if aircraft: - entry = self.aircraft_scramble_entries[unit_type] - total_count = self.base.aircraft[unit_type] - else: - entry = self.armor_scramble_entries[unit_type] - total_count = self.base.armor[unit_type] + entry = self.scramble_entries[task][unit_type][0] # type: Entry + value = entry.get() - existing_count = int(entry.get()) + total_units = self.base.total_units_of_type(unit_type) + + amount = int(value and value or "0") entry.delete(0, END) - entry.insert(0, "{}".format(int(existing_count + math.ceil(total_count/2)))) + entry.insert(0, str(amount + int(math.ceil(total_units/2)))) return action - def client_one(self, unit_type: UnitType) -> typing.Callable: + def client_one(self, task: typing.Type[Task], unit_type: UnitType) -> typing.Callable: def action(): - entry = self.aircraft_client_entries[unit_type] # type: Entry + entry = self.scramble_entries[task][unit_type][1] # type: Entry value = entry.get() amount = int(value and value or "0") entry.delete(0, END) @@ -199,94 +140,37 @@ class EventMenu(Menu): else: self.event.is_awacs_enabled = False - scrambled_aircraft = {} - scrambled_sweep = {} - scrambled_cas = {} - for unit_type, field in self.aircraft_scramble_entries.items(): - amount = self._scrambled_aircraft_count(unit_type) - if amount > 0: - task = db.unit_task(unit_type) + flights = {k: {} for k in self.event.tasks} # type: ScrambledFlightsDict + total_counts_scrambled = {} # type: typing.Dict[typing.Type[UnitType], int] - scrambled_aircraft[unit_type] = amount - if task == CAS: - scrambled_cas[unit_type] = amount - elif task == CAP: - scrambled_sweep[unit_type] = amount + def dampen_count(unit_type: typing.Type[UnitType], count: int) -> int: + nonlocal total_counts_scrambled + total_count = self.base.total_units_of_type(unit_type) - scrambled_clients = {} - for unit_type, field in self.aircraft_client_entries.items(): - value = field.get() - if value and int(value) > 0: - amount = int(value) - scrambled_clients[unit_type] = amount + total_scrambled = total_counts_scrambled.get(unit_type, 0) + dampened_value = count if count + total_scrambled < total_count else total_count - total_scrambled + total_counts_scrambled[unit_type] = total_counts_scrambled.get(unit_type, 0) + dampened_value + return dampened_value - scrambled_armor = {} - for unit_type, field in self.armor_scramble_entries.items(): - amount = self._scrambled_armor_count(unit_type) - if amount > 0: - scrambled_armor[unit_type] = amount + for task_type, dict in self.scramble_entries.items(): + for unit_type, (count_entry, clients_entry) in dict.items(): + try: + count = int(count_entry.get()) + except: + count = 0 - if type(self.event) in AI_BAN_FOR_EVENTS: - banned_tasks_for_ai = AI_BAN_FOR_EVENTS[type(self.event)] - for task in banned_tasks_for_ai: - scrambled_slots = [1 for x in scrambled_aircraft if db.unit_task(x) == task] - scrambled_client_slots = [1 for x in scrambled_clients if db.unit_task(x) == task] + try: + clients_count = int(clients_entry and clients_entry.get() or 0) + except: + clients_count = 0 - if scrambled_slots != scrambled_client_slots: - self.error_label["text"] = "AI slots of task {} are not supported for this operation".format(task.name) - return + flights[task_type][unit_type] = dampen_count(unit_type, count), clients_count - if type(self.event) is BaseAttackEvent: - e = self.event # type: BaseAttackEvent - if self.game.is_player_attack(self.event): - e.player_attacking(cas=scrambled_cas, - escort=scrambled_sweep, - armor=scrambled_armor, - clients=scrambled_clients) - else: - e.player_defending(interceptors=scrambled_aircraft, - clients=scrambled_clients) - elif type(self.event) is InterceptEvent: - e = self.event # type: InterceptEvent - if self.game.is_player_attack(self.event): - e.player_attacking(interceptors=scrambled_aircraft, - clients=scrambled_clients) - else: - e.player_defending(escort=scrambled_aircraft, - clients=scrambled_clients) - 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, armor=scrambled_armor) - elif type(self.event) is NavalInterceptEvent: - e = self.event # type: NavalInterceptEvent - if self.game.is_player_attack(self.event): - e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) - else: - e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients) - elif type(self.event) is InsurgentAttackEvent: - e = self.event # type: InsurgentAttackEvent - if self.game.is_player_attack(self.event): - assert False - else: - e.player_defending(strikegroup=scrambled_aircraft, clients=scrambled_clients) - elif type(self.event) is InfantryTransportEvent: - e = self.event # type: InfantryTransportEvent - if self.game.is_player_attack(self.event): - e.player_attacking(transport=scrambled_aircraft, clients=scrambled_clients) - else: - assert False - elif type(self.event) is StrikeEvent: - e = self.event # type: StrikeEvent - if self.game.is_player_attack(self.event): - e.player_attacking(strikegroup=scrambled_cas, - escort=scrambled_sweep, - clients=scrambled_clients) - else: - assert False + if self.game.is_player_attack(self.event): + self.event.player_attacking(flights) + else: + self.event.player_defending(flights) self.game.initiate_event(self.event) EventResultsMenu(self.window, self.parent, self.game, self.event).display()