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 df8dc635..16ce2213 100644 Binary files a/resources/caulandmap.p and b/resources/caulandmap.p differ 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, {})),