diff --git a/__init__.py b/__init__.py index 9cec15f8..8a5d950f 100755 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import os +import sys import dcs import theater.caucasus @@ -15,6 +16,47 @@ from game.game import Game from theater import start_generator from userdata import persistency + +""" +from dcs.lua.parse import * +a = loads(open("build/mission", "r").read()) +b = loads(open("build/mission_workin.lua", "r").read()) + + +def get(a, k): + b = a + for x in k.strip().split(" "): + if isinstance(a, dict): + y = a + a = a.get(x, None) + if a is None: + try: + a = y.get(int(x), None) + except: + pass + else: + break + if a is None: + pass + return a + +def cycle(kk, ref, v): + if isinstance(v, dict): + for k, v in v.items(): + cycle(kk + " " + str(k), ref, v) + elif isinstance(v, list): + for i, v in enumerate(v): + cycle(kk + " " + str(i), ref, v) + else: + if get(ref, kk) != v: + print(kk, v) + print(get(ref, kk)) + +cycle("", a, b) +sys.exit(0) +""" + +persistency.setup(sys.argv[1]) dcs.planes.FlyingType.payload_dirs.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads")) diff --git a/game/db.py b/game/db.py index b1953b46..91105b95 100644 --- a/game/db.py +++ b/game/db.py @@ -54,6 +54,7 @@ PRICES = { F_15C: 24, # bomber + Su_25: 15, Su_25T: 13, L_39ZA: 10, Su_34: 18, @@ -150,6 +151,7 @@ UNIT_BY_TASK = { AV8BNA, A_10A, A_10C, + Su_25, Su_25T, Su_34, Ka_50, @@ -235,6 +237,7 @@ UNIT_BY_COUNTRY = { C_101CC, AJS37, F_5E_3, + Su_25, Su_27, Su_33, MiG_15bis, @@ -279,7 +282,6 @@ UNIT_BY_COUNTRY = { F_15C, FA_18C_hornet, AJS37, - F_5E_3, M_2000C, MiG_21Bis, MiG_15bis, @@ -361,7 +363,7 @@ PLANE_PAYLOAD_OVERRIDES = { Aircraft livery overrides. Syntax as follows: `Identifier`: "LiveryName", - + `Identifier` is aircraft identifier (as used troughout the file) and "LiveryName" (with double quotes) is livery name as found in mission editor. """ diff --git a/game/event/groundintercept.py b/game/event/groundintercept.py index 5810de5d..1cac6288 100644 --- a/game/event/groundintercept.py +++ b/game/event/groundintercept.py @@ -26,7 +26,7 @@ class GroundInterceptEvent(Event): return super(GroundInterceptEvent, self).threat_description def __str__(self): - return "Fontline CAS from {} at {}".format(self.from_cp, self.to_cp) + return "Frontline CAS from {} at {}".format(self.from_cp, self.to_cp) def is_successfull(self, debriefing: Debriefing): total_targets = sum(self.targets.values()) diff --git a/game/operation/operation.py b/game/operation/operation.py index 73d0bc02..70db7faf 100644 --- a/game/operation/operation.py +++ b/game/operation/operation.py @@ -1,4 +1,5 @@ from dcs.terrain import Terrain +from dcs.lua.parse import loads from userdata.debriefing import * @@ -61,7 +62,11 @@ class Operation: self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.game, player_name, enemy_name) def prepare(self, terrain: Terrain, is_quick: bool): + with open("resources/default_options.lua", "r") as f: + options_dict = loads(f.read())["options"] + self.mission = dcs.Mission(terrain) + self.mission.options.load_from_dict(options_dict) self.is_quick = is_quick if is_quick: diff --git a/gen/aircraft.py b/gen/aircraft.py index dc4a09f5..93fb53e7 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -164,6 +164,16 @@ class AircraftConflictGenerator: else: assert False + def _rtb_for(self, group: FlyingGroup, cp: ControlPoint, at: db.StartingPosition = None): + group.add_waypoint(cp.position, RTB_ALTITUDE) + + if isinstance(cp.at, Point): + pass + elif isinstance(cp.at, ShipGroup): + pass + elif issubclass(cp.at, Airport): + group.land_at(cp.at) + def _at_position(self, at) -> Point: if isinstance(at, Point): return at @@ -226,9 +236,7 @@ class AircraftConflictGenerator: group.task = CAS.name self._setup_group(group, CAS, client_count) self.escort_targets.append((group, group.points.index(waypoint))) - - group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) - group.land_at(self.conflict.from_cp.at) + self._rtb_for(group, self.conflict.from_cp, at) def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None): assert len(self.escort_targets) == 0 @@ -249,9 +257,7 @@ class AircraftConflictGenerator: group.task = AntishipStrike.name self._setup_group(group, AntishipStrike, client_count) self.escort_targets.append((group, group.points.index(wayp))) - - group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) - group.land_at(self.conflict.from_cp.at) + self._rtb_for(group, self.conflict.from_cp, at) def generate_strikegroup_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( @@ -261,8 +267,7 @@ class AircraftConflictGenerator: at=at and at or self._group_point(self.conflict.air_attackers_location), is_quick=at is None, should_orbit=True): - g.add_waypoint(self.conflict.position, WARM_START_ALTITUDE) - g.land_at(self.conflict.from_cp.at) + self._rtb_for(g, self.conflict.from_cp, at) def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for g in self._generate_escort( @@ -272,8 +277,7 @@ class AircraftConflictGenerator: at=at and at or self._group_point(self.conflict.air_defenders_location), is_quick=at is None, should_orbit=False): - g.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE) - g.land_at(self.conflict.to_cp.at) + self._rtb_for(g, self.conflict.to_cp, at) def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None): for flying_type, count, client_count in self._split_to_groups(defenders, clients): @@ -290,9 +294,7 @@ class AircraftConflictGenerator: wayp.tasks.append(dcs.task.EngageTargets(max_distance=DEFENCE_ENGAGEMENT_MAX_DISTANCE)) wayp.tasks.append(dcs.task.OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle)) self._setup_group(group, CAP, client_count) - - group.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE) - group.land_at(self.conflict.to_cp.at) + self._rtb_for(group, self.conflict.to_cp, at) def generate_transport(self, transport: db.PlaneDict, destination: Airport): assert len(self.escort_targets) == 0 @@ -331,9 +333,7 @@ class AircraftConflictGenerator: wayp = group.add_waypoint(self.conflict.position, WARM_START_ALTITUDE, INTERCEPTION_AIRSPEED) wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE)) self._setup_group(group, CAP, client_count) - - group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE) - group.land_at(self.conflict.from_cp.at) + self._rtb_for(group, self.conflict.from_cp, at) def generate_passenger_transport(self, helis: db.HeliDict, clients: db.HeliDict, at: db.StartingPosition): for heli_type, count, client_count in self._split_to_groups(helis, clients): diff --git a/start.bat b/start.bat index 49106032..dfd9b9e8 100644 --- a/start.bat +++ b/start.bat @@ -1 +1 @@ -py.exe __init__.py > logs.txt 2>&1 +py.exe __init__.py %UserProfile% > logs.txt 2>&1 diff --git a/userdata/debriefing.py b/userdata/debriefing.py index 73ab30aa..0cdadcb5 100644 --- a/userdata/debriefing.py +++ b/userdata/debriefing.py @@ -1,4 +1,5 @@ import typing +import re import threading import time import os @@ -14,7 +15,7 @@ from dcs.unit import UnitType from game import db -from .persistency import _base_path +from .persistency import base_path DEBRIEFING_LOG_EXTENSION = "log" @@ -24,11 +25,53 @@ class Debriefing: self.destroyed_units = {} # type: typing.Dict[str, typing.Dict[UnitType, int]] self.alive_units = alive_units # type: typing.Dict[str, typing.Dict[UnitType, int]] + @classmethod + def parse_mp_debrief(cls, string: str): + # TODO: actually write a parser + result = {} + append = False + + country = None + unit_type = None + + for line in string.split("\n"): + line = line.strip() + if not append: + if line == "world_state =": + append = True + continue + + if append: + if line.startswith("country"): + country = re.findall(r"country\s*=\s*(\d+),", line)[0] + if line.startswith("type"): + unit_type = re.findall(r"type\s*=\s*\"(.*?)\",", line)[0] + + if country and unit_type: + result[len(result)+1] = { + "country": int(country), + "type": unit_type, + } + + country = unit_type = None + + if line.strip() == "} -- end of world_state": + break + + return { + "debriefing": { + "world_state": result, + }, + } + @classmethod def parse(cls, path: str): with open(path, "r") as f: table_string = f.read() - table = parse.loads(table_string) + try: + table = parse.loads(table_string) + except: + table = cls.parse_mp_debrief(table_string) units = table.get("debriefing", {}).get("world_state", {}) alive_units = {} @@ -94,7 +137,7 @@ class Debriefing: def debriefing_directory_location() -> str: - return os.path.join(_base_path(), "liberation_debriefings") + return os.path.join(base_path(), "liberation_debriefings") def _logfiles_snapshot() -> typing.Dict[str, float]: diff --git a/userdata/persistency.py b/userdata/persistency.py index 25f78d93..5027e189 100644 --- a/userdata/persistency.py +++ b/userdata/persistency.py @@ -3,9 +3,19 @@ import pickle import os import shutil +_user_folder = None # type: str -def _base_path() -> str: - openbeta_path = os.path.expanduser("~\Saved Games\DCS.openbeta") + +def setup(user_folder: str): + global _user_folder + _user_folder = user_folder + + +def base_path() -> str: + global _user_folder + assert _user_folder + + openbeta_path = os.path.join(_user_folder, "Saved Games\DCS.openbeta") if os.path.exists(openbeta_path): return openbeta_path else: @@ -13,11 +23,11 @@ def _base_path() -> str: def _save_file() -> str: - return os.path.join(_base_path(), "liberation_save") + return os.path.join(base_path(), "liberation_save") def _temporary_save_file() -> str: - return os.path.join(_base_path(), "liberation_save_tmp") + return os.path.join(base_path(), "liberation_save_tmp") def _save_file_exists() -> bool: @@ -25,7 +35,7 @@ def _save_file_exists() -> bool: def mission_path_for(name: str) -> str: - return os.path.join(_base_path(), "Missions\{}".format(name)) + return os.path.join(base_path(), "Missions\{}".format(name)) def restore_game():