diff --git a/game/db.py b/game/db.py index 31c666f7..f82b84f5 100644 --- a/game/db.py +++ b/game/db.py @@ -73,6 +73,8 @@ PRICES = { An_30M: 13, Yak_40: 13, S_3B_Tanker: 13, + IL_78M: 13, + KC_135: 13, A_50: 8, E_3A: 8, @@ -167,6 +169,11 @@ UNIT_BY_TASK = { C_130, ], + Refueling: [ + IL_78M, + KC_135, + ], + AWACS: [E_3A, A_50, ], PinpointStrike: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ], @@ -251,6 +258,7 @@ UNIT_BY_COUNTRY = { L_39ZA, IL_76MD, + IL_78M, An_26B, An_30M, Yak_40, @@ -290,6 +298,7 @@ UNIT_BY_COUNTRY = { A_10C, AV8BNA, + KC_135, S_3B_Tanker, C_130, E_3A, @@ -450,7 +459,11 @@ def unitdict_split(unit_dict: UnitsDict, count: int): def unitdict_restrict_count(unit_dict: UnitsDict, total_count: int) -> UnitsDict: - return list(unitdict_split(unit_dict, total_count))[0] + groups = list(unitdict_split(unit_dict, total_count)) + if len(groups) > 0: + return groups[0] + else: + return {} def _validate_db(): diff --git a/game/event/__init__.py b/game/event/__init__.py index 4f9eee7c..3ee97e52 100644 --- a/game/event/__init__.py +++ b/game/event/__init__.py @@ -1,5 +1,6 @@ from .event import * from .frontlineattack import * +from .frontlinepatrol import * from .intercept import * from .baseattack import * from .navalintercept import * diff --git a/game/event/baseattack.py b/game/event/baseattack.py index b7ecbf64..e93aba31 100644 --- a/game/event/baseattack.py +++ b/game/event/baseattack.py @@ -16,7 +16,7 @@ class BaseAttackEvent(Event): STRENGTH_RECOVERY = 0.55 def __str__(self): - return "Attack from {} to {}".format(self.from_cp, self.to_cp) + return "Base attack from {} to {}".format(self.from_cp, self.to_cp) def is_successfull(self, debriefing: Debriefing): alive_attackers = sum([v for k, v in debriefing.alive_units[self.attacker_name].items() if db.unit_task(k) == PinpointStrike]) diff --git a/game/event/frontlineattack.py b/game/event/frontlineattack.py index b35f6d4e..11146809 100644 --- a/game/event/frontlineattack.py +++ b/game/event/frontlineattack.py @@ -16,7 +16,7 @@ class FrontlineAttackEvent(Event): ATTACKER_AMOUNT_FACTOR = 0.4 ATTACKER_DEFENDER_FACTOR = 0.7 STRENGTH_INFLUENCE = 0.3 - SUCCESS_MIN_TARGETS = 3 + SUCCESS_TARGETS_HIT_PERCENTAGE = 0.25 defenders = None # type: db.ArmorDict @@ -35,9 +35,9 @@ class FrontlineAttackEvent(Event): destroyed_targets += count if self.from_cp.captured: - return float(destroyed_targets) >= min(self.SUCCESS_MIN_TARGETS, total_targets) + return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE else: - return float(destroyed_targets) < min(self.SUCCESS_MIN_TARGETS, total_targets) + return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE def commit(self, debriefing: Debriefing): super(FrontlineAttackEvent, self).commit(debriefing) diff --git a/game/event/frontlinepatrol.py b/game/event/frontlinepatrol.py new file mode 100644 index 00000000..ddce50f3 --- /dev/null +++ b/game/event/frontlinepatrol.py @@ -0,0 +1,72 @@ +import math +import random + +from dcs.task import * +from dcs.vehicles import AirDefence + +from game import * +from game.event import * +from game.operation.frontlinepatrol import FrontlinePatrolOperation +from userdata.debriefing import Debriefing + + +class FrontlinePatrolEvent(Event): + ESCORT_FACTOR = 0.5 + STRENGTH_INFLUENCE = 0.3 + SUCCESS_TARGETS_HIT_PERCENTAGE = 0.6 + + cas = None # type: db.PlaneDict + escort = None # type: db.PlaneDict + + @property + def threat_description(self): + return "{} aircraft + ? CAS".format(self.to_cp.base.scramble_count(self.game.settings.multiplier * self.ESCORT_FACTOR, CAP)) + + def __str__(self): + return "Frontline CAP from {} at {}".format(self.from_cp, self.to_cp) + + def is_successfull(self, debriefing: Debriefing): + total_targets = sum(self.cas.values()) + destroyed_targets = 0 + for unit, count in debriefing.destroyed_units[self.defender_name].items(): + if unit in self.cas: + destroyed_targets += count + + if self.from_cp.captured: + return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE + else: + return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE + + def commit(self, debriefing: Debriefing): + super(FrontlinePatrolEvent, self).commit(debriefing) + + if self.from_cp.captured: + if self.is_successfull(debriefing): + self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) + else: + self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE) + else: + if self.is_successfull(debriefing): + self.from_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) + else: + self.to_cp.base.affect_strength(-self.STRENGTH_INFLUENCE) + + def skip(self): + pass + + def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict): + self.cas = self.to_cp.base.scramble_cas(self.game.settings.multiplier) + self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR) + + op = FrontlinePatrolOperation(game=self.game, + attacker_name=self.attacker_name, + defender_name=self.defender_name, + attacker_clients={}, + defender_clients=clients, + from_cp=self.from_cp, + to_cp=self.to_cp) + op.setup(cas=self.cas, + escort=self.escort, + interceptors=interceptors) + + self.operation = op diff --git a/game/game.py b/game/game.py index 7256718e..9c0d02f3 100644 --- a/game/game.py +++ b/game/game.py @@ -5,6 +5,7 @@ import math from dcs.task import * from dcs.vehicles import * +from gen.conflictgen import Conflict from userdata.debriefing import Debriefing from theater import * @@ -23,7 +24,7 @@ COMMISION_LIMITS_FACTORS = { COMMISION_AMOUNTS_SCALE = 1.5 COMMISION_AMOUNTS_FACTORS = { - PinpointStrike: 2, + PinpointStrike: 6, CAS: 1, CAP: 2, AirDefence: 0.3, @@ -31,6 +32,7 @@ COMMISION_AMOUNTS_FACTORS = { PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 25 PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2 +PLAYER_BASEATTACK_THRESHOLD = 0.2 """ Various events probabilities. First key is player probabilty, second is enemy probability. @@ -47,8 +49,9 @@ Events: """ EVENT_PROBABILITIES = { BaseAttackEvent: [100, 10], - InterceptEvent: [25, 10], FrontlineAttackEvent: [100, 0], + FrontlinePatrolEvent: [1000, 0], + InterceptEvent: [25, 10], InsurgentAttackEvent: [0, 10], NavalInterceptEvent: [25, 10], AntiAAStrikeEvent: [25, 10], @@ -65,7 +68,7 @@ ENEMY_BASE_STRENGTH_RECOVERY = 0.05 AWACS_BUDGET_COST = 4 # Initial budget value -PLAYER_BUDGET_INITIAL = 120 +PLAYER_BUDGET_INITIAL = 170 # Base post-turn bonus value PLAYER_BUDGET_BASE = 10 # Bonus multiplier logarithm base @@ -112,11 +115,18 @@ class Game: continue for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items(): + if event_class == FrontlineAttackEvent or event_class == InfantryTransportEvent or event_class == FrontlinePatrolEvent: + if not Conflict.has_frontline_between(player_cp, enemy_cp): + continue + if self._roll(player_probability, player_cp.base.strength): if event_class == NavalInterceptEvent and enemy_cp.radials == LAND: pass else: - self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self)) + if event_class == BaseAttackEvent and enemy_cp.base.strength > PLAYER_BASEATTACK_THRESHOLD: + pass + else: + self.events.append(event_class(self.player, self.enemy, player_cp, enemy_cp, self)) elif self._roll(enemy_probability, enemy_cp.base.strength): if event_class in enemy_generated_types: continue diff --git a/game/operation/antiaastrike.py b/game/operation/antiaastrike.py index 4403f504..424705a6 100644 --- a/game/operation/antiaastrike.py +++ b/game/operation/antiaastrike.py @@ -6,7 +6,7 @@ from gen.aircraft import * from gen.aaa import * from gen.shipgen import * from gen.triggergen import * -from gen.awacsgen import * +from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict diff --git a/game/operation/baseattack.py b/game/operation/baseattack.py index dee129fc..8add9744 100644 --- a/game/operation/baseattack.py +++ b/game/operation/baseattack.py @@ -6,7 +6,7 @@ from gen.aircraft import * from gen.aaa import * from gen.shipgen import * from gen.triggergen import * -from gen.awacsgen import * +from gen.airsupportgen import * from gen.visualgen import * from .operation import Operation @@ -60,7 +60,7 @@ class BaseAttackOperation(Operation): self.airgen.generate_defense(self.intercept, clients=self.defender_clients, at=self.defenders_starting_position) self.airgen.generate_cas_strikegroup(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position) - self.airgen.generate_strikegroup_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position) + self.airgen.generate_attackers_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position) self.visualgen.generate_target_smokes(self.to_cp) super(BaseAttackOperation, self).generate() diff --git a/game/operation/frontlineattack.py b/game/operation/frontlineattack.py index b89d9a69..17513925 100644 --- a/game/operation/frontlineattack.py +++ b/game/operation/frontlineattack.py @@ -8,7 +8,7 @@ from gen.aircraft import * from gen.aaa import * from gen.shipgen import * from gen.triggergen import * -from gen.awacsgen import * +from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict diff --git a/game/operation/frontlinepatrol.py b/game/operation/frontlinepatrol.py new file mode 100644 index 00000000..fd486747 --- /dev/null +++ b/game/operation/frontlinepatrol.py @@ -0,0 +1,53 @@ +from itertools import zip_longest + +from dcs.terrain import Terrain + +from game import db +from gen.armor import * +from gen.aircraft import * +from gen.aaa import * +from gen.shipgen import * +from gen.triggergen import * +from gen.airsupportgen import * +from gen.visualgen import * +from gen.conflictgen import Conflict + +from .operation import Operation + + +MAX_DISTANCE_BETWEEN_GROUPS = 12000 + + +class FrontlinePatrolOperation(Operation): + cas = None # type: db.PlaneDict + escort = None # type: db.PlaneDict + interceptors = None # type: db.PlaneDict + + def setup(self, cas: db.PlaneDict, escort: db.PlaneDict, interceptors: db.PlaneDict): + self.cas = cas + self.escort = escort + self.interceptors = interceptors + + def prepare(self, terrain: Terrain, is_quick: bool): + super(FrontlinePatrolOperation, self).prepare(terrain, is_quick) + self.defenders_starting_position = None + + conflict = Conflict.frontline_cap_conflict( + attacker=self.mission.country(self.attacker_name), + defender=self.mission.country(self.defender_name), + from_cp=self.from_cp, + to_cp=self.to_cp, + theater=self.game.theater + ) + + self.initialize(mission=self.mission, + conflict=conflict) + + def generate(self): + self.airgen.generate_defenders_cas(self.cas, {}, self.defenders_starting_position) + self.airgen.generate_defenders_escort(self.escort, {}, self.defenders_starting_position) + self.airgen.generate_patrol(self.interceptors, self.defender_clients, self.attackers_starting_position) + + # todo: generate armor + + super(FrontlinePatrolOperation, self).generate() diff --git a/game/operation/infantrytransport.py b/game/operation/infantrytransport.py index 82b360f9..d327eb3a 100644 --- a/game/operation/infantrytransport.py +++ b/game/operation/infantrytransport.py @@ -6,7 +6,7 @@ from gen.aircraft import * from gen.aaa import * from gen.shipgen import * from gen.triggergen import * -from gen.awacsgen import * +from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict diff --git a/game/operation/insurgentattack.py b/game/operation/insurgentattack.py index 92091002..e0358c68 100644 --- a/game/operation/insurgentattack.py +++ b/game/operation/insurgentattack.py @@ -6,7 +6,7 @@ from gen.aircraft import * from gen.aaa import * from gen.shipgen import * from gen.triggergen import * -from gen.awacsgen import * +from gen.airsupportgen import * from gen.visualgen import * from gen.conflictgen import Conflict diff --git a/game/operation/intercept.py b/game/operation/intercept.py index 59750f38..3121c794 100644 --- a/game/operation/intercept.py +++ b/game/operation/intercept.py @@ -52,7 +52,7 @@ class InterceptOperation(Operation): self.attackers_starting_position = ship self.airgen.generate_transport(self.transport, self.to_cp.at) - self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients) + self.airgen.generate_defenders_escort(self.escort, clients=self.defender_clients) self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position) super(InterceptOperation, self).generate() diff --git a/game/operation/operation.py b/game/operation/operation.py index 4071dc69..677f3a91 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -18,7 +18,7 @@ class Operation: extra_aagen = None # type: ExtraAAConflictGenerator shipgen = None # type: ShipGenerator triggersgen = None # type: TriggersGenerator - awacsgen = None # type: AWACSConflictGenerator + awacsgen = None # type: AirSupportConflictGenerator visualgen = None # type: VisualGenerator envgen = None # type: EnvironmentGenerator @@ -52,7 +52,7 @@ class Operation: self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings) self.aagen = AAConflictGenerator(mission, conflict) self.shipgen = ShipGenerator(mission, conflict) - self.awacsgen = AWACSConflictGenerator(mission, conflict, self.game) + self.awacsgen = AirSupportConflictGenerator(mission, conflict, self.game) self.triggersgen = TriggersGenerator(mission, conflict, self.game) self.visualgen = VisualGenerator(mission, conflict, self.game) self.envgen = EnviromentGenerator(mission, conflict, self.game) @@ -78,9 +78,7 @@ class Operation: def generate(self): self.visualgen.generate() - - if self.is_awacs_enabled: - self.awacsgen.generate() + self.awacsgen.generate(self.is_awacs_enabled) self.extra_aagen.generate() self.triggersgen.generate(self.is_quick, self.trigger_radius) diff --git a/gen/__init__.py b/gen/__init__.py index 0e4e80ab..7a5565ac 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -1,7 +1,7 @@ from .aaa import * from .aircraft import * from .armor import * -from .awacsgen import * +from .airsupportgen import * from .conflictgen import * from .shipgen import * from .visualgen import * diff --git a/gen/aircraft.py b/gen/aircraft.py index 48ee4c8c..4c1d7cc4 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -243,13 +243,35 @@ class AircraftConflictGenerator: waypoint = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) if self.conflict.is_vector: - group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_ALTITUDE) + group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_AIRSPEED) group.task = CAS.name self._setup_group(group, CAS, client_count) self.escort_targets.append((group, group.points.index(waypoint))) self._rtb_for(group, self.conflict.from_cp, at) + def generate_defenders_cas(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): + assert len(self.escort_targets) == 0 + + for flying_type, count, client_count in self._split_to_groups(defenders, clients): + group = self._generate_group( + name=namegen.next_unit_name(self.conflict.defenders_side, flying_type), + side=self.conflict.defenders_side, + unit_type=flying_type, + count=count, + client_count=client_count, + at=at and at or self._group_point(self.conflict.air_defenders_location)) + + pos = self.conflict.air_defenders_location.point_from_heading(self.conflict.heading-90, CAP_CAS_DISTANCE) + waypoint = group.add_waypoint(pos, CAS_ALTITUDE, WARM_START_AIRSPEED) + if self.conflict.is_vector: + group.add_waypoint(self.conflict.tail, CAS_ALTITUDE, WARM_START_AIRSPEED) + + group.task = CAS.name + self._setup_group(group, CAS, client_count) + self.escort_targets.append((group, group.points.index(waypoint))) + self._rtb_for(group, self.conflict.to_cp, at) + def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None): assert len(self.escort_targets) == 0 @@ -271,7 +293,7 @@ class AircraftConflictGenerator: self.escort_targets.append((group, group.points.index(wayp))) self._rtb_for(group, self.conflict.from_cp, at) - def generate_strikegroup_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): + def generate_attackers_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( side=self.conflict.attackers_side, units=attackers, @@ -281,7 +303,7 @@ class AircraftConflictGenerator: should_orbit=True): self._rtb_for(g, self.conflict.from_cp, at) - def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): + def generate_defenders_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( side=self.conflict.defenders_side, units=escort, @@ -308,6 +330,24 @@ class AircraftConflictGenerator: self._setup_group(group, CAP, client_count) self._rtb_for(group, self.conflict.to_cp, at) + def generate_patrol(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): + for flying_type, count, client_count in self._split_to_groups(patrol, clients): + group = self._generate_group( + name=namegen.next_unit_name(self.conflict.attackers_side, flying_type), + side=self.conflict.attackers_side, + unit_type=flying_type, + count=count, + client_count=client_count, + at=at and at or self._group_point(self.conflict.air_attackers_location)) + + waypoint = group.add_waypoint(self.conflict.position, WARM_START_ALTITUDE, WARM_START_AIRSPEED) + if self.conflict.is_vector: + group.add_waypoint(self.conflict.tail, WARM_START_ALTITUDE, WARM_START_AIRSPEED) + + group.task = CAP.name + self._setup_group(group, CAP, client_count) + self._rtb_for(group, self.conflict.from_cp, at) + def generate_transport(self, transport: db.PlaneDict, destination: Airport): assert len(self.escort_targets) == 0 diff --git a/gen/airsupportgen.py b/gen/airsupportgen.py new file mode 100644 index 00000000..e3e34aa3 --- /dev/null +++ b/gen/airsupportgen.py @@ -0,0 +1,50 @@ +from game import db +from .conflictgen import * +from .naming import * + +from dcs.mission import * +from dcs.unitgroup import * +from dcs.unittype import * +from dcs.task import * +from dcs.terrain.terrain import NoParkingSlotError + +TANKER_DISTANCE = 15000 +TANKER_ALT = 10000 + +AWACS_DISTANCE = 150000 +AWACS_ALT = 10000 + + +class AirSupportConflictGenerator: + def __init__(self, mission: Mission, conflict: Conflict, game): + self.mission = mission + self.conflict = conflict + self.game = game + + def generate(self, is_awacs_enabled): + tanker_unit = db.find_unittype(Refueling, self.conflict.attackers_side.name)[0] + tanker_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position) + tanker_position = self.conflict.from_cp.position.point_from_heading(tanker_heading, TANKER_DISTANCE) + self.mission.refuel_flight( + country=self.mission.country(self.game.player), + name=namegen.next_tanker_name(self.mission.country(self.game.player)), + airport=None, + plane_type=tanker_unit, + position=tanker_position, + altitude=TANKER_ALT, + frequency=140, + start_type=StartType.Warm, + ) + + if is_awacs_enabled: + awacs_unit = db.find_unittype(AWACS, self.conflict.attackers_side.name)[0] + self.mission.awacs_flight( + country=self.mission.country(self.game.player), + name=namegen.next_awacs_name(self.mission.country(self.game.player),), + plane_type=awacs_unit, + altitude=AWACS_ALT, + airport=None, + position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE), + frequency=251, + start_type=StartType.Warm, + ) diff --git a/gen/awacsgen.py b/gen/awacsgen.py deleted file mode 100644 index 4f17fb02..00000000 --- a/gen/awacsgen.py +++ /dev/null @@ -1,32 +0,0 @@ -from game import db -from .conflictgen import * -from .naming import * - -from dcs.mission import * -from dcs.unitgroup import * -from dcs.unittype import * -from dcs.task import * -from dcs.terrain.terrain import NoParkingSlotError - -AWACS_DISTANCE = 150000 -AWACS_ALT = 10000 - - -class AWACSConflictGenerator: - def __init__(self, mission: Mission, conflict: Conflict, game): - self.mission = mission - self.conflict = conflict - self.game = game - - def generate(self): - plane = db.find_unittype(AWACS, self.conflict.attackers_side.name)[0] - - self.mission.awacs_flight( - country=self.mission.country(self.game.player), - name=namegen.next_awacs_name(self.mission.country(self.game.player),), - plane_type=plane, - altitude=AWACS_ALT, - airport=None, - position=self.conflict.position.random_point_within(AWACS_DISTANCE, AWACS_DISTANCE), - frequency=251 - ) diff --git a/gen/conflictgen.py b/gen/conflictgen.py index 3a60e0e8..ad31d529 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -20,6 +20,7 @@ AIR_DISTANCE = 40000 CAPTURE_AIR_ATTACKERS_DISTANCE = 25000 CAPTURE_AIR_DEFENDERS_DISTANCE = 60000 +CAP_CAS_DISTANCE = 10000 GROUND_INTERCEPT_SPREAD = 5000 GROUND_DISTANCE_FACTOR = 1 @@ -261,8 +262,11 @@ class Conflict: @classmethod def frontline_cap_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): assert cls.has_frontline_between(from_cp, to_cp) + position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater) - defenders_distance = random.randint(distance/3, distance) + attack_position = position.point_from_heading(heading, randint(0, int(distance))) + attackers_position = attack_position.point_from_heading(heading - 90, AIR_DISTANCE) + defenders_position = attack_position.point_from_heading(heading + 90, CAP_CAS_DISTANCE) return cls( position=position, @@ -273,10 +277,8 @@ class Conflict: to_cp=to_cp, attackers_side=attacker, defenders_side=defender, - ground_attackers_location=None, - ground_defenders_location=None, - air_attackers_location=position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE), - air_defenders_location=position.point_from_heading(heading, max(AIR_DISTANCE, defenders_distance)), + air_attackers_location=attackers_position, + air_defenders_location=defenders_position, ) @classmethod diff --git a/gen/naming.py b/gen/naming.py index 3f28e62c..f769dfb3 100644 --- a/gen/naming.py +++ b/gen/naming.py @@ -15,6 +15,10 @@ class NameGenerator: self.number += 1 return "awacs|{}|{}|0|".format(country.id, self.number) + def next_tanker_name(self, country): + self.number += 1 + return "tanker|{}|{}|0|".format(country.id, self.number) + def next_carrier_name(self, country): self.number += 1 return "carrier|{}|{}|0|".format(country.id, self.number) diff --git a/gen/triggergen.py b/gen/triggergen.py index 94b5138a..7c79f553 100644 --- a/gen/triggergen.py +++ b/gen/triggergen.py @@ -73,7 +73,7 @@ class TriggersGenerator: for country in coalition.countries.values(): if coalition_name == player_coalition: for plane_group in country.plane_group + country.helicopter_group: - if plane_group.task == AWACS.name: + if plane_group.task == AWACS.name or plane_group.task == Refueling.name: continue regroup_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position) diff --git a/ui/eventmenu.py b/ui/eventmenu.py index e4081975..e2fe4992 100644 --- a/ui/eventmenu.py +++ b/ui/eventmenu.py @@ -1,9 +1,22 @@ +from dcs.helicopters import helicopter_map + from ui.eventresultsmenu import * from game import * from game.event import * +UNITTYPES_FOR_EVENTS = { + FrontlineAttackEvent: CAS, + FrontlinePatrolEvent: CAP, + InterceptEvent: CAP, + InsurgentAttackEvent: CAS, + NavalInterceptEvent: CAS, + AntiAAStrikeEvent: CAS, + InfantryTransportEvent: Embarking, +} + + class EventMenu(Menu): aircraft_scramble_entries = None # type: typing.Dict[PlaneType , Entry] aircraft_client_entries = None # type: typing.Dict[PlaneType, Entry] @@ -87,7 +100,14 @@ class EventMenu(Menu): Label(self.frame, text="Client slots").grid(row=row, column=3, columnspan=2) row += 1 + filter_to = UNITTYPES_FOR_EVENTS[self.event.__class__] for unit_type, count in self.base.aircraft.items(): + if filter_to and db.unit_task(unit_type) != filter_to: + continue + + if unit_type in helicopter_map and self.event.__class__ != InsurgentAttackEvent: + continue + scrable_row(unit_type, count) if not self.base.total_planes: @@ -193,6 +213,9 @@ class EventMenu(Menu): elif type(self.event) is FrontlineAttackEvent: e = self.event # type: FrontlineAttackEvent e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients) + elif type(self.event) is FrontlinePatrolEvent: + e = self.event # type: FrontlinePatrolEvent + e.player_attacking(interceptors=scrambled_aircraft, clients=scrambled_clients) elif type(self.event) is NavalInterceptEvent: e = self.event # type: NavalInterceptEvent