import typing import logging from dcs.action import Coalition from dcs.unittype import UnitType from dcs.task import * from dcs.vehicles import AirDefence from dcs.unittype import UnitType from game import * from theater import * from gen.environmentgen import EnvironmentSettings from gen.conflictgen import Conflict from game.db import assigned_units_from, unitdict_from from userdata.debriefing import Debriefing from userdata import persistency import game.db as db DIFFICULTY_LOG_BASE = 1.1 EVENT_DEPARTURE_MAX_DISTANCE = 340000 class Event: silent = False informational = False is_awacs_enabled = False ca_slots = 0 game = None # type: Game location = None # type: Point from_cp = None # type: ControlPoint departure_cp = None # type: ControlPoint to_cp = None # type: ControlPoint operation = None # type: Operation difficulty = 1 # type: int environment_settings = None # type: EnvironmentSettings BONUS_BASE = 5 def __init__(self, game, from_cp: ControlPoint, target_cp: ControlPoint, location: Point, attacker_name: str, defender_name: str): self.game = game self.departure_cp = None self.from_cp = from_cp self.to_cp = target_cp self.location = location self.attacker_name = attacker_name self.defender_name = defender_name @property def is_player_attacking(self) -> bool: return self.attacker_name == self.game.player_name @property def enemy_cp(self) -> ControlPoint: if self.attacker_name == self.game.player_name: return self.to_cp else: return self.departure_cp @property def threat_description(self) -> str: return "" def flight_name(self, for_task: typing.Type[typing.Type[Task]]) -> str: return "Flight" @property def tasks(self) -> typing.Collection[typing.Type[Task]]: return [] @property def ai_banned_tasks(self) -> typing.Collection[typing.Type[Task]]: return [] @property def player_banned_tasks(self) -> typing.Collection[typing.Type[Task]]: return [] @property def global_cp_available(self) -> bool: return False def is_departure_available_from(self, cp: ControlPoint) -> bool: if not cp.captured: return False if self.location.distance_to_point(cp.position) > EVENT_DEPARTURE_MAX_DISTANCE: return False if cp.is_global and not self.global_cp_available: return False return True def bonus(self) -> int: return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE) def is_successfull(self, debriefing: Debriefing) -> bool: return self.operation.is_successfull(debriefing) def player_attacking(self, cp: ControlPoint, flights: db.TaskForceDict): if self.is_player_attacking: self.departure_cp = cp else: self.to_cp = cp def player_defending(self, cp: ControlPoint, flights: db.TaskForceDict): if self.is_player_attacking: self.departure_cp = cp else: self.to_cp = cp def generate(self): self.operation.is_awacs_enabled = self.is_awacs_enabled self.operation.ca_slots = self.ca_slots self.operation.prepare(self.game.theater.terrain, is_quick=False) self.operation.generate() self.operation.current_mission.save(persistency.mission_path_for("liberation_nextturn.miz")) self.environment_settings = self.operation.environment_settings def generate_quick(self): self.operation.is_awacs_enabled = self.is_awacs_enabled self.operation.environment_settings = self.environment_settings self.operation.prepare(self.game.theater.terrain, is_quick=True) self.operation.generate() self.operation.current_mission.save(persistency.mission_path_for("liberation_nextturn_quick.miz")) def commit(self, debriefing: Debriefing): logging.info("Commiting mission results") # ------------------------------ # Destroyed aircrafts cp_map = {cp.id: cp for cp in self.game.theater.controlpoints} for destroyed_aircraft in debriefing.killed_aircrafts: try: cpid = int(destroyed_aircraft.split("|")[3]) type = db.unit_type_from_name(destroyed_aircraft.split("|")[4]) if cpid in cp_map.keys(): cp = cp_map[cpid] if type in cp.base.aircraft.keys(): logging.info("Aircraft destroyed : " + str(type)) cp.base.aircraft[type] = max(0, cp.base.aircraft[type]-1) except Exception as e: print(e) # ------------------------------ # Destroyed ground units cp_map = {cp.id: cp for cp in self.game.theater.controlpoints} for killed_ground_unit in debriefing.killed_ground_units: try: cpid = int(killed_ground_unit.split("|")[3]) type = db.unit_type_from_name(killed_ground_unit.split("|")[4]) if cpid in cp_map.keys(): cp = cp_map[cpid] if type in cp.base.armor.keys(): logging.info("Ground unit destroyed : " + str(type)) cp.base.armor[type] = max(0, cp.base.armor[type] - 1) except Exception as e: print(e) # ------------------------------ # Static ground objects for destroyed_ground_unit_name in debriefing.killed_ground_units: for cp in self.game.theater.controlpoints: if not cp.ground_objects: continue # -- Static ground objects for i, ground_object in enumerate(cp.ground_objects): if ground_object.is_dead: continue if ground_object.matches_string_identifier(destroyed_ground_unit_name): logging.info("cp {} killing ground object {}".format(cp, ground_object.string_identifier)) cp.ground_objects[i].is_dead = True # -- AA Site groups for i, ground_object in enumerate(cp.ground_objects): if ground_object.dcs_identifier in ["AA", "CARRIER"]: for g in ground_object.groups: for u in g.units: if u.name == destroyed_ground_unit_name: g.units.remove(u) ucount = sum([len(g.units) for g in ground_object.groups]) if ucount == 0: ground_object.is_dead = True # ------------------------------ # Captured bases if self.game.player_country in db.BLUEFOR_FACTIONS: coalition = 2 # Value in DCS mission event for BLUE else: coalition = 1 # Value in DCS mission event for RED for captured in debriefing.base_capture_events: try: id = int(captured.split("||")[0]) new_owner_coalition = int(captured.split("||")[1]) for cp in self.game.theater.controlpoints: if cp.id == id: if cp.captured and new_owner_coalition != coalition: cp.captured = False cp.base.aircraft = {} cp.base.armor = {} cp.base.aa = {} for g in cp.ground_objects: g.groups = [] elif not(cp.captured) and new_owner_coalition == coalition: cp.captured = True cp.base.aircraft = {} cp.base.armor = {} cp.base.aa = {} for g in cp.ground_objects: g.groups = [] except Exception as e: print(e) def skip(self): pass class UnitsDeliveryEvent(Event): informational = True units = None # type: typing.Dict[UnitType, int] def __init__(self, attacker_name: str, defender_name: str, from_cp: ControlPoint, to_cp: ControlPoint, game): super(UnitsDeliveryEvent, self).__init__(game=game, location=to_cp.position, from_cp=from_cp, target_cp=to_cp, attacker_name=attacker_name, defender_name=defender_name) self.units = {} def __str__(self): return "Pending delivery to {}".format(self.to_cp) def deliver(self, units: typing.Dict[UnitType, int]): for k, v in units.items(): self.units[k] = self.units.get(k, 0) + v def skip(self): self.to_cp.base.commision_units(self.units)