Implement Template System for ground objects

- Factored out the current generators to use a better approach with Templates build from the dcs mission editor.
- This information is extended with a template-mapping in a json file which allows to logically group together multiple dcs groups and even statics to one template
- The combination of mapping and miz will be serialized to a template.json which is only used for loading.
- Factions now load templates during initialization and hold all the templates they can really use. This is based around the faction file.
- Implemented a template randomizer which allows to add some randomization to templates
- Each Template Group can have 1 randomizer which randomizes unit_type and size based on the mapping definition. Larger groups need to be devided in more fine detailed groups as we can now handle them better due to the change from dcs group types to our own classes.
- Rewritten the ArmorGroup, Naval and EWR template handling

Rework GroundObjectBuyMenu to support templates
This commit is contained in:
RndName
2022-01-19 13:06:19 +01:00
parent d154069877
commit 5febcdd4e4
11 changed files with 1884 additions and 591 deletions

View File

@@ -1,5 +1,6 @@
from __future__ import annotations
import copy
import itertools
import logging
from dataclasses import dataclass, field
@@ -24,6 +25,7 @@ from game.data.doctrine import (
from game.data.groundunitclass import GroundUnitClass
from game.dcs.aircrafttype import AircraftType
from game.dcs.groundunittype import GroundUnitType
from gen.templates import GroundObjectTemplates, TemplateCategory
if TYPE_CHECKING:
from game.theater.start_generator import ModSettings
@@ -72,7 +74,7 @@ class Faction:
air_defenses: List[str] = field(default_factory=list)
# Possible EWR generators for this faction.
ewrs: List[str] = field(default_factory=list)
ewrs: List[GroundUnitType] = field(default_factory=list)
# Possible Missile site generators for this faction
missiles: List[str] = field(default_factory=list)
@@ -137,12 +139,68 @@ class Faction:
#: both will use it.
unrestricted_satnav: bool = False
def has_access_to_unittype(self, unit_class: GroundUnitClass) -> bool:
# All possible templates which can be generated by the faction
templates: GroundObjectTemplates = field(default=GroundObjectTemplates())
def __getitem__(self, item: str) -> Any:
return getattr(self, item)
def has_access_to_unit_type(self, unit_type: str) -> bool:
# Supports all GroundUnit lists and AirDefenses
for unit in self.ground_units:
if unit_type == unit.dcs_id:
return True
return unit_type in self.air_defenses
def has_access_to_unit_class(self, unit_class: GroundUnitClass) -> bool:
for vehicle in itertools.chain(self.frontline_units, self.artillery_units):
if vehicle.unit_class is unit_class:
return True
return False
def load_templates(self, all_templates: GroundObjectTemplates) -> None:
# This loads all faction possible sam templates and the default ones
# For legacy reasons this allows to check for template names. This can be
# improved in the future to have more control about the possible Templates.
# For example it can be possible to define the unit_types and check if all
# requirements for the template are fulfilled.
for category, template in all_templates.templates:
if (
(
category == TemplateCategory.AirDefence
and (
# Check if faction has the template name or ALL required
# unit_types in the list air_defenses. For legacy reasons this
# allows both and also the EWR template
template.name in self.air_defenses
or all(
self.has_access_to_unit_type(required_unit)
for required_unit in template.required_units
)
or template.template_type == "EWR"
)
)
or template.name in self.navy_generators
or template.name in self.missiles
or template.name in self.coastal_defenses
or (
template.template_type
in self.building_set + ["fob", "ammo", "factory"]
)
or (template.template_type == "carrier" and self.aircraft_carrier)
or (template.template_type == "lha" and self.helicopter_carrier)
or category == TemplateCategory.Armor
):
# Make a deep copy of a template and add it to the template_list.
# This is required to have faction independent templates. Otherwise
# the reference would be the same and changes would affect all.
faction_template = copy.deepcopy(template)
# Initialize all randomizers
for group_template in faction_template.groups:
if group_template.randomizer:
group_template.randomizer.init_randomization_for_faction(self)
self.templates.add_template(category, faction_template)
@classmethod
def from_json(cls: Type[Faction], json: Dict[str, Any]) -> Faction:
faction = Faction(locales=json.get("locales"))
@@ -182,8 +240,7 @@ class Faction:
faction.logistics_units = [
GroundUnitType.named(n) for n in json.get("logistics_units", [])
]
faction.ewrs = json.get("ewrs", [])
faction.ewrs = [GroundUnitType.named(n) for n in json.get("ewrs", [])]
faction.air_defenses = json.get("air_defenses", [])
# Compatibility for older factions. All air defenses now belong to a
@@ -245,6 +302,8 @@ class Faction:
faction.unrestricted_satnav = json.get("unrestricted_satnav", False)
# Templates
faction.templates = GroundObjectTemplates()
return faction
@property
@@ -320,13 +379,13 @@ class Faction:
self.remove_vehicle("KORNET")
# high digit sams
if not mod_settings.high_digit_sams:
self.remove_air_defenses("SA10BGenerator")
self.remove_air_defenses("SA12Generator")
self.remove_air_defenses("SA20Generator")
self.remove_air_defenses("SA20BGenerator")
self.remove_air_defenses("SA23Generator")
self.remove_air_defenses("SA17Generator")
self.remove_air_defenses("KS19Generator")
self.remove_air_defenses("SA-10B/S-300PS Battery")
self.remove_air_defenses("SA-12/S-300V Battery")
self.remove_air_defenses("SA-20/S-300PMU-1 Battery")
self.remove_air_defenses("SA-20B/S-300PMU-2 Battery")
self.remove_air_defenses("SA-23/S-300VM Battery")
self.remove_air_defenses("SA-17 Grizzly Battery")
self.remove_air_defenses("KS-19 AAA Site")
return self
def remove_aircraft(self, name: str) -> None: