Restored Retribution scripts and triggers to Pretense campaigns. Pretense progress can now be translated back to Retribution. Moved the trigger clearing from pretenseluagenerator.py to pretensemissiongenerator.py

keepActive is now only enabled for airbases and carriers/LHAs, for performance reasons.
This commit is contained in:
MetalStormGhost 2023-10-22 22:01:00 +03:00
parent 87975b9aad
commit 595c468ab2
3 changed files with 273 additions and 13 deletions

View File

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import os
import random import random
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
@ -14,10 +15,12 @@ from dcs.triggers import TriggerStart
from dcs.vehicles import AirDefence from dcs.vehicles import AirDefence
from game.ato import FlightType from game.ato import FlightType
from game.dcs.aircrafttype import AircraftType
from game.missiongenerator.luagenerator import LuaGenerator from game.missiongenerator.luagenerator import LuaGenerator
from game.missiongenerator.missiondata import MissionData from game.missiongenerator.missiondata import MissionData
from game.plugins import LuaPluginManager from game.plugins import LuaPluginManager
from game.theater import Airfield, OffMapSpawn from game.theater import Airfield, OffMapSpawn, TheaterGroundObject
from game.theater.iadsnetwork.iadsrole import IadsRole
from game.utils import escape_string_for_lua from game.utils import escape_string_for_lua
if TYPE_CHECKING: if TYPE_CHECKING:
@ -63,12 +66,180 @@ class PretenseLuaGenerator(LuaGenerator):
ewrj_triggers = [ ewrj_triggers = [
x for x in self.mission.triggerrules.triggers if isinstance(x, TriggerStart) x for x in self.mission.triggerrules.triggers if isinstance(x, TriggerStart)
] ]
self.generate_pretense_plugin_data()
self.generate_plugin_data() self.generate_plugin_data()
self.inject_plugins() self.inject_plugins()
for t in ewrj_triggers: for t in ewrj_triggers:
self.mission.triggerrules.triggers.remove(t) self.mission.triggerrules.triggers.remove(t)
self.mission.triggerrules.triggers.append(t) self.mission.triggerrules.triggers.append(t)
def generate_plugin_data(self) -> None:
lua_data = LuaData("dcsRetribution")
install_path = lua_data.add_item("installPath")
install_path.set_value(os.path.abspath("."))
lua_data.add_item("Airbases")
carriers_object = lua_data.add_item("Carriers")
for carrier in self.mission_data.carriers:
carrier_item = carriers_object.add_item()
carrier_item.add_key_value("dcsGroupName", carrier.group_name)
carrier_item.add_key_value("unit_name", carrier.unit_name)
carrier_item.add_key_value("callsign", carrier.callsign)
carrier_item.add_key_value("radio", str(carrier.freq.mhz))
carrier_item.add_key_value(
"tacan", str(carrier.tacan.number) + carrier.tacan.band.name
)
tankers_object = lua_data.add_item("Tankers")
for tanker in self.mission_data.tankers:
tanker_item = tankers_object.add_item()
tanker_item.add_key_value("dcsGroupName", tanker.group_name)
tanker_item.add_key_value("callsign", tanker.callsign)
tanker_item.add_key_value("variant", tanker.variant)
tanker_item.add_key_value("radio", str(tanker.freq.mhz))
if tanker.tacan is not None:
tanker_item.add_key_value(
"tacan", str(tanker.tacan.number) + tanker.tacan.band.name
)
awacs_object = lua_data.add_item("AWACs")
for awacs in self.mission_data.awacs:
awacs_item = awacs_object.add_item()
awacs_item.add_key_value("dcsGroupName", awacs.group_name)
awacs_item.add_key_value("callsign", awacs.callsign)
awacs_item.add_key_value("radio", str(awacs.freq.mhz))
jtacs_object = lua_data.add_item("JTACs")
for jtac in self.mission_data.jtacs:
jtac_item = jtacs_object.add_item()
jtac_item.add_key_value("dcsGroupName", jtac.group_name)
jtac_item.add_key_value("callsign", jtac.callsign)
jtac_item.add_key_value("zone", jtac.region)
jtac_item.add_key_value("dcsUnit", jtac.unit_name)
jtac_item.add_key_value("laserCode", jtac.code)
jtac_item.add_key_value("radio", str(jtac.freq.mhz))
jtac_item.add_key_value("modulation", jtac.freq.modulation.name)
logistics_object = lua_data.add_item("Logistics")
logistics_flights = logistics_object.add_item("flights")
crates_object = logistics_object.add_item("crates")
spawnable_crates: dict[str, str] = {}
transports: list[AircraftType] = []
for logistic_info in self.mission_data.logistics:
if logistic_info.transport not in transports:
transports.append(logistic_info.transport)
coalition_color = "blue" if logistic_info.blue else "red"
logistics_item = logistics_flights.add_item()
logistics_item.add_data_array("pilot_names", logistic_info.pilot_names)
logistics_item.add_key_value("pickup_zone", logistic_info.pickup_zone)
logistics_item.add_key_value("drop_off_zone", logistic_info.drop_off_zone)
logistics_item.add_key_value("target_zone", logistic_info.target_zone)
logistics_item.add_key_value("side", str(2 if logistic_info.blue else 1))
logistics_item.add_key_value("logistic_unit", logistic_info.logistic_unit)
logistics_item.add_key_value(
"aircraft_type", logistic_info.transport.dcs_id
)
logistics_item.add_key_value(
"preload", "true" if logistic_info.preload else "false"
)
for cargo in logistic_info.cargo:
if cargo.unit_type not in spawnable_crates:
spawnable_crates[cargo.unit_type] = str(200 + len(spawnable_crates))
crate_weight = spawnable_crates[cargo.unit_type]
for i in range(cargo.amount):
cargo_item = crates_object.add_item()
cargo_item.add_key_value("weight", crate_weight)
cargo_item.add_key_value("coalition", coalition_color)
cargo_item.add_key_value("zone", cargo.spawn_zone)
transport_object = logistics_object.add_item("transports")
for transport in transports:
transport_item = transport_object.add_item()
transport_item.add_key_value("aircraft_type", transport.dcs_id)
transport_item.add_key_value("cabin_size", str(transport.cabin_size))
transport_item.add_key_value(
"troops", "true" if transport.cabin_size > 0 else "false"
)
transport_item.add_key_value(
"crates", "true" if transport.can_carry_crates else "false"
)
spawnable_crates_object = logistics_object.add_item("spawnable_crates")
for unit, weight in spawnable_crates.items():
crate_item = spawnable_crates_object.add_item()
crate_item.add_key_value("unit", unit)
crate_item.add_key_value("weight", weight)
target_points = lua_data.add_item("TargetPoints")
for flight in self.mission_data.flights:
if flight.friendly and flight.flight_type in [
FlightType.ANTISHIP,
FlightType.DEAD,
FlightType.SEAD,
FlightType.STRIKE,
]:
flight_type = str(flight.flight_type)
flight_target = flight.package.target
if flight_target:
flight_target_name = None
flight_target_type = None
if isinstance(flight_target, TheaterGroundObject):
flight_target_name = flight_target.obj_name
flight_target_type = (
flight_type + f" TGT ({flight_target.category})"
)
elif hasattr(flight_target, "name"):
flight_target_name = flight_target.name
flight_target_type = flight_type + " TGT (Airbase)"
target_item = target_points.add_item()
if flight_target_name:
target_item.add_key_value("name", flight_target_name)
if flight_target_type:
target_item.add_key_value("type", flight_target_type)
target_item.add_key_value(
"positionX", str(flight_target.position.x)
)
target_item.add_key_value(
"positionY", str(flight_target.position.y)
)
for cp in self.game.theater.controlpoints:
coalition_object = (
lua_data.get_or_create_item("BlueAA")
if cp.captured
else lua_data.get_or_create_item("RedAA")
)
for ground_object in cp.ground_objects:
for g in ground_object.groups:
threat_range = g.max_threat_range()
if not threat_range:
continue
aa_item = coalition_object.add_item()
aa_item.add_key_value("name", ground_object.name)
aa_item.add_key_value("range", str(threat_range.meters))
aa_item.add_key_value("positionX", str(ground_object.position.x))
aa_item.add_key_value("positionY", str(ground_object.position.y))
# Generate IADS Lua Item
iads_object = lua_data.add_item("IADS")
for node in self.game.theater.iads_network.skynet_nodes(self.game):
coalition = iads_object.get_or_create_item("BLUE" if node.player else "RED")
iads_type = coalition.get_or_create_item(node.iads_role.value)
iads_element = iads_type.add_item()
iads_element.add_key_value("dcsGroupName", node.dcs_name)
if node.iads_role in [IadsRole.SAM, IadsRole.SAM_AS_EWR]:
# add additional SkynetProperties to SAM Sites
for property, value in node.properties.items():
iads_element.add_key_value(property, value)
for role, connections in node.connections.items():
iads_element.add_data_array(role, connections)
trigger = TriggerStart(comment="Set DCS Retribution data")
trigger.add_action(DoScript(String(lua_data.create_operations_lua())))
self.mission.triggerrules.triggers.append(trigger)
@staticmethod @staticmethod
def generate_sam_from_preset( def generate_sam_from_preset(
preset: str, cp_side_str: str, cp_name_trimmed: str preset: str, cp_side_str: str, cp_name_trimmed: str
@ -650,9 +821,7 @@ class PretenseLuaGenerator(LuaGenerator):
return lua_string_connman return lua_string_connman
def generate_plugin_data(self) -> None: def generate_pretense_plugin_data(self) -> None:
self.mission.triggerrules.triggers.clear()
self.inject_plugin_script("base", "mist_4_5_107.lua", "mist_4_5_107") self.inject_plugin_script("base", "mist_4_5_107.lua", "mist_4_5_107")
self.inject_plugin_script( self.inject_plugin_script(
"pretense", "pretense_compiled.lua", "pretense_compiled" "pretense", "pretense_compiled.lua", "pretense_compiled"
@ -660,6 +829,23 @@ class PretenseLuaGenerator(LuaGenerator):
trigger = TriggerStart(comment="Pretense init") trigger = TriggerStart(comment="Pretense init")
lua_string_config = ""
lua_string_config += (
f"Config.maxDistFromFront = "
+ str(self.game.settings.pretense_maxdistfromfront_distance * 1000)
+ "\n"
)
lua_string_config += (
f"Config.closeOverride = "
+ str(self.game.settings.pretense_closeoverride_distance * 1000)
+ "\n"
)
if self.game.settings.pretense_do_not_generate_sead_missions:
lua_string_config += "Config.disablePlayerSead = true\n"
else:
lua_string_config += "Config.disablePlayerSead = false\n"
init_header_file = open("./resources/plugins/pretense/init_header.lua", "r") init_header_file = open("./resources/plugins/pretense/init_header.lua", "r")
init_header = init_header_file.read() init_header = init_header_file.read()
@ -687,10 +873,10 @@ class PretenseLuaGenerator(LuaGenerator):
+ str(cp_side) + str(cp_side)
+ " }\n" + " }\n"
) )
lua_string_zones += f"zones.{cp_name_trimmed}.keepActive = true\n"
max_resource = 20000 max_resource = 20000
is_helo_spawn = "false" is_helo_spawn = "false"
is_plane_spawn = "false" is_plane_spawn = "false"
is_keep_active = "false"
if cp.has_helipads: if cp.has_helipads:
is_helo_spawn = "true" is_helo_spawn = "true"
max_resource = 30000 max_resource = 30000
@ -701,9 +887,12 @@ class PretenseLuaGenerator(LuaGenerator):
is_helo_spawn = "true" is_helo_spawn = "true"
is_plane_spawn = "true" is_plane_spawn = "true"
max_resource = 40000 max_resource = 40000
if cp.is_lha:
is_keep_active = "true"
if isinstance(cp, Airfield) or cp.is_carrier: if isinstance(cp, Airfield) or cp.is_carrier:
is_helo_spawn = "true" is_helo_spawn = "true"
is_plane_spawn = "true" is_plane_spawn = "true"
is_keep_active = "true"
max_resource = 50000 max_resource = 50000
lua_string_zones += ( lua_string_zones += (
f"zones.{cp_name_trimmed}.maxResource = {max_resource}\n" f"zones.{cp_name_trimmed}.maxResource = {max_resource}\n"
@ -714,6 +903,9 @@ class PretenseLuaGenerator(LuaGenerator):
lua_string_zones += ( lua_string_zones += (
f"zones.{cp_name_trimmed}.isPlaneSpawn = " + is_plane_spawn + "\n" f"zones.{cp_name_trimmed}.isPlaneSpawn = " + is_plane_spawn + "\n"
) )
lua_string_zones += (
f"zones.{cp_name_trimmed}.keepActive = " + is_keep_active + "\n"
)
if cp.is_fleet: if cp.is_fleet:
lua_string_zones += self.generate_pretense_zone_sea(cp.name) lua_string_zones += self.generate_pretense_zone_sea(cp.name)
else: else:
@ -805,7 +997,8 @@ class PretenseLuaGenerator(LuaGenerator):
init_footer = init_footer_file.read() init_footer = init_footer_file.read()
lua_string = ( lua_string = (
init_header lua_string_config
+ init_header
+ lua_string_zones + lua_string_zones
+ lua_string_connman + lua_string_connman
+ init_body_1 + init_body_1
@ -854,7 +1047,7 @@ class PretenseLuaGenerator(LuaGenerator):
def inject_plugins(self) -> None: def inject_plugins(self) -> None:
for plugin in LuaPluginManager.plugins(): for plugin in LuaPluginManager.plugins():
if plugin.enabled and plugin.identifier not in ("base"): if plugin.enabled:
plugin.inject_scripts(self) plugin.inject_scripts(self)
plugin.inject_configuration(self) plugin.inject_configuration(self)

View File

@ -101,6 +101,7 @@ class PretenseMissionGenerator(MissionGenerator):
self.generate_ground_conflicts() self.generate_ground_conflicts()
self.generate_air_units(tgo_generator) self.generate_air_units(tgo_generator)
self.mission.triggerrules.triggers.clear()
PretenseTriggerGenerator(self.mission, self.game).generate() PretenseTriggerGenerator(self.mission, self.game).generate()
ForcedOptionsGenerator(self.mission, self.game).generate() ForcedOptionsGenerator(self.mission, self.game).generate()
VisualsGenerator(self.mission, self.game).generate() VisualsGenerator(self.mission, self.game).generate()

View File

@ -152,9 +152,72 @@ class PretenseTriggerGenerator:
v += 1 v += 1
self.mission.triggerrules.triggers.append(mark_trigger) self.mission.triggerrules.triggers.append(mark_trigger)
def _generate_pretense_zone_triggers( def _generate_capture_triggers(
self, player_coalition: str, enemy_coalition: str self, player_coalition: str, enemy_coalition: str
) -> None: ) -> None:
"""Creates a pair of triggers for each control point of `cls.capture_zone_types`.
One for the initial capture of a control point, and one if it is recaptured.
Directly appends to the global `base_capture_events` var declared by `dcs_libaration.lua`
"""
for cp in self.game.theater.controlpoints:
if isinstance(cp, self.capture_zone_types) and not cp.is_carrier:
if cp.captured:
attacking_coalition = enemy_coalition
attack_coalition_int = 1 # 1 is the Event int for Red
defending_coalition = player_coalition
defend_coalition_int = 2 # 2 is the Event int for Blue
else:
attacking_coalition = player_coalition
attack_coalition_int = 2
defending_coalition = enemy_coalition
defend_coalition_int = 1
trigger_zone = self.mission.triggers.add_triggerzone(
cp.position,
radius=TRIGGER_RADIUS_CAPTURE,
hidden=False,
name="CAPTURE",
)
flag = self.get_capture_zone_flag()
capture_trigger = TriggerCondition(Event.NoEvent, "Capture Trigger")
capture_trigger.add_condition(
AllOfCoalitionOutsideZone(
defending_coalition, trigger_zone.id, unit_type="GROUND"
)
)
capture_trigger.add_condition(
PartOfCoalitionInZone(
attacking_coalition, trigger_zone.id, unit_type="GROUND"
)
)
capture_trigger.add_condition(FlagIsFalse(flag=flag))
script_string = String(
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{attack_coalition_int}||{cp.full_name}"'
)
capture_trigger.add_action(DoScript(script_string))
capture_trigger.add_action(SetFlag(flag=flag))
self.mission.triggerrules.triggers.append(capture_trigger)
recapture_trigger = TriggerCondition(Event.NoEvent, "Capture Trigger")
recapture_trigger.add_condition(
AllOfCoalitionOutsideZone(
attacking_coalition, trigger_zone.id, unit_type="GROUND"
)
)
recapture_trigger.add_condition(
PartOfCoalitionInZone(
defending_coalition, trigger_zone.id, unit_type="GROUND"
)
)
recapture_trigger.add_condition(FlagIsTrue(flag=flag))
script_string = String(
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{defend_coalition_int}||{cp.full_name}"'
)
recapture_trigger.add_action(DoScript(script_string))
recapture_trigger.add_action(ClearFlag(flag=flag))
self.mission.triggerrules.triggers.append(recapture_trigger)
def _generate_pretense_zone_triggers(self) -> None:
"""Creates a pair of triggers for each control point of `cls.capture_zone_types`. """Creates a pair of triggers for each control point of `cls.capture_zone_types`.
One for the initial capture of a control point, and one if it is recaptured. One for the initial capture of a control point, and one if it is recaptured.
Directly appends to the global `base_capture_events` var declared by `dcs_libaration.lua` Directly appends to the global `base_capture_events` var declared by `dcs_libaration.lua`
@ -166,7 +229,7 @@ class PretenseTriggerGenerator:
trigger_radius = TRIGGER_RADIUS_CAPTURE trigger_radius = TRIGGER_RADIUS_CAPTURE
if not isinstance(cp, OffMapSpawn): if not isinstance(cp, OffMapSpawn):
zone_color = {1: 0.0, 2: 0.0, 3: 0.0, 4: 0.15} zone_color = {1: 0.0, 2: 0.0, 3: 0.0, 4: 0.15}
trigger_zone = self.mission.triggers.add_triggerzone( self.mission.triggers.add_triggerzone(
cp.position, cp.position,
radius=trigger_radius, radius=trigger_radius,
hidden=False, hidden=False,
@ -180,7 +243,7 @@ class PretenseTriggerGenerator:
continue continue
tgo_num += 1 tgo_num += 1
zone_color = {1: 1.0, 2: 1.0, 3: 1.0, 4: 0.15} zone_color = {1: 1.0, 2: 1.0, 3: 1.0, 4: 0.15}
trigger_zone = self.mission.triggers.add_triggerzone( self.mission.triggers.add_triggerzone(
tgo.position, tgo.position,
radius=TRIGGER_RADIUS_PRETENSE_TGO, radius=TRIGGER_RADIUS_PRETENSE_TGO,
hidden=False, hidden=False,
@ -189,7 +252,7 @@ class PretenseTriggerGenerator:
) )
for helipad in cp.helipads + cp.helipads_invisible + cp.helipads_quad: for helipad in cp.helipads + cp.helipads_invisible + cp.helipads_quad:
zone_color = {1: 1.0, 2: 1.0, 3: 1.0, 4: 0.15} zone_color = {1: 1.0, 2: 1.0, 3: 1.0, 4: 0.15}
trigger_zone = self.mission.triggers.add_triggerzone( self.mission.triggers.add_triggerzone(
position=helipad, position=helipad,
radius=TRIGGER_RADIUS_PRETENSE_HELI, radius=TRIGGER_RADIUS_PRETENSE_HELI,
hidden=False, hidden=False,
@ -206,7 +269,7 @@ class PretenseTriggerGenerator:
supply_position = origin_position.point_from_heading( supply_position = origin_position.point_from_heading(
convoy_heading, 300 convoy_heading, 300
) )
trigger_zone = self.mission.triggers.add_triggerzone( self.mission.triggers.add_triggerzone(
supply_position, supply_position,
radius=TRIGGER_RADIUS_PRETENSE_TGO, radius=TRIGGER_RADIUS_PRETENSE_TGO,
hidden=False, hidden=False,
@ -219,6 +282,8 @@ class PretenseTriggerGenerator:
] ]
for airfield in airfields: for airfield in airfields:
cp_airport = self.mission.terrain.airport_by_id(airfield.airport.id) cp_airport = self.mission.terrain.airport_by_id(airfield.airport.id)
if cp_airport is None:
continue
cp_name_trimmed = "".join( cp_name_trimmed = "".join(
[i for i in cp_airport.name.lower() if i.isalnum()] [i for i in cp_airport.name.lower() if i.isalnum()]
) )
@ -263,7 +328,8 @@ class PretenseTriggerGenerator:
self._set_skill(player_coalition, enemy_coalition) self._set_skill(player_coalition, enemy_coalition)
self._set_allegiances(player_coalition, enemy_coalition) self._set_allegiances(player_coalition, enemy_coalition)
self._generate_pretense_zone_triggers(player_coalition, enemy_coalition) self._generate_pretense_zone_triggers()
self._generate_capture_triggers(player_coalition, enemy_coalition)
@classmethod @classmethod
def get_capture_zone_flag(cls) -> int: def get_capture_zone_flag(cls) -> int: