mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
dont limit aircraft to predefined role; better scrambling screen
This commit is contained in:
parent
4ba1dd87e8
commit
a918914431
@ -1,4 +1,5 @@
|
|||||||
import typing
|
import typing
|
||||||
|
import enum
|
||||||
|
|
||||||
from dcs.vehicles import *
|
from dcs.vehicles import *
|
||||||
from dcs.unitgroup import *
|
from dcs.unitgroup import *
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
|
import typing
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from dcs.task import *
|
from dcs.task import *
|
||||||
|
from dcs.unittype import UnitType
|
||||||
|
|
||||||
from game import db
|
from game import db
|
||||||
from game.operation.baseattack import BaseAttackOperation
|
from game.operation.baseattack import BaseAttackOperation
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
|
|
||||||
from .event import Event
|
from .event import *
|
||||||
|
from ..operation.operation import flight_dict_from
|
||||||
|
|
||||||
|
|
||||||
class BaseAttackEvent(Event):
|
class BaseAttackEvent(Event):
|
||||||
@ -18,6 +21,18 @@ class BaseAttackEvent(Event):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Base attack"
|
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):
|
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_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])
|
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:
|
if not self.is_player_attacking and self.to_cp.captured:
|
||||||
self.to_cp.captured = False
|
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)
|
cas = self.from_cp.base.scramble_cas(self.game.settings.multiplier)
|
||||||
escort = self.from_cp.base.scramble_sweep(self.game.settings.multiplier)
|
escort = self.from_cp.base.scramble_sweep(self.game.settings.multiplier)
|
||||||
attackers = self.from_cp.base.armor
|
attackers = self.from_cp.base.armor
|
||||||
@ -53,36 +70,34 @@ class BaseAttackEvent(Event):
|
|||||||
op = BaseAttackOperation(game=self.game,
|
op = BaseAttackOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
|
||||||
defender_clients=clients,
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
op.setup(cas=cas,
|
op.setup(cas=flight_dict_from(cas),
|
||||||
escort=escort,
|
escort=flight_dict_from(escort),
|
||||||
|
intercept=flights[CAP],
|
||||||
attack=attackers,
|
attack=attackers,
|
||||||
intercept=interceptors,
|
|
||||||
defense=self.to_cp.base.armor,
|
defense=self.to_cp.base.armor,
|
||||||
aa=self.to_cp.base.aa)
|
aa=self.to_cp.base.aa)
|
||||||
|
|
||||||
self.operation = op
|
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,
|
op = BaseAttackOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
defenders = self.to_cp.base.scramble_sweep(self.game.settings.multiplier)
|
defenders = self.to_cp.base.scramble_sweep(self.game.settings.multiplier)
|
||||||
defenders.update(self.to_cp.base.scramble_cas(self.game.settings.multiplier))
|
defenders.update(self.to_cp.base.scramble_cas(self.game.settings.multiplier))
|
||||||
|
|
||||||
op.setup(cas=cas,
|
op.setup(cas=flights[CAS],
|
||||||
escort=escort,
|
escort=flights[CAP],
|
||||||
attack=armor,
|
attack=flights[PinpointStrike],
|
||||||
intercept=defenders,
|
intercept=flight_dict_from(defenders),
|
||||||
defense=self.to_cp.base.armor,
|
defense=self.to_cp.base.armor,
|
||||||
aa=self.to_cp.base.assemble_aa())
|
aa=self.to_cp.base.assemble_aa())
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,22 @@
|
|||||||
|
import typing
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from dcs.unittype import UnitType
|
||||||
|
from dcs.task import Task
|
||||||
from dcs.unittype import UnitType
|
from dcs.unittype import UnitType
|
||||||
|
|
||||||
from game import *
|
from game import *
|
||||||
from theater import *
|
from theater import *
|
||||||
from gen.environmentgen import EnvironmentSettings
|
from gen.environmentgen import EnvironmentSettings
|
||||||
|
from game.operation.operation import flight_dict_from, dict_from_flight
|
||||||
|
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
from userdata import persistency
|
from userdata import persistency
|
||||||
|
|
||||||
DIFFICULTY_LOG_BASE = 1.1
|
DIFFICULTY_LOG_BASE = 1.1
|
||||||
|
|
||||||
|
ScrambledFlightsDict = typing.Dict[typing.Type[Task], typing.Dict[typing.Type[UnitType], typing.Tuple[int, int]]]
|
||||||
|
|
||||||
|
|
||||||
class Event:
|
class Event:
|
||||||
silent = False
|
silent = False
|
||||||
@ -44,12 +50,25 @@ class Event:
|
|||||||
def threat_description(self) -> str:
|
def threat_description(self) -> str:
|
||||||
return ""
|
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:
|
def bonus(self) -> int:
|
||||||
return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
||||||
|
|
||||||
def is_successfull(self, debriefing: Debriefing) -> bool:
|
def is_successfull(self, debriefing: Debriefing) -> bool:
|
||||||
return self.operation.is_successfull(debriefing)
|
return self.operation.is_successfull(debriefing)
|
||||||
|
|
||||||
|
def player_attacking(self, flights: ScrambledFlightsDict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def player_defending(self, flights: ScrambledFlightsDict):
|
||||||
|
pass
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,21 @@ class FrontlineAttackEvent(Event):
|
|||||||
def threat_description(self):
|
def threat_description(self):
|
||||||
return "{} vehicles".format(self.to_cp.base.assemble_count())
|
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):
|
def __str__(self):
|
||||||
return "Frontline attack"
|
return "Frontline attack"
|
||||||
|
|
||||||
@ -54,20 +69,21 @@ class FrontlineAttackEvent(Event):
|
|||||||
if self.to_cp.captured:
|
if self.to_cp.captured:
|
||||||
self.to_cp.base.affect_strength(-0.1)
|
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()
|
self.defenders = self.to_cp.base.assemble_attack()
|
||||||
|
|
||||||
op = FrontlineAttackOperation(game=self.game,
|
op = FrontlineAttackOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
|
armor = dict_from_flight(flights[PinpointStrike])
|
||||||
op.setup(target=self.defenders,
|
op.setup(target=self.defenders,
|
||||||
attackers=db.unitdict_restrict_count(armor, sum(self.defenders.values())),
|
attackers=db.unitdict_restrict_count(armor, sum(self.defenders.values())),
|
||||||
strikegroup=strikegroup)
|
strikegroup=flights[CAS])
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,16 @@ class FrontlinePatrolEvent(Event):
|
|||||||
def threat_description(self):
|
def threat_description(self):
|
||||||
return "{} aircraft + ? CAS".format(self.to_cp.base.scramble_count(self.game.settings.multiplier * self.ESCORT_FACTOR, CAP))
|
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):
|
def __str__(self):
|
||||||
return "Frontline CAP"
|
return "Frontline CAP"
|
||||||
|
|
||||||
@ -65,23 +75,23 @@ class FrontlinePatrolEvent(Event):
|
|||||||
def skip(self):
|
def skip(self):
|
||||||
pass
|
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.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)
|
self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR)
|
||||||
|
|
||||||
op = FrontlinePatrolOperation(game=self.game,
|
op = FrontlinePatrolOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
defenders = self.to_cp.base.assemble_attack()
|
defenders = self.to_cp.base.assemble_attack()
|
||||||
op.setup(cas=self.cas,
|
op.setup(cas=flight_dict_from(self.cas),
|
||||||
escort=self.escort,
|
escort=flight_dict_from(self.escort),
|
||||||
interceptors=interceptors,
|
interceptors=flights[CAP],
|
||||||
armor_attackers=db.unitdict_restrict_count(armor, sum(defenders.values())),
|
armor_attackers=db.unitdict_restrict_count(dict_from_flight(flights[PinpointStrike]), sum(defenders.values())),
|
||||||
armor_defenders=defenders)
|
armor_defenders=defenders)
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from game.operation.infantrytransport import InfantryTransportOperation
|
|||||||
from theater.conflicttheater import *
|
from theater.conflicttheater import *
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
|
|
||||||
from .event import Event
|
from .event import *
|
||||||
|
|
||||||
|
|
||||||
class InfantryTransportEvent(Event):
|
class InfantryTransportEvent(Event):
|
||||||
@ -18,6 +18,14 @@ class InfantryTransportEvent(Event):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Frontline transport troops"
|
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):
|
def is_successfull(self, debriefing: Debriefing):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -29,19 +37,19 @@ class InfantryTransportEvent(Event):
|
|||||||
else:
|
else:
|
||||||
self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
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(
|
op = InfantryTransportOperation(
|
||||||
game=self.game,
|
game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp
|
to_cp=self.to_cp
|
||||||
)
|
)
|
||||||
|
|
||||||
air_defense = db.find_unittype(AirDefence, self.defender_name)[0]
|
air_defense = db.find_unittype(AirDefence, self.defender_name)[0]
|
||||||
op.setup(transport=transport,
|
op.setup(transport=flights[Embarking],
|
||||||
aa={air_defense: 2})
|
aa={air_defense: 2})
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|||||||
@ -18,6 +18,14 @@ class InsurgentAttackEvent(Event):
|
|||||||
def threat_description(self):
|
def threat_description(self):
|
||||||
return ""
|
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):
|
def __str__(self):
|
||||||
return "Destroy insurgents"
|
return "Destroy insurgents"
|
||||||
|
|
||||||
@ -30,7 +38,9 @@ class InsurgentAttackEvent(Event):
|
|||||||
else:
|
else:
|
||||||
return not attackers_success
|
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)
|
suitable_unittypes = db.find_unittype(Reconnaissance, self.attacker_name)
|
||||||
random.shuffle(suitable_unittypes)
|
random.shuffle(suitable_unittypes)
|
||||||
unittypes = suitable_unittypes[:self.TARGET_VARIETY]
|
unittypes = suitable_unittypes[:self.TARGET_VARIETY]
|
||||||
@ -40,12 +50,10 @@ class InsurgentAttackEvent(Event):
|
|||||||
op = InsurgentAttackOperation(game=self.game,
|
op = InsurgentAttackOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
|
||||||
defender_clients=clients,
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
op.setup(target=self.targets,
|
op.setup(target=self.targets,
|
||||||
strikegroup=strikegroup)
|
strikegroup=flights[CAS])
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from game.operation.intercept import InterceptOperation
|
|||||||
from theater.conflicttheater import *
|
from theater.conflicttheater import *
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
|
|
||||||
from .event import Event
|
from .event import *
|
||||||
|
|
||||||
|
|
||||||
class InterceptEvent(Event):
|
class InterceptEvent(Event):
|
||||||
@ -22,6 +22,17 @@ class InterceptEvent(Event):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Air Intercept"
|
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:
|
def _enemy_scramble_multiplier(self) -> float:
|
||||||
is_global = self.from_cp.is_global or self.to_cp.is_global
|
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
|
return self.game.settings.multiplier * is_global and 0.5 or 1
|
||||||
@ -57,7 +68,9 @@ class InterceptEvent(Event):
|
|||||||
if self.to_cp.captured:
|
if self.to_cp.captured:
|
||||||
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
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())
|
escort = self.to_cp.base.scramble_sweep(self._enemy_scramble_multiplier())
|
||||||
|
|
||||||
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
||||||
@ -67,20 +80,17 @@ class InterceptEvent(Event):
|
|||||||
op = InterceptOperation(game=self.game,
|
op = InterceptOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
op.setup(escort=escort,
|
op.setup(escort=flight_dict_from(escort),
|
||||||
transport={self.transport_unit: 1},
|
transport={self.transport_unit: 1},
|
||||||
airdefense={airdefense_unit: self.AIRDEFENSE_COUNT},
|
airdefense={airdefense_unit: self.AIRDEFENSE_COUNT},
|
||||||
interceptors=interceptors)
|
interceptors=flights[CAP])
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|
||||||
def player_defending(self, escort: db.PlaneDict, clients: db.PlaneDict):
|
def player_defending(self, flights: ScrambledFlightsDict):
|
||||||
# TODO: even not quick mission is too quick
|
|
||||||
interceptors = self.from_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
interceptors = self.from_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
||||||
|
|
||||||
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
||||||
@ -89,14 +99,12 @@ class InterceptEvent(Event):
|
|||||||
op = InterceptOperation(game=self.game,
|
op = InterceptOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
|
||||||
defender_clients=clients,
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp)
|
to_cp=self.to_cp)
|
||||||
|
|
||||||
op.setup(escort=escort,
|
op.setup(escort=flights[CAP],
|
||||||
transport={self.transport_unit: 1},
|
transport={self.transport_unit: 1},
|
||||||
interceptors=interceptors,
|
interceptors=flight_dict_from(interceptors),
|
||||||
airdefense={})
|
airdefense={})
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from game import db
|
|||||||
from game.operation.navalintercept import NavalInterceptionOperation
|
from game.operation.navalintercept import NavalInterceptionOperation
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
|
|
||||||
from .event import Event
|
from .event import *
|
||||||
|
|
||||||
|
|
||||||
class NavalInterceptEvent(Event):
|
class NavalInterceptEvent(Event):
|
||||||
@ -26,6 +26,19 @@ class NavalInterceptEvent(Event):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "Naval intercept"
|
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
|
@property
|
||||||
def threat_description(self):
|
def threat_description(self):
|
||||||
s = "{} ship(s)".format(self._targets_count())
|
s = "{} ship(s)".format(self._targets_count())
|
||||||
@ -64,7 +77,9 @@ class NavalInterceptEvent(Event):
|
|||||||
if self.to_cp.captured:
|
if self.to_cp.captured:
|
||||||
self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE)
|
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 = {
|
self.targets = {
|
||||||
random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(),
|
random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(),
|
||||||
}
|
}
|
||||||
@ -73,19 +88,19 @@ class NavalInterceptEvent(Event):
|
|||||||
self.game,
|
self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp
|
to_cp=self.to_cp
|
||||||
)
|
)
|
||||||
|
|
||||||
op.setup(strikegroup=strikegroup,
|
op.setup(strikegroup=flights[CAS],
|
||||||
interceptors={},
|
interceptors={},
|
||||||
targets=self.targets)
|
targets=self.targets)
|
||||||
|
|
||||||
self.operation = op
|
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 = {
|
self.targets = {
|
||||||
random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(),
|
random.choice(db.find_unittype(CargoTransportation, self.defender_name)): self._targets_count(),
|
||||||
}
|
}
|
||||||
@ -94,15 +109,13 @@ class NavalInterceptEvent(Event):
|
|||||||
self.game,
|
self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
|
||||||
defender_clients=clients,
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp
|
to_cp=self.to_cp
|
||||||
)
|
)
|
||||||
|
|
||||||
strikegroup = self.from_cp.base.scramble_cas(self.game.settings.multiplier)
|
strikegroup = self.from_cp.base.scramble_cas(self.game.settings.multiplier)
|
||||||
op.setup(strikegroup=strikegroup,
|
op.setup(strikegroup=flight_dict_from(strikegroup),
|
||||||
interceptors=interceptors,
|
interceptors=flights[CAP],
|
||||||
targets=self.targets)
|
targets=self.targets)
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from game.operation.strike import StrikeOperation
|
|||||||
from theater.conflicttheater import *
|
from theater.conflicttheater import *
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
|
|
||||||
from .event import Event
|
from .event import *
|
||||||
|
|
||||||
|
|
||||||
class StrikeEvent(Event):
|
class StrikeEvent(Event):
|
||||||
@ -22,25 +22,40 @@ class StrikeEvent(Event):
|
|||||||
def is_successfull(self, debriefing: Debriefing):
|
def is_successfull(self, debriefing: Debriefing):
|
||||||
return True
|
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):
|
def commit(self, debriefing: Debriefing):
|
||||||
super(StrikeEvent, self).commit(debriefing)
|
super(StrikeEvent, self).commit(debriefing)
|
||||||
self.to_cp.base.affect_strength(-self.SINGLE_OBJECT_STRENGTH_INFLUENCE * len(debriefing.destroyed_objects))
|
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(
|
op = StrikeOperation(
|
||||||
self.game,
|
self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
|
||||||
defender_clients={},
|
|
||||||
from_cp=self.from_cp,
|
from_cp=self.from_cp,
|
||||||
to_cp=self.to_cp
|
to_cp=self.to_cp
|
||||||
)
|
)
|
||||||
|
|
||||||
interceptors = self.to_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
interceptors = self.to_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
||||||
|
op.setup(strikegroup=flights[CAS],
|
||||||
op.setup(strikegroup=strikegroup,
|
escort=flights[CAP],
|
||||||
escort=escort,
|
interceptors=flight_dict_from(interceptors))
|
||||||
interceptors=interceptors)
|
|
||||||
|
|
||||||
self.operation = op
|
self.operation = op
|
||||||
|
|||||||
@ -120,7 +120,7 @@ class Game:
|
|||||||
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
||||||
continue
|
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:
|
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -131,7 +131,7 @@ class Game:
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self))
|
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:
|
if event_class in enemy_generated_types:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,13 @@ from gen.triggergen import *
|
|||||||
from gen.airsupportgen import *
|
from gen.airsupportgen import *
|
||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class BaseAttackOperation(Operation):
|
class BaseAttackOperation(Operation):
|
||||||
cas = None # type: db.PlaneDict
|
cas = None # type: FlightDict
|
||||||
escort = None # type: db.PlaneDict
|
escort = None # type: FlightDict
|
||||||
intercept = None # type: db.PlaneDict
|
intercept = None # type: FlightDict
|
||||||
attack = None # type: db.ArmorDict
|
attack = None # type: db.ArmorDict
|
||||||
defense = None # type: db.ArmorDict
|
defense = None # type: db.ArmorDict
|
||||||
aa = None # type: db.AirDefenseDict
|
aa = None # type: db.AirDefenseDict
|
||||||
@ -23,10 +23,10 @@ class BaseAttackOperation(Operation):
|
|||||||
trigger_radius = TRIGGER_RADIUS_SMALL
|
trigger_radius = TRIGGER_RADIUS_SMALL
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
cas: db.PlaneDict,
|
cas: FlightDict,
|
||||||
escort: db.PlaneDict,
|
escort: FlightDict,
|
||||||
attack: db.ArmorDict,
|
attack: FlightDict,
|
||||||
intercept: db.PlaneDict,
|
intercept: FlightDict,
|
||||||
defense: db.ArmorDict,
|
defense: db.ArmorDict,
|
||||||
aa: db.AirDefenseDict):
|
aa: db.AirDefenseDict):
|
||||||
self.cas = cas
|
self.cas = cas
|
||||||
@ -57,10 +57,10 @@ class BaseAttackOperation(Operation):
|
|||||||
self.armorgen.generate(self.attack, self.defense)
|
self.armorgen.generate(self.attack, self.defense)
|
||||||
self.aagen.generate(self.aa)
|
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_cas_strikegroup(*flight_arguments(self.cas), 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.visualgen.generate_target_smokes(self.to_cp)
|
self.visualgen.generate_target_smokes(self.to_cp)
|
||||||
|
|
||||||
|
|||||||
@ -12,21 +12,21 @@ from gen.airsupportgen import *
|
|||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
MAX_DISTANCE_BETWEEN_GROUPS = 12000
|
MAX_DISTANCE_BETWEEN_GROUPS = 12000
|
||||||
|
|
||||||
|
|
||||||
class FrontlineAttackOperation(Operation):
|
class FrontlineAttackOperation(Operation):
|
||||||
|
strikegroup = None # type: FlightDict
|
||||||
attackers = None # type: db.ArmorDict
|
attackers = None # type: db.ArmorDict
|
||||||
strikegroup = None # type: db.PlaneDict
|
|
||||||
target = None # type: db.ArmorDict
|
target = None # type: db.ArmorDict
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
target: db.ArmorDict,
|
target: db.ArmorDict,
|
||||||
attackers: db.ArmorDict,
|
attackers: db.ArmorDict,
|
||||||
strikegroup: db.PlaneDict):
|
strikegroup: FlightDict):
|
||||||
self.strikegroup = strikegroup
|
self.strikegroup = strikegroup
|
||||||
self.target = target
|
self.target = target
|
||||||
self.attackers = attackers
|
self.attackers = attackers
|
||||||
@ -50,7 +50,7 @@ class FrontlineAttackOperation(Operation):
|
|||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.armorgen.generate_vec(self.attackers, self.target)
|
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.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."
|
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."
|
||||||
|
|||||||
@ -12,21 +12,26 @@ from gen.airsupportgen import *
|
|||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
MAX_DISTANCE_BETWEEN_GROUPS = 12000
|
MAX_DISTANCE_BETWEEN_GROUPS = 12000
|
||||||
|
|
||||||
|
|
||||||
class FrontlinePatrolOperation(Operation):
|
class FrontlinePatrolOperation(Operation):
|
||||||
cas = None # type: db.PlaneDict
|
cas = None # type: FlightDict
|
||||||
escort = None # type: db.PlaneDict
|
escort = None # type: FlightDict
|
||||||
interceptors = None # type: db.PlaneDict
|
interceptors = None # type: FlightDict
|
||||||
|
|
||||||
armor_attackers = None # type: db.ArmorDict
|
armor_attackers = None # type: db.ArmorDict
|
||||||
armor_defenders = 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.cas = cas
|
||||||
self.escort = escort
|
self.escort = escort
|
||||||
self.interceptors = interceptors
|
self.interceptors = interceptors
|
||||||
@ -50,9 +55,9 @@ class FrontlinePatrolOperation(Operation):
|
|||||||
conflict=conflict)
|
conflict=conflict)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.airgen.generate_defenders_cas(self.cas, {}, self.defenders_starting_position)
|
self.airgen.generate_defenders_cas(*flight_arguments(self.cas), at=self.defenders_starting_position)
|
||||||
self.airgen.generate_defenders_escort(self.escort, {}, self.defenders_starting_position)
|
self.airgen.generate_defenders_escort(*flight_arguments(self.escort), at=self.defenders_starting_position)
|
||||||
self.airgen.generate_migcap(self.interceptors, self.attacker_clients, self.attackers_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)
|
self.armorgen.generate_vec(self.armor_attackers, self.armor_defenders)
|
||||||
|
|
||||||
|
|||||||
@ -10,14 +10,14 @@ from gen.airsupportgen import *
|
|||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class InfantryTransportOperation(Operation):
|
class InfantryTransportOperation(Operation):
|
||||||
transport = None # type: db.HeliDict
|
transport = None # type: FlightDict
|
||||||
aa = None # type: db.AirDefenseDict
|
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.transport = transport
|
||||||
self.aa = aa
|
self.aa = aa
|
||||||
|
|
||||||
@ -36,11 +36,7 @@ class InfantryTransportOperation(Operation):
|
|||||||
conflict=conflict)
|
conflict=conflict)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.airgen.generate_passenger_transport(
|
self.airgen.generate_passenger_transport(*flight_arguments(self.transport), at=self.attackers_starting_position)
|
||||||
helis=self.transport,
|
|
||||||
clients=self.attacker_clients,
|
|
||||||
at=self.attackers_starting_position
|
|
||||||
)
|
|
||||||
|
|
||||||
self.armorgen.generate_passengers(count=6)
|
self.armorgen.generate_passengers(count=6)
|
||||||
self.aagen.generate_at_defenders_location(self.aa)
|
self.aagen.generate_at_defenders_location(self.aa)
|
||||||
|
|||||||
@ -10,16 +10,16 @@ from gen.airsupportgen import *
|
|||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class InsurgentAttackOperation(Operation):
|
class InsurgentAttackOperation(Operation):
|
||||||
strikegroup = None # type: db.PlaneDict
|
strikegroup = None # type: FlightDict
|
||||||
target = None # type: db.ArmorDict
|
target = None # type: db.ArmorDict
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
target: db.ArmorDict,
|
target: db.ArmorDict,
|
||||||
strikegroup: db.PlaneDict):
|
strikegroup: FlightDict):
|
||||||
self.strikegroup = strikegroup
|
self.strikegroup = strikegroup
|
||||||
self.target = target
|
self.target = target
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class InsurgentAttackOperation(Operation):
|
|||||||
conflict=conflict)
|
conflict=conflict)
|
||||||
|
|
||||||
def generate(self):
|
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.armorgen.generate(self.target, {})
|
||||||
|
|
||||||
self.briefinggen.title = "Destroy insurgents"
|
self.briefinggen.title = "Destroy insurgents"
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
from dcs.terrain import Terrain
|
from dcs.terrain import Terrain
|
||||||
|
|
||||||
from gen import *
|
from gen import *
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class InterceptOperation(Operation):
|
class InterceptOperation(Operation):
|
||||||
escort = None # type: db.PlaneDict
|
escort = None # type: FlightDict
|
||||||
transport = None # type: db.PlaneDict
|
transport = None # type: db.PlaneDict
|
||||||
interceptors = None # type: db.PlaneDict
|
interceptors = None # type: FlightDict
|
||||||
airdefense = None # type: db.AirDefenseDict
|
airdefense = None # type: db.AirDefenseDict
|
||||||
|
|
||||||
trigger_radius = TRIGGER_RADIUS_LARGE
|
trigger_radius = TRIGGER_RADIUS_LARGE
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
escort: db.PlaneDict,
|
escort: FlightDict,
|
||||||
transport: db.PlaneDict,
|
transport: db.PlaneDict,
|
||||||
airdefense: db.AirDefenseDict,
|
airdefense: db.AirDefenseDict,
|
||||||
interceptors: db.PlaneDict):
|
interceptors: FlightDict):
|
||||||
self.escort = escort
|
self.escort = escort
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
self.airdefense = airdefense
|
self.airdefense = airdefense
|
||||||
@ -52,9 +52,9 @@ class InterceptOperation(Operation):
|
|||||||
self.attackers_starting_position = ship
|
self.attackers_starting_position = ship
|
||||||
|
|
||||||
self.airgen.generate_transport(self.transport, self.to_cp.at)
|
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.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"
|
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"
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
from dcs.terrain import Terrain
|
from dcs.terrain import Terrain
|
||||||
|
|
||||||
from gen import *
|
from gen import *
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class NavalInterceptionOperation(Operation):
|
class NavalInterceptionOperation(Operation):
|
||||||
strikegroup = None # type: db.PlaneDict
|
strikegroup = None # type: FlightDict
|
||||||
interceptors = None # type: db.PlaneDict
|
interceptors = None # type: FlightDict
|
||||||
targets = None # type: db.ShipDict
|
targets = None # type: db.ShipDict
|
||||||
trigger_radius = TRIGGER_RADIUS_LARGE
|
trigger_radius = TRIGGER_RADIUS_LARGE
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
strikegroup: db.PlaneDict,
|
strikegroup: FlightDict,
|
||||||
interceptors: db.PlaneDict,
|
interceptors: FlightDict,
|
||||||
targets: db.ShipDict):
|
targets: db.ShipDict):
|
||||||
self.strikegroup = strikegroup
|
self.strikegroup = strikegroup
|
||||||
self.interceptors = interceptors
|
self.interceptors = interceptors
|
||||||
@ -37,16 +37,14 @@ class NavalInterceptionOperation(Operation):
|
|||||||
target_groups = self.shipgen.generate_cargo(units=self.targets)
|
target_groups = self.shipgen.generate_cargo(units=self.targets)
|
||||||
|
|
||||||
self.airgen.generate_ship_strikegroup(
|
self.airgen.generate_ship_strikegroup(
|
||||||
attackers=self.strikegroup,
|
*flight_arguments(self.strikegroup),
|
||||||
clients=self.attacker_clients,
|
|
||||||
target_groups=target_groups,
|
target_groups=target_groups,
|
||||||
at=self.attackers_starting_position
|
at=self.attackers_starting_position
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.interceptors:
|
if self.interceptors:
|
||||||
self.airgen.generate_defense(
|
self.airgen.generate_defense(
|
||||||
defenders=self.interceptors,
|
*flight_arguments(self.interceptors),
|
||||||
clients=self.defender_clients,
|
|
||||||
at=self.defenders_starting_position
|
at=self.defenders_starting_position
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,27 @@
|
|||||||
from dcs.terrain import Terrain
|
import typing
|
||||||
|
|
||||||
from dcs.lua.parse import loads
|
from dcs.lua.parse import loads
|
||||||
|
from dcs.unittype import UnitType
|
||||||
|
|
||||||
from userdata.debriefing import *
|
from userdata.debriefing import *
|
||||||
|
|
||||||
from theater import *
|
from theater import *
|
||||||
from gen 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:
|
class Operation:
|
||||||
attackers_starting_position = None # type: db.StartingPosition
|
attackers_starting_position = None # type: db.StartingPosition
|
||||||
@ -33,15 +49,11 @@ class Operation:
|
|||||||
game,
|
game,
|
||||||
attacker_name: str,
|
attacker_name: str,
|
||||||
defender_name: str,
|
defender_name: str,
|
||||||
attacker_clients: db.PlaneDict,
|
|
||||||
defender_clients: db.PlaneDict,
|
|
||||||
from_cp: ControlPoint,
|
from_cp: ControlPoint,
|
||||||
to_cp: ControlPoint = None):
|
to_cp: ControlPoint = None):
|
||||||
self.game = game
|
self.game = game
|
||||||
self.attacker_name = attacker_name
|
self.attacker_name = attacker_name
|
||||||
self.defender_name = defender_name
|
self.defender_name = defender_name
|
||||||
self.attacker_clients = attacker_clients
|
|
||||||
self.defender_clients = defender_clients
|
|
||||||
self.from_cp = from_cp
|
self.from_cp = from_cp
|
||||||
self.to_cp = to_cp
|
self.to_cp = to_cp
|
||||||
self.is_quick = False
|
self.is_quick = False
|
||||||
|
|||||||
@ -10,18 +10,18 @@ from gen.airsupportgen import *
|
|||||||
from gen.visualgen import *
|
from gen.visualgen import *
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
|
||||||
from .operation import Operation
|
from .operation import *
|
||||||
|
|
||||||
|
|
||||||
class StrikeOperation(Operation):
|
class StrikeOperation(Operation):
|
||||||
strikegroup = None # type: db.PlaneDict
|
strikegroup = None # type: FlightDict
|
||||||
escort = None # type: db.PlaneDict
|
escort = None # type: FlightDict
|
||||||
interceptors = None # type: db.PlaneDict
|
interceptors = None # type: FlightDict
|
||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
strikegroup: db.PlaneDict,
|
strikegroup: FlightDict,
|
||||||
escort: db.PlaneDict,
|
escort: FlightDict,
|
||||||
interceptors: db.PlaneDict):
|
interceptors: FlightDict):
|
||||||
self.strikegroup = strikegroup
|
self.strikegroup = strikegroup
|
||||||
self.escort = escort
|
self.escort = escort
|
||||||
self.interceptors = interceptors
|
self.interceptors = interceptors
|
||||||
@ -49,10 +49,10 @@ class StrikeOperation(Operation):
|
|||||||
category_counters = {} # type: typing.Dict[str, int]
|
category_counters = {} # type: typing.Dict[str, int]
|
||||||
processed_groups = []
|
processed_groups = []
|
||||||
for object in self.to_cp.ground_objects:
|
for object in self.to_cp.ground_objects:
|
||||||
if object.group_id in processed_groups:
|
if object.group_identifier in processed_groups:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
processed_groups.append(object.group_id)
|
processed_groups.append(object.group_identifier)
|
||||||
|
|
||||||
category_counters[object.category] = category_counters.get(object.category, 0) + 1
|
category_counters[object.category] = category_counters.get(object.category, 0) + 1
|
||||||
markpoint_name = "{}{}".format(object.name_abbrev, category_counters[object.category])
|
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]))
|
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,
|
targets=targets,
|
||||||
clients=self.attacker_clients,
|
|
||||||
at=self.attackers_starting_position)
|
at=self.attackers_starting_position)
|
||||||
|
|
||||||
self.airgen.generate_attackers_escort(self.escort,
|
self.airgen.generate_attackers_escort(*flight_arguments(self.escort), at=self.attackers_starting_position)
|
||||||
clients=self.attacker_clients,
|
|
||||||
at=self.attackers_starting_position)
|
|
||||||
|
|
||||||
self.airgen.generate_barcap(patrol=self.interceptors,
|
self.airgen.generate_barcap(*flight_arguments(self.interceptors), at=self.defenders_starting_position)
|
||||||
clients={},
|
|
||||||
at=self.defenders_starting_position)
|
|
||||||
|
|
||||||
self.briefinggen.title = "Strike"
|
self.briefinggen.title = "Strike"
|
||||||
self.briefinggen.description = "Destroy infrastructure assets and military supplies in the region. Each building destroyed will lower targets strength."
|
self.briefinggen.description = "Destroy infrastructure assets and military supplies in the region. Each building destroyed will lower targets strength."
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
class Settings:
|
class Settings:
|
||||||
player_skill = "Good"
|
player_skill = "Good"
|
||||||
enemy_skill = "Average"
|
enemy_skill = "Average"
|
||||||
only_player_takeoff = False
|
only_player_takeoff = True
|
||||||
night_disabled = False
|
night_disabled = False
|
||||||
multiplier = 1
|
multiplier = 1
|
||||||
sams = True
|
sams = True
|
||||||
|
|||||||
@ -265,7 +265,7 @@ class AircraftConflictGenerator:
|
|||||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||||
self._rtb_for(group, self.conflict.from_cp, at)
|
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
|
assert len(self.escort_targets) == 0
|
||||||
|
|
||||||
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
|
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
|
||||||
|
|||||||
5
gen/heli.py
Normal file
5
gen/heli.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .aircraft import *
|
||||||
|
|
||||||
|
|
||||||
|
class HelicopterConflictGenerator(AircraftConflictGenerator):
|
||||||
|
pass
|
||||||
@ -41,6 +41,10 @@ class TheaterGroundObject:
|
|||||||
def string_identifier(self):
|
def string_identifier(self):
|
||||||
return "{}|{}|{}|{}".format(self.category, self.cp_id, self.group_id, self.object_id)
|
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
|
@property
|
||||||
def name_abbrev(self) -> str:
|
def name_abbrev(self) -> str:
|
||||||
return ABBREV_NAME[self.category]
|
return ABBREV_NAME[self.category]
|
||||||
|
|||||||
226
ui/eventmenu.py
226
ui/eventmenu.py
@ -7,27 +7,9 @@ from game.event import *
|
|||||||
from .styles import STYLES, RED
|
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):
|
class EventMenu(Menu):
|
||||||
aircraft_scramble_entries = None # type: typing.Dict[PlaneType , Entry]
|
scramble_entries = None # type: typing.Dict[typing.Type[Task], typing.Dict[typing.Type[UnitType], typing.Tuple[Entry, Entry]]]
|
||||||
aircraft_client_entries = None # type: typing.Dict[PlaneType, Entry]
|
|
||||||
armor_scramble_entries = None # type: typing.Dict[VehicleType, Entry]
|
|
||||||
error_label = None # type: Label
|
error_label = None # type: Label
|
||||||
awacs = None # type: IntVar
|
awacs = None # type: IntVar
|
||||||
|
|
||||||
@ -35,9 +17,7 @@ class EventMenu(Menu):
|
|||||||
super(EventMenu, self).__init__(window, parent, game)
|
super(EventMenu, self).__init__(window, parent, game)
|
||||||
|
|
||||||
self.event = event
|
self.event = event
|
||||||
self.aircraft_scramble_entries = {}
|
self.scramble_entries = {k: {} for k in self.event.tasks}
|
||||||
self.armor_scramble_entries = {}
|
|
||||||
self.aircraft_client_entries = {}
|
|
||||||
|
|
||||||
if self.event.attacker_name == self.game.player:
|
if self.event.attacker_name == self.game.player:
|
||||||
self.base = self.event.from_cp.base
|
self.base = self.event.from_cp.base
|
||||||
@ -68,32 +48,24 @@ class EventMenu(Menu):
|
|||||||
|
|
||||||
return new_label
|
return new_label
|
||||||
|
|
||||||
def scrable_row(unit_type, unit_count):
|
def scrable_row(task_type, unit_type, unit_count, client_slots: bool):
|
||||||
nonlocal row
|
nonlocal row
|
||||||
Label(self.frame, text="{} ({})".format(db.unit_type_name(unit_type), unit_count), **STYLES["widget"]).grid(row=row, sticky=W)
|
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 = Entry(self.frame, width=2)
|
||||||
scramble_entry.grid(column=1, row=row, sticky=E, padx=5)
|
scramble_entry.grid(column=1, row=row, sticky=E, padx=5)
|
||||||
scramble_entry.insert(0, "0")
|
scramble_entry.insert(0, "0")
|
||||||
self.aircraft_scramble_entries[unit_type] = scramble_entry
|
Button(self.frame, text="+", command=self.scramble_half(task_type, unit_type), **STYLES["btn-primary"]).grid(column=2, row=row)
|
||||||
Button(self.frame, text="+", command=self.scramble_half(True, unit_type), **STYLES["btn-primary"]).grid(column=2, row=row)
|
|
||||||
|
|
||||||
|
if client_slots:
|
||||||
client_entry = Entry(self.frame, width=2)
|
client_entry = Entry(self.frame, width=2)
|
||||||
client_entry.grid(column=3, row=row, sticky=E, padx=5)
|
client_entry.grid(column=3, row=row, sticky=E, padx=5)
|
||||||
client_entry.insert(0, "0")
|
client_entry.insert(0, "0")
|
||||||
self.aircraft_client_entries[unit_type] = client_entry
|
Button(self.frame, text="+", command=self.client_one(task_type, unit_type), **STYLES["btn-primary"]).grid(column=4, row=row)
|
||||||
Button(self.frame, text="+", command=self.client_one(unit_type), **STYLES["btn-primary"]).grid(column=4, row=row)
|
else:
|
||||||
|
client_entry = None
|
||||||
|
|
||||||
row += 1
|
self.scramble_entries[task_type][unit_type] = scramble_entry, client_entry
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
row += 1
|
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)
|
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
|
row += 1
|
||||||
|
|
||||||
header("Aircraft :")
|
|
||||||
|
|
||||||
if self.base.aircraft:
|
|
||||||
Label(self.frame, text="Amount", **STYLES["widget"]).grid(row=row, column=1, columnspan=2)
|
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)
|
Label(self.frame, text="Client slots", **STYLES["widget"]).grid(row=row, column=3, columnspan=2)
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
filter_attackers_index = 0 if self.game.is_player_attack(self.event) else 1
|
for flight_task in self.event.tasks:
|
||||||
filter_to = UNITTYPES_FOR_EVENTS[self.event.__class__][filter_attackers_index]
|
header("{}:".format(self.event.flight_name(flight_task)))
|
||||||
for unit_type, count in self.base.aircraft.items():
|
if flight_task == PinpointStrike:
|
||||||
if filter_to and db.unit_task(unit_type) not in filter_to:
|
if not self.base.armor:
|
||||||
continue
|
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)
|
||||||
|
|
||||||
if unit_type in helicopter_map and self.event.__class__ != InsurgentAttackEvent:
|
header("Support:")
|
||||||
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 :")
|
|
||||||
# Options
|
# Options
|
||||||
awacs_enabled = self.game.budget >= AWACS_BUDGET_COST and NORMAL or DISABLED
|
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)
|
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)
|
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
|
row += 1
|
||||||
|
|
||||||
header("Ready ?")
|
header("Ready?")
|
||||||
self.error_label = label("")
|
self.error_label = label("")
|
||||||
self.error_label["fg"] = RED
|
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="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))
|
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
|
row += 1
|
||||||
|
|
||||||
def _scrambled_aircraft_count(self, unit_type: UnitType) -> int:
|
def scramble_half(self, task: typing.Type[UnitType], unit_type: UnitType) -> typing.Callable:
|
||||||
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 action():
|
def action():
|
||||||
entry = None # type: Entry
|
entry = self.scramble_entries[task][unit_type][0] # type: Entry
|
||||||
total_count = 0
|
value = entry.get()
|
||||||
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]
|
|
||||||
|
|
||||||
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.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
|
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():
|
def action():
|
||||||
entry = self.aircraft_client_entries[unit_type] # type: Entry
|
entry = self.scramble_entries[task][unit_type][1] # type: Entry
|
||||||
value = entry.get()
|
value = entry.get()
|
||||||
amount = int(value and value or "0")
|
amount = int(value and value or "0")
|
||||||
entry.delete(0, END)
|
entry.delete(0, END)
|
||||||
@ -199,94 +140,37 @@ class EventMenu(Menu):
|
|||||||
else:
|
else:
|
||||||
self.event.is_awacs_enabled = False
|
self.event.is_awacs_enabled = False
|
||||||
|
|
||||||
scrambled_aircraft = {}
|
flights = {k: {} for k in self.event.tasks} # type: ScrambledFlightsDict
|
||||||
scrambled_sweep = {}
|
total_counts_scrambled = {} # type: typing.Dict[typing.Type[UnitType], int]
|
||||||
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)
|
|
||||||
|
|
||||||
scrambled_aircraft[unit_type] = amount
|
def dampen_count(unit_type: typing.Type[UnitType], count: int) -> int:
|
||||||
if task == CAS:
|
nonlocal total_counts_scrambled
|
||||||
scrambled_cas[unit_type] = amount
|
total_count = self.base.total_units_of_type(unit_type)
|
||||||
elif task == CAP:
|
|
||||||
scrambled_sweep[unit_type] = amount
|
|
||||||
|
|
||||||
scrambled_clients = {}
|
total_scrambled = total_counts_scrambled.get(unit_type, 0)
|
||||||
for unit_type, field in self.aircraft_client_entries.items():
|
dampened_value = count if count + total_scrambled < total_count else total_count - total_scrambled
|
||||||
value = field.get()
|
total_counts_scrambled[unit_type] = total_counts_scrambled.get(unit_type, 0) + dampened_value
|
||||||
if value and int(value) > 0:
|
return dampened_value
|
||||||
amount = int(value)
|
|
||||||
scrambled_clients[unit_type] = amount
|
|
||||||
|
|
||||||
scrambled_armor = {}
|
for task_type, dict in self.scramble_entries.items():
|
||||||
for unit_type, field in self.armor_scramble_entries.items():
|
for unit_type, (count_entry, clients_entry) in dict.items():
|
||||||
amount = self._scrambled_armor_count(unit_type)
|
try:
|
||||||
if amount > 0:
|
count = int(count_entry.get())
|
||||||
scrambled_armor[unit_type] = amount
|
except:
|
||||||
|
count = 0
|
||||||
|
|
||||||
if type(self.event) in AI_BAN_FOR_EVENTS:
|
try:
|
||||||
banned_tasks_for_ai = AI_BAN_FOR_EVENTS[type(self.event)]
|
clients_count = int(clients_entry and clients_entry.get() or 0)
|
||||||
for task in banned_tasks_for_ai:
|
except:
|
||||||
scrambled_slots = [1 for x in scrambled_aircraft if db.unit_task(x) == task]
|
clients_count = 0
|
||||||
scrambled_client_slots = [1 for x in scrambled_clients if db.unit_task(x) == task]
|
|
||||||
|
|
||||||
if scrambled_slots != scrambled_client_slots:
|
flights[task_type][unit_type] = dampen_count(unit_type, count), clients_count
|
||||||
self.error_label["text"] = "AI slots of task {} are not supported for this operation".format(task.name)
|
|
||||||
return
|
|
||||||
|
|
||||||
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):
|
if self.game.is_player_attack(self.event):
|
||||||
e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients)
|
self.event.player_attacking(flights)
|
||||||
else:
|
else:
|
||||||
e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients)
|
self.event.player_defending(flights)
|
||||||
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
|
|
||||||
|
|
||||||
self.game.initiate_event(self.event)
|
self.game.initiate_event(self.event)
|
||||||
EventResultsMenu(self.window, self.parent, self.game, self.event).display()
|
EventResultsMenu(self.window, self.parent, self.game, self.event).display()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user