From 78ab7cadd4eb94d5b10894bde86881615337435a Mon Sep 17 00:00:00 2001 From: Vasyl Horbachenko Date: Tue, 19 Jun 2018 03:11:01 +0300 Subject: [PATCH] naval interceptions fixed; unit placement fixes --- game/db.py | 16 ++- game/event/capture.py | 6 +- game/event/groundintercept.py | 42 +++++- game/event/navalintercept.py | 18 ++- game/game.py | 29 ++++- game/operation/capture.py | 3 +- game/operation/groundintercept.py | 20 ++- game/operation/intercept.py | 3 +- game/operation/navalintercept.py | 25 ++-- gen/aaa.py | 2 +- gen/aircraft.py | 7 +- gen/conflictgen.py | 195 ++++++++++++++++++---------- gen/shipgen.py | 2 +- resources/caulandmap.p | Bin 3700 -> 3704 bytes resources/tools/generate_landmap.py | 4 +- theater/base.py | 2 +- theater/caucasus.py | 36 ++--- theater/conflicttheater.py | 24 +++- theater/controlpoint.py | 2 +- theater/nevada.py | 24 ++-- theater/persiangulf.py | 34 ++--- ui/eventmenu.py | 11 +- ui/overviewcanvas.py | 3 +- userdata/debriefing.py | 11 +- 24 files changed, 342 insertions(+), 177 deletions(-) diff --git a/game/db.py b/game/db.py index 20b1a091..84df67b2 100644 --- a/game/db.py +++ b/game/db.py @@ -72,8 +72,10 @@ PRICES = { CV_1143_5_Admiral_Kuznetsov: 100, CVN_74_John_C__Stennis: 100, - Bulk_cargo_ship_Yakushev: 100, - Dry_cargo_ship_Ivanov: 100, + LHA_1_Tarawa: 30, + Bulk_cargo_ship_Yakushev: 10, + Dry_cargo_ship_Ivanov: 10, + Tanker_Elnya_160: 10, } UNIT_BY_TASK = { @@ -135,7 +137,7 @@ UNIT_BY_TASK = { ], Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ], - CargoTransportation: [Dry_cargo_ship_Ivanov, Bulk_cargo_ship_Yakushev], + CargoTransportation: [Dry_cargo_ship_Ivanov, Bulk_cargo_ship_Yakushev, Tanker_Elnya_160, LHA_1_Tarawa], } SAM_BAN = [ @@ -193,6 +195,7 @@ UNIT_BY_COUNTRY = { CV_1143_5_Admiral_Kuznetsov, Bulk_cargo_ship_Yakushev, Dry_cargo_ship_Ivanov, + Tanker_Elnya_160, ], "USA": [ @@ -220,15 +223,14 @@ UNIT_BY_COUNTRY = { AirDefence.SAM_Patriot_ICC, CVN_74_John_C__Stennis, - # TODO: verify or find out proper USA cargo ship - Bulk_cargo_ship_Yakushev, - Dry_cargo_ship_Ivanov, + LHA_1_Tarawa, ], } PLANE_PAYLOAD_OVERRIDES = { FA_18C_hornet: { - "*": "AIM-9M*6, AIM-7M*2, FUEL*3", + Escort: "AIM-9M*6, AIM-7M*2, FUEL*3", + CAP: "AIM-9M*6, AIM-7M*2, FUEL*3", }, # TODO: figure out a way to setup su33 loadout diff --git a/game/event/capture.py b/game/event/capture.py index c1f44283..06855515 100644 --- a/game/event/capture.py +++ b/game/event/capture.py @@ -1,6 +1,8 @@ import math import random +from dcs.task import * + from game import db from game.operation.capture import CaptureOperation from userdata.debriefing import Debriefing @@ -29,8 +31,8 @@ class CaptureEvent(Event): return descr def is_successfull(self, debriefing: Debriefing): - alive_attackers = sum(debriefing.alive_units[self.attacker_name].values()) - alive_defenders = sum(debriefing.alive_units[self.defender_name].values()) + 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]) attackers_success = alive_attackers > alive_defenders if self.from_cp.captured: return attackers_success diff --git a/game/event/groundintercept.py b/game/event/groundintercept.py index 2e5f1814..0508e6e7 100644 --- a/game/event/groundintercept.py +++ b/game/event/groundintercept.py @@ -5,6 +5,7 @@ from dcs.task import * from game import * from game.event import * +from game.operation.groundintercept import GroundInterceptOperation from userdata.debriefing import Debriefing @@ -27,7 +28,10 @@ class GroundInterceptEvent(Event): if unit in self.targets: destroyed_targets += count - return (float(destroyed_targets) / float(total_targets)) >= self.SUCCESS_TARGETS_HIT_PERCENTAGE + if self.from_cp.captured: + return math.ceil(float(destroyed_targets) / total_targets) >= self.SUCCESS_TARGETS_HIT_PERCENTAGE + else: + return math.ceil(float(destroyed_targets) / total_targets) < self.SUCCESS_TARGETS_HIT_PERCENTAGE def commit(self, debriefing: Debriefing): super(GroundInterceptEvent, self).commit(debriefing) @@ -38,13 +42,14 @@ class GroundInterceptEvent(Event): else: self.to_cp.base.affect_strength(+self.STRENGTH_INFLUENCE) else: - assert False + 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): - if not self.to_cp.captured: - self.to_cp.base.affect_strength(+0.1) - else: - pass + if self.to_cp.captured: + self.to_cp.base.affect_strength(-0.1) def player_attacking(self, strikegroup: db.PlaneDict, clients: db.PlaneDict): suitable_unittypes = db.find_unittype(PinpointStrike, self.defender_name) @@ -61,8 +66,31 @@ class GroundInterceptEvent(Event): from_cp=self.from_cp, to_cp=self.to_cp) op.setup(target=self.targets, - strikegroup=strikegroup) + strikegroup=strikegroup, + interceptors={}) self.operation = op + def player_defending(self, interceptors: db.PlaneDict, clients: db.PlaneDict): + suitable_unittypes = db.find_unittype(PinpointStrike, self.defender_name) + random.shuffle(suitable_unittypes) + unittypes = suitable_unittypes[:self.TARGET_VARIETY] + typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1) + self.targets = {unittype: typecount for unittype in unittypes} + op = GroundInterceptOperation( + self.game, + attacker_name=self.attacker_name, + defender_name=self.defender_name, + attacker_clients={}, + defender_clients=clients, + from_cp=self.from_cp, + to_cp=self.to_cp + ) + + strikegroup = self.from_cp.base.scramble_cas() + op.setup(target=self.targets, + strikegroup=strikegroup, + interceptors=interceptors) + + self.operation = op diff --git a/game/event/navalintercept.py b/game/event/navalintercept.py index 95bea82c..be543e6e 100644 --- a/game/event/navalintercept.py +++ b/game/event/navalintercept.py @@ -14,13 +14,14 @@ from .event import Event class NavalInterceptEvent(Event): STRENGTH_INFLUENCE = 0.3 + SUCCESS_RATE = 0.5 targets = None # type: db.ShipDict def _targets_count(self) -> int: from gen.conflictgen import IMPORTANCE_LOW, IMPORTANCE_HIGH factor = (self.to_cp.importance - IMPORTANCE_LOW) * 10 - return min(int(factor), 1) + return max(int(factor), 1) def __str__(self) -> str: return "Naval intercept at {}".format(self.to_cp) @@ -33,11 +34,16 @@ class NavalInterceptEvent(Event): return s def is_successfull(self, debriefing: Debriefing): - targets_destroyed = [c for t, c in debriefing.destroyed_units.items() if t in self.targets.values()] + total_targets = sum(self.targets.values()) + destroyed_targets = 0 + for unit, count in debriefing.destroyed_units[self.defender_name].items(): + if unit in self.targets: + destroyed_targets += count + if self.from_cp.captured: - return targets_destroyed > 0 + return math.ceil(float(destroyed_targets) / total_targets) > self.SUCCESS_RATE else: - return targets_destroyed == 0 + return math.ceil(float(destroyed_targets) / total_targets) < self.SUCCESS_RATE def commit(self, debriefing: Debriefing): super(NavalInterceptEvent, self).commit(debriefing) @@ -88,8 +94,8 @@ class NavalInterceptEvent(Event): self.game, attacker_name=self.attacker_name, defender_name=self.defender_name, - attacker_clients=clients, - defender_clients={}, + attacker_clients={}, + defender_clients=clients, from_cp=self.from_cp, to_cp=self.to_cp ) diff --git a/game/game.py b/game/game.py index 76c6a3f5..1aeb21b0 100644 --- a/game/game.py +++ b/game/game.py @@ -32,10 +32,12 @@ COMMISION_AMOUNTS_FACTORS = { ENEMY_INTERCEPT_PROBABILITY_BASE = 8 ENEMY_INTERCEPT_GLOBAL_PROBABILITY_BASE = 5 ENEMY_CAPTURE_PROBABILITY_BASE = 4 +ENEMY_GROUNDINTERCEPT_PROBABILITY_BASE = 8 +ENEMY_NAVALINTERCEPT_PROBABILITY_BASE = 8 PLAYER_INTERCEPT_PROBABILITY_BASE = 35 PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 35 - +PLAYER_NAVALINTERCEPT_PROBABILITY_BASE = 35 PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 25 PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2 @@ -135,12 +137,21 @@ class Game: game=self)) break + for from_cp, to_cp in self.theater.conflicts(False): + if self._roll(ENEMY_GROUNDINTERCEPT_PROBABILITY_BASE, from_cp.base.strength): + self.events.append(GroundInterceptEvent(attacker_name=self.enemy, + defender_name=self.player, + from_cp=from_cp, + to_cp=to_cp, + game=self)) + break + def _generate_navalinterceptions(self): for from_cp, to_cp in self.theater.conflicts(True): - if to_cp.radials == ALL_RADIALS: + if to_cp.radials == LAND: continue - if self._roll(100, from_cp.base.strength): + if self._roll(PLAYER_NAVALINTERCEPT_PROBABILITY_BASE, from_cp.base.strength): self.events.append(NavalInterceptEvent(attacker_name=self.player, defender_name=self.enemy, from_cp=from_cp, @@ -148,6 +159,18 @@ class Game: game=self)) break + for from_cp, to_cp in self.theater.conflicts(False): + if to_cp.radials == LAND: + continue + + if self._roll(ENEMY_NAVALINTERCEPT_PROBABILITY_BASE, from_cp.base.strength): + self.events.append(NavalInterceptEvent(attacker_name=self.enemy, + defender_name=self.player, + from_cp=from_cp, + to_cp=to_cp, + game=self)) + break + def _generate_globalinterceptions(self): global_count = len([x for x in self.theater.player_points() if x.is_global]) for from_cp in [x for x in self.theater.player_points() if x.is_global]: diff --git a/game/operation/capture.py b/game/operation/capture.py index 20eb24a0..d8cbdfea 100644 --- a/game/operation/capture.py +++ b/game/operation/capture.py @@ -44,7 +44,8 @@ class CaptureOperation(Operation): attacker=self.mission.country(self.attacker_name), defender=self.mission.country(self.defender_name), from_cp=self.from_cp, - to_cp=self.to_cp + to_cp=self.to_cp, + theater=self.game.theater ) self.initialize(mission=self.mission, conflict=conflict) diff --git a/game/operation/groundintercept.py b/game/operation/groundintercept.py index 3750cad7..1153a328 100644 --- a/game/operation/groundintercept.py +++ b/game/operation/groundintercept.py @@ -13,20 +13,31 @@ from gen.conflictgen import Conflict from .operation import Operation class GroundInterceptOperation(Operation): + strikegroup = None # type: db.PlaneDict + interceptors = None # type: db.PlaneDict + target = None # type: db.ArmorDict + def setup(self, target: db.ArmorDict, - strikegroup: db.PlaneDict): + strikegroup: db.PlaneDict, + interceptors: db.PlaneDict): self.strikegroup = strikegroup + self.interceptors = interceptors self.target = target def prepare(self, terrain: Terrain, is_quick: bool): super(GroundInterceptOperation, self).prepare(terrain, is_quick) + if self.defender_name == self.game.player: + self.attackers_starting_position = None + self.defenders_starting_position = None + conflict = Conflict.ground_intercept_conflict( attacker=self.mission.country(self.attacker_name), defender=self.mission.country(self.defender_name), heading=self.to_cp.position.heading_between_point(self.from_cp.position), from_cp=self.from_cp, - to_cp=self.to_cp + to_cp=self.to_cp, + theater=self.game.theater ) self.initialize(mission=self.mission, @@ -34,6 +45,9 @@ class GroundInterceptOperation(Operation): def generate(self): self.airgen.generate_cas_strikegroup(self.strikegroup, clients=self.attacker_clients, at=self.attackers_starting_position) - self.armorgen.generate({}, self.target) + if self.interceptors: + self.airgen.generate_defense(self.interceptors, clients=self.defender_clients, at=self.defenders_starting_position) + + self.armorgen.generate({}, self.target) super(GroundInterceptOperation, self).generate() diff --git a/game/operation/intercept.py b/game/operation/intercept.py index 92cb09f3..4d99bc44 100644 --- a/game/operation/intercept.py +++ b/game/operation/intercept.py @@ -30,7 +30,8 @@ class InterceptOperation(Operation): attacker=self.mission.country(self.attacker_name), defender=self.mission.country(self.defender_name), from_cp=self.from_cp, - to_cp=self.to_cp + to_cp=self.to_cp, + theater=self.game.theater ) self.initialize(mission=self.mission, diff --git a/game/operation/navalintercept.py b/game/operation/navalintercept.py index 76db55fd..b5ef999c 100644 --- a/game/operation/navalintercept.py +++ b/game/operation/navalintercept.py @@ -19,13 +19,15 @@ class NavalInterceptionOperation(Operation): def prepare(self, terrain: Terrain, is_quick: bool): super(NavalInterceptionOperation, self).prepare(terrain, is_quick) + if self.defender_name == self.game.player: + self.attackers_starting_position = None conflict = Conflict.naval_intercept_conflict( attacker=self.mission.country(self.attacker_name), defender=self.mission.country(self.defender_name), - theater=self.game.theater, from_cp=self.from_cp, - to_cp=self.to_cp + to_cp=self.to_cp, + theater=self.game.theater ) self.initialize(self.mission, conflict) @@ -33,17 +35,18 @@ class NavalInterceptionOperation(Operation): def generate(self): super(NavalInterceptionOperation, self).generate() + target_groups = self.shipgen.generate_cargo(units=self.targets) + self.airgen.generate_ship_strikegroup( - attackers= self.strikegroup, + attackers=self.strikegroup, clients=self.attacker_clients, + target_groups=target_groups, at=self.attackers_starting_position ) - self.airgen.generate_interception( - interceptors=self.interceptors, - clients=self.defender_clients, - at=self.defenders_starting_position - ) - - self.shipgen.generate_cargo(units=self.targets) - + if self.interceptors: + self.airgen.generate_defense( + defenders=self.interceptors, + clients=self.defender_clients, + at=self.defenders_starting_position + ) diff --git a/gen/aaa.py b/gen/aaa.py index b1354cae..39b4809d 100644 --- a/gen/aaa.py +++ b/gen/aaa.py @@ -6,7 +6,7 @@ from .naming import * from dcs.mission import * -DISTANCE_FACTOR = 2, 4 +DISTANCE_FACTOR = 0.5, 1 EXTRA_AA_MIN_DISTANCE = 35000 EXTRA_AA_POSITION_FROM_CP = 550 diff --git a/gen/aircraft.py b/gen/aircraft.py index 1896190f..ee21aff8 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -195,7 +195,7 @@ class AircraftConflictGenerator: group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) - def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): + 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 for flying_type, count, client_count in self._split_to_groups(attackers, clients): @@ -208,7 +208,10 @@ class AircraftConflictGenerator: at=at and at or self._group_point(self.conflict.air_attackers_location)) self.escort_targets.append(group) - group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) + wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) + for target_group in target_groups: + wayp.tasks.append(AttackGroup(target_group.id)) + group.task = AntishipStrike.name self._setup_group(group, AntishipStrike, clients) diff --git a/gen/conflictgen.py b/gen/conflictgen.py index 68a26c9f..27ddd1b0 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -17,8 +17,8 @@ from dcs.country import * from theater import * -GROUND_DISTANCE_FACTOR = 0.8 -GROUNDINTERCEPT_DISTANCE_FACTOR = 3 +GROUND_DISTANCE_FACTOR = 1 +GROUNDINTERCEPT_DISTANCE_FACTOR = 6 AIR_DISTANCE = 32000 INTERCEPT_ATTACKERS_HEADING = -45, 45 @@ -29,6 +29,7 @@ INTERCEPT_MAX_DISTANCE = 80000 INTERCEPT_MIN_DISTANCE = 45000 NAVAL_INTERCEPT_DISTANCE_FACTOR = 1.3 +NAVAL_INTERCEPT_DISTANCE_MAX = 90000 NAVAL_INTERCEPT_STEP = 3000 @@ -60,96 +61,148 @@ class Conflict: air_attackers_location = None # type: Point air_defenders_location = None # type: Point + def __init__(self, + position: Point, + theater: ConflictTheater, + from_cp: ControlPoint, + to_cp: ControlPoint, + attackers_side: Country, + defenders_side: Country, + ground_attackers_location: Point, + ground_defenders_location: Point, + air_attackers_location: Point, + air_defenders_location: Point): + self.attackers_side = attackers_side + self.defenders_side = defenders_side + self.from_cp = from_cp + self.to_cp = to_cp + self.theater = theater + self.position = position + self.size = to_cp.size + self.radials = to_cp.radials + self.ground_attackers_location = ground_attackers_location + self.ground_defenders_location = ground_defenders_location + self.air_attackers_location = air_attackers_location + self.air_defenders_location = air_defenders_location + @classmethod - def capture_conflict(self, attacker: Country, defender: Country, from_cp, to_cp): + def _find_ground_location(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point: + for _ in range(0, int(max_distance), 100): + if theater.is_on_land(initial): + return initial + + initial = initial.point_from_heading(heading, 100) + return initial + + @classmethod + def capture_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + position = to_cp.position attack_heading = to_cp.find_radial(to_cp.position.heading_between_point(from_cp.position)) defense_heading = to_cp.find_radial(from_cp.position.heading_between_point(to_cp.position), ignored_radial=attack_heading) - position = to_cp.position - instance = self() - instance.attackers_side = attacker - instance.defenders_side = defender - instance.from_cp = from_cp - instance.to_cp = to_cp - instance.position = position - instance.size = to_cp.size - instance.radials = to_cp.radials + distance = to_cp.size * GROUND_DISTANCE_FACTOR + attackers_location = position.point_from_heading(attack_heading, distance) + attackers_location = Conflict._find_ground_location(attackers_location, distance * 2, _heading_sum(attack_heading, 180), theater) - instance.ground_attackers_location = instance.position.point_from_heading(attack_heading, instance.size * GROUND_DISTANCE_FACTOR) - instance.ground_defenders_location = instance.position.point_from_heading(defense_heading, instance.size * GROUND_DISTANCE_FACTOR) + defenders_location = position.point_from_heading(defense_heading, distance) + defenders_location = Conflict._find_ground_location(defenders_location, distance * 2, _heading_sum(defense_heading, 180), theater) - instance.air_attackers_location = instance.position.point_from_heading(attack_heading, AIR_DISTANCE) - instance.air_defenders_location = instance.position.point_from_heading(defense_heading, AIR_DISTANCE) - - return instance + return cls( + position=position, + theater=theater, + from_cp=from_cp, + to_cp=to_cp, + attackers_side=attacker, + defenders_side=defender, + ground_attackers_location=attackers_location, + ground_defenders_location=defenders_location, + air_attackers_location=position.point_from_heading(attack_heading, AIR_DISTANCE), + air_defenders_location=position.point_from_heading(defense_heading, AIR_DISTANCE) + ) @classmethod - def intercept_conflict(self, attacker: Country, defender: Country, from_cp, to_cp): - from theater.conflicttheater import SIZE_REGULAR - from theater.conflicttheater import ALL_RADIALS - - heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), random.choice([-1, 1]) * random.randint(60, 100)) - + def intercept_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): raw_distance = from_cp.position.distance_to_point(to_cp.position) * 0.4 distance = max(min(raw_distance, INTERCEPT_MAX_DISTANCE), INTERCEPT_MIN_DISTANCE) + + heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), random.choice([-1, 1]) * random.randint(60, 100)) position = from_cp.position.point_from_heading(heading, distance) - instance = self() - instance.from_cp = from_cp - instance.to_cp = to_cp - instance.attackers_side = attacker - instance.defenders_side = defender - - instance.position = position - instance.size = SIZE_REGULAR - instance.radials = ALL_RADIALS - - instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, INTERCEPT_ATTACKERS_DISTANCE) - instance.air_defenders_location = instance.position - - return instance + return cls( + position=position, + theater=theater, + from_cp=from_cp, + 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, INTERCEPT_ATTACKERS_DISTANCE), + air_defenders_location=position + ) @classmethod - def ground_intercept_conflict(self, attacker: Country, defender: Country, heading: int, from_cp, to_cp): - instance = self() - instance.from_cp = from_cp - instance.to_cp = to_cp - instance.attackers_side = attacker - instance.defenders_side = defender + 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), + max_distance = to_cp.size * GROUNDINTERCEPT_DISTANCE_FACTOR + ground_location = Conflict._find_ground_location(initial_location, max_distance, _heading_sum(heading, 180), theater) - instance.position = to_cp.position - instance.size = to_cp.size - instance.radials = to_cp.radials - - instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE) - instance.ground_defenders_location = instance.position.point_from_heading(random.choice(to_cp.radials), instance.size * GROUNDINTERCEPT_DISTANCE_FACTOR) - - return instance + return cls( + position=to_cp.position, + theater=theater, + from_cp=from_cp, + to_cp=to_cp, + attackers_side=attacker, + defenders_side=defender, + ground_attackers_location=None, + ground_defenders_location=ground_location, + air_attackers_location=to_cp.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, AIR_DISTANCE), + air_defenders_location=to_cp.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + _opposite_heading(heading), AIR_DISTANCE) + ) @classmethod - def naval_intercept_conflict(cls, attacker: Country, defender: Country, theater: ConflictTheater, from_cp: ControlPoint, to_cp: ControlPoint): + def intercept_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): + raw_distance = from_cp.position.distance_to_point(to_cp.position) * 0.4 + distance = max(min(raw_distance, INTERCEPT_MAX_DISTANCE), INTERCEPT_MIN_DISTANCE) + + heading = _heading_sum(from_cp.position.heading_between_point(to_cp.position), random.choice([-1, 1]) * random.randint(60, 100)) + position = from_cp.position.point_from_heading(heading, distance) + + return cls( + position=position, + theater=theater, + from_cp=from_cp, + 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, INTERCEPT_ATTACKERS_DISTANCE), + air_defenders_location=position + ) + + @classmethod + def naval_intercept_conflict(cls, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater): radial = random.choice(to_cp.sea_radials) - initial_distance = int(from_cp.position.distance_to_point(to_cp.position) * NAVAL_INTERCEPT_DISTANCE_FACTOR) + initial_distance = min(int(from_cp.position.distance_to_point(to_cp.position) * NAVAL_INTERCEPT_DISTANCE_FACTOR), NAVAL_INTERCEPT_DISTANCE_MAX) position = to_cp.position.point_from_heading(radial, initial_distance) for offset in range(0, initial_distance, NAVAL_INTERCEPT_STEP): - if theater.is_on_land(position): + if not theater.is_on_land(position): + position = to_cp.position.point_from_heading(radial, initial_distance - offset) break - else: - position = to_cp.position.point_from_heading(radial, offset) - - instance = cls() - instance.from_cp = from_cp - instance.to_cp = to_cp - instance.attackers_side = attacker - instance.defenders_side = defender - - instance.position = position - instance.size = SIZE_REGULAR - instance.radials = to_cp.radials attacker_heading = from_cp.position.heading_between_point(to_cp.position) - instance.air_attackers_location = instance.position.point_from_heading(attacker_heading, AIR_DISTANCE) - instance.air_defenders_location = instance.position.point_from_heading(_opposite_heading(attacker_heading), AIR_DISTANCE) - - return instance + return cls( + position=position, + theater=theater, + from_cp=from_cp, + to_cp=to_cp, + attackers_side=attacker, + defenders_side=defender, + ground_attackers_location=None, + ground_defenders_location=position, + air_attackers_location=position.point_from_heading(attacker_heading, AIR_DISTANCE), + air_defenders_location=position.point_from_heading(_opposite_heading(attacker_heading), AIR_DISTANCE) + ) diff --git a/gen/shipgen.py b/gen/shipgen.py index 93b23207..18c9ec01 100644 --- a/gen/shipgen.py +++ b/gen/shipgen.py @@ -28,7 +28,7 @@ class ShipGenerator: country=self.conflict.defenders_side, name=namegen.next_transport_group_name(), _type=unit_type, - position=self.conflict.position.random_point_within(SHIP_RANDOM_SPREAD, SHIP_RANDOM_SPREAD), + position=self.conflict.ground_defenders_location.random_point_within(SHIP_RANDOM_SPREAD, SHIP_RANDOM_SPREAD), group_size=unit_count, ) diff --git a/resources/caulandmap.p b/resources/caulandmap.p index df8dc6352fa638e7e2207524dd0695eb0e149088..16ce2213ec994d383819bf03fb4658a9cbbc5e49 100644 GIT binary patch literal 3704 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 literal 3700 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 diff --git a/resources/tools/generate_landmap.py b/resources/tools/generate_landmap.py index 324ad725..500df0dd 100644 --- a/resources/tools/generate_landmap.py +++ b/resources/tools/generate_landmap.py @@ -4,11 +4,11 @@ from dcs.mission import Mission from dcs.terrain import PersianGulf m = Mission() -m.load_file("./gulf_terrain.miz") +m.load_file("tools/cau_terrain.miz") landmap = [] for plane_group in m.country("USA").plane_group: landmap.append([(x.position.x, x.position.y) for x in plane_group.points]) -with open("gulflandmap.p", "wb") as f: +with open("./caulandmap.p", "wb") as f: pickle.dump(landmap, f) diff --git a/theater/base.py b/theater/base.py index 3fdf068a..fb85442d 100644 --- a/theater/base.py +++ b/theater/base.py @@ -99,7 +99,7 @@ class Base: def filter_units(self, applicable_units: typing.Collection): self.aircraft = {k: v for k, v in self.aircraft.items() if k in applicable_units} - self.armor = {k: v for k, v in self.aircraft.items() if k in applicable_units} + self.armor = {k: v for k, v in self.armor.items() if k in applicable_units} def commision_units(self, units: typing.Dict[typing.Any, int]): for value in units.values(): diff --git a/theater/caucasus.py b/theater/caucasus.py index 4c3d32a9..0f86e47e 100644 --- a/theater/caucasus.py +++ b/theater/caucasus.py @@ -19,26 +19,26 @@ class CaucasusTheater(ConflictTheater): "night": (0, 5), } - soganlug = ControlPoint.from_airport(caucasus.Soganlug, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) - kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) - senaki = ControlPoint.from_airport(caucasus.Senaki_Kolkhi, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW) - kobuleti = ControlPoint.from_airport(caucasus.Kobuleti, COAST_NS_E, SIZE_SMALL, IMPORTANCE_LOW) - batumi = ControlPoint.from_airport(caucasus.Batumi, COAST_NS_E, SIZE_SMALL, IMPORTANCE_MEDIUM) - sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_NS_E, SIZE_REGULAR, IMPORTANCE_MEDIUM) - gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_NS_E, SIZE_REGULAR, IMPORTANCE_MEDIUM) - sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_NS_E, SIZE_BIG, IMPORTANCE_HIGH) + soganlug = ControlPoint.from_airport(caucasus.Soganlug, LAND, SIZE_SMALL, IMPORTANCE_LOW) + kutaisi = ControlPoint.from_airport(caucasus.Kutaisi, LAND, SIZE_SMALL, IMPORTANCE_LOW) + senaki = ControlPoint.from_airport(caucasus.Senaki_Kolkhi, LAND, SIZE_REGULAR, IMPORTANCE_LOW) + kobuleti = ControlPoint.from_airport(caucasus.Kobuleti, COAST_A_E, SIZE_SMALL, IMPORTANCE_LOW) + batumi = ControlPoint.from_airport(caucasus.Batumi, COAST_DL_E, SIZE_SMALL, IMPORTANCE_MEDIUM) + sukhumi = ControlPoint.from_airport(caucasus.Sukhumi_Babushara, COAST_DR_E, SIZE_REGULAR, IMPORTANCE_MEDIUM) + gudauta = ControlPoint.from_airport(caucasus.Gudauta, COAST_DR_E, SIZE_REGULAR, IMPORTANCE_MEDIUM) + sochi = ControlPoint.from_airport(caucasus.Sochi_Adler, COAST_DR_E, SIZE_BIG, IMPORTANCE_HIGH) - gelendzhik = ControlPoint.from_airport(caucasus.Gelendzhik, COAST_NS_E, SIZE_BIG, IMPORTANCE_MEDIUM) - maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) - krasnodar = ControlPoint.from_airport(caucasus.Krasnodar_Center, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) - novorossiysk = ControlPoint.from_airport(caucasus.Novorossiysk, COAST_NS_E, SIZE_BIG, IMPORTANCE_MEDIUM) - krymsk = ControlPoint.from_airport(caucasus.Krymsk, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) - anapa = ControlPoint.from_airport(caucasus.Anapa_Vityazevo, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) + gelendzhik = ControlPoint.from_airport(caucasus.Gelendzhik, COAST_DR_E, SIZE_BIG, IMPORTANCE_MEDIUM) + maykop = ControlPoint.from_airport(caucasus.Maykop_Khanskaya, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + krasnodar = ControlPoint.from_airport(caucasus.Krasnodar_Center, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + novorossiysk = ControlPoint.from_airport(caucasus.Novorossiysk, COAST_DR_E, SIZE_BIG, IMPORTANCE_MEDIUM) + krymsk = ControlPoint.from_airport(caucasus.Krymsk, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + anapa = ControlPoint.from_airport(caucasus.Anapa_Vityazevo, LAND, SIZE_LARGE, IMPORTANCE_HIGH) - beslan = ControlPoint.from_airport(caucasus.Beslan, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW) - nalchik = ControlPoint.from_airport(caucasus.Nalchik, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW) - mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM) - mozdok = ControlPoint.from_airport(caucasus.Mozdok, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM) + beslan = ControlPoint.from_airport(caucasus.Beslan, LAND, SIZE_REGULAR, IMPORTANCE_LOW) + nalchik = ControlPoint.from_airport(caucasus.Nalchik, LAND, SIZE_REGULAR, IMPORTANCE_LOW) + mineralnye = ControlPoint.from_airport(caucasus.Mineralnye_Vody, LAND, SIZE_BIG, IMPORTANCE_MEDIUM) + mozdok = ControlPoint.from_airport(caucasus.Mozdok, LAND, SIZE_BIG, IMPORTANCE_MEDIUM) carrier_1 = ControlPoint.carrier("Carrier", mapping.Point(-305810.6875, 406399.1875)) diff --git a/theater/conflicttheater.py b/theater/conflicttheater.py index 3aea52ca..ef65b03c 100644 --- a/theater/conflicttheater.py +++ b/theater/conflicttheater.py @@ -17,15 +17,32 @@ IMPORTANCE_LOW = 1 IMPORTANCE_MEDIUM = 1.2 IMPORTANCE_HIGH = 1.4 +""" ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ] COAST_NS_E = [45, 90, 135, ] COAST_EW_N = [315, 0, 45, ] +COAST_NSEW_E = [225, 270, 315, ] +COAST_NSEW_W = [45, 90, 135, ] COAST_NS_W = [225, 270, 315, ] COAST_EW_S = [135, 180, 225, ] +""" -COAST_SWNE = [45, 90, 135, 180, 225, ] -COAST_SENW = [135, 180, 225, 270, 315, ] +LAND = [0, 45, 90, 135, 180, 225, 270, 315, ] + +COAST_V_E = [0, 45, 90, 135, 180] +COAST_V_W = [180, 225, 270, 315, 0] + +COAST_A_W = [315, 0, 45, 135, 180, 225, 270] +COAST_A_E = [0, 45, 90, 135, 180, 225, 315] + +COAST_H_N = [270, 315, 0, 45, 90] +COAST_H_S = [90, 135, 180, 225, 270] + +COAST_DL_E = [45, 90, 135, 180, 225] +COAST_DL_W = [225, 270, 315, 0, 45] +COAST_DR_E = [315, 0, 45, 90, 135] +COAST_DR_W = [135, 180, 225, 315] class ConflictTheater: @@ -50,7 +67,8 @@ class ConflictTheater: return True for poly in self.landmap_poly: - return ray_tracing(point.x, point.y, poly) + if ray_tracing(point.x, point.y, poly): + return True return False diff --git a/theater/controlpoint.py b/theater/controlpoint.py index 48689805..9d851382 100644 --- a/theater/controlpoint.py +++ b/theater/controlpoint.py @@ -36,7 +36,7 @@ class ControlPoint: @classmethod def carrier(cls, name: str, at: Point): import theater.conflicttheater - return cls(name, at, at, theater.conflicttheater.ALL_RADIALS, theater.conflicttheater.SIZE_SMALL, 1) + return cls(name, at, at, theater.conflicttheater.LAND, theater.conflicttheater.SIZE_SMALL, 1) def __str__(self): return self.name diff --git a/theater/nevada.py b/theater/nevada.py index 2239977a..d72ea871 100644 --- a/theater/nevada.py +++ b/theater/nevada.py @@ -17,20 +17,20 @@ class NevadaTheater(ConflictTheater): "night": (0, 5), } - mina = ControlPoint.from_airport(nevada.Mina_Airport_3Q0, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) - tonopah = ControlPoint.from_airport(nevada.Tonopah_Airport, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) - tonopah_test_range = ControlPoint.from_airport(nevada.Tonopah_Test_Range_Airfield, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) - lincoln_conty = ControlPoint.from_airport(nevada.Lincoln_County, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW) + mina = ControlPoint.from_airport(nevada.Mina_Airport_3Q0, LAND, SIZE_SMALL, IMPORTANCE_LOW) + tonopah = ControlPoint.from_airport(nevada.Tonopah_Airport, LAND, SIZE_SMALL, IMPORTANCE_LOW) + tonopah_test_range = ControlPoint.from_airport(nevada.Tonopah_Test_Range_Airfield, LAND, SIZE_SMALL, IMPORTANCE_LOW) + lincoln_conty = ControlPoint.from_airport(nevada.Lincoln_County, LAND, SIZE_SMALL, IMPORTANCE_LOW) - pahute_mesa = ControlPoint.from_airport(nevada.Pahute_Mesa_Airstrip, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_MEDIUM) - groom_lake = ControlPoint.from_airport(nevada.Groom_Lake_AFB, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_MEDIUM) - mesquite = ControlPoint.from_airport(nevada.Mesquite, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_MEDIUM) - beatty = ControlPoint.from_airport(nevada.Beatty_Airport, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_MEDIUM) + pahute_mesa = ControlPoint.from_airport(nevada.Pahute_Mesa_Airstrip, LAND, SIZE_SMALL, IMPORTANCE_MEDIUM) + groom_lake = ControlPoint.from_airport(nevada.Groom_Lake_AFB, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM) + mesquite = ControlPoint.from_airport(nevada.Mesquite, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM) + beatty = ControlPoint.from_airport(nevada.Beatty_Airport, LAND, SIZE_REGULAR, IMPORTANCE_MEDIUM) - creech = ControlPoint.from_airport(nevada.Creech_AFB, ALL_RADIALS, SIZE_BIG, IMPORTANCE_HIGH) - las_vegas = ControlPoint.from_airport(nevada.North_Las_Vegas, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) - jean = ControlPoint.from_airport(nevada.Jean_Airport, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_HIGH) - laughlin = ControlPoint.from_airport(nevada.Laughlin_Airport, ALL_RADIALS, SIZE_LARGE, IMPORTANCE_HIGH) + creech = ControlPoint.from_airport(nevada.Creech_AFB, LAND, SIZE_BIG, IMPORTANCE_HIGH) + las_vegas = ControlPoint.from_airport(nevada.North_Las_Vegas, LAND, SIZE_LARGE, IMPORTANCE_HIGH) + jean = ControlPoint.from_airport(nevada.Jean_Airport, LAND, SIZE_REGULAR, IMPORTANCE_HIGH) + laughlin = ControlPoint.from_airport(nevada.Laughlin_Airport, LAND, SIZE_LARGE, IMPORTANCE_HIGH) def __init__(self): super(NevadaTheater, self).__init__() diff --git a/theater/persiangulf.py b/theater/persiangulf.py index 2adb7104..68dc1708 100644 --- a/theater/persiangulf.py +++ b/theater/persiangulf.py @@ -19,27 +19,27 @@ class PersianGulfTheater(ConflictTheater): "night": (0, 5), } - al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW) - al_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, ALL_RADIALS, SIZE_BIG, IMPORTANCE_LOW) - al_minhad = ControlPoint.from_airport(persiangulf.Al_Minhad_AB, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW) - sir_abu_nuayr = ControlPoint.from_airport(persiangulf.Sir_Abu_Nuayr, [330], SIZE_SMALL, IMPORTANCE_LOW) + al_dhafra = ControlPoint.from_airport(persiangulf.Al_Dhafra_AB, LAND, SIZE_BIG, IMPORTANCE_LOW) + al_maktoum = ControlPoint.from_airport(persiangulf.Al_Maktoum_Intl, LAND, SIZE_BIG, IMPORTANCE_LOW) + al_minhad = ControlPoint.from_airport(persiangulf.Al_Minhad_AB, LAND, SIZE_REGULAR, IMPORTANCE_LOW) + sir_abu_nuayr = ControlPoint.from_airport(persiangulf.Sir_Abu_Nuayr, [0, 330], SIZE_SMALL, IMPORTANCE_LOW) - dubai = ControlPoint.from_airport(persiangulf.Dubai_Intl, COAST_SWNE, SIZE_LARGE, IMPORTANCE_MEDIUM) - sharjah = ControlPoint.from_airport(persiangulf.Sharjah_Intl, ALL_RADIALS, SIZE_BIG, IMPORTANCE_MEDIUM) - fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_NS_W, SIZE_REGULAR, IMPORTANCE_MEDIUM) - khasab = ControlPoint.from_airport(persiangulf.Khasab, COAST_EW_S, SIZE_SMALL, IMPORTANCE_MEDIUM) + dubai = ControlPoint.from_airport(persiangulf.Dubai_Intl, COAST_DL_E, SIZE_LARGE, IMPORTANCE_MEDIUM) + sharjah = ControlPoint.from_airport(persiangulf.Sharjah_Intl, LAND, SIZE_BIG, IMPORTANCE_MEDIUM) + fujairah = ControlPoint.from_airport(persiangulf.Fujairah_Intl, COAST_V_W, SIZE_REGULAR, IMPORTANCE_MEDIUM) + khasab = ControlPoint.from_airport(persiangulf.Khasab, LAND, SIZE_SMALL, IMPORTANCE_MEDIUM) - sirri = ControlPoint.from_airport(persiangulf.Sirri_Island, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM) - abu_musa = ControlPoint.from_airport(persiangulf.Abu_Musa_Island_Airport, ALL_RADIALS, SIZE_TINY, IMPORTANCE_MEDIUM) - tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, [0, 270, 330], SIZE_SMALL, IMPORTANCE_HIGH) - tunb_kochak = ControlPoint.from_airport(persiangulf.Tunb_Kochak, COAST_EW_S, SIZE_TINY, IMPORTANCE_HIGH) + sirri = ControlPoint.from_airport(persiangulf.Sirri_Island, COAST_DL_W, SIZE_REGULAR, IMPORTANCE_MEDIUM) + abu_musa = ControlPoint.from_airport(persiangulf.Abu_Musa_Island_Airport, LAND, SIZE_SMALL, IMPORTANCE_MEDIUM) + tunb_island = ControlPoint.from_airport(persiangulf.Tunb_Island_AFB, [0, 270, 330], SIZE_REGULAR, IMPORTANCE_HIGH) + tunb_kochak = ControlPoint.from_airport(persiangulf.Tunb_Kochak, [135, 180], SIZE_SMALL, IMPORTANCE_HIGH) - bandar_lengeh = ControlPoint.from_airport(persiangulf.Bandar_Lengeh, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH) - qeshm = ControlPoint.from_airport(persiangulf.Qeshm_Island, COAST_EW_N, SIZE_SMALL, IMPORTANCE_HIGH) + bandar_lengeh = ControlPoint.from_airport(persiangulf.Bandar_Lengeh, [270, 315, 0, 45], SIZE_SMALL, IMPORTANCE_HIGH) + qeshm = ControlPoint.from_airport(persiangulf.Qeshm_Island, [270, 315, 0, 45, 90, 135, 180], SIZE_SMALL, IMPORTANCE_HIGH) - havadarya = ControlPoint.from_airport(persiangulf.Havadarya, COAST_EW_N, SIZE_REGULAR, IMPORTANCE_HIGH) - bandar_abbas = ControlPoint.from_airport(persiangulf.Bandar_Abbas_Intl, COAST_EW_N, SIZE_BIG, IMPORTANCE_HIGH) - lar = ControlPoint.from_airport(persiangulf.Lar_Airbase, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_HIGH) + havadarya = ControlPoint.from_airport(persiangulf.Havadarya, COAST_DL_W, SIZE_REGULAR, IMPORTANCE_HIGH) + bandar_abbas = ControlPoint.from_airport(persiangulf.Bandar_Abbas_Intl, LAND, SIZE_BIG, IMPORTANCE_HIGH) + lar = ControlPoint.from_airport(persiangulf.Lar_Airbase, LAND, SIZE_REGULAR, IMPORTANCE_HIGH) east_carrier = ControlPoint.carrier("West carrier", Point(-91023.430176, -159467.078125)) west_carrier = ControlPoint.carrier("East carrier", Point(-100531.972946, 60939.275818)) diff --git a/ui/eventmenu.py b/ui/eventmenu.py index 7b45bd38..c8d7bfe7 100644 --- a/ui/eventmenu.py +++ b/ui/eventmenu.py @@ -187,10 +187,17 @@ class EventMenu(Menu): clients=scrambled_clients) elif type(self.event) is GroundInterceptEvent: e = self.event # type: GroundInterceptEvent - e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) + if self.game.is_player_attack(self.event): + e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) + else: + e.player_defending(interceptors=scrambled_aircraft, clients=scrambled_clients) elif type(self.event) is NavalInterceptEvent: e = self.event # type: NavalInterceptEvent - e.player_attacking(strikegroup=scrambled_aircraft, clients=scrambled_clients) + + 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() diff --git a/ui/overviewcanvas.py b/ui/overviewcanvas.py index 6eeb5747..685a7dca 100644 --- a/ui/overviewcanvas.py +++ b/ui/overviewcanvas.py @@ -83,11 +83,12 @@ class OverviewCanvas: extent=extent) """ - For debugging purposes + #For debugging purposes for r in cp.radials: p = self.transform_point(cp.position.point_from_heading(r, 20000)) self.canvas.create_text(p[0], p[1], text="{}".format(r)) + continue """ self.canvas.tag_bind(cp_id, "", self.display(cp)) diff --git a/userdata/debriefing.py b/userdata/debriefing.py index 244fe330..e857e608 100644 --- a/userdata/debriefing.py +++ b/userdata/debriefing.py @@ -6,8 +6,9 @@ import os from dcs.lua import parse from dcs.mission import Mission -from dcs.unit import Vehicle +from dcs.unit import Vehicle, Ship from dcs.vehicles import vehicle_map +from dcs.ships import ship_map from dcs.planes import plane_map from dcs.unit import UnitType @@ -34,7 +35,7 @@ class Debriefing: country_id = int(unit["country"]) if type(unit_type_name) == str: - unit_type = vehicle_map.get(unit_type_name, plane_map.get(unit_type_name, None)) + unit_type = vehicle_map.get(unit_type_name, plane_map.get(unit_type_name, ship_map.get(unit_type_name, None))) if unit_type is None: continue @@ -55,6 +56,8 @@ class Debriefing: unit_type = None if isinstance(unit, Vehicle): unit_type = vehicle_map[unit.type] + elif isinstance(unit, Ship): + unit_type = ship_map[unit.type] else: unit_type = unit.unit_type @@ -74,8 +77,8 @@ class Debriefing: player = mission.country(player_name) enemy = mission.country(enemy_name) - player_units = count_groups(player.plane_group + player.vehicle_group) - enemy_units = count_groups(enemy.plane_group + enemy.vehicle_group) + player_units = count_groups(player.plane_group + player.vehicle_group + player.ship_group) + enemy_units = count_groups(enemy.plane_group + enemy.vehicle_group + enemy.ship_group) self.destroyed_units = { player.name: calculate_losses(player_units, self.alive_units.get(player.id, {})),