From 344d4e31b7dbef3f88c9a62931aa269cd5964d52 Mon Sep 17 00:00:00 2001 From: RndName Date: Sat, 29 Jan 2022 00:43:28 +0100 Subject: [PATCH] Migrate generators to templats - added all new templates - deleted the generators - added documentation --- doc/templates/ground_object_buy_menu.png | Bin 0 -> 22743 bytes doc/templates/template_list.md | 56 + doc/templates/template_miz_example.png | Bin 0 -> 58033 bytes doc/templates/template_overview.png | Bin 0 -> 90882 bytes doc/templates/templates.md | 202 +++ gen/group_generator.py | 223 --- gen/to_remove/aaa_bofors.py | 35 - gen/to_remove/aaa_flak.py | 99 -- gen/to_remove/aaa_flak18.py | 45 - gen/to_remove/aaa_ks19.py | 41 - gen/to_remove/aaa_ww2_ally_flak.py | 81 - gen/to_remove/aaa_zsu57.py | 32 - gen/to_remove/aaa_zu23_insurgent.py | 34 - gen/to_remove/airdefensegroupgenerator.py | 66 - gen/to_remove/armor_group_generator.py | 63 - gen/to_remove/armored_group_generator.py | 84 - gen/to_remove/carrier_group.py | 124 -- gen/to_remove/cn_dd_group.py | 59 - gen/to_remove/coastal_group_generator.py | 13 - gen/to_remove/cold_war_flak.py | 153 -- gen/to_remove/dd_group.py | 56 - gen/to_remove/ewr_group_generator.py | 27 - gen/to_remove/ewrs.py | 114 -- gen/to_remove/freya_ewr.py | 110 -- gen/to_remove/lacombattanteII.py | 13 - gen/to_remove/lha_group.py | 39 - gen/to_remove/missiles_group_generator.py | 12 - gen/to_remove/ru_dd_group.py | 92 -- gen/to_remove/sam_avenger.py | 40 - gen/to_remove/sam_chaparral.py | 40 - gen/to_remove/sam_gepard.py | 40 - gen/to_remove/sam_group_generator.py | 172 -- gen/to_remove/sam_hawk.py | 66 - gen/to_remove/sam_hq7.py | 59 - gen/to_remove/sam_linebacker.py | 40 - gen/to_remove/sam_nasams.py | 67 - gen/to_remove/sam_patriot.py | 88 - gen/to_remove/sam_rapier.py | 52 - gen/to_remove/sam_roland.py | 51 - gen/to_remove/sam_sa10.py | 222 --- gen/to_remove/sam_sa11.py | 48 - gen/to_remove/sam_sa13.py | 47 - gen/to_remove/sam_sa15.py | 46 - gen/to_remove/sam_sa17.py | 46 - gen/to_remove/sam_sa19.py | 42 - gen/to_remove/sam_sa2.py | 48 - gen/to_remove/sam_sa3.py | 48 - gen/to_remove/sam_sa5.py | 77 - gen/to_remove/sam_sa6.py | 41 - gen/to_remove/sam_sa8.py | 40 - gen/to_remove/sam_sa9.py | 47 - gen/to_remove/sam_vulcan.py | 40 - gen/to_remove/sam_zsu23.py | 40 - gen/to_remove/sam_zu23.py | 41 - gen/to_remove/sam_zu23_ural.py | 33 - gen/to_remove/sam_zu23_ural_insurgent.py | 33 - gen/to_remove/schnellboot.py | 20 - gen/to_remove/scud_site.py | 68 - gen/to_remove/ship_group_generator.py | 52 - gen/to_remove/silkworm.py | 64 - gen/to_remove/uboat.py | 20 - gen/to_remove/v1_group.py | 70 - gen/to_remove/ww2lst.py | 29 - resources/templates/anti_air/AAA.miz | Bin 0 -> 8617 bytes resources/templates/anti_air/AAA_Mobile.yaml | 23 + resources/templates/anti_air/AAA_Radar.yaml | 29 + resources/templates/anti_air/AAA_Site.yaml | 23 + .../anti_air/Cold_War_Flak_Site.yaml | 36 + .../anti_air/Early-Warning_Radar.yaml | 15 + resources/templates/anti_air/Flak_Site.yaml | 51 + .../templates/anti_air/Freya_EWR_Site.yaml | 51 + resources/templates/anti_air/HQ-7_Site.yaml | 24 + resources/templates/anti_air/Hawk_Site.yaml | 36 + .../templates/anti_air/NASAMS_AIM-120B.yaml | 21 + .../templates/anti_air/NASAMS_AIM-120C.yaml | 21 + .../templates/anti_air/Patriot_Battery.yaml | 56 + .../templates/anti_air/Rapier_AA_Site.yaml | 21 + resources/templates/anti_air/Roland_Site.yaml | 21 + resources/templates/anti_air/SA-10.miz | Bin 0 -> 8780 bytes .../anti_air/SA-10_S-300PS_Battery.yaml | 62 + .../templates/anti_air/SA-11_Buk_Battery.yaml | 21 + .../anti_air/SA-12_S-300V_Battery.yaml | 54 + .../anti_air/SA-17_Grizzly_Battery.yaml | 21 + .../anti_air/SA-20B_S-300PMU-2_Battery.yaml | 48 + .../anti_air/SA-20_S-300PMU-1_Battery.yaml | 54 + .../anti_air/SA-23_S-300VM_Battery.yaml | 54 + .../templates/anti_air/SA-2_S-75_Site.yaml | 21 + .../templates/anti_air/SA-3_S-125_Site.yaml | 21 + .../templates/anti_air/SA-5_S-200_Site.yaml | 26 + .../templates/anti_air/SA-6_Kub_Site.yaml | 16 + .../anti_air/Short_Range_Anti_Air.yaml | 19 + .../anti_air/WW2_Ally_Flak_Site.yaml | 41 + .../templates/anti_air/WW2_Flak_Site.yaml | 16 + resources/templates/anti_air/flak.miz | Bin 0 -> 7806 bytes .../anti_air/legacy_ground_templates.miz | Bin 0 -> 21470 bytes resources/templates/anti_air/shorad.miz | Bin 0 -> 7205 bytes resources/templates/buildings/allycamp1.yaml | 83 + resources/templates/buildings/ammo1.yaml | 21 + resources/templates/buildings/buildings.miz | Bin 0 -> 14905 bytes resources/templates/buildings/comms.yaml | 15 + resources/templates/buildings/derrick1.yaml | 30 + resources/templates/buildings/factory1.yaml | 22 + resources/templates/buildings/farp1.yaml | 40 + resources/templates/buildings/fob1.yaml | 30 + resources/templates/buildings/fuel1.yaml | 27 + resources/templates/buildings/oil1.yaml | 17 + resources/templates/buildings/power1.yaml | 36 + resources/templates/buildings/village1.yaml | 38 + resources/templates/buildings/ware1.yaml | 23 + resources/templates/buildings/ww2bunker1.yaml | 33 + resources/templates/buildings/ww2bunker2.yaml | 56 + resources/templates/defenses/Silkworm.yaml | 34 + resources/templates/defenses/defenses.miz | Bin 0 -> 7993 bytes resources/templates/defenses/missile.yaml | 29 + .../templates/ground_forces/Armor_Group.yaml | 17 + .../Armor_Group_with_Anti-Air.yaml | 26 + .../templates/ground_forces/ground_forces.miz | Bin 0 -> 7813 bytes resources/templates/naval/Carrier_Group.yaml | 19 + .../naval/Carrier_Strike_Group_8.yaml | 25 + resources/templates/naval/Chinese-Navy.yaml | 19 + resources/templates/naval/LHA_Group.yaml | 19 + resources/templates/naval/Naval-Two-Ship.yaml | 16 + resources/templates/naval/Russian-Navy.yaml | 27 + resources/templates/naval/WW2-LST.yaml | 16 + .../naval/legacy_naval_templates.miz | Bin 0 -> 8837 bytes resources/templates/naval/naval.miz | Bin 0 -> 6923 bytes .../templates/original_generator_layouts.miz | Bin 0 -> 32251 bytes resources/tools/template_helper.py | 1464 ++++++++++------- 128 files changed, 2736 insertions(+), 4198 deletions(-) create mode 100644 doc/templates/ground_object_buy_menu.png create mode 100644 doc/templates/template_list.md create mode 100644 doc/templates/template_miz_example.png create mode 100644 doc/templates/template_overview.png create mode 100644 doc/templates/templates.md delete mode 100644 gen/group_generator.py delete mode 100644 gen/to_remove/aaa_bofors.py delete mode 100644 gen/to_remove/aaa_flak.py delete mode 100644 gen/to_remove/aaa_flak18.py delete mode 100644 gen/to_remove/aaa_ks19.py delete mode 100644 gen/to_remove/aaa_ww2_ally_flak.py delete mode 100644 gen/to_remove/aaa_zsu57.py delete mode 100644 gen/to_remove/aaa_zu23_insurgent.py delete mode 100644 gen/to_remove/airdefensegroupgenerator.py delete mode 100644 gen/to_remove/armor_group_generator.py delete mode 100644 gen/to_remove/armored_group_generator.py delete mode 100644 gen/to_remove/carrier_group.py delete mode 100644 gen/to_remove/cn_dd_group.py delete mode 100644 gen/to_remove/coastal_group_generator.py delete mode 100644 gen/to_remove/cold_war_flak.py delete mode 100644 gen/to_remove/dd_group.py delete mode 100644 gen/to_remove/ewr_group_generator.py delete mode 100644 gen/to_remove/ewrs.py delete mode 100644 gen/to_remove/freya_ewr.py delete mode 100644 gen/to_remove/lacombattanteII.py delete mode 100644 gen/to_remove/lha_group.py delete mode 100644 gen/to_remove/missiles_group_generator.py delete mode 100644 gen/to_remove/ru_dd_group.py delete mode 100644 gen/to_remove/sam_avenger.py delete mode 100644 gen/to_remove/sam_chaparral.py delete mode 100644 gen/to_remove/sam_gepard.py delete mode 100644 gen/to_remove/sam_group_generator.py delete mode 100644 gen/to_remove/sam_hawk.py delete mode 100644 gen/to_remove/sam_hq7.py delete mode 100644 gen/to_remove/sam_linebacker.py delete mode 100644 gen/to_remove/sam_nasams.py delete mode 100644 gen/to_remove/sam_patriot.py delete mode 100644 gen/to_remove/sam_rapier.py delete mode 100644 gen/to_remove/sam_roland.py delete mode 100644 gen/to_remove/sam_sa10.py delete mode 100644 gen/to_remove/sam_sa11.py delete mode 100644 gen/to_remove/sam_sa13.py delete mode 100644 gen/to_remove/sam_sa15.py delete mode 100644 gen/to_remove/sam_sa17.py delete mode 100644 gen/to_remove/sam_sa19.py delete mode 100644 gen/to_remove/sam_sa2.py delete mode 100644 gen/to_remove/sam_sa3.py delete mode 100644 gen/to_remove/sam_sa5.py delete mode 100644 gen/to_remove/sam_sa6.py delete mode 100644 gen/to_remove/sam_sa8.py delete mode 100644 gen/to_remove/sam_sa9.py delete mode 100644 gen/to_remove/sam_vulcan.py delete mode 100644 gen/to_remove/sam_zsu23.py delete mode 100644 gen/to_remove/sam_zu23.py delete mode 100644 gen/to_remove/sam_zu23_ural.py delete mode 100644 gen/to_remove/sam_zu23_ural_insurgent.py delete mode 100644 gen/to_remove/schnellboot.py delete mode 100644 gen/to_remove/scud_site.py delete mode 100644 gen/to_remove/ship_group_generator.py delete mode 100644 gen/to_remove/silkworm.py delete mode 100644 gen/to_remove/uboat.py delete mode 100644 gen/to_remove/v1_group.py delete mode 100644 gen/to_remove/ww2lst.py create mode 100644 resources/templates/anti_air/AAA.miz create mode 100644 resources/templates/anti_air/AAA_Mobile.yaml create mode 100644 resources/templates/anti_air/AAA_Radar.yaml create mode 100644 resources/templates/anti_air/AAA_Site.yaml create mode 100644 resources/templates/anti_air/Cold_War_Flak_Site.yaml create mode 100644 resources/templates/anti_air/Early-Warning_Radar.yaml create mode 100644 resources/templates/anti_air/Flak_Site.yaml create mode 100644 resources/templates/anti_air/Freya_EWR_Site.yaml create mode 100644 resources/templates/anti_air/HQ-7_Site.yaml create mode 100644 resources/templates/anti_air/Hawk_Site.yaml create mode 100644 resources/templates/anti_air/NASAMS_AIM-120B.yaml create mode 100644 resources/templates/anti_air/NASAMS_AIM-120C.yaml create mode 100644 resources/templates/anti_air/Patriot_Battery.yaml create mode 100644 resources/templates/anti_air/Rapier_AA_Site.yaml create mode 100644 resources/templates/anti_air/Roland_Site.yaml create mode 100644 resources/templates/anti_air/SA-10.miz create mode 100644 resources/templates/anti_air/SA-10_S-300PS_Battery.yaml create mode 100644 resources/templates/anti_air/SA-11_Buk_Battery.yaml create mode 100644 resources/templates/anti_air/SA-12_S-300V_Battery.yaml create mode 100644 resources/templates/anti_air/SA-17_Grizzly_Battery.yaml create mode 100644 resources/templates/anti_air/SA-20B_S-300PMU-2_Battery.yaml create mode 100644 resources/templates/anti_air/SA-20_S-300PMU-1_Battery.yaml create mode 100644 resources/templates/anti_air/SA-23_S-300VM_Battery.yaml create mode 100644 resources/templates/anti_air/SA-2_S-75_Site.yaml create mode 100644 resources/templates/anti_air/SA-3_S-125_Site.yaml create mode 100644 resources/templates/anti_air/SA-5_S-200_Site.yaml create mode 100644 resources/templates/anti_air/SA-6_Kub_Site.yaml create mode 100644 resources/templates/anti_air/Short_Range_Anti_Air.yaml create mode 100644 resources/templates/anti_air/WW2_Ally_Flak_Site.yaml create mode 100644 resources/templates/anti_air/WW2_Flak_Site.yaml create mode 100644 resources/templates/anti_air/flak.miz create mode 100644 resources/templates/anti_air/legacy_ground_templates.miz create mode 100644 resources/templates/anti_air/shorad.miz create mode 100644 resources/templates/buildings/allycamp1.yaml create mode 100644 resources/templates/buildings/ammo1.yaml create mode 100644 resources/templates/buildings/buildings.miz create mode 100644 resources/templates/buildings/comms.yaml create mode 100644 resources/templates/buildings/derrick1.yaml create mode 100644 resources/templates/buildings/factory1.yaml create mode 100644 resources/templates/buildings/farp1.yaml create mode 100644 resources/templates/buildings/fob1.yaml create mode 100644 resources/templates/buildings/fuel1.yaml create mode 100644 resources/templates/buildings/oil1.yaml create mode 100644 resources/templates/buildings/power1.yaml create mode 100644 resources/templates/buildings/village1.yaml create mode 100644 resources/templates/buildings/ware1.yaml create mode 100644 resources/templates/buildings/ww2bunker1.yaml create mode 100644 resources/templates/buildings/ww2bunker2.yaml create mode 100644 resources/templates/defenses/Silkworm.yaml create mode 100644 resources/templates/defenses/defenses.miz create mode 100644 resources/templates/defenses/missile.yaml create mode 100644 resources/templates/ground_forces/Armor_Group.yaml create mode 100644 resources/templates/ground_forces/Armor_Group_with_Anti-Air.yaml create mode 100644 resources/templates/ground_forces/ground_forces.miz create mode 100644 resources/templates/naval/Carrier_Group.yaml create mode 100644 resources/templates/naval/Carrier_Strike_Group_8.yaml create mode 100644 resources/templates/naval/Chinese-Navy.yaml create mode 100644 resources/templates/naval/LHA_Group.yaml create mode 100644 resources/templates/naval/Naval-Two-Ship.yaml create mode 100644 resources/templates/naval/Russian-Navy.yaml create mode 100644 resources/templates/naval/WW2-LST.yaml create mode 100644 resources/templates/naval/legacy_naval_templates.miz create mode 100644 resources/templates/naval/naval.miz create mode 100644 resources/templates/original_generator_layouts.miz diff --git a/doc/templates/ground_object_buy_menu.png b/doc/templates/ground_object_buy_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..57f6d519b044075586448b9855a6285d3df003a2 GIT binary patch literal 22743 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 JSD0Q%_z$XOeN+Gd literal 0 HcmV?d00001 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 |
  • Tank
  • Tank 3
