mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Allow skynet properties override and improve dead unit handling
Now the user can override special skynet properties from the unit.yaml of the main Radar of the sam site. Which unit needs these overrides can be looked up over here: https://github.com/walder/Skynet-IADS/blob/develop/skynet-iads-source/skynet-iads-supported-types.lua - fixed wrong exclusion of groups with the first unit dead but still able to participate - added some exception handling in the lua script for groups which skynet is not able to control. preventing scripting errors
This commit is contained in:
parent
4664a7bbd4
commit
004bcce58e
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Type, Iterator
|
||||
from typing import Any, Optional, Type, Iterator
|
||||
|
||||
import yaml
|
||||
from dcs.unittype import VehicleType
|
||||
@ -13,9 +13,47 @@ from game.data.units import UnitClass
|
||||
from game.dcs.unittype import UnitType
|
||||
|
||||
|
||||
@dataclass
|
||||
class SkynetProperties:
|
||||
can_engage_harm: Optional[str] = None
|
||||
can_engage_air_weapon: Optional[str] = None
|
||||
go_live_range_in_percent: Optional[str] = None
|
||||
engagement_zone: Optional[str] = None
|
||||
autonomous_behaviour: Optional[str] = None
|
||||
harm_detection_chance: Optional[str] = None
|
||||
|
||||
@classmethod
|
||||
def from_data(cls, data: dict[str, Any]) -> SkynetProperties:
|
||||
props = SkynetProperties()
|
||||
if "can_engage_harm" in data:
|
||||
props.can_engage_harm = str(data["can_engage_harm"]).lower()
|
||||
if "can_engage_air_weapon" in data:
|
||||
props.can_engage_air_weapon = str(data["can_engage_air_weapon"]).lower()
|
||||
if "go_live_range_in_percent" in data:
|
||||
props.go_live_range_in_percent = str(data["go_live_range_in_percent"])
|
||||
if "engagement_zone" in data:
|
||||
props.engagement_zone = str(data["engagement_zone"])
|
||||
if "autonomous_behaviour" in data:
|
||||
props.autonomous_behaviour = str(data["autonomous_behaviour"])
|
||||
if "harm_detection_chance" in data:
|
||||
props.harm_detection_chance = str(data["harm_detection_chance"])
|
||||
return props
|
||||
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
properties: dict[str, str] = {}
|
||||
for key, value in self.__dict__.items():
|
||||
if value is not None:
|
||||
properties[key] = value
|
||||
return properties
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(id(self))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class GroundUnitType(UnitType[Type[VehicleType]]):
|
||||
spawn_weight: int
|
||||
skynet_properties: SkynetProperties
|
||||
|
||||
@classmethod
|
||||
def named(cls, name: str) -> GroundUnitType:
|
||||
@ -76,4 +114,7 @@ class GroundUnitType(UnitType[Type[VehicleType]]):
|
||||
manufacturer=data.get("manufacturer", "No data."),
|
||||
role=data.get("role", "No data."),
|
||||
price=data.get("price", 1),
|
||||
skynet_properties=SkynetProperties.from_data(
|
||||
data.get("skynet_properties", {})
|
||||
),
|
||||
)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
from __future__ import annotations
|
||||
from collections import defaultdict
|
||||
|
||||
import logging
|
||||
import os
|
||||
@ -15,6 +14,7 @@ from dcs.triggers import TriggerStart
|
||||
from game.ato import FlightType
|
||||
from game.plugins import LuaPluginManager
|
||||
from game.theater import TheaterGroundObject
|
||||
from game.theater.iadsnetwork.iadsrole import IadsRole
|
||||
from game.utils import escape_string_for_lua
|
||||
|
||||
from .aircraft.flightdata import FlightData
|
||||
@ -142,6 +142,10 @@ class LuaGenerator:
|
||||
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)
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ class IadsConnectionJs(BaseModel):
|
||||
node=tgo.id,
|
||||
connected=connection.ground_object.id,
|
||||
active=(
|
||||
tgo.alive_unit_count > 0
|
||||
and connection.ground_object.alive_unit_count > 0
|
||||
network_node.group.alive_units > 0
|
||||
and connection.alive_units > 0
|
||||
),
|
||||
blue=tgo.is_friendly(True),
|
||||
is_power="power"
|
||||
|
||||
@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Iterator, Optional
|
||||
from uuid import UUID
|
||||
import uuid
|
||||
from game.theater.iadsnetwork.iadsrole import IadsRole
|
||||
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.theater.theatergroundobject import (
|
||||
IadsBuildingGroundObject,
|
||||
IadsGroundObject,
|
||||
@ -31,6 +31,7 @@ class SkynetNode:
|
||||
dcs_name: str
|
||||
player: bool
|
||||
iads_role: IadsRole
|
||||
properties: dict[str, str] = field(default_factory=dict)
|
||||
connections: dict[str, list[str]] = field(default_factory=lambda: defaultdict(list))
|
||||
|
||||
@staticmethod
|
||||
@ -42,18 +43,30 @@ class SkynetNode:
|
||||
IadsRole.POWER_SOURCE,
|
||||
]:
|
||||
# Use UnitName for EWR, CommandCenter, Comms, Power
|
||||
return group.units[0].unit_name
|
||||
for unit in group.units:
|
||||
# Check for alive units in the group
|
||||
if unit.alive:
|
||||
return unit.unit_name
|
||||
if group.units[0].is_static:
|
||||
# Statics will be placed as dead unit
|
||||
return group.units[0].unit_name
|
||||
# If no alive unit is available and not static raise error
|
||||
raise IadsNetworkException("Group has no skynet usable units")
|
||||
else:
|
||||
# Use the GroupName for SAMs, SAMAsEWR and PDs
|
||||
return group.group_name
|
||||
|
||||
@classmethod
|
||||
def from_group(cls, group: IadsGroundGroup) -> SkynetNode:
|
||||
return cls(
|
||||
node = cls(
|
||||
cls.dcs_name_for_group(group),
|
||||
group.ground_object.is_friendly(True),
|
||||
group.iads_role,
|
||||
)
|
||||
unit_type = group.units[0].unit_type
|
||||
if unit_type is not None and isinstance(unit_type, GroundUnitType):
|
||||
node.properties = unit_type.skynet_properties.to_dict()
|
||||
return node
|
||||
|
||||
|
||||
class IadsNetworkNode:
|
||||
@ -102,24 +115,22 @@ class IadsNetwork:
|
||||
"""Get all skynet nodes from the IADS Network"""
|
||||
skynet_nodes: list[SkynetNode] = []
|
||||
for node in self.nodes:
|
||||
if game.iads_considerate_culling(node.group.ground_object) or (
|
||||
node.group.units[0].is_vehicle and not node.group.units[0].alive
|
||||
):
|
||||
# Skip
|
||||
if game.iads_considerate_culling(node.group.ground_object):
|
||||
# Skip culled ground objects
|
||||
continue
|
||||
try:
|
||||
skynet_node = SkynetNode.from_group(node.group)
|
||||
for connection in node.connections.values():
|
||||
if connection.ground_object.is_friendly(
|
||||
skynet_node.player
|
||||
) and not game.iads_considerate_culling(connection.ground_object):
|
||||
skynet_node.connections[connection.iads_role.value].append(
|
||||
SkynetNode.dcs_name_for_group(connection)
|
||||
)
|
||||
skynet_nodes.append(skynet_node)
|
||||
except IadsNetworkException:
|
||||
# Node not skynet compatible
|
||||
continue
|
||||
skynet_node = SkynetNode.from_group(node.group)
|
||||
for connection in node.connections.values():
|
||||
if (
|
||||
connection.ground_object.is_friendly(skynet_node.player)
|
||||
and not game.iads_considerate_culling(connection.ground_object)
|
||||
and not (
|
||||
connection.units[0].is_vehicle and not connection.units[0].alive
|
||||
)
|
||||
):
|
||||
skynet_node.connections[connection.iads_role.value].append(
|
||||
SkynetNode.dcs_name_for_group(connection)
|
||||
)
|
||||
skynet_nodes.append(skynet_node)
|
||||
return skynet_nodes
|
||||
|
||||
def update_tgo(self, tgo: TheaterGroundObject) -> None:
|
||||
|
||||
@ -40,6 +40,28 @@ if dcsLiberation and SkynetIADS then
|
||||
|
||||
-- actual configuration code
|
||||
local function initializeIADSElement(iads, iads_unit, element)
|
||||
if iads_unit == nil then
|
||||
-- skip processing of units which can not be handled by skynet
|
||||
return
|
||||
end
|
||||
if element.engagement_zone then
|
||||
iads_unit:setEngagementZone(element.engagement_zone)
|
||||
end
|
||||
if element.can_engage_harm then
|
||||
iads_unit:setCanEngageHARM(element.can_engage_harm)
|
||||
end
|
||||
if element.harm_detection_chance then
|
||||
iads_unit:setHARMDetectionChance(tonumber(element.harm_detection_chance))
|
||||
end
|
||||
if element.can_engage_air_weapon then
|
||||
iads_unit:setCanEngageAirWeapons(element.can_engage_air_weapon)
|
||||
end
|
||||
if element.go_live_range_in_percent then
|
||||
iads_unit:setGoLiveRangeInPercent(tonumber(element.go_live_range_in_percent))
|
||||
end
|
||||
if element.autonomous_behaviour then
|
||||
iads_unit:setAutonomousBehaviour(element.autonomous_behaviour)
|
||||
end
|
||||
if element.ConnectionNode then
|
||||
for i,cn in pairs(element.ConnectionNode) do
|
||||
env.info(string.format("DCSLiberation|Skynet-IADS plugin - adding IADS ConnectionNode %s", cn))
|
||||
|
||||
@ -2,3 +2,10 @@ class: SearchRadar
|
||||
price: 22
|
||||
variants:
|
||||
SAM Patriot STR: null
|
||||
skynet_properties: # Override skynet default properties
|
||||
can_engage_harm: true
|
||||
# can_engage_air_weapon: true # https://github.com/walder/Skynet-IADS/tree/develop#engage-air-weapons
|
||||
go_live_range_in_percent: 100
|
||||
harm_detection_chance: 90
|
||||
engagement_zone: SkynetIADSAbstractRadarElement.GO_LIVE_WHEN_IN_KILL_ZONE # https://github.com/walder/Skynet-IADS/tree/develop#engagement-zone
|
||||
autonomous_behaviour: SkynetIADSAbstractRadarElement.AUTONOMOUS_STATE_DCS_AI # https://github.com/walder/Skynet-IADS/tree/develop#autonomous-mode-behaviour
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user