mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
reworked the skynet group name generation
- added information about the role of the aa site - moved handling of ground name from tgo to the sam generator to make the tgo cleaner - adjusted the skynet-config lua to the changes
This commit is contained in:
parent
20839853b7
commit
de443fa3f0
@ -13,13 +13,14 @@ Saves from 4.0.0 are compatible with 4.0.1.
|
|||||||
## Features/Improvements
|
## Features/Improvements
|
||||||
|
|
||||||
* **[Plugins]** Increased time JTAC Autolase messages stay visible on the UI.
|
* **[Plugins]** Increased time JTAC Autolase messages stay visible on the UI.
|
||||||
|
* **[Mission Generation]** Improvements for better support of the Skynet Plugin and long range SAMs are now acting as EWR
|
||||||
* **[UI]** Added ability to take notes and have those notes appear as a kneeboard page.
|
* **[UI]** Added ability to take notes and have those notes appear as a kneeboard page.
|
||||||
* **[UI]** Hovering over the weather information now dispalys the cloud base (meters and feet).
|
* **[UI]** Hovering over the weather information now dispalys the cloud base (meters and feet).
|
||||||
* **[UI]** Google search link added to unit information when there is no information provided.
|
* **[UI]** Google search link added to unit information when there is no information provided.
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
* **[UI]** Statistics window tick marks are now always integers.
|
* **[UI]** Statistics window tick marks are now always integers.
|
||||||
|
* **[Mission Generation]** The lua data for other plugins is now generated correctly
|
||||||
* **[Flight Planning]** Fixed potential issue with angles > 360° or < 0° being generated when summing two angles.
|
* **[Flight Planning]** Fixed potential issue with angles > 360° or < 0° being generated when summing two angles.
|
||||||
|
|
||||||
# 4.0.0
|
# 4.0.0
|
||||||
|
|||||||
@ -483,7 +483,7 @@ class Game:
|
|||||||
self.current_unit_id += 1
|
self.current_unit_id += 1
|
||||||
return self.current_unit_id
|
return self.current_unit_id
|
||||||
|
|
||||||
def next_group_id(self):
|
def next_group_id(self) -> int:
|
||||||
"""
|
"""
|
||||||
Next unit id for pre-generated units
|
Next unit id for pre-generated units
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -460,9 +460,9 @@ class CoastalSiteGroundObject(TheaterGroundObject):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# TODO: Differentiate types.
|
# The SamGroundObject represents all type of AA
|
||||||
# This type gets used both for AA sites (SAM, AAA, or SHORAD). These should each
|
# The TGO can have multiple types of units (AAA,SAM,Support...)
|
||||||
# be split into their own types.
|
# Differentiation can be made during generation with the airdefensegroupgenerator
|
||||||
class SamGroundObject(TheaterGroundObject):
|
class SamGroundObject(TheaterGroundObject):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -481,18 +481,6 @@ class SamGroundObject(TheaterGroundObject):
|
|||||||
dcs_identifier="AA",
|
dcs_identifier="AA",
|
||||||
sea_object=False,
|
sea_object=False,
|
||||||
)
|
)
|
||||||
# Set by the SAM unit generator if the generated group is compatible
|
|
||||||
# with Skynet.
|
|
||||||
self.skynet_capable = False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def group_name(self) -> str:
|
|
||||||
if self.skynet_capable:
|
|
||||||
# Prefix the group names of SAM sites with the side color so Skynet
|
|
||||||
# can find them.
|
|
||||||
return f"{self.faction_color}|SAM|{self.group_id}"
|
|
||||||
else:
|
|
||||||
return super().group_name
|
|
||||||
|
|
||||||
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||||
from gen.flights.flight import FlightType
|
from gen.flights.flight import FlightType
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Iterator, List
|
from typing import Iterator, List
|
||||||
@ -9,11 +11,31 @@ from game.theater.theatergroundobject import SamGroundObject
|
|||||||
from gen.sam.group_generator import GroupGenerator
|
from gen.sam.group_generator import GroupGenerator
|
||||||
|
|
||||||
|
|
||||||
|
class SkynetRole(Enum):
|
||||||
|
#: A radar SAM that should be controlled by Skynet.
|
||||||
|
Sam = "Sam"
|
||||||
|
|
||||||
|
#: A radar SAM that should be controlled and used as an EWR by Skynet.
|
||||||
|
SamAsEwr = "SamAsEwr"
|
||||||
|
|
||||||
|
#: An air defense unit that should be used as point defense by Skynet.
|
||||||
|
PointDefense = "PD"
|
||||||
|
|
||||||
|
#: All other types of groups that might be present in a SAM TGO. This includes
|
||||||
|
#: SHORADS, AAA, supply trucks, etc. Anything that shouldn't be controlled by Skynet
|
||||||
|
#: should use this role.
|
||||||
|
NoSkynetBehavior = "NoSkynetBehavior"
|
||||||
|
|
||||||
|
|
||||||
class AirDefenseRange(Enum):
|
class AirDefenseRange(Enum):
|
||||||
AAA = "AAA"
|
AAA = ("AAA", SkynetRole.NoSkynetBehavior)
|
||||||
Short = "short"
|
Short = ("short", SkynetRole.NoSkynetBehavior)
|
||||||
Medium = "medium"
|
Medium = ("medium", SkynetRole.Sam)
|
||||||
Long = "long"
|
Long = ("long", SkynetRole.SamAsEwr)
|
||||||
|
|
||||||
|
def __init__(self, description: str, default_role: SkynetRole) -> None:
|
||||||
|
self.range_name = description
|
||||||
|
self.default_role = default_role
|
||||||
|
|
||||||
|
|
||||||
class AirDefenseGroupGenerator(GroupGenerator, ABC):
|
class AirDefenseGroupGenerator(GroupGenerator, ABC):
|
||||||
@ -24,18 +46,32 @@ class AirDefenseGroupGenerator(GroupGenerator, ABC):
|
|||||||
price: int
|
price: int
|
||||||
|
|
||||||
def __init__(self, game: Game, ground_object: SamGroundObject) -> None:
|
def __init__(self, game: Game, ground_object: SamGroundObject) -> None:
|
||||||
ground_object.skynet_capable = True
|
|
||||||
super().__init__(game, ground_object)
|
super().__init__(game, ground_object)
|
||||||
|
|
||||||
|
self.vg.name = self.group_name_for_role(self.vg.id, self.primary_group_role())
|
||||||
self.auxiliary_groups: List[VehicleGroup] = []
|
self.auxiliary_groups: List[VehicleGroup] = []
|
||||||
|
|
||||||
def add_auxiliary_group(self, name_suffix: str) -> VehicleGroup:
|
def add_auxiliary_group(self, role: SkynetRole) -> VehicleGroup:
|
||||||
group = VehicleGroup(
|
gid = self.game.next_group_id()
|
||||||
self.game.next_group_id(), "|".join([self.go.group_name, name_suffix])
|
group = VehicleGroup(gid, self.group_name_for_role(gid, role))
|
||||||
)
|
|
||||||
self.auxiliary_groups.append(group)
|
self.auxiliary_groups.append(group)
|
||||||
return group
|
return group
|
||||||
|
|
||||||
|
def group_name_for_role(self, gid: int, role: SkynetRole) -> str:
|
||||||
|
if role is SkynetRole.NoSkynetBehavior:
|
||||||
|
# No special naming needed for air defense groups that don't participate in
|
||||||
|
# Skynet.
|
||||||
|
return f"{self.go.group_name}|{gid}"
|
||||||
|
|
||||||
|
# For those that do, we need a prefix of `$COLOR|SAM| so our Skynet config picks
|
||||||
|
# the group up at all. To support PDs we need to append the ID of the TGO so
|
||||||
|
# that the PD will know which group it's protecting. We then append the role so
|
||||||
|
# our config knows what to do with the group, and finally the GID of *this*
|
||||||
|
# group to ensure no conflicts.
|
||||||
|
return "|".join(
|
||||||
|
[self.go.faction_color, "SAM", str(self.go.group_id), role.value, str(gid)]
|
||||||
|
)
|
||||||
|
|
||||||
def get_generated_group(self) -> VehicleGroup:
|
def get_generated_group(self) -> VehicleGroup:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Deprecated call to AirDefenseGroupGenerator.get_generated_group "
|
"Deprecated call to AirDefenseGroupGenerator.get_generated_group "
|
||||||
@ -52,3 +88,7 @@ class AirDefenseGroupGenerator(GroupGenerator, ABC):
|
|||||||
@abstractmethod
|
@abstractmethod
|
||||||
def range(cls) -> AirDefenseRange:
|
def range(cls) -> AirDefenseRange:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def primary_group_role(cls) -> SkynetRole:
|
||||||
|
return cls.range().default_role
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from dcs.vehicles import AirDefence
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ class HawkGenerator(AirDefenseGroupGenerator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Triple A for close range defense
|
# Triple A for close range defense
|
||||||
aa_group = self.add_auxiliary_group("AA")
|
aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
|
||||||
self.add_unit_to_group(
|
self.add_unit_to_group(
|
||||||
aa_group,
|
aa_group,
|
||||||
AirDefence.Vulcan,
|
AirDefence.Vulcan,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from dcs.vehicles import AirDefence
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ class HQ7Generator(AirDefenseGroupGenerator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Triple A for close range defense
|
# Triple A for close range defense
|
||||||
aa_group = self.add_auxiliary_group("AA")
|
aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
|
||||||
self.add_unit_to_group(
|
self.add_unit_to_group(
|
||||||
aa_group,
|
aa_group,
|
||||||
AirDefence.Ural_375_ZU_23,
|
AirDefence.Ural_375_ZU_23,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from dcs.vehicles import AirDefence
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ class PatriotGenerator(AirDefenseGroupGenerator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Short range protection for high value site
|
# Short range protection for high value site
|
||||||
aa_group = self.add_auxiliary_group("AA")
|
aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
|
||||||
num_launchers = random.randint(3, 4)
|
num_launchers = random.randint(3, 4)
|
||||||
positions = self.get_circular_position(
|
positions = self.get_circular_position(
|
||||||
num_launchers, launcher_distance=200, coverage=360
|
num_launchers, launcher_distance=200, coverage=360
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from dcs.vehicles import AirDefence
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -49,3 +50,7 @@ class RapierGenerator(AirDefenseGroupGenerator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def range(cls) -> AirDefenseRange:
|
def range(cls) -> AirDefenseRange:
|
||||||
return AirDefenseRange.Short
|
return AirDefenseRange.Short
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def primary_group_role(cls) -> SkynetRole:
|
||||||
|
return SkynetRole.Sam
|
||||||
|
|||||||
@ -3,6 +3,7 @@ from dcs.vehicles import AirDefence, Unarmed
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -40,3 +41,7 @@ class RolandGenerator(AirDefenseGroupGenerator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def range(cls) -> AirDefenseRange:
|
def range(cls) -> AirDefenseRange:
|
||||||
return AirDefenseRange.Short
|
return AirDefenseRange.Short
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def primary_group_role(cls) -> SkynetRole:
|
||||||
|
return SkynetRole.Sam
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from game.theater import SamGroundObject
|
|||||||
from gen.sam.airdefensegroupgenerator import (
|
from gen.sam.airdefensegroupgenerator import (
|
||||||
AirDefenseRange,
|
AirDefenseRange,
|
||||||
AirDefenseGroupGenerator,
|
AirDefenseGroupGenerator,
|
||||||
|
SkynetRole,
|
||||||
)
|
)
|
||||||
from pydcs_extensions.highdigitsams import highdigitsams
|
from pydcs_extensions.highdigitsams import highdigitsams
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ class SA10Generator(AirDefenseGroupGenerator):
|
|||||||
|
|
||||||
def generate_defensive_groups(self) -> None:
|
def generate_defensive_groups(self) -> None:
|
||||||
# AAA for defending against close targets.
|
# AAA for defending against close targets.
|
||||||
aa_group = self.add_auxiliary_group("AA")
|
aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
|
||||||
num_launchers = random.randint(6, 8)
|
num_launchers = random.randint(6, 8)
|
||||||
positions = self.get_circular_position(
|
positions = self.get_circular_position(
|
||||||
num_launchers, launcher_distance=210, coverage=360
|
num_launchers, launcher_distance=210, coverage=360
|
||||||
@ -101,7 +102,7 @@ class Tier2SA10Generator(SA10Generator):
|
|||||||
super().generate_defensive_groups()
|
super().generate_defensive_groups()
|
||||||
|
|
||||||
# SA-15 for both shorter range targets and point defense.
|
# SA-15 for both shorter range targets and point defense.
|
||||||
pd_group = self.add_auxiliary_group("PD")
|
pd_group = self.add_auxiliary_group(SkynetRole.PointDefense)
|
||||||
num_launchers = random.randint(2, 4)
|
num_launchers = random.randint(2, 4)
|
||||||
positions = self.get_circular_position(
|
positions = self.get_circular_position(
|
||||||
num_launchers, launcher_distance=140, coverage=360
|
num_launchers, launcher_distance=140, coverage=360
|
||||||
@ -123,7 +124,7 @@ class Tier3SA10Generator(SA10Generator):
|
|||||||
|
|
||||||
def generate_defensive_groups(self) -> None:
|
def generate_defensive_groups(self) -> None:
|
||||||
# AAA for defending against close targets.
|
# AAA for defending against close targets.
|
||||||
aa_group = self.add_auxiliary_group("AA")
|
aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
|
||||||
num_launchers = random.randint(6, 8)
|
num_launchers = random.randint(6, 8)
|
||||||
positions = self.get_circular_position(
|
positions = self.get_circular_position(
|
||||||
num_launchers, launcher_distance=210, coverage=360
|
num_launchers, launcher_distance=210, coverage=360
|
||||||
@ -138,7 +139,7 @@ class Tier3SA10Generator(SA10Generator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# SA-15 for both shorter range targets and point defense.
|
# SA-15 for both shorter range targets and point defense.
|
||||||
pd_group = self.add_auxiliary_group("PD")
|
pd_group = self.add_auxiliary_group(SkynetRole.PointDefense)
|
||||||
num_launchers = random.randint(2, 4)
|
num_launchers = random.randint(2, 4)
|
||||||
positions = self.get_circular_position(
|
positions = self.get_circular_position(
|
||||||
num_launchers, launcher_distance=140, coverage=360
|
num_launchers, launcher_distance=140, coverage=360
|
||||||
|
|||||||
@ -93,9 +93,28 @@ if dcsLiberation and SkynetIADS then
|
|||||||
for i = 1, #sites do
|
for i = 1, #sites do
|
||||||
local site = sites[i]
|
local site = sites[i]
|
||||||
local name = site:getDCSName()
|
local name = site:getDCSName()
|
||||||
|
|
||||||
|
if string.match(name, "|SamAsEwr|") then
|
||||||
|
env.info(string.format("DCSLiberation|Skynet-IADS plugin - %s now acting as EWR", name))
|
||||||
|
site:setActAsEW(true)
|
||||||
|
end
|
||||||
|
|
||||||
if not string.match(name, "|PD") then
|
if not string.match(name, "|PD") then
|
||||||
env.info(string.format("DCSLiberation|Skynet-IADS plugin - Checking %s for PD", name))
|
-- Name is prefixed with `$color|SAM|$tgoid`. For pre-4.1 generated
|
||||||
local pds = iads:getSAMSitesByPrefix(name .. "|PD")
|
-- campaigns that's the full name of the primary SAM and any PD are just
|
||||||
|
-- that name suffixed with |PD.
|
||||||
|
--
|
||||||
|
-- For 4.1+ generated campaigns the name will be
|
||||||
|
-- `$color|SAM|$tgoid|$role|$gid`, so we need to replace the content
|
||||||
|
-- beginning with the third pipe with `|PD` to find our PDs.
|
||||||
|
local first_pipe = string.find(name, "|")
|
||||||
|
local second_pipe = string.find(name, "|", first_pipe + 1)
|
||||||
|
local third_pipe = string.find(name, "|", second_pipe + 1)
|
||||||
|
local pd_prefix = name .. "|PD"
|
||||||
|
if third_pipe ~= nil then
|
||||||
|
pd_prefix = string.sub(name, 1, third_pipe) .. "PD"
|
||||||
|
end
|
||||||
|
local pds = iads:getSAMSitesByPrefix(pd_prefix)
|
||||||
for j = 1, #pds do
|
for j = 1, #pds do
|
||||||
pd = pds[j]
|
pd = pds[j]
|
||||||
env.info(string.format("DCSLiberation|Skynet-IADS plugin - Adding %s as PD for %s", pd:getDCSName(), name))
|
env.info(string.format("DCSLiberation|Skynet-IADS plugin - Adding %s as PD for %s", pd:getDCSName(), name))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user