Improve the optional unit handling in layouts

added the fill property to the layout groups which allows to specify if a optional layout group should be filled with a faction accessible unit if it was not defined by the preset groups. This is usefull to allow more generalized templates which for example may or may not have a Search Radar without adding one to all layouts (example: Rapier and Roland Sites which use the generic SHORAD layout)

this fixes an issue which prevented optional units like logistics to be added to the forcegroup if they were not defined in the preset group yaml
This commit is contained in:
RndName 2022-03-21 20:17:17 +01:00
parent 923549ef69
commit 4ace13c857
9 changed files with 51 additions and 3 deletions

View File

@ -62,6 +62,8 @@ class ForceGroup:
units: set[UnitType[Any]] = set()
statics: set[Type[DcsUnitType]] = set()
for group in layout.all_groups:
if group.optional and not group.fill:
continue
for unit_type in group.possible_types_for_faction(faction):
if issubclass(unit_type, VehicleType):
units.add(next(GroundUnitType.for_dcs_type(unit_type)))
@ -81,6 +83,36 @@ class ForceGroup:
def __str__(self) -> str:
return self.name
def has_unit_for_layout_group(self, group: TgoLayoutGroup) -> bool:
for unit in self.units:
if (
unit.dcs_unit_type in group.unit_types
or unit.unit_class in group.unit_classes
):
return True
return False
@classmethod
def for_faction_by_name(cls, name: str, faction: Faction) -> ForceGroup:
"""Load a PresetGroup as ForceGroup with faction sensitive handling"""
force_group = cls.named(name)
for layout in force_group.layouts:
for groups in layout.groups.values():
for group in groups:
if group.fill and not force_group.has_unit_for_layout_group(group):
for unit_type in group.possible_types_for_faction(faction):
if issubclass(unit_type, VehicleType):
force_group.units.append(
next(GroundUnitType.for_dcs_type(unit_type))
)
elif issubclass(unit_type, ShipType):
force_group.units.append(
next(ShipUnitType.for_dcs_type(unit_type))
)
elif issubclass(unit_type, StaticType):
force_group.statics.append(unit_type)
return force_group
@classmethod
def named(cls, name: str) -> ForceGroup:
if not cls._loaded:

View File

@ -216,7 +216,8 @@ class Faction:
# This has to be loaded AFTER GroundUnitType and ShipUnitType to work properly
faction.preset_groups = [
ForceGroup.named(n) for n in json.get("preset_groups", [])
ForceGroup.for_faction_by_name(n, faction)
for n in json.get("preset_groups", [])
]
faction.requirements = json.get("requirements", {})

View File

@ -96,6 +96,9 @@ class TgoLayoutGroup:
# Defines if this groupTemplate is required or not
optional: bool = False
# Should this be filled by accessible units if optional or not
fill: bool = True
def possible_types_for_faction(self, faction: Faction) -> list[Type[DcsUnitType]]:
"""Determine the possible dcs unit types for the TgoLayoutGroup and the given faction"""
unit_types = [t for t in self.unit_types if faction.has_access_to_dcs_type(t)]

View File

@ -166,6 +166,7 @@ class LayoutLoader:
group_mapping.fallback_classes,
)
group_layout.optional = group_mapping.optional
group_layout.fill = group_mapping.fill
# Add the group at the correct index
layout.add_layout_group(group_name, group_layout, g_id)
layout_unit = LayoutUnit.from_unit(unit)

View File

@ -19,6 +19,9 @@ class GroupLayoutMapping:
# Defines if the group is required for the template or can be skipped
optional: bool = False
# Should this be filled by accessible units if optional or not
fill: bool = True
# All static units for the group
statics: list[str] = field(default_factory=list)
@ -40,6 +43,7 @@ class GroupLayoutMapping:
@staticmethod
def from_dict(d: dict[str, Any]) -> GroupLayoutMapping:
optional = d["optional"] if "optional" in d else False
fill = d["fill"] if "fill" in d else True
statics = d["statics"] if "statics" in d else []
unit_count = d["unit_count"] if "unit_count" in d else []
unit_types = []
@ -59,6 +63,7 @@ class GroupLayoutMapping:
return GroupLayoutMapping(
d["name"],
optional,
fill,
statics,
unit_count,
unit_types,

View File

@ -12,12 +12,14 @@ groups:
- SearchTrackRadar
- name: Track Radar
optional: true # Allow groups without TR
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:
- TrackRadar
- name: Command Post
optional: true
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:

View File

@ -12,17 +12,18 @@ groups:
- SearchTrackRadar
- name: Track Radar
optional: true # Allow groups without TR
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:
- TrackRadar
- name: Command Post
optional: true
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:
- CommandPost
- name: Launcher
unit_count:
- 6

View File

@ -3,8 +3,9 @@ tasks:
- AAA
groups:
- AAA:
- name: Cold War Flak Site Radar
- name: Cold War Flak Site Radar
optional: true # Only available to Late Cold War
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:

View File

@ -5,6 +5,7 @@ groups:
- SHORAD:
- name: SHORAD STR
optional: true
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes:
@ -13,6 +14,7 @@ groups:
- TrackRadar
- name: SHORAD OTR
optional: true
fill: false # Do not fill with faction possible units
unit_count:
- 1
unit_classes: