FARPs for heli flights WIP

This commit is contained in:
Vasyl Horbachenko 2018-09-10 23:12:04 +03:00
parent f21c515d5c
commit ca521e7e51
23 changed files with 128 additions and 222 deletions

View File

@ -366,7 +366,7 @@ PLANE_PAYLOAD_OVERRIDES = {
}, },
MiG_21Bis: { MiG_21Bis: {
"*": "Patrol, medium range", CAP: "Patrol, medium range",
} }
} }
@ -392,7 +392,11 @@ HeliDict = typing.Dict[HelicopterType, int]
ArmorDict = typing.Dict[VehicleType, int] ArmorDict = typing.Dict[VehicleType, int]
ShipDict = typing.Dict[ShipType, int] ShipDict = typing.Dict[ShipType, int]
AirDefenseDict = typing.Dict[AirDefence, int] AirDefenseDict = typing.Dict[AirDefence, int]
StartingPosition = typing.Optional[typing.Union[ShipGroup, Airport, Point]]
AssignedUnitsDict = typing.Dict[typing.Type[UnitType], typing.Tuple[int, int]]
TaskForceDict = typing.Dict[typing.Type[Task], AssignedUnitsDict]
StartingPosition = typing.Optional[typing.Union[ShipGroup, StaticGroup, Airport, Point]]
def unit_task(unit: UnitType) -> Task: def unit_task(unit: UnitType) -> Task:
@ -471,6 +475,18 @@ def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict
return {} return {}
def assigned_units_split(fd: AssignedUnitsDict) -> typing.Tuple[PlaneDict, PlaneDict]:
return {k: v1 for k, (v1, v2) in fd.items()}, {k: v2 for k, (v1, v2) in fd.items()},
def assigned_units_from(d: PlaneDict) -> AssignedUnitsDict:
return {k: (v, 0) for k, v in d.items()}
def unitdict_from(fd: AssignedUnitsDict) -> Dict:
return {k: v1 for k, (v1, v2) in fd.items()}
def _validate_db(): def _validate_db():
# check unit by task uniquity # check unit by task uniquity
total_set = set() total_set = set()

View File

