New automatic de-briefing system implemented

This commit is contained in:
Khopa 2019-10-13 03:40:22 +02:00
parent 4365db0fae
commit 3f5f4f4bb1
18 changed files with 309 additions and 696 deletions

View File

@ -2,6 +2,7 @@ import typing
import enum
from datetime import datetime
from dcs.countries import get_by_id, country_dict
from dcs.vehicles import *
from dcs.ships import *
from dcs.planes import *
@ -836,6 +837,13 @@ def unitdict_from(fd: AssignedUnitsDict) -> Dict:
return {k: v1 for k, (v1, v2) in fd.items()}
def country_id_from_name(name):
for k,v in country_dict.items():
if v.name == name:
return k
return -1
def _validate_db():
# check unit by task uniquity
total_set = set()

View File

@ -130,44 +130,65 @@ class Event:
def commit(self, debriefing: Debriefing):
for destroyed_unit_name in debriefing.dead_units_name:
logging.info("Commiting mission results")
for cp in self.game.theater.controlpoints:
# ------------------------------
# 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)
for i, ground_object in enumerate(cp.ground_objects):
if ground_object.dcs_identifier == "AA":
for g in ground_object.groups:
for u in g.units:
if u.name == destroyed_unit_name:
g.units.remove(u)
ucount = sum([len(g.units) for g in ground_object.groups])
print(ucount)
if ucount == 0:
print("SET DEAD")
ground_object.is_dead = True
# ------------------------------
# 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)
for country, losses in debriefing.destroyed_units.items():
if country == self.attacker_name:
cp = self.departure_cp
else:
cp = self.to_cp
logging.info("base {} commit losses {}".format(cp.base, losses))
cp.base.commit_losses(losses)
for object_identifier in debriefing.destroyed_objects:
# ------------------------------
# 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(object_identifier):
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 == "AA":
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
def skip(self):
pass

View File

@ -46,10 +46,12 @@ class FrontlineAttackEvent(Event):
attacker_country = self.game.enemy_country
defender_country = self.game.player_country
alive_attackers = sum([v for k, v in debriefing.alive_units.get(attacker_country, {}).items() if db.unit_task(k) == PinpointStrike])
alive_defenders = sum([v for k, v in debriefing.alive_units.get(defender_country, {}).items() if db.unit_task(k) == PinpointStrike])
# TODO : Rework
#alive_attackers = sum([v for k, v in debriefing.alive_units.get(attacker_country, {}).items() if db.unit_task(k) == PinpointStrike])
#alive_defenders = sum([v for k, v in debriefing.alive_units.get(defender_country, {}).items() if db.unit_task(k) == PinpointStrike])
#attackers_success = (float(alive_attackers) / (alive_defenders + 0.01)) > self.SUCCESS_FACTOR
attackers_success = True
attackers_success = (float(alive_attackers) / (alive_defenders + 0.01)) > self.SUCCESS_FACTOR
if self.from_cp.captured:
return attackers_success
else:

View File

@ -50,7 +50,6 @@ class BaseAttackOperation(Operation):
def generate(self):
self.armorgen.generate(self.attack, self.defense)
self.aagen.generate(self.aa)
self.airgen.generate_defense(*assigned_units_split(self.intercept), at=self.defenders_starting_position)

View File

@ -31,7 +31,6 @@ class InfantryTransportOperation(Operation):
self.airgen.generate_passenger_transport(*assigned_units_split(self.transport), at=self.attackers_starting_position)
self.armorgen.generate_passengers(count=6)
self.aagen.generate_at_defenders_location(self.aa)
self.visualgen.generate_transportation_marker(self.conflict.ground_attackers_location)
self.visualgen.generate_transportation_destination(self.conflict.position)

View File

