mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Improvement for factions and templates which will allow decoupling of the templates from the actual units - Implement UnitGroup class which matches unit_types and possible templates as the needed abstraction layer for decoupling. - Refactor UnitType, Add ShipUnitType and all ships we currently use - Remove serialized template.json and migrated to multiple yaml templates (one for each template) and multiple .miz - Reorganized a lot of templates and started with generalization of many types (AAA, Flak, SHORAD, Navy) - Fixed a lot of bugs from the previous reworks (group name generation, strike targets...) - Reorganized the faction file completly. removed redundant lists, added presets for complex groups / families of units like sams - Reworked the building template handling. Some templates are unused like "village" - Reworked how groups from templates can be merged again for the dcs group creation (e.g. the skynet plugin requires them to be in the same group) - Allow to define alternative tasks
310 lines
11 KiB
Python
310 lines
11 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING
|
|
|
|
from dcs import Mission
|
|
from dcs.action import DoScript, DoScriptFile
|
|
from dcs.translation import String
|
|
from dcs.triggers import TriggerStart
|
|
|
|
from game.ato import FlightType
|
|
from game.plugins import LuaPluginManager
|
|
from game.theater import TheaterGroundObject
|
|
|
|
from .aircraft.flightdata import FlightData
|
|
from .airsupport import AirSupport
|
|
|
|
if TYPE_CHECKING:
|
|
from game import Game
|
|
|
|
|
|
class LuaGenerator:
|
|
def __init__(
|
|
self,
|
|
game: Game,
|
|
mission: Mission,
|
|
air_support: AirSupport,
|
|
flights: list[FlightData],
|
|
) -> None:
|
|
self.game = game
|
|
self.mission = mission
|
|
self.air_support = air_support
|
|
self.flights = flights
|
|
self.plugin_scripts: list[str] = []
|
|
|
|
def generate(self) -> None:
|
|
self.generate_plugin_data()
|
|
self.inject_plugins()
|
|
|
|
def generate_plugin_data(self) -> None:
|
|
# TODO: Refactor this
|
|
lua_data = {
|
|
"AircraftCarriers": {},
|
|
"Tankers": {},
|
|
"AWACs": {},
|
|
"JTACs": {},
|
|
"TargetPoints": {},
|
|
"RedAA": {},
|
|
"BlueAA": {},
|
|
} # type: ignore
|
|
|
|
for i, tanker in enumerate(self.air_support.tankers):
|
|
lua_data["Tankers"][i] = {
|
|
"dcsGroupName": tanker.group_name,
|
|
"callsign": tanker.callsign,
|
|
"variant": tanker.variant,
|
|
"radio": tanker.freq.mhz,
|
|
"tacan": str(tanker.tacan.number) + tanker.tacan.band.name,
|
|
}
|
|
|
|
for i, awacs in enumerate(self.air_support.awacs):
|
|
lua_data["AWACs"][i] = {
|
|
"dcsGroupName": awacs.group_name,
|
|
"callsign": awacs.callsign,
|
|
"radio": awacs.freq.mhz,
|
|
}
|
|
|
|
for i, jtac in enumerate(self.air_support.jtacs):
|
|
lua_data["JTACs"][i] = {
|
|
"dcsGroupName": jtac.group_name,
|
|
"callsign": jtac.callsign,
|
|
"zone": jtac.region,
|
|
"dcsUnit": jtac.unit_name,
|
|
"laserCode": jtac.code,
|
|
"radio": jtac.freq.mhz,
|
|
}
|
|
flight_count = 0
|
|
for flight in self.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)"
|
|
lua_data["TargetPoints"][flight_count] = {
|
|
"name": flight_target_name,
|
|
"type": flight_target_type,
|
|
"position": {
|
|
"x": flight_target.position.x,
|
|
"y": flight_target.position.y,
|
|
},
|
|
}
|
|
flight_count += 1
|
|
|
|
for cp in self.game.theater.controlpoints:
|
|
for ground_object in cp.ground_objects:
|
|
if ground_object.might_have_aa and not ground_object.is_dead:
|
|
for g in ground_object.groups:
|
|
threat_range = ground_object.threat_range(g)
|
|
|
|
if not threat_range:
|
|
continue
|
|
|
|
faction = "BlueAA" if cp.captured else "RedAA"
|
|
|
|
lua_data[faction][g.group_name] = {
|
|
"name": ground_object.name,
|
|
"range": threat_range.meters,
|
|
"position": {
|
|
"x": ground_object.position.x,
|
|
"y": ground_object.position.y,
|
|
},
|
|
}
|
|
|
|
# set a LUA table with data from Liberation that we want to set
|
|
# at the moment it contains Liberation's install path, and an overridable
|
|
# definition for the JTACAutoLase function later, we'll add data about the units
|
|
# and points having been generated, in order to facilitate the configuration of
|
|
# the plugin lua scripts
|
|
state_location = "[[" + os.path.abspath(".") + "]]"
|
|
lua = (
|
|
"""
|
|
-- setting configuration table
|
|
env.info("DCSLiberation|: setting configuration table")
|
|
|
|
-- all data in this table is overridable.
|
|
dcsLiberation = {}
|
|
|
|
-- the base location for state.json; if non-existent, it'll be replaced with
|
|
-- LIBERATION_EXPORT_DIR, TEMP, or DCS working directory
|
|
dcsLiberation.installPath="""
|
|
+ state_location
|
|
+ """
|
|
|
|
"""
|
|
)
|
|
# Process the tankers
|
|
lua += """
|
|
|
|
-- list the tankers generated by Liberation
|
|
dcsLiberation.Tankers = {
|
|
"""
|
|
for key in lua_data["Tankers"]:
|
|
data = lua_data["Tankers"][key]
|
|
dcs_group_name = data["dcsGroupName"]
|
|
callsign = data["callsign"]
|
|
variant = data["variant"]
|
|
tacan = data["tacan"]
|
|
radio = data["radio"]
|
|
lua += (
|
|
f" {{dcsGroupName='{dcs_group_name}', callsign='{callsign}', "
|
|
f"variant='{variant}', tacan='{tacan}', radio='{radio}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
# Process the AWACSes
|
|
lua += """
|
|
|
|
-- list the AWACs generated by Liberation
|
|
dcsLiberation.AWACs = {
|
|
"""
|
|
for key in lua_data["AWACs"]:
|
|
data = lua_data["AWACs"][key]
|
|
dcs_group_name = data["dcsGroupName"]
|
|
callsign = data["callsign"]
|
|
radio = data["radio"]
|
|
lua += (
|
|
f" {{dcsGroupName='{dcs_group_name}', callsign='{callsign}', "
|
|
f"radio='{radio}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
# Process the JTACs
|
|
lua += """
|
|
|
|
-- list the JTACs generated by Liberation
|
|
dcsLiberation.JTACs = {
|
|
"""
|
|
for key in lua_data["JTACs"]:
|
|
data = lua_data["JTACs"][key]
|
|
dcs_group_name = data["dcsGroupName"]
|
|
callsign = data["callsign"]
|
|
zone = data["zone"]
|
|
laser_code = data["laserCode"]
|
|
dcs_unit = data["dcsUnit"]
|
|
radio = data["radio"]
|
|
lua += (
|
|
f" {{dcsGroupName='{dcs_group_name}', callsign='{callsign}', "
|
|
f"zone={repr(zone)}, laserCode='{laser_code}', dcsUnit='{dcs_unit}', "
|
|
f"radio='{radio}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
# Process the Target Points
|
|
lua += """
|
|
|
|
-- list the target points generated by Liberation
|
|
dcsLiberation.TargetPoints = {
|
|
"""
|
|
for key in lua_data["TargetPoints"]:
|
|
data = lua_data["TargetPoints"][key]
|
|
name = data["name"]
|
|
point_type = data["type"]
|
|
position_x = data["position"]["x"]
|
|
position_y = data["position"]["y"]
|
|
lua += (
|
|
f" {{name='{name}', pointType='{point_type}', "
|
|
f"positionX='{position_x}', positionY='{position_y}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
lua += """
|
|
|
|
-- list the airbases generated by Liberation
|
|
-- dcsLiberation.Airbases = {}
|
|
|
|
-- list the aircraft carriers generated by Liberation
|
|
-- dcsLiberation.Carriers = {}
|
|
|
|
-- list the Red AA generated by Liberation
|
|
dcsLiberation.RedAA = {
|
|
"""
|
|
for key in lua_data["RedAA"]:
|
|
data = lua_data["RedAA"][key]
|
|
name = data["name"]
|
|
radius = data["range"]
|
|
position_x = data["position"]["x"]
|
|
position_y = data["position"]["y"]
|
|
lua += (
|
|
f" {{dcsGroupName='{key}', name='{name}', range='{radius}', "
|
|
f"positionX='{position_x}', positionY='{position_y}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
lua += """
|
|
|
|
-- list the Blue AA generated by Liberation
|
|
dcsLiberation.BlueAA = {
|
|
"""
|
|
for key in lua_data["BlueAA"]:
|
|
data = lua_data["BlueAA"][key]
|
|
name = data["name"]
|
|
radius = data["range"]
|
|
position_x = data["position"]["x"]
|
|
position_y = data["position"]["y"]
|
|
lua += (
|
|
f" {{dcsGroupName='{key}', name='{name}', range='{radius}', "
|
|
f"positionX='{position_x}', positionY='{position_y}' }}, \n"
|
|
)
|
|
lua += "}"
|
|
|
|
lua += """
|
|
|
|
"""
|
|
|
|
trigger = TriggerStart(comment="Set DCS Liberation data")
|
|
trigger.add_action(DoScript(String(lua)))
|
|
self.mission.triggerrules.triggers.append(trigger)
|
|
|
|
def inject_lua_trigger(self, contents: str, comment: str) -> None:
|
|
trigger = TriggerStart(comment=comment)
|
|
trigger.add_action(DoScript(String(contents)))
|
|
self.mission.triggerrules.triggers.append(trigger)
|
|
|
|
def bypass_plugin_script(self, mnemonic: str) -> None:
|
|
self.plugin_scripts.append(mnemonic)
|
|
|
|
def inject_plugin_script(
|
|
self, plugin_mnemonic: str, script: str, script_mnemonic: str
|
|
) -> None:
|
|
if script_mnemonic in self.plugin_scripts:
|
|
logging.debug(f"Skipping already loaded {script} for {plugin_mnemonic}")
|
|
return
|
|
|
|
self.plugin_scripts.append(script_mnemonic)
|
|
|
|
plugin_path = Path("./resources/plugins", plugin_mnemonic)
|
|
|
|
script_path = Path(plugin_path, script)
|
|
if not script_path.exists():
|
|
logging.error(f"Cannot find {script_path} for plugin {plugin_mnemonic}")
|
|
return
|
|
|
|
trigger = TriggerStart(comment=f"Load {script_mnemonic}")
|
|
filename = script_path.resolve()
|
|
fileref = self.mission.map_resource.add_resource_file(filename)
|
|
trigger.add_action(DoScriptFile(fileref))
|
|
self.mission.triggerrules.triggers.append(trigger)
|
|
|
|
def inject_plugins(self) -> None:
|
|
for plugin in LuaPluginManager.plugins():
|
|
if plugin.enabled:
|
|
plugin.inject_scripts(self)
|
|
plugin.inject_configuration(self)
|