mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
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
132 lines
4.4 KiB
Python
132 lines
4.4 KiB
Python
from __future__ import annotations
|
|
from collections import defaultdict
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Type
|
|
|
|
from dcs.unittype import UnitType as DcsUnitType
|
|
|
|
from game.data.groups import GroupRole, GroupTask
|
|
from game.data.units import UnitClass
|
|
from game.dcs.helpers import unit_type_from_name
|
|
|
|
|
|
@dataclass
|
|
class GroupLayoutMapping:
|
|
# The group name used in the template.miz
|
|
name: str
|
|
|
|
# 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)
|
|
|
|
# How many units should be generated from the grouplayout. If only one value is
|
|
# added this will be an exact amount. If 2 values are used it will be a random
|
|
# amount between these values.
|
|
unit_count: list[int] = field(default_factory=list)
|
|
|
|
# All unit types the template supports.
|
|
unit_types: list[Type[DcsUnitType]] = field(default_factory=list)
|
|
|
|
# All unit classes the template supports.
|
|
unit_classes: list[UnitClass] = field(default_factory=list)
|
|
|
|
# Fallback Classes which are used when the unit_classes and unit_types do not fit any accessible unit from the faction. Only used for EWRs to also Use SR when no
|
|
# dedicated EWRs are available to the faction
|
|
fallback_classes: list[UnitClass] = field(default_factory=list)
|
|
|
|
@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 = []
|
|
if "unit_types" in d:
|
|
for u in d["unit_types"]:
|
|
unit_type = unit_type_from_name(u)
|
|
if unit_type:
|
|
unit_types.append(unit_type)
|
|
unit_classes = (
|
|
[UnitClass(u) for u in d["unit_classes"]] if "unit_classes" in d else []
|
|
)
|
|
fallback_classes = (
|
|
[UnitClass(u) for u in d["fallback_classes"]]
|
|
if "fallback_classes" in d
|
|
else []
|
|
)
|
|
return GroupLayoutMapping(
|
|
d["name"],
|
|
optional,
|
|
fill,
|
|
statics,
|
|
unit_count,
|
|
unit_types,
|
|
unit_classes,
|
|
fallback_classes,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class LayoutMapping:
|
|
# The name of the Template
|
|
name: str
|
|
|
|
# An optional description to give more information about the template
|
|
description: str
|
|
|
|
# Optional field to define if the template can be used to create generic groups
|
|
generic: bool
|
|
|
|
# All taskings the template can be used for
|
|
tasks: list[GroupTask]
|
|
|
|
# All Groups the template has
|
|
groups: dict[str, list[GroupLayoutMapping]]
|
|
|
|
# Define the miz file for the template. Optional. If empty use the mapping name
|
|
layout_file: str
|
|
|
|
@property
|
|
def primary_role(self) -> GroupRole:
|
|
return self.tasks[0].role
|
|
|
|
@staticmethod
|
|
def from_dict(d: dict[str, Any], file_name: str) -> LayoutMapping:
|
|
groups: dict[str, list[GroupLayoutMapping]] = defaultdict(list)
|
|
for group in d["groups"]:
|
|
for group_name, group_layouts in group.items():
|
|
groups[group_name].extend(
|
|
[
|
|
GroupLayoutMapping.from_dict(group_layout)
|
|
for group_layout in group_layouts
|
|
]
|
|
)
|
|
|
|
description = d["description"] if "description" in d else ""
|
|
generic = d["generic"] if "generic" in d else False
|
|
layout_file = (
|
|
d["layout_file"] if "layout_file" in d else file_name.replace("yaml", "miz")
|
|
)
|
|
tasks = [GroupTask.by_description(task) for task in d["tasks"]]
|
|
return LayoutMapping(
|
|
d["name"],
|
|
description,
|
|
generic,
|
|
tasks,
|
|
groups,
|
|
layout_file,
|
|
)
|
|
|
|
def group_for_name(self, name: str) -> tuple[int, str, GroupLayoutMapping]:
|
|
for group_name, group_mappings in self.groups.items():
|
|
for g_id, group_mapping in enumerate(group_mappings):
|
|
if group_mapping.name == name or name in group_mapping.statics:
|
|
return g_id, group_name, group_mapping
|
|
raise KeyError
|