@ -1,16 +1,7 @@
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 game.operation.baseattack import BaseAttackOperation
from userdata.debriefing import Debriefing
from .event import * from .event import *
from ..operation.operation import flight_dict_from from game.db import assigned_units_from
class BaseAttackEvent(Event): class BaseAttackEvent(Event):
@ -60,7 +51,7 @@ 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, flights: ScrambledFlightsDict): def player_defending(self, flights: db.TaskForceDict):
assert CAP in flights and len(flights) == 1, "Invalid scrambled flights" assert CAP in flights and len(flights) == 1, "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)
@ -73,8 +64,8 @@ class BaseAttackEvent(Event):
from_cp=self.from_cp, from_cp=self.from_cp,
to_cp=self.to_cp) to_cp=self.to_cp)
op.setup(cas=flight_dict_from(cas), op.setup(cas=assigned_units_from(cas),
escort=flight_dict_from(escort), escort=assigned_units_from(escort),
intercept=flights[CAP], intercept=flights[CAP],
attack=attackers, attack=attackers,
defense=self.to_cp.base.armor, defense=self.to_cp.base.armor,
@ -82,7 +73,7 @@ class BaseAttackEvent(Event):
self.operation = op self.operation = op
def player_attacking(self, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAP in flights and CAS in flights and PinpointStrike in flights and len(flights) == 3, "Invalid flights" assert CAP in flights and CAS in flights and PinpointStrike in flights and len(flights) == 3, "Invalid flights"
op = BaseAttackOperation(game=self.game, op = BaseAttackOperation(game=self.game,
@ -97,7 +88,7 @@ class BaseAttackEvent(Event):
op.setup(cas=flights[CAS], op.setup(cas=flights[CAS],
escort=flights[CAP], escort=flights[CAP],
attack=flights[PinpointStrike], attack=flights[PinpointStrike],
intercept=flight_dict_from(defenders), intercept=assigned_units_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())

View File

@ -8,15 +8,13 @@ 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 game.db import assigned_units_from, unitdict_from
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
@ -67,10 +65,10 @@ class Event:
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): def player_attacking(self, flights: db.TaskForceDict):
assert False assert False
def player_defending(self, flights: ScrambledFlightsDict): def player_defending(self, flights: db.TaskForceDict):
assert False assert False
def generate(self): def generate(self):

View File

@ -1,10 +1,3 @@
import math
import random
from dcs.task import *
from dcs.vehicles import AirDefence
from game import *
from game.event import * from game.event import *
from game.operation.frontlineattack import FrontlineAttackOperation from game.operation.frontlineattack import FrontlineAttackOperation
from userdata.debriefing import Debriefing from userdata.debriefing import Debriefing
@ -69,7 +62,7 @@ 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, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAS in flights and PinpointStrike in flights and len(flights) == 2, "Invalid flights" assert CAS in flights and PinpointStrike in flights and len(flights) == 2, "Invalid flights"
self.defenders = self.to_cp.base.assemble_attack() self.defenders = self.to_cp.base.assemble_attack()
@ -80,7 +73,7 @@ class FrontlineAttackEvent(Event):
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]) armor = unitdict_from(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=flights[CAS]) strikegroup=flights[CAS])

View File

@ -1,10 +1,3 @@
import math
import random
from dcs.task import *
from dcs.vehicles import AirDefence
from game import *
from game.event import * from game.event import *
from game.operation.frontlinepatrol import FrontlinePatrolOperation from game.operation.frontlinepatrol import FrontlinePatrolOperation
from userdata.debriefing import Debriefing from userdata.debriefing import Debriefing
@ -61,7 +54,7 @@ class FrontlinePatrolEvent(Event):
def skip(self): def skip(self):
pass pass
def player_attacking(self, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAP in flights and PinpointStrike in flights and len(flights) == 2, "Invalid flights" assert CAP in flights and PinpointStrike in flights 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)
@ -74,8 +67,8 @@ class FrontlinePatrolEvent(Event):
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=flight_dict_from(self.cas), op.setup(cas=assigned_units_from(self.cas),
escort=flight_dict_from(self.escort), escort=assigned_units_from(self.escort),
interceptors=flights[CAP], interceptors=flights[CAP],
armor_attackers=db.unitdict_restrict_count(dict_from_flight(flights[PinpointStrike]), sum(defenders.values())), armor_attackers=db.unitdict_restrict_count(dict_from_flight(flights[PinpointStrike]), sum(defenders.values())),
armor_defenders=defenders) armor_defenders=defenders)

View File

@ -37,7 +37,7 @@ 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, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert Embarking in flights and len(flights) == 1, "Invalid flights" assert Embarking in flights and len(flights) == 1, "Invalid flights"
op = InfantryTransportOperation( op = InfantryTransportOperation(

View File

@ -40,7 +40,7 @@ class InsurgentAttackEvent(Event):
else: else:
return not attackers_success return not attackers_success
def player_defending(self, flights: ScrambledFlightsDict): def player_defending(self, flights: db.TaskForceDict):
assert CAS in flights and len(flights) == 1, "Invalid flights" assert CAS in flights and len(flights) == 1, "Invalid flights"
suitable_unittypes = db.find_unittype(Reconnaissance, self.attacker_name) suitable_unittypes = db.find_unittype(Reconnaissance, self.attacker_name)

View File

@ -1,13 +1,4 @@
import math
import random
from dcs.task import *
from dcs.vehicles import *
from game import db
from game.operation.intercept import InterceptOperation from game.operation.intercept import InterceptOperation
from theater.conflicttheater import *
from userdata.debriefing import Debriefing
from .event import * from .event import *
@ -68,7 +59,7 @@ 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, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAP in flights and len(flights) == 1, "Invalid flights" assert CAP in flights 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())
@ -83,14 +74,14 @@ class InterceptEvent(Event):
from_cp=self.from_cp, from_cp=self.from_cp,
to_cp=self.to_cp) to_cp=self.to_cp)
op.setup(escort=flight_dict_from(escort), op.setup(escort=assigned_units_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=flights[CAP]) interceptors=flights[CAP])
self.operation = op self.operation = op
def player_defending(self, flights: ScrambledFlightsDict): def player_defending(self, flights: db.TaskForceDict):
assert CAP in flights and len(flights) == 1, "Invalid flights" assert CAP in flights and len(flights) == 1, "Invalid flights"
interceptors = self.from_cp.base.scramble_interceptors(self.game.settings.multiplier) interceptors = self.from_cp.base.scramble_interceptors(self.game.settings.multiplier)
@ -106,7 +97,7 @@ class InterceptEvent(Event):
op.setup(escort=flights[CAP], op.setup(escort=flights[CAP],
transport={self.transport_unit: 1}, transport={self.transport_unit: 1},
interceptors=flight_dict_from(interceptors), interceptors=assigned_units_from(interceptors),
airdefense={}) airdefense={})
self.operation = op self.operation = op

View File

@ -1,13 +1,4 @@
import typing
import math
import random
from dcs.task import *
from dcs.vehicles import *
from game import db
from game.operation.navalintercept import NavalInterceptionOperation from game.operation.navalintercept import NavalInterceptionOperation
from userdata.debriefing import Debriefing
from .event import * from .event import *
@ -19,7 +10,7 @@ class NavalInterceptEvent(Event):
targets = None # type: db.ShipDict targets = None # type: db.ShipDict
def _targets_count(self) -> int: def _targets_count(self) -> int:
from gen.conflictgen import IMPORTANCE_LOW, IMPORTANCE_HIGH from gen.conflictgen import IMPORTANCE_LOW
factor = (self.to_cp.importance - IMPORTANCE_LOW) * 10 factor = (self.to_cp.importance - IMPORTANCE_LOW) * 10
return max(int(factor), 1) return max(int(factor), 1)
@ -77,7 +68,7 @@ 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, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAS in flights and len(flights) == 1, "Invalid flights" assert CAS in flights and len(flights) == 1, "Invalid flights"
self.targets = { self.targets = {
@ -98,7 +89,7 @@ class NavalInterceptEvent(Event):
self.operation = op self.operation = op
def player_defending(self, flights: ScrambledFlightsDict): def player_defending(self, flights: db.TaskForceDict):
assert CAP in flights and len(flights) == 1, "Invalid flights" assert CAP in flights and len(flights) == 1, "Invalid flights"
self.targets = { self.targets = {
@ -114,7 +105,7 @@ class NavalInterceptEvent(Event):
) )
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=flight_dict_from(strikegroup), op.setup(strikegroup=assigned_units_from(strikegroup),
interceptors=flights[CAP], interceptors=flights[CAP],
targets=self.targets) targets=self.targets)

View File

@ -1,13 +1,4 @@
import math
import random
from dcs.task import *
from dcs.vehicles import *
from game import db
from game.operation.strike import StrikeOperation from game.operation.strike import StrikeOperation
from theater.conflicttheater import *
from userdata.debriefing import Debriefing
from .event import * from .event import *
@ -50,7 +41,7 @@ class StrikeEvent(Event):
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, flights: ScrambledFlightsDict): def player_attacking(self, flights: db.TaskForceDict):
assert CAP in flights and CAS in flights and len(flights) == 2, "Invalid flights" assert CAP in flights and CAS in flights and len(flights) == 2, "Invalid flights"
op = StrikeOperation( op = StrikeOperation(
@ -64,6 +55,6 @@ class StrikeEvent(Event):
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=flights[CAS],
escort=flights[CAP], escort=flights[CAP],
interceptors=flight_dict_from(interceptors)) interceptors=assigned_units_from(interceptors))
self.operation = op self.operation = op

View File

@ -1,21 +1,14 @@
from game import db from game.db import assigned_units_split
from gen.conflictgen import Conflict
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import * from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from .operation import * from .operation import *
class BaseAttackOperation(Operation): class BaseAttackOperation(Operation):
cas = None # type: FlightDict cas = None # type: db.AssignedUnitsDict
escort = None # type: FlightDict escort = None # type: db.AssignedUnitsDict
intercept = None # type: FlightDict intercept = None # type: db.AssignedUnitsDict
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 +16,10 @@ class BaseAttackOperation(Operation):
trigger_radius = TRIGGER_RADIUS_SMALL trigger_radius = TRIGGER_RADIUS_SMALL
def setup(self, def setup(self,
cas: FlightDict, cas: db.AssignedUnitsDict,
escort: FlightDict, escort: db.AssignedUnitsDict,
attack: FlightDict, attack: db.AssignedUnitsDict,
intercept: FlightDict, intercept: db.AssignedUnitsDict,
defense: db.ArmorDict, defense: db.ArmorDict,
aa: db.AirDefenseDict): aa: db.AirDefenseDict):
self.cas = cas self.cas = cas
@ -57,10 +50,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(*flight_arguments(self.intercept), at=self.defenders_starting_position) self.airgen.generate_defense(*assigned_units_split(self.intercept), at=self.defenders_starting_position)
self.airgen.generate_cas_strikegroup(*flight_arguments(self.cas), at=self.attackers_starting_position) self.airgen.generate_cas_strikegroup(*assigned_units_split(self.cas), at=self.attackers_starting_position)
self.airgen.generate_attackers_escort(*flight_arguments(self.escort), at=self.attackers_starting_position) self.airgen.generate_attackers_escort(*assigned_units_split(self.escort), at=self.attackers_starting_position)
self.visualgen.generate_target_smokes(self.to_cp) self.visualgen.generate_target_smokes(self.to_cp)

View File

@ -1,16 +1,4 @@
from itertools import zip_longest from game.db import assigned_units_split
from dcs.terrain import Terrain
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import * from .operation import *
@ -19,14 +7,14 @@ MAX_DISTANCE_BETWEEN_GROUPS = 12000
class FrontlineAttackOperation(Operation): class FrontlineAttackOperation(Operation):
strikegroup = None # type: FlightDict strikegroup = None # type: db.AssignedUnitsDict
attackers = None # type: db.ArmorDict attackers = None # type: db.ArmorDict
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: FlightDict): strikegroup: db.AssignedUnitsDict):
self.strikegroup = strikegroup self.strikegroup = strikegroup
self.target = target self.target = target
self.attackers = attackers self.attackers = attackers
@ -50,7 +38,13 @@ 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(*flight_arguments(self.strikegroup), at=self.attackers_starting_position)
planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map}
self.airgen.generate_cas_strikegroup(*assigned_units_split(planes_flights), at=self.attackers_starting_position)
heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map}
if heli_flights:
self.airgen.generate_cas_strikegroup(*assigned_units_split(heli_flights), at=self.groundobjectgen.generate_farp())
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."

View File

@ -1,16 +1,4 @@
from itertools import zip_longest from game.db import assigned_units_split
from dcs.terrain import Terrain
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import * from .operation import *
@ -19,17 +7,17 @@ MAX_DISTANCE_BETWEEN_GROUPS = 12000
class FrontlinePatrolOperation(Operation): class FrontlinePatrolOperation(Operation):
cas = None # type: FlightDict cas = None # type: db.AssignedUnitsDict
escort = None # type: FlightDict escort = None # type: db.AssignedUnitsDict
interceptors = None # type: FlightDict interceptors = None # type: db.AssignedUnitsDict
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, def setup(self,
cas: FlightDict, cas: db.AssignedUnitsDict,
escort: FlightDict, escort: db.AssignedUnitsDict,
interceptors: FlightDict, interceptors: db.AssignedUnitsDict,
armor_attackers: db.ArmorDict, armor_attackers: db.ArmorDict,
armor_defenders: db.ArmorDict): armor_defenders: db.ArmorDict):
self.cas = cas self.cas = cas
@ -55,9 +43,9 @@ class FrontlinePatrolOperation(Operation):
conflict=conflict) conflict=conflict)
def generate(self): def generate(self):
self.airgen.generate_defenders_cas(*flight_arguments(self.cas), at=self.defenders_starting_position) self.airgen.generate_defenders_cas(*assigned_units_split(self.cas), at=self.defenders_starting_position)
self.airgen.generate_defenders_escort(*flight_arguments(self.escort), at=self.defenders_starting_position) self.airgen.generate_defenders_escort(*assigned_units_split(self.escort), at=self.defenders_starting_position)
self.airgen.generate_migcap(*flight_arguments(self.interceptors), at=self.attackers_starting_position) self.airgen.generate_migcap(*assigned_units_split(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)

View File

@ -1,23 +1,13 @@
from dcs.terrain import Terrain from game.db import assigned_units_split
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import * from .operation import *
class InfantryTransportOperation(Operation): class InfantryTransportOperation(Operation):
transport = None # type: FlightDict transport = None # type: db.AssignedUnitsDict
aa = None # type: db.AirDefenseDict aa = None # type: db.AirDefenseDict
def setup(self, transport: FlightDict, aa: db.AirDefenseDict): def setup(self, transport: db.AssignedUnitsDict, aa: db.AirDefenseDict):
self.transport = transport self.transport = transport
self.aa = aa self.aa = aa
@ -36,7 +26,7 @@ class InfantryTransportOperation(Operation):
conflict=conflict) conflict=conflict)
def generate(self): def generate(self):
self.airgen.generate_passenger_transport(*flight_arguments(self.transport), at=self.attackers_starting_position) self.airgen.generate_passenger_transport(*assigned_units_split(self.transport), 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)

View File

@ -1,25 +1,15 @@
from dcs.terrain import Terrain from game.db import assigned_units_split
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import * from .operation import *
class InsurgentAttackOperation(Operation): class InsurgentAttackOperation(Operation):
strikegroup = None # type: FlightDict strikegroup = None # type: db.AssignedUnitsDict
target = None # type: db.ArmorDict target = None # type: db.ArmorDict
def setup(self, def setup(self,
target: db.ArmorDict, target: db.ArmorDict,
strikegroup: FlightDict): strikegroup: db.AssignedUnitsDict):
self.strikegroup = strikegroup self.strikegroup = strikegroup
self.target = target self.target = target
@ -38,7 +28,7 @@ class InsurgentAttackOperation(Operation):
conflict=conflict) conflict=conflict)
def generate(self): def generate(self):
self.airgen.generate_defense(*flight_arguments(self.strikegroup), at=self.defenders_starting_position) self.airgen.generate_defense(*assigned_units_split(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"

View File

@ -1,22 +1,21 @@
from dcs.terrain import Terrain from game.db import assigned_units_split
from gen import *
from .operation import * from .operation import *
class InterceptOperation(Operation): class InterceptOperation(Operation):
escort = None # type: FlightDict escort = None # type: db.AssignedUnitsDict
transport = None # type: db.PlaneDict transport = None # type: db.PlaneDict
interceptors = None # type: FlightDict interceptors = None # type: db.AssignedUnitsDict
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: FlightDict, escort: db.AssignedUnitsDict,
transport: db.PlaneDict, transport: db.PlaneDict,
airdefense: db.AirDefenseDict, airdefense: db.AirDefenseDict,
interceptors: FlightDict): interceptors: db.AssignedUnitsDict):
self.escort = escort self.escort = escort
self.transport = transport self.transport = transport
self.airdefense = airdefense self.airdefense = airdefense
@ -52,9 +51,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(*flight_arguments(self.escort), at=self.defenders_starting_position) self.airgen.generate_defenders_escort(*assigned_units_split(self.escort), at=self.defenders_starting_position)
self.airgen.generate_interception(*flight_arguments(self.interceptors), at=self.attackers_starting_position) self.airgen.generate_interception(*assigned_units_split(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"

View File

@ -1,18 +1,17 @@
from dcs.terrain import Terrain from game.db import assigned_units_split
from gen import *
from .operation import * from .operation import *
class NavalInterceptionOperation(Operation): class NavalInterceptionOperation(Operation):
strikegroup = None # type: FlightDict strikegroup = None # type: db.AssignedUnitsDict
interceptors = None # type: FlightDict interceptors = None # type: db.AssignedUnitsDict
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: FlightDict, strikegroup: db.AssignedUnitsDict,
interceptors: FlightDict, interceptors: db.AssignedUnitsDict,
targets: db.ShipDict): targets: db.ShipDict):
self.strikegroup = strikegroup self.strikegroup = strikegroup
self.interceptors = interceptors self.interceptors = interceptors
@ -37,14 +36,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(
*flight_arguments(self.strikegroup), *assigned_units_split(self.strikegroup),
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(
*flight_arguments(self.interceptors), *assigned_units_split(self.interceptors),
at=self.defenders_starting_position at=self.defenders_starting_position
) )

View File

@ -1,31 +1,14 @@
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 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
defenders_starting_position = None # type: db.StartingPosition defenders_starting_position = None # type: db.StartingPosition
mission = None # type: dcs.Mission mission = None # type: dcs.Mission
conflict = None # type: Conflict conflict = None # type: Conflict
armorgen = None # type: ArmorConflictGenerator armorgen = None # type: ArmorConflictGenerator

View File