| +| Building | StrikeTarget | ware1 |
  • Warehouse
  • Hangar A
| +| 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 |
  • TV tower, Comms tower M
| +| Building | Oil | oil1 |
  • Oil platform
| +| 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 |
  • LS Samuel Chase
  • LST Mk.II
| +| 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 0000000000000000000000000000000000000000..e227e72675a94d33ab4cec54290e8e783cb739ca GIT binary patch literal 58033 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 F{{YgfSn>b> literal 0 HcmV?d00001 diff --git a/doc/templates/template_overview.png b/doc/templates/template_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..21ece57d89224076cbe9625a8fee31de647c3dc4 GIT binary patch literal 90882 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 literal 0 HcmV?d00001 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 + + +![Overview](template_overview.png) + +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: +![ground_object_buy_menu.png](ground_object_buy_menu.png) + +### 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. + +![template_miz_example.png](template_miz_example.png) + +### 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 0000000000000000000000000000000000000000..8207e4a401504491367549dfe813df192788d062 GIT binary patch literal 8617 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..669c54ece5470856bdd6d10711645451b90109c1 GIT binary patch literal 8780 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 UMaTFZz_`Dy?oS1S_V?_608~dff&c&j literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4d1a592079d15c7909418bc5dc8be59c939e153e GIT binary patch literal 21470 zcmZU51z40_^EV*fNGXjVAgy$FNOwwicXvxGAPq|>-Q7q_cP!oA-F!Fd^L+37{;$1u z?=!zSG3VZM?wK<)yK<5*ps^sJ;Nc-4AV?t8xF7~H1R)?+zaT=u0f?2EgM*ok^+B_y z1HM>8j>nOX-*I)&(AkPUy&+h8VUDggKCk9Vst5W-j&ArIRzBp%s~FV*pCuChK63ah z>Q*Tzk?qkSu4M88>aQ1@D{e~zo<5%5-k#2!x5U{Dk9Xmt_e-rUO^Jk0w;N9_x4n~3 zI**PwDZQgz_cp^%_Ztg**R48{={)$-vP)4z-t`aDwIz%XUheLrS5Ry|o_l9v30t@( zM;_jfo6$C2j|u(b+36td$DM=WbSdwHJ8&0h(fhD+yte19&f)>uJk3*Em!Y%WP3E@6 z^?A}ao9ulJ7v7VuWInYP?rEDb%Ud7%Xp`|;hT%o+bgAL#RwcfN^V-(P^x;L2){toI zjnSf1^kNzjG2PSc%96L!-b){z$BPBFo>n3q0&X9-hx$goTl0nNMURHPTyL)W#1fwg z8wz6F){$D9N50%x@M^B;4p*zIo3s0g^+`(Evr>*|CQ6zmrG8D>a4bJOWwEI)?TW(Cb+S&U0M?d4c9m8F-JBRwfzhm zQ?<;vFLcJ5RaOsf;}1p4r=cF5oSofnFS|aSRaVAcaPso{ICC`}v59Ixj$K-n$`2 zMkN*ohmR}MY)%a)rP?~v2QPf8PO%>i9>VLJCYD&meahb6&I!?Voa!&p>FiRfDPN^~ zO7EmEF>f;v9a_U`{&YfX&53{`&JjBc@zk){I0(^J%<0NlL%`m;bz{3ADn!{1UapbqAA#@Ajp&WQoH%K`o}oU4~Kwv3(5xW&Kg?$wF>-viBP<) zO|EPgt|!K) zi}T~vwU8Yz^9ll;*80>3Pqz;|JQ`=XwHuZ?!OKA)U+WG605CD!q5ddg#4 zb-VU(ckw)*yI-`(U7to7J?R~+j`TU!{4~EamG(5e6C>MWyXB`sf4%I`%){H7IM0lv zn&n>iXsvVV{5CaJtK}e(mhZT^_|80{;R=pVb|_)k9%Qs=t=&V_t9?8=#xR){jEu^J&Z7K zQR~X+`MEyl9jO0^o(6kz#+5jr)+Hi>Z>WTh&B~u>xRApFndsoG~U~;vma5w`uXuME16ZZ#GVZv1SYSN^j zMeQsnt4rIl7Uxa@MSGb*oV+KAw`aZ>tm3k{1%S*K0&j0>INfvqcU~UK0d|aHXqWYmj z_d^}16F){T@mfXF4EG0e;g70th2TkrS&?@g&9J8OePtRFjZ{WzbU(D>J{0|~c$jbS zAFyWJhm!a)x{W#wiCQY7Cdy`!cWdVF7P8{(s^hG|-xn>sJM5_{ZrA=3mhS^f_waOzr&wAvO07Jr)tB66t0PM+r(Dv_y|(hF zSz9QItURSPmaYpfB9A(X6c?{I z)x<<y0k5Cm8`@v=3q5SS z*j(NF;Ba!$psAC?zDMAXuJ<9Me@?7;&%v%Zh>+RkjH_t-8yLR*@SUTmynZ`MOQ^vMs@e-X!;I+U9(Bm+QLXoO7wgjo!oeCiZDZ&-3QuZ2F0+<%+?i z@~WTcG)xjSAL!dk+cLru9O>d`+B&R#rA5D$8pd~Tf<|_;iY7Z0f zMbmj)OVAN59j34e4?oU-OMCk%N%+t)PxWwX*d)AdO4Yy6GjV|8Xt*Dwb~(}IrP4Tu zh*#pw)?%glap{1CVSl4b{bMxv$m`aO_2yXb_VPvnrCODz+4Je_B2jc&yKqy>N;Ucl zFMJpHE`}HI?k^{obcmIvKHb?gTbY&i%*CdtYc;1&4N#SIG&T$dsZv%=dfw{Y|BvB0Aegj(j6IkWbslT3k0o@&KEgknS*{P{Lo$hV*!A~0wf)Au6-(5++2v2jy+z$UoSgSvS*f_O<2J@Ut+=gRU6JE`;m*a|3>wq&b_?8c zl+CFdXN5fes0`LPI_C{@cfC6s>+7YpyJbDK+UHhR{Az|Mtb8!)FDhWA-OVasU-aU+ zzP(|5rU!3}YT^Qm+UVa=s=uJ3jEhZ#j5|BaPKE75*sv7j;3M$*qAyb^GN8`sq7glD zuFGih1Z#dAS7|fJE%#O^CzTN43(-3?pdlvE;NFvJ>)Q@?Myj05UnJ08kRvlyZpgmR z?D;|wcP5y+QKdO#A8h{1%s2Ib)MTl^Ekhz0nS%>QqKE?;@)yE7v^^9DhR7d6@1TJ7``}9-^(%e{qp_rXm*WIf0JTT%fvu;s1;+S;4FfAT( zeeo|2cCrE6mx_+s6r40zX;UTIjtzp2z4dW|;?(ZdG@}>uW5v36tio5{g>j*?kT~Gz zu+xfh)AGyCK2?djG2!}%H&&dvA9hZ5mNp{ptxE7Qp`DXOT_n@|K^Zbq_f{vr>>k&y$(e`>`S!X;VxabSsVf08IoD5iL zW+a>pIBCS1AV;~6VBLWdVceP+oV|{Qu-DTsls~LjsrA%l^|<<1&1~k9(1~gkeWaAu zD6-NRu>YmoI!i{Uav5Evre6Osd{QgCO05-dJ+R=G2KP{d;?*F=Ys^XH5ah!$gsm?E z$;Xu7K#ycw)Ysnuvh9Fnr3jqYOl!f)ZdkS~uU0v#i`AJNNpY}2B!=SM#LbcXITls} zVQsCE%W$Opy>unDxnp+*zWqc7ne-%?h{%NQnIbw1iTTL)SPJuz59Z4j&P$i6@5LuF z-WQXY^G`th{;Fa=K-hazd{GnwmOy2^{g4<%&p3F6VJo%+BpW5W^k~nWLNr8SLwQPA z|2Dh`aZ73SX5yfJVozjLY#79#o>I^bqBb&+jt~Iz1cO=}RjqYA&zH@Mk&}F#X|3*5 z1APVgNi)#p;J1r;+sbDUp%5X1{(-2Vv7o5mWFP>Tl{o+Krq?|171%y1IbaN;mTJE^ zNnbE8d^HjJB7^3qbb!E|ft+e8q*n1aQiG8hKLN~FSjdR5Fad|euykO)Yi-an*}|zJ2j|{ybgMEy zA*8P>heoF49~{AknaBYap?QCiHZ95-N`FN1~Wec;LAq>j?4Q37= zo{$`qtgoqXe|Gj_BN7%udsEmz0w_aqL#9K>`cnR7 z#lMgpdiBD!1}c5HmE+5*OsQerxTMP*N)D0B)c$+DZu-2UG`mG}p&`7D0|_^c9PZda z(EtRxxLlfe_8Ii1mND(AcLz2#4JK!5^R&Eb?}S+Ks&?)1m}Oqb1b8}zjgOQxcALGD ztC~eGrq9`CM|plgeSevo*>e{-E;pmL%)FmfH~qpo6*e{aARZ-GV3ip<71q^+?#Pov zf-_V;7i^z1%lu0T|HI@Ub$*>aQBj;gw#-5hCrTdX1i~(~(;@!udEZpV5Ij)!=M+fG zkddSO%R-bhdB!Z{w+ef^_OJK#9lc2xh1)d|j%ibbLn-BIDP`G=9^CEi-lusL&5E~2 zf9u;d2dP;^M0z0e+$k&B!B`a~3IxcG!|>8AV;&=1Lwg<)Un{XRex&+I`4@oVg#`J^ z0;D1YFD8J25j}Z*Ziw}dcMO*mKi0;|MgGi%^<*u~TSc5zdmjJ`szLJP{I_)s(Brr|)ZuZpI}J0>Xj`QQZja9IpY+g+vu@sn+nk8@`N@d=8$t?KekJLs&g z4`*#9@mtbZQ||>1jCzT=RraiUi9O?Q0;C>&?*$6)+iDrsQ+Dr)H_>M4nm(+fB`Yh9 z2dQ=}+VweYpmE>4IE6bMin$kP^iH{N^F4)&x)%U*i9co-fhKWMzwphxy(ag80OWhg z0|B@|mMfQd8G(tK5Ffjp3k>jd#MkFqbn?*6pV`&r7Otl|kIav|*bPHm1$wmetfcQ( z4F@aQ%GOcNV;&;>#cYSo5A#>jZHJBhhE+>Dmzk`cavz-WWjKDCREC*1ti<6nUn6TR zGyT1#TaSLj1k^uGCVt=EKezuc%Y@^a`B@g4V>f&1&Ge7mJPzpg!!bAG6iu5nb-Azi zQmdVN#Y!b>7H3(nKFyDlv_5>(iSL!AOuBaj!?E?ss{Uf2+^SX6G-@6z5)8lha3j zz3Olhn+Nun>WiUGPB%a$msZ*JVkCSdnUHybXTwdCgYd)4hD~1`KnGp_K=3J$uB)zE zAvl)AAA)S1v*=L2RP#`e=du53)0SPfU*5&|*(h2XZ-6I?_}u_lyQ4Xl$@2>#Utm-y{kq^M5&T(Ox(HoE9N1>Oy`W0CgqkmqjX_pCoYSDG@o{eg)~ouOpa#%mSF6wFtpKA z6$3CQiiXXR767z$qx6cw{du>!c zCYi()dC;cvg>K2zZb>f1ubQCvw{gCD;L3W$N1 z;29vJPk-(TV#GznM;Zvy!n$(*8CmaJU$#)8M=w4Q6j2YcW!cUVo9JNtdW%`XA#;C! z%1KVz2X#~M#gLfh_P3S85_@hxsj96^ zhu{1E=;lwakXsV~W8oJX&6pTH05 zO59J>m`j+Zn$W%(3M`tXOr}21&MWsepoY*g;b6Ipu#9kBNZB&P*^9MCNOO+#-3iBq z#Ot5~xv+_H!e{+m{{%%E!>lHblK08otUc#CrxvtWp?zx zi-E3!+@$HhIg0$;bO5F<$=&+2NgM)re>qQH>lvANRr9A!dThDNZINZloGjLRkK~QJ zWDY_6qZo&{2>oIHS4aAD!sLzn0eW*X@9cDIr?+(r#K$8g8o~7tZ`4CyFj>(^^Ep1uGcI%N4J14>uX#tC+4s#yi5ZdK0gAyRsqqumUFX3FRyc{hW z9YpCtc@qxrkB}>xxxRfpSWssU(LkHlhdG)sD8#}4JbUBgWq9?evsUs%Be}?AI#BHnlCG6_Gk8CqWuS3O1`*QUiuEA9u;k*5vT8PbNb{&5~mG+uVbQt zJfuw(4b7FS&6R~41|_u;aEE&%%qV@EOfNbCiye46fBRLr%rbjBmX&^?^ocKJ*Jxy! z$;odR`CpaK6+%h*uO;wTv;DRs$N)P+9f=ps+tusUL$v;Ser+f>5~VEuNHP)PDZ#O^ zL|12}$%SP>ya49#ya0Ex|DUxn{6LnjqPm|KH^WZ^ES~>ZF_^3GNYW7itcW5#WVDt0 z{$ziB0eqytZ)P|%Zoblfxt^jct5_Y{guuCJshIktipIWMU-zz&`k)%3SjyK3)Cf}} zO#``$2$@rK{>h)yjgSSOCbM;6XE^jc*9m90bUzsXT(z<`X1W)={E2nS;!;J>r*RyV zup`?vK~=T;v_40ZRPIdbp0L#+YZKDgIJTM&D9Oruf6MEgA}Mc;6wy-$?9=ekLiVE@ zr5W({_*I+^zxN$2-)K~WD%aV^jp>4`Ge8%YD^3|_r`F_K8gvEUB58)EscY5M>z*o? zGcm2tBq?i^GfD49%p}bhkT_43%uzT`eQ@3c>y_CYU~tjgiR~8^&36v%mWb>Z>7cyi zDr}}LXVN!;i5A?q)FM6V9QshsRJXN&8Sm*11F)uIhR?>qEZ0q60*0HU zkJW33mkED%iv~nP@EYNxEEXsHAKTI}SKxnF#MV?BU_e6gTD0Xpp&zi^aC3Z%8E&W3 zG(5{w@jwCAaR=D)7z4bun!e9cxAhV$&3+xJHnL8nwx6|NhFm~vg;%ZG6^rYsG}@Bw zGqlS)0kS=qSj-Yn@se-Q(p~YAQ*dbulQ_&^HD>~0|Hils(_yXJSgiyVa#PTCjifaV z#XW0{R)gmI0M-?&1cW2TmG>(f%dnU&TGNpTOCy1}R%x9rl8MLBr~lz70`?PT%b`Z% zF|eO7TP`aSj}wo9{e;j8>?bML00gwVA|p`glecZ&*%RjajH3O7{K?cutIJQPJ{+#b zaRo~by^#hVL|-3#LmEQ6E^E~|1bblqXwXVHoEpfe&)ox7&%ajXegpJB_T@k3X3=Ik z4!{R4rP>6y#Qrz(sJsuXZ6*upk}k)|M99|!$2pQ+^NKY)V+&!gnXk^Z=9zv1M(b~T z^(>0ec==E9KTKCy$SX&HZ9;c-zh!BEIv~o>ldjkACOZ!AfmgOgraPRDT~)3R8_6St zdl{iCTShs9xnJ)xQ~7JPX`1dD;u6}!pQkPTF9QJ};|*ldfXkHrFpM?l{oVTM`SyY% zMF>b9nh&WmtNr5yMYl1{a_(yykd}nD*j}+wr5kgdA__$&^FLs#Uz*Fg?}j-PGgB?u zEJhD{GN)BVQF9fBG%no(cNFEY9#({scq297{P_KXM1V|D8zU=yQexKo*-fo9&vg%T z#*8+e=?shyuU8;_!QCo&=h(T?@2oa|{310acK*>;7Rj%{;HrW=$O_nMFU-nmzQn_S z#}JQAc?CT-d$9m~z>F2G&VO6179%O%C-$qVu*VcHY{c=a@@5eyDZZ?L9)tgm&5h_+ zvhr zcOIt_OYQ|cZX3?c$jKf#^oL1*zfgyxy4s@tUaHf@P~@`ycz%cxw4g>q4)r@<%Hz;>KCRuZ$1Xt;kKhWhJ)%7Ni%Y$_B(m4T zWOlU!JaMs!`rNqS@2lo_+h?(zuo%YRT z_)8o6;1XUG7p`*d=B1Dt$mKRL=D`O1^_^@NN3~V1y!>B>ic+9}x+^rS)n@^nrdJy; zaFtQuE;KhXT8!6zU{B@1bqEmKVUJzD&r8^EuF_x$=+0{x&->D+L34VSuUJH^k{x zO@^8BKC=tb^gSXS0_C_qVnZ5^Q_$PYqJHX6H!oRDoQ(y;UySI#G%L3?=+J!7?}81w zsxmc4{UIYtlWWCTV>wM#VP1oWAta)Q?k`kL`@&=CZdq-W>o5(BCVMvY>E7H$7>~T&ii8O*UX1iT6N=of9sJxsdB-O8Ag+R-AEIU{kD|MtbTPToLp2^P9k0N`<8!<{Yo)s4Hl0L9W#t# ze*IGsmK)USb!YB;xze-KxR%}XxVtDN%aCIO_!}R_mhm;cY%$g!Zr86@qlNH)8}S_b z-}X^Iv3p<*6A*WY-7<-fDR*d3J7C-D9asVqb}Y`ocwm;{&LHi>Tpr@?R~PIlZ5MGW><1Jp7t}YU`FlT$;zDzVIj~Hl_a!YRYX8fRj+@*4- zr+0e}q&;0qbh%c48{;hhcCTnoa~oWn9=2zq2t4QAbLe-IGSlT`^C%}Ap7L^w!|IHI zBIYi_MWDMN&tHxrKTl|#AWursPVFhnLwA2-E_M&M1LmfB>>0B`g4YLXb)#nEe&O%6 z_&XnKqy~Vn!MAjCa-N&?Q0pQ=cusTTYNSwU%&&_w-*Jt`!pGL&1FXq;6j#n+@Y8DO z!TXMeb3j|nowqB#iglq%nZ|75rN&F0mQ5dqhI>+YQC*fgVTl^)wAJDYxi9rfY5NF? z8dY8QUH9#219}!qI=T&P_R2%>qIp)!6Pg2D_W>7%b1gRWrvvLIS~en&h3ey(yGarv zj{~EVnUfhLBA93|z+83TCyFLquV3>zla41HCb^g~z>i*7E+=cwrQ<0y6a{^C-xpws zAtK@$^OzkQ|FFZ6-(&4awzKl51{uDsXnxP3#)Z43-~}$=*u?$c$EIlD*yQ?rY>EbsP0w=z%)FlGV-wG% zZx8Bekx2TI&LcO^&DH%`Zb6IY=Lt1xon+2P1wY9|Cqpsnw{#7h(`ZG zH1SHxDla#{owYD`^%kte5Rj9e6Yj3@cRkDt?W$v6Gyh&H|Fu4HecdU5I+Yj~MZeq; zqv=1a7Uh}=^6*UjfAKD=v?j&{{w}Bf`QHD(wEpR7FW)2>KrQmO`g?Ci8`s8nc5c>z zU1PCv&SdHE!=rJ)#Mc`TEIw(N(e!qwVLLa(TaYgkG&1~<4SIcx@DTWil-;I0#{|fE z)`xxEZhrt|8{BL8=a~PtCtW_6=Pat+1lr@dvl%8-Jda!Y{ntPLn3fJ`LLkWfXY=yE ztj&4W%L%~rG@-lX=Hqhn;7%iK0ewoBHK||Ky&^~U3SJl+KIa%2?&3jtGw*?6oCI$$ zTMd7KiJQ6ePB0w)N-IzXL8R_1eMIRqubd<-eVo6!ar=sh(C4!D`!G#Nv2^-zMrHweSo~?MDzNO8yu-veoZP~g% zOKH}%UM%YWe8E>Jt1}wH+Tz1t0@Cj04VZX1JDABWIb9O!d#{0Cr8-*)i~DdO>Z4b< z3F;qWo&e2zsT!m?$+T_1ax%W5yPf;`m?h;Slgx)yp7|&h^jPBFx^6k95fXS4_2``4 zNZ zK%<9nXZUJDhu_DefUmTs;jsNN?nefXLX zTv}|E*DCk*Vd56imwGP?u@TXyJN;I2+eYWY#PF7;BQd)2R-7*!`?kLiyzL~TQLjbk zEv|{6b0whNMI^7ffXwNc*3dqkbj-41Vb>~j-JmxuecfPn-N4P~RcONKckDFEC4SxT zpEs7mQ_F>}efq)t%dyje5rPh83%x5=`}7{78=L0=ybf?@S8~rnp4>Rx?jH9mOtowM z`43d+K39BHf-`0kE|XvJ&Kp4pm>CN~pJi4e6|hvQ!=*m|fGt{kw;>+P&PqLxhK-2( z_N^Ti7poF!=5O}=;TXBjOsI3-7gKYyqeiTTx}sa)H$d7U3Sm?XxIcw(YZ# z(FH22Wi_f27*q7_a0nK)`<1f`DkHYljVBfJfq>!{QELQT7*i$9w0c(Uvw#aj%>&R0 z!PPu^R_La5P!DF_Y0+CD46X5NvODUN5~hMwlgK`^VHq_AlJQb|U-ZyX4Z`iL6c!U*tIJ zT!!*5x6+$jg&@f#MV_bgfK5#Z zyKS~3{#RzWBvtIFyBfZ7Jf`Tojr^t%flz{wnZ9!TRDQsl1PdJz9_Am&ln0&#;FvO@ z?|KptdZEXT6xB!xrcel?gpTw;W=g-zG#(*gcJv#8|J%j`R#0)sPxybjp(1hIBbj&} zW{^LR#i92XM;?ytNPE)6+FL<7f+}^ZYP7&v0f&*9E&ltq=^JK<0soC>hQ*J3BlIGtS{8+Ic0aTXY zyaTC55@}|U_-Fc_38l{(w8CsdtSR3ODw=P*#YQuC@`b`tuRevyOpykYPh^HlJDGNJ zDy`AHptaz`&5G6&6RgryCmA)lR^YbWDM=H+56JI-HSj9nRlsRIdADw(Hi1Fe0ThA- zbwr!#d)V+rfrvK1aja>eS&ZpwvfUdW!8 zaDy=gAK7M#Z!f2#hdgW7C;HZ;Xo#LOLLjhCkrXxwJsSt_Wgi=MR*71EoTBY}&AlQ; zNE39@L#5C1o5=BAhbqygQi`N~X#zY^9KmrHo=VGUU>%dPt?M7I^J7|E0nV@vAxy8Z zhe(DpJU@go&6MEwytZsGl$)b+fvuKh4-h#b8Pe_NEiA6|Wtv&@YJW`&xC&tZxC($q z%YdtZiOL@K#SjTWReV5l0HeEu+wI=QjSVITjPx5s4d&>V!59NZ@*Aa6_KG7$pno$cqbY3wq&#C216pqqb(>7X|{4y3+(lQS0j`$hzC0ge_ z+3dwiB8Jr!!$3oOgxtQ48uILWvgZJb9)exsblg}(h-g6} z?LtTU#5v2E$8xSz|3WJOiGVf;V5VF|x2s)L#C3V*zIhAO=yVUdxVGZ~kXg~MMi+U} z4(|Mhc3(52RcmoivobKQPCk;9~}$){Sf#s53PZ~Ra1gl46{SR**x%=E6?k`DtB zkB=Rb{%*x3kI@9-oUd_M1nTTWz>9NQ^MgtUpT26LQnT+VDy0^O)54KU_J&S_Kh{pr zPde1nUSPV=u$$qkmwYus@BNUFHt%f_o}@e1r{H~P{i?9YX^7egcLK<`n{%*LhbCjBeII1EqYXtYFuqQVg1SSTiyfd9tr#H*z zP#};jB`nqHFV-gfN%dDFMOL>kbhwJaXklcePV;>(5yyp->&@V{Cq++YIYCIgOs+<8 zKI1L}n}|XLl*6FB4?3J^+$P!+mmdXh~3JPA>Ej<;UZx+9N29=!SQ-clBNaVjzi90T_E)Q{_W5R^`3k&>#u*eZ#!h~8AhH?V@s*~B9 zddp5JC7NEDEThW&p2$#*MAJ$B?MU1%T-WjB0v@wM@^k@N+Wk?g)X5STg4QKaVYhbY;N0cn%a58vWWrw?Rlj41 z)Lz(T&6TWD3G!UZcM%jJyl)(k52Uic3ae`8RVes{l}w}HjhIOovV76B#HybA{puR4 z-8(yZbyTVq53kBDkt?F(J0t3Q)C~vehz@5h&ThT60C=Wuy-ZwRyK7feh;GvE%zcel zA;4*Jt?aVmRmiIl;52Dh2b?A&JACcnv8<3pTJr<4WL(kph{Ei)X(EJJF1v42_0P|q z^a-+lK~jy`D1VLCRlG)A8;J;r;+U%^cc8zcW<-@=U!(f)E23jX?WU!j-El21Qu-aG zQEa$}1;M425OELtxezOA?Cu9tmS-6}OG52tN+f&OEgM!D!C}}TXY#b&dZS#Q?Pe;5 z%`Lcf2`+)SI4Y195z+A{E^hbPt`3Nc6NE){dIpv zXE3|dAy2!APKl1CN=5{`c}gS6*Wfdj3zY~s6wC=&>XxEj}mHO3F@e1?c);=P%rdv3Sg(mrBx9~g1oP2=ldzLS`K|D&6Vc~v5# zgR)d8+b~`jylGjh%8<0l*%@OxX^&Hz_+V~25+ArzK~5VF9Uth475;X#gsdmV)byk9 zTXx4s#ixug6`qnyY_*rsVmoEzxI$u&5ESgTe&=fvVEO%mGdn zHZ}_xuyL1?M@Qi}aH=)Cvkp44U}x8 zj3)jS@ju0b#I6P^nRb)`dl#*RO+q~2XIIm4q`h&HBLtu13O-)ICo^Ni1?GIu z9_BSRm?%M|sN!MS8Cf^U>?POSAwN6cN~WC)X$4VO1?3W_M$1zgL`F7_ec#Lf7)`;4 zByF5T;eazlS#4JOk#g!gQHZ7eFIG-A;?6_y*p^(17s>Yo%x2%DVpR%y@8Ofru|v$o zavc+q#^DMt0B2-Pj28_rFU6(`n2l|FUvs~&nG;-F17@??0JCKi zfNQf{zU*rPCe4Bs42o(aK109sW$~eg;nM9S3AlE)KgNsfPUV=&aA^wr)cSJpt5-ny zl)bzIx~L7ktWPudlhvE8OpVPA51O@15r;hQvO!g&MN4sdx2*st^;kEdaIT50V{}Sf zBO>pC%x0VmOq~RqnpJ66%}wcZb5;+P(TwKMi4AGPCWI!08(SQkEG?TTwo%vGG1@DN zDil}DAM=DZSwIF&yw$2SkU?`y0c?k+zuSS$j}6!kE7G5v5Te;2(TX=RZHA1q@8>n> zLNZnAe#yO>pikz%AhUurfFkAfBIR5OLs&6i!usSvx++m+&J{j4kgm*Zs`|#I?xp&Q z#InRMxQe=$2MzY0LW4_$&kM|Jb-P}hcXbk~{uaP|RRR#e_AMa5r@sQw_|ZHIAo2NA zs4op9vQF9DLl!S!Sz}R%XX^w~UBVsefgu z?t5>RmOfQk6K0Vwc7U7|WIWj=$U=*SgNPIqbV!V(%tAZSCa9NLCZ|UA7i|Z~mpFI; zHWEzBtXeTbVvs4(C#a=}Q=pewY+hIw?>;e~xtV!c8{ zh6(-$pVBjh1&FyeISXxXF4f4?APNK|x)doMea4A)LCwi2GH9U#K%xWvOw_*;T}1~` z(-~!wZtd&-@7&5p>~Zk0fyvHB1o6tM(w?s?4GC681W~WNlMunox1QakR?EZhF^u>y zOM{!bMa9%vXYfA$2HL0FyBRl3KDS1{h+}BLWUp#yC?xURHkwIue*8`M18z2s^$)8c zdc8iYF4InZ=Cv>S3i9(laGA zJrtG}n73+rnC6kvYUil>m^Fa+U>12M5YP~o?SO_zvHhbVF!eF5Yb|F2-=xSHU_uGu zx65fF2t^K1oXhV@ZO1cCsLlj>r%Kgui2V>6!An7Zf2a|mvMIGryU_ox3Ol<*traU3 zk-CvU!4cyRQ)Y?@_~9plwC4LhD?zTPDVhz>A&SnXY1Yi>AlA$&I!i%5)07bxa3Ev~ zdWsxxWhaH@^fv=c)@p><3T&=I5zF=p7xa`ez_BxB{F7q;gjWv}hZScg@J~)0(8jjW zsDlCv90;3&{z?N$Xi(r)b3OON#p!)*Xlj5v1{__oSm>7ALI$8@$*bBl461uMZUTiq zqq^h?f%B(1CDYtv=XT}z4hB&MS@%C{7aQAIfU})pt;7Q9x!&lD>5BalE1SVM;I!NS zT;nYKiv_M(c>lA)L=@pDkf#^UR8HpJBs+rvI4_+$|2QwBen!n$gUiT-oddg~AOfcJ zN7zg%<-M(o_ z7qUoRDCN0!bHi#l?&tS53?Q@Y7NYzDo`_1+GapWNOeHJoyk#$H>k4x+1Rjfmx?oly zOQQompC;l90vWpK7nhVkjM$j7%dVv)#Ul;{}M>w4jX+)VMti&rl zNn|Xt!pA-rh^XMem!cUclo9;+kA}b;%sLUsMm}ST&S;a#yvn?+2*iLV!{SEN3#3>B z1eewrct9g-N^eRVK-Fov9bRsUwTW5&W*8edCg(RYF|+Qr*Y+KQ$Syi&_W|S97zvTa z^f^H@;tN+hyv92q;{b?oQJ4ifYq6UJ)|dqvuA4y@W10m5Du(&De8QxWWs>j`c#!aj z&~HN^pdScGO(FcD1n>n$TAysMt5dzqU*FLtJ*R>JD>NT)f?3)ljwWJB{fd7`!dO0p zHWh}F`T!ZMuwnf&qhyAJCum;~akgN2z?RKK8`$bUy>K$V6^qdC{d&aGHK*h!!^yz2 zAXXk|OGd9;`U>G;%>TH7zRZg>5(=GX1Qqe4Z-Ja&(~eVs`Mn6p%Xze(5Mjis%ll}2 z8G9H5NWA!Ra7E+N-0w4eeRO?fZy4~jShCmcW8=o`w`J8Z;51EYyNa@oa;xh=de8=N){1)kj)JoD;zjGF1sv7*3lUd(`G5y0(k!%6}%?kMVyg=IbvgfbfQ2fKLoDIWt3U#F?w38o^+=Sod>QkWA9N7Ir1#ZvYur$)cdXLf~OQFxv`s;Q0KKw4=``>{BTgoZRl8SrXi-J^#QeT@w%7s)ICH#oGsrZADOK6m)n0VO46PpvWP8HM>`Kd}zq%JXmgmt^^f=z}pSC0Tb$KsOSPm1ilT zW%6u%X;)*dL-evawJjA-kNO8+R>zmLd``FRSyR%r7i>>Pmmiz9B^q~%W+a{u)w7E&oSc9OuKSJVP; zT;Of_p3#~?SVUAnSxSk)(9FOQ_(uypdpF5mDf-@lVM*Eor84E^f=vYof77?P8F?<| zMxNsG`r39fZ^T8KG8Jg$LStf3iC9F1^WIYkMk0KYF7_`e5j58h6ZB3NM4T`F1o7YF zbBJk{kOAYq1KzLxcYG^7TLmKr8z*}Mqkd^xcnP{82095D<=+w%D344kiw{c5|B_Yw zB_eJQ`9B>m-4rjILP0=?=s*BobO;C+J$oZl8z%=Nhl6=Zn-qSm;FV?{82tk!R&tq& zU+v*a1#vYBlO_m33&HZX9O02=6H0y(;rTM-5q_>gk1AX=6+$_1( zg(quDl(}`zVw<1I*i1ib_S8_SQ}Rr4vDAHw^(~n8Kt&t7I*Id#rlOXZS$t8=rHL|b zY5BmzyHpm>0ci|n*5(FAKB)?g*{q{Ide)kpeM&Fz+eH@VO&SM-)snW=!7QHnx8E*n z-CV;YTfy;z`i(V{r8VU9g;aaovPJLud=7fmOY4Sq>V~qud#ziEJ$2k941?lvTewcx z6pL9e3g`Rpreygx&yH@$qTO7*LO6)s9a5t0wS-f4>#t-!Z8^>-QMKNwJhm>`PL9uE zUmcA;(2Hr}*|>9C1Vo`z36nqzl0c7PQN=+KzCni~MTas&bfkje1i;_;wm4!H|KGAH zDGaCRKe!sAqdz}*35dZni~ZA@9_9^Z zyu&GE@-2i21*a0;r3m?T6+IzN(`q z+gAKXkE6%6#f2cM)cMbucYeJ(|Gm(CCH;ZqSO|y}28iGP7Gq=kytN!AHG1vW*k3kJ ztFn92Pnw=7gmB2ctX8tHh_PqD#DxDGC>-(e|J8Ax;cT#NAGaG~L=~lqYHGwLMrsGO z$8FErTVs|gqDD~^wOTu(s<)NmM(vuhgBWe?8ntJoCB@sm?{mC;9>?)q*Ku55&g=L8 zaDMxJ`A3mP1vScTF7VxgORy@Zg`P_6>by+VbZ*mKA>-AdbkPbr!sQx7Ae$oFBj(;P zB5#L1bMhzp{5T7WY&1a6;5=b(*nUcOQagkMp=5=wH3P3Ib(6J@gY7YZb5W*OiR2}V zuoD}eZ?c3!H+r50$|dULQQ#d+c2?l@2I?js#R>OyELDzlC+6dHz;%gU@*I1W(Rf#* zL3lfiMJ6C?+vi?)skox2m3L>G0eKoA^+B9RMu3sn!V-VEFSgO1aR#pz8pJ|&P2l+} zWowp}4a*-w3Gophbk+rG8oC)^I_q3d$aN^(UZ~^=ljN43)}=0TyNar{H#MtLcc4m@ zKTbm=cR9CX`Vd#Xu#g4j#D$uKjM`F`@{{pPblL$lvKd(PNH`n}ovn zX5uNN{zitidDI~^ug<=+#j9k_Pz5#=BRQYRwBmOC_x&nqDcpSM>BXi+vCty?ux5K- z!qzc`FY^eM63098>kwoXqxiFrEE-nb2SDEJChCw74SlmHmd^e|WL6dDAyQqcnv`XTj+C@uEA4*5;@I>STASFvM0IgC)n;MG1@3!X;1|84nea z*QAofmqfVoX^;F1(kNrQ)DLwnCCARm37l89pDhtm6RU!f0&2mjn_^WZ{#3WU-qz(*@E)8RQ8G;s(jLxYn}m#d9h(AW>|N(!^xPcuUYsKmpse%)u)> zJD$2QHx4cI*r>Wam}S+K72tQ3gGo#6QP4+z?k)i127~)Hpig?C_{p-l@gsT7l>pbi zdjfoNnv^qn_sGU5mVT}ik86!j^VNLq)Ba-akz>v5*MC_-Y8rb$=7tji<9YJJHi8AK zLV8W0qzyf7YAiH28PN)*0*+eFnmaS`)jx!k*#;YFcr)JhzGn)tPy`wBwug*+!@LixpUhw9vUE4 zY6}53vHGY<_JN^JB+6D#7BIb@MR0?senYP}s0?vZj1fg_b9YlcOgBHPk!=nSM8@e_ z`ksx4hFuV?o^eb3^vW23(?0c^%6PbBWyYlP{fF12@H+4sPJ)aXKJO_+o=vJ6C6Rq^ zwWYtJk>ZtBR|qKIfLSzyZb7iL8$?_u+q}BCd$p)+cqSP#nhOav+-4j1(OiycX%r9T zEgnCsTC5)|?o+sy^q9AJ(jwZp`w(@tH&abf3lPz~*xC#LVm@>VTUOcv`);#!$U4JO zMg8~V+^G8!j4)7;ddK+I_Zib>T>hHJYEH9xK)Pvq-YU;<4+Yk5O#ETn>?D!eDTSNr z#oC(k`{e8NDDF39XIry%OBfmviX<(4De;^;l)Y0rv3G{vs8 zO)8Es2*S;_Otv1)PnT_#so3DyG!^5Pf#&t;3K`}O{h3}89F1A6zU%ciScM3q-dg5w zN~2NwS{Vagu3mCC=8`2`hQ0ZWfCE*qks`~M0#TDB0h?$_V0?(N-bH%N>h3<5S^1Hy zJOjym=Wuj=({A+uvoBf4>@B%Z^mwP2qujvd4@fUCZ?rIZO&91LVk>5Oq&T1g-8wc3 zFlhmf08F}8V^mHm$%&#^M1OoDfBg1d4b;wwnH_P%NU-UJP}}RCZzKYcIOV3>U1&`U z$zzs)nZ0?X*=$+X;Xwd!8+5UcsA*r(F2(zTts_#@M$f3v>w7H;G(scgUplE7ExG0k zdQT@Ti_9Gwl{YI+4<(c}55yS;lH{g4Oc{}SsEPNjRtGc_;rKREC!F}VTL{26q)1i6 zYLB6P+P1c_h;yvLAa8YzfU!&&F;cH9o>R2h?*yGl46$z3kHq8^M|eeErQ>aHmw9o z{F>}b5ja5PHk<!9aL{8CrFNuKuXdc6V!Td={KPUzfl#rkhryDs$(~V;#B|y3f4B zB>s*xzK5n5O_x;6LS4wozEo?ny3hd?)WM6}1)&utiULcZpR%UUQ~x@KgP;YNH4#U3 zQ+rxQ)LjTC_ls4!7Ztu3FoYnTeC}OAT<(nf z`?RE;l2Yx@cZ-~!y9)k8XnEQ?dtC))b6D+kK|3A(;PvA}D)*MhaKbqI&`zSWaj0}Q z=c;G!+u2Whl;!#um0HV@RH;I}EJ9yWwiDN4zExM@kXjnvU&`OrX^)oA%Ngb_yYQ%B z=Vy!9vmx2v?%v<7Uv@_pEB+EeL{yFbc;||`j1E-`$2Y@9fWlThR^-}`;xBFd_2=g#lq*&mW zY0v>(J2G|D6rDBd0V0=hK^-sI9b~6Fi*{aZKoZf4Zpl^LC)U*cyz7U;02?^9FM7L9 zH2yK#TO0B`nsVa7lIc_<)nHl1UQ8=NDruN16Yc6#E%aCbOmTKp(NA!#XDu%%3)eQU z@Id7Rc&e1Cr}egt_(m`2D3O=qs31x;?-Vu1?2^S+YbfNiRzNZisv;CJknK)fi$gyiu;Z5j2$vw`iqT>J5ei@Vc%gxnE#+2${cbLTLI zJwnN#UQzAK9n9GD%60b%IZ1Ry~grB>T^X=q>aI_2?4{IGg!qzCycZ5S#xd7pjX9Dpf_QwA5zpJgu5ZF z608Kl*m+&+{EZMDpEu_B*|Wb+N$lqoM!d=2u%niKGi23f}1x7BRt zDhuV#prmujNK2O=3(p;+3=JHD)b-$Hh7C#;1$r}$XmaSX_#zz=$ng}+3s0n+$eiBg z)-lES1QdYI-j4wj{iV8sBkZ_%^i;D_X{%RqNauwXXdpajyKonINXDb}>EtDU2tSw+ z>K98|9esl(ccyS_Q{%^Tk4Xk&NoX9Yyv&_$2D*2Kg{ZE)fNX5xj%eJ)#6pT_#Ock5 z;D%NPt7gQ@e@+=97an{2a9JbYZ9QzKVpv&nATFEXK0`&pZhwOh*JUZqPL!3{lm&(1 z#Bkkr4$oBO?^xDyh{U!hG75cTACKpT&9mc`bZb-h5Qd8v7Wtt5w-~l}Ay-m(O}Fnd zZ~r7n|2Q4>I1c{aYR2UwSBW_f=VBiV{qp_uiq~Rr`Ny5fp^mQBAZO*d3C;t=TX5}+@nr!OQTO!doSNq>3kfA5+6#gLHxe*X9Tt99}+blK~F|NTFx z2mW6z|8mG>IsX%)u6ilt-&Fl_%4HM(lTz?2<&T$N<}Mr4A5P>R3CX|w=`wVAyMG`V aqyOKvp$;Y0?*Y}X>-cLcuD?bkB>w~6)`{Ez literal 0 HcmV?d00001 diff --git a/resources/templates/anti_air/shorad.miz b/resources/templates/anti_air/shorad.miz new file mode 100644 index 0000000000000000000000000000000000000000..c68e57958543e5382c9d1d32de76da8173826a6d GIT binary patch literal 7205 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a63abb1d91e81d97d8bf73f723acd8a8fc1f1a69 GIT binary patch literal 14905 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..40c5d71a1b1b0cba43ad6ddee931e70769c29cab GIT binary patch literal 7993 zcmZ{J1yoes`u>1`bVy1|cMjbHNHcVIN(~Ltf*{=`IWPz)2qPdMtsvbDA>Bx)bp7%B z?!Di={@3rEwfB17c;0ufz0NsnJ!fmEJVGG?AfuxL003IR$V$J|H4XqkiG&1r{NQnM z@bq+Wh3uKmdlm^l2{|`kKCa=9kbdR&BXVG9aA9&XP$#9OX}+AD^qcYk>g&wJftU4X zAyOQnuNgy=Ej-lge!580-0tYr8@1^TFb!1mM3*kAF^8y@tha>>9|N1AxAylo_aSF# zEl01LopU5w#36@21O4538IK&Z=LC#}p3^2W3|-@D2tj_~#c+THC9bF9DQ*v9gg2*i z1YFMIZ?0Q|91taQO3j$MX;ZtjOKn59K<+waN8w+~p9=*iH4~%XAsLHLC@c56%D+vS zh_um_V^}36p3;3`8ee_vNoStehA&m@s`{wVZ?#h_L;*@8ag+4@GF#GTqxy1M{PAcF zUEex_$=6qtELAYw+t|c;w)>ds&eubF6mK?gc}*i1?BTC-B$O$6F0o_RlZ?@CVuQwp3e7vM@uVmY zNa{TO%4WWcrO1j*o?)KzwN1^@DzOsynLU-Y)|!LJvje6lzR9f>nHc9O^+~GYxF9ln zKO+=B54{wj;uREi2!D!XekKfRvl8@7sqJFR(JuiMTU{$^ar{}t6D|xb7k6I`2_i+i zOjN}dhf}-u+si92L=s$Xy7qJvPKW+zR>#x2S0P)p=L|TlUHVbndL# zCasN;qB3IYs-&TOQOz+)WE2(+>ET9KXN05l+P2IGFXm(Ca&lxHnl?SAkv0aS8y_iB zT#BXmJbqE5FQ*QYEoXi%8L6@K96i$Q zu2I$kv-Vg?)~gR#=eZqZJ*Ds&jDn^o7b2=frk$0ta?-m$#^~nN$D89#*R6CE+2fLmXqt1_GX+vLzv6y3yn#96%z$g=M%s=2)?APHK zXF=Dr#{Is1%r%~l%88eNj0-v-7&_aCqEf(BeuHTlj0XS#QVQxME_Lq z&}HO7e62h0;+5F7?5N&o*SLobayfUnnHnGek0Nj@6W)Pb~WLRmRx*vs63?G6Ob8N~q7rivtN)^0_v(&3F**QEGv9Js0>k2gi+AC1zY+GRs^$9-hhXJov^W; zkb+%(#DH`DfMZXRA@(_p@dMIjI?*$O zJeYns*$?3kURGse1GNWK1Y}jtQE<>q!%ZB6u~1PL%WH~?E62jT!iE1v@{IrZP!0y*s;D&f=FIfF%Bk~Y?(DB?bqf50XYWbuhe`iO}bn+^1UMxZDh!`wlCfU+A3sD zx4yd|oaS`Zk{Y55x%Y^+|E?51#)Og`bwF01SinBKNl^R^?LF#k5d1d_@#qlB5BF@%kM zaKX$hNGt!EOG${sVLB5Nc4c;^>Q`VY?@s>4vh3{Ee+h^qYls0Bi%VF^)O;e&(oh51 z`Wb#2CJPd}_VN{KQNBs%3zuck*)H9nQ=r&xr47m%x$&*!?VAMOs+Dk6<&XCTOuj@o zqEsF+Rf-q=nA5u!%f_SZ=RTIRt>3NBxXZelx3Zk;cKuUTy*>yR6N?-vpN~;;h|pbW41d+RCdt2 zW^9of1rr9P7jKq|8nLZc^`<<<(#I{qj*XMoXuZ02el6kJAeLYz<2SwdKfpxF)H} z;79)I2ke?+Qh~PfRbPh-MWT*0y{MEq(Bt6%s{BZx1fIi7>ND|S>fVzPtaI_2(w~M) ze(>=VRkh)c?0ligeEU|n;hHq<9k$dwmaN|0RC@Lj1}eKP-O=7NDf8-q9jRBF0;^q# zSW;I39dQ!k`mFt%$)?ir@W(Yc0+R2KaONutyM(Ob;d8qrU9ZS#LZbC;1749Y))%!D zc9rrAj9)ZPJsH0MhM|sM+|js|hf_EPYODsBIcuyUJ{(P>jbFSvpzQO#3%uMx^$`zh zM~u;m6DMlSbeHTaX>xa{+5S+@ci?~-|B$5w=N2h9^SG18`;&kf!j>x2j#J8hFB7~r ztC^b8th7OdWrk;o#1X~}0&Rxy1-L*W^eoWjb7{qq*!Us+q;vrC9>!9HX@4+!3|f1G8(@2RPmmDy3LLTH~qx( z#=W!!j{<+H2G20}fFJjOX{ADMP>xSdlc8igsZjK1f7^ur4*Uy@(@OCsL8XIn8KtJ0 zY}ZKLKXD;gT#gYF^isT&^it^w8uQo`SL{hpFZGMG#d4o-5eZmU!;?NT*5agc+;gbQ zIl)U|#aRAETwe@cW;06H?$ykq4wCMN>48bVFNMK>pqk1Kqe{r0m)FrZ7M!-5;-7oT zP?#JFG|`T!%25rr-D%HCHksnLxsiT`uG3+6Ig(oXQ%!;2Zsc;e3o~=Ie{mx~<7(gZ zEOjHWYp$T+YLD|HKzz^(4mJs#-vHuH5N+E6k&f4?~yqfIvmkK|- zfwmG03t~gts0MX9BtzJr4SsTl<^P{n{N%^y7)Dy}TPsh?5~P07}zlIK$( z#ssTh9icPuT3|VzNr|S^AmUJxlWt67nuc&|())$}DRvBy@hBK%CxkU&?Li&Gi4Y#} z&3uPsSamY-L8PJX6g`-XcuOf1nyq%{-25Ya+6*i89!cYW^r5a)IE%`IF06kTqz}WH zmj}WvC;wbVS5=4G#=+X_K`dH&_^I@&a`g@jt8kR*e9~Pi+t31pypyh zW#+C;Kk zhrX;2gY3`#E|zXuww|uu9@e(~Y8>dwoI~84%Idm*t)NVIWI|VQP(`x`tlcB8=z;V{ z;l;~}r5DHmfV?>Xfca3^*V4oGg{!xxt>@mHiffKE(VOL#5LBx@9YF^5>YnykowBq# zt%*ulAIL6OH6qmGLxAR800zDX8M6aDqy1^M4X(Z27x8lNF09?e-rGU>U?Arv>*b*P zmO@=m4UFv;UT^O@>`lM7DNZ(&pwQ?9hw-U6JKktc1l#K0a@9`E&M>%~1`6gRI6_Jm zzJ=P4{pc4gnjFgY&i+wRp?cE_xtiwK(=#Kk%@Qp();3je$oN=yX0J;MuNt^z%@qh7 zP$SS4Y-!|?QmrfBOwE zy~3o?!==&Rv5rI&Z4!mzqle-vY8Plf)8LW)D@lv!y^I1nP~qQfE>t?g_}`Q=AZ}hJYY)J!hk8NNCzdPvCW<}%n z$k9KnHK|ORkB}-U`mZ(VhT1TRGW^{j8#&@3kn;Zr%8*a9Hg8)_r9L0ryR}i=1svS1 zF3d-;xtBN zU=1GQO@y*%mS*QFdDWpf(W_AK!WNg711iaBdNED2|A7Qx_1`BrgN_Gc$ z^L|TbHK^JK-FYf^5)OJ$ieSC|E<7RTfVuHK%-z_un|ak`;M*%m7$Vim8yRyy%kNqA zqOC2lk~xNYs2sOt%xiSusKG!CLxCU@ox0;SyF7J zPn>5BL((=+Ww8euy;F%P0Z`zYXRXfu)-k+Z4s|MDa3JkbObjnL;Tg?FmIZHig#ugH zQ!Byi1gj`R{8`WZr$p)fkLmUtRYmM6m0+VI@)isv>vp8*?oTKQmE>Of{9vK&KquJ3 zd$Eh&Be+=fYE@tRrMTjnr(Mr;R%S6p)Y;tU$fGFBH=Ea|HQHBsa&8tWn#7%Ar0Kot znIDmK-y9*^4|6df=yC(MeAz4gx^#d@^_{J9B$!kLFo{xDD0i$F#X7y4T^IAU8-t$@Iuu8;+0T3Cz8M!vbK~vhQv^c`qC35z3rjI8AVF zVi67VArpfZ9626kA<2gEWj$YS?)}(+@>Z$C4?hn~%$OLhH4JrYE5{!B#^2Cuch9~V67N|%#VLJw(L zYH32pf`4u2G^{Yi>Y;!7P1puhP}pl0X^+tpqXh@z%YPf&IiJ;S8qV8rSkG?K_e|AI z&0VJ(>_q8yALaFKotwDEuuh~!OWxR!{*pk3TR>Y%CMTD`u1NTXMNA}o#vSZE)7UDvo@)ko}x{B7=;*fcJ}I&*{;YxQfe z69dz0&PUZ9_@5v<;j2SMo*!W?qa)}#%~(U|IvwlbGM5#PuDQD*y-~3&QM(7#Kyzzi zatMVMdt)+3>$}ch09Lk0=|=hvn4$syDT(Lo!GhFWmN4mHKRVVf{{11Ox@}Fl6ye5T z9FizEa*J_S*JXHy$uU&E(vCr3NVAaNbv15SsBhUIz5Vg(m`_^qh!?LfPHgI%Ezx`FDZ9$rTsCjO{Y+KWtlC0l*P&`1QPkW` z?i5%BP{|_Ay_md8?X4I?aN_G?@4GjH8C=!Ul?;-~<55&8Hpe+N*((DhKZ1F>oJ}Z1 z>I4+J0Y$d;26zfRcit@?&FsIVwvAYe-5V`RA;ajQyH5q59`yy~>%nBVaOzH=ru#ed zV{;673$-yMqpB&@vO=x!pTkf_Qu!q_3hu>(GvykM?p5&fYe7YA z?7)vYlB~=4H^RE{Nt&l1d|*C&gUd=@*8-cMK$MM|HhCQ<`J)@0M^*Q&#{ps+ROnmi zNangLLO#9FCp+0?e2XK5$Pr~9&Y6AjB_(dJxKw#Yw9q=oukvJpb1@u8p0uq1 zno%AaJ6BubHGyo${WF8V>J%kH2g|92Jg_D*--*ac!UQ(z%y%-EhV~WuJ z#x#0l9oJxqZb*$99+Fyh?7NoR_#Oi1BHlOx42ho=p5xrIH3xGZISS0*#b9d?x~Tgw z^*TO=vIzV%OBH;7*f9ao4-^UI@miU}Kf-AXP8!jLWsErBKjO13I9)bB%1X82ZhulA zd<~PdPpG85G{)#<+C1h&HvwU|!FFr8qx@mc%53qkQO8}DbtfCp`peP|!duP+;s(*u zVRo)n9R92fD7Pmcd(Z6ZNXzrff|T_?IuvAkI?9yEr+AFB_%3uTOyE&&9(uV;icI#> zR5C}N)w={m1;BkJF2mG~=HdGaLV?l+t`+LtS1k9vrxacICvTXJudKs>PSXPwL$~*X zC(7;_3TiEr-TAthgZ+tYtCOboUPy5qI+QBg<^q^&38)emTr< z{E2Ed(%m7X-NS)J2O`tQ#+ixeEnS&K^l{Za*3@Z>?V%LAL|C4 z9-o_-8oui?DBvd>#YVnzH!Cb!Mo)LDnw(l^9XB>UF)N0zvGVFXJ;6NX8_LL6wE% zk8k^SMQIMBAorqE2WL4$FNB*`mget7@D9$3`_&3-GWX!4Q)|01-ERYb_Nj9WPu=we z+YVoDoKfHT470w~tC7FIVO?}4y#fLmg$Ic(&*Vb_p`D~lM1ZHugbO_U4a{La?GM|#HoWs0ot!`3f&|(cjsX#yI%Xj&~ax z-rBO|^{U?R43L|_{sY7DrZB4BrL@#jX?9M~b&%>O%V=3~M#CCPt~YJ51RTG}$D(LO z7RV7&sx?Um5RIjKgFO7+_wc8m{2nJV>F$aW@7|mVUR;ehocf-(=+U@}Rlx6pXvjwc zR?cVEoR)mcf9y>ReCufOv5}rn19yu+i^>HbpDADeW~nkRp3%2tr?Re-(5 z<)oC}AygcWw-mPY1^jNd+WuDvyk=f!_$^3(pU?h2k@b3EYw6`->#5G6rq02|iT0pl zksfsG|9yn}zyTorp8mT2b)fqv=}%q%JNIuAE$;uR^8YOIr#SzoNWq^){!6O=S>;b9 z{!f+5hbsT*@;`ZhDyDyU(F6d%zx30eq(67}A5sd{fA(5K1r_ag0PW$ndf1h34I3!pI65Js;k9_yO z|Gt;MUU!{c-TUmd)~Qp~)wRx6kw-wp2f(AE0ssJNfKot?o-_skfY|~7pgd>ntzBKM z9UTt!bX|-12m^jsJKcOMObitjJdkMf_3^YRVNWw-SJ%~LvwQtwiC9o?`fxYvsp}m) zihPe$#>IE$E!Kk3n~5n;x(WU>;8-0;)L=2CH>t3~W4(XfL%ztCW3Z$_ z(|DfY5%0CDKvx^-j2FMsQFbL6?Ia`VFMX6xWW2ZR(JacE6n6`8WDmzNUQ@Naj^7W+ zkg)Xc>Pi$_Q@lv_n5w^t^#o?4SQ}I{&erVHT1hxobW+kvB6N9`rKL`<#c&jlVhz_t zS~0Kz3(IHQNXnD;)_PeKS(5#YM!PcDOLoR|$a^q@&|61|X&Nj>w6)}uiOMdC{<#m2I@CG6w4X+K zLhh_YBlyd(VA1Z3H}kDFLlU~|EsxBHdRKg%^vbmN!{^&99k_g2oX!M(zC>(i`K`ng z4L%)g`2@`VR8kkFHBhRA9L&w_%TsEMuJBWd`8us?th_d_qCuzDkEf;ALNy|Y`wkX2 zvo>INtkr#5-jb2Q171J%r3<6-?2#tcI7ET~HFgEzSs2Qvz^2Fmhx3QS4iV9E)@>CB3u7B zps?raeb?G(qkefU7jj?QN^lUSbq-0c99?ircbwOV&pJ83)K8j-i5x(eL?=Zl#}CrDn~Yua+H2Gs~SlTQ|31_H8WuP}8bKdnf7 zUNOnsl|iwW?II-5s*R@JD3fp*bjqFX7f7IA{t5i_QKNNf1->FhJ7FuNVU;q(1jkGg zlnGMP$MP+Om54k_n3_LMy-SZy9qK(Vsl$k@n8RbU%9**~t)fD~HPHnzP*MwL9SuW@ zza$>x!Ony>eXyzd(!y_vY(2KF`;Zswgb=CE=DsD&9W8goVWK1vYdVaO@OCMFpMUZ8 zjK|zZc$k(OLjE2n4;T*_$^}l)Abb z6`sRQg`AYbO9c^wJgM`Z69H9{<-G(xKLW87qE2hwn>3}fu&?UbO6L61=6n@(+2wU) zs+r?j+8B$#a=3y9()TvyuZrgYnmQOQHs#-J%HfLV3d$Qu@q-Y$xQlCVzT0`8tF2nG zoB2%+<&6wY_ehPnA2NO5(X6u3YW*a%mBsKgIRMnSsoe6JKB7mF)f?ZzX1Lf%UH&K} zTjz{wc{Ukgy(C>Ivh<32c@}JMql!DEVxp>=Sl9=B{~T}wN#t0{&|I3LT_nPBV@N|^ z(i5(WhU3bYM-}$b$UWEM(3>#n{}qOnIa8}5ahFFZvKq3*|XpI%{J84pp4}?!`rqpxwUTaNpXkQN4z^J z;TT2vSX%geTT&x{+`+23Knmhu{#t@`ZI-=XeaxXJiTJ@ct1^XS!rfLai$dBSr#}}| zqGqp%^J`bCy{2TZc#ApygTy6g1iBy!-yvaZuy9R3@-O4G)*Q=SyQK8k-a<3oAqpP5 z(LABk@6_&A?fyT0eL8IG++ROJ`Qk<;ikV0?L{KJAD=aNWt`*cdk$XOUYMxTmb@!q>UBZ?7Sgu8j_&;85UxD{AsxOVFG=CiyJeIxn_h;^6D)X_KLovt~;cQW1_TWBgxtu1? zO{qW`ZEsLOfb~a6Z1l!q@e1E_`SH0FIRESwaP|tulm7LyFUk4mKvZ`s-ctkR7rzhN z{p*Qrenbjqala|&eTxDRE){S(5J6!~S+pAKJ&&A&28KK|9uR1iL^m*M>eWi2KW3RL zm(Okn4d%JsWCfa6)Mh{3nkI5Z3OCj^PHu-4uqekmv*PIE3mzDnTI2bu7wKd@yD>gw z!7tB>R8S>u{Bx$!jT6$qf~%BHE?krRN1e!b6;b@l^@ajPo)=~GZ`E9H__ z6X6eOQkG_KmGMyUF2N$}=Vq~cHjI2Xkp!Ps`nWIA#!FkZaTlg!G=wgN5;f93)0hJ3 z8+VB<#28;ioSg6XuX8I-745D)z3%k)@XZGiIw}XYKw>Hfzw5ATr_Bs9 zzwNV#gTC=Ctc^ayv8e1(s!~i_w!n;0DpKfk2+0W<+e#1<+_q(tb{gys=gdW+cb>My-;#&Fp0Q=q9mt!G=bT+}$d+i(XN7p$|%B zll2^@sNtZ4K&mlUIf4EDq_(7~d%Z(IZSx~%bG(JXuYE=oVRFQ`H9LMW6rm-`7o2(x z0x>1?j{&}wlM`QC@;Mf0n12ecaBt(1j%oKe&N`()(9Azx)te{K02^CWy==eH9&6^J z2+lcDF2tY%m=jq>TC?5hZ1%0^JuH9T72;$+{{;vaZA^h3E4v!DZAIxu(NxU7$f}D& z;B-5t-`O?EC;BZzfrZ&5ON%rCD22jdb_+ULb5ZVA3(Du*eljtUAdM^kkITy*hh=#& zG>X<8xrs}a@$51$-LV@y&sP|CgW0?(9~N`OmwZC0W1}xVeSwWj1%eDJdhE)>rk(&Q z|I2GZL_(S5pFLLd^B{U2cAOjz>|jYLF^GZ&yP37A+q3a9cJY=UR$v<*gUPd$Y1BY| zlx?d4g01L@3O;$-nET17nix1M(a1=4M5(c;L?tIF8=rv&+D1!a)Q zIf%@-yy}p$`jDiI3*2ACYd4iYtl$9vNkaet?U~rq*u~t+(cRVD^>A6dN2M5k0Y)DxpomfEB?R|Oprx5!Zl3v&7FtNQ5s0^5a{(VCXt^0Lkh)6$|vuw3~7 z+M{RbZY_5_mVKY;HSWAC-857W1wK?aTROtrX%BYFh84K-uv&4kfE!gDj^PM?ppN6FKf#iAw<=+V-L(ZJbq(}I1o^08;6KOoz8dY@je@^xe1YMRdkKWBIi)^1C-_Ry_d-+H3Q~9`NC%EW?v-etmE9w1mTh3(azSDf{ zUUQn8St9s-JoUgPtxM|YBWN2EkIe+8Mii$;oW^HLg{PpwhJS?(Z;j^0ge35s{3pL7 zgVrGW?`Nx5NCHy-oqvbs7A%SyDvJ7%c`^!r2R{fKH3(Zqy+Hky3Wvl$MQZq;#H3NV zrT-hvhD3uG_Xko2Kdj&;%0T)DqJfm0x$|Cu`;YQxG`craaG6$rl+_4iET9NnQ~xLc z6UV?PW>B0z3J~hdD9j-+?ekg_%S5^GC=#RoSra74j6s0zUjkY1Vb2rE|Nlf8{AK3O zL+7PP!|{_-H`$}_@#DtoN*Ghla%ACM(6HhE{?Ojb2fJ*d0|4vn|2ougbo%pYxz6bf zyKL~`b}ne~`LWGeovTIgtKc?j*xDw$u;byOMuvi8WrN{@JzC%Htuek5=OPkK_Pymg zlK+q>W7egx3C|#pWG?G*4$D>!3}_4L4qPe0383|hGIhCgyngTqYE_0V!EE?TNbcYC zyfF6mDBxqkZ%4-!>4Wc_rZcKWePqYWh(Rd+!GEJibHR6&Z;45>hP3`7eiEI&Iy2pE zVYh&S5%Gqacn~=Y)Kk5<;7ZIjfRJS*HW_K5HY(oDPsr<buS=1LJf8#nx~v-=WN?>j^k>AR={THGi-giT zeW&P7g#nE4pk9~db z5ImD&;tr2?lXpF5FO2_ z9RG@HJJX0Wt5O;mOkx7Mi#LhX#$IyGBf(D_MWH#gQQ)^EmxWGEN*d7-ZdnkaI^&Y# z$%4H+7MZAfQE_&$tPW6zKx;+sH?-8f1Z6f|Erz6+8Q;nvE#*kTPa&?~@7!J1tKa5= zos5!I3Hsj>r41{6sDOinpTb+h*yv_xa{P8ZUsrh#XmG2!1m}$88D_)p@^GJz!HP zt{mn(_Hh?k1;&FDSV*!WkZ29r`woWR8y^XZP|$XInD+I1y3>iG=DN2{9T9&S<~*P3 zzOJK*C-(c=c8+xi9UsO8PawW(!-9|rClSn*DYexxT+xb{A=~SXovTd1o{F*dy0j1b zZU=r3_s0=#VcGanJa94_=&N!-GVLg{5!%tp>B~?w{ZRFzX|!la2tU?`p=j=1hD78J1TnhmmXH_N`3SpT9U7PX5s~f!v+zSFNUJks=2WxzfSM}UV^m4 za<{Fwvf8y=Qy?ihTQuYSh=a~kobFxAb9XOH6R44swzoxF;)yW}s7uNo_Lm#itI^mH zV`Y_iIJ0tWph}8{RJdu0BsX_c&ggY`$2v^D35KOzJP}u;*s$e}xz6*|g|huJF+CWG zjBvyTx>i$)P^y;kaGEU_d24#7(@vA#pirRNKs~{Q$YijRZ0d-uh3#9im3S`maXUse z^pPt5i9+p;Ja&y(X1x$3^hj@Y#ix|It)mkv&GK_TK`g*(&v-~v+fnTZffM}KgDzco(M>IZ)ihh9o zbmCCgy(w2Z<3y($m;j!9c=6aYpnZkLGEx4s=LL>7)oR|r?W}g8mT{}-Ud8Phm#EAs zC)P;p+l8+XoB+jw*_LNVf;Q_v(*cvhF*{_T%>v!om-{88?CLJ5K`>^7(SlPRwr6TCoDG`Ns(-JmR+Cq zb8K=kfMdW;kBq;GM|u!YWZwJ^OM2+hz0;-R^@Yfu4s)?{n^CC)3^nM01VnN=;-9Ap zmDt5-I?vZX+FzMorpsMzj3%5?NUoFMrKk6i$4F9$vh(Bm9HcG(0JFj}1%|sGn^b)5)07yxlw1tsW;Z)6` z0LgGUp4k&G^enU?c0AxG{kA$HF+ZUDfWbSHE$|way=2vr9D7(?D)(KW&@|5Cb;DIh zSm!da7{A_Gt?ARt1%LaGK4-{Q9X{e$)1+gEF=pz%piIgwo9s`^-;R;Wm8!++wI>pJ z@)gsshGH{Ksea_@^yZI&lV@CbTr5nFUozU7@muk&dF376cW^9dAgz17$=5w{lz+1_ zEH__ZS6q!DNz`4CpI#mmv)oweHV1FP{ww`W?ImKE2D)u0sb76Wo-MwukREi(j_Z7~ zCs&UxU75|`ks(a|E5p>OX>6-8sx~E3Xkbe1ndfFs+b4%=HiGR_z=Ysc;ctuwU`GJ! zsSVG{WAsZEJbNV%hG83&d?ub>1}UIVC%tnHT7LXN9Bw}suun0%0}>}8(DX@bYy>Xz zg3EQo)65hz_8#2kfIFzLWqcL&jqZzKhMhB3R6X$*PSAr!_DCP7og6SO1ZmcO9WvjF zJX)4|9NKxs6FZKa2DNakW$|IALwq=|7{0P-A}Y@-^Ow`AurA1QwGk_mOm>-N@?7m* zox>vEIdO9q=AR#?s$z_|YPR=}^sV+3x(Qa&S*bpf=JgXTaI91syk&YCz9bvKJ`ZO& zyEP5ww*59%Iq~o`elF*nF0I%(KbQwW8y`&oZp`ajy1~V=lnXIEn%i&wQeeb_e^?mv zi6}FBt<~Ca*>aNC_6x~ia(%w`rU)(A^kzw1+&A&UNh zc=J-0&q;75Z+cMt^6a;szV^p~cLi^Vr(VL}IvW%gt)r&d*3Qp;W;Arblz5|gk}rr? z8n5qZ(;NQLt3&b*l^lSSYMXOTxBH$7hue3p{d7bb6MH9|%1^V)YlC2>Y{TttU*2Kn z&~P1_p+Gn~emY-{SMuy(Gd%}vZ{pXLBM}Dm1tKw0`!uk(~)l&?Q=9nmc}H$C6GL^@s@Axf;oUt@$8 z0D@9}VU2zX{=GC?kvkwFvXzPVm1MwCdBu%jlZOy&nRY^IXisTuETFcMM<;I3s!rRW z;Cn@3ke>3m##J?C)@T(u1}jX*aoeKx`CxTs7P`m3^(6ru$l3?&Zs*YE|XWK5?^%@R|Hirfa98N4?|sxQ+`Rpv{biiBaFnw%my z<)1x;9jk1Xt>1+ zTJy1Uq|yzj*>~?o#@bvrzT41*edlJUv;0hVw!?>{c_S)9BKn$D{LWvY#yCnskY2l< zoGrXN28ZQ>bUKonf0cAbM4>+M*g@sT)4N>k;ZM~hHQp!*43Gl>f`j`j(Dm)4^`+zCV9|-?aVVS-yBUH}z|3lLv z9@;U#xFb;K&jeZ~Ob{)B(7e>X?}2L0{p|J42qWcS=z{Xbm(-z0yV z^Z$?>{7v#dtoq+9e>?I2ut;M5Phb8w?r+ERAKV-^0Pt`B^f&15-Te<}mHhwhwTe6v S@}CLh=iB6YS1>64y!{spyG45d literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..cf8fb7c51af305b8422868f1cdaa914aa3601031 GIT binary patch literal 8837 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 KDyVN>M*jn^bq{C& literal 0 HcmV?d00001 diff --git a/resources/templates/naval/naval.miz b/resources/templates/naval/naval.miz new file mode 100644 index 0000000000000000000000000000000000000000..a23b2a8a319e76f019896293b7b1f11b6975c453 GIT binary patch literal 6923 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 WWjQG5zdN8nUq;ZGwfOw~_x}I|bU8Wz literal 0 HcmV?d00001 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, - "
      " + "".join(groups) + "
    ", - "
      " + "".join(options) + "
    ", - ] - ) - - 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, + "
      " + "".join(units) + "
    ", + ] ) + 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()