Add factory placement to the campaign files.

This also removes the "factory" type from the normal strike target
(money generating) generators to avoid confusion. Later only control
points with factories will be able to spawn ground units, at which point
these will no longer generate income.

https://github.com/Khopa/dcs_liberation/issues/986
This commit is contained in:
Dan Albert
2021-04-18 20:24:36 -07:00
parent 707323ca12
commit eff5b94db7
11 changed files with 104 additions and 9 deletions

View File

@@ -10,14 +10,12 @@ DEFAULT_AVAILABLE_BUILDINGS = [
"farp",
"fob",
"power",
"factory",
"derrick",
]
WW2_FREE = ["fuel", "factory", "ware", "fob"]
WW2_FREE = ["fuel", "ware", "fob"]
WW2_GERMANY_BUILDINGS = [
"fuel",
"factory",
"ww2bunker",
"ww2bunker",
"ww2bunker",
@@ -27,7 +25,6 @@ WW2_GERMANY_BUILDINGS = [
]
WW2_ALLIES_BUILDINGS = [
"fuel",
"factory",
"allycamp",
"allycamp",
"allycamp",

View File

@@ -1350,6 +1350,7 @@ REWARDS = {
"ammo": 2,
"farp": 1,
"fob": 1,
# TODO: Should generate no cash once they generate units.
"factory": 10,
"comms": 10,
"oil": 10,

View File

@@ -120,6 +120,8 @@ class MizCampaignLoader:
REQUIRED_EWR_UNIT_TYPE = AirDefence.EWR_1L13.id
FACTORY_UNIT_TYPE = Fortification.Workshop_A.id
BASE_DEFENSE_RADIUS = nautical_miles(2)
def __init__(self, miz: Path, theater: ConflictTheater) -> None:
@@ -261,6 +263,12 @@ class MizCampaignLoader:
if group.units[0].type == self.FARP_HELIPAD:
yield group
@property
def factories(self) -> Iterator[StaticGroup]:
for group in self.blue.static_group:
if group.units[0].type in self.FACTORY_UNIT_TYPE:
yield group
@cached_property
def control_points(self) -> Dict[int, ControlPoint]:
control_points = {}
@@ -421,6 +429,12 @@ class MizCampaignLoader:
PointWithHeading.from_point(group.position, group.units[0].heading)
)
for group in self.factories:
closest, distance = self.objective_info(group)
closest.preset_locations.factories.append(
PointWithHeading.from_point(group.position, group.units[0].heading)
)
def populate_theater(self) -> None:
for control_point in self.control_points.values():
self.theater.add_controlpoint(control_point)

View File

@@ -110,6 +110,9 @@ class PresetLocations:
#: Locations of EWRs which should always be spawned.
required_ewrs: List[PointWithHeading] = field(default_factory=list)
#: Locations of factories for producing ground units. These will always be spawned.
factories: 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

@@ -18,6 +18,7 @@ from game.theater.theatergroundobject import (
BuildingGroundObject,
CarrierGroundObject,
EwrGroundObject,
FactoryGroundObject,
LhaGroundObject,
MissileSiteGroundObject,
SamGroundObject,
@@ -612,6 +613,7 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
"""Generate ground objects and AA sites for the control point."""
skip_sams = self.generate_required_aa()
skip_ewrs = self.generate_required_ewr()
self.generate_factories()
if self.control_point.is_global:
return
@@ -717,6 +719,25 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
self.control_point.connected_objectives.append(g)
def generate_factories(self) -> None:
"""Generates the factories that are required by the campaign."""
for position in self.control_point.preset_locations.factories:
self.generate_factory_at(position)
def generate_factory_at(self, point: PointWithHeading) -> None:
obj_name = namegen.random_objective_name()
group_id = self.game.next_group_id()
g = FactoryGroundObject(
obj_name,
group_id,
point,
point.heading,
self.control_point,
)
self.control_point.connected_objectives.append(g)
def generate_aa_site(self) -> None:
position = self.location_finder.location_for(LocationType.Sam)
if position is None:

View File

@@ -266,6 +266,28 @@ class BuildingGroundObject(TheaterGroundObject):
self._dead = True
class FactoryGroundObject(BuildingGroundObject):
def __init__(
self,
name: str,
group_id: int,
position: Point,
heading: int,
control_point: ControlPoint,
) -> None:
super().__init__(
name=name,
category="factory",
group_id=group_id,
object_id=0,
position=position,
heading=heading,
control_point=control_point,
dcs_identifier="Workshop A",
airbase_group=False,
)
class NavalGroundObject(TheaterGroundObject):
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
from gen.flights.flight import FlightType

View File

@@ -24,4 +24,19 @@ VERSION = _build_version_string()
#:
#: There is no verification that the campaign author updated their campaign correctly
#: this is just a UI hint.
#:
#: Version history:
#:
#: Version 0
#: * Unknown compatibility.
#:
#: Version 1
#: * Compatible with Liberation 2.5.
#:
#: Version 2
#: * Front line endpoints now define convoy origin/destination waypoints. They should be
#: placed on or near roads.
#: * Factories (Warehouse_A) define factory objectives. Only control points with
#: factories will be able to recruit ground units, so they should exist in sufficient
#: number and be protected by IADS.
CAMPAIGN_FORMAT_VERSION = 1