mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add unit name -> Liberation object map.
Generated units are added to this during mission generation so we can map destroyed units back to the data that generated them. Currently only implemented for aircraft as a proof of concept.
This commit is contained in:
parent
d5a081a15f
commit
f6fad30852
@ -1,176 +1,209 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import typing
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, Callable, Dict, List, Type, TYPE_CHECKING
|
||||||
|
|
||||||
|
from dcs.unittype import FlyingType, UnitType
|
||||||
|
|
||||||
from game import db
|
from game import db
|
||||||
|
from game.theater import TheaterGroundObject
|
||||||
|
from game.unitmap import UnitMap
|
||||||
|
from gen.flights.flight import Flight
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from game import Game
|
||||||
|
|
||||||
DEBRIEFING_LOG_EXTENSION = "log"
|
DEBRIEFING_LOG_EXTENSION = "log"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
class DebriefingDeadUnitInfo:
|
class DebriefingDeadUnitInfo:
|
||||||
country_id = -1
|
player_unit: bool
|
||||||
player_unit = False
|
type: Type[UnitType]
|
||||||
type = None
|
|
||||||
|
|
||||||
def __init__(self, country_id, player_unit , type):
|
|
||||||
self.country_id = country_id
|
|
||||||
self.player_unit = player_unit
|
|
||||||
self.type = type
|
|
||||||
|
|
||||||
def __repr__(self):
|
@dataclass(frozen=True)
|
||||||
return str(self.country_id) + " " + str(self.player_unit) + " " + str(self.type)
|
class DebriefingDeadAircraftInfo:
|
||||||
|
#: The Flight that resulted in the generated unit.
|
||||||
|
flight: Flight
|
||||||
|
|
||||||
|
@property
|
||||||
|
def player_unit(self) -> bool:
|
||||||
|
return self.flight.departure.captured
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class DebriefingDeadBuildingInfo:
|
||||||
|
#: The ground object this building was present at.
|
||||||
|
ground_object: TheaterGroundObject
|
||||||
|
|
||||||
|
@property
|
||||||
|
def player_unit(self) -> bool:
|
||||||
|
return self.ground_object.control_point.captured
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class AirLosses:
|
||||||
|
losses: List[DebriefingDeadAircraftInfo]
|
||||||
|
|
||||||
|
def by_type(self, player: bool) -> Dict[Type[FlyingType], int]:
|
||||||
|
losses_by_type: Dict[Type[FlyingType], int] = defaultdict(int)
|
||||||
|
for loss in self.losses:
|
||||||
|
if loss.flight.departure.captured != player:
|
||||||
|
continue
|
||||||
|
|
||||||
|
losses_by_type[loss.flight.unit_type] += loss.flight.count
|
||||||
|
return losses_by_type
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class StateData:
|
||||||
|
#: True if the mission ended. If False, the mission exited abnormally.
|
||||||
|
mission_ended: bool
|
||||||
|
|
||||||
|
#: Names of aircraft units that were killed during the mission.
|
||||||
|
killed_aircraft: List[str]
|
||||||
|
|
||||||
|
#: Names of vehicle (and ship) units that were killed during the mission.
|
||||||
|
killed_ground_units: List[str]
|
||||||
|
|
||||||
|
#: Names of static units that were destroyed during the mission.
|
||||||
|
destroyed_statics: List[str]
|
||||||
|
|
||||||
|
#: Mangled names of bases that were captured during the mission.
|
||||||
|
base_capture_events: List[str]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_json(cls, data: Dict[str, Any]) -> StateData:
|
||||||
|
return cls(
|
||||||
|
mission_ended=data["mission_ended"],
|
||||||
|
killed_aircraft=data["killed_aircrafts"],
|
||||||
|
killed_ground_units=data["killed_ground_units"],
|
||||||
|
destroyed_statics=data["destroyed_objects_positions"],
|
||||||
|
base_capture_events=data["base_capture_events"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Debriefing:
|
class Debriefing:
|
||||||
def __init__(self, state_data, game):
|
def __init__(self, state_data: Dict[str, Any], game: Game,
|
||||||
self.state_data = state_data
|
unit_map: UnitMap) -> None:
|
||||||
self.killed_aircrafts = state_data["killed_aircrafts"]
|
self.state_data = StateData.from_json(state_data)
|
||||||
self.killed_ground_units = state_data["killed_ground_units"]
|
self.game = game
|
||||||
self.weapons_fired = state_data["weapons_fired"]
|
self.unit_map = unit_map
|
||||||
self.mission_ended = state_data["mission_ended"]
|
|
||||||
self.destroyed_units = state_data["destroyed_objects_positions"]
|
|
||||||
|
|
||||||
self.__destroyed_units = []
|
|
||||||
logging.info("--------------------------------")
|
logging.info("--------------------------------")
|
||||||
logging.info("Starting Debriefing preprocessing")
|
logging.info("Starting Debriefing preprocessing")
|
||||||
logging.info("--------------------------------")
|
logging.info("--------------------------------")
|
||||||
logging.info(self.base_capture_events)
|
logging.info(self.state_data)
|
||||||
logging.info(self.killed_aircrafts)
|
|
||||||
logging.info(self.killed_ground_units)
|
|
||||||
logging.info(self.weapons_fired)
|
|
||||||
logging.info(self.mission_ended)
|
|
||||||
logging.info(self.destroyed_units)
|
|
||||||
logging.info("--------------------------------")
|
logging.info("--------------------------------")
|
||||||
|
|
||||||
self.player_country_id = db.country_id_from_name(game.player_country)
|
self.player_country_id = db.country_id_from_name(game.player_country)
|
||||||
self.enemy_country_id = db.country_id_from_name(game.enemy_country)
|
self.enemy_country_id = db.country_id_from_name(game.enemy_country)
|
||||||
|
|
||||||
self.dead_aircraft = []
|
self.air_losses = self.dead_aircraft()
|
||||||
self.dead_units = []
|
self.dead_units: List[DebriefingDeadUnitInfo] = []
|
||||||
self.dead_aaa_groups = []
|
self.dead_aaa_groups: List[DebriefingDeadUnitInfo] = []
|
||||||
self.dead_buildings = []
|
self.dead_buildings: List[DebriefingDeadBuildingInfo] = []
|
||||||
|
|
||||||
for aircraft in self.killed_aircrafts:
|
for unit_name in self.state_data.killed_ground_units:
|
||||||
try:
|
try:
|
||||||
country = int(aircraft.split("|")[1])
|
if isinstance(unit_name, int):
|
||||||
type = db.unit_type_from_name(aircraft.split("|")[4])
|
# For some reason the state file will include many raw
|
||||||
player_unit = (country == self.player_country_id)
|
# integers in the list of destroyed units. These might be
|
||||||
aircraft = DebriefingDeadUnitInfo(country, player_unit, type)
|
# from the smoke effects?
|
||||||
if type is not None:
|
continue
|
||||||
self.dead_aircraft.append(aircraft)
|
country = int(unit_name.split("|")[1])
|
||||||
except Exception as e:
|
unit_type = db.unit_type_from_name(unit_name.split("|")[4])
|
||||||
logging.error(e)
|
if unit_type is None:
|
||||||
|
logging.error(f"Could not determine type of {unit_name}")
|
||||||
|
continue
|
||||||
|
player_unit = country == self.player_country_id
|
||||||
|
self.dead_units.append(
|
||||||
|
DebriefingDeadUnitInfo(player_unit, unit_type))
|
||||||
|
except Exception:
|
||||||
|
logging.exception(f"Failed to process dead unit {unit_name}")
|
||||||
|
|
||||||
for unit in self.killed_ground_units:
|
for unit_name in self.state_data.killed_ground_units:
|
||||||
try:
|
|
||||||
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)
|
|
||||||
if type is not None:
|
|
||||||
self.dead_units.append(unit)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(e)
|
|
||||||
|
|
||||||
for unit in self.killed_ground_units:
|
|
||||||
for cp in game.theater.controlpoints:
|
for cp in game.theater.controlpoints:
|
||||||
|
|
||||||
logging.info(cp.name)
|
|
||||||
logging.info(cp.captured)
|
|
||||||
|
|
||||||
if cp.captured:
|
if cp.captured:
|
||||||
country = self.player_country_id
|
country = self.player_country_id
|
||||||
else:
|
else:
|
||||||
country = self.enemy_country_id
|
country = self.enemy_country_id
|
||||||
player_unit = (country == self.player_country_id)
|
player_unit = (country == self.player_country_id)
|
||||||
|
|
||||||
for i, ground_object in enumerate(cp.ground_objects):
|
for ground_object in cp.ground_objects:
|
||||||
logging.info(unit)
|
# TODO: This seems to destroy an arbitrary building?
|
||||||
logging.info(ground_object.group_name)
|
if ground_object.is_same_group(unit_name):
|
||||||
if ground_object.is_same_group(unit):
|
self.dead_buildings.append(
|
||||||
unit = DebriefingDeadUnitInfo(country, player_unit, ground_object.dcs_identifier)
|
DebriefingDeadBuildingInfo(ground_object))
|
||||||
self.dead_buildings.append(unit)
|
elif ground_object.dcs_identifier in ["AA", "CARRIER",
|
||||||
elif ground_object.dcs_identifier in ["AA", "CARRIER", "LHA"]:
|
"LHA"]:
|
||||||
for g in ground_object.groups:
|
for g in ground_object.groups:
|
||||||
for u in g.units:
|
for u in g.units:
|
||||||
if u.name == unit:
|
if u.name != unit_name:
|
||||||
unit = DebriefingDeadUnitInfo(country, player_unit, db.unit_type_from_name(u.type))
|
continue
|
||||||
self.dead_units.append(unit)
|
unit_type = db.unit_type_from_name(u.type)
|
||||||
|
if unit_type is None:
|
||||||
|
logging.error(
|
||||||
|
f"Could not determine type of %s",
|
||||||
|
unit_name)
|
||||||
|
continue
|
||||||
|
self.dead_units.append(DebriefingDeadUnitInfo(
|
||||||
|
player_unit, unit_type))
|
||||||
|
|
||||||
self.player_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.player_country_id]
|
self.player_dead_units = [a for a in self.dead_units if a.player_unit]
|
||||||
self.enemy_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.enemy_country_id]
|
self.enemy_dead_units = [a for a in self.dead_units if not a.player_unit]
|
||||||
self.player_dead_units = [a for a in self.dead_units if a.country_id == self.player_country_id]
|
self.player_dead_buildings = [a for a in self.dead_buildings if a.player_unit]
|
||||||
self.enemy_dead_units = [a for a in self.dead_units if a.country_id == self.enemy_country_id]
|
self.enemy_dead_buildings = [a for a in self.dead_buildings if not a.player_unit]
|
||||||
self.player_dead_buildings = [a for a in self.dead_buildings if a.country_id == self.player_country_id]
|
|
||||||
self.enemy_dead_buildings = [a for a in self.dead_buildings if a.country_id == self.enemy_country_id]
|
|
||||||
|
|
||||||
logging.info(self.player_dead_aircraft)
|
self.player_dead_units_dict: Dict[Type[UnitType], int] = defaultdict(int)
|
||||||
logging.info(self.enemy_dead_aircraft)
|
|
||||||
logging.info(self.player_dead_units)
|
|
||||||
logging.info(self.enemy_dead_units)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
self.player_dead_units_dict = {}
|
|
||||||
for a in self.player_dead_units:
|
for a in self.player_dead_units:
|
||||||
if a.type in self.player_dead_units_dict.keys():
|
self.player_dead_units_dict[a.type] += 1
|
||||||
self.player_dead_units_dict[a.type] = self.player_dead_units_dict[a.type] + 1
|
|
||||||
else:
|
|
||||||
self.player_dead_units_dict[a.type] = 1
|
|
||||||
|
|
||||||
self.enemy_dead_units_dict = {}
|
self.enemy_dead_units_dict: Dict[Type[UnitType], int] = defaultdict(int)
|
||||||
for a in self.enemy_dead_units:
|
for a in self.enemy_dead_units:
|
||||||
if a.type in self.enemy_dead_units_dict.keys():
|
self.enemy_dead_units_dict[a.type] += 1
|
||||||
self.enemy_dead_units_dict[a.type] = self.enemy_dead_units_dict[a.type] + 1
|
|
||||||
else:
|
|
||||||
self.enemy_dead_units_dict[a.type] = 1
|
|
||||||
|
|
||||||
self.player_dead_buildings_dict = {}
|
self.player_dead_buildings_dict: Dict[str, int] = defaultdict(int)
|
||||||
for a in self.player_dead_buildings:
|
for b in self.player_dead_buildings:
|
||||||
if a.type in self.player_dead_buildings_dict.keys():
|
self.player_dead_buildings_dict[b.ground_object.dcs_identifier] += 1
|
||||||
self.player_dead_buildings_dict[a.type] = self.player_dead_buildings_dict[a.type] + 1
|
|
||||||
else:
|
|
||||||
self.player_dead_buildings_dict[a.type] = 1
|
|
||||||
|
|
||||||
self.enemy_dead_buildings_dict = {}
|
self.enemy_dead_buildings_dict: Dict[str, int] = defaultdict(int)
|
||||||
for a in self.enemy_dead_buildings:
|
for b in self.enemy_dead_buildings:
|
||||||
if a.type in self.enemy_dead_buildings_dict.keys():
|
self.enemy_dead_buildings_dict[b.ground_object.dcs_identifier] += 1
|
||||||
self.enemy_dead_buildings_dict[a.type] = self.enemy_dead_buildings_dict[a.type] + 1
|
|
||||||
else:
|
|
||||||
self.enemy_dead_buildings_dict[a.type] = 1
|
|
||||||
|
|
||||||
logging.info("--------------------------------")
|
logging.info("--------------------------------")
|
||||||
logging.info("Debriefing pre process results :")
|
logging.info("Debriefing pre process results :")
|
||||||
logging.info("--------------------------------")
|
logging.info("--------------------------------")
|
||||||
logging.info(self.player_dead_aircraft_dict)
|
logging.info(self.air_losses)
|
||||||
logging.info(self.enemy_dead_aircraft_dict)
|
|
||||||
logging.info(self.player_dead_units_dict)
|
logging.info(self.player_dead_units_dict)
|
||||||
logging.info(self.enemy_dead_units_dict)
|
logging.info(self.enemy_dead_units_dict)
|
||||||
logging.info(self.player_dead_buildings_dict)
|
logging.info(self.player_dead_buildings_dict)
|
||||||
logging.info(self.enemy_dead_buildings_dict)
|
logging.info(self.enemy_dead_buildings_dict)
|
||||||
|
|
||||||
|
def dead_aircraft(self) -> AirLosses:
|
||||||
|
losses = []
|
||||||
|
for unit_name in self.state_data.killed_aircraft:
|
||||||
|
flight = self.unit_map.flight(unit_name)
|
||||||
|
if flight is None:
|
||||||
|
logging.error(f"Could not find Flight matching {unit_name}")
|
||||||
|
continue
|
||||||
|
losses.append(DebriefingDeadAircraftInfo(flight))
|
||||||
|
return AirLosses(losses)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base_capture_events(self):
|
def base_capture_events(self):
|
||||||
"""Keeps only the last instance of a base capture event for each base ID"""
|
"""Keeps only the last instance of a base capture event for each base ID."""
|
||||||
reversed_captures = [i for i in self.state_data["base_capture_events"][::-1]]
|
reversed_captures = list(reversed(self.state_data.base_capture_events))
|
||||||
last_base_cap_indexes = []
|
last_base_cap_indexes = []
|
||||||
for idx, base in enumerate(i.split("||")[0] for i in reversed_captures):
|
for idx, base in enumerate(i.split("||")[0] for i in reversed_captures):
|
||||||
if base in [x[1] for x in last_base_cap_indexes]:
|
if base not in [x[1] for x in last_base_cap_indexes]:
|
||||||
continue
|
|
||||||
else:
|
|
||||||
last_base_cap_indexes.append((idx, base))
|
last_base_cap_indexes.append((idx, base))
|
||||||
return [reversed_captures[idx[0]] for idx in last_base_cap_indexes]
|
return [reversed_captures[idx[0]] for idx in last_base_cap_indexes]
|
||||||
|
|
||||||
@ -179,11 +212,13 @@ class PollDebriefingFileThread(threading.Thread):
|
|||||||
"""Thread class with a stop() method. The thread itself has to check
|
"""Thread class with a stop() method. The thread itself has to check
|
||||||
regularly for the stopped() condition."""
|
regularly for the stopped() condition."""
|
||||||
|
|
||||||
def __init__(self, callback: typing.Callable, game):
|
def __init__(self, callback: Callable[[Debriefing], None],
|
||||||
super(PollDebriefingFileThread, self).__init__()
|
game: Game, unit_map: UnitMap) -> None:
|
||||||
|
super().__init__()
|
||||||
self._stop_event = threading.Event()
|
self._stop_event = threading.Event()
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.game = game
|
self.game = game
|
||||||
|
self.unit_map = unit_map
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._stop_event.set()
|
self._stop_event.set()
|
||||||
@ -200,14 +235,14 @@ class PollDebriefingFileThread(threading.Thread):
|
|||||||
if os.path.isfile("state.json") and os.path.getmtime("state.json") > last_modified:
|
if os.path.isfile("state.json") and os.path.getmtime("state.json") > last_modified:
|
||||||
with open("state.json", "r") as json_file:
|
with open("state.json", "r") as json_file:
|
||||||
json_data = json.load(json_file)
|
json_data = json.load(json_file)
|
||||||
debriefing = Debriefing(json_data, self.game)
|
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
||||||
self.callback(debriefing)
|
self.callback(debriefing)
|
||||||
break
|
break
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
|
||||||
def wait_for_debriefing(callback: typing.Callable, game)->PollDebriefingFileThread:
|
def wait_for_debriefing(callback: Callable[[Debriefing], None],
|
||||||
thread = PollDebriefingFileThread(callback, game)
|
game: Game, unit_map) -> PollDebriefingFileThread:
|
||||||
|
thread = PollDebriefingFileThread(callback, game, unit_map)
|
||||||
thread.start()
|
thread.start()
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from game.debriefing import Debriefing
|
|||||||
from game.infos.information import Information
|
from game.infos.information import Information
|
||||||
from game.theater import ControlPoint
|
from game.theater import ControlPoint
|
||||||
from gen.ground_forces.combat_stance import CombatStance
|
from gen.ground_forces.combat_stance import CombatStance
|
||||||
|
from ..unitmap import UnitMap
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..game import Game
|
from ..game import Game
|
||||||
@ -85,17 +86,18 @@ class Event:
|
|||||||
def bonus(self) -> int:
|
def bonus(self) -> int:
|
||||||
return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
return int(math.log(self.to_cp.importance + 1, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
||||||
|
|
||||||
def is_successfull(self, debriefing: Debriefing) -> bool:
|
def is_successful(self, debriefing: Debriefing) -> bool:
|
||||||
return self.operation.is_successfull(debriefing)
|
return self.operation.is_successful(debriefing)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self) -> UnitMap:
|
||||||
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
self.operation.is_awacs_enabled = self.is_awacs_enabled
|
||||||
self.operation.ca_slots = self.ca_slots
|
self.operation.ca_slots = self.ca_slots
|
||||||
|
|
||||||
self.operation.prepare(self.game)
|
self.operation.prepare(self.game)
|
||||||
self.operation.generate()
|
unit_map = self.operation.generate()
|
||||||
self.operation.current_mission.save(persistency.mission_path_for("liberation_nextturn.miz"))
|
self.operation.current_mission.save(
|
||||||
self.environment_settings = self.operation.environment_settings
|
persistency.mission_path_for("liberation_nextturn.miz"))
|
||||||
|
return unit_map
|
||||||
|
|
||||||
def commit(self, debriefing: Debriefing):
|
def commit(self, debriefing: Debriefing):
|
||||||
|
|
||||||
@ -103,41 +105,39 @@ class Event:
|
|||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Destroyed aircrafts
|
# Destroyed aircrafts
|
||||||
cp_map = {cp.id: cp for cp in self.game.theater.controlpoints}
|
for loss in debriefing.air_losses.losses:
|
||||||
for destroyed_aircraft in debriefing.killed_aircrafts:
|
aircraft = loss.flight.unit_type
|
||||||
try:
|
cp = loss.flight.departure
|
||||||
cpid = int(destroyed_aircraft.split("|")[3])
|
available = cp.base.total_units_of_type(aircraft)
|
||||||
aircraft = db.unit_type_from_name(
|
if available <= 0:
|
||||||
destroyed_aircraft.split("|")[4])
|
logging.error(
|
||||||
if cpid in cp_map:
|
f"Found killed {aircraft} from {cp} but that airbase has "
|
||||||
cp = cp_map[cpid]
|
f"none available.")
|
||||||
if aircraft in cp.base.aircraft:
|
continue
|
||||||
logging.info(f"Aircraft destroyed: {aircraft}")
|
|
||||||
cp.base.aircraft[aircraft] = max(
|
logging.info(f"{aircraft} destroyed from {cp}")
|
||||||
0, cp.base.aircraft[aircraft] - 1)
|
cp.base.aircraft[aircraft] -= 1
|
||||||
except Exception:
|
|
||||||
logging.exception("Failed to commit destroyed aircraft")
|
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Destroyed ground units
|
# Destroyed ground units
|
||||||
killed_unit_count_by_cp = {cp.id: 0 for cp in self.game.theater.controlpoints}
|
killed_unit_count_by_cp = {cp.id: 0 for cp in self.game.theater.controlpoints}
|
||||||
cp_map = {cp.id: cp for cp in self.game.theater.controlpoints}
|
cp_map = {cp.id: cp for cp in self.game.theater.controlpoints}
|
||||||
for killed_ground_unit in debriefing.killed_ground_units:
|
for killed_ground_unit in debriefing.state_data.killed_ground_units:
|
||||||
try:
|
try:
|
||||||
cpid = int(killed_ground_unit.split("|")[3])
|
cpid = int(killed_ground_unit.split("|")[3])
|
||||||
aircraft = db.unit_type_from_name(killed_ground_unit.split("|")[4])
|
unit_type = db.unit_type_from_name(killed_ground_unit.split("|")[4])
|
||||||
if cpid in cp_map.keys():
|
if cpid in cp_map.keys():
|
||||||
killed_unit_count_by_cp[cpid] = killed_unit_count_by_cp[cpid] + 1
|
killed_unit_count_by_cp[cpid] = killed_unit_count_by_cp[cpid] + 1
|
||||||
cp = cp_map[cpid]
|
cp = cp_map[cpid]
|
||||||
if aircraft in cp.base.armor.keys():
|
if unit_type in cp.base.armor.keys():
|
||||||
logging.info("Ground unit destroyed : " + str(aircraft))
|
logging.info(f"Ground unit destroyed: {unit_type}")
|
||||||
cp.base.armor[aircraft] = max(0, cp.base.armor[aircraft] - 1)
|
cp.base.armor[unit_type] = max(0, cp.base.armor[unit_type] - 1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Static ground objects
|
# Static ground objects
|
||||||
for destroyed_ground_unit_name in debriefing.killed_ground_units:
|
for destroyed_ground_unit_name in debriefing.state_data.killed_ground_units:
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
if not cp.ground_objects:
|
if not cp.ground_objects:
|
||||||
continue
|
continue
|
||||||
@ -224,7 +224,7 @@ class Event:
|
|||||||
|
|
||||||
# Destroyed units carcass
|
# Destroyed units carcass
|
||||||
# -------------------------
|
# -------------------------
|
||||||
for destroyed_unit in debriefing.destroyed_units:
|
for destroyed_unit in debriefing.state_data.destroyed_statics:
|
||||||
self.game.add_destroyed_units(destroyed_unit)
|
self.game.add_destroyed_units(destroyed_unit)
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class FrontlineAttackEvent(Event):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Frontline attack"
|
return "Frontline attack"
|
||||||
|
|
||||||
def is_successfull(self, debriefing: Debriefing):
|
def is_successful(self, debriefing: Debriefing):
|
||||||
attackers_success = True
|
attackers_success = True
|
||||||
if self.from_cp.captured:
|
if self.from_cp.captured:
|
||||||
return attackers_success
|
return attackers_success
|
||||||
|
|||||||
@ -27,6 +27,7 @@ from .factions.faction import Faction
|
|||||||
from .infos.information import Information
|
from .infos.information import Information
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .theater import ConflictTheater, ControlPoint, OffMapSpawn
|
from .theater import ConflictTheater, ControlPoint, OffMapSpawn
|
||||||
|
from .unitmap import UnitMap
|
||||||
from .weather import Conditions, TimeOfDay
|
from .weather import Conditions, TimeOfDay
|
||||||
|
|
||||||
COMMISION_UNIT_VARIETY = 4
|
COMMISION_UNIT_VARIETY = 4
|
||||||
@ -173,15 +174,15 @@ class Game:
|
|||||||
self.events.append(event)
|
self.events.append(event)
|
||||||
return event
|
return event
|
||||||
|
|
||||||
def initiate_event(self, event: Event):
|
def initiate_event(self, event: Event) -> UnitMap:
|
||||||
#assert event in self.events
|
#assert event in self.events
|
||||||
logging.info("Generating {} (regular)".format(event))
|
logging.info("Generating {} (regular)".format(event))
|
||||||
event.generate()
|
return event.generate()
|
||||||
|
|
||||||
def finish_event(self, event: Event, debriefing: Debriefing):
|
def finish_event(self, event: Event, debriefing: Debriefing):
|
||||||
logging.info("Finishing event {}".format(event))
|
logging.info("Finishing event {}".format(event))
|
||||||
event.commit(debriefing)
|
event.commit(debriefing)
|
||||||
if event.is_successfull(debriefing):
|
if event.is_successful(debriefing):
|
||||||
self.budget += event.bonus()
|
self.budget += event.bonus()
|
||||||
|
|
||||||
if event in self.events:
|
if event in self.events:
|
||||||
|
|||||||
@ -34,6 +34,7 @@ from gen.triggergen import TRIGGER_RADIUS_MEDIUM, TriggersGenerator
|
|||||||
|
|
||||||
from .. import db
|
from .. import db
|
||||||
from ..debriefing import Debriefing
|
from ..debriefing import Debriefing
|
||||||
|
from ..unitmap import UnitMap
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
@ -59,6 +60,7 @@ class Operation:
|
|||||||
is_quick = None
|
is_quick = None
|
||||||
is_awacs_enabled = False
|
is_awacs_enabled = False
|
||||||
ca_slots = 0
|
ca_slots = 0
|
||||||
|
unit_map: UnitMap
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
departure_cp: ControlPoint,
|
departure_cp: ControlPoint,
|
||||||
@ -94,7 +96,7 @@ class Operation:
|
|||||||
def units_of(self, country_name: str) -> List[UnitType]:
|
def units_of(self, country_name: str) -> List[UnitType]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def is_successfull(self, debriefing: Debriefing) -> bool:
|
def is_successful(self, debriefing: Debriefing) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -177,6 +179,10 @@ class Operation:
|
|||||||
gen.add_flight(flight)
|
gen.add_flight(flight)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_unit_map(cls) -> None:
|
||||||
|
cls.unit_map = UnitMap()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_radio_registries(cls) -> None:
|
def create_radio_registries(cls) -> None:
|
||||||
unique_map_frequencies = set() # type: Set[RadioFrequency]
|
unique_map_frequencies = set() # type: Set[RadioFrequency]
|
||||||
@ -269,8 +275,9 @@ class Operation:
|
|||||||
dead=True,
|
dead=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self) -> UnitMap:
|
||||||
"""Build the final Mission to be exported"""
|
"""Build the final Mission to be exported"""
|
||||||
|
self.create_unit_map()
|
||||||
self.create_radio_registries()
|
self.create_radio_registries()
|
||||||
# Set mission time and weather conditions.
|
# Set mission time and weather conditions.
|
||||||
EnvironmentGenerator(self.current_mission,
|
EnvironmentGenerator(self.current_mission,
|
||||||
@ -323,6 +330,8 @@ class Operation:
|
|||||||
self.airgen
|
self.airgen
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return self.unit_map
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _generate_air_units(cls) -> None:
|
def _generate_air_units(cls) -> None:
|
||||||
"""Generate the air units for the Operation"""
|
"""Generate the air units for the Operation"""
|
||||||
@ -339,7 +348,7 @@ class Operation:
|
|||||||
# Generate Aircraft Activity on the map
|
# Generate Aircraft Activity on the map
|
||||||
cls.airgen = AircraftConflictGenerator(
|
cls.airgen = AircraftConflictGenerator(
|
||||||
cls.current_mission, cls.game.settings, cls.game,
|
cls.current_mission, cls.game.settings, cls.game,
|
||||||
cls.radio_registry)
|
cls.radio_registry, cls.unit_map)
|
||||||
|
|
||||||
cls.airgen.generate_flights(
|
cls.airgen.generate_flights(
|
||||||
cls.current_mission.country(cls.game.player_country),
|
cls.current_mission.country(cls.game.player_country),
|
||||||
|
|||||||
23
game/unitmap.py
Normal file
23
game/unitmap.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"""Maps generated units back to their Liberation types."""
|
||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
from dcs.unitgroup import FlyingGroup
|
||||||
|
|
||||||
|
from gen.flights.flight import Flight
|
||||||
|
|
||||||
|
|
||||||
|
class UnitMap:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.aircraft: Dict[str, Flight] = {}
|
||||||
|
|
||||||
|
def add_aircraft(self, group: FlyingGroup, flight: Flight) -> None:
|
||||||
|
for unit in group.units:
|
||||||
|
# The actual name is a String (the pydcs translatable string), which
|
||||||
|
# doesn't define __eq__.
|
||||||
|
name = str(unit.name)
|
||||||
|
if name in self.aircraft:
|
||||||
|
raise RuntimeError(f"Duplicate unit name: {name}")
|
||||||
|
self.aircraft[name] = flight
|
||||||
|
|
||||||
|
def flight(self, group_name: str) -> Optional[Flight]:
|
||||||
|
return self.aircraft.get(group_name, None)
|
||||||
@ -76,6 +76,7 @@ from game.theater.controlpoint import (
|
|||||||
OffMapSpawn,
|
OffMapSpawn,
|
||||||
)
|
)
|
||||||
from game.theater.theatergroundobject import TheaterGroundObject
|
from game.theater.theatergroundobject import TheaterGroundObject
|
||||||
|
from game.unitmap import UnitMap
|
||||||
from game.utils import knots_to_kph, nm_to_meter
|
from game.utils import knots_to_kph, nm_to_meter
|
||||||
from gen.airsupportgen import AirSupport
|
from gen.airsupportgen import AirSupport
|
||||||
from gen.ato import AirTaskingOrder, Package
|
from gen.ato import AirTaskingOrder, Package
|
||||||
@ -647,12 +648,13 @@ AIRCRAFT_DATA["P-47D-30"] = AIRCRAFT_DATA["P-51D"]
|
|||||||
|
|
||||||
|
|
||||||
class AircraftConflictGenerator:
|
class AircraftConflictGenerator:
|
||||||
def __init__(self, mission: Mission, settings: Settings,
|
def __init__(self, mission: Mission, settings: Settings, game: Game,
|
||||||
game: Game, radio_registry: RadioRegistry):
|
radio_registry: RadioRegistry, unit_map: UnitMap) -> None:
|
||||||
self.m = mission
|
self.m = mission
|
||||||
self.game = game
|
self.game = game
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.radio_registry = radio_registry
|
self.radio_registry = radio_registry
|
||||||
|
self.unit_map = unit_map
|
||||||
self.flights: List[FlightData] = []
|
self.flights: List[FlightData] = []
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@ -927,6 +929,7 @@ class AircraftConflictGenerator:
|
|||||||
logging.info(f"Generating flight: {flight.unit_type}")
|
logging.info(f"Generating flight: {flight.unit_type}")
|
||||||
group = self.generate_planned_flight(flight.from_cp, country,
|
group = self.generate_planned_flight(flight.from_cp, country,
|
||||||
flight)
|
flight)
|
||||||
|
self.unit_map.add_aircraft(group, flight)
|
||||||
self.setup_flight_group(group, package, flight, dynamic_runways)
|
self.setup_flight_group(group, package, flight, dynamic_runways)
|
||||||
self.create_waypoints(group, package, flight)
|
self.create_waypoints(group, package, flight)
|
||||||
|
|
||||||
|
|||||||
@ -235,8 +235,9 @@ class QTopPanel(QFrame):
|
|||||||
game_event.departure_cp = self.game.theater.controlpoints[0]
|
game_event.departure_cp = self.game.theater.controlpoints[0]
|
||||||
game_event.player_attacking()
|
game_event.player_attacking()
|
||||||
|
|
||||||
self.game.initiate_event(game_event)
|
unit_map = self.game.initiate_event(game_event)
|
||||||
waiting = QWaitingForMissionResultWindow(game_event, self.game)
|
waiting = QWaitingForMissionResultWindow(game_event, self.game,
|
||||||
|
unit_map)
|
||||||
waiting.show()
|
waiting.show()
|
||||||
|
|
||||||
def budget_update(self, game:Game):
|
def budget_update(self, game:Game):
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
from PySide2.QtGui import QIcon, QPixmap
|
from PySide2.QtGui import QIcon, QPixmap
|
||||||
from PySide2.QtWidgets import (
|
from PySide2.QtWidgets import (
|
||||||
QDialog,
|
QDialog,
|
||||||
@ -55,29 +57,35 @@ class QDebriefingWindow(QDialog):
|
|||||||
lostUnits.setLayout(lostUnitsLayout)
|
lostUnits.setLayout(lostUnitsLayout)
|
||||||
|
|
||||||
row = 0
|
row = 0
|
||||||
for unit_type, count in self.debriefing.player_dead_aircraft_dict.items():
|
player_air_losses = self.debriefing.air_losses.by_type(player=True)
|
||||||
|
for unit_type, count in player_air_losses.items():
|
||||||
try:
|
try:
|
||||||
lostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
|
lostUnitsLayout.addWidget(
|
||||||
lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
QLabel(db.unit_type_name(unit_type)), row, 0)
|
||||||
|
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||||
row += 1
|
row += 1
|
||||||
except:
|
except AttributeError:
|
||||||
print("Issue adding " + str(unit_type) + " to debriefing information")
|
logging.exception(
|
||||||
|
f"Issue adding {unit_type} to debriefing information")
|
||||||
|
|
||||||
for unit_type, count in self.debriefing.player_dead_units_dict.items():
|
for unit_type, count in self.debriefing.player_dead_units_dict.items():
|
||||||
try:
|
try:
|
||||||
lostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
|
lostUnitsLayout.addWidget(
|
||||||
lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
QLabel(db.unit_type_name(unit_type)), row, 0)
|
||||||
|
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||||
row += 1
|
row += 1
|
||||||
except:
|
except AttributeError:
|
||||||
print("Issue adding " + str(unit_type) + " to debriefing information")
|
logging.exception(
|
||||||
|
f"Issue adding {unit_type} to debriefing information")
|
||||||
|
|
||||||
for building, count in self.debriefing.player_dead_buildings_dict.items():
|
for building, count in self.debriefing.player_dead_buildings_dict.items():
|
||||||
try:
|
try:
|
||||||
lostUnitsLayout.addWidget(QLabel(building, row, 0))
|
lostUnitsLayout.addWidget(QLabel(building, row, 0))
|
||||||
lostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||||
row += 1
|
row += 1
|
||||||
except:
|
except AttributeError:
|
||||||
print("Issue adding " + str(building) + " to debriefing information")
|
logging.exception(
|
||||||
|
f"Issue adding {building} to debriefing information")
|
||||||
|
|
||||||
self.layout.addWidget(lostUnits)
|
self.layout.addWidget(lostUnits)
|
||||||
|
|
||||||
@ -92,15 +100,16 @@ class QDebriefingWindow(QDialog):
|
|||||||
# enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1)
|
# enemylostUnitsLayout.addWidget(QLabel("{}".format(len(self.debriefing.destroyed_objects))), row, 1)
|
||||||
# row += 1
|
# row += 1
|
||||||
|
|
||||||
for unit_type, count in self.debriefing.enemy_dead_aircraft_dict.items():
|
enemy_air_losses = self.debriefing.air_losses.by_type(player=False)
|
||||||
if count == 0:
|
for unit_type, count in enemy_air_losses.items():
|
||||||
continue
|
|
||||||
try:
|
try:
|
||||||
enemylostUnitsLayout.addWidget(QLabel(db.unit_type_name(unit_type)), row, 0)
|
enemylostUnitsLayout.addWidget(
|
||||||
enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
QLabel(db.unit_type_name(unit_type)), row, 0)
|
||||||
|
enemylostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||||
row += 1
|
row += 1
|
||||||
except:
|
except AttributeError:
|
||||||
print("Issue adding " + str(unit_type) + " to debriefing information")
|
logging.exception(
|
||||||
|
f"Issue adding {unit_type} to debriefing information")
|
||||||
|
|
||||||
for unit_type, count in self.debriefing.enemy_dead_units_dict.items():
|
for unit_type, count in self.debriefing.enemy_dead_units_dict.items():
|
||||||
if count == 0:
|
if count == 0:
|
||||||
@ -114,8 +123,9 @@ class QDebriefingWindow(QDialog):
|
|||||||
enemylostUnitsLayout.addWidget(QLabel(building), row, 0)
|
enemylostUnitsLayout.addWidget(QLabel(building), row, 0)
|
||||||
enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
enemylostUnitsLayout.addWidget(QLabel("{}".format(count)), row, 1)
|
||||||
row += 1
|
row += 1
|
||||||
except:
|
except AttributeError:
|
||||||
print("Issue adding " + str(building) + " to debriefing information")
|
logging.exception(
|
||||||
|
f"Issue adding {building} to debriefing information")
|
||||||
|
|
||||||
self.layout.addWidget(enemylostUnits)
|
self.layout.addWidget(enemylostUnits)
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|||||||
from game.debriefing import Debriefing, wait_for_debriefing
|
from game.debriefing import Debriefing, wait_for_debriefing
|
||||||
from game.game import Event, Game, logging
|
from game.game import Event, Game, logging
|
||||||
from game.persistency import base_path
|
from game.persistency import base_path
|
||||||
|
from game.unitmap import UnitMap
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
|
|
||||||
|
|
||||||
@ -39,22 +40,27 @@ class DebriefingFileWrittenSignal(QObject):
|
|||||||
def get_instance():
|
def get_instance():
|
||||||
return DebriefingFileWrittenSignal.instance
|
return DebriefingFileWrittenSignal.instance
|
||||||
|
|
||||||
|
|
||||||
DebriefingFileWrittenSignal()
|
DebriefingFileWrittenSignal()
|
||||||
|
|
||||||
|
|
||||||
class QWaitingForMissionResultWindow(QDialog):
|
class QWaitingForMissionResultWindow(QDialog):
|
||||||
|
|
||||||
def __init__(self, gameEvent: Event, game: Game):
|
def __init__(self, gameEvent: Event, game: Game, unit_map: UnitMap) -> None:
|
||||||
super(QWaitingForMissionResultWindow, self).__init__()
|
super(QWaitingForMissionResultWindow, self).__init__()
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.gameEvent = gameEvent
|
self.gameEvent = gameEvent
|
||||||
self.game = game
|
self.game = game
|
||||||
|
self.unit_map = unit_map
|
||||||
self.setWindowTitle("Waiting for mission completion.")
|
self.setWindowTitle("Waiting for mission completion.")
|
||||||
self.setWindowIcon(QIcon("./resources/icon.png"))
|
self.setWindowIcon(QIcon("./resources/icon.png"))
|
||||||
self.setMinimumHeight(570)
|
self.setMinimumHeight(570)
|
||||||
|
|
||||||
self.initUi()
|
self.initUi()
|
||||||
DebriefingFileWrittenSignal.get_instance().debriefingReceived.connect(self.updateLayout)
|
DebriefingFileWrittenSignal.get_instance().debriefingReceived.connect(self.updateLayout)
|
||||||
self.wait_thread = wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game)
|
self.wait_thread = wait_for_debriefing(
|
||||||
|
lambda debriefing: self.on_debriefing_update(debriefing), self.game,
|
||||||
|
self.unit_map)
|
||||||
|
|
||||||
def initUi(self):
|
def initUi(self):
|
||||||
self.layout = QGridLayout()
|
self.layout = QGridLayout()
|
||||||
@ -119,17 +125,17 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
self.layout.addLayout(self.gridLayout, 1, 0)
|
self.layout.addLayout(self.gridLayout, 1, 0)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def updateLayout(self, debriefing):
|
def updateLayout(self, debriefing: Debriefing) -> None:
|
||||||
updateBox = QGroupBox("Mission status")
|
updateBox = QGroupBox("Mission status")
|
||||||
updateLayout = QGridLayout()
|
updateLayout = QGridLayout()
|
||||||
updateBox.setLayout(updateLayout)
|
updateBox.setLayout(updateLayout)
|
||||||
self.debriefing = debriefing
|
self.debriefing = debriefing
|
||||||
|
|
||||||
updateLayout.addWidget(QLabel("<b>Aircraft destroyed</b>"), 0, 0)
|
updateLayout.addWidget(QLabel("<b>Aircraft destroyed</b>"), 0, 0)
|
||||||
updateLayout.addWidget(QLabel(str(len(debriefing.killed_aircrafts))), 0, 1)
|
updateLayout.addWidget(QLabel(str(len(debriefing.air_losses.losses))), 0, 1)
|
||||||
|
|
||||||
updateLayout.addWidget(QLabel("<b>Ground units destroyed</b>"), 1, 0)
|
updateLayout.addWidget(QLabel("<b>Ground units destroyed</b>"), 1, 0)
|
||||||
updateLayout.addWidget(QLabel(str(len(debriefing.killed_ground_units))), 1, 1)
|
updateLayout.addWidget(QLabel(str(len(debriefing.dead_units))), 1, 1)
|
||||||
|
|
||||||
#updateLayout.addWidget(QLabel("<b>Weapons fired</b>"), 2, 0)
|
#updateLayout.addWidget(QLabel("<b>Weapons fired</b>"), 2, 0)
|
||||||
#updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1)
|
#updateLayout.addWidget(QLabel(str(len(debriefing.weapons_fired))), 2, 1)
|
||||||
@ -142,28 +148,27 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
try:
|
try:
|
||||||
self.gridLayout.itemAt(i).widget().setParent(None)
|
self.gridLayout.itemAt(i).widget().setParent(None)
|
||||||
except:
|
except:
|
||||||
pass
|
logging.exception("Failed to clear window")
|
||||||
|
|
||||||
# Set new window content
|
# Set new window content
|
||||||
self.gridLayout.addWidget(updateBox, 0, 0)
|
self.gridLayout.addWidget(updateBox, 0, 0)
|
||||||
|
|
||||||
if not debriefing.mission_ended:
|
if not debriefing.state_data.mission_ended:
|
||||||
self.gridLayout.addWidget(QLabel("<b>Mission is being played</b>"), 1, 0)
|
self.gridLayout.addWidget(QLabel("<b>Mission is being played</b>"), 1, 0)
|
||||||
self.gridLayout.addWidget(self.actions, 2, 0)
|
self.gridLayout.addWidget(self.actions, 2, 0)
|
||||||
else:
|
else:
|
||||||
self.gridLayout.addWidget(QLabel("<b>Mission is over</b>"), 1, 0)
|
self.gridLayout.addWidget(QLabel("<b>Mission is over</b>"), 1, 0)
|
||||||
self.gridLayout.addWidget(self.actions2, 2, 0)
|
self.gridLayout.addWidget(self.actions2, 2, 0)
|
||||||
|
|
||||||
|
def on_debriefing_update(self, debriefing: Debriefing) -> None:
|
||||||
def on_debriefing_udpate(self, debriefing):
|
|
||||||
try:
|
try:
|
||||||
logging.info("On Debriefing update")
|
logging.info("On Debriefing update")
|
||||||
print(debriefing)
|
logging.debug(debriefing)
|
||||||
DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing)
|
DebriefingFileWrittenSignal.get_instance().sendDebriefing(debriefing)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logging.error("Got an error while sending debriefing")
|
logging.exception("Got an error while sending debriefing")
|
||||||
logging.error(e)
|
self.wait_thread = wait_for_debriefing(
|
||||||
self.wait_thread = wait_for_debriefing(lambda debriefing: self.on_debriefing_udpate(debriefing), self.game)
|
lambda d: self.on_debriefing_update(d), self.game, self.unit_map)
|
||||||
|
|
||||||
def process_debriefing(self):
|
def process_debriefing(self):
|
||||||
self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing)
|
self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing)
|
||||||
@ -187,8 +192,8 @@ class QWaitingForMissionResultWindow(QDialog):
|
|||||||
with open(file[0], "r") as json_file:
|
with open(file[0], "r") as json_file:
|
||||||
json_data = json.load(json_file)
|
json_data = json.load(json_file)
|
||||||
json_data["mission_ended"] = True
|
json_data["mission_ended"] = True
|
||||||
debriefing = Debriefing(json_data, self.game)
|
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
||||||
self.on_debriefing_udpate(debriefing)
|
self.on_debriefing_update(debriefing)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
msg = QMessageBox()
|
msg = QMessageBox()
|
||||||
|
|||||||
@ -6,7 +6,6 @@ logger:info("Check that json.lua is loaded : json = "..tostring(json))
|
|||||||
|
|
||||||
killed_aircrafts = {}
|
killed_aircrafts = {}
|
||||||
killed_ground_units = {}
|
killed_ground_units = {}
|
||||||
weapons_fired = {}
|
|
||||||
base_capture_events = {}
|
base_capture_events = {}
|
||||||
destroyed_objects_positions = {}
|
destroyed_objects_positions = {}
|
||||||
mission_ended = false
|
mission_ended = false
|
||||||
@ -33,7 +32,6 @@ function write_state()
|
|||||||
local game_state = {
|
local game_state = {
|
||||||
["killed_aircrafts"] = killed_aircrafts,
|
["killed_aircrafts"] = killed_aircrafts,
|
||||||
["killed_ground_units"] = killed_ground_units,
|
["killed_ground_units"] = killed_ground_units,
|
||||||
["weapons_fired"] = weapons_fired,
|
|
||||||
["base_capture_events"] = base_capture_events,
|
["base_capture_events"] = base_capture_events,
|
||||||
["mission_ended"] = mission_ended,
|
["mission_ended"] = mission_ended,
|
||||||
["destroyed_objects_positions"] = destroyed_objects_positions,
|
["destroyed_objects_positions"] = destroyed_objects_positions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user