Merge remote-tracking branch 'khopa/develop' into develop

This commit is contained in:
Khopa 2021-04-17 02:22:56 +02:00
commit a30d9276b8
11 changed files with 155 additions and 69 deletions

View File

@ -4,23 +4,21 @@ Saves from 2.4 are not compatible with 2.5.
## Features/Improvements
* **[Flight Planner]** (WIP) Added AEW&C missions. (by siKruger)
* **[Flight Planner]** Added AEW&C missions. (by siKruger)
* **[Kneeboard]** Added dark kneeboard option (by GvonH)
* **[Campaigns]** Multiple EWR sites may now be generated, and EWR sites may be generated outside bases (by SnappyComebacks)
## Fixes
* **[Flight Planner]** Front lines now project threat zones, so TARCAP/escorts will not be pruned for flights near the front. Packages may also route around the front line when practical.
* **[Flight Planner]** Fixed error when planning BAI at SAMs with dead subgroups.
* **[Flight Planner]** Mig-19 was not allowed for CAS roles fixed
* **[Flight Planner]** Increased size of navigation planning area to avoid plannign failures with distant waypoints.
* **[Objective names]** Fixed typos in objective name : ARMADILLLO -> ARMADILLO (by SnappyComebacks)
* **[Payloads]** F-86 Sabre was missing a custom payload
* **[Payloads]** Added GAR-8 period restrictions (by Mustang-25)
* **[Campaign]** Date now progresses.
# 2.4.4
## Fixes
* **[Campaign]** Added game over message when a coalition runs out of functioning airbases.
* **[Mission Generation]** Fixed "invalid face handle" error in kneeboard generation that occurred on some machines.
# 2.4.3

View File