@ -1,27 +1,17 @@
from dcs.terrain import Terrain from game.db import assigned_units_split
from game import db
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.shipgen import *
from gen.triggergen import *
from gen.airsupportgen import *
from gen.visualgen import *
from gen.conflictgen import Conflict
from .operation import * from .operation import *
class StrikeOperation(Operation): class StrikeOperation(Operation):
strikegroup = None # type: FlightDict strikegroup = None # type: db.AssignedUnitsDict
escort = None # type: FlightDict escort = None # type: db.AssignedUnitsDict
interceptors = None # type: FlightDict interceptors = None # type: db.AssignedUnitsDict
def setup(self, def setup(self,
strikegroup: FlightDict, strikegroup: db.AssignedUnitsDict,
escort: FlightDict, escort: db.AssignedUnitsDict,
interceptors: FlightDict): interceptors: db.AssignedUnitsDict):
self.strikegroup = strikegroup self.strikegroup = strikegroup
self.escort = escort self.escort = escort
self.interceptors = interceptors self.interceptors = interceptors
@ -61,13 +51,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(*flight_arguments(self.strikegroup), self.airgen.generate_ground_attack_strikegroup(*assigned_units_split(self.strikegroup),
targets=targets, targets=targets,
at=self.attackers_starting_position) at=self.attackers_starting_position)
self.airgen.generate_attackers_escort(*flight_arguments(self.escort), at=self.attackers_starting_position) self.airgen.generate_attackers_escort(*assigned_units_split(self.escort), at=self.attackers_starting_position)
self.airgen.generate_barcap(*flight_arguments(self.interceptors), at=self.defenders_starting_position) self.airgen.generate_barcap(*assigned_units_split(self.interceptors), 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."

View File

@ -42,7 +42,7 @@ GROUP_VERTICAL_OFFSET = 300
class AircraftConflictGenerator: class AircraftConflictGenerator:
escort_targets = [] # type: typing.List[typing.Tuple[PlaneGroup, int]] escort_targets = [] # type: typing.List[typing.Tuple[FlyingGroup, int]]
vertical_offset = None # type: int vertical_offset = None # type: int
def __init__(self, mission: Mission, conflict: Conflict, settings: Settings): def __init__(self, mission: Mission, conflict: Conflict, settings: Settings):
@ -77,7 +77,7 @@ class AircraftConflictGenerator:
count -= group_size count -= group_size
client_count -= client_size client_count -= client_size
def _setup_group(self, group: FlyingGroup, for_task: Task, client_count: int): def _setup_group(self, group: FlyingGroup, for_task: typing.Type[Task], client_count: int):
did_load_loadout = False did_load_loadout = False
unit_type = group.units[0].unit_type unit_type = group.units[0].unit_type
if unit_type in db.PLANE_PAYLOAD_OVERRIDES: if unit_type in db.PLANE_PAYLOAD_OVERRIDES:

View File

@ -142,6 +142,9 @@ class Conflict:
y = lerp * dy + self.tail.y y = lerp * dy + self.tail.y
return Point(x, y) return Point(x, y)
def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> typing.Optional[Point]:
return Conflict._find_ground_position(at, max_distance, heading, self.theater)
@classmethod @classmethod
def has_frontline_between(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> bool: def has_frontline_between(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> bool:
return from_cp.has_frontline and to_cp.has_frontline return from_cp.has_frontline and to_cp.has_frontline
@ -190,7 +193,7 @@ class Conflict:
return pos return pos
@classmethod @classmethod
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point: def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> typing.Optional[Point]:
pos = initial pos = initial
for _ in range(0, int(max_distance), 500): for _ in range(0, int(max_distance), 500):
if theater.is_on_land(pos): if theater.is_on_land(pos):

View File

@ -7,6 +7,8 @@ from .naming import *
from dcs.mission import * from dcs.mission import *
from dcs.statics import * from dcs.statics import *
FARP_FRONTLINE_DISTANCE = 10000
CATEGORY_MAPPING = { CATEGORY_MAPPING = {
"power": [Fortification.Workshop_A], "power": [Fortification.Workshop_A],
@ -25,6 +27,17 @@ class GroundObjectsGenerator:
self.conflict = conflict self.conflict = conflict
self.game = game self.game = game
def generate_farp(self) -> StaticGroup:
assert self.conflict.is_vector, "FARP could be generated only on frontline conflicts!"
position = self.conflict.find_ground_position(self.conflict.center.point_from_heading(self.conflict.opposite_heading, FARP_FRONTLINE_DISTANCE))
return self.m.static_group(
country=self.m.country(self.game.player),
name="",
_type=Fortification.FARP_Command_Post,
position=position
)
def generate(self): def generate(self):
side = self.m.country(self.game.enemy) side = self.m.country(self.game.enemy)

View File

@ -140,7 +140,7 @@ class EventMenu(Menu):
else: else:
self.event.is_awacs_enabled = False self.event.is_awacs_enabled = False
flights = {k: {} for k in self.event.tasks} # type: ScrambledFlightsDict flights = {k: {} for k in self.event.tasks} # type: db.TaskForceDict
units_scramble_counts = {} # type: typing.Dict[typing.Type[UnitType], int] units_scramble_counts = {} # type: typing.Dict[typing.Type[UnitType], int]
tasks_scramble_counts = {} # type: typing.Dict[typing.Type[Task], int] tasks_scramble_counts = {} # type: typing.Dict[typing.Type[Task], int]
tasks_clients_counts = {} # type: typing.Dict[typing.Type[Task], int] tasks_clients_counts = {} # type: typing.Dict[typing.Type[Task], int]