mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
fixed a number of issues: user directory on different drive, carrier ops, multiplayer debriefing parser, multiplayer mission generation; added su25
This commit is contained in:
parent
fa55ae1fcc
commit
32fb5ad0e2
42
__init__.py
42
__init__.py
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import dcs
|
import dcs
|
||||||
|
|
||||||
import theater.caucasus
|
import theater.caucasus
|
||||||
@ -15,6 +16,47 @@ from game.game import Game
|
|||||||
from theater import start_generator
|
from theater import start_generator
|
||||||
from userdata import persistency
|
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"))
|
dcs.planes.FlyingType.payload_dirs.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources\\payloads"))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,7 @@ PRICES = {
|
|||||||
F_15C: 24,
|
F_15C: 24,
|
||||||
|
|
||||||
# bomber
|
# bomber
|
||||||
|
Su_25: 15,
|
||||||
Su_25T: 13,
|
Su_25T: 13,
|
||||||
L_39ZA: 10,
|
L_39ZA: 10,
|
||||||
Su_34: 18,
|
Su_34: 18,
|
||||||
@ -150,6 +151,7 @@ UNIT_BY_TASK = {
|
|||||||
AV8BNA,
|
AV8BNA,
|
||||||
A_10A,
|
A_10A,
|
||||||
A_10C,
|
A_10C,
|
||||||
|
Su_25,
|
||||||
Su_25T,
|
Su_25T,
|
||||||
Su_34,
|
Su_34,
|
||||||
Ka_50,
|
Ka_50,
|
||||||
@ -235,6 +237,7 @@ UNIT_BY_COUNTRY = {
|
|||||||
C_101CC,
|
C_101CC,
|
||||||
AJS37,
|
AJS37,
|
||||||
F_5E_3,
|
F_5E_3,
|
||||||
|
Su_25,
|
||||||
Su_27,
|
Su_27,
|
||||||
Su_33,
|
Su_33,
|
||||||
MiG_15bis,
|
MiG_15bis,
|
||||||
@ -279,7 +282,6 @@ UNIT_BY_COUNTRY = {
|
|||||||
F_15C,
|
F_15C,
|
||||||
FA_18C_hornet,
|
FA_18C_hornet,
|
||||||
AJS37,
|
AJS37,
|
||||||
F_5E_3,
|
|
||||||
M_2000C,
|
M_2000C,
|
||||||
MiG_21Bis,
|
MiG_21Bis,
|
||||||
MiG_15bis,
|
MiG_15bis,
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class GroundInterceptEvent(Event):
|
|||||||
return super(GroundInterceptEvent, self).threat_description
|
return super(GroundInterceptEvent, self).threat_description
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
def is_successfull(self, debriefing: Debriefing):
|
||||||
total_targets = sum(self.targets.values())
|
total_targets = sum(self.targets.values())
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from dcs.terrain import Terrain
|
from dcs.terrain import Terrain
|
||||||
|
from dcs.lua.parse import loads
|
||||||
|
|
||||||
from userdata.debriefing import *
|
from userdata.debriefing import *
|
||||||
|
|
||||||
@ -61,7 +62,11 @@ class Operation:
|
|||||||
self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.game, player_name, enemy_name)
|
self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.game, player_name, enemy_name)
|
||||||
|
|
||||||
def prepare(self, terrain: Terrain, is_quick: bool):
|
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 = dcs.Mission(terrain)
|
||||||
|
self.mission.options.load_from_dict(options_dict)
|
||||||
self.is_quick = is_quick
|
self.is_quick = is_quick
|
||||||
|
|
||||||
if is_quick:
|
if is_quick:
|
||||||
|
|||||||
@ -164,6 +164,16 @@ class AircraftConflictGenerator:
|
|||||||
else:
|
else:
|
||||||
assert False
|
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:
|
def _at_position(self, at) -> Point:
|
||||||
if isinstance(at, Point):
|
if isinstance(at, Point):
|
||||||
return at
|
return at
|
||||||
@ -226,9 +236,7 @@ class AircraftConflictGenerator:
|
|||||||
group.task = CAS.name
|
group.task = CAS.name
|
||||||
self._setup_group(group, CAS, client_count)
|
self._setup_group(group, CAS, client_count)
|
||||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||||
|
self._rtb_for(group, self.conflict.from_cp, at)
|
||||||
group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
|
||||||
group.land_at(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):
|
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
|
assert len(self.escort_targets) == 0
|
||||||
@ -249,9 +257,7 @@ class AircraftConflictGenerator:
|
|||||||
group.task = AntishipStrike.name
|
group.task = AntishipStrike.name
|
||||||
self._setup_group(group, AntishipStrike, client_count)
|
self._setup_group(group, AntishipStrike, client_count)
|
||||||
self.escort_targets.append((group, group.points.index(wayp)))
|
self.escort_targets.append((group, group.points.index(wayp)))
|
||||||
|
self._rtb_for(group, self.conflict.from_cp, at)
|
||||||
group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
|
||||||
group.land_at(self.conflict.from_cp.at)
|
|
||||||
|
|
||||||
def generate_strikegroup_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
def generate_strikegroup_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||||
for g in self._generate_escort(
|
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),
|
at=at and at or self._group_point(self.conflict.air_attackers_location),
|
||||||
is_quick=at is None,
|
is_quick=at is None,
|
||||||
should_orbit=True):
|
should_orbit=True):
|
||||||
g.add_waypoint(self.conflict.position, WARM_START_ALTITUDE)
|
self._rtb_for(g, self.conflict.from_cp, at)
|
||||||
g.land_at(self.conflict.from_cp.at)
|
|
||||||
|
|
||||||
def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
def generate_transport_escort(self, escort: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||||
for g in self._generate_escort(
|
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),
|
at=at and at or self._group_point(self.conflict.air_defenders_location),
|
||||||
is_quick=at is None,
|
is_quick=at is None,
|
||||||
should_orbit=False):
|
should_orbit=False):
|
||||||
g.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE)
|
self._rtb_for(g, self.conflict.to_cp, at)
|
||||||
g.land_at(self.conflict.to_cp.at)
|
|
||||||
|
|
||||||
def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
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):
|
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.EngageTargets(max_distance=DEFENCE_ENGAGEMENT_MAX_DISTANCE))
|
||||||
wayp.tasks.append(dcs.task.OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle))
|
wayp.tasks.append(dcs.task.OrbitAction(ATTACK_CIRCLE_ALT, pattern=OrbitAction.OrbitPattern.Circle))
|
||||||
self._setup_group(group, CAP, client_count)
|
self._setup_group(group, CAP, client_count)
|
||||||
|
self._rtb_for(group, self.conflict.to_cp, at)
|
||||||
group.add_waypoint(self.conflict.to_cp.position, RTB_ALTITUDE)
|
|
||||||
group.land_at(self.conflict.to_cp.at)
|
|
||||||
|
|
||||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
||||||
assert len(self.escort_targets) == 0
|
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 = group.add_waypoint(self.conflict.position, WARM_START_ALTITUDE, INTERCEPTION_AIRSPEED)
|
||||||
wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
wayp.tasks.append(EngageTargets(max_distance=INTERCEPT_MAX_DISTANCE))
|
||||||
self._setup_group(group, CAP, client_count)
|
self._setup_group(group, CAP, client_count)
|
||||||
|
self._rtb_for(group, self.conflict.from_cp, at)
|
||||||
group.add_waypoint(self.conflict.from_cp.position, RTB_ALTITUDE)
|
|
||||||
group.land_at(self.conflict.from_cp.at)
|
|
||||||
|
|
||||||
def generate_passenger_transport(self, helis: db.HeliDict, clients: db.HeliDict, at: db.StartingPosition):
|
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):
|
for heli_type, count, client_count in self._split_to_groups(helis, clients):
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
py.exe __init__.py > logs.txt 2>&1
|
py.exe __init__.py %UserProfile% > logs.txt 2>&1
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import typing
|
import typing
|
||||||
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
@ -14,7 +15,7 @@ from dcs.unit import UnitType
|
|||||||
|
|
||||||
from game import db
|
from game import db
|
||||||
|
|
||||||
from .persistency import _base_path
|
from .persistency import base_path
|
||||||
|
|
||||||
DEBRIEFING_LOG_EXTENSION = "log"
|
DEBRIEFING_LOG_EXTENSION = "log"
|
||||||
|
|
||||||
@ -24,11 +25,53 @@ class Debriefing:
|
|||||||
self.destroyed_units = {} # type: typing.Dict[str, typing.Dict[UnitType, int]]
|
self.destroyed_units = {} # type: typing.Dict[str, typing.Dict[UnitType, int]]
|
||||||
self.alive_units = alive_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
|
@classmethod
|
||||||
def parse(cls, path: str):
|
def parse(cls, path: str):
|
||||||
with open(path, "r") as f:
|
with open(path, "r") as f:
|
||||||
table_string = f.read()
|
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", {})
|
units = table.get("debriefing", {}).get("world_state", {})
|
||||||
alive_units = {}
|
alive_units = {}
|
||||||
|
|
||||||
@ -94,7 +137,7 @@ class Debriefing:
|
|||||||
|
|
||||||
|
|
||||||
def debriefing_directory_location() -> str:
|
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]:
|
def _logfiles_snapshot() -> typing.Dict[str, float]:
|
||||||
|
|||||||
@ -3,9 +3,19 @@ import pickle
|
|||||||
import os
|
import os
|
||||||
import shutil
|
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):
|
if os.path.exists(openbeta_path):
|
||||||
return openbeta_path
|
return openbeta_path
|
||||||
else:
|
else:
|
||||||
@ -13,11 +23,11 @@ def _base_path() -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _save_file() -> 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:
|
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:
|
def _save_file_exists() -> bool:
|
||||||
@ -25,7 +35,7 @@ def _save_file_exists() -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def mission_path_for(name: str) -> str:
|
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():
|
def restore_game():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user