From cd391a360c30247bc0906cbb7b488698f86c0aac Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 18 May 2021 17:26:15 -0700 Subject: [PATCH] Add support for AAA objectives. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/999 --- changelog.md | 1 + game/theater/conflicttheater.py | 18 ++++++++++++++++++ game/theater/controlpoint.py | 3 +++ game/theater/start_generator.py | 15 +++++++++++++-- game/version.py | 9 ++++++++- gen/sam/aaa_bofors.py | 2 +- gen/sam/aaa_flak.py | 2 +- gen/sam/aaa_flak18.py | 2 +- gen/sam/aaa_ks19.py | 2 +- gen/sam/aaa_ww2_ally_flak.py | 2 +- gen/sam/aaa_zsu57.py | 2 +- gen/sam/aaa_zu23_insurgent.py | 2 +- gen/sam/airdefensegroupgenerator.py | 4 ++-- gen/sam/cold_war_flak.py | 5 ++--- gen/sam/sam_vulcan.py | 2 +- gen/sam/sam_zsu23.py | 2 +- gen/sam/sam_zu23.py | 2 +- gen/sam/sam_zu23_ural.py | 2 +- gen/sam/sam_zu23_ural_insurgent.py | 2 +- 19 files changed, 59 insertions(+), 20 deletions(-) diff --git a/changelog.md b/changelog.md index 15262e68..7dcb67e2 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,7 @@ Saves from 2.5 are not compatible with 3.0. * **[Modding]** Campaigns now choose locations for factories to spawn. * **[Modding]** Campaigns now use map structures as strike targets. * **[Modding]** Campaigns may now set *any* objective type to be a required spawn rather than random chance. +* **[Modding]** Campaigns may now place AAA objectives. * **[Modding]** Can now install custom factions to /Liberation/Factions instead of the Liberation install directory. * **[Performance Settings]** Added a settings to lower the number of smoke effects generated on frontlines. Lowered default settings for frontline smoke generators, so less smoke should be generated by default. * **[Configuration]** Liberation preferences (DCS install and save game location) are now saved to `%LOCALAPPDATA%/DCSLiberation` to prevent needing to reconfigure each new install. diff --git a/game/theater/conflicttheater.py b/game/theater/conflicttheater.py index 1b08980c..7e9fa0fe 100644 --- a/game/theater/conflicttheater.py +++ b/game/theater/conflicttheater.py @@ -115,6 +115,12 @@ class MizCampaignLoader: AirDefence.SAM_SA_9_Strela_1_Gaskin_TEL.id, } + REQUIRED_AAA_UNIT_TYPES = { + AirDefence.AAA_8_8cm_Flak_18.id, + AirDefence.SPAAA_Vulcan_M163.id, + AirDefence.SPAAA_ZSU_23_4_Shilka_Gun_Dish.id, + } + REQUIRED_EWR_UNIT_TYPE = AirDefence.EWR_1L13.id ARMOR_GROUP_UNIT_TYPE = Armor.MBT_M1A2_Abrams.id @@ -283,6 +289,12 @@ class MizCampaignLoader: if group.units[0].type in self.REQUIRED_SHORT_RANGE_SAM_UNIT_TYPES: yield group + @property + def required_aaa(self) -> Iterator[VehicleGroup]: + for group in itertools.chain(self.blue.vehicle_group, self.red.vehicle_group): + if group.units[0].type in self.REQUIRED_AAA_UNIT_TYPES: + yield group + @property def required_ewrs(self) -> Iterator[VehicleGroup]: for group in self.red.vehicle_group: @@ -516,6 +528,12 @@ class MizCampaignLoader: PointWithHeading.from_point(group.position, group.units[0].heading) ) + for group in self.required_aaa: + closest, distance = self.objective_info(group) + closest.preset_locations.required_aaa.append( + PointWithHeading.from_point(group.position, group.units[0].heading) + ) + for group in self.required_ewrs: closest, distance = self.objective_info(group) closest.preset_locations.required_ewrs.append( diff --git a/game/theater/controlpoint.py b/game/theater/controlpoint.py index dd90722b..03fe3ef9 100644 --- a/game/theater/controlpoint.py +++ b/game/theater/controlpoint.py @@ -135,6 +135,9 @@ class PresetLocations: #: Locations of short range SAMs which should always be spawned. required_short_range_sams: List[PointWithHeading] = field(default_factory=list) + #: Locations of AAA groups which should always be spawned. + required_aaa: List[PointWithHeading] = field(default_factory=list) + #: Locations of EWRs which should always be spawned. required_ewrs: List[PointWithHeading] = field(default_factory=list) diff --git a/game/theater/start_generator.py b/game/theater/start_generator.py index 2c02f83b..41eebbd1 100644 --- a/game/theater/start_generator.py +++ b/game/theater/start_generator.py @@ -407,7 +407,10 @@ class BaseDefenseGenerator: ) groups = generate_anti_air_group( - self.game, g, self.faction, ranges=[{AirDefenseRange.Short}] + self.game, + g, + self.faction, + ranges=[{AirDefenseRange.Short, AirDefenseRange.AAA}], ) if not groups: logging.error(f"Could not generate SHORAD group at {self.control_point}") @@ -540,6 +543,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator): {AirDefenseRange.Long}, {AirDefenseRange.Medium}, {AirDefenseRange.Short}, + {AirDefenseRange.AAA}, ], ) for position in presets.required_medium_range_sams: @@ -548,17 +552,24 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator): ranges=[ {AirDefenseRange.Medium}, {AirDefenseRange.Short}, + {AirDefenseRange.AAA}, ], ) for position in presets.required_short_range_sams: self.generate_aa_at( position, - ranges=[{AirDefenseRange.Short}], + ranges=[{AirDefenseRange.Short}, {AirDefenseRange.AAA}], + ) + for position in presets.required_aaa: + self.generate_aa_at( + position, + ranges=[{AirDefenseRange.AAA}], ) return ( len(presets.required_long_range_sams) + len(presets.required_medium_range_sams) + len(presets.required_short_range_sams) + + len(presets.required_aaa) ) def generate_required_ewr(self) -> int: diff --git a/game/version.py b/game/version.py index 12b06710..2a9cebbb 100644 --- a/game/version.py +++ b/game/version.py @@ -66,4 +66,11 @@ VERSION = _build_version_string() #: * Coastal defenses #: #: See the unit lists in MizCampaignLoader in conflicttheater.py for unit types. -CAMPAIGN_FORMAT_VERSION = (4, 1) +#: +#: Version 4.2 +#: * Adds support for AAA objectives. Place with any of the following units (either red +#: or blue): +#: * AAA_8_8cm_Flak_18, +#: * SPAAA_Vulcan_M163, +#: * SPAAA_ZSU_23_4_Shilka_Gun_Dish, +CAMPAIGN_FORMAT_VERSION = (4, 2) diff --git a/gen/sam/aaa_bofors.py b/gen/sam/aaa_bofors.py index 54e06f63..fc6636d9 100644 --- a/gen/sam/aaa_bofors.py +++ b/gen/sam/aaa_bofors.py @@ -36,4 +36,4 @@ class BoforsGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_flak.py b/gen/sam/aaa_flak.py index bec67196..25b9e274 100644 --- a/gen/sam/aaa_flak.py +++ b/gen/sam/aaa_flak.py @@ -98,4 +98,4 @@ class FlakGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_flak18.py b/gen/sam/aaa_flak18.py index 5dec254a..26b44f82 100644 --- a/gen/sam/aaa_flak18.py +++ b/gen/sam/aaa_flak18.py @@ -43,4 +43,4 @@ class Flak18Generator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_ks19.py b/gen/sam/aaa_ks19.py index c733b468..1e3de4ca 100644 --- a/gen/sam/aaa_ks19.py +++ b/gen/sam/aaa_ks19.py @@ -41,4 +41,4 @@ class KS19Generator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_ww2_ally_flak.py b/gen/sam/aaa_ww2_ally_flak.py index 3dd6b715..c9ace380 100644 --- a/gen/sam/aaa_ww2_ally_flak.py +++ b/gen/sam/aaa_ww2_ally_flak.py @@ -80,4 +80,4 @@ class AllyWW2FlakGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_zsu57.py b/gen/sam/aaa_zsu57.py index ad3c5eea..c87bf63d 100644 --- a/gen/sam/aaa_zsu57.py +++ b/gen/sam/aaa_zsu57.py @@ -30,4 +30,4 @@ class ZSU57Generator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/aaa_zu23_insurgent.py b/gen/sam/aaa_zu23_insurgent.py index 00e2f41f..87ef1cd9 100644 --- a/gen/sam/aaa_zu23_insurgent.py +++ b/gen/sam/aaa_zu23_insurgent.py @@ -36,4 +36,4 @@ class ZU23InsurgentGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/airdefensegroupgenerator.py b/gen/sam/airdefensegroupgenerator.py index 39d61e8f..3a25a2dd 100644 --- a/gen/sam/airdefensegroupgenerator.py +++ b/gen/sam/airdefensegroupgenerator.py @@ -1,4 +1,3 @@ -import logging from abc import ABC, abstractmethod from enum import Enum from typing import Iterator, List @@ -6,11 +5,12 @@ from typing import Iterator, List from dcs.unitgroup import VehicleGroup from game import Game -from gen.sam.group_generator import GroupGenerator from game.theater.theatergroundobject import SamGroundObject +from gen.sam.group_generator import GroupGenerator class AirDefenseRange(Enum): + AAA = "AAA" Short = "short" Medium = "medium" Long = "long" diff --git a/gen/sam/cold_war_flak.py b/gen/sam/cold_war_flak.py index 7b11f618..1ea3a724 100644 --- a/gen/sam/cold_war_flak.py +++ b/gen/sam/cold_war_flak.py @@ -6,7 +6,6 @@ from gen.sam.airdefensegroupgenerator import ( AirDefenseRange, AirDefenseGroupGenerator, ) -from gen.sam.group_generator import GroupGenerator class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator): @@ -80,7 +79,7 @@ class EarlyColdWarFlakGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA class ColdWarFlakGenerator(AirDefenseGroupGenerator): @@ -153,4 +152,4 @@ class ColdWarFlakGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/sam_vulcan.py b/gen/sam/sam_vulcan.py index 9ce2c04a..24998c4f 100644 --- a/gen/sam/sam_vulcan.py +++ b/gen/sam/sam_vulcan.py @@ -42,4 +42,4 @@ class VulcanGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/sam_zsu23.py b/gen/sam/sam_zsu23.py index 9caa1f01..5be3de8d 100644 --- a/gen/sam/sam_zsu23.py +++ b/gen/sam/sam_zsu23.py @@ -33,4 +33,4 @@ class ZSU23Generator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/sam_zu23.py b/gen/sam/sam_zu23.py index 0cd169a1..9cb43ab2 100644 --- a/gen/sam/sam_zu23.py +++ b/gen/sam/sam_zu23.py @@ -36,4 +36,4 @@ class ZU23Generator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/sam_zu23_ural.py b/gen/sam/sam_zu23_ural.py index 50e57a84..af5f85db 100644 --- a/gen/sam/sam_zu23_ural.py +++ b/gen/sam/sam_zu23_ural.py @@ -33,4 +33,4 @@ class ZU23UralGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA diff --git a/gen/sam/sam_zu23_ural_insurgent.py b/gen/sam/sam_zu23_ural_insurgent.py index 6c6f09ff..91ca4a66 100644 --- a/gen/sam/sam_zu23_ural_insurgent.py +++ b/gen/sam/sam_zu23_ural_insurgent.py @@ -33,4 +33,4 @@ class ZU23UralInsurgentGenerator(AirDefenseGroupGenerator): @classmethod def range(cls) -> AirDefenseRange: - return AirDefenseRange.Short + return AirDefenseRange.AAA