diff --git a/changelog.md b/changelog.md index 6ed5616c..4864dfd3 100644 --- a/changelog.md +++ b/changelog.md @@ -12,8 +12,9 @@ Saves from 4.0.0 are compatible with 4.1.0. ## Features/Improvements -* **[Plugins]** Increased time JTAC Autolase messages stay visible on the UI. +* **[Campaign]** Air defense sites now generate a fixed number of launchers per type. * **[Mission Generation]** Improvements for better support of the Skynet Plugin and long range SAMs are now acting as EWR +* **[Plugins]** Increased time JTAC Autolase messages stay visible on the UI. * **[UI]** Added ability to take notes and have those notes appear as a kneeboard page. * **[UI]** Hovering over the weather information now dispalys the cloud base (meters and feet). * **[UI]** Google search link added to unit information when there is no information provided. diff --git a/gen/sam/aaa_bofors.py b/gen/sam/aaa_bofors.py index 8c76f7f4..283c1d59 100644 --- a/gen/sam/aaa_bofors.py +++ b/gen/sam/aaa_bofors.py @@ -17,22 +17,19 @@ class BoforsGenerator(AirDefenseGroupGenerator): price = 75 def generate(self): - grid_x = random.randint(2, 3) - grid_y = random.randint(2, 3) - - spacing = random.randint(10, 40) index = 0 - for i in range(grid_x): - for j in range(grid_y): - index = index + 1 - self.add_unit( - AirDefence.Bofors40, - "AAA#" + str(index), - self.position.x + spacing * i, - self.position.y + spacing * j, - self.heading, - ) + 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: diff --git a/gen/sam/aaa_flak.py b/gen/sam/aaa_flak.py index f918e48a..141e5b7d 100644 --- a/gen/sam/aaa_flak.py +++ b/gen/sam/aaa_flak.py @@ -26,28 +26,24 @@ class FlakGenerator(AirDefenseGroupGenerator): price = 135 def generate(self): - grid_x = random.randint(2, 3) - grid_y = random.randint(2, 3) - - spacing = random.randint(20, 35) - index = 0 mixed = random.choice([True, False]) unit_type = random.choice(GFLAK) - for i in range(grid_x): - for j in range(grid_y): - index = index + 1 - self.add_unit( - unit_type, - "AAA#" + str(index), - self.position.x + spacing * i + random.randint(1, 5), - self.position.y + spacing * j + random.randint(1, 5), - self.heading, - ) + 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) + if mixed: + unit_type = random.choice(GFLAK) # Search lights search_pos = self.get_circular_position(random.randint(2, 3), 80) @@ -86,8 +82,8 @@ class FlakGenerator(AirDefenseGroupGenerator): ) # Some Opel Blitz trucks - for i in range(int(max(1, grid_x / 2))): - for j in range(int(max(1, grid_x / 2))): + for i in range(int(max(1, 2))): + for j in range(int(max(1, 2))): self.add_unit( Unarmed.Blitz_36_6700A, "BLITZ#" + str(index), diff --git a/gen/sam/aaa_ks19.py b/gen/sam/aaa_ks19.py index 1e3de4ca..bb51e92a 100644 --- a/gen/sam/aaa_ks19.py +++ b/gen/sam/aaa_ks19.py @@ -16,9 +16,6 @@ class KS19Generator(AirDefenseGroupGenerator): price = 98 def generate(self): - - spacing = random.randint(10, 40) - self.add_unit( highdigitsams.AAA_SON_9_Fire_Can, "TR", @@ -28,16 +25,17 @@ class KS19Generator(AirDefenseGroupGenerator): ) index = 0 - for i in range(3): - for j in range(3): - index = index + 1 - self.add_unit( - highdigitsams.AAA_100mm_KS_19, - "AAA#" + str(index), - self.position.x + spacing * i, - self.position.y + spacing * j, - self.heading, - ) + 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: diff --git a/gen/sam/aaa_zsu57.py b/gen/sam/aaa_zsu57.py index 4648e90b..422693d5 100644 --- a/gen/sam/aaa_zsu57.py +++ b/gen/sam/aaa_zsu57.py @@ -15,7 +15,7 @@ class ZSU57Generator(AirDefenseGroupGenerator): price = 60 def generate(self): - num_launchers = 5 + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=110, coverage=360 ) diff --git a/gen/sam/aaa_zu23_insurgent.py b/gen/sam/aaa_zu23_insurgent.py index 5ca97638..49113668 100644 --- a/gen/sam/aaa_zu23_insurgent.py +++ b/gen/sam/aaa_zu23_insurgent.py @@ -17,22 +17,18 @@ class ZU23InsurgentGenerator(AirDefenseGroupGenerator): price = 56 def generate(self): - grid_x = random.randint(2, 3) - grid_y = random.randint(2, 3) - - spacing = random.randint(10, 40) - index = 0 - for i in range(grid_x): - for j in range(grid_y): - index = index + 1 - self.add_unit( - AirDefence.ZU_23_Closed_Insurgent, - "AAA#" + str(index), - self.position.x + spacing * i, - self.position.y + spacing * j, - self.heading, - ) + 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: diff --git a/gen/sam/sam_avenger.py b/gen/sam/sam_avenger.py index b778cc62..b3f63354 100644 --- a/gen/sam/sam_avenger.py +++ b/gen/sam/sam_avenger.py @@ -17,7 +17,7 @@ class AvengerGenerator(AirDefenseGroupGenerator): price = 62 def generate(self): - num_launchers = random.randint(2, 3) + num_launchers = 2 self.add_unit( Unarmed.M_818, diff --git a/gen/sam/sam_chaparral.py b/gen/sam/sam_chaparral.py index 465ba0bd..ea239746 100644 --- a/gen/sam/sam_chaparral.py +++ b/gen/sam/sam_chaparral.py @@ -17,7 +17,7 @@ class ChaparralGenerator(AirDefenseGroupGenerator): price = 66 def generate(self): - num_launchers = random.randint(2, 4) + num_launchers = 2 self.add_unit( Unarmed.M_818, diff --git a/gen/sam/sam_gepard.py b/gen/sam/sam_gepard.py index 669781df..6128efab 100644 --- a/gen/sam/sam_gepard.py +++ b/gen/sam/sam_gepard.py @@ -17,20 +17,18 @@ class GepardGenerator(AirDefenseGroupGenerator): price = 50 def generate(self): - self.add_unit( - AirDefence.Gepard, - "SPAAA", - self.position.x, - self.position.y, - self.heading, + num_launchers = 2 + + positions = self.get_circular_position( + num_launchers, launcher_distance=120, coverage=180 ) - if random.randint(0, 1) == 1: + for i, position in enumerate(positions): self.add_unit( AirDefence.Gepard, - "SPAAA2", - self.position.x, - self.position.y, - self.heading, + "SPAA#" + str(i), + position[0], + position[1], + position[2], ) self.add_unit( Unarmed.M_818, diff --git a/gen/sam/sam_hawk.py b/gen/sam/sam_hawk.py index ea05f726..efec60a2 100644 --- a/gen/sam/sam_hawk.py +++ b/gen/sam/sam_hawk.py @@ -51,7 +51,7 @@ class HawkGenerator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(3, 6) + num_launchers = 6 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=180 ) diff --git a/gen/sam/sam_hq7.py b/gen/sam/sam_hq7.py index be5eeb6a..0143fc63 100644 --- a/gen/sam/sam_hq7.py +++ b/gen/sam/sam_hq7.py @@ -26,13 +26,6 @@ class HQ7Generator(AirDefenseGroupGenerator): self.position.y, self.heading, ) - self.add_unit( - AirDefence.HQ_7_LN_SP, - "LN", - self.position.x + 20, - self.position.y, - self.heading, - ) # Triple A for close range defense aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior) @@ -51,7 +44,7 @@ class HQ7Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(0, 3) + num_launchers = 2 if num_launchers > 0: positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=360 diff --git a/gen/sam/sam_linebacker.py b/gen/sam/sam_linebacker.py index b140b138..09c57117 100644 --- a/gen/sam/sam_linebacker.py +++ b/gen/sam/sam_linebacker.py @@ -17,7 +17,7 @@ class LinebackerGenerator(AirDefenseGroupGenerator): price = 75 def generate(self): - num_launchers = random.randint(2, 4) + num_launchers = 2 self.add_unit( Unarmed.M_818, diff --git a/gen/sam/sam_patriot.py b/gen/sam/sam_patriot.py index aafeb79c..fcd82417 100644 --- a/gen/sam/sam_patriot.py +++ b/gen/sam/sam_patriot.py @@ -1,5 +1,3 @@ -import random - from dcs.mapping import Point from dcs.vehicles import AirDefence @@ -56,10 +54,7 @@ class PatriotGenerator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(3, 4) - positions = self.get_circular_position( - num_launchers, launcher_distance=120, coverage=360 - ) + positions = self.get_circular_position(8, launcher_distance=120, coverage=360) for i, position in enumerate(positions): self.add_unit( AirDefence.Patriot_ln, @@ -71,10 +66,7 @@ class PatriotGenerator(AirDefenseGroupGenerator): # Short range protection for high value site aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior) - num_launchers = random.randint(3, 4) - positions = self.get_circular_position( - num_launchers, launcher_distance=200, coverage=360 - ) + 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, @@ -83,6 +75,15 @@ class PatriotGenerator(AirDefenseGroupGenerator): 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: diff --git a/gen/sam/sam_rapier.py b/gen/sam/sam_rapier.py index af3965e4..538dd7c4 100644 --- a/gen/sam/sam_rapier.py +++ b/gen/sam/sam_rapier.py @@ -33,7 +33,7 @@ class RapierGenerator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(3, 6) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=80, coverage=240 ) diff --git a/gen/sam/sam_roland.py b/gen/sam/sam_roland.py index e2e704af..64ee154d 100644 --- a/gen/sam/sam_roland.py +++ b/gen/sam/sam_roland.py @@ -16,6 +16,7 @@ class RolandGenerator(AirDefenseGroupGenerator): price = 40 def generate(self): + num_launchers = 2 self.add_unit( AirDefence.Roland_Radar, "EWR", @@ -23,13 +24,18 @@ class RolandGenerator(AirDefenseGroupGenerator): self.position.y, self.heading, ) - self.add_unit( - AirDefence.Roland_ADS, - "ADS", - self.position.x, - 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", diff --git a/gen/sam/sam_sa10.py b/gen/sam/sam_sa10.py index 35611e83..8d4d4e2c 100644 --- a/gen/sam/sam_sa10.py +++ b/gen/sam/sam_sa10.py @@ -1,5 +1,3 @@ -import random - from dcs.mapping import Point from dcs.vehicles import AirDefence @@ -45,17 +43,13 @@ class SA10Generator(AirDefenseGroupGenerator): # Command Post self.add_unit(self.cp, "CP", self.position.x, self.position.y, self.heading) - # 2 Tracking radars + # 1 Tracking radar self.add_unit( self.tr1, "TR1", self.position.x - 40, self.position.y - 40, self.heading ) - self.add_unit( - self.tr2, "TR2", self.position.x + 40, self.position.y - 40, self.heading - ) - # 2 different launcher type (C & D) - num_launchers = random.randint(6, 8) + num_launchers = 6 positions = self.get_circular_position( num_launchers, launcher_distance=100, coverage=360 ) @@ -78,7 +72,7 @@ class SA10Generator(AirDefenseGroupGenerator): def generate_defensive_groups(self) -> None: # AAA for defending against close targets. aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior) - num_launchers = random.randint(6, 8) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=210, coverage=360 ) @@ -103,7 +97,7 @@ class Tier2SA10Generator(SA10Generator): # SA-15 for both shorter range targets and point defense. pd_group = self.add_auxiliary_group(SkynetRole.PointDefense) - num_launchers = random.randint(2, 4) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=140, coverage=360 ) @@ -125,7 +119,7 @@ class Tier3SA10Generator(SA10Generator): def generate_defensive_groups(self) -> None: # AAA for defending against close targets. aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior) - num_launchers = random.randint(6, 8) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=210, coverage=360 ) @@ -140,7 +134,7 @@ class Tier3SA10Generator(SA10Generator): # SA-15 for both shorter range targets and point defense. pd_group = self.add_auxiliary_group(SkynetRole.PointDefense) - num_launchers = random.randint(2, 4) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=140, coverage=360 ) diff --git a/gen/sam/sam_sa11.py b/gen/sam/sam_sa11.py index 7fec37c2..3611aff5 100644 --- a/gen/sam/sam_sa11.py +++ b/gen/sam/sam_sa11.py @@ -32,7 +32,7 @@ class SA11Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(2, 4) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=140, coverage=180 ) diff --git a/gen/sam/sam_sa13.py b/gen/sam/sam_sa13.py index 0fbe1af0..24cd75a0 100644 --- a/gen/sam/sam_sa13.py +++ b/gen/sam/sam_sa13.py @@ -32,7 +32,7 @@ class SA13Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(2, 3) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=360 ) diff --git a/gen/sam/sam_sa15.py b/gen/sam/sam_sa15.py index 3dcb881a..d5d74b9c 100644 --- a/gen/sam/sam_sa15.py +++ b/gen/sam/sam_sa15.py @@ -15,13 +15,18 @@ class SA15Generator(AirDefenseGroupGenerator): price = 55 def generate(self): - self.add_unit( - AirDefence.Tor_9A331, - "ADS", - self.position.x, - 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.Tor_9A331, + "ADS#" + str(i), + position[0], + position[1], + position[2], + ) self.add_unit( Unarmed.UAZ_469, "EWR", diff --git a/gen/sam/sam_sa19.py b/gen/sam/sam_sa19.py index caac1f7c..0ff23158 100644 --- a/gen/sam/sam_sa19.py +++ b/gen/sam/sam_sa19.py @@ -17,7 +17,7 @@ class SA19Generator(AirDefenseGroupGenerator): price = 90 def generate(self): - num_launchers = random.randint(1, 3) + num_launchers = 2 if num_launchers == 1: self.add_unit( diff --git a/gen/sam/sam_sa2.py b/gen/sam/sam_sa2.py index 4b7341df..3cfae81e 100644 --- a/gen/sam/sam_sa2.py +++ b/gen/sam/sam_sa2.py @@ -32,7 +32,7 @@ class SA2Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(3, 6) + num_launchers = 6 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=180 ) diff --git a/gen/sam/sam_sa3.py b/gen/sam/sam_sa3.py index 1a95de12..400bda82 100644 --- a/gen/sam/sam_sa3.py +++ b/gen/sam/sam_sa3.py @@ -32,7 +32,7 @@ class SA3Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(3, 6) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=180 ) diff --git a/gen/sam/sam_sa6.py b/gen/sam/sam_sa6.py index fa72b24a..6706f250 100644 --- a/gen/sam/sam_sa6.py +++ b/gen/sam/sam_sa6.py @@ -25,7 +25,7 @@ class SA6Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(2, 4) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=360 ) diff --git a/gen/sam/sam_sa8.py b/gen/sam/sam_sa8.py index 3ab28dfc..7f3f72b3 100644 --- a/gen/sam/sam_sa8.py +++ b/gen/sam/sam_sa8.py @@ -15,13 +15,19 @@ class SA8Generator(AirDefenseGroupGenerator): price = 55 def generate(self): - self.add_unit( - AirDefence.Osa_9A33_ln, - "OSA", - self.position.x, - self.position.y, - self.heading, + 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", diff --git a/gen/sam/sam_sa9.py b/gen/sam/sam_sa9.py index fccc7973..ed7883b5 100644 --- a/gen/sam/sam_sa9.py +++ b/gen/sam/sam_sa9.py @@ -32,7 +32,7 @@ class SA9Generator(AirDefenseGroupGenerator): self.heading, ) - num_launchers = random.randint(2, 3) + num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=360 ) diff --git a/gen/sam/sam_vulcan.py b/gen/sam/sam_vulcan.py index 2d057dc0..0c869afc 100644 --- a/gen/sam/sam_vulcan.py +++ b/gen/sam/sam_vulcan.py @@ -17,20 +17,18 @@ class VulcanGenerator(AirDefenseGroupGenerator): price = 25 def generate(self): - self.add_unit( - AirDefence.Vulcan, - "SPAAA", - self.position.x, - self.position.y, - self.heading, + num_launchers = 2 + + positions = self.get_circular_position( + num_launchers, launcher_distance=120, coverage=180 ) - if random.randint(0, 1) == 1: + for i, position in enumerate(positions): self.add_unit( AirDefence.Vulcan, - "SPAAA2", - self.position.x, - self.position.y, - self.heading, + "SPAA#" + str(i), + position[0], + position[1], + position[2], ) self.add_unit( Unarmed.M_818, diff --git a/gen/sam/sam_zsu23.py b/gen/sam/sam_zsu23.py index 708ae5c6..0e638b62 100644 --- a/gen/sam/sam_zsu23.py +++ b/gen/sam/sam_zsu23.py @@ -1,6 +1,6 @@ import random -from dcs.vehicles import AirDefence +from dcs.vehicles import AirDefence, Unarmed from gen.sam.airdefensegroupgenerator import ( AirDefenseRange, @@ -17,7 +17,7 @@ class ZSU23Generator(AirDefenseGroupGenerator): price = 50 def generate(self): - num_launchers = random.randint(4, 5) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=120, coverage=180 @@ -30,6 +30,13 @@ class ZSU23Generator(AirDefenseGroupGenerator): 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: diff --git a/gen/sam/sam_zu23.py b/gen/sam/sam_zu23.py index 6a1b41cb..58c55ad5 100644 --- a/gen/sam/sam_zu23.py +++ b/gen/sam/sam_zu23.py @@ -1,6 +1,6 @@ import random -from dcs.vehicles import AirDefence +from dcs.vehicles import AirDefence, Unarmed from gen.sam.airdefensegroupgenerator import ( AirDefenseRange, @@ -17,22 +17,25 @@ class ZU23Generator(AirDefenseGroupGenerator): price = 54 def generate(self): - grid_x = random.randint(2, 3) - grid_y = random.randint(2, 3) - - spacing = random.randint(10, 40) - index = 0 - for i in range(grid_x): - for j in range(grid_y): - index = index + 1 - self.add_unit( - AirDefence.ZU_23_Emplacement_Closed, - "AAA#" + str(index), - self.position.x + spacing * i, - self.position.y + spacing * j, - self.heading, - ) + 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: diff --git a/gen/sam/sam_zu23_ural.py b/gen/sam/sam_zu23_ural.py index 4f97d6f3..47b7ac6a 100644 --- a/gen/sam/sam_zu23_ural.py +++ b/gen/sam/sam_zu23_ural.py @@ -17,7 +17,7 @@ class ZU23UralGenerator(AirDefenseGroupGenerator): price = 64 def generate(self): - num_launchers = random.randint(2, 8) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=80, coverage=360 diff --git a/gen/sam/sam_zu23_ural_insurgent.py b/gen/sam/sam_zu23_ural_insurgent.py index d0ab8405..0e277599 100644 --- a/gen/sam/sam_zu23_ural_insurgent.py +++ b/gen/sam/sam_zu23_ural_insurgent.py @@ -17,7 +17,7 @@ class ZU23UralInsurgentGenerator(AirDefenseGroupGenerator): price = 64 def generate(self): - num_launchers = random.randint(2, 8) + num_launchers = 4 positions = self.get_circular_position( num_launchers, launcher_distance=80, coverage=360