From 4ace13c857d0895b7ee32f93d021acbe4f950761 Mon Sep 17 00:00:00 2001 From: RndName Date: Mon, 21 Mar 2022 20:17:17 +0100 Subject: [PATCH] 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 --- game/armedforces/forcegroup.py | 32 +++++++++++++++++++ game/factions/faction.py | 3 +- game/layout/layout.py | 3 ++ game/layout/layoutloader.py | 1 + game/layout/layoutmapping.py | 5 +++ .../layouts/anti_air/4_Launcher_Site.yaml | 2 ++ .../layouts/anti_air/6_Launcher_Site.yaml | 3 +- .../layouts/anti_air/Cold_War_Flak_Site.yaml | 3 +- resources/layouts/anti_air/SHORAD_TR.yaml | 2 ++ 9 files changed, 51 insertions(+), 3 deletions(-) diff --git a/game/armedforces/forcegroup.py b/game/armedforces/forcegroup.py index 9c1c7c62..4f09b738 100644 --- a/game/armedforces/forcegroup.py +++ b/game/armedforces/forcegroup.py @@ -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: diff --git a/game/factions/faction.py b/game/factions/faction.py index 3503cda2..53312c4f 100644 --- a/game/factions/faction.py +++ b/game/factions/faction.py @@ -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", {}) diff --git a/game/layout/layout.py b/game/layout/layout.py index 45b7878d..667c69f5 100644 --- a/game/layout/layout.py +++ b/game/layout/layout.py @@ -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)] diff --git a/game/layout/layoutloader.py b/game/layout/layoutloader.py index c6548695..3fef361a 100644 --- a/game/layout/layoutloader.py +++ b/game/layout/layoutloader.py @@ -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) diff --git a/game/layout/layoutmapping.py b/game/layout/layoutmapping.py index a4dea739..b7f19550 100644 --- a/game/layout/layoutmapping.py +++ b/game/layout/layoutmapping.py @@ -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, diff --git a/resources/layouts/anti_air/4_Launcher_Site.yaml b/resources/layouts/anti_air/4_Launcher_Site.yaml index 8748de79..269a2490 100644 --- a/resources/layouts/anti_air/4_Launcher_Site.yaml +++ b/resources/layouts/anti_air/4_Launcher_Site.yaml @@ -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: diff --git a/resources/layouts/anti_air/6_Launcher_Site.yaml b/resources/layouts/anti_air/6_Launcher_Site.yaml index b5ff9617..dd7aa4b2 100644 --- a/resources/layouts/anti_air/6_Launcher_Site.yaml +++ b/resources/layouts/anti_air/6_Launcher_Site.yaml @@ -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 diff --git a/resources/layouts/anti_air/Cold_War_Flak_Site.yaml b/resources/layouts/anti_air/Cold_War_Flak_Site.yaml index c0028079..bb271d91 100644 --- a/resources/layouts/anti_air/Cold_War_Flak_Site.yaml +++ b/resources/layouts/anti_air/Cold_War_Flak_Site.yaml @@ -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: diff --git a/resources/layouts/anti_air/SHORAD_TR.yaml b/resources/layouts/anti_air/SHORAD_TR.yaml index 01e1e3d8..cde98530 100644 --- a/resources/layouts/anti_air/SHORAD_TR.yaml +++ b/resources/layouts/anti_air/SHORAD_TR.yaml @@ -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: