Decoupling and generalization of templates

Improvement for factions and templates which will allow decoupling of the templates from the actual units
- Implement UnitGroup class which matches unit_types and possible templates as the needed abstraction layer for decoupling.
- Refactor UnitType, Add ShipUnitType and all ships we currently use
- Remove serialized template.json and migrated to multiple yaml templates (one for each template) and multiple .miz
- Reorganized a lot of templates and started with generalization of many types (AAA, Flak, SHORAD, Navy)
- Fixed a lot of bugs from the previous reworks (group name generation, strike targets...)
- Reorganized the faction file completly. removed redundant lists, added presets for complex groups / families of units like sams
- Reworked the building template handling. Some templates are unused like "village"
- Reworked how groups from templates can be merged again for the dcs group creation (e.g. the skynet plugin requires them to be in the same group)
- Allow to define alternative tasks
This commit is contained in:
RndName
2022-01-29 00:42:58 +01:00
parent daf4704fe7
commit 60c8c80480
27 changed files with 1481 additions and 958 deletions

View File

@@ -15,7 +15,7 @@ class BaiIngressBuilder(PydcsWaypointBuilder):
target = self.package.target
if isinstance(target, TheaterGroundObject):
for group in target.groups:
group_names.append(group.name)
group_names.append(group.group_name)
elif isinstance(target, MultiGroupTransport):
group_names.append(target.name)
elif isinstance(target, NavalControlPoint):

View File

@@ -20,9 +20,11 @@ class DeadIngressBuilder(PydcsWaypointBuilder):
return
for group in target.groups:
miz_group = self.mission.find_group(group.name)
miz_group = self.mission.find_group(group.group_name)
if miz_group is None:
logging.error(f"Could not find group for DEAD mission {group.name}")
logging.error(
f"Could not find group for DEAD mission {group.group_name}"
)
continue
task = AttackGroup(miz_group.id, weapon_type=WeaponType.Auto)

View File

@@ -20,9 +20,11 @@ class SeadIngressBuilder(PydcsWaypointBuilder):
return
for group in target.groups:
miz_group = self.mission.find_group(group.name)
miz_group = self.mission.find_group(group.group_name)
if miz_group is None:
logging.error(f"Could not find group for SEAD mission {group.name}")
logging.error(
f"Could not find group for SEAD mission {group.group_name}"
)
continue
task = AttackGroup(miz_group.id, weapon_type=WeaponType.Guided)

View File

@@ -28,7 +28,7 @@ from dcs.triggers import Event, TriggerOnce
from dcs.unit import Vehicle, Skill
from dcs.unitgroup import VehicleGroup
from game.data.groundunitclass import GroundUnitClass
from game.data.units import UnitClass
from game.dcs.aircrafttype import AircraftType
from game.dcs.groundunittype import GroundUnitType
from game.theater.controlpoint import ControlPoint
@@ -221,7 +221,7 @@ class FlotGenerator:
if self.game.settings.manpads:
# 50% of armored units protected by manpad
if random.choice([True, False]):
manpads = list(faction.infantry_with_class(GroundUnitClass.Manpads))
manpads = list(faction.infantry_with_class(UnitClass.Manpad))
if manpads:
u = random.choices(
manpads, weights=[m.spawn_weight for m in manpads]
@@ -237,12 +237,10 @@ class FlotGenerator:
)
return
possible_infantry_units = set(
faction.infantry_with_class(GroundUnitClass.Infantry)
)
possible_infantry_units = set(faction.infantry_with_class(UnitClass.Infantry))
if self.game.settings.manpads:
possible_infantry_units |= set(
faction.infantry_with_class(GroundUnitClass.Manpads)
faction.infantry_with_class(UnitClass.Manpad)
)
if not possible_infantry_units:
return

View File

@@ -118,7 +118,7 @@ class LuaGenerator:
faction = "BlueAA" if cp.captured else "RedAA"
lua_data[faction][g.name] = {
lua_data[faction][g.group_name] = {
"name": ground_object.name,
"range": threat_range.meters,
"position": {

View File

@@ -22,7 +22,6 @@ from typing import (
TypeVar,
List,
Any,
Union,
)
from dcs import Mission, Point, unitgroup
@@ -110,108 +109,93 @@ class GroundObjectGenerator:
logging.warning(f"Found empty group in {self.ground_object}")
continue
group_name = group.group_name if unique_name else group.name
if group.static_group:
# Static Group
for i, u in enumerate(group.units):
if isinstance(u, SceneryGroundUnit):
# Special handling for scenery objects:
# Only create a trigger zone and no "real" dcs unit
self.add_trigger_zone_for_scenery(u)
continue
moving_group: Optional[MovingGroup[Any]] = None
for i, unit in enumerate(group.units):
if isinstance(unit, SceneryGroundUnit):
# Special handling for scenery objects:
# Only create a trigger zone and no "real" dcs unit
self.add_trigger_zone_for_scenery(unit)
continue
# Only skip dead units after trigger zone for scenery created!
if not u.alive:
continue
# Only skip dead units after trigger zone for scenery created!
if not unit.alive:
continue
unit_type = unit_type_from_name(u.type)
if not unit_type:
raise RuntimeError(
f"Unit type {u.type} is not a valid dcs unit type"
)
sg = self.m.static_group(
country=self.country,
name=u.unit_name if unique_name else u.name,
_type=unit_type,
position=u.position,
heading=u.position.heading.degrees,
dead=not u.alive,
unit_type = unit_type_from_name(unit.type)
if not unit_type:
raise RuntimeError(
f"Unit type {unit.type} is not a valid dcs unit type"
)
self._register_ground_unit(u, sg.units[0])
else:
# Moving Group
moving_group: Optional[MovingGroup[Any]] = None
for i, unit in enumerate(group.units):
if not unit.alive:
continue
if unit.type in vehicle_map:
# Vehicle Group
unit_type = vehicle_map[unit.type]
elif unit.type in ship_map:
# Ship Group
unit_type = ship_map[group.units[0].type]
else:
raise RuntimeError(
f"Unit type {unit.type} is not a valid dcs unit type"
)
unit_name = unit.unit_name if unique_name else unit.name
if moving_group is None:
# First unit of the group will create the dcs group
if issubclass(unit_type, VehicleType):
moving_group = self.m.vehicle_group(
self.country,
group_name,
unit_type,
position=unit.position,
heading=unit.position.heading.degrees,
)
moving_group.units[0].player_can_drive = True
self.enable_eplrs(moving_group, unit_type)
if issubclass(unit_type, ShipType):
moving_group = self.m.ship_group(
self.country,
group_name,
unit_type,
position=unit.position,
heading=unit.position.heading.degrees,
)
if moving_group:
moving_group.units[0].name = unit_name
self.set_alarm_state(moving_group)
self._register_ground_unit(unit, moving_group.units[0])
else:
raise RuntimeError("DCS Group creation failed")
unit_name = unit.unit_name if unique_name else unit.name
if moving_group is None or group.static_group:
# First unit of the group will create the dcs group
if issubclass(unit_type, VehicleType):
moving_group = self.m.vehicle_group(
self.country,
group_name,
unit_type,
position=unit.position,
heading=unit.position.heading.degrees,
)
moving_group.units[0].player_can_drive = True
self.enable_eplrs(moving_group, unit_type)
elif issubclass(unit_type, ShipType):
moving_group = self.m.ship_group(
self.country,
group_name,
unit_type,
position=unit.position,
heading=unit.position.heading.degrees,
)
elif issubclass(unit_type, StaticType):
static_group = self.m.static_group(
country=self.country,
name=unit_name,
_type=unit_type,
position=unit.position,
heading=unit.position.heading.degrees,
dead=not unit.alive,
)
self._register_ground_unit(unit, static_group.units[0])
continue
if moving_group:
moving_group.units[0].name = unit_name
self.set_alarm_state(moving_group)
self._register_ground_unit(unit, moving_group.units[0])
else:
# Additional Units in the group
dcs_unit: Optional[Unit] = None
if issubclass(unit_type, VehicleType):
dcs_unit = Vehicle(
self.m.next_unit_id(),
unit_name,
unit.type,
)
dcs_unit.player_can_drive = True
elif issubclass(unit_type, ShipType):
dcs_unit = Ship(
self.m.next_unit_id(),
unit_name,
unit_type,
)
if dcs_unit:
dcs_unit.position = unit.position
dcs_unit.heading = unit.position.heading.degrees
moving_group.add_unit(dcs_unit)
self._register_ground_unit(unit, dcs_unit)
else:
raise RuntimeError("DCS Unit creation failed")
raise RuntimeError("DCS Group creation failed")
else:
# Additional Units in the group
dcs_unit: Optional[Unit] = None
if issubclass(unit_type, VehicleType):
dcs_unit = Vehicle(
self.m.next_unit_id(),
unit_name,
unit.type,
)
dcs_unit.player_can_drive = True
elif issubclass(unit_type, ShipType):
dcs_unit = Ship(
self.m.next_unit_id(),
unit_name,
unit_type,
)
if dcs_unit:
dcs_unit.position = unit.position
dcs_unit.heading = unit.position.heading.degrees
moving_group.add_unit(dcs_unit)
self._register_ground_unit(unit, dcs_unit)
else:
raise RuntimeError("DCS Unit creation failed")
@staticmethod
def enable_eplrs(group: VehicleGroup, unit_type: Type[VehicleType]) -> None:
if unit_type.eplrs:
group.points[0].tasks.append(EPLRS(group.id))
def set_alarm_state(self, group: Union[ShipGroup, VehicleGroup]) -> None:
def set_alarm_state(self, group: MovingGroup[Any]) -> None:
if self.game.settings.perf_red_alert_state:
group.points[0].tasks.append(OptAlarmState(2))
else:
@@ -287,7 +271,7 @@ class MissileSiteGenerator(GroundObjectGenerator):
# TODO : Should be pre-planned ?
# TODO : Add delay to task to spread fire task over mission duration ?
for group in self.ground_object.groups:
vg = self.m.find_group(group.name)
vg = self.m.find_group(group.group_name)
if vg is not None:
targets = self.possible_missile_targets()
if targets:
@@ -327,7 +311,7 @@ class MissileSiteGenerator(GroundObjectGenerator):
"""
site_range = 0
for group in self.ground_object.groups:
vg = self.m.find_group(group.name)
vg = self.m.find_group(group.group_name)
if vg is not None:
for u in vg.units:
if u.type in vehicle_map:
@@ -383,7 +367,7 @@ class GenericCarrierGenerator(GroundObjectGenerator):
ship_group = self.m.ship_group(
self.country,
group.name,
group.group_name if unique_name else group.name,
unit_type,
position=group.units[0].position,
heading=group.units[0].position.heading.degrees,
@@ -523,23 +507,20 @@ class CarrierGenerator(GenericCarrierGenerator):
def tacan_callsign(self) -> str:
# TODO: Assign these properly.
if self.control_point.name == "Carrier Strike Group 8":
return "TRU"
else:
return random.choice(
[
"STE",
"CVN",
"CVH",
"CCV",
"ACC",
"ARC",
"GER",
"ABR",
"LIN",
"TRU",
]
)
return random.choice(
[
"STE",
"CVN",
"CVH",
"CCV",
"ACC",
"ARC",
"GER",
"ABR",
"LIN",
"TRU",
]
)
class LhaGenerator(GenericCarrierGenerator):