Rework killed map_objects recognition

- removed the map_object_id from the TGO
- add a new TriggerRule with the MapObjectIsDead Condition which adds the map object to the killed_map_objects array in the state.json
- Use the trigger_zone_name as the unique identifier used for the unit_map to recognize the kill
This commit is contained in:
RndName 2021-12-31 17:10:23 +01:00
parent ffd8152b36
commit e070d5bf0d
No known key found for this signature in database
GPG Key ID: 5EF516FD9537F7C0
6 changed files with 40 additions and 18 deletions

View File

@ -12,6 +12,7 @@ Saves from 5.0.0 are compatible with 5.1.0
## Fixes
* **[Campaign]** Fixed some minor issues in campaigns which generated error messages in the log.
* **[Campaign]** Changed the way how map object / scenery kills where tracked. This fixes issues with kill recognition after map updates from ED which change the object ids and therefore prevent correct kill recognition.
* **[Mission Generation]** Fixed incorrect radio specification for the AN/ARC-222.
* **[Mission Generation]** Fixed mission scripting error when using a dedicated server.
* **[Mission Generation]** Fixed an issue where empty convoys lead to an index error when a point capture made a pending transfer of units not completable anymore.

View File

@ -104,6 +104,9 @@ class StateData:
#: Names of vehicle (and ship) units that were killed during the mission.
killed_ground_units: List[str]
#: Names of map objects that were killed during the mission.
killed_map_objects: list[str]
#: List of descriptions of destroyed statics. Format of each element is a mapping of
#: the coordinate type ("x", "y", "z", "type", "orientation") to the value.
destroyed_statics: List[dict[str, Union[float, str]]]
@ -122,6 +125,7 @@ class StateData:
# Also normalize dead map objects (which are ints) to strings. The unit map
# only stores strings.
killed_ground_units=list({str(u) for u in data["killed_ground_units"]}),
killed_map_objects=data["killed_map_objects"],
destroyed_statics=data["destroyed_objects_positions"],
base_capture_events=data["base_capture_events"],
)
@ -323,6 +327,16 @@ class Debriefing:
losses.enemy_airlifts.append(airlift_unit)
continue
# Find killed map objects and mark them as loss
for map_object in self.state_data.killed_map_objects:
building = self.unit_map.building_or_fortification(map_object)
if building is not None:
if building.ground_object.control_point.captured:
losses.player_buildings.append(building)
else:
losses.enemy_buildings.append(building)
continue
return losses
def base_capture_events(self) -> List[BaseCaptureEvent]:

View File

@ -316,16 +316,6 @@ class SceneryGroundObject(BuildingGroundObject):
is_fob_structure=False,
)
self.zone = zone
try:
# In the default TriggerZone using "assign as..." in the DCS Mission Editor,
# property three has the scenery's object ID as its value.
self.map_object_id = self.zone.properties[3]["value"]
except (IndexError, KeyError):
logging.exception(
"Invalid TriggerZone for Scenery definition. The third property must "
"be the map object ID."
)
raise
class FactoryGroundObject(BuildingGroundObject):

View File

@ -217,7 +217,7 @@ class UnitMap:
self.buildings[name] = Building(ground_object)
def add_scenery(self, ground_object: SceneryGroundObject) -> None:
name = str(ground_object.map_object_id)
name = str(ground_object.zone.name)
if name in self.buildings:
raise RuntimeError(
f"Duplicate TGO unit: {name}. TriggerZone name: "

View File

@ -24,7 +24,8 @@ from typing import (
)
from dcs import Mission, Point, unitgroup
from dcs.action import SceneryDestructionZone
from dcs.action import SceneryDestructionZone, DoScript
from dcs.condition import MapObjectIsDead
from dcs.country import Country
from dcs.point import StaticPoint
from dcs.statics import Fortification, fortification_map, warehouse_map
@ -35,7 +36,8 @@ from dcs.task import (
OptAlarmState,
FireAtPoint,
)
from dcs.triggers import TriggerStart, TriggerZone
from dcs.translation import String
from dcs.triggers import TriggerStart, TriggerZone, Event, TriggerOnce
from dcs.unit import Ship, Unit, Vehicle, InvisibleFARP
from dcs.unitgroup import ShipGroup, StaticGroup, VehicleGroup
from dcs.unittype import StaticType, ShipType, VehicleType
@ -297,7 +299,9 @@ class SceneryGenerator(BuildingSiteGenerator):
# this trigger rule is applied. Otherwise you can kill a
# structure twice.
if self.ground_object.is_dead:
self.generate_dead_trigger_rule(trigger_zone)
self.generate_destruction_trigger_rule(trigger_zone)
else:
self.generate_on_dead_trigger_rule(trigger_zone)
# Tell Liberation to manage this groundobjectsgen as part of the campaign.
self.register_scenery()
@ -325,7 +329,7 @@ class SceneryGenerator(BuildingSiteGenerator):
zone.properties,
)
def generate_dead_trigger_rule(self, trigger_zone: TriggerZone) -> None:
def generate_destruction_trigger_rule(self, trigger_zone: TriggerZone) -> None:
# Add destruction zone trigger
t = TriggerStart(comment="Destruction")
t.actions.append(
@ -333,6 +337,17 @@ class SceneryGenerator(BuildingSiteGenerator):
)
self.m.triggerrules.triggers.append(t)
def generate_on_dead_trigger_rule(self, trigger_zone: TriggerZone) -> None:
# Add a TriggerRule with the MapObjectIsDead condition to recognize killed
# map objects and add them to the state.json with a DoScript
t = TriggerOnce(Event.NoEvent, f"MapObjectIsDead Trigger {trigger_zone.id}")
t.add_condition(MapObjectIsDead(trigger_zone.id))
script_string = String(
f'killed_map_objects[#killed_map_objects + 1] = "{trigger_zone.name}"'
)
t.actions.append(DoScript(script_string))
self.m.triggerrules.triggers.append(t)
def register_scenery(self) -> None:
scenery = self.ground_object
assert isinstance(scenery, SceneryGroundObject)

View File

@ -4,10 +4,11 @@ local WRITESTATE_SCHEDULE_IN_SECONDS = 60
logger = mist.Logger:new("DCSLiberation", "info")
logger:info("Check that json.lua is loaded : json = "..tostring(json))
killed_aircrafts = {}
killed_ground_units = {}
killed_aircrafts = {} -- killed aircraft will be added via S_EVENT_CRASH event
killed_ground_units = {} -- killed units will be added via S_EVENT_DEAD event
base_capture_events = {}
destroyed_objects_positions = {}
destroyed_objects_positions = {} -- will be added via S_EVENT_DEAD event
killed_map_objects = {} -- killed map objects will be added via TriggerRules
mission_ended = false
local function ends_with(str, ending)
@ -35,6 +36,7 @@ function write_state()
["base_capture_events"] = base_capture_events,
["mission_ended"] = mission_ended,
["destroyed_objects_positions"] = destroyed_objects_positions,
["killed_map_objects"] = killed_map_objects,
}
if not json then
local message = string.format("Unable to save DCS Liberation state to %s, JSON library is not loaded !", _debriefing_file_location)