dcs_liberation/gen/sam/sam_group_generator.py
Dan Albert 0e807d84c2 Differentiate required long and medium range SAMs.
To improve IADS design in campaigns, this differentiates required long
and medium range SAMs. SAMs that must be long range SAMs are defined by
SA-10 or Patriot launchers, while medium range SAMs are defined by SA-2,
SA-3, or Hawk launchers.

Long range SAMs positions will only be populated by long range SAMs
(Patriots and SA-10s), and not all factions have those available. Medium
range SAMs currently comprise all air defenses that are not long range
SAMs, so if the faction includes flak guns in their `sams` property then
flak guns may be spawned at medium range SAM locations.

Base defenses and random SAM locations continue to use either type of
SAM.
2020-11-26 19:48:14 -08:00

219 lines
8.0 KiB
Python

import random
from typing import List, Optional, Type
from dcs.unitgroup import VehicleGroup
from dcs.vehicles import AirDefence
from game import Game, db
from game.factions.faction import Faction
from game.theater import TheaterGroundObject
from game.theater.theatergroundobject import SamGroundObject
from gen.sam.aaa_bofors import BoforsGenerator
from gen.sam.aaa_flak import FlakGenerator
from gen.sam.aaa_flak18 import Flak18Generator
from gen.sam.aaa_ww2_ally_flak import AllyWW2FlakGenerator
from gen.sam.aaa_zu23_insurgent import ZU23InsurgentGenerator
from gen.sam.cold_war_flak import (
ColdWarFlakGenerator,
EarlyColdWarFlakGenerator,
)
from gen.sam.ewrs import (
BigBirdGenerator,
BoxSpringGenerator,
DogEarGenerator,
FlatFaceGenerator,
HawkEwrGenerator,
PatriotEwrGenerator,
RolandEwrGenerator,
SnowDriftGenerator,
StraightFlushGenerator,
TallRackGenerator,
)
from gen.sam.freya_ewr import FreyaGenerator
from gen.sam.group_generator import GroupGenerator
from gen.sam.sam_avenger import AvengerGenerator
from gen.sam.sam_chaparral import ChaparralGenerator
from gen.sam.sam_gepard import GepardGenerator
from gen.sam.sam_hawk import HawkGenerator
from gen.sam.sam_hq7 import HQ7Generator
from gen.sam.sam_linebacker import LinebackerGenerator
from gen.sam.sam_patriot import PatriotGenerator
from gen.sam.sam_rapier import RapierGenerator
from gen.sam.sam_roland import RolandGenerator
from gen.sam.sam_sa10 import SA10Generator
from gen.sam.sam_sa11 import SA11Generator
from gen.sam.sam_sa13 import SA13Generator
from gen.sam.sam_sa15 import SA15Generator
from gen.sam.sam_sa19 import SA19Generator
from gen.sam.sam_sa2 import SA2Generator
from gen.sam.sam_sa3 import SA3Generator
from gen.sam.sam_sa6 import SA6Generator
from gen.sam.sam_sa8 import SA8Generator
from gen.sam.sam_sa9 import SA9Generator
from gen.sam.sam_vulcan import VulcanGenerator
from gen.sam.sam_zsu23 import ZSU23Generator
from gen.sam.sam_zu23 import ZU23Generator
from gen.sam.sam_zu23_ural import ZU23UralGenerator
from gen.sam.sam_zu23_ural_insurgent import ZU23UralInsurgentGenerator
SAM_MAP = {
"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,
"SA6Generator": SA6Generator,
"SA8Generator": SA8Generator,
"SA9Generator": SA9Generator,
"SA10Generator": SA10Generator,
"SA11Generator": SA11Generator,
"SA13Generator": SA13Generator,
"SA15Generator": SA15Generator,
"SA19Generator": SA19Generator,
"HQ7Generator": HQ7Generator,
"Flak18Generator": Flak18Generator,
"ColdWarFlakGenerator": ColdWarFlakGenerator,
"EarlyColdWarFlakGenerator": EarlyColdWarFlakGenerator,
"FreyaGenerator": FreyaGenerator,
"AllyWW2FlakGenerator": AllyWW2FlakGenerator
}
#: Used to fill the long-range required SAM locations in the campaign.
LONG_RANGE_SAMS = {
"SA10Generator",
"PatriotGenerator",
}
#: Used to fill the medium-range required SAM location in the campaign.
MEDIUM_RANGE_SAMS = SAM_MAP.keys() - LONG_RANGE_SAMS
SAM_PRICES = {
AirDefence.SAM_Hawk_PCP: 35,
AirDefence.AAA_ZU_23_Emplacement: 10,
AirDefence.AAA_ZU_23_Closed: 10,
AirDefence.AAA_ZU_23_on_Ural_375: 10,
AirDefence.AAA_ZU_23_Insurgent_on_Ural_375: 10,
AirDefence.AAA_ZU_23_Insurgent_Closed: 10,
AirDefence.AAA_ZU_23_Insurgent: 10,
AirDefence.SPAAA_ZSU_23_4_Shilka: 10,
AirDefence.AAA_Vulcan_M163: 15,
AirDefence.SAM_Linebacker_M6: 20,
AirDefence.Rapier_FSA_Launcher: 20,
AirDefence.SAM_Avenger_M1097: 22,
AirDefence.SPAAA_Gepard: 24,
AirDefence.SAM_Roland_ADS: 40,
AirDefence.SAM_Patriot_LN_M901: 85,
AirDefence.SAM_Patriot_EPP_III: 85,
AirDefence.SAM_Chaparral_M48: 25,
AirDefence.AAA_Bofors_40mm: 15,
AirDefence.AAA_8_8cm_Flak_36: 15,
AirDefence.SAM_SA_2_LN_SM_90: 30,
AirDefence.SAM_SA_3_S_125_LN_5P73: 35,
AirDefence.SAM_SA_6_Kub_LN_2P25: 45,
AirDefence.SAM_SA_8_Osa_9A33: 30,
AirDefence.SAM_SA_9_Strela_1_9P31: 25,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 80,
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 80,
AirDefence.SAM_SA_11_Buk_LN_9A310M1: 60,
AirDefence.SAM_SA_13_Strela_10M3_9A35M3: 30,
AirDefence.SAM_SA_15_Tor_9A331: 40,
AirDefence.SAM_SA_19_Tunguska_2S6: 35,
AirDefence.HQ_7_Self_Propelled_LN: 35
}
EWR_MAP = {
"BoxSpringGenerator": BoxSpringGenerator,
"TallRackGenerator": TallRackGenerator,
"DogEarGenerator": DogEarGenerator,
"RolandEwrGenerator": RolandEwrGenerator,
"FlatFaceGenerator": FlatFaceGenerator,
"PatriotEwrGenerator": PatriotEwrGenerator,
"BigBirdGenerator": BigBirdGenerator,
"SnowDriftGenerator": SnowDriftGenerator,
"StraightFlushGenerator": StraightFlushGenerator,
"HawkEwrGenerator": HawkEwrGenerator,
}
def get_faction_possible_sams_generator(
faction: Faction,
filter_names: Optional[List[str]] = None) -> List[Type[GroupGenerator]]:
"""
Return the list of possible SAM generator for the given faction
:param faction: Faction name to search units for
:param filter_names: Optional list of names to filter allowed SAMs by.
"""
return [SAM_MAP[s] for s in faction.sams if
filter_names is None or s in filter_names]
def get_faction_possible_ewrs_generator(faction: Faction) -> List[Type[GroupGenerator]]:
"""
Return the list of possible SAM generator for the given faction
:param faction: Faction name to search units for
"""
return [EWR_MAP[s] for s in faction.ewrs]
def generate_anti_air_group(
game: Game, ground_object: TheaterGroundObject, faction: Faction,
filter_names: Optional[List[str]] = None) -> Optional[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 filter_names: Optional list of names to filter allowed SAMs by.
:return: The generated group, or None if one could not be generated.
"""
generators = get_faction_possible_sams_generator(faction, filter_names)
if len(generators) > 0:
sam_generator_class = random.choice(generators)
generator = sam_generator_class(game, ground_object)
generator.generate()
return generator.get_generated_group()
return None
def generate_ewr_group(game: Game, ground_object: TheaterGroundObject,
faction: Faction) -> Optional[VehicleGroup]:
"""Generates an early warning radar group.
:param game: The Game.
:param ground_object: The ground object which will own the EWR group.
:param faction: Owner faction.
:return: The generated group, or None if one could not be generated.
"""
generators = get_faction_possible_ewrs_generator(faction)
if len(generators) > 0:
generator_class = random.choice(generators)
generator = generator_class(game, ground_object)
generator.generate()
return generator.get_generated_group()
return None
def generate_shorad_group(game: Game, ground_object: SamGroundObject,
faction: Faction) -> Optional[VehicleGroup]:
if len(faction.shorads) > 0:
sam = random.choice(faction.shorads)
generator = SAM_MAP[sam](game, ground_object)
generator.generate()
return generator.get_generated_group()
else:
return generate_anti_air_group(game, ground_object, faction)