@ -1,8 +1,7 @@
from dcs.lua.parse import loads
from userdata.debriefing import *
from gen import *
from userdata.debriefing import *
TANKER_CALLSIGNS = ["Texaco", "Arco", "Shell"]
@ -17,7 +16,6 @@ class Operation:
conflict = None # type: Conflict
armorgen = None # type: ArmorConflictGenerator
airgen = None # type: AircraftConflictGenerator
aagen = None # type: AAConflictGenerator
extra_aagen = None # type: ExtraAAConflictGenerator
shipgen = None # type: ShipGenerator
triggersgen = None # type: TriggersGenerator
@ -67,7 +65,6 @@ class Operation:
self.conflict = conflict
self.armorgen = ArmorConflictGenerator(mission, conflict)
self.airgen = AircraftConflictGenerator(mission, conflict, self.game.settings)
self.aagen = AAConflictGenerator(mission, conflict)
self.shipgen = ShipGenerator(mission, conflict)
self.airsupportgen = AirSupportConflictGenerator(mission, conflict, self.game)
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
@ -85,8 +82,6 @@ class Operation:
with open("resources/default_options.lua", "r") as f:
options_dict = loads(f.read())["options"]
dcs.Mission.aaa_vehicle_group = aaa.aaa_vehicle_group
self.current_mission = dcs.Mission(terrain)
if is_quick:
@ -200,7 +195,10 @@ class Operation:
load_dcs_libe = TriggerStart(comment="Load DCS Liberation Script")
with open(os.path.abspath("./resources/scripts/dcs_liberation.lua")) as f:
script = f.read()
script = script.replace("{{json_file_abs_location}}", "'"+os.path.abspath("./resources/scripts/json.lua"+"'"))
json_location = "[["+os.path.abspath("resources\\scripts\\json.lua")+"]]"
state_location = "[[" + os.path.abspath("state.json") + "]]"
script = script.replace("{{json_file_abs_location}}", json_location)
script = script.replace("{{debriefing_file_location}}", state_location)
load_dcs_libe.add_action(DoScript(String(script)))
self.current_mission.triggerrules.triggers.append(load_dcs_libe)

View File

