diff --git a/doc/templates/ground_object_buy_menu.png b/doc/templates/ground_object_buy_menu.png
new file mode 100644
index 00000000..57f6d519
Binary files /dev/null and b/doc/templates/ground_object_buy_menu.png differ
diff --git a/doc/templates/template_list.md b/doc/templates/template_list.md
new file mode 100644
index 00000000..d2d6d801
--- /dev/null
+++ b/doc/templates/template_list.md
@@ -0,0 +1,56 @@
+| Role | Tasks | Template Name | Units |
+|---------------|------------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| AntiAir | AAA | AAA Site |
- Classes = [ AAA]
- Classes = [ Logistics]
|
+| AntiAir | AAA | AAA Mobile | - Classes = [ AAA]
- Classes = [ Logistics]
|
+| AntiAir | AAA | AAA Radar Site | - Classes = [ SearchRadar]
- Classes = [ AAA]
- Classes = [ Logistics]
|
+| AntiAir | AAA | Cold War Flak Site | - Classes = [ SearchRadar]
- 8.8 cm Flak 18
- S-60 57mm
- Classes = [ AAA]
- Classes = [ Logistics]
|
+| AntiAir | AAA | Flak Site | - 2 cm Flakvierling 38, 8.8 cm Flak 18, 8.8 cm Flak 36, 8.8 cm Flak 37, 8.8 cm Flak 41, 2 cm Flak 38
- 2 cm Flakvierling 38
- 8.8 cm Flak 36
- SL Flakscheinwerfer 37
- PU Maschinensatz_33
- AAA SP Kdo.G.40
- LUV Kubelwagen 82
- Truck Opel Blitz
|
+| AntiAir | AAA | WW2 Flak Site | - 8.8 cm Flak 18
- Truck Opel Blitz
|
+| AntiAir | AAA | WW2 Ally Flak Site | - QF 3.7-inch AA Gun
- M1 37mm Gun
- M45 Quadmount
- Willys Jeep
- M30 Cargo Carrier
- M4 High-Speed Tractor
- Truck Bedford
|
+| AntiAir | MERAD | Hawk Site | - SAM Hawk SR (AN/MPQ-50)
- SAM Hawk Platoon Command Post (PCP)
- SAM Hawk TR (AN/MPQ-46)
- SAM Hawk LN M192
- M163 Vulcan Air Defense System
|
+| AntiAir | MERAD | SA-2/S-75 Site | - SAM P19 "Flat Face" SR (SA-2/3)
- SAM SA-2 S-75 "Fan Song" TR
- SAM SA-2 S-75 "Guideline" LN
|
+| AntiAir | MERAD | SA-3/S-125 Site | - SAM P19 "Flat Face" SR (SA-2/3)
- SAM SA-3 S-125 "Low Blow" TR
- SAM SA-3 S-125 "Goa" LN
|
+| AntiAir | MERAD | SA-6 Kub Site | - SAM SA-6 Kub "Straight Flush" STR
- SAM SA-6 Kub "Gainful" TEL
|
+| AntiAir | MERAD | SA-11 Buk Battery | - SAM SA-11 Buk "Gadfly" Snow Drift SR
- SAM SA-11 Buk "Gadfly" C2
- SAM SA-11 Buk "Gadfly" Fire Dome TEL
|
+| AntiAir | MERAD | SA-17 Grizzly Battery | - SAM SA-11 Buk "Gadfly" Snow Drift SR
- SAM SA-11 Buk "Gadfly" C2
- SAM SA-17 Buk M1-2 LN 9A310M1-2
|
+| AntiAir | MERAD | NASAMS AIM-120B | - SAM NASAMS SR MPQ64F1
- SAM NASAMS C2
- SAM NASAMS LN AIM-120B
|
+| AntiAir | MERAD | NASAMS AIM-120C | - SAM NASAMS SR MPQ64F1
- SAM NASAMS C2
- SAM NASAMS LN AIM-120C
|
+| AntiAir | SHORAD | Rapier AA Site | - SAM Rapier Blindfire TR
- SAM Rapier Tracker
- SAM Rapier LN
|
+| AntiAir | SHORAD | Roland Site | - SAM Roland EWR
- Roland 2 (Marder Chassis)
- Truck M818 6x6
|
+| AntiAir | SHORAD | HQ-7 Site | - HQ-7 Self-Propelled STR
- HQ-7 Launcher
- ZU-23 on Ural-375
|
+| AntiAir | SHORAD | Freya EWR Site | - EWR FuMG-401 Freya LZ
- 2 cm Flakvierling 38
- 8.8 cm Flak 18
- LUV Kubelwagen 82
- Sd.Kfz.7 Tractor
- LUV Kettenrad
- PU Maschinensatz_33
- AAA SP Kdo.G.40
- Infantry Mauser 98
|
+| AntiAir | SHORAD | Short Range Anti Air Group | - Classes = [ SHORAD]
- Classes = [ Logistics]
|
+| AntiAir | LORAD | Patriot Battery | - SAM Patriot STR
- SAM Patriot CR (AMG AN/MRC-137)
- SAM Patriot ECS
- SAM Patriot C2 ICC
- SAM Patriot EPP-III
- SAM Patriot LN
- Classes = [ AAA]
- Classes = [ SHORAD]
|
+| AntiAir | LORAD | SA-5/S-200 Site | - SAM SA-5 S-200 ST-68U "Tin Shield" SR
- SAM SA-5 S-200 "Square Pair" TR"
- Truck Ural-375
- SAM SA-5 S-200 "Gammon" LN"
|
+| AntiAir | LORAD | SA-12/S-300V Battery | - SAM SA-12 S-300V 9S15 SR
- SAM SA-12 S-300V 9S19 SR
- SAM SA-12 S-300V 9S457 CP
- SAM SA-12 S-300V 9S32 TR
- SAM SA-12 S-300V 9A82 LN
- SAM SA-12 S-300V 9A83 LN
- SA-19 Grison (2K22 Tunguska)
- SA-15 Tor
|
+| AntiAir | LORAD | SA-20/S-300PMU-1 Battery | - SAM SA-20 S-300PMU1 SR 5N66E
- SAM SA-20 S-300PMU1 SR 64N6E
- SAM SA-20 S-300PMU1 CP 54K6
- SAM SA-20 S-300PMU1 TR 30N6E
- SAM SA-20 S-300PMU1 LN 5P85CE
- SAM SA-20 S-300PMU1 LN 5P85DE
- SA-19 Grison (2K22 Tunguska)
- SA-15 Tor
|
+| AntiAir | LORAD | SA-20B/S-300PMU-2 Battery | - SAM SA-20 S-300PMU1 SR 5N66E
- SAM SA-20 S-300PMU1 SR 64N6E
- SAM SA-20B S-300PMU2 CP 54K6E2
- SAM SA-20B S-300PMU2 TR 92H6E(truck)
- SAM SA-20B S-300PMU2 LN 5P85SE2
- SA-19 Grison (2K22 Tunguska)
- SA-15 Tor
|
+| AntiAir | LORAD | SA-23/S-300VM Battery | - SAM SA-23 S-300VM 9S15M2 SR
- SAM SA-23 S-300VM 9S19M2 SR
- SAM SA-23 S-300VM 9S457ME CP
- SAM SA-23 S-300VM 9S32ME TR
- SAM SA-23 S-300VM 9A82ME LN
- SAM SA-23 S-300VM 9A83ME LN
- SA-19 Grison (2K22 Tunguska)
- SA-15 Tor
|
+| AntiAir | LORAD | SA-10/S-300PS Battery | - SAM SA-10 S-300 "Grumble" Clam Shell SR
- SAM SA-10 S-300 "Grumble" Big Bird SR
- SAM SA-10 S-300 "Grumble" C2
- SAM SA-10 S-300 "Grumble" Flap Lid TR
- SAM SA-10 S-300 "Grumble" TEL D
- SAM SA-10 S-300 "Grumble" TEL C
- Classes = [ AAA]
- Classes = [ SHORAD]
|
+| AntiAir | EarlyWarningRadar | Early-Warning Radar | - Classes = [ EarlyWarningRadar]
|
+| Building | StrikeTarget | ww2bunker1 | - Siegfried Line
- Fire Control Bunker
|
+| Building | StrikeTarget | allycamp1 | - FARP Tent
- Haystack 4
- Haystack 3
- Concertina wire
|
+| Building | StrikeTarget | fuel1 | |
+| Building | StrikeTarget | ware1 | |
+| Building | StrikeTarget | farp1 | - FARP Tent
- FARP Ammo Dump Coating
- FARP CP Blindage
- FARP Fuel Depot
|
+| Building | StrikeTarget | derrick1 | - Oil derrick
- Pump station
- Subsidiary structure 2
|
+| Building | StrikeTarget | village1 | - Small house 1A
- Small werehouse 1
- Small house 1B
|
+| Building | StrikeTarget | ww2bunker2 | - Fire Control Bunker
- Siegfried Line
- Concertina wire
- Belgian gate
- Czech hedgehogs 1
|
+| Building | Ammo | ammo1 | - .Ammunition depot
- Hangar B
|
+| Building | StrikeTarget, Comms | comms | |
+| Building | Oil | oil1 | |
+| Building | FOB | fob1 | - .Command Center
- Barracks 2
- Garage small B
|
+| Building | StrikeTarget, Power | power1 | - Repair workshop
- Workshop A
- Garage B
- Farm B
|
+| Building | Factory | factory1 | - Tech combine
- Tech hangar A
|
+| Defenses | Missile | Missile | - Classes = [ Missile]
- Classes = [ Logistics]
- Classes = [ AAA]
- Classes = [ SHORAD]
|
+| Defenses | Coastal | Silkworm | - Classes = [ SearchRadar]
- Classes = [ Missile]
- Classes = [ Logistics]
- Classes = [ AAA]
- Classes = [ SHORAD]
|
+| GroundForce | BaseDefense, FrontLine | Armor Group | - Classes = [ APC, ATGM, IFV, Tank]
|
+| GroundForce | BaseDefense, FrontLine | Armor Group with Anti-Air | - Classes = [ APC, ATGM, IFV, Tank]
- Classes = [ AAA, SHORAD, Manpad]
|
+| Naval | Navy | WW2 LST Group | |
+| Naval | Navy | Russian Navy | - Corvette 1124.4 Grish, Corvette 1241.1 Molniya
- Frigate 11540 Neustrashimy, Frigate 1135M Rezky
- Cruiser 1164 Moskva
|
+| Naval | Navy | Chinese Navy | - Type 054A Frigate
- Type 052C Destroyer, Type 052B Destroyer
|
+| Naval | Navy | Naval Two Ship | - Classes = [ Destroyer, Cruiser, Boat, Submarine, LandingShip]
|
+| Naval | AircraftCarrier | Carrier Group | - Classes = [ AircraftCarrier]
- Classes = [ Destroyer]
|
+| Naval | AircraftCarrier | Carrier Strike Group 8 | - CVN-74 John C. Stennis
- DDG Arleigh Burke IIa
- CG Ticonderoga
|
+| Naval | HelicopterCarrier | LHA Group | - Classes = [ HelicopterCarrier]
- Classes = [ Destroyer]
|
+| Missing Units | SK_C_28_naval_gun, house2arm | | |
\ No newline at end of file
diff --git a/doc/templates/template_miz_example.png b/doc/templates/template_miz_example.png
new file mode 100644
index 00000000..e227e726
Binary files /dev/null and b/doc/templates/template_miz_example.png differ
diff --git a/doc/templates/template_overview.png b/doc/templates/template_overview.png
new file mode 100644
index 00000000..21ece57d
Binary files /dev/null and b/doc/templates/template_overview.png differ
diff --git a/doc/templates/templates.md b/doc/templates/templates.md
new file mode 100644
index 00000000..4685c572
--- /dev/null
+++ b/doc/templates/templates.md
@@ -0,0 +1,202 @@
+# The Template System
+
+The Template System is a complete rework of the generator-based logic to build theater-ground-objects (Liberation Objects).
+In the original system the generator was written in python and generated a group with a defined and static logic, written in code.
+The template sytem will now decouple the alignment / positioning from units and the definition of theire actual type (like Ural-375).
+The template system allows to define the layout and set which unit types or classes (All logistic units for example) are able to fit into the template.
+Ultimately this will allow to have generalized templates which can be reused by multiple types of units. Best example is the definition of a SAM layout.
+Previously we had a generator for every different SAM Site, now we can just reuse the alignemnt (e.g. 6 Launchers in a circle alignment) with more generalization.
+
+This also allows Users and Designers to easily create or modify templates as the new templates are defined with the DCS Mission editor and an additional .yaml file which provides mapping information.
+In total the new system reduces the complexity and allows to precisely align / orient units as needed and create realistic looking ground units.
+As the whole ground unit generation and handling was reworked it is now also possible to add static units to a ground object, so even Fortifcation or similar can be added to templates in the future.
+
+
+## General Concept
+
+
+
+
+TODO: Describe the general flow of the Template system
+
+TODO Lifecycle:
+The template will be automatically validated on campaign generation against the player and enemy factions.
+If the factions support the template (based on the unit_types and unit_classes) then it will be added to the game.
+If a faction does not support a group from the template it will be removed if optional == True otherwise the complete template will be marked as unsupported and will not be used for the game.
+During campaign initialization the start_generator will request unit_groups for the preset locations defined by the campaign designer. The faction will then offer possible groups and the matching template.
+The Liberation Group (TheaterGroundObject) is then being generated from this UnitGroup.
+
+- GroundWar currently does **not** use the template system
+- User can buy new SAM or ArmorGroup using this template system
+
+
+Example for a customized Ground Object Buy Menu which makes use of Templates and UnitGroups:
+
+
+### The template miz
+
+*Important*: Every unit_type has to be in a separate Group for the template to work.
+The template system merges the groups back together later with the group_id property (defaults to 1 which means that all groups in the template will be merged to group 1)
+
+The function of the miz is to have the positioning and alignment of all the units within the template. Coordinates and headings will be used for the generated group.
+
+Unit Count per group has to be the amount set with the unit_count property.
+
+During template generation the system will go through all possible units and will assign the respective unit_type to the units up to the maximum allow unit_count from the mapping.
+
+
+
+### The template yaml
+
+Possible Information:
+
+| Property | Type | Required | Description | Example |
+|---------------|-----------------------|----------|----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
+| Name | (str) | Yes | A name to identify the template | `name: Armor Group` |
+| Role | (GroupRole) | Yes | The role which the template should fit in | `role: AntiAir` or `role: GroundForce` |
+| Tasks | (list of GroupTask) | Yes | A list of tasks which the template can fullfill | `tasks: - AAA - SHORAD` |
+| Generic | (bool, default False) | No | If this is true this template will be used to create general unitGroups | |
+| Description | (str) | No | Short description of the template | |
+| category | (str) | No | Only used for building templates to identify the type of the building | `category: ammo` |
+| Groups | (list of Groups) | Yes | see below for definition of a group | |
+| template_file | (str) | No | the .miz file which has the template included. Only needed if the file has a different name than the yaml file | `template_file: resources/templates/anti_air/legacy_ground_templates.miz` |
+
+Groups within the template are defined as following:
+
+| Property | Type | Required | Description | Example |
+|--------------|------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
+| name | (str) | Yes | The group name used in the .miz. Must match exactly! | |
+| optional | (bool, default: False) | No | Defines wether the template can be used without this group if the faction has no access to the unit type or the user wants to disable this group | |
+| group | (int, default: 1) | No | The ID of the group which the templategroup will be merged into | |
+| unit_count | (list of int) | No | Amount of units to be generated for this group. Can be fixed or a range where it will be picked randomly | |
+| unit_types | (list dcs unit types) | No | Specific unit_types for ground units. Complete list from pydcs: [Vehicles.py](https://github.com/pydcs/dcs/blob/master/dcs/vehicles.py). This list is extended by all supported mods! | |
+| unit_classes | (list unit classes) | No | Unit_classes of supported units. Defined in [UnitClass](/game/data/units.py) | |
+| statics | (list static types) | No | Specific unit_types of statics. Complete list from pydcs: [Statics.py](https://github.com/pydcs/dcs/blob/master/dcs/statics.py) | |
+
+Complete example of a generic template for AAA Groups:
+
+```
+name: AAA Site
+description: A standard AAA template
+generic: true
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: AAA Site 0
+ group: 1
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - AAA
+ - name: AAA Site 1
+ optional: true
+ group: 1
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/AAA.miz
+```
+
+### Roles, Tasks and Classes
+TODO Improve Naming? Same logic as with the Squadrons.. Also brainstorm if we should rename the UnitGroup which basicly is the equivalent of a "Package"
+
+Role and Tasking
+
+[GroupRole and GroupTask](/game/data/groups.py)
+
+[UnitClass](/game/data/units.py)
+
+## How to add / modify a template
+
+template.miz (positioning / alignment) and template.yaml (Mapping)
+
+Best practice:
+- Copy existing Template and rename the files
+- Adjust the .miz and change the group names accordingly
+- Adjust the .yaml file to the needs and check for the correct group names
+
+
+## Migration from Generators
+
+- All generators removed and migrated to templates
+- These templates will in the next step be generalized
+
+ TODO: Update the template_list.md with the changes in Role/Tasking
+
+[List of supported templates](template_list.md)
+
+
+### Updates for Factions
+
+With the rework there were also some changes to the faction file definitions. Older faction files can not be loaded anymore and have to be adopted to the new changes.
+During migration all default factions were automatically updated, so they will work out of the box.
+
+What was changed:
+- Removed the `ewrs` list. All EWRs are now defined in the list "air_defense_units".
+- Added the `air_defense_units` list. All units with the Role AntiAir can be defined here as [GroundUnitType](/game/dcs/groundunittype.py). All possible units are defined in [/resources/units/ground_units](/resources/units/ground_units)
+- Added `preset_groups`. This list allows to define Preset Groups (described above) like SAM Systems consisting of Launcher, SR, TR and so on instead of adding them each to "air_defense_units". The presets are defined in [/resources/units/unit_groups](/resources/units/unit_groups)
+- Migrated `air_defenses` to air_defense_units and preset_sets.
+- `Missiles` are migrated to GroundUnitTypes instead of Generator names (see air_defense_units for how to use)
+- Removed `cruisers`, `destroyers` and `naval_generators`. Migrated them to naval_units and preset_groups
+- added `naval_units` with the correct ship name found here [/resources/units/ships](/resources/units/ships)
+- `aircraft_carrier` and `helicopter_carrier` were moved to `naval_units` as well.
+
+Possible Preset Groups:
+
+TODO generate list with old generator name
+
+Possible EWRs:
+
+| Name in Faction file |
+|------------------------------------------------------|
+| EWR 1L13 |
+| EWR 55G6 |
+| MCC-SR Sborka "Dog Ear" SR |
+| SAM Roland EWR |
+| SAM P19 "Flat Face" SR (SA-2/3) |
+| SAM Patriot STR |
+| SAM SA-10 S-300 "Grumble" Big Bird SR |
+| SAM SA-11 Buk "Gadfly" Snow Drift SR |
+| SAM SA-6 Kub "Straight Flush" STR |
+| SAM Hawk SR (AN/MPQ-50) |
+| SAM SA-5 S-200 ST-68U "Tin Shield" SR |
+
+## Unit Groups
+
+- Sum up groups of different units which are used together (like a sam site).
+- UnitGroup allows to define this logical group and add this to the faction file.
+- UnitGroups can have preferred templates
+
+# Open Points
+
+- [x] Rework SAM Systems to unit_groups: migrated all `air_defense`
+- [ ] Review Naming of all classes and so on
+- [X] Improve UI Display Name for the new ShipUniType
+- [ ] Verify if the campaign will be generated the same as before
+- [x] Fix the generation of buildings
+- [ ] Verify the handling of buildings (ammo and factory for example work different.)
+- [X] Correct Missiles and Coastal (Counts?)
+- [X] Faction Group Count (Navy, Missile, Coastal).. used for?? For nothing! removed.
+- [x] Navy Generators -> Destroyers, Cruisers und Preset_groups Migration
+- [x] Fix & Generalize Navy Templates (wrong unit number)
+- [X] Fix Bug: Enemy Navy PLanes spawn at blue Carrier.
+- [x] Add Naming for all AircraftCarrier and HelicopterCarrier (whats with the SC updated ones?)
+- [X] Verfiy SuperCarrier Upgrade
+- [X] Special Handling for Carrier Strike Group 8 (was not even working before..) can now be added as preset group
+- [X] Validate that all Waypoints and taskings are correct and working (some use the group.name)
+- [ ] Verify that DEAD Flights are untouched from these changes.. They are missing a attack command
+- [ ] Finish Documentation
+- [ ] Naming of created groups -> It uses the template name currently which is not great
+- [x] Fix the Faction overview site not showing the newly added preset_groups and AA Units
+- [ ] Add missing classes to the units so that they can be used by the templates
+- [x] Replace BuyUi implementation from Template to "Preset" by using the available UnitGroups
+- [x] Fix Buy menu for Armor Groups.
+- [x] Fix Buy menu not allowing to change the amount when only one unit_type is available.
+- [x] Fix Group order is not correct (group2 is 0, group1 is 1 if dcs_group id for group2 is smaller)
+- [ ] Add generalized Templates for Lorad and Merad
+- [ ] Generalize all Templates
+
diff --git a/gen/group_generator.py b/gen/group_generator.py
deleted file mode 100644
index 58f287c0..00000000
--- a/gen/group_generator.py
+++ /dev/null
@@ -1,223 +0,0 @@
-from __future__ import annotations
-
-import logging
-import math
-import operator
-from collections.abc import Iterable
-from typing import Any, Generic, TYPE_CHECKING, Type, TypeVar, Iterator
-
-from dcs import unitgroup
-from dcs.mapping import Point
-from dcs.point import PointAction
-from dcs.unit import Ship, Unit, Vehicle
-from dcs.unitgroup import ShipGroup, VehicleGroup
-from dcs.unittype import ShipType, UnitType, VehicleType
-
-from game.dcs.groundunittype import GroundUnitType
-from game.factions.faction import Faction
-from game.theater import MissionTarget
-from game.theater.theatergroundobject import NavalGroundObject, TheaterGroundObject
-from game.utils import Heading
-
-if TYPE_CHECKING:
- from game.game import Game
-
-
-GroupT = TypeVar("GroupT", VehicleGroup, ShipGroup)
-UnitT = TypeVar("UnitT", bound=Unit)
-UnitTypeT = TypeVar("UnitTypeT", bound=Type[UnitType])
-TgoT = TypeVar("TgoT", bound=TheaterGroundObject)
-
-
-# TODO: Generate a group description rather than a pydcs group.
-# It appears that all of this work gets redone at miz generation time (see
-# groundobjectsgen for an example). We can do less work and include the data we
-# care about in the format we want if we just generate our own group description
-# types rather than pydcs groups.
-class GroupGenerator(Generic[GroupT, UnitT, UnitTypeT, TgoT]):
- def __init__(self, game: Game, ground_object: TgoT, group: GroupT) -> None:
- self.game = game
- self.go = ground_object
- self.position = ground_object.position
- self.heading: Heading = Heading.random()
- self.price = 0
- self.vg: GroupT = group
- self.auxiliary_groups: list[GroupT] = []
-
- def generate(self) -> None:
- raise NotImplementedError
-
- def get_generated_group(self) -> GroupT:
- return self.vg
-
- @property
- def groups(self) -> Iterator[GroupT]:
- yield self.vg
- yield from self.auxiliary_groups
-
- def add_unit(
- self,
- unit_type: UnitTypeT,
- name: str,
- pos_x: float,
- pos_y: float,
- heading: Heading,
- ) -> UnitT:
- return self.add_unit_to_group(
- self.vg, unit_type, name, Point(pos_x, pos_y), heading
- )
-
- def add_unit_to_group(
- self,
- group: GroupT,
- unit_type: UnitTypeT,
- name: str,
- position: Point,
- heading: Heading,
- ) -> UnitT:
- raise NotImplementedError
-
- def heading_to_conflict(self) -> Heading:
- # Heading for a Group to the enemy.
- # Should be the point between the nearest and the most distant conflict
- conflicts: dict[MissionTarget, float] = {}
-
- for conflict in self.game.theater.conflicts():
- conflicts[conflict] = conflict.distance_to(self.go)
-
- if len(conflicts) == 0:
- return self.heading
-
- closest_conflict = min(conflicts.items(), key=operator.itemgetter(1))[0]
- most_distant_conflict = max(conflicts.items(), key=operator.itemgetter(1))[0]
-
- conflict_center = Point(
- (closest_conflict.position.x + most_distant_conflict.position.x) / 2,
- (closest_conflict.position.y + most_distant_conflict.position.y) / 2,
- )
-
- return Heading.from_degrees(
- self.go.position.heading_between_point(conflict_center)
- )
-
-
-class VehicleGroupGenerator(
- Generic[TgoT], GroupGenerator[VehicleGroup, Vehicle, Type[VehicleType], TgoT]
-):
- def __init__(self, game: Game, ground_object: TgoT) -> None:
- super().__init__(
- game,
- ground_object,
- unitgroup.VehicleGroup(game.next_group_id(), ground_object.group_name),
- )
- wp = self.vg.add_waypoint(self.position, PointAction.OffRoad, 0)
- wp.ETA_locked = True
-
- def add_vehicle_group(self) -> VehicleGroup:
- gid = self.game.next_group_id()
- group = VehicleGroup(gid, f"{self.go.group_name} #{len(self.auxiliary_groups)}")
- self.auxiliary_groups.append(group)
- return group
-
- def generate(self) -> None:
- raise NotImplementedError
-
- def add_unit_to_group(
- self,
- group: VehicleGroup,
- unit_type: Type[VehicleType],
- name: str,
- position: Point,
- heading: Heading,
- ) -> Vehicle:
- unit = Vehicle(self.game.next_unit_id(), f"{group.name}|{name}", unit_type.id)
- unit.position = position
- unit.heading = heading.degrees
- group.add_unit(unit)
-
- # get price of unit to calculate the real price of the whole group
- try:
- ground_unit_type = next(GroundUnitType.for_dcs_type(unit_type))
- self.price += ground_unit_type.price
- except StopIteration:
- logging.error(f"Cannot get price for unit {unit_type.name}")
-
- return unit
-
- def get_circular_position(
- self, num_units: int, launcher_distance: int, coverage: int = 90
- ) -> Iterable[tuple[float, float, Heading]]:
- """
- Given a position on the map, array a group of units in a circle a uniform distance from the unit
- :param num_units:
- number of units to play on the circle
- :param launcher_distance:
- distance the units should be from the center unit
- :param coverage:
- 0-360
- :return:
- list of tuples representing each unit location
- [(pos_x, pos_y, heading), ...]
- """
- if coverage == 360:
- # one of the positions is shared :'(
- outer_offset = coverage / num_units
- else:
- outer_offset = coverage / (num_units - 1)
-
- positions = []
-
- if num_units % 2 == 0:
- current_offset = self.heading.degrees - ((coverage / (num_units - 1)) / 2)
- else:
- current_offset = self.heading.degrees
- current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
- for _ in range(1, num_units + 1):
- x: float = self.position.x + launcher_distance * math.cos(
- math.radians(current_offset)
- )
- y: float = self.position.y + launcher_distance * math.sin(
- math.radians(current_offset)
- )
- positions.append((x, y, Heading.from_degrees(current_offset)))
- current_offset += outer_offset
- return positions
-
-
-class ShipGroupGenerator(
- GroupGenerator[ShipGroup, Ship, Type[ShipType], NavalGroundObject]
-):
- """Abstract class for other ship generator classes"""
-
- def __init__(self, game: Game, ground_object: NavalGroundObject, faction: Faction):
- super().__init__(
- game,
- ground_object,
- unitgroup.ShipGroup(game.next_group_id(), ground_object.group_name),
- )
- self.faction = faction
- wp = self.vg.add_waypoint(self.position, 0)
- wp.ETA_locked = True
-
- def add_auxiliary_group(self) -> ShipGroup:
- gid = self.game.next_group_id()
- group = ShipGroup(gid, f"{self.go.group_name} #{len(self.auxiliary_groups)}")
- self.auxiliary_groups.append(group)
- return group
-
- def generate(self) -> None:
- raise NotImplementedError
-
- def add_unit_to_group(
- self,
- group: ShipGroup,
- unit_type: Type[ShipType],
- name: str,
- position: Point,
- heading: Heading,
- ) -> Ship:
- unit = Ship(self.game.next_unit_id(), f"{self.go.group_name}|{name}", unit_type)
- unit.position = position
- unit.heading = heading.degrees
- group.add_unit(unit)
- return unit
diff --git a/gen/to_remove/aaa_bofors.py b/gen/to_remove/aaa_bofors.py
deleted file mode 100644
index dfdfa9f3..00000000
--- a/gen/to_remove/aaa_bofors.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class BoforsGenerator(AirDefenseGroupGenerator):
- """
- This generate a Bofors flak artillery group
- """
-
- name = "Bofors AAA"
-
- def generate(self) -> None:
-
- index = 0
- for i in range(4):
- spacing_x = random.randint(10, 40)
- spacing_y = random.randint(10, 40)
- index = index + 1
- self.add_unit(
- AirDefence.Bofors40,
- "AAA#" + str(index),
- self.position.x + spacing_x * i,
- self.position.y + spacing_y * i,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_flak.py b/gen/to_remove/aaa_flak.py
deleted file mode 100644
index 6009923c..00000000
--- a/gen/to_remove/aaa_flak.py
+++ /dev/null
@@ -1,99 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from game.utils import Heading
-
-GFLAK = [
- AirDefence.Flak38,
- AirDefence.Flak18,
- AirDefence.Flak36,
- AirDefence.Flak37,
- AirDefence.Flak41,
- AirDefence.Flak30,
-]
-
-
-class FlakGenerator(AirDefenseGroupGenerator):
- """
- This generate a German flak artillery group
- """
-
- name = "Flak Site"
-
- def generate(self) -> None:
- index = 0
- mixed = random.choice([True, False])
- unit_type = random.choice(GFLAK)
-
- for i in range(4):
- index = index + 1
- spacing_x = random.randint(10, 40)
- spacing_y = random.randint(10, 40)
- self.add_unit(
- unit_type,
- "AAA#" + str(index),
- self.position.x + spacing_x * i + random.randint(1, 5),
- self.position.y + spacing_y * i + random.randint(1, 5),
- self.heading,
- )
-
- if mixed:
- unit_type = random.choice(GFLAK)
-
- # Search lights
- search_pos = self.get_circular_position(random.randint(2, 3), 80)
- for index, pos in enumerate(search_pos):
- self.add_unit(
- AirDefence.Flakscheinwerfer_37,
- "SearchLight#" + str(index),
- pos[0],
- pos[1],
- self.heading,
- )
-
- # Support
- self.add_unit(
- AirDefence.Maschinensatz_33,
- "MC33#",
- self.position.x - 20,
- self.position.y - 20,
- self.heading,
- )
- self.add_unit(
- AirDefence.KDO_Mod40,
- "KDO#",
- self.position.x - 25,
- self.position.y - 20,
- self.heading,
- )
-
- # Commander
- self.add_unit(
- Unarmed.Kubelwagen_82,
- "Kubel#",
- self.position.x - 35,
- self.position.y - 20,
- self.heading,
- )
-
- # Some Opel Blitz trucks
- index = 0
- for i in range(int(max(1, 2))):
- for j in range(int(max(1, 2))):
- index += 1
- self.add_unit(
- Unarmed.Blitz_36_6700A,
- "BLITZ#" + str(index),
- self.position.x + 125 + 15 * i + random.randint(1, 5),
- self.position.y + 15 * j + random.randint(1, 5),
- Heading.from_degrees(75),
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_flak18.py b/gen/to_remove/aaa_flak18.py
deleted file mode 100644
index 7668902f..00000000
--- a/gen/to_remove/aaa_flak18.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class Flak18Generator(AirDefenseGroupGenerator):
- """
- This generate a German flak artillery group using only free units, thus not requiring the WW2 asset pack
- """
-
- name = "WW2 Flak Site"
-
- def generate(self) -> None:
-
- spacing = random.randint(30, 60)
- index = 0
-
- for i in range(3):
- for j in range(2):
- index = index + 1
- self.add_unit(
- AirDefence.Flak18,
- "AAA#" + str(index),
- self.position.x + spacing * i + random.randint(1, 5),
- self.position.y + spacing * j + random.randint(1, 5),
- self.heading,
- )
-
- # Add a commander truck
- self.add_unit(
- Unarmed.Blitz_36_6700A,
- "Blitz#",
- self.position.x - 35,
- self.position.y - 20,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_ks19.py b/gen/to_remove/aaa_ks19.py
deleted file mode 100644
index 6c63cb9f..00000000
--- a/gen/to_remove/aaa_ks19.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import random
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from pydcs_extensions.highdigitsams import highdigitsams
-
-
-class KS19Generator(AirDefenseGroupGenerator):
- """
- This generate a KS 19 flak artillery group (KS-19 from the High Digit SAM mod)
- """
-
- name = "KS-19 AAA Site"
-
- def generate(self) -> None:
- self.add_unit(
- highdigitsams.AAA_SON_9_Fire_Can,
- "TR",
- self.position.x - 20,
- self.position.y - 20,
- self.heading,
- )
-
- index = 0
- for i in range(4):
- spacing_x = random.randint(10, 40)
- spacing_y = random.randint(10, 40)
- index = index + 1
- self.add_unit(
- highdigitsams.AAA_100mm_KS_19,
- "AAA#" + str(index),
- self.position.x + spacing_x * i,
- self.position.y + spacing_y * i,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_ww2_ally_flak.py b/gen/to_remove/aaa_ww2_ally_flak.py
deleted file mode 100644
index 9ca96c28..00000000
--- a/gen/to_remove/aaa_ww2_ally_flak.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from game.utils import Heading
-
-
-class AllyWW2FlakGenerator(AirDefenseGroupGenerator):
- """
- This generate an ally flak artillery group
- """
-
- name = "WW2 Ally Flak Site"
-
- def generate(self) -> None:
-
- positions = self.get_circular_position(4, launcher_distance=30, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.QF_37_AA,
- "AA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- positions = self.get_circular_position(8, launcher_distance=60, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.M1_37mm,
- "AA#" + str(4 + i),
- position[0],
- position[1],
- position[2],
- )
-
- positions = self.get_circular_position(8, launcher_distance=90, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.M45_Quadmount,
- "AA#" + str(12 + i),
- position[0],
- position[1],
- position[2],
- )
-
- # Add a commander truck
- self.add_unit(
- Unarmed.Willys_MB,
- "CMD#1",
- self.position.x,
- self.position.y - 20,
- Heading.random(),
- )
- self.add_unit(
- Unarmed.M30_CC,
- "LOG#1",
- self.position.x,
- self.position.y + 20,
- Heading.random(),
- )
- self.add_unit(
- Unarmed.M4_Tractor,
- "LOG#2",
- self.position.x + 20,
- self.position.y,
- Heading.random(),
- )
- self.add_unit(
- Unarmed.Bedford_MWD,
- "LOG#3",
- self.position.x - 20,
- self.position.y,
- Heading.random(),
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_zsu57.py b/gen/to_remove/aaa_zsu57.py
deleted file mode 100644
index c603d93b..00000000
--- a/gen/to_remove/aaa_zsu57.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZSU57Generator(AirDefenseGroupGenerator):
- """
- This generate a Zsu 57 group
- """
-
- name = "ZSU-57-2 Group"
-
- def generate(self) -> None:
- num_launchers = 4
- positions = self.get_circular_position(
- num_launchers, launcher_distance=110, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.ZSU_57_2,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/aaa_zu23_insurgent.py b/gen/to_remove/aaa_zu23_insurgent.py
deleted file mode 100644
index ac000e93..00000000
--- a/gen/to_remove/aaa_zu23_insurgent.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZU23InsurgentGenerator(AirDefenseGroupGenerator):
- """
- This generate a ZU23 insurgent flak artillery group
- """
-
- name = "Zu-23 Site"
-
- def generate(self) -> None:
- index = 0
- for i in range(4):
- index = index + 1
- spacing_x = random.randint(10, 40)
- spacing_y = random.randint(10, 40)
- self.add_unit(
- AirDefence.ZU_23_Closed_Insurgent,
- "AAA#" + str(index),
- self.position.x + spacing_x * i,
- self.position.y + spacing_y * i,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/airdefensegroupgenerator.py b/gen/to_remove/airdefensegroupgenerator.py
deleted file mode 100644
index 0a6d82bb..00000000
--- a/gen/to_remove/airdefensegroupgenerator.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from typing import Iterator, List
-
-from dcs.unitgroup import VehicleGroup
-
-from game import Game
-from game.theater.theatergroundobject import (
- SamGroundObject,
- SkynetRole,
- AirDefenseRange,
-)
-from gen.group_generator import VehicleGroupGenerator
-
-
-class AirDefenseGroupGenerator(VehicleGroupGenerator[SamGroundObject], ABC):
- """
- This is the base for all SAM group generators
- """
-
- def __init__(self, game: Game, ground_object: SamGroundObject) -> None:
- super().__init__(game, ground_object)
-
- self.vg.name = self.group_name_for_role(self.vg.id, self.primary_group_role())
- self.auxiliary_groups: List[VehicleGroup] = []
-
- def add_auxiliary_group(self, role: SkynetRole) -> VehicleGroup:
- gid = self.game.next_group_id()
- group = VehicleGroup(gid, self.group_name_for_role(gid, role))
- self.auxiliary_groups.append(group)
- return group
-
- def group_name_for_role(self, gid: int, role: SkynetRole) -> str:
- if role is SkynetRole.NoSkynetBehavior:
- # No special naming needed for air defense groups that don't participate in
- # Skynet.
- return f"{self.go.group_name}|{gid}"
-
- # For those that do, we need a prefix of `$COLOR|SAM| so our Skynet config picks
- # the group up at all. To support PDs we need to append the ID of the TGO so
- # that the PD will know which group it's protecting. We then append the role so
- # our config knows what to do with the group, and finally the GID of *this*
- # group to ensure no conflicts.
- return "|".join([self.go.faction_color, "SAM", role.value, str(gid)])
-
- def get_generated_group(self) -> VehicleGroup:
- raise RuntimeError(
- "Deprecated call to AirDefenseGroupGenerator.get_generated_group "
- "misses auxiliary groups. Use AirDefenseGroupGenerator.groups "
- "instead."
- )
-
- @property
- def groups(self) -> Iterator[VehicleGroup]:
- yield self.vg
- yield from self.auxiliary_groups
-
- @classmethod
- @abstractmethod
- def range(cls) -> AirDefenseRange:
- ...
-
- @classmethod
- def primary_group_role(cls) -> SkynetRole:
- return cls.range().default_role
diff --git a/gen/to_remove/armor_group_generator.py b/gen/to_remove/armor_group_generator.py
deleted file mode 100644
index 5dba3295..00000000
--- a/gen/to_remove/armor_group_generator.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import random
-from typing import Optional
-
-from dcs.unitgroup import VehicleGroup
-
-from game import Game
-from game.data.units import UnitClass
-from game.dcs.groundunittype import GroundUnitType
-from game.factions import FACTIONS
-from game.theater.theatergroundobject import VehicleGroupGroundObject
-from gen.to_remove.armored_group_generator import (
- ArmoredGroupGenerator,
- FixedSizeArmorGroupGenerator,
-)
-
-
-def generate_armor_group(
- faction: str, game: Game, ground_object: VehicleGroupGroundObject
-) -> Optional[VehicleGroup]:
- """
- This generate a group of ground units
- :return: Generated group
- """
- armor_types = (
- UnitClass.Apc,
- UnitClass.Atgm,
- UnitClass.Ifv,
- UnitClass.Tank,
- )
- possible_unit = [
- u for u in FACTIONS[faction].frontline_units if u.unit_class in armor_types
- ]
- if len(possible_unit) > 0:
- unit_type = random.choice(possible_unit)
- return generate_armor_group_of_type(game, ground_object, unit_type)
- return None
-
-
-def generate_armor_group_of_type(
- game: Game, ground_object: VehicleGroupGroundObject, unit_type: GroundUnitType
-) -> VehicleGroup:
- """
- This generate a group of ground units of given type
- :return: Generated group
- """
- generator = ArmoredGroupGenerator(game, ground_object, unit_type)
- generator.generate()
- return generator.get_generated_group()
-
-
-def generate_armor_group_of_type_and_size(
- game: Game,
- ground_object: VehicleGroupGroundObject,
- unit_type: GroundUnitType,
- size: int,
-) -> VehicleGroup:
- """
- This generate a group of ground units of given type and size
- :return: Generated group
- """
- generator = FixedSizeArmorGroupGenerator(game, ground_object, unit_type, size)
- generator.generate()
- return generator.get_generated_group()
diff --git a/gen/to_remove/armored_group_generator.py b/gen/to_remove/armored_group_generator.py
deleted file mode 100644
index 5eb734ca..00000000
--- a/gen/to_remove/armored_group_generator.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import random
-
-import dcs.vehicles
-from dcs import Point
-
-from game import Game
-from game.dcs.groundunittype import GroundUnitType
-from game.theater.theatergroundobject import VehicleGroupGroundObject
-from game.utils import Heading
-from gen.group_generator import VehicleGroupGenerator
-
-
-class ArmoredGroupGenerator(VehicleGroupGenerator[VehicleGroupGroundObject]):
- def __init__(
- self,
- game: Game,
- ground_object: VehicleGroupGroundObject,
- unit_type: GroundUnitType,
- ) -> None:
- super().__init__(game, ground_object)
- self.unit_type = unit_type
- self.heading = Heading.from_degrees(0)
-
- def generate(self) -> None:
- grid_x = random.randint(2, 3)
- grid_y = random.randint(1, 2)
-
- spacing = random.randint(30, 80)
-
- index = 0
- for i in range(grid_x):
- for j in range(grid_y):
- index = index + 1
- self.add_unit(
- self.unit_type.dcs_unit_type,
- "Armor#" + str(index),
- self.position.x + spacing * i,
- self.position.y + spacing * j,
- self.heading,
- )
-
-
-class FixedSizeArmorGroupGenerator(VehicleGroupGenerator[VehicleGroupGroundObject]):
- def __init__(
- self,
- game: Game,
- ground_object: VehicleGroupGroundObject,
- unit_type: GroundUnitType,
- size: int,
- ) -> None:
- super().__init__(game, ground_object)
- self.unit_type = unit_type
- self.size = size
- self.spacing = random.randint(20, 70)
- self.heading = Heading.from_degrees(0)
-
- def generate(self) -> None:
-
- index = 0
- for i in range(self.size):
- index = index + 1
- self.add_unit(
- self.unit_type.dcs_unit_type,
- "Armor#" + str(index),
- self.position.x + self.spacing * i,
- self.position.y,
- self.heading,
- )
-
-
-class FixedSizeArmorGroupGeneratorWithAA(FixedSizeArmorGroupGenerator):
- def generate(self) -> None:
- super(FixedSizeArmorGroupGeneratorWithAA, self).generate()
- aux_group = self.add_vehicle_group()
- index = 0
- for i in [1, 2]:
- index = index + 1
- self.add_unit_to_group(
- aux_group,
- dcs.vehicles.AirDefence.M6_Linebacker,
- "Anti Air#" + str(index),
- Point(self.position.x - self.spacing * i, self.position.y),
- self.heading,
- )
diff --git a/gen/to_remove/carrier_group.py b/gen/to_remove/carrier_group.py
deleted file mode 100644
index 8037086a..00000000
--- a/gen/to_remove/carrier_group.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import random
-
-import dcs.ships
-from dcs import Point
-
-from gen.group_generator import ShipGroupGenerator
-from game.utils import Heading
-
-from dcs.ships import USS_Arleigh_Burke_IIa, TICONDEROG
-
-
-class CarrierGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
- self.add_unit(
- dcs.ships.Stennis,
- "Carrier",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- aux_group = self.add_auxiliary_group()
- # Add destroyers escort
- dd_type = dcs.ships.USS_Arleigh_Burke_IIa
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD1",
- Point(self.position.x + 2500, self.position.y + 4500),
- self.heading,
- )
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD2",
- Point(self.position.x + 2500, self.position.y - 4500),
- self.heading,
- )
-
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD3",
- Point(self.position.x + 4500, self.position.y + 8500),
- self.heading,
- )
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD4",
- Point(self.position.x + 4500, self.position.y - 8500),
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
-
-
-class CarrierStrikeGroup8Generator(ShipGroupGenerator):
- def generate(self) -> None:
- # Carrier Strike Group 8
- carrier_type = dcs.ships.Stennis
-
- self.add_unit(
- carrier_type,
- "CVN-75 Harry S. Truman",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- aux_group = self.add_auxiliary_group()
-
- # Add Arleigh Burke escort
- self.add_unit_to_group(
- aux_group,
- USS_Arleigh_Burke_IIa,
- "USS Ramage",
- Point(self.position.x + 6482, self.position.y + 6667),
- self.heading,
- )
-
- self.add_unit_to_group(
- aux_group,
- USS_Arleigh_Burke_IIa,
- "USS Mitscher",
- Point(self.position.x - 7963, self.position.y + 7037),
- self.heading,
- )
-
- self.add_unit_to_group(
- aux_group,
- USS_Arleigh_Burke_IIa,
- "USS Forrest Sherman",
- Point(self.position.x - 7408, self.position.y - 7408),
- self.heading,
- )
-
- self.add_unit_to_group(
- aux_group,
- USS_Arleigh_Burke_IIa,
- "USS Lassen",
- Point(self.position.x + 8704, self.position.y - 6296),
- self.heading,
- )
-
- # Add Ticonderoga escort
- if self.heading >= Heading.from_degrees(180):
- self.add_unit_to_group(
- aux_group,
- TICONDEROG,
- "USS Hué City",
- Point(self.position.x + 2222, self.position.y - 3333),
- self.heading,
- )
- else:
- self.add_unit_to_group(
- aux_group,
- TICONDEROG,
- "USS Hué City",
- Point(self.position.x - 3333, self.position.y + 2222),
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
diff --git a/gen/to_remove/cn_dd_group.py b/gen/to_remove/cn_dd_group.py
deleted file mode 100644
index ce04e023..00000000
--- a/gen/to_remove/cn_dd_group.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from __future__ import annotations
-
-import random
-from typing import TYPE_CHECKING
-
-from dcs.ships import (
- Type_052C,
- Type_052B,
- Type_054A,
-)
-
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import ShipGroundObject
-from gen.to_remove.dd_group import DDGroupGenerator
-from gen.group_generator import ShipGroupGenerator
-
-if TYPE_CHECKING:
- from game.game import Game
-
-
-class ChineseNavyGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
- self.add_unit(
- Type_054A,
- "FF1",
- self.position.x + 1200,
- self.position.y + 900,
- self.heading,
- )
- self.add_unit(
- Type_054A,
- "FF2",
- self.position.x + 1200,
- self.position.y - 900,
- self.heading,
- )
- self.add_unit(
- Type_052C,
- "DD1",
- self.position.x + 2400,
- self.position.y + 900,
- self.heading,
- )
- self.add_unit(
- Type_052C,
- "DD2",
- self.position.x + 2400,
- self.position.y - 900,
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
-
-
-class Type54GroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(Type54GroupGenerator, self).__init__(
- game, ground_object, faction, Type_054A
- )
diff --git a/gen/to_remove/coastal_group_generator.py b/gen/to_remove/coastal_group_generator.py
deleted file mode 100644
index 26d8d4b0..00000000
--- a/gen/to_remove/coastal_group_generator.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import logging
-import random
-from typing import Optional
-
-from dcs.unitgroup import VehicleGroup
-
-from game import db, Game
-from game.theater.theatergroundobject import CoastalSiteGroundObject
-from gen.to_remove.silkworm import SilkwormGenerator
-
-COASTAL_MAP = {
- "SilkwormGenerator": SilkwormGenerator,
-}
diff --git a/gen/to_remove/cold_war_flak.py b/gen/to_remove/cold_war_flak.py
deleted file mode 100644
index 583be9dd..00000000
--- a/gen/to_remove/cold_war_flak.py
+++ /dev/null
@@ -1,153 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator):
- """
- This generator attempt to mimic an early cold-war era flak AAA site.
- The Flak 18 88mm is used as the main long range gun, S-60 is used as a mid range gun and 2 Bofors 40mm guns provide short range protection.
-
- This does not include search lights and telemeter computer (Kdo.G 40) because these are paid units only available in WW2 asset pack
- """
-
- name = "Early Cold War Flak Site"
-
- def generate(self) -> None:
-
- spacing = random.randint(30, 60)
- index = 0
-
- # Long range guns
- for i in range(3):
- for j in range(2):
- index = index + 1
- self.add_unit(
- AirDefence.Flak18,
- "AAA#" + str(index),
- self.position.x + spacing * i + random.randint(1, 5),
- self.position.y + spacing * j + random.randint(1, 5),
- self.heading,
- )
-
- # Medium range guns
- self.add_unit(
- AirDefence.S_60_Type59_Artillery,
- "SHO#1",
- self.position.x - 40,
- self.position.y - 40,
- self.heading.opposite,
- ),
- self.add_unit(
- AirDefence.S_60_Type59_Artillery,
- "SHO#2",
- self.position.x + spacing * 2 + 40,
- self.position.y + spacing + 40,
- self.heading,
- ),
-
- # Short range guns
- self.add_unit(
- AirDefence.ZU_23_Emplacement_Closed,
- "SHO#3",
- self.position.x - 80,
- self.position.y - 40,
- self.heading.opposite,
- ),
- self.add_unit(
- AirDefence.ZU_23_Emplacement_Closed,
- "SHO#4",
- self.position.x + spacing * 2 + 80,
- self.position.y + spacing + 40,
- self.heading,
- ),
-
- # Add a truck
- self.add_unit(
- Unarmed.KAMAZ_Truck,
- "Truck#",
- self.position.x - 60,
- self.position.y - 20,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
-
-
-class ColdWarFlakGenerator(AirDefenseGroupGenerator):
- """
- This generator attempt to mimic a cold-war era flak AAA site.
- The Flak 18 88mm is used as the main long range gun, 2 S-60 57mm gun improve mid range firepower, while 2 Zu-23 guns even provide short range protection.
- The site is also fitted with a P-19 radar for early detection.
- """
-
- name = "Cold War Flak Site"
-
- def generate(self) -> None:
-
- spacing = random.randint(30, 60)
- index = 0
-
- # Long range guns
- for i in range(3):
- for j in range(2):
- index = index + 1
- self.add_unit(
- AirDefence.Flak18,
- "AAA#" + str(index),
- self.position.x + spacing * i + random.randint(1, 5),
- self.position.y + spacing * j + random.randint(1, 5),
- self.heading,
- )
-
- # Medium range guns
- self.add_unit(
- AirDefence.S_60_Type59_Artillery,
- "SHO#1",
- self.position.x - 40,
- self.position.y - 40,
- self.heading.opposite,
- ),
- self.add_unit(
- AirDefence.S_60_Type59_Artillery,
- "SHO#2",
- self.position.x + spacing * 2 + 40,
- self.position.y + spacing + 40,
- self.heading,
- ),
-
- # Short range guns
- self.add_unit(
- AirDefence.ZU_23_Emplacement_Closed,
- "SHO#3",
- self.position.x - 80,
- self.position.y - 40,
- self.heading.opposite,
- ),
- self.add_unit(
- AirDefence.ZU_23_Emplacement_Closed,
- "SHO#4",
- self.position.x + spacing * 2 + 80,
- self.position.y + spacing + 40,
- self.heading,
- ),
-
- # Add a P19 Radar for EWR
- self.add_unit(
- AirDefence.P_19_s_125_sr,
- "SR#0",
- self.position.x - 60,
- self.position.y - 20,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/dd_group.py b/gen/to_remove/dd_group.py
deleted file mode 100644
index 2a1a11ab..00000000
--- a/gen/to_remove/dd_group.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Type
-
-from dcs.ships import PERRY, USS_Arleigh_Burke_IIa
-from dcs.unittype import ShipType
-
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import ShipGroundObject
-from gen.group_generator import ShipGroupGenerator
-
-if TYPE_CHECKING:
- from game.game import Game
-
-
-class DDGroupGenerator(ShipGroupGenerator):
- def __init__(
- self,
- game: Game,
- ground_object: ShipGroundObject,
- faction: Faction,
- ddtype: Type[ShipType],
- ):
- super(DDGroupGenerator, self).__init__(game, ground_object, faction)
- self.ddtype = ddtype
-
- def generate(self) -> None:
- self.add_unit(
- self.ddtype,
- "DD1",
- self.position.x + 500,
- self.position.y + 900,
- self.heading,
- )
- self.add_unit(
- self.ddtype,
- "DD2",
- self.position.x + 500,
- self.position.y - 900,
- self.heading,
- )
- self.get_generated_group().points[0].speed = 20
-
-
-class OliverHazardPerryGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(OliverHazardPerryGroupGenerator, self).__init__(
- game, ground_object, faction, PERRY
- )
-
-
-class ArleighBurkeGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(ArleighBurkeGroupGenerator, self).__init__(
- game, ground_object, faction, USS_Arleigh_Burke_IIa
- )
diff --git a/gen/to_remove/ewr_group_generator.py b/gen/to_remove/ewr_group_generator.py
deleted file mode 100644
index d7a83dd8..00000000
--- a/gen/to_remove/ewr_group_generator.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from gen.to_remove.ewrs import (
- BigBirdGenerator,
- BoxSpringGenerator,
- DogEarGenerator,
- FlatFaceGenerator,
- HawkEwrGenerator,
- PatriotEwrGenerator,
- RolandEwrGenerator,
- SnowDriftGenerator,
- StraightFlushGenerator,
- TallRackGenerator,
- TinShieldGenerator,
-)
-
-EWR_MAP = {
- "BoxSpringGenerator": BoxSpringGenerator,
- "TallRackGenerator": TallRackGenerator,
- "DogEarGenerator": DogEarGenerator,
- "RolandEwrGenerator": RolandEwrGenerator,
- "FlatFaceGenerator": FlatFaceGenerator,
- "PatriotEwrGenerator": PatriotEwrGenerator,
- "BigBirdGenerator": BigBirdGenerator,
- "SnowDriftGenerator": SnowDriftGenerator,
- "StraightFlushGenerator": StraightFlushGenerator,
- "HawkEwrGenerator": HawkEwrGenerator,
- "TinShieldGenerator": TinShieldGenerator,
-}
diff --git a/gen/to_remove/ewrs.py b/gen/to_remove/ewrs.py
deleted file mode 100644
index 8857880e..00000000
--- a/gen/to_remove/ewrs.py
+++ /dev/null
@@ -1,114 +0,0 @@
-from typing import Type
-
-from dcs.unittype import VehicleType
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import EwrGroundObject
-from gen.group_generator import VehicleGroupGenerator
-
-
-class EwrGenerator(VehicleGroupGenerator[EwrGroundObject]):
- unit_type: Type[VehicleType] = AirDefence.P_19_s_125_sr
-
- @classmethod
- def name(cls) -> str:
- return cls.unit_type.name
-
- def generate(self) -> None:
- self.add_unit(
- self.unit_type,
- "EWR",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
-
-class BoxSpringGenerator(EwrGenerator):
- """1L13 "Box Spring" EWR."""
-
- unit_type = AirDefence._1L13_EWR
-
-
-class TallRackGenerator(EwrGenerator):
- """55G6 "Tall Rack" EWR."""
-
- unit_type = AirDefence._55G6_EWR
-
-
-class DogEarGenerator(EwrGenerator):
- """9S80M1 "Dog Ear" EWR.
-
- This is the SA-8 search radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.Dog_Ear_radar
-
-
-class RolandEwrGenerator(EwrGenerator):
- """Roland EWR.
-
- This is the Roland search radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.Roland_Radar
-
-
-class FlatFaceGenerator(EwrGenerator):
- """P-19 "Flat Face" EWR.
-
- This is the SA-3 search radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.P_19_s_125_sr
-
-
-class PatriotEwrGenerator(EwrGenerator):
- """Patriot EWR.
-
- This is the Patriot search/track radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.Patriot_str
-
-
-class BigBirdGenerator(EwrGenerator):
- """64H6E "Big Bird" EWR.
-
- This is the SA-10 track radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.S_300PS_64H6E_sr
-
-
-class SnowDriftGenerator(EwrGenerator):
- """9S18M1 "Snow Drift" EWR.
-
- This is the SA-11 search radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.SA_11_Buk_SR_9S18M1
-
-
-class StraightFlushGenerator(EwrGenerator):
- """1S91 "Straight Flush" EWR.
-
- This is the SA-6 search/track radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.Kub_1S91_str
-
-
-class HawkEwrGenerator(EwrGenerator):
- """Hawk EWR.
-
- This is the Hawk search radar, but used as an early warning radar.
- """
-
- unit_type = AirDefence.Hawk_sr
-
-
-class TinShieldGenerator(EwrGenerator):
- """19ZH6 "Tin Shield" EWR."""
-
- unit_type = AirDefence.RLS_19J6
diff --git a/gen/to_remove/freya_ewr.py b/gen/to_remove/freya_ewr.py
deleted file mode 100644
index 26c4c911..00000000
--- a/gen/to_remove/freya_ewr.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from dcs.vehicles import AirDefence, Infantry, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from game.utils import Heading
-
-
-class FreyaGenerator(AirDefenseGroupGenerator):
- """
- This generate a German flak artillery group using only free units, thus not requiring the WW2 asset pack
- """
-
- name = "Freya EWR Site"
-
- def generate(self) -> None:
-
- # TODO : would be better with the Concrete structure that is supposed to protect it
- self.add_unit(
- AirDefence.FuMG_401,
- "EWR#1",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- positions = self.get_circular_position(4, launcher_distance=50, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Flak38,
- "AA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- positions = self.get_circular_position(4, launcher_distance=100, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Flak18,
- "AA#" + str(4 + i),
- position[0],
- position[1],
- position[2],
- )
-
- # Command/Logi
- self.add_unit(
- Unarmed.Kubelwagen_82,
- "Kubel#1",
- self.position.x - 20,
- self.position.y - 20,
- self.heading,
- )
- self.add_unit(
- Unarmed.Sd_Kfz_7,
- "Sdkfz#1",
- self.position.x + 20,
- self.position.y + 22,
- self.heading,
- )
- self.add_unit(
- Unarmed.Sd_Kfz_2,
- "Sdkfz#2",
- self.position.x - 22,
- self.position.y + 20,
- self.heading,
- )
-
- # Maschinensatz_33 and Kdo.g 40 Telemeter
- self.add_unit(
- AirDefence.Maschinensatz_33,
- "Energy#1",
- self.position.x + 20,
- self.position.y - 20,
- self.heading,
- )
- self.add_unit(
- AirDefence.KDO_Mod40,
- "Telemeter#1",
- self.position.x + 20,
- self.position.y - 10,
- self.heading,
- )
- self.add_unit(
- Infantry.Soldier_mauser98,
- "Inf#1",
- self.position.x + 20,
- self.position.y - 14,
- self.heading,
- )
- self.add_unit(
- Infantry.Soldier_mauser98,
- "Inf#2",
- self.position.x + 20,
- self.position.y - 22,
- self.heading,
- )
- self.add_unit(
- Infantry.Soldier_mauser98,
- "Inf#3",
- self.position.x + 20,
- self.position.y - 24,
- self.heading + Heading.from_degrees(45),
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/lacombattanteII.py b/gen/to_remove/lacombattanteII.py
deleted file mode 100644
index 53b529dd..00000000
--- a/gen/to_remove/lacombattanteII.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from dcs.ships import La_Combattante_II
-
-from game import Game
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import ShipGroundObject
-from gen.to_remove.dd_group import DDGroupGenerator
-
-
-class LaCombattanteIIGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(LaCombattanteIIGroupGenerator, self).__init__(
- game, ground_object, faction, La_Combattante_II
- )
diff --git a/gen/to_remove/lha_group.py b/gen/to_remove/lha_group.py
deleted file mode 100644
index 0719503f..00000000
--- a/gen/to_remove/lha_group.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import random
-
-import dcs.ships
-from dcs import Point
-
-from gen.group_generator import ShipGroupGenerator
-
-
-class LHAGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
-
- # Add carrier
- self.add_unit(
- dcs.ships.LHA_Tarawa,
- "LHA",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- # Add destroyers escort
- aux_group = self.add_auxiliary_group()
- dd_type = dcs.ships.USS_Arleigh_Burke_IIa
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD1",
- Point(self.position.x + 1250, self.position.y + 1450),
- self.heading,
- )
- self.add_unit_to_group(
- aux_group,
- dd_type,
- "DD2",
- Point(self.position.x + 1250, self.position.y - 1450),
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
diff --git a/gen/to_remove/missiles_group_generator.py b/gen/to_remove/missiles_group_generator.py
deleted file mode 100644
index ac5fafcc..00000000
--- a/gen/to_remove/missiles_group_generator.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import logging
-import random
-from typing import Optional
-
-from dcs.unitgroup import VehicleGroup
-
-from game import db, Game
-from game.theater.theatergroundobject import MissileSiteGroundObject
-from gen.to_remove.scud_site import ScudGenerator
-from gen.to_remove.v1_group import V1GroupGenerator
-
-MISSILES_MAP = {"V1GroupGenerator": V1GroupGenerator, "ScudGenerator": ScudGenerator}
diff --git a/gen/to_remove/ru_dd_group.py b/gen/to_remove/ru_dd_group.py
deleted file mode 100644
index 5c3d9b3d..00000000
--- a/gen/to_remove/ru_dd_group.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from __future__ import annotations
-
-import random
-from typing import TYPE_CHECKING
-
-from dcs.ships import (
- ALBATROS,
- MOLNIYA,
- NEUSTRASH,
- REZKY,
- MOSCOW,
- KILO,
- SOM,
-)
-
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import ShipGroundObject
-from gen.to_remove.dd_group import DDGroupGenerator
-from gen.group_generator import ShipGroupGenerator
-
-if TYPE_CHECKING:
- from game.game import Game
-
-
-class RussianNavyGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
-
- self.add_unit(
- ALBATROS,
- "FF1",
- self.position.x + 1200,
- self.position.y + 900,
- self.heading,
- )
- self.add_unit(
- ALBATROS,
- "FF2",
- self.position.x + 1200,
- self.position.y - 900,
- self.heading,
- )
-
- self.add_unit(
- NEUSTRASH,
- "DD1",
- self.position.x + 2400,
- self.position.y + 900,
- self.heading,
- )
- self.add_unit(
- NEUSTRASH,
- "DD2",
- self.position.x + 2400,
- self.position.y - 900,
- self.heading,
- )
-
- # Only include the Moskva for now, the Pyotry Velikiy is an unkillable monster.
- # See https://github.com/dcs-liberation/dcs_liberation/issues/567
- self.add_unit(
- MOSCOW,
- "CC1",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
-
-
-class GrishaGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(GrishaGroupGenerator, self).__init__(
- game, ground_object, faction, ALBATROS
- )
-
-
-class MolniyaGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(MolniyaGroupGenerator, self).__init__(
- game, ground_object, faction, MOLNIYA
- )
-
-
-class KiloSubGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(KiloSubGroupGenerator, self).__init__(game, ground_object, faction, KILO)
-
-
-class TangoSubGroupGenerator(DDGroupGenerator):
- def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
- super(TangoSubGroupGenerator, self).__init__(game, ground_object, faction, SOM)
diff --git a/gen/to_remove/sam_avenger.py b/gen/to_remove/sam_avenger.py
deleted file mode 100644
index 92b60e84..00000000
--- a/gen/to_remove/sam_avenger.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class AvengerGenerator(AirDefenseGroupGenerator):
- """
- This generate an Avenger group
- """
-
- name = "Avenger Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x,
- self.position.y,
- self.heading,
- )
- positions = self.get_circular_position(
- num_launchers, launcher_distance=110, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.M1097_Avenger,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_chaparral.py b/gen/to_remove/sam_chaparral.py
deleted file mode 100644
index 4e145a79..00000000
--- a/gen/to_remove/sam_chaparral.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ChaparralGenerator(AirDefenseGroupGenerator):
- """
- This generate a Chaparral group
- """
-
- name = "Chaparral Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x,
- self.position.y,
- self.heading,
- )
- positions = self.get_circular_position(
- num_launchers, launcher_distance=110, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.M48_Chaparral,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_gepard.py b/gen/to_remove/sam_gepard.py
deleted file mode 100644
index 20fe67ae..00000000
--- a/gen/to_remove/sam_gepard.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class GepardGenerator(AirDefenseGroupGenerator):
- """
- This generate a Gepard group
- """
-
- name = "Gepard Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Gepard,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_group_generator.py b/gen/to_remove/sam_group_generator.py
deleted file mode 100644
index 7935ef82..00000000
--- a/gen/to_remove/sam_group_generator.py
+++ /dev/null
@@ -1,172 +0,0 @@
-import random
-from typing import Dict, Iterable, List, Optional, Sequence, Set, Type
-
-from dcs.unitgroup import VehicleGroup
-
-from game import Game
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import SamGroundObject, AirDefenseRange
-from gen.to_remove.aaa_bofors import BoforsGenerator
-from gen.to_remove.aaa_flak import FlakGenerator
-from gen.to_remove.aaa_flak18 import Flak18Generator
-from gen.to_remove.aaa_ks19 import KS19Generator
-from gen.to_remove.aaa_ww2_ally_flak import AllyWW2FlakGenerator
-from gen.to_remove.aaa_zsu57 import ZSU57Generator
-from gen.to_remove.aaa_zu23_insurgent import ZU23InsurgentGenerator
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from gen.to_remove.cold_war_flak import (
- ColdWarFlakGenerator,
- EarlyColdWarFlakGenerator,
-)
-from gen.to_remove.freya_ewr import FreyaGenerator
-from gen.to_remove.sam_avenger import AvengerGenerator
-from gen.to_remove.sam_chaparral import ChaparralGenerator
-from gen.to_remove.sam_gepard import GepardGenerator
-from gen.to_remove.sam_hawk import HawkGenerator
-from gen.to_remove.sam_hq7 import HQ7Generator
-from gen.to_remove.sam_linebacker import LinebackerGenerator
-from gen.to_remove.sam_nasams import NasamBGenerator, NasamCGenerator
-from gen.to_remove.sam_patriot import PatriotGenerator
-from gen.to_remove.sam_rapier import RapierGenerator
-from gen.to_remove.sam_roland import RolandGenerator
-from gen.to_remove.sam_sa10 import (
- SA10Generator,
- Tier2SA10Generator,
- Tier3SA10Generator,
- SA10BGenerator,
- SA12Generator,
- SA20Generator,
- SA20BGenerator,
- SA23Generator,
-)
-from gen.to_remove.sam_sa11 import SA11Generator
-from gen.to_remove.sam_sa13 import SA13Generator
-from gen.to_remove.sam_sa15 import SA15Generator
-from gen.to_remove.sam_sa17 import SA17Generator
-from gen.to_remove.sam_sa19 import SA19Generator
-from gen.to_remove.sam_sa2 import SA2Generator
-from gen.to_remove.sam_sa3 import SA3Generator
-from gen.to_remove.sam_sa5 import SA5Generator, SA5FlatFaceGenerator
-from gen.to_remove.sam_sa6 import SA6Generator
-from gen.to_remove.sam_sa8 import SA8Generator
-from gen.to_remove.sam_sa9 import SA9Generator
-from gen.to_remove.sam_vulcan import VulcanGenerator
-from gen.to_remove.sam_zsu23 import ZSU23Generator
-from gen.to_remove.sam_zu23 import ZU23Generator
-from gen.to_remove.sam_zu23_ural import ZU23UralGenerator
-from gen.to_remove.sam_zu23_ural_insurgent import ZU23UralInsurgentGenerator
-
-SAM_MAP: Dict[str, Type[AirDefenseGroupGenerator]] = {
- "HawkGenerator": HawkGenerator,
- "ZU23Generator": ZU23Generator,
- "ZU23UralGenerator": ZU23UralGenerator,
- "ZU23UralInsurgentGenerator": ZU23UralInsurgentGenerator,
- "ZU23InsurgentGenerator": ZU23InsurgentGenerator,
- "ZSU23Generator": ZSU23Generator,
- "VulcanGenerator": VulcanGenerator,
- "LinebackerGenerator": LinebackerGenerator,
- "RapierGenerator": RapierGenerator,
- "AvengerGenerator": AvengerGenerator,
- "GepardGenerator": GepardGenerator,
- "RolandGenerator": RolandGenerator,
- "PatriotGenerator": PatriotGenerator,
- "ChaparralGenerator": ChaparralGenerator,
- "BoforsGenerator": BoforsGenerator,
- "FlakGenerator": FlakGenerator,
- "SA2Generator": SA2Generator,
- "SA3Generator": SA3Generator,
- "SA5Generator": SA5Generator,
- "SA5FlatFaceGenerator": SA5FlatFaceGenerator,
- "SA6Generator": SA6Generator,
- "SA8Generator": SA8Generator,
- "SA9Generator": SA9Generator,
- "SA10Generator": SA10Generator,
- "Tier2SA10Generator": Tier2SA10Generator,
- "Tier3SA10Generator": Tier3SA10Generator,
- "SA11Generator": SA11Generator,
- "SA13Generator": SA13Generator,
- "SA15Generator": SA15Generator,
- "SA19Generator": SA19Generator,
- "HQ7Generator": HQ7Generator,
- "Flak18Generator": Flak18Generator,
- "ColdWarFlakGenerator": ColdWarFlakGenerator,
- "EarlyColdWarFlakGenerator": EarlyColdWarFlakGenerator,
- "FreyaGenerator": FreyaGenerator,
- "AllyWW2FlakGenerator": AllyWW2FlakGenerator,
- "ZSU57Generator": ZSU57Generator,
- "KS19Generator": KS19Generator,
- "SA10BGenerator": SA10BGenerator,
- "SA12Generator": SA12Generator,
- "SA17Generator": SA17Generator,
- "SA20Generator": SA20Generator,
- "SA20BGenerator": SA20BGenerator,
- "SA23Generator": SA23Generator,
- "NasamBGenerator": NasamBGenerator,
- "NasamCGenerator": NasamCGenerator,
-}
-
-
-def get_faction_possible_sams_generator(
- faction: Faction,
-) -> List[Type[AirDefenseGroupGenerator]]:
- """
- Return the list of possible SAM generator for the given faction
- :param faction: Faction name to search units for
- """
- return [SAM_MAP[s] for s in faction.air_defenses]
-
-
-def _generate_anti_air_from(
- generators: Sequence[Type[AirDefenseGroupGenerator]],
- game: Game,
- ground_object: SamGroundObject,
-) -> List[VehicleGroup]:
- if not generators:
- return []
- sam_generator_class = random.choice(generators)
- generator = sam_generator_class(game, ground_object)
- generator.generate()
- return list(generator.groups)
-
-
-def generate_anti_air_group(
- game: Game,
- ground_object: SamGroundObject,
- faction: Faction,
- ranges: Optional[Iterable[Set[AirDefenseRange]]] = None,
-) -> List[VehicleGroup]:
- """
- This generate a SAM group
- :param game: The Game.
- :param ground_object: The ground object which will own the sam group.
- :param faction: Owner faction.
- :param ranges: Optional list of preferred ranges of the air defense to
- create. If None, any generator may be used. Otherwise generators
- matching the given ranges will be used in order of preference. For
- example, when given `[{Long, Medium}, {Short}]`, long and medium range
- air defenses will be tried first with no bias, and short range air
- defenses will be used if no long or medium range generators are
- available to the faction. If instead `[{Long}, {Medium}, {Short}]` had
- been used, long range systems would take precedence over medium range
- systems. If instead `[{Long, Medium, Short}]` had been used, all types
- would be considered with equal preference.
- :return: The generated group, or None if one could not be generated.
- """
- generators = get_faction_possible_sams_generator(faction)
- if ranges is None:
- ranges = [
- {
- AirDefenseRange.Long,
- AirDefenseRange.Medium,
- AirDefenseRange.Short,
- }
- ]
-
- for range_options in ranges:
- generators_for_range = [g for g in generators if g.range() in range_options]
- groups = _generate_anti_air_from(generators_for_range, game, ground_object)
- if groups:
- return groups
- return []
diff --git a/gen/to_remove/sam_hawk.py b/gen/to_remove/sam_hawk.py
deleted file mode 100644
index 808d6aef..00000000
--- a/gen/to_remove/sam_hawk.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from dcs.mapping import Point
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange, SkynetRole
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class HawkGenerator(AirDefenseGroupGenerator):
- """
- This generate an HAWK group
- """
-
- name = "Hawk Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.Hawk_sr,
- "SR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Hawk_pcp,
- "PCP",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Hawk_tr,
- "TR",
- self.position.x + 40,
- self.position.y,
- self.heading,
- )
-
- # Triple A for close range defense
- aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
- self.add_unit_to_group(
- aa_group,
- AirDefence.Vulcan,
- "AAA",
- self.position + Point(20, 30),
- self.heading,
- )
-
- num_launchers = 6
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Hawk_ln,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_hq7.py b/gen/to_remove/sam_hq7.py
deleted file mode 100644
index 6c850108..00000000
--- a/gen/to_remove/sam_hq7.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from dcs.mapping import Point
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange, SkynetRole
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class HQ7Generator(AirDefenseGroupGenerator):
- """
- This generate an HQ7 group
- """
-
- name = "HQ-7 Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.HQ_7_STR_SP,
- "STR",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- # Triple A for close range defense
- aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
- self.add_unit_to_group(
- aa_group,
- AirDefence.Ural_375_ZU_23,
- "AAA1",
- self.position + Point(20, 30),
- self.heading,
- )
- self.add_unit_to_group(
- aa_group,
- AirDefence.Ural_375_ZU_23,
- "AAA2",
- self.position - Point(20, 30),
- self.heading,
- )
-
- num_launchers = 2
- if num_launchers > 0:
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.HQ_7_LN_SP,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_linebacker.py b/gen/to_remove/sam_linebacker.py
deleted file mode 100644
index b8fefde0..00000000
--- a/gen/to_remove/sam_linebacker.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class LinebackerGenerator(AirDefenseGroupGenerator):
- """
- This generate an m6 linebacker group
- """
-
- name = "Linebacker Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x,
- self.position.y,
- self.heading,
- )
- positions = self.get_circular_position(
- num_launchers, launcher_distance=110, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.M6_Linebacker,
- "M6#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_nasams.py b/gen/to_remove/sam_nasams.py
deleted file mode 100644
index 4181ef58..00000000
--- a/gen/to_remove/sam_nasams.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from typing import Type
-
-from dcs.unittype import VehicleType
-from dcs.vehicles import AirDefence
-
-from game import Game
-from game.theater import SamGroundObject
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class NasamCGenerator(AirDefenseGroupGenerator):
- """
- This generate a Nasams group with AIM-120C missiles
- """
-
- name = "NASAMS AIM-120C"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.launcherType: Type[VehicleType] = AirDefence.NASAMS_LN_C
-
- def generate(self) -> None:
- # Command Post
- self.add_unit(
- AirDefence.NASAMS_Command_Post,
- "CP",
- self.position.x + 30,
- self.position.y + 30,
- self.heading,
- )
- # Radar
- self.add_unit(
- AirDefence.NASAMS_Radar_MPQ64F1,
- "RADAR",
- self.position.x - 30,
- self.position.y - 30,
- self.heading,
- )
-
- positions = self.get_circular_position(4, launcher_distance=120, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- self.launcherType,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
-
-
-class NasamBGenerator(NasamCGenerator):
- """
- This generate a Nasams group with AIM-120B missiles
- """
-
- name = "NASAMS AIM-120B"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.launcherType: Type[VehicleType] = AirDefence.NASAMS_LN_B
diff --git a/gen/to_remove/sam_patriot.py b/gen/to_remove/sam_patriot.py
deleted file mode 100644
index f88d845c..00000000
--- a/gen/to_remove/sam_patriot.py
+++ /dev/null
@@ -1,88 +0,0 @@
-from dcs.mapping import Point
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import SkynetRole, AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class PatriotGenerator(AirDefenseGroupGenerator):
- """
- This generate a Patriot group
- """
-
- name = "Patriot Battery"
-
- def generate(self) -> None:
- # Command Post
- self.add_unit(
- AirDefence.Patriot_str,
- "STR",
- self.position.x + 30,
- self.position.y + 30,
- self.heading,
- )
- self.add_unit(
- AirDefence.Patriot_AMG,
- "MRC",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Patriot_ECS,
- "MSQ",
- self.position.x + 30,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Patriot_cp,
- "ICC",
- self.position.x + 60,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Patriot_EPP,
- "EPP",
- self.position.x,
- self.position.y + 30,
- self.heading,
- )
-
- positions = self.get_circular_position(8, launcher_distance=120, coverage=360)
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Patriot_ln,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- # Short range protection for high value site
- aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
- positions = self.get_circular_position(2, launcher_distance=200, coverage=360)
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- aa_group,
- AirDefence.Vulcan,
- f"SPAAA#{i}",
- Point(x, y),
- heading,
- )
- positions = self.get_circular_position(2, launcher_distance=300, coverage=360)
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- aa_group,
- AirDefence.M1097_Avenger,
- f"Avenger#{i}",
- Point(x, y),
- heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Long
diff --git a/gen/to_remove/sam_rapier.py b/gen/to_remove/sam_rapier.py
deleted file mode 100644
index 30e67400..00000000
--- a/gen/to_remove/sam_rapier.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import SkynetRole, AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class RapierGenerator(AirDefenseGroupGenerator):
- """
- This generate a Rapier Group
- """
-
- name = "Rapier AA Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.Rapier_fsa_blindfire_radar,
- "BT",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Rapier_fsa_optical_tracker_unit,
- "OT",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=80, coverage=240
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Rapier_fsa_launcher,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
-
- @classmethod
- def primary_group_role(cls) -> SkynetRole:
- return SkynetRole.Sam
diff --git a/gen/to_remove/sam_roland.py b/gen/to_remove/sam_roland.py
deleted file mode 100644
index 006e77ac..00000000
--- a/gen/to_remove/sam_roland.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import SkynetRole, AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class RolandGenerator(AirDefenseGroupGenerator):
- """
- This generate a Roland group
- """
-
- name = "Roland Site"
-
- def generate(self) -> None:
- num_launchers = 2
- self.add_unit(
- AirDefence.Roland_Radar,
- "EWR",
- self.position.x + 40,
- self.position.y,
- self.heading,
- )
- positions = self.get_circular_position(
- num_launchers, launcher_distance=80, coverage=240
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Roland_ADS,
- "ADS#" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
-
- @classmethod
- def primary_group_role(cls) -> SkynetRole:
- return SkynetRole.Sam
diff --git a/gen/to_remove/sam_sa10.py b/gen/to_remove/sam_sa10.py
deleted file mode 100644
index 0be9694a..00000000
--- a/gen/to_remove/sam_sa10.py
+++ /dev/null
@@ -1,222 +0,0 @@
-from typing import Type
-
-from dcs.mapping import Point
-from dcs.unittype import VehicleType
-from dcs.vehicles import AirDefence
-
-from game import Game
-from game.theater import SamGroundObject
-from game.theater.theatergroundobject import SkynetRole, AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from pydcs_extensions.highdigitsams import highdigitsams
-
-
-class SA10Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-10 group
- """
-
- name = "SA-10/S-300PS Battery - With ZSU-23"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1: Type[VehicleType] = AirDefence.S_300PS_40B6MD_sr
- self.sr2: Type[VehicleType] = AirDefence.S_300PS_64H6E_sr
- self.cp: Type[VehicleType] = AirDefence.S_300PS_54K6_cp
- self.tr1: Type[VehicleType] = AirDefence.S_300PS_40B6M_tr
- self.tr2: Type[VehicleType] = AirDefence.S_300PS_40B6M_tr
- self.ln1: Type[VehicleType] = AirDefence.S_300PS_5P85C_ln
- self.ln2: Type[VehicleType] = AirDefence.S_300PS_5P85D_ln
-
- def generate(self) -> None:
- # Search Radar
- self.add_unit(
- self.sr1, "SR1", self.position.x, self.position.y + 40, self.heading
- )
-
- # Search radar for missiles (optionnal)
- self.add_unit(
- self.sr2, "SR2", self.position.x - 40, self.position.y, self.heading
- )
-
- # Command Post
- self.add_unit(self.cp, "CP", self.position.x, self.position.y, self.heading)
-
- # 1 Tracking radar
- self.add_unit(
- self.tr1, "TR1", self.position.x - 40, self.position.y - 40, self.heading
- )
-
- # 2 different launcher type (C & D)
- num_launchers = 6
- positions = self.get_circular_position(
- num_launchers, launcher_distance=100, coverage=360
- )
- for i, position in enumerate(positions):
- if i % 2 == 0:
- self.add_unit(
- self.ln1, "LN#" + str(i), position[0], position[1], position[2]
- )
- else:
- self.add_unit(
- self.ln2, "LN#" + str(i), position[0], position[1], position[2]
- )
-
- self.generate_defensive_groups()
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Long
-
- def generate_defensive_groups(self) -> None:
- # AAA for defending against close targets.
- aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=210, coverage=360
- )
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- aa_group,
- AirDefence.ZSU_23_4_Shilka,
- f"AA#{i}",
- Point(x, y),
- heading,
- )
-
-
-class Tier2SA10Generator(SA10Generator):
-
- name = "SA-10/S-300PS Battery - With SA-15 PD"
-
- def generate_defensive_groups(self) -> None:
- # Create AAA the way the main group does.
- super().generate_defensive_groups()
-
- # SA-15 for both shorter range targets and point defense.
- pd_group = self.add_auxiliary_group(SkynetRole.PointDefense)
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=140, coverage=360
- )
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- pd_group,
- AirDefence.Tor_9A331,
- f"PD#{i}",
- Point(x, y),
- heading,
- )
-
-
-class Tier3SA10Generator(SA10Generator):
-
- name = "SA-10/S-300PS Battery - With SA-15 PD & SA-19 SHORAD"
-
- def generate_defensive_groups(self) -> None:
- # AAA for defending against close targets.
- aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior)
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=210, coverage=360
- )
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- aa_group,
- AirDefence._2S6_Tunguska,
- f"AA#{i}",
- Point(x, y),
- heading,
- )
-
- # SA-15 for both shorter range targets and point defense.
- pd_group = self.add_auxiliary_group(SkynetRole.PointDefense)
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=140, coverage=360
- )
- for i, (x, y, heading) in enumerate(positions):
- self.add_unit_to_group(
- pd_group,
- AirDefence.Tor_9A331,
- f"PD#{i}",
- Point(x, y),
- heading,
- )
-
-
-class SA10BGenerator(Tier3SA10Generator):
-
- name = "SA-10B/S-300PS Battery"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1 = highdigitsams.SAM_SA_10B_S_300PS_40B6MD_SR
- self.sr2 = highdigitsams.SAM_SA_10B_S_300PS_64H6E_SR
- self.cp = highdigitsams.SAM_SA_10B_S_300PS_54K6_CP
- self.tr1 = highdigitsams.SAM_SA_10B_S_300PS_30N6_TR
- self.tr2 = highdigitsams.SAM_SA_10B_S_300PS_40B6M_TR
- self.ln1 = highdigitsams.SAM_SA_10B_S_300PS_5P85SE_LN
- self.ln2 = highdigitsams.SAM_SA_10B_S_300PS_5P85SU_LN
-
-
-class SA12Generator(Tier3SA10Generator):
-
- name = "SA-12/S-300V Battery"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1 = highdigitsams.SAM_SA_12_S_300V_9S15_SR
- self.sr2 = highdigitsams.SAM_SA_12_S_300V_9S19_SR
- self.cp = highdigitsams.SAM_SA_12_S_300V_9S457_CP
- self.tr1 = highdigitsams.SAM_SA_12_S_300V_9S32_TR
- self.tr2 = highdigitsams.SAM_SA_12_S_300V_9S32_TR
- self.ln1 = highdigitsams.SAM_SA_12_S_300V_9A82_LN
- self.ln2 = highdigitsams.SAM_SA_12_S_300V_9A83_LN
-
-
-class SA20Generator(Tier3SA10Generator):
-
- name = "SA-20/S-300PMU-1 Battery"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1 = highdigitsams.SAM_SA_20_S_300PMU1_SR_5N66E
- self.sr2 = highdigitsams.SAM_SA_20_S_300PMU1_SR_64N6E
- self.cp = highdigitsams.SAM_SA_20_S_300PMU1_CP_54K6
- self.tr1 = highdigitsams.SAM_SA_20_S_300PMU1_TR_30N6E
- self.tr2 = highdigitsams.SAM_SA_20_S_300PMU1_TR_30N6E_truck
- self.ln1 = highdigitsams.SAM_SA_20_S_300PMU1_LN_5P85CE
- self.ln2 = highdigitsams.SAM_SA_20_S_300PMU1_LN_5P85DE
-
-
-class SA20BGenerator(Tier3SA10Generator):
-
- name = "SA-20B/S-300PMU-2 Battery"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1 = highdigitsams.SAM_SA_20_S_300PMU1_SR_5N66E
- self.sr2 = highdigitsams.SAM_SA_20_S_300PMU1_SR_64N6E
- self.cp = highdigitsams.SAM_SA_20B_S_300PMU2_CP_54K6E2
- self.tr1 = highdigitsams.SAM_SA_20B_S_300PMU2_TR_92H6E_truck
- self.tr2 = highdigitsams.SAM_SA_20B_S_300PMU2_TR_92H6E_truck
- self.ln1 = highdigitsams.SAM_SA_20B_S_300PMU2_LN_5P85SE2
- self.ln2 = highdigitsams.SAM_SA_20B_S_300PMU2_LN_5P85SE2
-
-
-class SA23Generator(Tier3SA10Generator):
-
- name = "SA-23/S-300VM Battery"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr1 = highdigitsams.SAM_SA_23_S_300VM_9S15M2_SR
- self.sr2 = highdigitsams.SAM_SA_23_S_300VM_9S19M2_SR
- self.cp = highdigitsams.SAM_SA_23_S_300VM_9S457ME_CP
- self.tr1 = highdigitsams.SAM_SA_23_S_300VM_9S32ME_TR
- self.tr2 = highdigitsams.SAM_SA_23_S_300VM_9S32ME_TR
- self.ln1 = highdigitsams.SAM_SA_23_S_300VM_9A82ME_LN
- self.ln2 = highdigitsams.SAM_SA_23_S_300VM_9A83ME_LN
diff --git a/gen/to_remove/sam_sa11.py b/gen/to_remove/sam_sa11.py
deleted file mode 100644
index e4c13bc8..00000000
--- a/gen/to_remove/sam_sa11.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA11Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-11 group
- """
-
- name = "SA-11 Buk Battery"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.SA_11_Buk_SR_9S18M1,
- "SR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.SA_11_Buk_CC_9S470M1,
- "CC",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 4
- positions = self.get_circular_position(
- num_launchers, launcher_distance=140, coverage=180
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.SA_11_Buk_LN_9A310M1,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa13.py b/gen/to_remove/sam_sa13.py
deleted file mode 100644
index a88af0ed..00000000
--- a/gen/to_remove/sam_sa13.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA13Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-13 group
- """
-
- name = "SA-13 Strela Group"
-
- def generate(self) -> None:
- self.add_unit(
- Unarmed.UAZ_469,
- "UAZ",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- Unarmed.KAMAZ_Truck,
- "TRUCK",
- self.position.x + 40,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Strela_10M3,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_sa15.py b/gen/to_remove/sam_sa15.py
deleted file mode 100644
index 658518f8..00000000
--- a/gen/to_remove/sam_sa15.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA15Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-15 group
- """
-
- name = "SA-15 Tor Group"
-
- def generate(self) -> None:
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Tor_9A331,
- "ADS#" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- Unarmed.UAZ_469,
- "EWR",
- self.position.x + 40,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- Unarmed.KAMAZ_Truck,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa17.py b/gen/to_remove/sam_sa17.py
deleted file mode 100644
index a67652de..00000000
--- a/gen/to_remove/sam_sa17.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-from pydcs_extensions.highdigitsams import highdigitsams
-
-
-class SA17Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-17 group
- """
-
- name = "SA-17 Grizzly Battery"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.SA_11_Buk_SR_9S18M1,
- "SR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.SA_11_Buk_CC_9S470M1,
- "CC",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- positions = self.get_circular_position(3, launcher_distance=140, coverage=180)
-
- for i, position in enumerate(positions):
- self.add_unit(
- highdigitsams.SAM_SA_17_Buk_M1_2_LN_9A310M1_2,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa19.py b/gen/to_remove/sam_sa19.py
deleted file mode 100644
index 4b78db21..00000000
--- a/gen/to_remove/sam_sa19.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA19Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-19 group
- """
-
- name = "SA-19 Tunguska Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- if num_launchers == 1:
- self.add_unit(
- AirDefence._2S6_Tunguska,
- "LN#0",
- self.position.x,
- self.position.y,
- self.heading,
- )
- else:
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence._2S6_Tunguska,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_sa2.py b/gen/to_remove/sam_sa2.py
deleted file mode 100644
index 76159a41..00000000
--- a/gen/to_remove/sam_sa2.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA2Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-2 group
- """
-
- name = "SA-2/S-75 Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.P_19_s_125_sr,
- "SR",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.SNR_75V,
- "TR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 6
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.S_75M_Volhov,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa3.py b/gen/to_remove/sam_sa3.py
deleted file mode 100644
index f86943d3..00000000
--- a/gen/to_remove/sam_sa3.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA3Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-3 group
- """
-
- name = "SA-3/S-125 Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.P_19_s_125_sr,
- "SR",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.Snr_s_125_tr,
- "TR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 4
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence._5p73_s_125_ln,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa5.py b/gen/to_remove/sam_sa5.py
deleted file mode 100644
index 7a7c972b..00000000
--- a/gen/to_remove/sam_sa5.py
+++ /dev/null
@@ -1,77 +0,0 @@
-from typing import Type
-
-from dcs.unittype import VehicleType
-from dcs.vehicles import AirDefence, Unarmed
-
-from game import Game
-from game.theater import SamGroundObject
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA5Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-5 group using the TinShield SR
- """
-
- name = "SA-5/S-200 Site"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr: Type[VehicleType] = AirDefence.RLS_19J6
-
- def generate(self) -> None:
- self.add_unit(
- self.sr,
- "SR",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- AirDefence.RPC_5N62V,
- "TR",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- Unarmed.Ural_375,
- "LOGI",
- self.position.x - 20,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 6
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.S_200_Launcher,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Long
-
-
-# TODO Replace this legacy handling once the Generators can be faction sensitive #1903
-class SA5FlatFaceGenerator(SA5Generator):
- """
- This generate a SA-5 group using the P-19 FlatFace SR
- """
-
- name = "SA-5/S-200 Site wit FlatFace SR"
-
- def __init__(self, game: Game, ground_object: SamGroundObject):
- super().__init__(game, ground_object)
- self.sr: Type[VehicleType] = AirDefence.P_19_s_125_sr
diff --git a/gen/to_remove/sam_sa6.py b/gen/to_remove/sam_sa6.py
deleted file mode 100644
index eff1c02f..00000000
--- a/gen/to_remove/sam_sa6.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA6Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-6 group
- """
-
- name = "SA-6 Kub Site"
-
- def generate(self) -> None:
- self.add_unit(
- AirDefence.Kub_1S91_str,
- "STR",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 4
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Kub_2P25_ln,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa8.py b/gen/to_remove/sam_sa8.py
deleted file mode 100644
index 855fe903..00000000
--- a/gen/to_remove/sam_sa8.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA8Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-8 group
- """
-
- name = "SA-8 OSA Site"
-
- def generate(self) -> None:
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
-
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Osa_9A33_ln,
- "OSA" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- AirDefence.SA_8_Osa_LD_9T217,
- "LD",
- self.position.x + 20,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Medium
diff --git a/gen/to_remove/sam_sa9.py b/gen/to_remove/sam_sa9.py
deleted file mode 100644
index db18dbe2..00000000
--- a/gen/to_remove/sam_sa9.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class SA9Generator(AirDefenseGroupGenerator):
- """
- This generate a SA-9 group
- """
-
- name = "SA-9 Group"
-
- def generate(self) -> None:
- self.add_unit(
- Unarmed.UAZ_469,
- "UAZ",
- self.position.x,
- self.position.y,
- self.heading,
- )
- self.add_unit(
- Unarmed.KAMAZ_Truck,
- "TRUCK",
- self.position.x + 40,
- self.position.y,
- self.heading,
- )
-
- num_launchers = 2
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Strela_1_9P31,
- "LN#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.Short
diff --git a/gen/to_remove/sam_vulcan.py b/gen/to_remove/sam_vulcan.py
deleted file mode 100644
index 4c3e1732..00000000
--- a/gen/to_remove/sam_vulcan.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class VulcanGenerator(AirDefenseGroupGenerator):
- """
- This generate a Vulcan group
- """
-
- name = "Vulcan Group"
-
- def generate(self) -> None:
- num_launchers = 2
-
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Vulcan,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/sam_zsu23.py b/gen/to_remove/sam_zsu23.py
deleted file mode 100644
index 7434cfab..00000000
--- a/gen/to_remove/sam_zsu23.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZSU23Generator(AirDefenseGroupGenerator):
- """
- This generate a ZSU 23 group
- """
-
- name = "ZSU-23 Group"
-
- def generate(self) -> None:
- num_launchers = 4
-
- positions = self.get_circular_position(
- num_launchers, launcher_distance=120, coverage=180
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.ZSU_23_4_Shilka,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/sam_zu23.py b/gen/to_remove/sam_zu23.py
deleted file mode 100644
index 1880cb32..00000000
--- a/gen/to_remove/sam_zu23.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import random
-
-from dcs.vehicles import AirDefence, Unarmed
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZU23Generator(AirDefenseGroupGenerator):
- """
- This generate a ZU23 flak artillery group
- """
-
- name = "ZU-23 Group"
-
- def generate(self) -> None:
- index = 0
- for i in range(4):
- index = index + 1
- spacing_x = random.randint(10, 40)
- spacing_y = random.randint(10, 40)
- self.add_unit(
- AirDefence.ZU_23_Emplacement_Closed,
- "AAA#" + str(index),
- self.position.x + spacing_x * i,
- self.position.y + spacing_y * i,
- self.heading,
- )
- self.add_unit(
- Unarmed.M_818,
- "TRUCK",
- self.position.x + 80,
- self.position.y,
- self.heading,
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/sam_zu23_ural.py b/gen/to_remove/sam_zu23_ural.py
deleted file mode 100644
index c7b01ae5..00000000
--- a/gen/to_remove/sam_zu23_ural.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZU23UralGenerator(AirDefenseGroupGenerator):
- """
- This generate a Zu23 Ural group
- """
-
- name = "ZU-23 Ural Group"
-
- def generate(self) -> None:
- num_launchers = 4
-
- positions = self.get_circular_position(
- num_launchers, launcher_distance=80, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Ural_375_ZU_23,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
diff --git a/gen/to_remove/sam_zu23_ural_insurgent.py b/gen/to_remove/sam_zu23_ural_insurgent.py
deleted file mode 100644
index 92c167ee..00000000
--- a/gen/to_remove/sam_zu23_ural_insurgent.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from dcs.vehicles import AirDefence
-
-from game.theater.theatergroundobject import AirDefenseRange
-from gen.to_remove.airdefensegroupgenerator import (
- AirDefenseGroupGenerator,
-)
-
-
-class ZU23UralInsurgentGenerator(AirDefenseGroupGenerator):
- """
- This generate a Zu23 Ural group
- """
-
- name = "ZU-23 Ural Insurgent Group"
-
- @classmethod
- def range(cls) -> AirDefenseRange:
- return AirDefenseRange.AAA
-
- def generate(self) -> None:
- num_launchers = 4
-
- positions = self.get_circular_position(
- num_launchers, launcher_distance=80, coverage=360
- )
- for i, position in enumerate(positions):
- self.add_unit(
- AirDefence.Ural_375_ZU_23_Insurgent,
- "SPAA#" + str(i),
- position[0],
- position[1],
- position[2],
- )
diff --git a/gen/to_remove/schnellboot.py b/gen/to_remove/schnellboot.py
deleted file mode 100644
index 04cce7c3..00000000
--- a/gen/to_remove/schnellboot.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import random
-
-from dcs.ships import Schnellboot_type_S130
-
-from gen.group_generator import ShipGroupGenerator
-
-
-class SchnellbootGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
-
- for i in range(random.randint(2, 4)):
- self.add_unit(
- Schnellboot_type_S130,
- "Schnellboot" + str(i),
- self.position.x + i * random.randint(100, 250),
- self.position.y + (random.randint(100, 200) - 100),
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
diff --git a/gen/to_remove/scud_site.py b/gen/to_remove/scud_site.py
deleted file mode 100644
index 1d03649d..00000000
--- a/gen/to_remove/scud_site.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import random
-
-from dcs.vehicles import Unarmed, MissilesSS, AirDefence
-
-from game import Game
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import MissileSiteGroundObject
-from game.utils import Heading
-from gen.group_generator import VehicleGroupGenerator
-
-
-class ScudGenerator(VehicleGroupGenerator[MissileSiteGroundObject]):
- def __init__(
- self, game: Game, ground_object: MissileSiteGroundObject, faction: Faction
- ) -> None:
- super(ScudGenerator, self).__init__(game, ground_object)
- self.faction = faction
-
- def generate(self) -> None:
-
- # Scuds
- self.add_unit(
- MissilesSS.Scud_B,
- "V1#0",
- self.position.x,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
- self.add_unit(
- MissilesSS.Scud_B,
- "V1#1",
- self.position.x + 50,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
- self.add_unit(
- MissilesSS.Scud_B,
- "V1#2",
- self.position.x + 100,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
-
- # Commander
- self.add_unit(
- Unarmed.UAZ_469,
- "Kubel#0",
- self.position.x - 35,
- self.position.y - 20,
- self.heading,
- )
-
- # Shorad
- self.add_unit(
- AirDefence.ZSU_23_4_Shilka,
- "SHILKA#0",
- self.position.x - 55,
- self.position.y - 38,
- self.heading,
- )
-
- self.add_unit(
- AirDefence.Strela_1_9P31,
- "STRELA#0",
- self.position.x + 200,
- self.position.y + 15,
- Heading.from_degrees(90),
- )
diff --git a/gen/to_remove/ship_group_generator.py b/gen/to_remove/ship_group_generator.py
deleted file mode 100644
index 92ee198c..00000000
--- a/gen/to_remove/ship_group_generator.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from __future__ import annotations
-
-import logging
-import random
-from typing import TYPE_CHECKING, Optional
-
-from dcs.unitgroup import ShipGroup
-
-from game import db
-from game.theater.theatergroundobject import (
- LhaGroundObject,
- CarrierGroundObject,
- ShipGroundObject,
-)
-from gen.to_remove.carrier_group import CarrierGroupGenerator
-from gen.to_remove.cn_dd_group import ChineseNavyGroupGenerator, Type54GroupGenerator
-from gen.to_remove.dd_group import (
- ArleighBurkeGroupGenerator,
- OliverHazardPerryGroupGenerator,
-)
-from gen.to_remove.lacombattanteII import LaCombattanteIIGroupGenerator
-from gen.to_remove.lha_group import LHAGroupGenerator
-from gen.to_remove.ru_dd_group import (
- RussianNavyGroupGenerator,
- GrishaGroupGenerator,
- MolniyaGroupGenerator,
- KiloSubGroupGenerator,
- TangoSubGroupGenerator,
-)
-from gen.to_remove.schnellboot import SchnellbootGroupGenerator
-from gen.to_remove.uboat import UBoatGroupGenerator
-from gen.to_remove.ww2lst import WW2LSTGroupGenerator
-
-if TYPE_CHECKING:
- from game import Game
-
-
-SHIP_MAP = {
- "SchnellbootGroupGenerator": SchnellbootGroupGenerator,
- "WW2LSTGroupGenerator": WW2LSTGroupGenerator,
- "UBoatGroupGenerator": UBoatGroupGenerator,
- "OliverHazardPerryGroupGenerator": OliverHazardPerryGroupGenerator,
- "ArleighBurkeGroupGenerator": ArleighBurkeGroupGenerator,
- "RussianNavyGroupGenerator": RussianNavyGroupGenerator,
- "ChineseNavyGroupGenerator": ChineseNavyGroupGenerator,
- "GrishaGroupGenerator": GrishaGroupGenerator,
- "MolniyaGroupGenerator": MolniyaGroupGenerator,
- "KiloSubGroupGenerator": KiloSubGroupGenerator,
- "TangoSubGroupGenerator": TangoSubGroupGenerator,
- "Type54GroupGenerator": Type54GroupGenerator,
- "LaCombattanteIIGroupGenerator": LaCombattanteIIGroupGenerator,
-}
diff --git a/gen/to_remove/silkworm.py b/gen/to_remove/silkworm.py
deleted file mode 100644
index 7d042f69..00000000
--- a/gen/to_remove/silkworm.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from dcs.vehicles import MissilesSS, Unarmed, AirDefence
-
-from game import Game
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import CoastalSiteGroundObject
-from game.utils import Heading
-from gen.group_generator import VehicleGroupGenerator
-
-
-class SilkwormGenerator(VehicleGroupGenerator[CoastalSiteGroundObject]):
- def __init__(
- self, game: Game, ground_object: CoastalSiteGroundObject, faction: Faction
- ) -> None:
- super(SilkwormGenerator, self).__init__(game, ground_object)
- self.faction = faction
-
- def generate(self) -> None:
-
- positions = self.get_circular_position(5, launcher_distance=120, coverage=180)
-
- self.add_unit(
- MissilesSS.Silkworm_SR,
- "SR#0",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- # Launchers
- for i, p in enumerate(positions):
- self.add_unit(
- MissilesSS.Hy_launcher,
- "Missile#" + str(i),
- p[0],
- p[1],
- self.heading,
- )
-
- # Commander
- self.add_unit(
- Unarmed.KAMAZ_Truck,
- "KAMAZ#0",
- self.position.x - 35,
- self.position.y - 20,
- self.heading,
- )
-
- # Shorad
- self.add_unit(
- AirDefence.ZSU_23_4_Shilka,
- "SHILKA#0",
- self.position.x - 55,
- self.position.y - 38,
- self.heading,
- )
-
- # Shorad 2
- self.add_unit(
- AirDefence.Strela_1_9P31,
- "STRELA#0",
- self.position.x + 200,
- self.position.y + 15,
- Heading.from_degrees(90),
- )
diff --git a/gen/to_remove/uboat.py b/gen/to_remove/uboat.py
deleted file mode 100644
index 48e6c7a6..00000000
--- a/gen/to_remove/uboat.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import random
-
-from dcs.ships import Uboat_VIIC
-
-from gen.group_generator import ShipGroupGenerator
-
-
-class UBoatGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
-
- for i in range(random.randint(1, 4)):
- self.add_unit(
- Uboat_VIIC,
- "Uboat" + str(i),
- self.position.x + i * random.randint(100, 250),
- self.position.y + (random.randint(100, 200) - 100),
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
diff --git a/gen/to_remove/v1_group.py b/gen/to_remove/v1_group.py
deleted file mode 100644
index 1374d1f6..00000000
--- a/gen/to_remove/v1_group.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import random
-
-from dcs.vehicles import Unarmed, MissilesSS, AirDefence
-
-from game import Game
-from game.factions.faction import Faction
-from game.theater.theatergroundobject import MissileSiteGroundObject
-from game.utils import Heading
-from gen.group_generator import VehicleGroupGenerator
-
-
-class V1GroupGenerator(VehicleGroupGenerator[MissileSiteGroundObject]):
- def __init__(
- self, game: Game, ground_object: MissileSiteGroundObject, faction: Faction
- ) -> None:
- super(V1GroupGenerator, self).__init__(game, ground_object)
- self.faction = faction
-
- def generate(self) -> None:
-
- # Ramps
- self.add_unit(
- MissilesSS.V1_launcher,
- "V1#0",
- self.position.x,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
- self.add_unit(
- MissilesSS.V1_launcher,
- "V1#1",
- self.position.x + 50,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
- self.add_unit(
- MissilesSS.V1_launcher,
- "V1#2",
- self.position.x + 100,
- self.position.y + random.randint(1, 8),
- self.heading,
- )
-
- # Commander
- self.add_unit(
- Unarmed.Kubelwagen_82,
- "Kubel#0",
- self.position.x - 35,
- self.position.y - 20,
- self.heading,
- )
-
- # Self defense flak
- flak_unit = random.choice([AirDefence.Flak38, AirDefence.Flak30])
-
- self.add_unit(
- flak_unit,
- "FLAK#0",
- self.position.x - 55,
- self.position.y - 38,
- self.heading,
- )
-
- self.add_unit(
- Unarmed.Blitz_36_6700A,
- "Blitz#0",
- self.position.x + 200,
- self.position.y + 15,
- Heading.from_degrees(90),
- )
diff --git a/gen/to_remove/ww2lst.py b/gen/to_remove/ww2lst.py
deleted file mode 100644
index 0ff74dcf..00000000
--- a/gen/to_remove/ww2lst.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import random
-
-from dcs.ships import USS_Samuel_Chase, LST_Mk2
-
-from gen.group_generator import ShipGroupGenerator
-
-
-class WW2LSTGroupGenerator(ShipGroupGenerator):
- def generate(self) -> None:
-
- # Add LS Samuel Chase
- self.add_unit(
- USS_Samuel_Chase,
- "SamuelChase",
- self.position.x,
- self.position.y,
- self.heading,
- )
-
- for i in range(1, random.randint(3, 4)):
- self.add_unit(
- LST_Mk2,
- "LST" + str(i),
- self.position.x + i * random.randint(800, 1200),
- self.position.y,
- self.heading,
- )
-
- self.get_generated_group().points[0].speed = 20
diff --git a/resources/templates/anti_air/AAA.miz b/resources/templates/anti_air/AAA.miz
new file mode 100644
index 00000000..8207e4a4
Binary files /dev/null and b/resources/templates/anti_air/AAA.miz differ
diff --git a/resources/templates/anti_air/AAA_Mobile.yaml b/resources/templates/anti_air/AAA_Mobile.yaml
new file mode 100644
index 00000000..d290c1be
--- /dev/null
+++ b/resources/templates/anti_air/AAA_Mobile.yaml
@@ -0,0 +1,23 @@
+name: AAA Mobile
+description: A standard AAA template
+generic: true
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: AAA Mobile 0
+ group: 1
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - AAA
+ - name: AAA Mobile 1
+ optional: true
+ group: 1
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/AAA.miz
\ No newline at end of file
diff --git a/resources/templates/anti_air/AAA_Radar.yaml b/resources/templates/anti_air/AAA_Radar.yaml
new file mode 100644
index 00000000..bfb0570b
--- /dev/null
+++ b/resources/templates/anti_air/AAA_Radar.yaml
@@ -0,0 +1,29 @@
+name: AAA Radar Site
+description: AAA Template with a Radar
+generic: false
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: AAA Radar Site 0
+ group: 1
+ unit_count:
+ - 1
+ unit_classes:
+ - SearchRadar
+ - name: AAA Radar Site 1
+ group: 1
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - AAA
+ - name: AAA Radar Site 2
+ optional: true
+ group: 1
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/AAA.miz
\ No newline at end of file
diff --git a/resources/templates/anti_air/AAA_Site.yaml b/resources/templates/anti_air/AAA_Site.yaml
new file mode 100644
index 00000000..9a549894
--- /dev/null
+++ b/resources/templates/anti_air/AAA_Site.yaml
@@ -0,0 +1,23 @@
+name: AAA Site
+description: A standard AAA template
+generic: true
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: AAA Site 0
+ group: 1
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - AAA
+ - name: AAA Site 1
+ optional: true
+ group: 1
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/AAA.miz
\ No newline at end of file
diff --git a/resources/templates/anti_air/Cold_War_Flak_Site.yaml b/resources/templates/anti_air/Cold_War_Flak_Site.yaml
new file mode 100644
index 00000000..5ff23d19
--- /dev/null
+++ b/resources/templates/anti_air/Cold_War_Flak_Site.yaml
@@ -0,0 +1,36 @@
+name: Cold War Flak Site
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: Cold War Flak Site Radar
+ optional: true # Only available to Late Cold War
+ unit_count:
+ - 1
+ unit_classes:
+ - SearchRadar
+ - name: Cold War Flak Site Flak
+ unit_count:
+ - 4
+ - 6
+ unit_types:
+ - flak18
+ - name: Cold War Flak Site S-60
+ unit_count:
+ - 2
+ unit_types:
+ - S-60_Type59_Artillery
+ - name: Cold War Flak Site AAA
+ optional: true
+ unit_count:
+ - 2
+ unit_classes:
+ - AAA
+ - name: Cold War Flak Site Logistics
+ optional: true
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/flak.miz
diff --git a/resources/templates/anti_air/Early-Warning_Radar.yaml b/resources/templates/anti_air/Early-Warning_Radar.yaml
new file mode 100644
index 00000000..271182d4
--- /dev/null
+++ b/resources/templates/anti_air/Early-Warning_Radar.yaml
@@ -0,0 +1,15 @@
+name: Early-Warning Radar
+generic: true
+role: AntiAir
+tasks:
+ - EarlyWarningRadar
+groups:
+ - name: Early-Warning Radar 0
+ unit_count:
+ - 1
+ unit_classes:
+ - EarlyWarningRadar
+ alternative_classes:
+ - SearchRadar
+ - SearchTrackRadar
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Flak_Site.yaml b/resources/templates/anti_air/Flak_Site.yaml
new file mode 100644
index 00000000..02f63008
--- /dev/null
+++ b/resources/templates/anti_air/Flak_Site.yaml
@@ -0,0 +1,51 @@
+name: Flak Site
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: Flak Site 0
+ unit_count:
+ - 4
+ unit_types:
+ - flak38
+ - flak18
+ - flak36
+ - flak37
+ - flak41
+ - flak30
+ - name: Flak Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - flak38
+ - name: Flak Site 2
+ unit_count:
+ - 1
+ unit_types:
+ - flak36
+ - name: Flak Site 3
+ unit_count:
+ - 2
+ unit_types:
+ - Flakscheinwerfer_37
+ - name: Flak Site 4
+ unit_count:
+ - 1
+ unit_types:
+ - Maschinensatz_33
+ - name: Flak Site 5
+ unit_count:
+ - 1
+ unit_types:
+ - KDO_Mod40
+ - name: Flak Site 6
+ unit_count:
+ - 1
+ unit_types:
+ - Kubelwagen_82
+ - name: Flak Site 7
+ unit_count:
+ - 4
+ unit_types:
+ - Blitz_36-6700A
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Freya_EWR_Site.yaml b/resources/templates/anti_air/Freya_EWR_Site.yaml
new file mode 100644
index 00000000..7a97515b
--- /dev/null
+++ b/resources/templates/anti_air/Freya_EWR_Site.yaml
@@ -0,0 +1,51 @@
+name: Freya EWR Site
+role: AntiAir
+tasks:
+ - SHORAD
+groups:
+ - name: Freya EWR Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - FuMG-401
+ - name: Freya EWR Site 1
+ unit_count:
+ - 4
+ unit_types:
+ - flak38
+ - name: Freya EWR Site 2
+ unit_count:
+ - 4
+ unit_types:
+ - flak18
+ - name: Freya EWR Site 3
+ unit_count:
+ - 1
+ unit_types:
+ - Kubelwagen_82
+ - name: Freya EWR Site 4
+ unit_count:
+ - 1
+ unit_types:
+ - Sd_Kfz_7
+ - name: Freya EWR Site 5
+ unit_count:
+ - 1
+ unit_types:
+ - Sd_Kfz_2
+ - name: Freya EWR Site 6
+ unit_count:
+ - 1
+ unit_types:
+ - Maschinensatz_33
+ - name: Freya EWR Site 7
+ unit_count:
+ - 1
+ unit_types:
+ - KDO_Mod40
+ - name: Freya EWR Site 8
+ unit_count:
+ - 3
+ unit_types:
+ - soldier_mauser98
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/HQ-7_Site.yaml b/resources/templates/anti_air/HQ-7_Site.yaml
new file mode 100644
index 00000000..8c080c1d
--- /dev/null
+++ b/resources/templates/anti_air/HQ-7_Site.yaml
@@ -0,0 +1,24 @@
+name: HQ-7 Site
+role: AntiAir
+tasks:
+ - SHORAD
+groups:
+ - name: HQ-7 Site 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - HQ-7_STR_SP
+ - name: HQ-7 Site 1
+ group: 1
+ unit_count:
+ - 2
+ unit_types:
+ - HQ-7_LN_SP
+ - name: HQ-7 Site 2
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - Ural-375 ZU-23
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Hawk_Site.yaml b/resources/templates/anti_air/Hawk_Site.yaml
new file mode 100644
index 00000000..1a66d4cb
--- /dev/null
+++ b/resources/templates/anti_air/Hawk_Site.yaml
@@ -0,0 +1,36 @@
+name: Hawk Site
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: Hawk Site 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Hawk sr
+ - name: Hawk Site 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Hawk pcp
+ - name: Hawk Site 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Hawk tr
+ - name: Hawk Site 3
+ group: 1
+ unit_count:
+ - 6
+ unit_types:
+ - Hawk ln
+ - name: Hawk Site 4
+ group: 2
+ unit_count:
+ - 1
+ unit_types:
+ - Vulcan
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/NASAMS_AIM-120B.yaml b/resources/templates/anti_air/NASAMS_AIM-120B.yaml
new file mode 100644
index 00000000..6da0ff3c
--- /dev/null
+++ b/resources/templates/anti_air/NASAMS_AIM-120B.yaml
@@ -0,0 +1,21 @@
+name: NASAMS AIM-120B
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: NASAMS AIM-120B 1
+ unit_count:
+ - 1
+ unit_types:
+ - NASAMS_Radar_MPQ64F1
+ - name: NASAMS AIM-120B 0
+ unit_count:
+ - 1
+ unit_types:
+ - NASAMS_Command_Post
+ - name: NASAMS AIM-120B 2
+ unit_count:
+ - 4
+ unit_types:
+ - NASAMS_LN_B
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/NASAMS_AIM-120C.yaml b/resources/templates/anti_air/NASAMS_AIM-120C.yaml
new file mode 100644
index 00000000..9714b18f
--- /dev/null
+++ b/resources/templates/anti_air/NASAMS_AIM-120C.yaml
@@ -0,0 +1,21 @@
+name: NASAMS AIM-120C
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: NASAMS AIM-120C 1
+ unit_count:
+ - 1
+ unit_types:
+ - NASAMS_Radar_MPQ64F1
+ - name: NASAMS AIM-120C 0
+ unit_count:
+ - 1
+ unit_types:
+ - NASAMS_Command_Post
+ - name: NASAMS AIM-120C 2
+ unit_count:
+ - 4
+ unit_types:
+ - NASAMS_LN_C
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Patriot_Battery.yaml b/resources/templates/anti_air/Patriot_Battery.yaml
new file mode 100644
index 00000000..e34e7032
--- /dev/null
+++ b/resources/templates/anti_air/Patriot_Battery.yaml
@@ -0,0 +1,56 @@
+name: Patriot Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: Patriot Battery 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Patriot str
+ - name: Patriot Battery 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Patriot AMG
+ - name: Patriot Battery 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Patriot ECS
+ - name: Patriot Battery 3
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Patriot cp
+ - name: Patriot Battery 4
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Patriot EPP
+ - name: Patriot Battery 5
+ group: 1
+ unit_count:
+ - 8
+ unit_types:
+ - Patriot ln
+ - name: Patriot Battery 6
+ optional: true
+ group: 2
+ unit_count:
+ - 2
+ unit_classes:
+ - AAA
+ - name: Patriot Battery 7
+ optional: true
+ group: 2
+ unit_count:
+ - 2
+ unit_classes:
+ - SHORAD
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Rapier_AA_Site.yaml b/resources/templates/anti_air/Rapier_AA_Site.yaml
new file mode 100644
index 00000000..794ff572
--- /dev/null
+++ b/resources/templates/anti_air/Rapier_AA_Site.yaml
@@ -0,0 +1,21 @@
+name: Rapier AA Site
+role: AntiAir
+tasks:
+ - SHORAD
+groups:
+ - name: Rapier AA Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - rapier_fsa_blindfire_radar
+ - name: Rapier AA Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - rapier_fsa_optical_tracker_unit
+ - name: Rapier AA Site 2
+ unit_count:
+ - 2
+ unit_types:
+ - rapier_fsa_launcher
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Roland_Site.yaml b/resources/templates/anti_air/Roland_Site.yaml
new file mode 100644
index 00000000..2deee5fc
--- /dev/null
+++ b/resources/templates/anti_air/Roland_Site.yaml
@@ -0,0 +1,21 @@
+name: Roland Site
+role: AntiAir
+tasks:
+ - SHORAD
+groups:
+ - name: Roland Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - Roland Radar
+ - name: Roland Site 1
+ unit_count:
+ - 2
+ unit_types:
+ - Roland ADS
+ - name: Roland Site 2
+ unit_count:
+ - 1
+ unit_types:
+ - M 818
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-10.miz b/resources/templates/anti_air/SA-10.miz
new file mode 100644
index 00000000..669c54ec
Binary files /dev/null and b/resources/templates/anti_air/SA-10.miz differ
diff --git a/resources/templates/anti_air/SA-10_S-300PS_Battery.yaml b/resources/templates/anti_air/SA-10_S-300PS_Battery.yaml
new file mode 100644
index 00000000..191f354b
--- /dev/null
+++ b/resources/templates/anti_air/SA-10_S-300PS_Battery.yaml
@@ -0,0 +1,62 @@
+name: SA-10/S-300PS Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-10/S-300PS Battery SR1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PS 40B6MD sr
+ - name: SA-10/S-300PS Battery SR2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PS 64H6E sr
+ - name: SA-10/S-300PS Battery CP
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PS 54K6 cp
+ - name: SA-10/S-300PS Battery TR
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PS 40B6M tr
+ - name: SA-10/S-300PS Battery LN1
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300PS 5P85C ln
+ - name: SA-10/S-300PS Battery LN2
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300PS 5P85D ln
+ - name: SA-10/S-300PS Battery AAA
+ group: 2
+ unit_count:
+ - 2
+ unit_classes:
+ - AAA
+ - name: SA-10/S-300PS Battery SHORAD1
+ group: 3
+ unit_count:
+ - 0
+ - 2
+ unit_classes:
+ - SHORAD
+# - name: SA-10/S-300PS Battery SHORAD2
+# group: 3
+# unit_count:
+# - 0
+# - 2
+# unit_classes:
+# - SHORAD
+template_file: resources/templates/anti_air/SA-10.miz
diff --git a/resources/templates/anti_air/SA-11_Buk_Battery.yaml b/resources/templates/anti_air/SA-11_Buk_Battery.yaml
new file mode 100644
index 00000000..5c1438b4
--- /dev/null
+++ b/resources/templates/anti_air/SA-11_Buk_Battery.yaml
@@ -0,0 +1,21 @@
+name: SA-11 Buk Battery
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: SA-11 Buk Battery 0
+ unit_count:
+ - 1
+ unit_types:
+ - SA-11 Buk SR 9S18M1
+ - name: SA-11 Buk Battery 1
+ unit_count:
+ - 1
+ unit_types:
+ - SA-11 Buk CC 9S470M1
+ - name: SA-11 Buk Battery 2
+ unit_count:
+ - 4
+ unit_types:
+ - SA-11 Buk LN 9A310M1
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-12_S-300V_Battery.yaml b/resources/templates/anti_air/SA-12_S-300V_Battery.yaml
new file mode 100644
index 00000000..d322f26f
--- /dev/null
+++ b/resources/templates/anti_air/SA-12_S-300V_Battery.yaml
@@ -0,0 +1,54 @@
+name: SA-12/S-300V Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-12/S-300V Battery 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300V 9S15 sr
+ - name: SA-12/S-300V Battery 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300V 9S19 sr
+ - name: SA-12/S-300V Battery 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300V 9S457 cp
+ - name: SA-12/S-300V Battery 3
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300V 9S32 tr
+ - name: SA-12/S-300V Battery 4
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300V 9A82 ln
+ - name: SA-12/S-300V Battery 5
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300V 9A83 ln
+ - name: SA-12/S-300V Battery 6
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - 2S6 Tunguska
+ - name: SA-12/S-300V Battery 7
+ group: 3
+ unit_count:
+ - 2
+ unit_types:
+ - Tor 9A331
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-17_Grizzly_Battery.yaml b/resources/templates/anti_air/SA-17_Grizzly_Battery.yaml
new file mode 100644
index 00000000..42a68d5b
--- /dev/null
+++ b/resources/templates/anti_air/SA-17_Grizzly_Battery.yaml
@@ -0,0 +1,21 @@
+name: SA-17 Grizzly Battery
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: SA-17 Grizzly Battery 0
+ unit_count:
+ - 1
+ unit_types:
+ - SA-11 Buk SR 9S18M1
+ - name: SA-17 Grizzly Battery 1
+ unit_count:
+ - 1
+ unit_types:
+ - SA-11 Buk CC 9S470M1
+ - name: SA-17 Grizzly Battery 2
+ unit_count:
+ - 3
+ unit_types:
+ - SA-17 Buk M1-2 LN 9A310M1-2
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-20B_S-300PMU-2_Battery.yaml b/resources/templates/anti_air/SA-20B_S-300PMU-2_Battery.yaml
new file mode 100644
index 00000000..3388a534
--- /dev/null
+++ b/resources/templates/anti_air/SA-20B_S-300PMU-2_Battery.yaml
@@ -0,0 +1,48 @@
+name: SA-20B/S-300PMU-2 Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-20B/S-300PMU-2 Battery 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 40B6MD sr
+ - name: SA-20B/S-300PMU-2 Battery 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 64N6E sr
+ - name: SA-20B/S-300PMU-2 Battery 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU2 54K6E2 cp
+ - name: SA-20B/S-300PMU-2 Battery 3
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU2 92H6E tr
+ - name: SA-20B/S-300PMU-2 Battery 4
+ group: 1
+ unit_count:
+ - 6
+ unit_types:
+ - S-300PMU2 5P85SE2 ln
+ - name: SA-20B/S-300PMU-2 Battery 5
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - 2S6 Tunguska
+ - name: SA-20B/S-300PMU-2 Battery 6
+ group: 3
+ unit_count:
+ - 2
+ unit_types:
+ - Tor 9A331
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-20_S-300PMU-1_Battery.yaml b/resources/templates/anti_air/SA-20_S-300PMU-1_Battery.yaml
new file mode 100644
index 00000000..3cc02315
--- /dev/null
+++ b/resources/templates/anti_air/SA-20_S-300PMU-1_Battery.yaml
@@ -0,0 +1,54 @@
+name: SA-20/S-300PMU-1 Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-20/S-300PMU-1 Battery 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 40B6MD sr
+ - name: SA-20/S-300PMU-1 Battery 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 64N6E sr
+ - name: SA-20/S-300PMU-1 Battery 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 54K6 cp
+ - name: SA-20/S-300PMU-1 Battery 3
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300PMU1 40B6M tr
+ - name: SA-20/S-300PMU-1 Battery 4
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300PMU1 5P85CE ln
+ - name: SA-20/S-300PMU-1 Battery 5
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300PMU1 5P85DE ln
+ - name: SA-20/S-300PMU-1 Battery 6
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - 2S6 Tunguska
+ - name: SA-20/S-300PMU-1 Battery 7
+ group: 3
+ unit_count:
+ - 2
+ unit_types:
+ - Tor 9A331
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-23_S-300VM_Battery.yaml b/resources/templates/anti_air/SA-23_S-300VM_Battery.yaml
new file mode 100644
index 00000000..5c4f431b
--- /dev/null
+++ b/resources/templates/anti_air/SA-23_S-300VM_Battery.yaml
@@ -0,0 +1,54 @@
+name: SA-23/S-300VM Battery
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-23/S-300VM Battery 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300VM 9S15M2 sr
+ - name: SA-23/S-300VM Battery 1
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300VM 9S19M2 sr
+ - name: SA-23/S-300VM Battery 2
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300VM 9S457ME cp
+ - name: SA-23/S-300VM Battery 3
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - S-300VM 9S32ME tr
+ - name: SA-23/S-300VM Battery 4
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300VM 9A82ME ln
+ - name: SA-23/S-300VM Battery 5
+ group: 1
+ unit_count:
+ - 3
+ unit_types:
+ - S-300VM 9A83ME ln
+ - name: SA-23/S-300VM Battery 6
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - 2S6 Tunguska
+ - name: SA-23/S-300VM Battery 7
+ group: 3
+ unit_count:
+ - 2
+ unit_types:
+ - Tor 9A331
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-2_S-75_Site.yaml b/resources/templates/anti_air/SA-2_S-75_Site.yaml
new file mode 100644
index 00000000..2bff4a59
--- /dev/null
+++ b/resources/templates/anti_air/SA-2_S-75_Site.yaml
@@ -0,0 +1,21 @@
+name: SA-2/S-75 Site
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: SA-2/S-75 Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - p-19 s-125 sr
+ - name: SA-2/S-75 Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - SNR_75V
+ - name: SA-2/S-75 Site 2
+ unit_count:
+ - 6
+ unit_types:
+ - S_75M_Volhov
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-3_S-125_Site.yaml b/resources/templates/anti_air/SA-3_S-125_Site.yaml
new file mode 100644
index 00000000..40ec7872
--- /dev/null
+++ b/resources/templates/anti_air/SA-3_S-125_Site.yaml
@@ -0,0 +1,21 @@
+name: SA-3/S-125 Site
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: SA-3/S-125 Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - p-19 s-125 sr
+ - name: SA-3/S-125 Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - snr s-125 tr
+ - name: SA-3/S-125 Site 2
+ unit_count:
+ - 4
+ unit_types:
+ - 5p73 s-125 ln
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-5_S-200_Site.yaml b/resources/templates/anti_air/SA-5_S-200_Site.yaml
new file mode 100644
index 00000000..5a8dae94
--- /dev/null
+++ b/resources/templates/anti_air/SA-5_S-200_Site.yaml
@@ -0,0 +1,26 @@
+name: SA-5/S-200 Site
+role: AntiAir
+tasks:
+ - LORAD
+groups:
+ - name: SA-5/S-200 Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - RLS_19J6
+ - name: SA-5/S-200 Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - RPC_5N62V
+ - name: SA-5/S-200 Site 2
+ unit_count:
+ - 1
+ unit_types:
+ - Ural-375
+ - name: SA-5/S-200 Site 3
+ unit_count:
+ - 6
+ unit_types:
+ - S-200_Launcher
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/SA-6_Kub_Site.yaml b/resources/templates/anti_air/SA-6_Kub_Site.yaml
new file mode 100644
index 00000000..72b51c41
--- /dev/null
+++ b/resources/templates/anti_air/SA-6_Kub_Site.yaml
@@ -0,0 +1,16 @@
+name: SA-6 Kub Site
+role: AntiAir
+tasks:
+ - MERAD
+groups:
+ - name: SA-6 Kub Site 0
+ unit_count:
+ - 1
+ unit_types:
+ - Kub 1S91 str
+ - name: SA-6 Kub Site 1
+ unit_count:
+ - 4
+ unit_types:
+ - Kub 2P25 ln
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/Short_Range_Anti_Air.yaml b/resources/templates/anti_air/Short_Range_Anti_Air.yaml
new file mode 100644
index 00000000..f9ac7dc9
--- /dev/null
+++ b/resources/templates/anti_air/Short_Range_Anti_Air.yaml
@@ -0,0 +1,19 @@
+name: Short Range Anti Air Group
+role: AntiAir
+generic: true
+tasks:
+ - SHORAD
+groups:
+ - name: SHORAD Group 0
+ unit_count:
+ - 2
+ unit_classes:
+ - SHORAD
+ - name: SHORAD Group 1
+ optional: true
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - Logistics
+template_file: resources/templates/anti_air/shorad.miz
diff --git a/resources/templates/anti_air/WW2_Ally_Flak_Site.yaml b/resources/templates/anti_air/WW2_Ally_Flak_Site.yaml
new file mode 100644
index 00000000..812e05ae
--- /dev/null
+++ b/resources/templates/anti_air/WW2_Ally_Flak_Site.yaml
@@ -0,0 +1,41 @@
+name: WW2 Ally Flak Site
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: WW2 Ally Flak Site 0
+ unit_count:
+ - 4
+ unit_types:
+ - QF_37_AA
+ - name: WW2 Ally Flak Site 1
+ unit_count:
+ - 8
+ unit_types:
+ - M1_37mm
+ - name: WW2 Ally Flak Site 2
+ unit_count:
+ - 8
+ unit_types:
+ - M45_Quadmount
+ - name: WW2 Ally Flak Site 3
+ unit_count:
+ - 1
+ unit_types:
+ - Willys_MB
+ - name: WW2 Ally Flak Site 4
+ unit_count:
+ - 1
+ unit_types:
+ - M30_CC
+ - name: WW2 Ally Flak Site 5
+ unit_count:
+ - 1
+ unit_types:
+ - M4_Tractor
+ - name: WW2 Ally Flak Site 6
+ unit_count:
+ - 1
+ unit_types:
+ - Bedford_MWD
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/WW2_Flak_Site.yaml b/resources/templates/anti_air/WW2_Flak_Site.yaml
new file mode 100644
index 00000000..f41ae68c
--- /dev/null
+++ b/resources/templates/anti_air/WW2_Flak_Site.yaml
@@ -0,0 +1,16 @@
+name: WW2 Flak Site
+role: AntiAir
+tasks:
+ - AAA
+groups:
+ - name: WW2 Flak Site 0
+ unit_count:
+ - 6
+ unit_types:
+ - flak18
+ - name: WW2 Flak Site 1
+ unit_count:
+ - 1
+ unit_types:
+ - Blitz_36-6700A
+template_file: resources/templates/anti_air/legacy_ground_templates.miz
diff --git a/resources/templates/anti_air/flak.miz b/resources/templates/anti_air/flak.miz
new file mode 100644
index 00000000..4226e980
Binary files /dev/null and b/resources/templates/anti_air/flak.miz differ
diff --git a/resources/templates/anti_air/legacy_ground_templates.miz b/resources/templates/anti_air/legacy_ground_templates.miz
new file mode 100644
index 00000000..4d1a5920
Binary files /dev/null and b/resources/templates/anti_air/legacy_ground_templates.miz differ
diff --git a/resources/templates/anti_air/shorad.miz b/resources/templates/anti_air/shorad.miz
new file mode 100644
index 00000000..c68e5795
Binary files /dev/null and b/resources/templates/anti_air/shorad.miz differ
diff --git a/resources/templates/buildings/allycamp1.yaml b/resources/templates/buildings/allycamp1.yaml
new file mode 100644
index 00000000..7118a4ee
--- /dev/null
+++ b/resources/templates/buildings/allycamp1.yaml
@@ -0,0 +1,83 @@
+name: allycamp1
+role: Building
+tasks:
+ - StrikeTarget
+ - AllyCamp
+groups:
+ - name: allycamp1 0
+ statics:
+ - allycamp1 0-0
+ - allycamp1 0-1
+ - allycamp1 0-2
+ - allycamp1 0-3
+ unit_count:
+ - 4
+ unit_types:
+ - FARP Tent
+ - name: allycamp1 1
+ statics:
+ - allycamp1 1-0
+ - allycamp1 1-1
+ - allycamp1 1-2
+ - allycamp1 1-3
+ - allycamp1 1-4
+ - allycamp1 1-5
+ - allycamp1 1-6
+ - allycamp1 1-7
+ - allycamp1 1-8
+ - allycamp1 1-9
+ - allycamp1 1-10
+ - allycamp1 1-11
+ - allycamp1 1-12
+ - allycamp1 1-13
+ - allycamp1 1-14
+ - allycamp1 1-15
+ - allycamp1 1-16
+ - allycamp1 1-17
+ - allycamp1 1-18
+ - allycamp1 1-19
+ - allycamp1 1-20
+ - allycamp1 1-21
+ unit_count:
+ - 22
+ unit_types:
+ - Haystack 4
+ - name: allycamp1 2
+ statics:
+ - allycamp1 2-0
+ - allycamp1 2-1
+ - allycamp1 2-2
+ - allycamp1 2-3
+ - allycamp1 2-4
+ - allycamp1 2-5
+ - allycamp1 2-6
+ - allycamp1 2-7
+ - allycamp1 2-8
+ - allycamp1 2-9
+ - allycamp1 2-10
+ - allycamp1 2-11
+ unit_count:
+ - 12
+ unit_types:
+ - Haystack 3
+ - name: allycamp1 3
+ statics:
+ - allycamp1 3-0
+ - allycamp1 3-1
+ - allycamp1 3-2
+ - allycamp1 3-3
+ - allycamp1 3-4
+ - allycamp1 3-5
+ - allycamp1 3-6
+ - allycamp1 3-7
+ unit_count:
+ - 8
+ unit_types:
+ - Concertina wire
+ - name: allycamp1 4
+ group: 2 # Vehicle and static can not be mixed
+ unit_count:
+ - 4
+ unit_types:
+ - house2arm
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/ammo1.yaml b/resources/templates/buildings/ammo1.yaml
new file mode 100644
index 00000000..c8b13c2a
--- /dev/null
+++ b/resources/templates/buildings/ammo1.yaml
@@ -0,0 +1,21 @@
+name: ammo1
+role: Building
+tasks:
+ - Ammo
+groups:
+ - name: ammo1 0
+ statics:
+ - ammo1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - .Ammunition depot
+ - name: ammo1 1
+ statics:
+ - ammo1 1-0
+ - ammo1 1-1
+ unit_count:
+ - 2
+ unit_types:
+ - Hangar B
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/buildings.miz b/resources/templates/buildings/buildings.miz
new file mode 100644
index 00000000..a63abb1d
Binary files /dev/null and b/resources/templates/buildings/buildings.miz differ
diff --git a/resources/templates/buildings/comms.yaml b/resources/templates/buildings/comms.yaml
new file mode 100644
index 00000000..1d12d866
--- /dev/null
+++ b/resources/templates/buildings/comms.yaml
@@ -0,0 +1,15 @@
+name: comms
+role: Building
+tasks:
+ - StrikeTarget
+ - Comms
+groups:
+ - name: comms1 0
+ statics:
+ - comms1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - TV tower
+ - Comms tower M
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/derrick1.yaml b/resources/templates/buildings/derrick1.yaml
new file mode 100644
index 00000000..831dd032
--- /dev/null
+++ b/resources/templates/buildings/derrick1.yaml
@@ -0,0 +1,30 @@
+name: derrick1
+role: Building
+tasks:
+ - StrikeTarget
+ - Derrick
+groups:
+ - name: derrick1 0
+ statics:
+ - derrick1 0-0
+ - derrick1 0-1
+ unit_count:
+ - 2
+ unit_types:
+ - Oil derrick
+ - name: derrick1 1
+ statics:
+ - derrick1 1-0
+ - derrick1 1-1
+ unit_count:
+ - 2
+ unit_types:
+ - Pump station
+ - name: derrick1 2
+ statics:
+ - derrick1 2-0
+ unit_count:
+ - 1
+ unit_types:
+ - Subsidiary structure 2
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/factory1.yaml b/resources/templates/buildings/factory1.yaml
new file mode 100644
index 00000000..305224e4
--- /dev/null
+++ b/resources/templates/buildings/factory1.yaml
@@ -0,0 +1,22 @@
+name: factory1
+role: Building
+tasks:
+ - Factory
+groups:
+ - name: factory1 0
+ statics:
+ - factory1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - Tech combine
+ - name: factory1 1
+ statics:
+ - factory1 1-0
+ - factory1 1-1
+ - factory1 1-2
+ unit_count:
+ - 3
+ unit_types:
+ - Tech hangar A
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/farp1.yaml b/resources/templates/buildings/farp1.yaml
new file mode 100644
index 00000000..9589efe6
--- /dev/null
+++ b/resources/templates/buildings/farp1.yaml
@@ -0,0 +1,40 @@
+name: farp1
+role: Building
+tasks:
+ - StrikeTarget
+ - Farp
+groups:
+ - name: farp1 0
+ statics:
+ - farp1 0-0
+ - farp1 0-1
+ - farp1 0-2
+ - farp1 0-3
+ - farp1 0-4
+ unit_count:
+ - 5
+ unit_types:
+ - FARP Tent
+ - name: farp1 1
+ statics:
+ - farp1 1-0
+ unit_count:
+ - 1
+ unit_types:
+ - FARP Ammo Dump Coating
+ - name: farp1 2
+ statics:
+ - farp1 2-0
+ unit_count:
+ - 1
+ unit_types:
+ - FARP CP Blindage
+ - name: farp1 3
+ statics:
+ - farp1 3-0
+ - farp1 3-1
+ unit_count:
+ - 2
+ unit_types:
+ - FARP Fuel Depot
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/fob1.yaml b/resources/templates/buildings/fob1.yaml
new file mode 100644
index 00000000..aa7341aa
--- /dev/null
+++ b/resources/templates/buildings/fob1.yaml
@@ -0,0 +1,30 @@
+name: fob1
+role: Building
+tasks:
+ - FOB
+groups:
+ - name: fob1 0
+ statics:
+ - fob1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - .Command Center
+ - name: fob1 1
+ statics:
+ - fob1 1-0
+ - fob1 1-1
+ - fob1 1-2
+ unit_count:
+ - 3
+ unit_types:
+ - Barracks 2
+ - name: fob1 2
+ statics:
+ - fob1 2-0
+ - fob1 2-1
+ unit_count:
+ - 2
+ unit_types:
+ - Garage small B
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/fuel1.yaml b/resources/templates/buildings/fuel1.yaml
new file mode 100644
index 00000000..de10eef2
--- /dev/null
+++ b/resources/templates/buildings/fuel1.yaml
@@ -0,0 +1,27 @@
+name: fuel1
+role: Building
+tasks:
+ - StrikeTarget
+ - Fuel
+groups:
+ - name: fuel1 0
+ statics:
+ - fuel1 0-0
+ - fuel1 0-1
+ - fuel1 0-2
+ - fuel1 0-3
+ - fuel1 0-4
+ - fuel1 0-5
+ unit_count:
+ - 6
+ unit_types:
+ - Tank
+ - name: fuel1 1
+ statics:
+ - fuel1 1-0
+ - fuel1 1-1
+ unit_count:
+ - 2
+ unit_types:
+ - Tank 3
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/oil1.yaml b/resources/templates/buildings/oil1.yaml
new file mode 100644
index 00000000..d56e0ad7
--- /dev/null
+++ b/resources/templates/buildings/oil1.yaml
@@ -0,0 +1,17 @@
+name: oil1
+role: Building
+tasks:
+ - OffShoreStrikeTarget
+ - Oil
+groups:
+ - name: oil1 0
+ statics:
+ - oil1 0-0
+ - oil1 0-1
+ - oil1 0-2
+ - oil1 0-3
+ unit_count:
+ - 4
+ unit_types:
+ - Oil platform
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/power1.yaml b/resources/templates/buildings/power1.yaml
new file mode 100644
index 00000000..526cb4d5
--- /dev/null
+++ b/resources/templates/buildings/power1.yaml
@@ -0,0 +1,36 @@
+name: power1
+role: Building
+tasks:
+ - StrikeTarget
+ - Power
+groups:
+ - name: power1 0
+ statics:
+ - power1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - Repair workshop
+ - name: power1 1
+ statics:
+ - power1 1-0
+ unit_count:
+ - 1
+ unit_types:
+ - Workshop A
+ - name: power1 2
+ statics:
+ - power1 2-0
+ - power1 2-1
+ unit_count:
+ - 2
+ unit_types:
+ - Garage B
+ - name: power1 3
+ statics:
+ - power1 3-0
+ unit_count:
+ - 1
+ unit_types:
+ - Farm B
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/village1.yaml b/resources/templates/buildings/village1.yaml
new file mode 100644
index 00000000..f75ff93f
--- /dev/null
+++ b/resources/templates/buildings/village1.yaml
@@ -0,0 +1,38 @@
+name: village1
+role: Building
+tasks:
+ - StrikeTarget
+ - Village
+groups:
+ - name: village1 0
+ statics:
+ - village1 0-0
+ - village1 0-1
+ unit_count:
+ - 2
+ unit_types:
+ - Small house 1A
+ - name: village1 1
+ statics:
+ - village1 1-0
+ - village1 1-1
+ - village1 1-2
+ - village1 1-3
+ - village1 1-4
+ - village1 1-5
+ - village1 1-6
+ - village1 1-7
+ unit_count:
+ - 8
+ unit_types:
+ - Small werehouse 1
+ - name: village1 2
+ statics:
+ - village1 2-0
+ - village1 2-1
+ - village1 2-2
+ unit_count:
+ - 3
+ unit_types:
+ - Small house 1B
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/ware1.yaml b/resources/templates/buildings/ware1.yaml
new file mode 100644
index 00000000..dd19f466
--- /dev/null
+++ b/resources/templates/buildings/ware1.yaml
@@ -0,0 +1,23 @@
+name: ware1
+role: Building
+tasks:
+ - StrikeTarget
+ - Ware
+groups:
+ - name: ware1 0
+ statics:
+ - ware1 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - Warehouse
+ - name: ware1 1
+ statics:
+ - ware1 1-0
+ - ware1 1-1
+ - ware1 1-2
+ unit_count:
+ - 3
+ unit_types:
+ - Hangar A
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/ww2bunker1.yaml b/resources/templates/buildings/ww2bunker1.yaml
new file mode 100644
index 00000000..2ee19d35
--- /dev/null
+++ b/resources/templates/buildings/ww2bunker1.yaml
@@ -0,0 +1,33 @@
+name: ww2bunker1
+role: Building
+tasks:
+ - StrikeTarget
+ - WW2Bunker
+groups:
+ - name: ww2bunker1 0
+ statics:
+ - ww2bunker1 0-0
+ - ww2bunker1 0-1
+ - ww2bunker1 0-2
+ - ww2bunker1 0-3
+ unit_count:
+ - 4
+ unit_types:
+ - Siegfried Line
+ - name: ww2bunker1 1
+ statics:
+ - ww2bunker1 1-0
+ - ww2bunker1 1-1
+ - ww2bunker1 1-2
+ - ww2bunker1 1-3
+ unit_count:
+ - 4
+ unit_types:
+ - Fire Control Bunker
+ - name: ww2bunker1 2
+ group: 2 # Vehicle and static can not be mixed
+ unit_count:
+ - 4
+ unit_types:
+ - SK_C_28_naval_gun
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/buildings/ww2bunker2.yaml b/resources/templates/buildings/ww2bunker2.yaml
new file mode 100644
index 00000000..3f7e6f80
--- /dev/null
+++ b/resources/templates/buildings/ww2bunker2.yaml
@@ -0,0 +1,56 @@
+name: ww2bunker2
+role: Building
+tasks:
+ - StrikeTarget
+ - WW2Bunker
+groups:
+ - name: ww2bunker2 0
+ statics:
+ - ww2bunker2 0-0
+ unit_count:
+ - 1
+ unit_types:
+ - Fire Control Bunker
+ - name: ww2bunker2 1
+ statics:
+ - ww2bunker2 1-0
+ - ww2bunker2 1-1
+ unit_count:
+ - 2
+ unit_types:
+ - Siegfried Line
+ - name: ww2bunker2 2
+ statics:
+ - ww2bunker2 2-0
+ - ww2bunker2 2-1
+ - ww2bunker2 2-2
+ - ww2bunker2 2-3
+ - ww2bunker2 2-4
+ - ww2bunker2 2-5
+ - ww2bunker2 2-6
+ - ww2bunker2 2-7
+ unit_count:
+ - 8
+ unit_types:
+ - Concertina wire
+ - name: ww2bunker2 3
+ statics:
+ - ww2bunker2 3-0
+ unit_count:
+ - 1
+ unit_types:
+ - Belgian gate
+ - name: ww2bunker2 4
+ statics:
+ - ww2bunker2 4-0
+ - ww2bunker2 4-1
+ - ww2bunker2 4-2
+ - ww2bunker2 4-3
+ - ww2bunker2 4-4
+ - ww2bunker2 4-5
+ - ww2bunker2 4-6
+ unit_count:
+ - 7
+ unit_types:
+ - Czech hedgehogs 1
+template_file: resources/templates/buildings/buildings.miz
diff --git a/resources/templates/defenses/Silkworm.yaml b/resources/templates/defenses/Silkworm.yaml
new file mode 100644
index 00000000..5929ca7b
--- /dev/null
+++ b/resources/templates/defenses/Silkworm.yaml
@@ -0,0 +1,34 @@
+name: Silkworm
+role: Defenses
+tasks:
+ - Coastal
+groups:
+ - name: SilkwormGenerator 0
+ unit_count:
+ - 1
+ unit_classes:
+ - SearchRadar
+ - name: SilkwormGenerator 1
+ unit_count:
+ - 5
+ unit_classes:
+ - Missile
+ - name: SilkwormGenerator 2
+ optional: true
+ unit_count:
+ - 1
+ unit_classes:
+ - Logistics
+ - name: SilkwormGenerator 3
+ optional: true
+ unit_count:
+ - 1
+ unit_classes:
+ - AAA
+ - name: SilkwormGenerator 4
+ optional: true
+ unit_count:
+ - 1
+ unit_classes:
+ - SHORAD
+template_file: resources/templates/defenses/defenses.miz
\ No newline at end of file
diff --git a/resources/templates/defenses/defenses.miz b/resources/templates/defenses/defenses.miz
new file mode 100644
index 00000000..40c5d71a
Binary files /dev/null and b/resources/templates/defenses/defenses.miz differ
diff --git a/resources/templates/defenses/missile.yaml b/resources/templates/defenses/missile.yaml
new file mode 100644
index 00000000..bd9d45d1
--- /dev/null
+++ b/resources/templates/defenses/missile.yaml
@@ -0,0 +1,29 @@
+name: Missile
+role: Defenses
+generic: true
+tasks:
+ - Missile
+groups:
+ - name: ScudGenerator 0
+ unit_count:
+ - 3
+ unit_classes:
+ - Missile
+ - name: ScudGenerator 1
+ unit_count:
+ - 1
+ unit_classes:
+ - Logistics
+ - name: ScudGenerator 2
+ optional: true
+ unit_count:
+ - 1
+ unit_classes:
+ - AAA
+ - name: ScudGenerator 3
+ optional: true
+ unit_count:
+ - 1
+ unit_classes:
+ - SHORAD
+template_file: resources/templates/defenses/defenses.miz
diff --git a/resources/templates/ground_forces/Armor_Group.yaml b/resources/templates/ground_forces/Armor_Group.yaml
new file mode 100644
index 00000000..22d0b24a
--- /dev/null
+++ b/resources/templates/ground_forces/Armor_Group.yaml
@@ -0,0 +1,17 @@
+name: Armor Group
+role: GroundForce
+generic: true
+tasks:
+ - BaseDefense
+ - FrontLine
+groups:
+ - name: Armor Group 0
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - APC
+ - ATGM
+ - IFV
+ - Tank
+template_file: resources/templates/ground_forces/ground_forces.miz
diff --git a/resources/templates/ground_forces/Armor_Group_with_Anti-Air.yaml b/resources/templates/ground_forces/Armor_Group_with_Anti-Air.yaml
new file mode 100644
index 00000000..2d9dec29
--- /dev/null
+++ b/resources/templates/ground_forces/Armor_Group_with_Anti-Air.yaml
@@ -0,0 +1,26 @@
+name: Armor Group with Anti-Air
+role: GroundForce
+generic: true
+tasks:
+ - BaseDefense
+ - FrontLine
+groups:
+ - name: Armor Group with Anti-Air 0
+ unit_count:
+ - 2
+ - 6
+ unit_classes:
+ - APC
+ - ATGM
+ - IFV
+ - Tank
+ - name: Armor Group with Anti-Air 1
+ optional: true
+ unit_count:
+ - 1
+ - 2
+ unit_classes:
+ - AAA
+ - SHORAD
+ - Manpad
+template_file: resources/templates/ground_forces/ground_forces.miz
diff --git a/resources/templates/ground_forces/ground_forces.miz b/resources/templates/ground_forces/ground_forces.miz
new file mode 100644
index 00000000..45457eb7
Binary files /dev/null and b/resources/templates/ground_forces/ground_forces.miz differ
diff --git a/resources/templates/naval/Carrier_Group.yaml b/resources/templates/naval/Carrier_Group.yaml
new file mode 100644
index 00000000..bbadbcb0
--- /dev/null
+++ b/resources/templates/naval/Carrier_Group.yaml
@@ -0,0 +1,19 @@
+name: Carrier Group
+role: Naval
+generic: true
+tasks:
+ - AircraftCarrier
+groups:
+ - name: Carrier Group 0
+ group: 1
+ unit_count:
+ - 1
+ unit_classes:
+ - AircraftCarrier
+ - name: Carrier Group 1
+ group: 2
+ unit_count:
+ - 4
+ unit_classes:
+ - Destroyer
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/Carrier_Strike_Group_8.yaml b/resources/templates/naval/Carrier_Strike_Group_8.yaml
new file mode 100644
index 00000000..7d244604
--- /dev/null
+++ b/resources/templates/naval/Carrier_Strike_Group_8.yaml
@@ -0,0 +1,25 @@
+name: Carrier Strike Group 8
+role: Naval
+generic: true
+tasks:
+ - AircraftCarrier
+groups:
+ - name: Carrier Strike Group 8 0
+ group: 1
+ unit_count:
+ - 1
+ unit_types:
+ - Stennis
+ - name: Carrier Strike Group 8 1
+ group: 2
+ unit_count:
+ - 5
+ unit_types:
+ - USS_Arleigh_Burke_IIa
+ - name: Carrier Strike Group 8 2
+ group: 2
+ unit_count:
+ - 2
+ unit_types:
+ - TICONDEROG
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/Chinese-Navy.yaml b/resources/templates/naval/Chinese-Navy.yaml
new file mode 100644
index 00000000..84684247
--- /dev/null
+++ b/resources/templates/naval/Chinese-Navy.yaml
@@ -0,0 +1,19 @@
+name: Chinese Navy
+role: Naval
+tasks:
+ - Navy
+groups:
+ - name: Chinese Navy 0
+ unit_count:
+ - 0
+ - 2
+ unit_types:
+ - Type_054A
+ - name: Chinese Navy 1
+ unit_count:
+ - 0
+ - 2
+ unit_types:
+ - Type_052C
+ - Type_052B
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/LHA_Group.yaml b/resources/templates/naval/LHA_Group.yaml
new file mode 100644
index 00000000..0d0eff4e
--- /dev/null
+++ b/resources/templates/naval/LHA_Group.yaml
@@ -0,0 +1,19 @@
+name: LHA Group
+generic: true
+role: Naval
+tasks:
+ - HelicopterCarrier
+groups:
+ - name: LHA Group 0
+ group: 1
+ unit_count:
+ - 1
+ unit_classes:
+ - HelicopterCarrier
+ - name: LHA Group 1
+ group: 2
+ unit_count:
+ - 2
+ unit_classes:
+ - Destroyer
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/Naval-Two-Ship.yaml b/resources/templates/naval/Naval-Two-Ship.yaml
new file mode 100644
index 00000000..690e161b
--- /dev/null
+++ b/resources/templates/naval/Naval-Two-Ship.yaml
@@ -0,0 +1,16 @@
+name: Naval Two Ship
+role: Naval
+generic: true
+tasks:
+ - Navy
+groups:
+ - name: Naval Group 0
+ unit_count:
+ - 2
+ unit_classes:
+ - Destroyer
+ - Cruiser
+ - Boat
+ - Submarine
+ - LandingShip
+template_file: resources/templates/naval/naval.miz
diff --git a/resources/templates/naval/Russian-Navy.yaml b/resources/templates/naval/Russian-Navy.yaml
new file mode 100644
index 00000000..32286e3a
--- /dev/null
+++ b/resources/templates/naval/Russian-Navy.yaml
@@ -0,0 +1,27 @@
+name: Russian Navy
+role: Naval
+tasks:
+ - Navy
+groups:
+ - name: Russian Navy 0
+ unit_count:
+ - 0
+ - 2
+ unit_types:
+ - ALBATROS
+ - MOLNIYA
+ - name: Russian Navy 1
+ unit_count:
+ - 0
+ - 2
+ unit_types:
+ - NEUSTRASH
+ - REZKY
+ - name: Russian Navy 2
+ optional: true
+ unit_count:
+ - 0
+ - 1
+ unit_types:
+ - MOSCOW
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/WW2-LST.yaml b/resources/templates/naval/WW2-LST.yaml
new file mode 100644
index 00000000..bffc8a6a
--- /dev/null
+++ b/resources/templates/naval/WW2-LST.yaml
@@ -0,0 +1,16 @@
+name: WW2 LST Group
+role: Naval
+tasks:
+ - Navy
+groups:
+ - name: WW2 LST Group 0
+ unit_count:
+ - 1
+ unit_types:
+ - USS_Samuel_Chase
+ - name: WW2 LST Group 1
+ unit_count:
+ - 3
+ unit_types:
+ - LST_Mk2
+template_file: resources/templates/naval/legacy_naval_templates.miz
diff --git a/resources/templates/naval/legacy_naval_templates.miz b/resources/templates/naval/legacy_naval_templates.miz
new file mode 100644
index 00000000..cf8fb7c5
Binary files /dev/null and b/resources/templates/naval/legacy_naval_templates.miz differ
diff --git a/resources/templates/naval/naval.miz b/resources/templates/naval/naval.miz
new file mode 100644
index 00000000..a23b2a8a
Binary files /dev/null and b/resources/templates/naval/naval.miz differ
diff --git a/resources/templates/original_generator_layouts.miz b/resources/templates/original_generator_layouts.miz
new file mode 100644
index 00000000..914ea7b0
Binary files /dev/null and b/resources/templates/original_generator_layouts.miz differ
diff --git a/resources/tools/template_helper.py b/resources/tools/template_helper.py
index e7311fab..2389eb97 100644
--- a/resources/tools/template_helper.py
+++ b/resources/tools/template_helper.py
@@ -8,22 +8,46 @@ from datetime import datetime
from pathlib import Path
from typing import Optional, Any, Iterator
+import yaml
+from dcs.ships import ship_map
+from dcs.unit import Unit
+from dcs.vehicles import vehicle_map
from tabulate import tabulate
import dcs
from dcs import Point
-from game import Game
+from game import Game, db
from game.campaignloader import CampaignAirWingConfig
+from game.data.groups import GroupRole, GroupTask, ROLE_TASKINGS
+from game.data.units import UnitClass
from game.db import FACTIONS
+from game.dcs.groundunittype import GroundUnitType
+from game.dcs.shipunittype import ShipUnitType
from game.missiongenerator.tgogenerator import (
GroundObjectGenerator,
)
from game.point_with_heading import PointWithHeading
from game.settings import Settings
from game.theater import CaucasusTheater, OffMapSpawn
+from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings
+from game.theater.theatergroundobject import AirDefenseRange, SamGroundObject
from game.unitmap import UnitMap
from game.utils import Heading
+from gen.templates import (
+ GroundObjectTemplates,
+ GroupTemplate,
+ UnitTemplate,
+ BuildingTemplate,
+ DefensesTemplate,
+ NavalTemplate,
+ TemplateMapping,
+ GroupTemplateMapping,
+ AntiAirTemplate,
+ GroundForceTemplate,
+)
+from gen.naming import namegen
+from qt_ui import liberation_install
from gen.to_remove.armored_group_generator import (
FixedSizeArmorGroupGenerator,
FixedSizeArmorGroupGeneratorWithAA,
@@ -35,245 +59,23 @@ from gen.to_remove.carrier_group import (
from gen.to_remove.lha_group import LHAGroupGenerator
from gen.to_remove.ship_group_generator import SHIP_MAP
from gen.to_remove.coastal_group_generator import COASTAL_MAP
-from gen.templates import (
- GroundObjectTemplates,
- TemplateCategory,
- GroupTemplate,
- UnitTemplate,
- TemplateEncoder,
- MissileTemplate,
- BuildingTemplate,
- CoastalTemplate,
- NavalTemplate,
- TemplateRandomizer,
- ArmorTemplate,
- TEMPLATE_TYPES,
- AirDefenceTemplate,
-)
from gen.to_remove.missiles_group_generator import MISSILES_MAP
from gen.to_remove.airdefensegroupgenerator import AirDefenseGroupGenerator
from gen.to_remove.ewr_group_generator import EWR_MAP
from gen.to_remove.ewrs import EwrGenerator
from gen.to_remove.sam_group_generator import SAM_MAP
-from gen.naming import namegen
-from qt_ui import liberation_install
-TEMPLATES_MIZ = "resources/templates/templates.miz"
+TEMPLATES_MIZ = "resources/templates/legacy_templates.miz"
MIGRATE_MIZ = "resources/tools/groundobject_templates.miz"
-TEMPLATES_BLOB = "resources/templates/templates.json"
-TEMPLATES_MAP = "resources/templates/template_map.json"
+TEMPLATES_FOLDER = "resources/templates/"
TABLE_FILE = "doc/templates/template_list.md"
-@dataclass
-class GroupTemplateMapping:
- name: str
- optional: bool
- unit_types: list[str]
- unit_classes: list[UnitClass]
-
- def to_json(self) -> dict[str, Any]:
- d = self.__dict__
- if not self.optional:
- d.pop("optional")
- if not self.unit_types:
- d.pop("unit_types")
- if not self.unit_classes:
- d.pop("unit_classes")
- return d
-
- @staticmethod
- def from_dict(d: dict[str, Any]) -> GroupTemplateMapping:
- optional = d["optional"] if "optional" in d else False
- return GroupTemplateMapping(
- d["name"], optional, d["unit_types"], d["unit_classes"]
- )
-
-
-@dataclass
-class TemplateMapping:
- name: str
- template_type: str
- description: str
- groups: list[GroupTemplateMapping]
- statics: list[str]
- static_mapping: Optional[GroupTemplateMapping] = None
-
- def to_json(self) -> dict[str, Any]:
- d = self.__dict__
- if not self.static_mapping:
- d.pop("static_mapping")
- return d
-
- @staticmethod
- def from_dict(d: dict[str, Any]) -> TemplateMapping:
- groups = [GroupTemplateMapping.from_dict(group) for group in d["groups"]]
- static_mapping = (
- GroupTemplateMapping.from_dict(d["static_mapping"])
- if "static_mapping" in d
- else None
- )
- return TemplateMapping(
- d["name"],
- d["template_type"],
- d["description"],
- groups,
- d["statics"],
- static_mapping,
- )
-
-
-class TemplateMap:
- _map: dict[str, list[TemplateMapping]] = {}
-
- def __init__(self):
- self._map = {}
-
- def __getitem__(self, item: str) -> list[TemplateMapping]:
- return self._map[item]
-
- def __setitem__(self, key, value) -> None:
- self._map[key] = value
-
- def to_json(self) -> dict[str, Any]:
- return self._map
-
- def mapping_for_template(self, template_name: str) -> tuple[str, TemplateMapping]:
- for category, mappings in self._map.items():
- for mapping in mappings:
- if mapping.name == template_name:
- return category, mapping
- raise RuntimeError(f"No mapping for template {template_name}")
-
- def mapping_for_group(
- self, group_name: str
- ) -> tuple[str, TemplateMapping, Optional[GroupTemplateMapping]]:
- for category, mappings in self._map.items():
- for mapping in mappings:
- for group_mapping in mapping.groups:
- if group_mapping.name == group_name:
- return category, mapping, group_mapping
- if group_name in mapping.statics:
- return category, mapping, mapping.static_mapping
- raise RuntimeError(f"No mapping for group {group_name}")
-
- @property
- def mappings(self) -> Iterator[TemplateMapping]:
- for mapping in self._map.values():
- yield mapping
-
-
-def import_templates(
- miz_file: str, template_map_file: str, target_file: str, table_file: str
-) -> None:
- """Imports the template miz and the template_map as json into liberation"""
- temp_mis = dcs.Mission()
- temp_mis.load_file(miz_file)
-
- templates = GroundObjectTemplates()
-
- with open(template_map_file, "r") as f:
- template_map_json = json.load(f)
-
- template_map = TemplateMap()
- for name, mappings in template_map_json.items():
- template_map[TemplateCategory(name)] = []
- for mapping in mappings:
- template_map[TemplateCategory(name)].append(
- TemplateMapping.from_dict(mapping)
- )
-
- template_position: dict[str, Point] = {}
- for static_group in temp_mis.country("USA").static_group:
- category, mapping, group_mapping = template_map.mapping_for_group(
- static_group.name
- )
- template = templates.by_category_and_name(
- TemplateCategory(category), mapping.name
- )
- static_template = None
- if not template:
- template = BuildingTemplate(
- mapping.name, mapping.template_type, mapping.description
- )
- static_template = GroupTemplate(mapping.name, [], True)
- if group_mapping:
- static_template.randomizer = group_mapping.randomizer
- static_template.optional = group_mapping.optional
- template.groups.append(static_template)
- templates.add_template(TemplateCategory(category), template)
-
- else:
- for group in template.groups:
- if mapping.name in group.name:
- static_template = group
-
- if not static_template:
- raise RuntimeError(f"No mapping for group {static_group.name}")
-
- for i, unit in enumerate(static_group.units):
- unit_template = UnitTemplate.from_unit(unit)
- if i == 0 and template.name not in template_position:
- template_position[template.name] = unit.position
- unit_template.position = (
- unit_template.position - template_position[template.name]
- )
- static_template.units.append(unit_template)
- pass
-
- for vehicle_group in (
- temp_mis.country("USA").vehicle_group + temp_mis.country("USA").ship_group
- ):
- category, mapping, group_mapping = template_map.mapping_for_group(
- vehicle_group.name
- )
- template = templates.by_category_and_name(
- TemplateCategory(category), mapping.name
- )
- if not template:
- template = TEMPLATE_TYPES[TemplateCategory(category)](
- mapping.name, mapping.template_type, mapping.description
- )
- templates.add_template(TemplateCategory(category), template)
- for i, unit in enumerate(vehicle_group.units):
- group_template = None
- for group in template.groups:
- if group.name == vehicle_group.name:
- group_template = group
- if not group_template:
- group_template = GroupTemplate(
- vehicle_group.name,
- [],
- False,
- group_mapping.randomizer,
- group_mapping.optional,
- )
- template.groups.append(group_template)
- unit_template = UnitTemplate.from_unit(unit)
- if i == 0 and template.name not in template_position:
- template_position[template.name] = unit.position
- unit_template.position = (
- unit_template.position - template_position[template.name]
- )
- group_template.units.append(unit_template)
- pass
-
- with open(target_file, "w") as f:
- json.dump(templates.to_json(), f, cls=TemplateEncoder, indent="\t")
-
- # print Table
- print_table(target_file, table_file)
-
-
def export_templates(
- templates_file: str, miz_file: str, template_map_file: str
+ miz_file: str, mapping_folder: str, templates: GroundObjectTemplates
) -> None:
- """Exports the templates.json to the templates.miz and the mapping"""
- # This function will only be used on mass jobs or specific fine tuning
-
- templates = GroundObjectTemplates.from_json(templates_file)
-
+ """Exports the migrated templates to the templates.miz and the mapping"""
# Prepare game
theater = CaucasusTheater()
initial_ground_position = Point(-500000, 250000)
@@ -283,34 +85,43 @@ def export_templates(
theater.add_controlpoint(control_point_ground)
theater.add_controlpoint(control_point_water)
- game = Game(
+ generator = GameGenerator(
FACTIONS["Bluefor Modern"],
FACTIONS["Russia 2010"],
theater,
CampaignAirWingConfig({control_point_ground: [], control_point_water: []}),
- datetime.today(),
Settings(),
- 10000,
- 10000,
+ GeneratorSettings(
+ start_date=datetime.today(),
+ player_budget=1000,
+ enemy_budget=1000,
+ inverted=False,
+ no_carrier=False,
+ no_lha=False,
+ no_player_navy=False,
+ no_enemy_navy=False,
+ ),
+ ModSettings(),
)
+ game = generator.generate()
+
+ # TODO Define combined forces as country so that the missioneditor type is correct
m = dcs.Mission(game.theater.terrain)
country = m.country("USA")
unit_map = UnitMap()
- template_map = TemplateMap()
offset_x = 0
offset_y = 0
- for count, template_category in enumerate(TemplateCategory):
- template_map[template_category.value] = []
- temmplates_for_category = list(templates.for_category(template_category))
+ for group_role in GroupRole:
+ temmplates_for_category = list(templates.for_role_and_task(group_role))
# Define the offset / separation
category_separation = 10000
group_separation = 5000
- if template_category in [TemplateCategory.Naval]:
+ if group_role == GroupRole.Naval:
initial_position = initial_water_position
control_point = control_point_water
else:
@@ -324,28 +135,28 @@ def export_templates(
for template in temmplates_for_category:
mapping = TemplateMapping(
template.name,
- template.template_type,
template.description,
+ template.category,
+ template.generic,
+ group_role,
+ template.tasks,
[],
- [],
+ miz_file,
)
position = Point(
initial_position.x + offset_x, initial_position.y + offset_y
)
- # Initialize the template
- for group_template in template.groups:
- if group_template.randomizer:
- group_template.randomizer.init_randomization_for_faction(
- game.blue.faction
- )
+ # Initialize the group template so that a unit can be selected
+ for group in template.groups:
+ game.blue.faction.initialize_group_template(group, False)
ground_object = template.generate(
template.name,
PointWithHeading.from_point(position, Heading.from_degrees(0)),
control_point,
game,
- False, # Do not use randomization during export!
+ merge_groups=False, # Do not merge groups for migration
)
for g_id, group in enumerate(ground_object.groups):
@@ -354,14 +165,15 @@ def export_templates(
unit.name = f"{template.name} {g_id}-{u_id}"
group_template = template.groups[g_id]
group_mapping = GroupTemplateMapping(
- group.name, group_template.optional, group_template.randomizer
+ group.name,
+ group_template.optional,
+ [unit.name for unit in group.units] if group.static_group else [],
+ group_template.group,
+ group_template.unit_count,
+ group_template.unit_types,
+ group_template.unit_classes,
)
- if group.static_group:
- for unit in group.units:
- mapping.statics.append(unit.name)
- # No mapping as we have no randomization yet
- else:
- mapping.groups.append(group_mapping)
+ mapping.groups.append(group_mapping)
generator = GroundObjectGenerator(ground_object, country, game, m, unit_map)
generator.generate(unique_name=False) # Prevent the ID prefix
@@ -372,87 +184,25 @@ def export_templates(
offset_y = current_separation
offset_x += group_separation
- template_map[template_category.name].append(mapping)
- # Dump the template_map as json
- with open(template_map_file, "w") as f:
- json.dump(template_map, f, cls=TemplateEncoder, sort_keys=True, indent="\t")
+ # Export the mapping as yaml
+ mapping.export(mapping_folder)
m.save(miz_file)
-def print_table(templates_file: str, table_file: str) -> None:
- # Category # Sub Category # Template Name # Unit_types
-
- templates = GroundObjectTemplates.from_json(templates_file)
- table = []
-
- for template_category in TemplateCategory:
- category_templates = list(templates.for_category(template_category))
- for template in sorted(
- category_templates, key=lambda x: (x.template_type, x.name)
- ):
- groups = []
- options = []
- for group in template.groups:
- units = []
- group_options = []
- for unit in group.units:
- units.append(unit.type)
- groups.append("" + ", ".join(units) + "")
- if group.randomizer:
- # Add More info about the randomizer?
- group_options.append("Randomizer")
- if group.static:
- group_options.append("Static")
- if group_options:
- options.append("" + ", ".join(group_options) + "")
- table.append(
- [
- template_category.value,
- template.template_type,
- template.name,
- "",
- "",
- ]
- )
-
- table_str = tabulate(
- table,
- headers=["Category", "Sub-Category", "Template", "Groups & Units", "Options"],
- tablefmt="github",
- )
-
- with open(table_file, "w", encoding="utf-8") as fdata:
- fdata.write(table_str)
-
-
-def replace(string: str, replacement) -> str:
- for old_name, new_name in replacement:
- string = string.replace(old_name, new_name)
- return string
-
-
def update_factions(generator_names) -> None:
folder: Path = Path("./resources/factions/")
factions = [f for f in folder.glob("*.json") if f.is_file()]
for f in factions:
with open(f, "r", encoding="utf-8") as fdata:
- data = json.load(fdata)
-
- updated_faction = {}
- for key, item in data.items():
- if isinstance(item, list):
- updated = []
- for string in item:
- updated.append(replace(string, generator_names))
- updated_faction[key] = updated
- elif isinstance(item, str):
- updated_faction[key] = replace(item, generator_names)
- else:
- updated_faction[key] = item
+ data = fdata.read()
with open(f, "w", encoding="utf-8") as fdata:
- json.dump(updated_faction, fdata, indent=2)
+ for old_name, new_name in generator_names:
+ new_name = new_name.replace('"', '\\"')
+ data = data.replace(f'"{old_name}"', f'"{new_name}"')
+ data = data.replace(f'"ewrs"', f'"air_defense_units"')
+ fdata.write(data)
print("\n \n Faction Updates:")
print(
@@ -463,267 +213,310 @@ def update_factions(generator_names) -> None:
)
)
- # def migrate_generators_to_templates(
- # input_miz: str,
- # templates_file: str,
- # miz_file: str,
- # template_map_file: str,
- # table_file: str,
- # ) -> None:
- #
- # templates = GroundObjectTemplates()
- #
- # theater = CaucasusTheater()
- #
- # initial_position = Point(0, 0)
- # control_point = OffMapSpawn(1, "Spawn", initial_position, True)
- # theater.add_controlpoint(control_point)
- #
- # game = Game(
- # FACTIONS["Bluefor Modern"],
- # FACTIONS["Russia 2010"],
- # theater,
- # CampaignAirWingConfig({control_point: []}),
- # datetime.today(),
- # Settings(),
- # 10000,
- # 10000,
- # )
- #
- # generators: dict[TemplateCategory, dict[str, Any]] = {
- # TemplateCategory.AirDefence: SAM_MAP,
- # TemplateCategory.Naval: SHIP_MAP,
- # TemplateCategory.Missile: MISSILES_MAP,
- # TemplateCategory.Coastal: COASTAL_MAP,
- # TemplateCategory.Armor: {},
- # }
- #
- # # Only use one EWR generator. The differnt units will be placed as randomizer
- # generators[TemplateCategory.AirDefence]["EWRGenerator"] = EwrGenerator
- #
- # generators[TemplateCategory.Naval]["CarrierGroupGenerator"] = CarrierGroupGenerator
- # generators[TemplateCategory.Naval][
- # "CarrierStrikeGroup8Generator"
- # ] = CarrierStrikeGroup8Generator
- # generators[TemplateCategory.Naval]["LHAGroupGenerator"] = LHAGroupGenerator
- # generators[TemplateCategory.Armor][
- # "RandomArmorGroup"
- # ] = FixedSizeArmorGroupGenerator
- # generators[TemplateCategory.Armor][
- # "RandomArmorGroupWithAA"
- # ] = FixedSizeArmorGroupGeneratorWithAA
- #
- # generator_names = []
- #
- # for category, template_generators in generators.items():
- # for generator_name, generator_class in template_generators.items():
- # # Just reuse SamGroundObject to make it easy
- # ground_object = SamGroundObject(
- # namegen.random_objective_name(),
- # initial_position,
- # Heading.from_degrees(0),
- # control_point,
- # )
- #
- # if category in (
- # TemplateCategory.Naval,
- # TemplateCategory.Missile,
- # TemplateCategory.Coastal,
- # ):
- # generator = generator_class(game, ground_object, game.blue.faction)
- # elif category == TemplateCategory.Armor:
- # unit_type = next(
- # GroundUnitType.for_dcs_type(dcs.vehicles.Armor.M_1_Abrams)
- # )
- # generator = generator_class(
- # game,
- # ground_object,
- # unit_type,
- # # Create a group of 8 Armored Vehicles
- # 8,
- # )
- # else:
- # generator = generator_class(game, ground_object)
- #
- # # Generate the DCS Groups
- # generator.generate()
- #
- # if isinstance(generator, EwrGenerator):
- # template = AirDefenceTemplate("Early-Warning Radar", "EWR")
- # elif isinstance(generator, AirDefenseGroupGenerator):
- # template = AirDefenceTemplate(generator.name, generator.range().name)
- # elif generator_name in MISSILES_MAP:
- # template = MissileTemplate(generator_name, category.name)
- # elif generator_name in COASTAL_MAP:
- # template = CoastalTemplate(generator_name, category.name)
- # elif category == TemplateCategory.Naval:
- # if generator_name == "CarrierGroupGenerator":
- # template = NavalTemplate("Carrier Group", "carrier")
- # elif generator_name == "CarrierStrikeGroup8Generator":
- # template = NavalTemplate("Carrier Strike Group 8", "carrier")
- # elif generator_name == "LHAGroupGenerator":
- # template = NavalTemplate("LHA Group", "lha")
- # else:
- # template = NavalTemplate(generator_name, "ship")
- # elif category == TemplateCategory.Armor:
- # if generator_name == "RandomArmorGroup":
- # template = ArmorTemplate("Armor Group", "armor")
- # elif generator_name == "RandomArmorGroupWithAA":
- # template = ArmorTemplate("Armor Group with Anti-Air", "armor_aa")
- # else:
- # raise RuntimeError("Generator handling missing")
- #
- # groups = list(generator.groups)
- #
- # # These have to be identical!
- # for i, group in enumerate(groups):
- # for j, unit in enumerate(group.units):
- # unit.name = f"{template.name} {i}-{j}"
- #
- # group_template = GroupTemplate(
- # f"{template.name} #{str(i)}",
- # [UnitTemplate.from_unit(unit) for unit in group.units],
- # )
- #
- # if generator_name in [
- # "CarrierGroupGenerator",
- # "CarrierStrikeGroup8Generator",
- # ]:
- # if i == 0:
- # group_template.randomizer = TemplateRandomizer(
- # [0], 1, ["aircraft_carrier"]
- # )
- # elif i == 1:
- # count = (
- # 5 if generator_name == "CarrierStrikeGroup8Generator" else 4
- # )
- # group_template.randomizer = TemplateRandomizer(
- # [], count, ["destroyers"]
- # )
- # elif generator_name == "LHAGroupGenerator":
- # if i == 0:
- # group_template.randomizer = TemplateRandomizer(
- # [0], 1, ["helicopter_carrier"]
- # )
- # elif i == 1:
- # group_template.randomizer = TemplateRandomizer(
- # [], 2, ["destroyers"]
- # )
- # elif generator_name == "RandomArmorGroup" and i == 0:
- # group_template.randomizer = TemplateRandomizer(
- # [],
- # [2, 6],
- # ["frontline_units"],
- # ["APC", "ATGM", "IFV", "Tank"],
- # )
- # elif generator_name == "RandomArmorGroupWithAA":
- # if i == 0:
- # group_template.randomizer = TemplateRandomizer(
- # [],
- # [2, 6],
- # ["frontline_units"],
- # ["APC", "ATGM", "IFV", "Tank"],
- # )
- # elif i == 1:
- # group_template.randomizer = TemplateRandomizer(
- # [],
- # [1, 2],
- # ["frontline_units", "infantry_units"],
- # ["SHORADS", "MANPADS"],
- # )
- # group_template.optional = True
- # elif generator_name == "EWRGenerator" and i == 0:
- # for ewr_generator_name, ewr_generator in EWR_MAP.items():
- # unit_type = next(
- # GroundUnitType.for_dcs_type(ewr_generator.unit_type)
- # )
- # # Update all factions from generator to unit_type
- # generator_names.append(
- # [ewr_generator.unit_type.name, str(unit_type)]
- # )
- # # Update old generator names
- # generator_names.append([ewr_generator_name, str(unit_type)])
- #
- # group_template.randomizer = TemplateRandomizer(
- # [],
- # 1,
- # ["ewrs"], # Randomization based on faction template
- # )
- #
- # template.groups.append(group_template)
- #
- # templates.add_template(category, template)
- # generator_names.append([generator_name, template.name])
- #
- # # Load the basic templates
- # temp_mis = dcs.Mission()
- # temp_mis.load_file(input_miz)
- #
- # position_for_template: dict[str, Point] = {}
- # group_for_template: dict[str, GroupTemplate] = {}
- # for static_group in (
- # temp_mis.country("USA").static_group
- # + temp_mis.country("USAF Aggressors").static_group
- # ):
- # # Naming is: fob1 #001 -> name: fob1, category fob, group_name: fob1 #001
- # template_name = str(static_group.name).split()[0]
- # category_name, idx = template_name[:-1], int(template_name[-1])
- #
- # template = templates.by_name(template_name)
- # if not template:
- # template = BuildingTemplate(template_name, category_name)
- #
- # # Store original position to make the template relative to TGO later
- # position_for_template[template_name] = static_group.position
- #
- # # Create Group Template for the satic group. Within Liberation we map
- # # static units in groups even if dcs can not handle this. The dcs specific
- # # handling will happpen later in miz generation again.
- # group_template = GroupTemplate(f"{template.name}", [], True)
- # group_for_template[template_name] = group_template
- # template.groups.append(group_template)
- #
- # templates.add_template(TemplateCategory.Building, template)
- #
- # for u_id, unit in enumerate(static_group.units):
- # unit_template = UnitTemplate.from_unit(unit)
- # unit_template.position = Point(
- # int(unit_template.position.x - position_for_template[template_name].x),
- # int(unit_template.position.y - position_for_template[template_name].y),
- # )
- # group_for_template[template_name].units.append(unit_template)
- #
- # # Dump the template_map as json
- # with open(templates_file, "w") as f:
- # json.dump(templates.to_json(), f, cls=TemplateEncoder, indent=4)
- #
- # # Update Faction files
- # update_factions(generator_names)
- #
- print(
- "Migrate successful. To finish the migration also run export followed by an import again."
+def migrate_generators_to_templates(
+ input_miz: str,
+ templates_miz: str,
+ mapping_folder: str,
+) -> None:
+
+ templates = GroundObjectTemplates()
+
+ theater = CaucasusTheater()
+
+ initial_position = Point(0, 0)
+ control_point = OffMapSpawn(1, "Spawn", initial_position, True)
+ theater.add_controlpoint(control_point)
+
+ game = Game(
+ FACTIONS["Bluefor Modern"],
+ FACTIONS["Russia 2010"],
+ theater,
+ CampaignAirWingConfig({control_point: []}),
+ datetime.today(),
+ Settings(),
+ 10000,
+ 10000,
)
+ generators: dict[GroupRole, dict[str, Any]] = {
+ GroupRole.AntiAir: SAM_MAP,
+ GroupRole.Naval: SHIP_MAP,
+ GroupRole.Defenses: MISSILES_MAP | COASTAL_MAP,
+ GroupRole.GroundForce: {},
+ }
+
+ aa_range_taskings = {
+ AirDefenseRange.AAA: GroupTask.AAA,
+ AirDefenseRange.Short: GroupTask.SHORAD,
+ AirDefenseRange.Medium: GroupTask.MERAD,
+ AirDefenseRange.Long: GroupTask.LORAD,
+ }
+
+ # Only use one EWR generator. The differnt units will be placed as randomizer
+ generators[GroupRole.AntiAir]["EWRGenerator"] = EwrGenerator
+
+ generators[GroupRole.Naval]["CarrierGroupGenerator"] = CarrierGroupGenerator
+ generators[GroupRole.Naval][
+ "CarrierStrikeGroup8Generator"
+ ] = CarrierStrikeGroup8Generator
+ generators[GroupRole.Naval]["LHAGroupGenerator"] = LHAGroupGenerator
+ generators[GroupRole.GroundForce]["RandomArmorGroup"] = FixedSizeArmorGroupGenerator
+ generators[GroupRole.GroundForce][
+ "RandomArmorGroupWithAA"
+ ] = FixedSizeArmorGroupGeneratorWithAA
+
+ generator_names = []
+
+ for category, template_generators in generators.items():
+ for generator_name, generator_class in template_generators.items():
+ # Just reuse SamGroundObject to make it easy
+ ground_object = SamGroundObject(
+ namegen.random_objective_name(),
+ initial_position,
+ Heading.from_degrees(0),
+ control_point,
+ )
+
+ if category in (GroupRole.Naval, GroupRole.Defenses):
+ generator = generator_class(game, ground_object, game.blue.faction)
+ elif category == GroupRole.GroundForce:
+ unit_type = next(
+ GroundUnitType.for_dcs_type(dcs.vehicles.Armor.M_1_Abrams)
+ )
+ generator = generator_class(
+ game,
+ ground_object,
+ unit_type,
+ # Create a group of 8 Armored Vehicles
+ 8,
+ )
+ else:
+ generator = generator_class(game, ground_object)
+
+ # Generate the DCS Groups
+ generator.generate()
+
+ if isinstance(generator, EwrGenerator):
+ template = AntiAirTemplate("Early-Warning Radar")
+ template.tasks = [GroupTask.EWR]
+ elif isinstance(generator, AirDefenseGroupGenerator):
+ template = AntiAirTemplate(generator.name)
+ template.tasks = [aa_range_taskings[generator.range()]]
+ elif generator_name in MISSILES_MAP:
+ template = DefensesTemplate(generator_name)
+ template.tasks = [GroupTask.Missile]
+ elif generator_name in COASTAL_MAP:
+ template = DefensesTemplate(generator_name)
+ template.tasks = [GroupTask.Coastal]
+ elif category == GroupRole.Naval:
+ if generator_name == "CarrierGroupGenerator":
+ template = NavalTemplate("Carrier Group")
+ template.tasks = [GroupTask.AircraftCarrier]
+ elif generator_name == "CarrierStrikeGroup8Generator":
+ template = NavalTemplate("Carrier Strike Group 8")
+ template.tasks = [GroupTask.AircraftCarrier]
+ elif generator_name == "LHAGroupGenerator":
+ template = NavalTemplate("LHA Group")
+ template.tasks = [GroupTask.HelicopterCarrier]
+ else:
+ template = NavalTemplate(generator_name)
+ template.tasks = [GroupTask.Navy]
+ elif category == GroupRole.GroundForce:
+ if generator_name == "RandomArmorGroup":
+ template = GroundForceTemplate("Armor Group")
+ template.tasks = ROLE_TASKINGS[GroupRole.GroundForce]
+ elif generator_name == "RandomArmorGroupWithAA":
+ template = GroundForceTemplate("Armor Group with Anti-Air")
+ template.tasks = ROLE_TASKINGS[GroupRole.GroundForce]
+ else:
+ raise RuntimeError("Generator handling missing")
+
+ # Split groups by the unit_type
+ units_of_type: dict[str, tuple[int, list[Unit]]] = {}
+ for g_id, group in enumerate(generator.groups):
+ for unit in group.units:
+ if unit.type in units_of_type:
+ units_of_type[unit.type][1].append(unit)
+ else:
+ units_of_type[unit.type] = (g_id + 1, [unit])
+
+ i = 0
+ for unit_type, data in units_of_type.items():
+ g_id, units = data
+ for j, unit in enumerate(units):
+ unit.name = f"{template.name} {i}-{j}"
+
+ group_template = GroupTemplate(
+ f"{template.name} #{str(i)}",
+ [UnitTemplate.from_unit(unit) for unit in units],
+ )
+
+ # Save the group_id
+ group_template.group = g_id
+
+ if generator_name in [
+ "CarrierGroupGenerator",
+ "CarrierStrikeGroup8Generator",
+ ]:
+ if i == 0:
+ group_template.unit_classes = [UnitClass.AircraftCarrier]
+ group_template.unit_count = [1]
+ elif i == 1:
+ group_template.unit_count = [
+ 5 if generator_name == "CarrierStrikeGroup8Generator" else 4
+ ]
+ group_template.unit_classes = [UnitClass.Destroyer]
+ elif i == 2:
+ group_template.unit_count = [2]
+ group_template.unit_classes = [UnitClass.Cruiser]
+ elif generator_name == "LHAGroupGenerator":
+ if i == 0:
+ group_template.unit_classes = [UnitClass.HelicopterCarrier]
+ group_template.unit_count = [1]
+ elif i == 1:
+ group_template.unit_count = [2]
+ group_template.unit_classes = [UnitClass.Destroyer]
+ elif generator_name == "RandomArmorGroup" and i == 0:
+ group_template.unit_count = [2, 6]
+ group_template.unit_classes = [
+ UnitClass.Apc,
+ UnitClass.Atgm,
+ UnitClass.Ifv,
+ UnitClass.Tank,
+ ]
+ elif generator_name == "RandomArmorGroupWithAA":
+ if i == 0:
+ group_template.unit_count = [2, 6]
+ group_template.unit_classes = [
+ UnitClass.Apc,
+ UnitClass.Atgm,
+ UnitClass.Ifv,
+ UnitClass.Tank,
+ ]
+ elif i == 1:
+ group_template.unit_count = [1, 2]
+ group_template.unit_classes = [
+ UnitClass.AAA,
+ UnitClass.SHORAD,
+ UnitClass.Manpad,
+ ]
+ group_template.optional = True
+ elif generator_name == "EWRGenerator" and i == 0:
+ for ewr_generator_name, ewr_generator in EWR_MAP.items():
+ unit_type = next(
+ GroundUnitType.for_dcs_type(ewr_generator.unit_type)
+ )
+ # Update all factions from generator to unit_type
+ generator_names.append(
+ [ewr_generator.unit_type.name, str(unit_type)]
+ )
+ # Update old generator names
+ generator_names.append([ewr_generator_name, str(unit_type)])
+
+ group_template.unit_classes = [UnitClass.EWR, UnitClass.SR]
+ group_template.unit_count = [1]
+ elif generator_name == "ChineseNavyGroupGenerator":
+ if i == 0:
+ group_template.unit_types = [unit_type]
+ group_template.unit_count = [0, 2]
+ if i == 1:
+ group_template.unit_count = [0, 2]
+ group_template.unit_types = ["Type_052C", "Type_052B"]
+ elif generator_name == "RussianNavyGroupGenerator":
+ if i == 0:
+ group_template.unit_count = [0, 2]
+ group_template.unit_types = ["ALBATROS", "MOLNIYA"]
+ if i == 1:
+ group_template.unit_count = [0, 2]
+ group_template.unit_types = ["NEUSTRASH", "REZKY"]
+ if i == 2:
+ group_template.unit_count = [1]
+ group_template.unit_types = ["MOSCOW"]
+ elif generator_name == "FlakGenerator" and i == 0:
+ group_template.unit_count = [4]
+ group_template.unit_types = [
+ "flak38",
+ "flak18",
+ "flak36",
+ "flak37",
+ "flak41",
+ "flak30",
+ ]
+ elif generator_name == "V1GroupGenerator" and i == 2:
+ group_template.unit_types = ["flak38", "flak30"]
+ elif generator_name == "SchnellbootGroupGenerator" and i == 0:
+ group_template.unit_types = [unit_type]
+ group_template.unit_count = [2, 4]
+ elif generator_name == "UBoatGroupGenerator" and i == 0:
+ group_template.unit_types = [unit_type]
+ group_template.unit_count = [1, 4]
+ else:
+ group_template.unit_types = [unit_type]
+ group_template.unit_count = [len(units)]
+
+ template.groups.append(group_template)
+ i += 1
+
+ templates.add_template(category, template)
+ generator_names.append([generator_name, template.name])
+
+ # Load the basic templates
+ temp_mis = dcs.Mission()
+ temp_mis.load_file(input_miz)
+
+ position_for_template: dict[str, Point] = {}
+ group_for_template_and_type: dict[str, dict[str, GroupTemplate]] = {}
+ for static_group in (
+ temp_mis.country("USA").static_group
+ + temp_mis.country("USAF Aggressors").static_group
+ ):
+ # Naming is: fob1 #001 -> name: fob1, category fob, group_name: fob1 #001
+ template_name = str(static_group.name).split()[0]
+ category_name, idx = template_name[:-1], int(template_name[-1])
+
+ template = templates.by_name(template_name)
+ if not template:
+ template = BuildingTemplate(template_name)
+ template.category = category_name
+ # Store original position to make the template relative to TGO later
+ position_for_template[template_name] = static_group.position
+ templates.add_template(GroupRole.Building, template)
+ group_for_template_and_type[template_name] = {}
+
+ for unit in static_group.units:
+ if unit.type not in group_for_template_and_type[template_name]:
+ # Create Group Template for the satic group. Within Liberation we map
+ # static units in groups even if dcs can not handle this. The dcs specific
+ # handling will happpen later in miz generation again.
+ is_static = False if unit.type in vehicle_map else True
+ group_template = GroupTemplate(f"{template.name}", [], is_static)
+ group_template.unit_types = [unit.type]
+ group_template.unit_count = [0]
+ group_for_template_and_type[template_name][unit.type] = group_template
+ template.groups.append(group_template)
+ else:
+ group_template = group_for_template_and_type[template_name][unit.type]
+
+ unit_template = UnitTemplate.from_unit(unit)
+ unit_template.position = Point(
+ int(unit_template.position.x - position_for_template[template_name].x),
+ int(unit_template.position.y - position_for_template[template_name].y),
+ )
+ group_template.units.append(unit_template)
+ group_template.unit_count = [group_template.unit_count[0] + 1]
+
+ # Update Faction files
+ update_factions(generator_names)
+
+ # Export
+ export_templates(templates_miz, mapping_folder, templates)
+
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
my_group = parser.add_mutually_exclusive_group(required=True)
- my_group.add_argument(
- "-i",
- "--import",
- dest="Import",
- help="Imports the templates from the miz into liberation",
- action="store_true",
- )
- my_group.add_argument(
- "-e",
- "--export",
- dest="Export",
- help="Exports the templates from liberation to the miz",
- action="store_true",
- )
my_group.add_argument(
"-m",
"--migrate",
@@ -738,23 +531,12 @@ def parse_args() -> argparse.Namespace:
help="Prints a table of all templates",
action="store_true",
)
-
- parser.add_argument(
- "--template_miz", default=TEMPLATES_MIZ, help="Set the template mission (.miz)"
- )
- parser.add_argument(
- "--target_file", default=TEMPLATES_BLOB, help="Set the target file"
- )
- parser.add_argument(
- "--template_map", default=TEMPLATES_MAP, help="Set the template map"
- )
- parser.add_argument(
- "--migrate_file", default=MIGRATE_MIZ, help="Set the migrate mission"
- )
- parser.add_argument(
- "--table_file",
- default=TABLE_FILE,
- help="Output file for template documentation",
+ my_group.add_argument(
+ "-f",
+ "--faction",
+ dest="Faction",
+ help="Updates all factions",
+ action="store_true",
)
return parser.parse_args()
@@ -764,23 +546,493 @@ def main():
args = parse_args()
liberation_install.init()
- miz_file = args.template_miz
- target_file = args.target_file
- migrate_file = args.migrate_file
- template_map = args.template_map
- table_file = args.table_file
-
- if args.Import:
- import_templates(miz_file, template_map, target_file, table_file)
- elif args.Export:
- export_templates(target_file, miz_file, template_map)
- elif args.Table:
- print_table(target_file, table_file)
+ if args.Table:
+ export_template_list()
+ elif args.Faction:
+ migrate_factions()
elif args.Migrate:
- migrate_generators_to_templates(
- migrate_file, target_file, miz_file, template_map, table_file
+ migrate_generators_to_templates(MIGRATE_MIZ, TEMPLATES_MIZ, TEMPLATES_FOLDER)
+
+
+def export_template_list() -> None:
+ # Extrac UnitMaps from all templates: Units with the GroundUnitType name!
+ templates = GroundObjectTemplates.from_folder(TEMPLATES_FOLDER)
+ template_maps: dict[str, list[Any]] = {}
+ missing_units = []
+ for role, template in templates.templates:
+ units = []
+ for group in template.groups:
+ group_units = []
+ for unit_type in group.unit_types:
+ try:
+ if unit_type in vehicle_map:
+ group_units.append(
+ next(
+ GroundUnitType.for_dcs_type(vehicle_map[unit_type])
+ ).name
+ )
+ elif unit_type in ship_map:
+ group_units.append(
+ next(ShipUnitType.for_dcs_type(ship_map[unit_type])).name
+ )
+ elif db.static_type_from_name(unit_type):
+ group_units.append(unit_type)
+ continue
+ except StopIteration:
+ pass
+ missing_units.append(unit_type)
+ if group.unit_classes:
+ group_units.append(
+ f"Classes = [ {', '.join(c.value for c in group.unit_classes)}]"
+ )
+ units.append(f"{', '.join(group_units)}")
+ tasks = ", ".join(t.value for t in template.tasks)
+ category = role.value + tasks
+
+ if category not in template_maps:
+ template_maps[category] = []
+
+ template_maps[category].append(
+ [
+ role.value,
+ tasks,
+ template.name,
+ "",
+ ]
)
+ templates = [
+ template for templates in template_maps.values() for template in templates
+ ]
+
+ templates.append(["Missing Units", ", ".join(set(missing_units))])
+
+ table_str = tabulate(
+ templates,
+ headers=[
+ "Role",
+ "Tasks",
+ "Template Name",
+ "Units",
+ ],
+ tablefmt="github",
+ )
+
+ with open(TABLE_FILE, "w", encoding="utf-8") as fdata:
+ fdata.write(table_str)
+
+
+@dataclass
+class MigratedTemplate:
+ original_key: str
+ new_key: str
+ original_value: str
+ new_value: str
+
+
+def migrate_factions() -> None:
+ # List of all currently migrated templates
+ migrated_templates: list[MigratedTemplate] = [
+ MigratedTemplate("air_defenses", "preset_groups", "Hawk Site", "Hawk"),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-5/S-200 Site", "SA-5/S-200"
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-5/S-200 Site wit FlatFace SR",
+ "SA-5/S-200",
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-2/S-75 Site", "SA-2/S-75"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-3/S-125 Site", "SA-3/S-125"
+ ),
+ MigratedTemplate("air_defenses", "preset_groups", "SA-6 Kub Site", "SA-6"),
+ MigratedTemplate("air_defenses", "preset_groups", "SA-11 Buk Battery", "SA-11"),
+ MigratedTemplate("air_defenses", "preset_groups", "Rapier AA Site", "Rapier"),
+ MigratedTemplate("air_defenses", "preset_groups", "Roland Site", "Roland"),
+ MigratedTemplate("air_defenses", "preset_groups", "Patriot Battery", "Patriot"),
+ MigratedTemplate("air_defenses", "preset_groups", "HQ-7 Site", "HQ-7"),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-10/S-300PS Battery - With ZSU-23",
+ "SA-10/S-300PS",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-10/S-300PS Battery - With SA-15 PD",
+ "SA-10/S-300PS",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-10/S-300PS Battery - With SA-15 PD & SA-19 SHORAD",
+ "SA-10/S-300PS",
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-10B/S-300PS Battery", "SA-10B/S-300PS"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-17 Grizzly Battery", "SA-17"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-12/S-300V Battery", "SA-12/S-300V"
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-20/S-300PMU-1 Battery",
+ "SA-20/S-300PMU-1",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "preset_groups",
+ "SA-20B/S-300PMU-2 Battery",
+ "SA-20B/S-300PMU-2",
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "SA-23/S-300VM Battery", "SA-23/S-300VM"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "NASAMS AIM-120B", "NASAMS AIM-120B"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "NASAMS AIM-120C", "NASAMS AIM-120C"
+ ),
+ MigratedTemplate("air_defenses", "preset_groups", "KS-19 AAA Site", "KS-19"),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "Cold War Flak Site", "Cold-War-Flak"
+ ),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "Early Cold War Flak Site", "Cold-War-Flak"
+ ),
+ MigratedTemplate("air_defenses", "preset_groups", "Flak Site", "Flak"),
+ MigratedTemplate(
+ "air_defenses", "preset_groups", "WW2 Ally Flak Site", "Ally Flak"
+ ),
+ MigratedTemplate("air_defenses", "preset_groups", "Freya EWR Site", "Freya"),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Vulcan Group",
+ "M163 Vulcan Air Defense System",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Avenger Group",
+ "M1097 Heavy HMMWV Avenger",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Chaparral Group",
+ "M48 Chaparral",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Gepard Group",
+ "Flakpanzer Gepard",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Linebacker Group",
+ "M6 Linebacker",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "SA-8 OSA Site",
+ 'SAM SA-8 Osa "Gecko" TEL',
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "SA-9 Group",
+ "SA-9 Strela",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "SA-13 Strela Group",
+ "SA-13 Gopher (9K35 Strela-10M3)",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "SA-15 Tor Group",
+ "SA-15 Tor",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "SA-19 Tunguska Group",
+ "SA-19 Grison (2K22 Tunguska)",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Bofors AAA",
+ "Bofors 40 mm Gun",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "ZU-23 Group",
+ "AAA ZU-23 Closed Emplacement",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "ZU-23 Ural Group",
+ "ZU-23 on Ural-375",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "ZU-23 Ural Insurgent Group",
+ "ZU-23 on Ural-375",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "Zu-23 Site",
+ "AAA ZU-23 Insurgent Closed Emplacement",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "ZSU-23 Group",
+ "ZSU-23-4 Shilka",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "WW2 Flak Site",
+ "8.8 cm Flak 18",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "ZSU-57-2 Group",
+ "ZSU-57-2 'Sparka'",
+ ),
+ MigratedTemplate(
+ "air_defenses",
+ "air_defense_units",
+ "WW2 Flak Site",
+ "8.8 cm Flak 18",
+ ),
+ MigratedTemplate(
+ "missiles",
+ "missiles",
+ "V1GroupGenerator",
+ "V-1 Launch Ramp",
+ ),
+ MigratedTemplate(
+ "missiles",
+ "missiles",
+ "ScudGenerator",
+ "SSM SS-1C Scud-B",
+ ),
+ MigratedTemplate(
+ "coastal_defenses",
+ "preset_groups",
+ "SilkwormGenerator",
+ "Silkworm",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "destroyers",
+ "Type54GroupGenerator",
+ "Type 054A Frigate",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "Type54GroupGenerator",
+ "Type 054A Frigate",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "SchnellbootGroupGenerator",
+ "Boat Schnellboot type S130",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "preset_groups",
+ "WW2LSTGroupGenerator",
+ "WW2LST",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "preset_groups",
+ "ChineseNavyGroupGenerator",
+ "Chinese Navy",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "UBoatGroupGenerator",
+ "U-boat VIIC U-flak",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "OliverHazardPerryGroupGenerator",
+ "FFG Oliver Hazard Perry",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "ArleighBurkeGroupGenerator",
+ "DDG Arleigh Burke IIa",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "GrishaGroupGenerator",
+ "Corvette 1124.4 Grish",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "MolniyaGroupGenerator",
+ "Corvette 1241.1 Molniya",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "KiloSubGroupGenerator",
+ "SSK 877V Kilo",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "naval_units",
+ "LaCombattanteIIGroupGenerator",
+ "FAC La Combattante IIa",
+ ),
+ MigratedTemplate(
+ "navy_generators",
+ "preset_groups",
+ "RussianNavyGroupGenerator",
+ "Russian Navy",
+ ),
+ MigratedTemplate(
+ "aircraft_carrier",
+ "naval_units",
+ "Forrestal",
+ "CV-59 Forrestal",
+ ),
+ MigratedTemplate(
+ "aircraft_carrier",
+ "naval_units",
+ "KUZNECOW",
+ "CV 1143.5 Admiral Kuznetsov",
+ ),
+ MigratedTemplate(
+ "helicopter_carrier",
+ "naval_units",
+ "LHA_Tarawa",
+ "LHA-1 Tarawa",
+ ),
+ MigratedTemplate(
+ "aircraft_carrier",
+ "naval_units",
+ "Stennis",
+ "CVN-74 John C. Stennis",
+ ),
+ MigratedTemplate(
+ "helicopter_carrier",
+ "naval_units",
+ "Type_071",
+ "Type 071 Amphibious Transport Dock",
+ ),
+ ]
+ # Find the "air_defenses" key remove the template name there
+ folder: Path = Path("./resources/factions/")
+ factions = [f for f in folder.glob("*.json") if f.is_file()]
+ for f in factions:
+ with open(f, "r", encoding="utf-8") as fdata:
+ data = json.load(fdata)
+
+ with open(f, "w", encoding="utf-8") as fdata:
+ for migrated_template in migrated_templates:
+ if migrated_template.new_key not in data:
+ new_faction = {}
+ for key, value in data.items():
+ new_faction[key] = value
+ if key == "preset_groups":
+ # Add New Key after air_defenses
+ new_faction[migrated_template.new_key] = []
+ data = new_faction
+ if (
+ migrated_template.original_key in data
+ and migrated_template.original_value
+ in data[migrated_template.original_key]
+ ):
+ data[migrated_template.original_key].remove(
+ migrated_template.original_value
+ )
+ if (
+ migrated_template.new_value
+ not in data[migrated_template.new_key]
+ ):
+ data[migrated_template.new_key].append(
+ migrated_template.new_value
+ )
+ # Remove air_defenses and coastal if empty
+ if "coastal_defenses" in data and len(data["coastal_defenses"]) == 0:
+ data.pop("coastal_defenses")
+ if "navy_generators" in data and len(data["navy_generators"]) == 0:
+ data.pop("navy_generators")
+ if "destroyers" in data:
+ for unit in data["destroyers"]:
+ data["naval_units"].append(unit)
+ data.pop("destroyers")
+ if "cruisers" in data:
+ for unit in data["cruisers"]:
+ data["naval_units"].append(unit)
+ data.pop("cruisers")
+ if "air_defenses" in data and len(data["air_defenses"]) == 0:
+ data.pop("air_defenses")
+ if "helicopter_carrier" in data and len(data["helicopter_carrier"]) == 0:
+ data.pop("helicopter_carrier")
+ if "aircraft_carrier" in data and len(data["aircraft_carrier"]) == 0:
+ data.pop("aircraft_carrier")
+ if "navy_group_count" in data:
+ data.pop("navy_group_count")
+ if "missiles_group_count" in data:
+ data.pop("missiles_group_count")
+ if "coastal_group_count" in data:
+ data.pop("coastal_group_count")
+
+ for key, value in data.items():
+ # Remove duplicates
+ if isinstance(value, list):
+ data[key] = []
+ [data[key].append(item) for item in value if item not in data[key]]
+
+ json.dump(data, fdata, indent=2)
+
+
+def list_units_without_class() -> None:
+ folder: Path = Path("./resources/units/ground_units/")
+ unit_files = [f for f in folder.glob("*.yaml") if f.is_file()]
+ for f in unit_files:
+ with f.open(encoding="utf-8") as data_file:
+ data = yaml.safe_load(data_file)
+
+ if data.get("class") is None:
+ print(f)
+
if __name__ == "__main__":
main()