mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
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:
parent
707323ca12
commit
eff5b94db7
@ -7,6 +7,7 @@ Saves from 2.5 are not compatible with 2.6.
|
||||
* **[Campaign]** Ground units can now be transferred by road. See https://github.com/Khopa/dcs_liberation/wiki/Unit-Transfers for more information.
|
||||
* **[Campaign]** Ground units can no longer be sold. To move units to a new location, transfer them.
|
||||
* **[UI]** Campaigns generated for an older or newer version of the game will now be marked as incompatible. They can still be played, but bugs may be present.
|
||||
* **[Modding]** Campaigns now choose locations for factories to spawn.
|
||||
|
||||
## Fixes
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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."""
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -14,7 +14,7 @@ from typing import Dict, Iterator, Optional, TYPE_CHECKING, Type, List
|
||||
from dcs import Mission, Point, unitgroup
|
||||
from dcs.country import Country
|
||||
from dcs.point import StaticPoint
|
||||
from dcs.statics import fortification_map, warehouse_map, Warehouse
|
||||
from dcs.statics import Fortification, fortification_map, warehouse_map, Warehouse
|
||||
from dcs.task import (
|
||||
ActivateBeaconCommand,
|
||||
ActivateICLSCommand,
|
||||
@ -34,6 +34,7 @@ from game.theater import ControlPoint, TheaterGroundObject
|
||||
from game.theater.theatergroundobject import (
|
||||
BuildingGroundObject,
|
||||
CarrierGroundObject,
|
||||
FactoryGroundObject,
|
||||
GenericCarrierGroundObject,
|
||||
LhaGroundObject,
|
||||
ShipGroundObject,
|
||||
@ -213,7 +214,7 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator):
|
||||
f"{self.ground_object.dcs_identifier} not found in static maps"
|
||||
)
|
||||
|
||||
def generate_vehicle_group(self, unit_type: UnitType) -> None:
|
||||
def generate_vehicle_group(self, unit_type: Type[UnitType]) -> None:
|
||||
if not self.ground_object.is_dead:
|
||||
group = self.m.vehicle_group(
|
||||
country=self.country,
|
||||
@ -224,7 +225,7 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator):
|
||||
)
|
||||
self._register_fortification(group)
|
||||
|
||||
def generate_static(self, static_type: StaticType) -> None:
|
||||
def generate_static(self, static_type: Type[StaticType]) -> None:
|
||||
group = self.m.static_group(
|
||||
country=self.country,
|
||||
name=self.ground_object.group_name,
|
||||
@ -244,6 +245,22 @@ class BuildingSiteGenerator(GenericGroundObjectGenerator):
|
||||
self.unit_map.add_building(self.ground_object, building)
|
||||
|
||||
|
||||
class FactoryGenerator(BuildingSiteGenerator):
|
||||
"""Generator for factory sites.
|
||||
|
||||
Factory sites are the buildings that allow the recruitment of ground units.
|
||||
Destroying these prevents the owner from recruiting ground units at the connected
|
||||
control point.
|
||||
"""
|
||||
|
||||
def generate(self) -> None:
|
||||
if self.game.position_culled(self.ground_object.position):
|
||||
return
|
||||
|
||||
# TODO: Faction specific?
|
||||
self.generate_static(Fortification.Workshop_A)
|
||||
|
||||
|
||||
class GenericCarrierGenerator(GenericGroundObjectGenerator):
|
||||
"""Base type for carrier group generation.
|
||||
|
||||
@ -557,7 +574,11 @@ class GroundObjectsGenerator:
|
||||
).generate()
|
||||
|
||||
for ground_object in cp.ground_objects:
|
||||
if isinstance(ground_object, BuildingGroundObject):
|
||||
if isinstance(ground_object, FactoryGroundObject):
|
||||
generator = FactoryGenerator(
|
||||
ground_object, country, self.game, self.m, self.unit_map
|
||||
)
|
||||
elif isinstance(ground_object, BuildingGroundObject):
|
||||
generator = BuildingSiteGenerator(
|
||||
ground_object, country, self.game, self.m, self.unit_map
|
||||
)
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"recommended_player_faction": "USA 2005",
|
||||
"recommended_enemy_faction": "Insurgents (Hard)",
|
||||
"description": "<p>In this scenario, you start from Jordan, and have to fight your way through eastern Syria.</p>",
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"miz": "inherent_resolve.miz",
|
||||
"performance": 1
|
||||
}
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user