@ -1,441 +1,17 @@
import random
import math
from .conflictgen import *
from .naming import *
from dcs.mission import *
from dcs.mission import *
from .conflictgen import *
from .naming import *
DISTANCE_FACTOR = 0.5, 1
EXTRA_AA_MIN_DISTANCE = 50000
EXTRA_AA_MAX_DISTANCE = 150000
EXTRA_AA_POSITION_FROM_CP = 550
def num_sam_dead(sam_type, destroyed_count):
"""
Given a type and count of SAM units, determine if enough units were destroyed to warrant the
loss of a site
:param sam_type:
inidivudal unit name in SAM site which was destroyed
:param destroyed_count:
count of that unit type which was destroyed *in the sortie*
:return:
INT: number of sites lost
"""
sam_threshold = {
AirDefence.SAM_SR_P_19: 1,
AirDefence.SAM_SA_3_S_125_TR_SNR: 1,
AirDefence.SAM_SA_6_Kub_STR_9S91: 1,
AirDefence.SAM_SA_10_S_300PS_SR_5N66M: 1,
AirDefence.SAM_SA_10_S_300PS_TR_30N6: 1,
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 1,
AirDefence.SAM_SA_10_S_300PS_SR_64H6E: 1,
AirDefence.SAM_SA_3_S_125_LN_5P73: 4,
AirDefence.SAM_SA_6_Kub_LN_2P25: 6,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 8,
AirDefence.SAM_SA_2_LN_SM_90:4,
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song: 1,
AirDefence.SAM_Hawk_PCP: 1,
AirDefence.SAM_Hawk_LN_M192: 4,
AirDefence.SAM_Hawk_SR_AN_MPQ_50: 1,
AirDefence.SAM_Hawk_TR_AN_MPQ_46: 1
}
return int(destroyed_count / sam_threshold[sam_type])
def determine_positions(position, heading, num_units, launcher_distance, coverage=90):
"""
Given a position on the map, array a group of units in a circle a uniform distance from the unit
:param position:
position of the center unit
:param heading:
the direction the units should be arranged toward if coverage is not 360
:param num_units:
number of units to play on the circle
:param launcher_distance:
distance the units should be from the center unit
:param coverage:
0-360
:return:
list of tuples representing each unit location
[(pos_x, pos_y, heading), ...]
"""
if coverage == 360:
# one of the positions is shared :'(
outer_offset = coverage / num_units
else:
outer_offset = coverage / (num_units - 1)
positions = []
if num_units % 2 == 0:
current_offset = heading - ((coverage / (num_units - 1)) / 2)
else:
current_offset = heading
current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
for x in range(1, num_units + 1):
positions.append((
position.x + launcher_distance * math.cos(math.radians(current_offset)),
position.y + launcher_distance * math.sin(math.radians(current_offset)),
current_offset,
))
current_offset += outer_offset
return positions
def aaa_vehicle_group(self, country, name, _type: unittype.VehicleType, position: mapping.Point,
heading=0, group_size=1,
formation=unitgroup.VehicleGroup.Formation.Line,
move_formation: PointAction=PointAction.OffRoad):
"""
Override the default vehicle group so that our group can contain a mix of units (which is required for advanced
SAM sites)
For further docstrings, see the built-in function
"""
vg = unitgroup.VehicleGroup(self.next_group_id(), self.string(name))
for i in range(1, group_size + 1):
heading = randint(0, 359)
if _type == AirDefence.SAM_SA_3_S_125_LN_5P73:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SR_P_19,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_3_S_125_TR_SNR,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_3_S_125_LN_5P73,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_6_Kub_LN_2P25:
# 6 launchers (360 degree coverage)
# 1 S/TR
# search/track radar
num_launchers = 6
v = self.vehicle(
name + " Unit #{nr}-str".format(nr=i),
AirDefence.SAM_SA_6_Kub_STR_9S91,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_6_Kub_LN_2P25,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_10_S_300PS_LN_5P85C:
# 8 launchers - 4 directions, two in each direction
# 1 SR (offset)
# 1 TR (center)
# search radar
num_launchers = 8
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_SR_5N66M,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_TR_30N6,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# command center
v = self.vehicle(
name + " Unit #{nr}-c".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_CP_54K6,
)
center_x = position.x + randint(40, 60)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=150,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_10_S_300PS_LN_5P85C,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_10_S_300PS_CP_54K6:
# 8 launchers - 4 directions, two in each direction
# 1 SR (offset)
# 1 TR (center)
# search radar
num_launchers = 8
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_SR_64H6E,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_TR_30N6,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# command center
v = self.vehicle(
name + " Unit #{nr}-c".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_CP_54K6,
)
center_x = position.x + randint(40, 60)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_units=num_launchers,
launcher_distance=150,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_10_S_300PS_LN_5P85D,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_Hawk_PCP:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR, 1 PCP
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_Hawk_SR_AN_MPQ_50,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_Hawk_TR_AN_MPQ_46,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# PCP
v = self.vehicle(
name + " Unit #{nr}-pcp".format(nr=i),
AirDefence.SAM_Hawk_PCP,
)
center_x = position.x + randint(60, 80)
center_y = position.y + 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_Hawk_LN_M192,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_2_LN_SM_90:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SR_P_19,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_2_LN_SM_90,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
else:
v = self.vehicle(name + " Unit #{nr}-sam".format(nr=i), _type)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
wp = vg.add_waypoint(vg.units[0].position, move_formation, 0)
wp.ETA_locked = True
if _type.eplrs:
wp.tasks.append(task.EPLRS(self.next_eplrs("vehicle")))
country.add_vehicle_group(vg)
return vg
class AAConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict):
self.m = mission
self.conflict = conflict
def generate_at_defenders_location(self, units: db.AirDefenseDict):
for unit_type, count in units.items():
for _ in range(count):
self.m.vehicle_group(
country=self.conflict.defenders_country,
name=namegen.next_unit_name(self.conflict.defenders_country, unit_type),
_type=unit_type,
position=self.conflict.ground_defenders_location.random_point_within(100, 100),
group_size=1)
def generate(self, units: db.AirDefenseDict):
for type, count in units.items():
for _, radial in zip(range(count), self.conflict.radials):
distance = randint(self.conflict.size * DISTANCE_FACTOR[0] + 9000, self.conflict.size * DISTANCE_FACTOR[1] + 14000)
p = self.conflict.position.point_from_heading(random.choice(self.conflict.radials), distance)
self.m.aaa_vehicle_group(
country=self.conflict.defenders_country,
name=namegen.next_unit_name(self.conflict.defenders_country, type),
_type=type,
position=p,
group_size=1)
class ExtraAAConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game, player_country: Country, enemy_country: Country):
self.mission = mission
@ -445,7 +21,6 @@ class ExtraAAConflictGenerator:
self.enemy_country = enemy_country
def generate(self):
from theater.conflicttheater import ControlPoint
for cp in self.game.theater.controlpoints:
if cp.is_global:

View File

