diff --git a/.idea/dcs_pmcliberation.iml b/.idea/dcs_pmcliberation.iml index 1f377c84..9eedabcf 100644 --- a/.idea/dcs_pmcliberation.iml +++ b/.idea/dcs_pmcliberation.iml @@ -4,7 +4,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 65531ca9..e524f659 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/game/db.py b/game/db.py index 84df67b2..c1992a48 100644 --- a/game/db.py +++ b/game/db.py @@ -12,26 +12,27 @@ PRICES = { C_101CC: 8, MiG_23MLD: 20, MiG_25PD: 24, - MiG_31: 28, + MiG_31: 26, Su_27: 24, Su_33: 25, - MiG_29A: 28, + MiG_29A: 26, - AJS37: 13, - F_5E: 8, + F_5E: 6, MiG_15bis: 5, - MiG_21Bis: 8, + MiG_21Bis: 6, + AJS37: 8, - M_2000C: 18, - FA_18C_hornet: 22, - F_15C: 28, + AV8BNA: 13, + M_2000C: 13, + FA_18C_hornet: 18, + F_15C: 24, # bomber - Su_25T: 15, - Su_24M: 18, - Su_17M4: 13, + Su_25T: 13, + Su_24M: 15, + Su_17M4: 10, L_39ZA: 10, - MiG_29G: 18, + MiG_29G: 15, Su_34: 22, A_10A: 18, @@ -97,6 +98,7 @@ UNIT_BY_TASK = { CAS: [ MiG_15bis, L_39ZA, + AV8BNA, A_10A, A_10C, Su_25T, @@ -148,6 +150,10 @@ SAM_BAN = [ AirDefence.SAM_SA_8_Osa_9A33, ] +TAKEOFF_BAN = [ + AV8BNA, +] + EXTRA_AA = { "Russia": AirDefence.SAM_SA_9_Strela_1_9P31, "USA": AirDefence.SAM_Patriot_EPP_III, @@ -167,6 +173,7 @@ UNIT_BY_COUNTRY = { MiG_21Bis, MiG_29A, M_2000C, + AV8BNA, A_10A, A_10C, @@ -209,6 +216,7 @@ UNIT_BY_COUNTRY = { A_10A, A_10C, + AV8BNA, S_3B_Tanker, C_130, @@ -229,8 +237,11 @@ UNIT_BY_COUNTRY = { PLANE_PAYLOAD_OVERRIDES = { FA_18C_hornet: { - Escort: "AIM-9M*6, AIM-7M*2, FUEL*3", - CAP: "AIM-9M*6, AIM-7M*2, FUEL*3", + "*": "AIM-9M*6, AIM-7M*2, FUEL*3", + }, + + AV8BNA: { + CAS: "AS 2", }, # TODO: figure out a way to setup su33 loadout diff --git a/game/event/__init__.py b/game/event/__init__.py index 9f5fe917..12902ff4 100644 --- a/game/event/__init__.py +++ b/game/event/__init__.py @@ -3,3 +3,4 @@ from .groundintercept import * from .intercept import * from .capture import * from .navalintercept import * +from .antiaastrike import * \ No newline at end of file diff --git a/game/event/antiaastrike.py b/game/event/antiaastrike.py index cac348ee..4ff8b839 100644 --- a/game/event/antiaastrike.py +++ b/game/event/antiaastrike.py @@ -51,7 +51,7 @@ class AntiAAStrikeEvent(Event): self.to_cp.base.affect_strength(-0.1) def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict): - self.targets = self.to_cp.base.assemble_aa() + self.targets = self.to_cp.base.assemble_aa(count=self.to_cp.base.total_aa) op = AntiAAStrikeOperation(game=self.game, attacker_name=self.attacker_name, diff --git a/game/event/capture.py b/game/event/capture.py index 06855515..d5020f03 100644 --- a/game/event/capture.py +++ b/game/event/capture.py @@ -79,6 +79,7 @@ class CaptureEvent(Event): self.operation = op def player_attacking(self, cas: db.PlaneDict, escort: db.PlaneDict, armor: db.ArmorDict, clients: db.PlaneDict): + # TODO: also include CAS planes interceptors = self.to_cp.base.scramble_sweep() op = CaptureOperation(game=self.game, @@ -93,6 +94,7 @@ class CaptureEvent(Event): escort=escort, attack=armor, intercept=interceptors, + # TODO: should strength affect this? defense=self.to_cp.base.armor, aa=self.to_cp.base.assemble_aa()) diff --git a/game/game.py b/game/game.py index 49b36dbb..c475cf10 100644 --- a/game/game.py +++ b/game/game.py @@ -9,6 +9,7 @@ from userdata.debriefing import Debriefing from theater import * from . import db +from .settings import Settings from .event import * COMMISION_LIMITS_SCALE = 2 @@ -33,29 +34,32 @@ ENEMY_INTERCEPT_PROBABILITY_BASE = 5 ENEMY_CAPTURE_PROBABILITY_BASE = 4 ENEMY_GROUNDINTERCEPT_PROBABILITY_BASE = 5 ENEMY_NAVALINTERCEPT_PROBABILITY_BASE = 5 +ENEMY_ANTIAASTRIKE_PROBABILITY_BASE = 5 ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE = 5 PLAYER_INTERCEPT_PROBABILITY_BASE = 35 PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 35 PLAYER_NAVALINTERCEPT_PROBABILITY_BASE = 35 +PLAYER_ANTIAASTRIKE_PROBABILITY_BASE = 35 PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 25 PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2 -PLAYER_BUDGET_INITIAL = 90 -PLAYER_BUDGET_BASE = 20 +PLAYER_BUDGET_INITIAL = 120 +PLAYER_BUDGET_BASE = 30 PLAYER_BUDGET_IMPORTANCE_LOG = 2 AWACS_BUDGET_COST = 4 class Game: + settings = None # type: Settings budget = PLAYER_BUDGET_INITIAL events = None # type: typing.List[Event] pending_transfers = None # type: typing.Dict[] - player_skill = "Good" - enemy_skill = "Average" + ignored_cps = None # type: typing.Collection[ControlPoint] def __init__(self, player_name: str, enemy_name: str, theater: ConflictTheater): + self.settings = Settings() self.events = [] self.theater = theater self.player = player_name @@ -73,12 +77,12 @@ class Game: to_cp=to_cp, game=self)) - def _generate_enemy_caps(self, ignored_cps: typing.Collection[ControlPoint] = None): + def _generate_enemy_caps(self): for from_cp, to_cp in self.theater.conflicts(False): if from_cp.base.total_planes == 0 or from_cp.base.total_armor == 0: continue - if ignored_cps and to_cp in ignored_cps: + if to_cp in self.ignored_cps: continue if self._roll(ENEMY_CAPTURE_PROBABILITY_BASE, from_cp.base.strength): @@ -90,13 +94,12 @@ class Game: break def _generate_interceptions(self): - enemy_interception = False for from_cp, to_cp in self.theater.conflicts(False): if from_cp.base.total_units(CAP) == 0: continue - if enemy_interception: - break + if to_cp in self.ignored_cps: + continue if self._roll(ENEMY_INTERCEPT_PROBABILITY_BASE, from_cp.base.strength): self.events.append(InterceptEvent(attacker_name=self.enemy, @@ -104,7 +107,6 @@ class Game: from_cp=from_cp, to_cp=to_cp, game=self)) - enemy_interception = True break if to_cp in self.theater.conflicts(False): @@ -118,7 +120,6 @@ class Game: from_cp=from_cp, to_cp=to_cp, game=self)) - enemy_interception = True break for from_cp, to_cp in self.theater.conflicts(True): @@ -141,6 +142,9 @@ class Game: break for from_cp, to_cp in self.theater.conflicts(False): + if to_cp in self.ignored_cps: + continue + if self._roll(ENEMY_GROUNDINTERCEPT_PROBABILITY_BASE, from_cp.base.strength): self.events.append(GroundInterceptEvent(attacker_name=self.enemy, defender_name=self.player, @@ -166,6 +170,9 @@ class Game: if to_cp.radials == LAND: continue + if to_cp in self.ignored_cps: + continue + if self._roll(ENEMY_NAVALINTERCEPT_PROBABILITY_BASE, from_cp.base.strength): self.events.append(NavalInterceptEvent(attacker_name=self.enemy, defender_name=self.player, @@ -188,6 +195,34 @@ class Game: game=self)) break + def _generate_aastrikes(self): + for from_cp, to_cp in self.theater.conflicts(True): + if to_cp.base.total_aa == 0: + continue + + if self._roll(PLAYER_ANTIAASTRIKE_PROBABILITY_BASE, from_cp.base.strength): + self.events.append(AntiAAStrikeEvent(attacker_name=self.player, + defender_name=self.enemy, + from_cp=from_cp, + to_cp=to_cp, + game=self)) + break + + for from_cp, to_cp in self.theater.conflicts(False): + if to_cp in self.ignored_cps: + continue + + if to_cp.base.total_aa == 0: + continue + + if self._roll(ENEMY_ANTIAASTRIKE_PROBABILITY_BASE, from_cp.base.strength): + self.events.append(AntiAAStrikeEvent(attacker_name=self.enemy, + defender_name=self.player, + from_cp=from_cp, + to_cp=to_cp, + game=self)) + break + def _commision_units(self, cp: ControlPoint): for for_task in [PinpointStrike, CAS, CAP, AirDefence]: limit = COMMISION_LIMITS_FACTORS[for_task] * math.pow(cp.importance, COMMISION_LIMITS_SCALE) @@ -253,11 +288,16 @@ class Game: for cp in self.theater.enemy_points(): self._commision_units(cp) + self.ignored_cps = [] + if ignored_cps: + self.ignored_cps = ignored_cps + self.events = [] # type: typing.List[Event] self._fill_cap_events() - self._generate_enemy_caps(ignored_cps=ignored_cps) + self._generate_enemy_caps() self._generate_interceptions() self._generate_globalinterceptions() self._generate_groundinterceptions() self._generate_navalinterceptions() + self._generate_aastrikes() diff --git a/game/operation/operation.py b/game/operation/operation.py index 088b81d5..d6c84bb2 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -44,7 +44,7 @@ class Operation: self.conflict = conflict self.armorgen = ArmorConflictGenerator(mission, conflict) - self.airgen = AircraftConflictGenerator(mission, conflict) + 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) diff --git a/game/settings.py b/game/settings.py new file mode 100644 index 00000000..1b969ef0 --- /dev/null +++ b/game/settings.py @@ -0,0 +1,5 @@ + +class Settings: + player_skill = "Good" + enemy_skill = "Average" + only_player_takeoff = False diff --git a/gen/aaa.py b/gen/aaa.py index 39b4809d..9cc5afb4 100644 --- a/gen/aaa.py +++ b/gen/aaa.py @@ -45,15 +45,20 @@ class ExtraAAConflictGenerator: if cp.is_global: continue - if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MIN_DISTANCE: - country_name = cp.captured and self.player_name or self.enemy_name - position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP) + if cp.position.distance_to_point(self.conflict.position) < EXTRA_AA_MIN_DISTANCE: + continue - self.mission.vehicle_group( - country=self.mission.country(country_name), - name=namegen.next_ground_group_name(), - _type=db.EXTRA_AA[country_name], - position=position, - group_size=2 - ) + if cp.position.distance_to_point(self.conflict.from_cp.position) < EXTRA_AA_MIN_DISTANCE: + continue + + country_name = cp.captured and self.player_name or self.enemy_name + position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP) + + self.mission.vehicle_group( + country=self.mission.country(country_name), + name=namegen.next_ground_group_name(), + _type=db.EXTRA_AA[country_name], + position=position, + group_size=2 + ) diff --git a/gen/aircraft.py b/gen/aircraft.py index ee21aff8..61a645c5 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -1,4 +1,5 @@ from game import db +from game.settings import Settings from .conflictgen import * from .naming import * @@ -12,23 +13,24 @@ SPREAD_DISTANCE_FACTOR = 1, 2 ESCORT_MAX_DIST = 30000 WORKAROUND_WAYP_DIST = 1000 -WARM_START_ALTITUDE = 3600 -WARM_START_AIRSPEED = 600 -INTERCEPTION_AIRSPEED = 1200 +WARM_START_ALTITUDE = 4600 +INTERCEPTION_ALT = 4600 +CAS_ALTITUDE = 4600 +RTB_ALTITUDE = 4600 +TRANSPORT_LANDING_ALT = 4600 -TRANSPORT_LANDING_ALT = 500 - -INTERCEPTION_ALT = 3600 -CAS_ALTITUDE = 1000 -RTB_ALTITUDE = 1000 +WARM_START_AIRSPEED = 540 +INTERCEPTION_AIRSPEED = 1000 INTERCEPT_MAX_DISTANCE = 80000 + class AircraftConflictGenerator: escort_targets = [] # type: typing.List[PlaneGroup] - def __init__(self, mission: Mission, conflict: Conflict): + def __init__(self, mission: Mission, conflict: Conflict, settings: Settings): self.m = mission + self.settings = settings self.conflict = conflict self.escort_targets = [] @@ -134,10 +136,15 @@ class AircraftConflictGenerator: elif isinstance(at, ShipGroup): return self._generate_at_carrier(name, side, unit_type, count, client_count, at) elif issubclass(at, Airport): - try: - return self._generate_at_airport(name, side, unit_type, count, client_count, at) - except NoParkingSlotError: - return self._generate_inflight(name, side, unit_type, count, client_count, at.position) + takeoff_ban = unit_type in db.TAKEOFF_BAN + ai_ban = client_count == 0 and self.settings.only_player_takeoff + + if not takeoff_ban and not ai_ban: + try: + return self._generate_at_airport(name, side, unit_type, count, client_count, at) + except NoParkingSlotError: + pass + return self._generate_inflight(name, side, unit_type, count, client_count, at.position) else: assert False diff --git a/gen/conflictgen.py b/gen/conflictgen.py index 27ddd1b0..1be0f22d 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -144,7 +144,7 @@ class Conflict: @classmethod def ground_intercept_conflict(cls, attacker: Country, defender: Country, heading: int, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): heading = random.choice(to_cp.radials) - initial_location = to_cp.position.point_from_heading(heading, to_cp.size * GROUNDINTERCEPT_DISTANCE_FACTOR), + initial_location = to_cp.position.point_from_heading(heading, to_cp.size * GROUNDINTERCEPT_DISTANCE_FACTOR) max_distance = to_cp.size * GROUNDINTERCEPT_DISTANCE_FACTOR ground_location = Conflict._find_ground_location(initial_location, max_distance, _heading_sum(heading, 180), theater) diff --git a/gen/settingsgen.py b/gen/settingsgen.py index e2f71637..e5daaeaa 100644 --- a/gen/settingsgen.py +++ b/gen/settingsgen.py @@ -7,13 +7,20 @@ from dcs.triggers import * from dcs.condition import * from dcs.action import * from dcs.unit import Skill +from dcs.point import MovingPoint, PointProperties +from dcs.action import * from game import db from theater import * from gen import * ACTIVATION_TRIGGER_SIZE = 40000 -ACTIVATION_TRIGGER_MIN_DISTANCE = 5000 +ACTIVATION_TRIGGER_MIN_DISTANCE = 20000 + +PUSH_TRIGGER_SIZE = 3000 + +REGROUP_ZONE_DISTANCE = 12000 +REGROUP_ALT = 5000 RANDOM_TIME = { "night": 5, @@ -23,8 +30,8 @@ RANDOM_TIME = { } RANDOM_WEATHER = { - 1: 10, # heavy rain - 2: 20, # rain + 1: 5, # heavy rain + 2: 15, # rain 3: 100, # random dynamic } @@ -77,10 +84,10 @@ class SettingsGenerator: vehicle_group.late_activation = True activate_by_trigger.append(vehicle_group) - zone_distance_to_aircraft = self.conflict.air_attackers_location.distance_to_point(self.conflict.position) + zone_distance_to_aircraft = self.conflict.from_cp.position.distance_to_point(self.conflict.position) zone_size = min(zone_distance_to_aircraft - ACTIVATION_TRIGGER_MIN_DISTANCE, ACTIVATION_TRIGGER_SIZE) - activation_trigger_zone = self.mission.triggers.add_triggerzone(self.conflict.position, zone_size) + activation_trigger_zone = self.mission.triggers.add_triggerzone(self.conflict.position, zone_size, name="Activation zone") activation_trigger = TriggerOnce(Event.NoEvent, "Activation trigger") activation_trigger.add_condition(PartOfCoalitionInZone(player_coalition, activation_trigger_zone.id)) for group in activate_by_trigger: @@ -88,6 +95,39 @@ class SettingsGenerator: self.mission.triggerrules.triggers.append(activation_trigger) + def _gen_push_trigger(self, player_coalition: str): + push_by_trigger = [] + for coalition_name, coalition in self.mission.coalition.items(): + for country in coalition.countries.values(): + if coalition_name == player_coalition: + for plane_group in country.plane_group: + regroup_heading = self.conflict.to_cp.position.heading_between_point(self.conflict.from_cp.position) + + pos1 = plane_group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE) + pos2 = plane_group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE+5000) + w1 = plane_group.add_waypoint(pos1, REGROUP_ALT) + w2 = plane_group.add_waypoint(pos2, REGROUP_ALT) + + plane_group.points.remove(w1) + plane_group.points.remove(w2) + + plane_group.points.insert(1, w2) + plane_group.points.insert(1, w1) + + w2.tasks.append(SwitchWaypoint(from_waypoint=3, to_waypoint=2)) + plane_group.add_trigger_action(SwitchWaypoint(to_waypoint=4)) + push_by_trigger.append(plane_group) + + push_trigger_zone = self.mission.triggers.add_triggerzone(self.conflict.from_cp.position, PUSH_TRIGGER_SIZE, name="Push zone") + push_trigger = TriggerOnce(Event.NoEvent, "Push trigger") + push_trigger.add_condition(AllOfCoalitionOutsideZone(player_coalition, push_trigger_zone.id)) + for group in push_by_trigger: + push_trigger.add_action(AITaskPush(group.id, 1)) + message_string = self.mission.string("Task force is in the air, proceed with the objective.") + push_trigger.add_action(MessageToAll(message_string, clearview=True)) + + self.mission.triggerrules.triggers.append(push_trigger) + def _set_allegiances(self, player_coalition: str, enemy_coalition: str): for cp in self.game.theater.controlpoints: if cp.is_global: @@ -96,7 +136,13 @@ class SettingsGenerator: def _set_skill(self, player_coalition: str, enemy_coalition: str): for coalition_name, coalition in self.mission.coalition.items(): - skill_level = player_coalition == coalition_name and self.game.player_skill or self.game.enemy_skill + if coalition_name == player_coalition: + skill_level = self.game.settings.player_skill + elif coalition_name == enemy_coalition: + skill_level = self.game.settings.enemy_skill + else: + continue + for country in coalition.countries.values(): for plane_group in country.plane_group: for plane_unit in plane_group.units: @@ -119,4 +165,6 @@ class SettingsGenerator: self._set_allegiances(player_coalition, enemy_coalition) if not is_quick: + # TODO: waypoint parts of this should not be post-hacked but added in airgen self._gen_activation_trigger(player_coalition, enemy_coalition) + self._gen_push_trigger(player_coalition) diff --git a/theater/base.py b/theater/base.py index d7543290..e682e755 100644 --- a/theater/base.py +++ b/theater/base.py @@ -54,6 +54,7 @@ class Base: def _find_best_unit(self, dict, for_type: Task, count: int) -> typing.Dict: if count <= 0: + print("{}: no units for {}".format(self, for_type)) return {} sorted_units = [key for key in dict.keys() if key in db.UNIT_BY_TASK[for_type]] @@ -74,6 +75,7 @@ class Base: assert result_unit_count > 0 result[unit_type] = result.get(unit_type, 0) + result_unit_count + print("{} for {} ({}): {}".format(self, for_type, count, result)) return result def _find_best_planes(self, for_type: Task, count: int) -> typing.Dict[PlaneType, int]: @@ -150,7 +152,7 @@ class Base: return min(min(max(count, PLANES_SCRAMBLE_MIN), PLANES_SCRAMBLE_MAX), self.total_planes) def assemble_count(self): - return self.total_armor * self.strength + return int(self.total_armor * self.strength) def assemble_aa_count(self) -> int: return int(self.total_aa * (self.strength > 0.2 and self.strength or 0)) @@ -170,5 +172,5 @@ class Base: def assemble_defense(self) -> typing.Dict[Armor, int]: return self._find_best_armor(PinpointStrike, self.assemble_count()) - def assemble_aa(self) -> typing.Dict[AirDefence, int]: - return self._find_best_unit(self.aa, AirDefence, self.assemble_aa_count()) + def assemble_aa(self, count=None) -> typing.Dict[AirDefence, int]: + return self._find_best_unit(self.aa, AirDefence, count and min(count, self.total_aa) or self.assemble_aa_count()) diff --git a/theater/caucasus.py b/theater/caucasus.py index 0f86e47e..76c27c96 100644 --- a/theater/caucasus.py +++ b/theater/caucasus.py @@ -1,3 +1,5 @@ +import re + from dcs.terrain import caucasus from dcs import mapping @@ -70,3 +72,8 @@ class CaucasusTheater(ConflictTheater): self.carrier_1.captured = True self.soganlug.captured = True + + def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []): + point.name = " ".join(re.split(r" |-", point.name)[:1]) + + super(CaucasusTheater, self).add_controlpoint(point, connected_to=connected_to) \ No newline at end of file diff --git a/theater/persiangulf.py b/theater/persiangulf.py index 68dc1708..1948f1c8 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -77,8 +77,6 @@ class PersianGulfTheater(ConflictTheater): """ Mid game: - """ - self.al_maktoum.captured = True self.al_minhad.captured = True self.dubai.captured = True @@ -86,3 +84,4 @@ class PersianGulfTheater(ConflictTheater): self.fujairah.captured = True self.khasab.captured = True self.sir_abu_nuayr.captured = True + """ diff --git a/ui/configurationmenu.py b/ui/configurationmenu.py index 51485a30..c20e8f51 100644 --- a/ui/configurationmenu.py +++ b/ui/configurationmenu.py @@ -9,14 +9,18 @@ class ConfigurationMenu(Menu): super(ConfigurationMenu, self).__init__(window, parent, game) self.frame = window.right_pane self.player_skill_var = StringVar() - self.player_skill_var.set(self.game.player_skill) + self.player_skill_var.set(self.game.settings.player_skill) self.enemy_skill_var = StringVar() - self.enemy_skill_var.set(self.game.enemy_skill) + self.enemy_skill_var.set(self.game.settings.enemy_skill) + + self.takeoff_var = BooleanVar() + self.takeoff_var.set(self.game.settings.only_player_takeoff) def dismiss(self): - self.game.player_skill = self.player_skill_var.get() - self.game.enemy_skill = self.enemy_skill_var.get() + self.game.settings.player_skill = self.player_skill_var.get() + self.game.settings.enemy_skill = self.enemy_skill_var.get() + self.game.settings.only_player_takeoff = self.takeoff_var.get() super(ConfigurationMenu, self).dismiss() def display(self): @@ -28,8 +32,10 @@ class ConfigurationMenu(Menu): OptionMenu(self.frame, self.player_skill_var, "Average", "Good", "High", "Excellent").grid(row=0, column=1) OptionMenu(self.frame, self.enemy_skill_var, "Average", "Good", "High", "Excellent").grid(row=1, column=1) - Button(self.frame, text="Back", command=self.dismiss).grid(row=2, column=0, columnspan=1) - Button(self.frame, text="Cheat +200m", command=self.cheat_money).grid(row=3, column=0) + Checkbutton(self.frame, text="Takeoff only for player group", variable=self.takeoff_var).grid(row=2, column=0, columnspan=2) + + Button(self.frame, text="Back", command=self.dismiss).grid(row=3, column=0, columnspan=1) + Button(self.frame, text="Cheat +200m", command=self.cheat_money).grid(row=4, column=0) def cheat_money(self): self.game.budget += 200 diff --git a/ui/eventmenu.py b/ui/eventmenu.py index c8d7bfe7..7fc6a1f0 100644 --- a/ui/eventmenu.py +++ b/ui/eventmenu.py @@ -66,7 +66,11 @@ class EventMenu(Menu): row += 1 - Label(self.frame, text="{}. {}".format(self.event, self.event.threat_description)).grid(row=row, column=0, columnspan=5) + threat_descr = self.event.threat_description + if threat_descr: + threat_descr = "Approx. {}".format(threat_descr) + + Label(self.frame, text="{}. {}".format(self.event, threat_descr)).grid(row=row, column=0, columnspan=5) row += 1 Button(self.frame, text="Commit", command=self.start).grid(column=3, row=row, sticky=E) @@ -198,6 +202,12 @@ class EventMenu(Menu): e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) else: e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients) + elif type(self.event) is AntiAAStrikeEvent: + e = self.event # type: AntiAAStrikeEvent + if self.game.is_player_attack(self.event): + e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) + else: + e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients) self.game.initiate_event(self.event) EventResultsMenu(self.window, self.parent, self.game, self.event).display()