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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user