@ -242,11 +242,11 @@ class AircraftConflictGenerator:
else:
assert False
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition, is_quick=False, should_orbit=False):
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition, cp, is_quick=False, should_orbit=False):
groups = []
for flying_type, count, client_count in self._split_to_groups(units, clients):
group = self._generate_group(
name=namegen.next_unit_name(side, flying_type),
name=namegen.next_unit_name(side, cp.id, flying_type),
side=side,
unit_type=flying_type,
count=count,
@ -279,7 +279,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -313,7 +313,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -322,7 +322,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -360,7 +360,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -369,7 +369,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -413,7 +413,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -422,7 +422,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@ -450,7 +450,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -476,7 +476,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -502,7 +502,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.defenders_country, self.conflict.to_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@ -528,7 +528,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -552,6 +552,7 @@ class AircraftConflictGenerator:
clients=clients,
at=at and at or self._group_point(self.conflict.air_attackers_location),
is_quick=at is None,
cp=self.conflict.from_cp,
should_orbit=True):
self._rtb_for(g, self.conflict.from_cp, at)
@ -562,13 +563,14 @@ class AircraftConflictGenerator:
clients=clients,
at=at and at or self._group_point(self.conflict.air_defenders_location),
is_quick=at is None,
cp=self.conflict.to_cp,
should_orbit=False):
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):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.to_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@ -585,7 +587,7 @@ class AircraftConflictGenerator:
def generate_migcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -603,7 +605,7 @@ class AircraftConflictGenerator:
def generate_barcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@ -629,7 +631,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(transport):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@ -647,7 +649,7 @@ class AircraftConflictGenerator:
def generate_interception(self, interceptors: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(interceptors, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@ -669,7 +671,7 @@ class AircraftConflictGenerator:
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):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, heli_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, heli_type),
side=self.conflict.attackers_country,
unit_type=heli_type,
count=count,

View File

@ -37,11 +37,17 @@ class ArmorConflictGenerator:
return point.random_point_within(distance, self.conflict.size * SPREAD_DISTANCE_SIZE_FACTOR)
def _generate_group(self, side: Country, unit: VehicleType, count: int, at: Point, to: Point = None, move_formation: PointAction = PointAction.OffRoad):
if side == self.conflict.attackers_country:
cp = self.conflict.from_cp
else:
cp = self.conflict.to_cp
for c in range(count):
logging.info("armorgen: {} for {}".format(unit, side.id))
group = self.m.vehicle_group(
side,
namegen.next_unit_name(side, unit),
namegen.next_unit_name(side, cp.id, unit),
unit,
position=self._group_point(at),
group_size=1,

View File

@ -4,9 +4,9 @@ from game import db
class NameGenerator:
number = 0
def next_unit_name(self, country, unit_type):
def next_unit_name(self, country, parent_base_id, unit_type):
self.number += 1
return "unit|{}|{}|{}|".format(country.id, self.number, db.unit_type_name(unit_type))
return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type))
def next_basedefense_name(self):
return "basedefense_aa|0|0|"

View File

@ -47,12 +47,6 @@ if __name__ == "__main__":
copyfile("./resources/scripts/MissionScripting.lua", installation.get_dcs_install_directory() + os.path.sep + "Scripts/MissionScripting.lua")
app.processEvents()
# Create DCS Liberation script folder
script_dir = installation.get_dcs_saved_games_directory() + os.sep + "Scripts" + os.sep + "DCSLiberation"
if not os.path.exists(script_dir):
os.makedirs(script_dir)
copyfile("./resources/scripts/json.lua", script_dir + os.path.sep + "json.lua")
# Apply CSS (need works)
app.setStyleSheet(css)
GameUpdateSignal()

View File

@ -0,0 +1,11 @@
from PySide2.QtWidgets import QFrame
class QDebriefingInformation(QFrame):
"""
UI component to display debreifing informations
"""
def __init__(self):
super(QDebriefingInformation, self).__init__()
self.init_ui()

View File

