mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Limit front line size with ammo depots.
This limit is determined by the number of buildings that belong to Ammo Depots at the front line's connected Control Point. The limit increases for every surviving building at ammo depot objectives. There is a lower limit to the number of units that will spawn, so that if there are no surviving ammo depot buildings at a control point, there will still be some ground conflict.
This commit is contained in:
parent
077ca19912
commit
95b0b851a5
@ -3,7 +3,6 @@ import dcs
|
||||
|
||||
DEFAULT_AVAILABLE_BUILDINGS = [
|
||||
"fuel",
|
||||
"ammo",
|
||||
"comms",
|
||||
"oil",
|
||||
"ware",
|
||||
|
||||
@ -262,10 +262,19 @@ class ProcurementAi:
|
||||
# Prefer to buy front line units at active front lines that are not
|
||||
# already overloaded.
|
||||
for cp in self.owned_points:
|
||||
|
||||
total_ground_units_allocated_to_this_control_point = (
|
||||
self.total_ground_units_allocated_to(cp)
|
||||
)
|
||||
|
||||
if not cp.has_ground_unit_source(self.game):
|
||||
continue
|
||||
|
||||
if self.total_ground_units_allocated_to(cp) >= 50:
|
||||
if (
|
||||
total_ground_units_allocated_to_this_control_point >= 50
|
||||
or total_ground_units_allocated_to_this_control_point
|
||||
>= cp.frontline_unit_count_limit
|
||||
):
|
||||
# Control point is already sufficiently defended.
|
||||
continue
|
||||
for connected in cp.connected_points:
|
||||
|
||||
@ -22,7 +22,7 @@ from dcs.ships import (
|
||||
DDG_Arleigh_Burke_IIa,
|
||||
LHA_1_Tarawa,
|
||||
)
|
||||
from dcs.statics import Fortification
|
||||
from dcs.statics import Fortification, Warehouse
|
||||
from dcs.terrain import (
|
||||
caucasus,
|
||||
nevada,
|
||||
@ -128,6 +128,8 @@ class MizCampaignLoader:
|
||||
|
||||
FACTORY_UNIT_TYPE = Fortification.Workshop_A.id
|
||||
|
||||
AMMUNITION_DEPOT_UNIT_TYPE = Warehouse.Ammunition_depot.id
|
||||
|
||||
REQUIRED_STRIKE_TARGET_UNIT_TYPE = Fortification.Tech_combine.id
|
||||
|
||||
BASE_DEFENSE_RADIUS = nautical_miles(2)
|
||||
@ -320,6 +322,12 @@ class MizCampaignLoader:
|
||||
if group.units[0].type in self.FACTORY_UNIT_TYPE:
|
||||
yield group
|
||||
|
||||
@property
|
||||
def ammunition_depots(self) -> Iterator[StaticGroup]:
|
||||
for group in itertools.chain(self.blue.static_group, self.red.static_group):
|
||||
if group.units[0].type in self.AMMUNITION_DEPOT_UNIT_TYPE:
|
||||
yield group
|
||||
|
||||
@property
|
||||
def required_strike_targets(self) -> Iterator[StaticGroup]:
|
||||
for group in itertools.chain(self.blue.static_group, self.red.static_group):
|
||||
@ -559,6 +567,12 @@ class MizCampaignLoader:
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.ammunition_depots:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.ammunition_depots.append(
|
||||
PointWithHeading.from_point(group.position, group.units[0].heading)
|
||||
)
|
||||
|
||||
for group in self.required_strike_targets:
|
||||
closest, distance = self.objective_info(group)
|
||||
closest.preset_locations.required_strike_locations.append(
|
||||
|
||||
@ -59,6 +59,9 @@ if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from gen.flights.flight import FlightType
|
||||
|
||||
FREE_FRONTLINE_UNIT_SUPPLY: int = 15
|
||||
AMMO_DEPOT_FRONTLINE_UNIT_CONTRIBUTION: int = 12
|
||||
|
||||
|
||||
class ControlPointType(Enum):
|
||||
#: An airbase with slots for everything.
|
||||
@ -161,6 +164,9 @@ class PresetLocations:
|
||||
#: Locations of factories for producing ground units. These will always be spawned.
|
||||
factories: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations of ammo depots for controlling number of units on the front line at a control point.
|
||||
ammunition_depots: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
#: Locations of stationary armor groups. These will always be spawned.
|
||||
armor_groups: List[PointWithHeading] = field(default_factory=list)
|
||||
|
||||
@ -783,6 +789,20 @@ class ControlPoint(MissionTarget, ABC):
|
||||
|
||||
return self.captured != other.captured
|
||||
|
||||
@property
|
||||
def frontline_unit_count_limit(self) -> int:
|
||||
|
||||
tally_connected_ammo_depots = 0
|
||||
|
||||
for cp_objective in self.connected_objectives:
|
||||
if cp_objective.category == "ammo" and not cp_objective.is_dead:
|
||||
tally_connected_ammo_depots += 1
|
||||
|
||||
return (
|
||||
FREE_FRONTLINE_UNIT_SUPPLY
|
||||
+ tally_connected_ammo_depots * AMMO_DEPOT_FRONTLINE_UNIT_CONTRIBUTION
|
||||
)
|
||||
|
||||
@property
|
||||
def strike_targets(self) -> List[Union[MissionTarget, Unit]]:
|
||||
return []
|
||||
|
||||
@ -471,6 +471,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
self.generate_strike_targets()
|
||||
self.generate_offshore_strike_targets()
|
||||
self.generate_factories()
|
||||
self.generate_ammunition_depots()
|
||||
|
||||
if self.faction.missiles:
|
||||
self.generate_missile_sites()
|
||||
@ -629,6 +630,10 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||
|
||||
self.control_point.connected_objectives.append(g)
|
||||
|
||||
def generate_ammunition_depots(self) -> None:
|
||||
for position in self.control_point.preset_locations.ammunition_depots:
|
||||
self.generate_strike_target_at(category="ammo", position=position)
|
||||
|
||||
def generate_factories(self) -> None:
|
||||
"""Generates the factories that are required by the campaign."""
|
||||
for position in self.control_point.preset_locations.factories:
|
||||
@ -828,6 +833,7 @@ class FobGroundObjectGenerator(AirbaseGroundObjectGenerator):
|
||||
FobDefenseGenerator(self.game, self.control_point).generate()
|
||||
self.generate_armor_groups()
|
||||
self.generate_factories()
|
||||
self.generate_ammunition_depots()
|
||||
self.generate_required_aa()
|
||||
self.generate_required_ewr()
|
||||
self.generate_scenery_sites()
|
||||
|
||||
@ -73,4 +73,12 @@ VERSION = _build_version_string()
|
||||
#: * AAA_8_8cm_Flak_18,
|
||||
#: * SPAAA_Vulcan_M163,
|
||||
#: * SPAAA_ZSU_23_4_Shilka_Gun_Dish,
|
||||
CAMPAIGN_FORMAT_VERSION = (4, 2)
|
||||
#:
|
||||
#: Version 5.0
|
||||
#: * Ammunition Depots objective locations are now predetermined using the "Ammunition Depot"
|
||||
#: Warehouse object, and through trigger zone based scenery objects.
|
||||
#: * The number of alive Ammunition Depot objective buildings connected to a control point
|
||||
#: directly influences how many ground units can be supported on the front line.
|
||||
#: * The number of supported ground units at any control point is artificially capped at 50,
|
||||
#: even if the number of alive Ammunition Depot objectives can support more.
|
||||
CAMPAIGN_FORMAT_VERSION = (5, 0)
|
||||
|
||||
@ -80,6 +80,10 @@ class GroundPlanner:
|
||||
|
||||
def plan_groundwar(self):
|
||||
|
||||
ground_unit_limit = self.cp.frontline_unit_count_limit
|
||||
|
||||
remaining_available_frontline_units = ground_unit_limit
|
||||
|
||||
if hasattr(self.cp, "stance"):
|
||||
group_size_choice = GROUP_SIZES_BY_COMBAT_STANCE[self.cp.stance]
|
||||
else:
|
||||
@ -118,6 +122,12 @@ class GroundPlanner:
|
||||
continue
|
||||
|
||||
available = self.cp.base.armor[key]
|
||||
|
||||
if available > remaining_available_frontline_units:
|
||||
available = remaining_available_frontline_units
|
||||
|
||||
remaining_available_frontline_units -= available
|
||||
|
||||
while available > 0:
|
||||
|
||||
if role == CombatGroupRole.SHORAD:
|
||||
@ -144,6 +154,9 @@ class GroundPlanner:
|
||||
group.units.append(key)
|
||||
collection.append(group)
|
||||
|
||||
if remaining_available_frontline_units == 0:
|
||||
break
|
||||
|
||||
print("------------------")
|
||||
print("Ground Planner : ")
|
||||
print(self.cp.name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user