@ -118,6 +118,8 @@ class MizCampaignLoader:
AirDefence.SAM_SA_3_S_125_Goa_LN.id,
}
REQUIRED_EWR_UNIT_TYPE = AirDefence.EWR_1L13.id
BASE_DEFENSE_RADIUS = nautical_miles(2)
def __init__(self, miz: Path, theater: ConflictTheater) -> None:
@ -247,6 +249,12 @@ class MizCampaignLoader:
if group.units[0].type in self.REQUIRED_MEDIUM_RANGE_SAM_UNIT_TYPES:
yield group
@property
def required_ewrs(self) -> Iterator[VehicleGroup]:
for group in self.red.vehicle_group:
if group.units[0].type in self.REQUIRED_EWR_UNIT_TYPE:
yield group
@property
def helipads(self) -> Iterator[StaticGroup]:
for group in self.blue.static_group:
@ -356,6 +364,11 @@ class MizCampaignLoader:
for group in self.ewrs:
closest, distance = self.objective_info(group)
if distance < self.BASE_DEFENSE_RADIUS:
closest.preset_locations.ewrs.append(
PointWithHeading.from_point(group.position, group.units[0].heading)
)
else:
closest.preset_locations.ewrs.append(
PointWithHeading.from_point(group.position, group.units[0].heading)
)
@ -396,6 +409,12 @@ class MizCampaignLoader:
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(
PointWithHeading.from_point(group.position, group.units[0].heading)
)
for group in self.helipads:
closest, distance = self.objective_info(group)
closest.helipads.append(

View File

@ -107,6 +107,9 @@ class PresetLocations:
#: Locations of medium range SAMs which should always be spawned.
required_medium_range_sams: List[PointWithHeading] = field(default_factory=list)
#: Locations of EWRs which should always be spawned.
required_ewrs: List[PointWithHeading] = field(default_factory=list)
@staticmethod
def _random_from(points: List[PointWithHeading]) -> Optional[PointWithHeading]:
"""Finds, removes, and returns a random position from the given list."""

View File

@ -37,10 +37,8 @@ from gen.fleet.ship_group_generator import (
from gen.locations.preset_location_finder import MizDataLocationFinder
from gen.missiles.missiles_group_generator import generate_missile_group
from gen.sam.airdefensegroupgenerator import AirDefenseRange
from gen.sam.sam_group_generator import (
generate_anti_air_group,
generate_ewr_group,
)
from gen.sam.sam_group_generator import generate_anti_air_group
from gen.sam.ewr_group_generator import generate_ewr_group
from . import (
ConflictTheater,
ControlPoint,
@ -464,7 +462,11 @@ class BaseDefenseGenerator:
group_id = self.game.next_group_id()
g = EwrGroundObject(
namegen.random_objective_name(), group_id, position, self.control_point
namegen.random_objective_name(),
group_id,
position,
self.control_point,
True,
)
group = generate_ewr_group(self.game, g, self.faction)
@ -609,6 +611,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
def generate_ground_points(self) -> None:
"""Generate ground objects and AA sites for the control point."""
skip_sams = self.generate_required_aa()
skip_ewrs = self.generate_required_ewr()
if self.control_point.is_global:
return
@ -625,6 +628,12 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
skip_sams -= 1
else:
self.generate_aa_site()
# 1 in 4 additional objectives are EWR.
elif random.randint(0, 3) == 0:
if skip_ewrs > 0:
skip_ewrs -= 1
else:
self.generate_ewr_site()
else:
self.generate_ground_point()
@ -656,6 +665,17 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
presets.required_medium_range_sams
)
def generate_required_ewr(self) -> int:
"""Generates the EWR sites that are required by the campaign.
Returns:
The number of EWR sites that were generated.
"""
presets = self.control_point.preset_locations
for position in presets.required_ewrs:
self.generate_ewr_at(position)
return len(presets.required_ewrs)
def generate_ground_point(self) -> None:
try:
category = random.choice(self.faction.building_set)
@ -733,6 +753,33 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
g.groups = groups
self.control_point.connected_objectives.append(g)
def generate_ewr_site(self) -> None:
position = self.location_finder.location_for(LocationType.Ewr)
if position is None:
return
self.generate_ewr_at(position)
def generate_ewr_at(self, position: Point) -> None:
group_id = self.game.next_group_id()
g = EwrGroundObject(
namegen.random_objective_name(),
group_id,
position,
self.control_point,
for_airbase=False,
)
group = generate_ewr_group(self.game, g, self.faction)
if group is None:
logging.error(
"Could not generate ewr group for %s at %s",
g.name,
self.control_point,
)
return
g.groups = [group]
self.control_point.connected_objectives.append(g)
def generate_missile_sites(self) -> None:
for i in range(self.faction.missiles_group_count):
self.generate_missile_site()

View File

@ -442,7 +442,12 @@ class VehicleGroupGroundObject(BaseDefenseGroundObject):
class EwrGroundObject(BaseDefenseGroundObject):
def __init__(
self, name: str, group_id: int, position: Point, control_point: ControlPoint
self,
name: str,
group_id: int,
position: Point,
control_point: ControlPoint,
for_airbase: bool,
) -> None:
super().__init__(
name=name,
@ -452,7 +457,7 @@ class EwrGroundObject(BaseDefenseGroundObject):
heading=0,
control_point=control_point,
dcs_identifier="EWR",
airbase_group=True,
airbase_group=for_airbase,
sea_object=False,
)

View File

@ -0,0 +1,63 @@
import random
from typing import List, Optional, Type
from dcs.unitgroup import VehicleGroup
from game import Game
from game.factions.faction import Faction
from game.theater.theatergroundobject import EwrGroundObject
from gen.sam.ewrs import (
BigBirdGenerator,
BoxSpringGenerator,
DogEarGenerator,
FlatFaceGenerator,
HawkEwrGenerator,
PatriotEwrGenerator,
RolandEwrGenerator,
SnowDriftGenerator,
StraightFlushGenerator,
TallRackGenerator,
)
from gen.sam.group_generator import GroupGenerator
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_ewrs_generator(
faction: Faction,
) -> List[Type[GroupGenerator]]:
"""
Return the list of possible EWR generators for the given faction
:param faction: Faction name to search units for
"""
return [EWR_MAP[s] for s in faction.ewrs]
def generate_ewr_group(
game: Game, ground_object: EwrGroundObject, 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

View File

@ -23,18 +23,7 @@ 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
@ -152,19 +141,6 @@ SAM_PRICES = {
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,
@ -176,14 +152,6 @@ def get_faction_possible_sams_generator(
return [SAM_MAP[s] for s in faction.air_defenses]
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_from(
generators: Sequence[Type[AirDefenseGroupGenerator]],
game: Game,
@ -236,22 +204,3 @@ def generate_anti_air_group(
if groups:
return groups
return []
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

View File

@ -147,6 +147,8 @@ def load_icons():
"./resources/ui/ground_assets/" + category + "_blue.png"
)
ICONS["destroyed"] = QPixmap("./resources/ui/ground_assets/destroyed.png")
ICONS["EWR"] = QPixmap("./resources/ui/ground_assets/ewr.png")
ICONS["EWR_blue"] = QPixmap("./resources/ui/ground_assets/ewr_blue.png")
ICONS["ship"] = QPixmap("./resources/ui/ground_assets/ship.png")
ICONS["ship_blue"] = QPixmap("./resources/ui/ground_assets/ship_blue.png")
ICONS["missile"] = QPixmap("./resources/ui/ground_assets/missile.png")

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B