@ -19,9 +19,6 @@ class QDebriefingWindow(QDialog):
self.gameEvent = gameEvent
self.debriefing = debriefing
self.player_losses = debriefing.destroyed_units.get(self.game.player_country, {})
self.enemy_losses = debriefing.destroyed_units.get(self.game.enemy_country, {})
self.initUI()
def initUI(self):
@ -44,7 +41,12 @@ class QDebriefingWindow(QDialog):
lostUnits.setLayout(lostUnitsLayout)
row = 0
for unit_type, count in self.player_losses.items():
for unit_type, count in self.debriefing.player_dead_aircraft_dict.items():
lostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
row += 1
for unit_type, count in self.debriefing.player_dead_units_dict.items():
lostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
row += 1
@ -56,13 +58,20 @@ class QDebriefingWindow(QDialog):
enemylostUnitsLayout = QGridLayout()
enemylostUnits.setLayout(enemylostUnitsLayout)
row = 0
if self.debriefing.destroyed_objects:
enemylostUnitsLayout.addWidget(QLabel("Ground assets"), row, 0)
enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1)
#row = 0
#if self.debriefing.destroyed_objects:
# enemylostUnitsLayout.addWidget(QLabel("Ground assets"), row, 0)
# enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1)
# row += 1
for unit_type, count in self.debriefing.enemy_dead_aircraft_dict.items():
if count == 0:
continue
enemylostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
row += 1
for unit_type, count in self.enemy_losses.items():
for unit_type, count in self.debriefing.enemy_dead_units_dict.items():
if count == 0:
continue
enemylostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)

View File

@ -1,14 +1,32 @@
import os
from PySide2 import QtCore
from PySide2.QtCore import QObject, Signal
from PySide2.QtGui import QMovie, QIcon
from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout
from PySide2.QtWidgets import QLabel, QDialog, QVBoxLayout, QGroupBox, QGridLayout, QPushButton
from game.game import Event, Game
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from userdata.debriefing import wait_for_debriefing, Debriefing
from userdata.persistency import base_path
class DebriefingFileWrittenSignal(QObject):
instance = None
debriefingReceived = Signal(Debriefing)
def __init__(self):
super(DebriefingFileWrittenSignal, self).__init__()
DebriefingFileWrittenSignal.instance = self
def sendDebriefing(self, debriefing: Debriefing):
self.debriefingReceived.emit(debriefing)
@staticmethod
def get_instance():
return DebriefingFileWrittenSignal.instance
DebriefingFileWrittenSignal()
class QWaitingForMissionResultWindow(QDialog):
@ -22,34 +40,67 @@ class QWaitingForMissionResultWindow(QDialog):
self.setWindowIcon(QIcon("./resources/icon.png"))
self.initUi()
wait_for_debriefing(lambda debriefing: self.process_debriefing(debriefing))
DebriefingFileWrittenSignal.get_instance().debriefingReceived.connect(self.updateLayout)
wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game)
def initUi(self):
self.layout = QVBoxLayout()
self.layout.addWidget(QLabel("<b>You are clear for takeoff !</b>"))
self.layout.addWidget(QLabel("In DCS open and play the mission : "))
self.layout.addWidget(QLabel("<i>liberation_nextturn</i>"))
self.layout.addWidget(QLabel("or"))
self.layout.addWidget(QLabel("<i>liberation_nextturn_quick</i>"))
self.layout.addWidget(QLabel("<b>Then save the debriefing to the folder :</b>"))
self.layout.addWidget(QLabel(self.debriefing_directory_location()))
self.layout = QGridLayout()
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(QLabel("<b>You are clear for takeoff !</b>"),0,0)
self.gridLayout.addWidget(QLabel("In DCS open and start playing the mission : "),1,0)
self.gridLayout.addWidget(QLabel("<i>liberation_nextturn</i>"),2,0)
self.gridLayout.addWidget(QLabel("or"),3,0)
self.gridLayout.addWidget(QLabel("<i>liberation_nextturn_quick</i>"),4,0)
progress = QLabel("")
progress.setAlignment(QtCore.Qt.AlignCenter)
progressBar = QMovie("./resources/ui/loader.gif")
progress.setMovie(progressBar)
self.layout.addWidget(progress)
self.gridLayout.addWidget(progress,5,0)
progressBar.start()
self.layout.addLayout(self.gridLayout,0,0)
self.setLayout(self.layout)
def updateLayout(self, debriefing):
updateBox = QGroupBox("Mission status")
updateLayout = QGridLayout()
updateBox.setLayout(updateLayout)
updateLayout.addWidget(QLabel("<b>Aircrafts destroyed</b>"), 0, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.killed_aircrafts))), 0, 1)
updateLayout.addWidget(QLabel("<b>Ground units destroyed</b>"), 1, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.killed_ground_units))), 1, 1)
updateLayout.addWidget(QLabel("<b>Weapons fired</b>"), 2, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1)
updateLayout.addWidget(QLabel("<b>Base Capture Events</b>"), 3, 0)
updateLayout.addWidget(QLabel(str(len(debriefing.base_capture_events))), 3, 1)
# Clear previous content of the window
for i in reversed(range(self.gridLayout.count())):
self.gridLayout.itemAt(i).widget().setParent(None)
# Set new window content
self.gridLayout.addWidget(updateBox, 0, 0)
if not debriefing.mission_ended:
self.gridLayout.addWidget(QLabel("<b>Mission is being played</b>"), 1, 0)
else:
#self.gridLayout.addWidget(QLabel("<b>Mission is over !</b>"), 1, 0)
proceed = QPushButton("Accept results")
proceed.setProperty("style", "btn-primary")
proceed.clicked.connect(lambda: self.process_debriefing(debriefing))
self.gridLayout.addWidget(proceed, 1, 0)
def on_debriefing_udpate(self, debriefing):
print("On Debriefing update")
print(debriefing)
DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing)
wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game)
def process_debriefing(self, debriefing: Debriefing):
debriefing.calculate_units(regular_mission=self.gameEvent.operation.regular_mission,
quick_mission=self.gameEvent.operation.quick_mission,
player_country=self.game.player_country,
enemy_country=self.game.enemy_country)
self.game.finish_event(event=self.gameEvent, debriefing=debriefing)
self.game.pass_turn(ignored_cps=[self.gameEvent.to_cp, ])

View File

@ -1,9 +1,15 @@
local jsonlib = lfs.writedir() .. "Scripts\\DCSLiberation\\json.lua"
local jsonlib = {{json_file_abs_location}}
json = loadfile(jsonlib)()
killed_aircrafts = {};
killed_ground_units = {};
logger = mist.Logger:new("DCSLiberation", "info")
debriefing_file_location = {{debriefing_file_location}}
killed_aircrafts = {}
killed_ground_units = {}
weapons_fired = {}
base_capture_events = {}
mission_ended = false
local function messageAll(message)
local msg = {}
@ -14,23 +20,24 @@ local function messageAll(message)
end
write_state = function()
log("Writing DCS Liberation State...")
local stateFile = lfs.writedir()..[[Scripts\DCSLiberation\state.json]]
local fp = io.open(stateFile, 'w')
messageAll("Writing DCS Liberation State...")
local fp = io.open(debriefing_file_location, 'w')
local game_state = {
["killed_aircrafts"] = killed_aircrafts,
["killed_ground_units"] = killed_ground_units,
["weapons_fired"] = weapons_fired,
["base_capture_events"] = base_capture_events,
["mission_ended"] = mission_ended,
}
fp:write(json:encode(game_state))
fp:close()
log("Done writing DCS Liberation state.")
messageAll("Done writing DCS Liberation state.")
end
mist.scheduleFunction(write_state, {}, timer.getTime() + 10, 60, timer.getTime() + 3600)
activeWeapons = {}
local function onCrash(event)
local function onEvent(event)
if event.id == world.event.S_EVENT_CRASH and event.initiator then
messageAll("Crash :" .. event.initiator.getName(event.initiator))
killed_aircrafts[#killed_aircrafts + 1] = event.initiator.getName(event.initiator)
@ -43,8 +50,16 @@ local function onCrash(event)
if event.id == world.event.S_EVENT_SHOT and event.weapon then
weapons_fired[#weapons_fired + 1] = event.weapon.getTypeName(event.weapon)
end
if event.id == world.event.S_EVENT_BASE_CAPTURED and event.place then
base_capture_events[#base_capture_events + 1] = event.place.getName(event.place) .. "||" .. event.place.getCoalition(event.place)
end
if event.id == world.event.S_EVENT_MISSION_END then
mission_ended = true
write_state()
end
end
mist.addEventHandler(onCrash)
mist.addEventHandler(onEvent)

View File

@ -1,3 +1,4 @@
import json
import logging
import os
import re
@ -14,188 +15,97 @@ from .persistency import base_path
DEBRIEFING_LOG_EXTENSION = "log"
class DebriefingDeadUnitInfo:
country_id = -1
player_unit = False
type = None
def parse_mutliplayer_debriefing(contents: str):
result = {}
element = None
in_events = False
for line in [x.strip() for x in contents.splitlines()]:
if line.startswith("events ="):
in_events = True
elif line.startswith("} -- end of events"):
in_events = False
if not in_events:
continue
key = None
if line.startswith("initiator\t"):
key = "initiator"
if element is None:
element = {}
elif line.startswith("initiatorMissionID\t"):
key = "initiatorMissionID"
if element is None:
element = {}
elif line.startswith("type\t"):
key = "type"
if element is None:
element = {}
elif line.startswith("}, -- end of ["):
result[len(result)] = element
element = None
continue
else:
continue
value = re.findall(r"=\s*\"(.*?)\",", line)[0]
element[key] = value
return {"debriefing": {"events": result}}
def __init__(self, country_id, player_unit , type):
self.country_id = country_id
self.player_unit = player_unit
self.type = type
class Debriefing:
def __init__(self, dead_units, dead_units_name, trigger_state):
self.destroyed_units = {} # type: typing.Dict[str, typing.Dict[UnitType, int]]
self.alive_units = {} # type: typing.Dict[str, typing.Dict[UnitType, int]]
self.destroyed_objects = [] # type: typing.List[str]
def __init__(self, state_data, game):
self.base_capture_events = state_data["base_capture_events"]
self.killed_aircrafts = state_data["killed_aircrafts"]
self.killed_ground_units = state_data["killed_ground_units"]
self.weapons_fired = state_data["weapons_fired"]
self.mission_ended = state_data["mission_ended"]
self._trigger_state = trigger_state
self._dead_units = dead_units
self.dead_units_name = dead_units_name
self.player_country_id = db.country_id_from_name(game.player_country)
self.enemy_country_id = db.country_id_from_name(game.enemy_country)
@classmethod
def parse(cls, path: str):
dead_units = []
dead_units_name = []
self.dead_aircraft = []
self.dead_units = []
def append_dead_object(object_mission_id_str, object_name):
nonlocal dead_units
object_mission_id = int(object_mission_id_str)
if object_mission_id in dead_units:
logging.error("debriefing: failed to append_dead_object {}: already exists!".format(object_mission_id))
return
dead_units.append(object_mission_id)
dead_units_name.append(object_name)
def parse_dead_object(event):
print(event)
for aircraft in self.killed_aircrafts:
try:
append_dead_object(event["initiatorMissionID"], event["initiator"])
country = int(aircraft.split("|")[1])
type = db.unit_type_from_name(aircraft.split("|")[4])
player_unit = (country == self.player_country_id)
aircraft = DebriefingDeadUnitInfo(country, player_unit, type)
self.dead_aircraft.append(aircraft)
except Exception as e:
logging.error(e)
print(e)
with open(path, "r") as f:
table_string = f.read()
for unit in self.killed_ground_units:
try:
table = parse.loads(table_string)
country = int(unit.split("|")[1])
type = db.unit_type_from_name(unit.split("|")[4])
player_unit = (country == self.player_country_id)
unit = DebriefingDeadUnitInfo(country, player_unit, type)
self.dead_units.append(unit)
except Exception as e:
table = parse_mutliplayer_debriefing(table_string)
print(e)
events = table.get("debriefing", {}).get("events", {})
for event in events.values():
event_type = event.get("type", None)
if event_type in ["crash", "dead"]:
parse_dead_object(event)
self.player_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.player_country_id]
self.enemy_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.enemy_country_id]
self.player_dead_units = [a for a in self.dead_units if a.country_id == self.player_country_id]
self.enemy_dead_units = [a for a in self.dead_units if a.country_id == self.enemy_country_id]
trigger_state = table.get("debriefing", {}).get("triggers_state", {})
self.player_dead_aircraft_dict = {}
for a in self.player_dead_aircraft:
if a.type in self.player_dead_aircraft_dict.keys():
self.player_dead_aircraft_dict[a.type] = self.player_dead_aircraft_dict[a.type] + 1
else:
self.player_dead_aircraft_dict[a.type] = 1
return Debriefing(dead_units, dead_units_name, trigger_state)
self.enemy_dead_aircraft_dict = {}
for a in self.enemy_dead_aircraft:
if a.type in self.enemy_dead_aircraft_dict.keys():
self.enemy_dead_aircraft_dict[a.type] = self.enemy_dead_aircraft_dict[a.type] + 1
else:
self.enemy_dead_aircraft_dict[a.type] = 1
def calculate_units(self, regular_mission: Mission, quick_mission: Mission, player_country: str, enemy_country: str):
def count_groups(groups: typing.List[UnitType]) -> typing.Dict[UnitType, int]:
result = {}
for group in groups:
for unit in group.units:
unit_type = db.unit_type_of(unit)
if unit_type in db.EXTRA_AA.values():
continue
self.player_dead_units_dict = {}
for a in self.player_dead_units:
if a.type in self.player_dead_units_dict.keys():
self.player_dead_units_dict[a.type] = self.player_dead_units_dict[a.type] + 1
else:
self.player_dead_units_dict[a.type] = 1
result[unit_type] = result.get(unit_type, 0) + 1
self.enemy_dead_units_dict = {}
for a in self.enemy_dead_units:
if a.type in self.enemy_dead_units_dict.keys():
self.enemy_dead_units_dict[a.type] = self.enemy_dead_units_dict[a.type] + 1
else:
self.enemy_dead_units_dict[a.type] = 1
return result
mission = regular_mission if len(self._trigger_state) else quick_mission
player = mission.country(player_country)
enemy = mission.country(enemy_country)
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: {},
enemy.name: {},
}
all_groups = {
player.name: player.plane_group + player.helicopter_group + player.vehicle_group + player.ship_group,
enemy.name: enemy.plane_group + enemy.helicopter_group + enemy.vehicle_group + enemy.ship_group,
}
static_groups = enemy.static_group
for country_name, country_groups in all_groups.items():
for group in country_groups:
for unit in group.units:
if unit.id in self._dead_units:
unit_type = db.unit_type_of(unit)
logging.info("debriefing: found dead unit {} ({}, {}) for country {}".format(str(unit.name), unit.id, unit_type, country_name))
assert country_name
assert unit_type
self.destroyed_units[country_name][unit_type] = self.destroyed_units[country_name].get(unit_type, 0) + 1
self._dead_units.remove(unit.id)
for group in static_groups:
identifier = group.units[0].id
if identifier in self._dead_units:
logging.info("debriefing: found dead static {} ({})".format(str(group.name), identifier))
assert str(group.name)
self.destroyed_objects.append(str(group.name))
self._dead_units.remove(identifier)
logging.info("debriefing: unsatistied ids: {}".format(self._dead_units))
self.alive_units = {
player.name: {k: v - self.destroyed_units[player.name].get(k, 0) for k, v in player_units.items()},
enemy.name: {k: v - self.destroyed_units[enemy.name].get(k, 0) for k, v in enemy_units.items()},
}
def debriefing_directory_location() -> str:
return os.path.join(base_path(), "liberation_debriefings")
def _logfiles_snapshot() -> typing.Dict[str, float]:
result = {}
for file in os.listdir(debriefing_directory_location()):
fullpath = os.path.join(debriefing_directory_location(), file)
result[file] = os.path.getmtime(fullpath)
return result
def _poll_new_debriefing_log(snapshot: typing.Dict[str, float], callback: typing.Callable):
should_run = True
while should_run:
for file, timestamp in _logfiles_snapshot().items():
if file not in snapshot or timestamp != snapshot[file]:
debriefing = Debriefing.parse(os.path.join(debriefing_directory_location(), file))
def _poll_new_debriefing_log(callback: typing.Callable, game):
if os.path.isfile("state.json"):
last_modified = os.path.getmtime("state.json")
else:
last_modified = 0
while True:
if os.path.isfile("state.json") and os.path.getmtime("state.json") > last_modified:
with open("state.json", "r") as json_file:
json_data = json.load(json_file) #Debriefing.parse(os.path.join(debriefing_directory_location(), file))
debriefing = Debriefing(json_data, game)
callback(debriefing)
should_run = False
break
break
time.sleep(5)
time.sleep(3)
def wait_for_debriefing(callback: typing.Callable):
if not os.path.exists(debriefing_directory_location()):
os.mkdir(debriefing_directory_location())
threading.Thread(target=_poll_new_debriefing_log, args=(_logfiles_snapshot(), callback)).start()
def wait_for_debriefing(callback: typing.Callable, game):
threading.Thread(target=_poll_new_debriefing_log, args=[callback, game]).start()

View File

@ -5,6 +5,8 @@ import os
import sys
import shutil
from dcs import installation
_user_folder = None # type: str
@ -17,6 +19,7 @@ def base_path() -> str:
global _user_folder
assert _user_folder
return installation.get_dcs_saved_games_directory()
openbeta_path = os.path.join(_user_folder, "DCS.openbeta")
if "--force-stable-DCS" not in sys.argv and os.path.exists(openbeta_path):
return openbeta_path

10
userdata/state.py Normal file
View File

@ -0,0 +1,10 @@
class RunningMissionState:
killed_aircrafts = []
killed_ground_units = []
weapons_fired = []
def __init__(self):
pass