mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
commit
aef4316f72
@ -39,7 +39,7 @@ from dcs.unitgroup import (
|
|||||||
StaticGroup,
|
StaticGroup,
|
||||||
VehicleGroup,
|
VehicleGroup,
|
||||||
)
|
)
|
||||||
from dcs.vehicles import AirDefence, Armor, MissilesSS
|
from dcs.vehicles import AirDefence, Armor, MissilesSS, Unarmed
|
||||||
|
|
||||||
from gen.flights.flight import FlightType
|
from gen.flights.flight import FlightType
|
||||||
from .controlpoint import (
|
from .controlpoint import (
|
||||||
@ -49,6 +49,7 @@ from .controlpoint import (
|
|||||||
Lha,
|
Lha,
|
||||||
MissionTarget,
|
MissionTarget,
|
||||||
OffMapSpawn,
|
OffMapSpawn,
|
||||||
|
Fob,
|
||||||
)
|
)
|
||||||
from .landmap import Landmap, load_landmap, poly_contains
|
from .landmap import Landmap, load_landmap, poly_contains
|
||||||
from ..utils import nm_to_meter
|
from ..utils import nm_to_meter
|
||||||
@ -87,6 +88,8 @@ class MizCampaignLoader:
|
|||||||
LHA_UNIT_TYPE = LHA_1_Tarawa.id
|
LHA_UNIT_TYPE = LHA_1_Tarawa.id
|
||||||
FRONT_LINE_UNIT_TYPE = Armor.APC_M113.id
|
FRONT_LINE_UNIT_TYPE = Armor.APC_M113.id
|
||||||
|
|
||||||
|
FOB_UNIT_TYPE = Unarmed.CP_SKP_11_ATC_Mobile_Command_Post.id
|
||||||
|
|
||||||
EWR_UNIT_TYPE = AirDefence.EWR_55G6.id
|
EWR_UNIT_TYPE = AirDefence.EWR_55G6.id
|
||||||
SAM_UNIT_TYPE = AirDefence.SAM_SA_10_S_300PS_SR_64H6E.id
|
SAM_UNIT_TYPE = AirDefence.SAM_SA_10_S_300PS_SR_64H6E.id
|
||||||
GARRISON_UNIT_TYPE = AirDefence.SAM_SA_19_Tunguska_2S6.id
|
GARRISON_UNIT_TYPE = AirDefence.SAM_SA_19_Tunguska_2S6.id
|
||||||
@ -178,6 +181,11 @@ class MizCampaignLoader:
|
|||||||
if group.units[0].type == self.LHA_UNIT_TYPE:
|
if group.units[0].type == self.LHA_UNIT_TYPE:
|
||||||
yield group
|
yield group
|
||||||
|
|
||||||
|
def fobs(self, blue: bool) -> Iterator[VehicleGroup]:
|
||||||
|
for group in self.country(blue).vehicle_group:
|
||||||
|
if group.units[0].type == self.FOB_UNIT_TYPE:
|
||||||
|
yield group
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ships(self) -> Iterator[ShipGroup]:
|
def ships(self) -> Iterator[ShipGroup]:
|
||||||
for group in self.blue.ship_group:
|
for group in self.blue.ship_group:
|
||||||
@ -261,6 +269,13 @@ class MizCampaignLoader:
|
|||||||
control_point.captured = blue
|
control_point.captured = blue
|
||||||
control_point.captured_invert = group.late_activation
|
control_point.captured_invert = group.late_activation
|
||||||
control_points[control_point.id] = control_point
|
control_points[control_point.id] = control_point
|
||||||
|
for group in self.fobs(blue):
|
||||||
|
control_point = Fob(
|
||||||
|
str(group.name), group.position, next(self.control_point_id)
|
||||||
|
)
|
||||||
|
control_point.captured = blue
|
||||||
|
control_point.captured_invert = group.late_activation
|
||||||
|
control_points[control_point.id] = control_point
|
||||||
|
|
||||||
return control_points
|
return control_points
|
||||||
|
|
||||||
@ -279,14 +294,14 @@ class MizCampaignLoader:
|
|||||||
# final waypoint at the destination CP. Intermediate waypoints
|
# final waypoint at the destination CP. Intermediate waypoints
|
||||||
# define the curve of the front line.
|
# define the curve of the front line.
|
||||||
waypoints = [p.position for p in group.points]
|
waypoints = [p.position for p in group.points]
|
||||||
origin = self.mission.terrain.nearest_airport(waypoints[0])
|
origin = self.theater.closest_control_point(waypoints[0])
|
||||||
if origin is None:
|
if origin is None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"No airport near the first waypoint of {group.name}")
|
f"No control point near the first waypoint of {group.name}")
|
||||||
destination = self.mission.terrain.nearest_airport(waypoints[-1])
|
destination = self.theater.closest_control_point(waypoints[-1])
|
||||||
if destination is None:
|
if destination is None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"No airport near the final waypoint of {group.name}")
|
f"No control point near the final waypoint of {group.name}")
|
||||||
|
|
||||||
# Snap the begin and end points to the control points.
|
# Snap the begin and end points to the control points.
|
||||||
waypoints[0] = origin.position
|
waypoints[0] = origin.position
|
||||||
|
|||||||
@ -623,3 +623,51 @@ class OffMapSpawn(ControlPoint):
|
|||||||
@property
|
@property
|
||||||
def runway_status(self) -> RunwayStatus:
|
def runway_status(self) -> RunwayStatus:
|
||||||
return RunwayStatus()
|
return RunwayStatus()
|
||||||
|
|
||||||
|
|
||||||
|
class Fob(ControlPoint):
|
||||||
|
|
||||||
|
def __init__(self, name: str, at: Point, cp_id: int):
|
||||||
|
import game.theater.conflicttheater
|
||||||
|
super().__init__(cp_id, name, at, at,
|
||||||
|
game.theater.conflicttheater.SIZE_SMALL, 1,
|
||||||
|
has_frontline=True, cptype=ControlPointType.FOB)
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def runway_is_operational(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def active_runway(self, conditions: Conditions,
|
||||||
|
dynamic_runways: Dict[str, RunwayData]) -> RunwayData:
|
||||||
|
logging.warning("TODO: FOBs have no runways.")
|
||||||
|
return RunwayData(self.full_name, runway_heading=0, runway_name="")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def runway_status(self) -> RunwayStatus:
|
||||||
|
return RunwayStatus()
|
||||||
|
|
||||||
|
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
|
||||||
|
from gen.flights.flight import FlightType
|
||||||
|
if self.is_friendly(for_player):
|
||||||
|
yield from [
|
||||||
|
FlightType.BARCAP,
|
||||||
|
# TODO: FlightType.LOGISTICS
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
yield from [
|
||||||
|
FlightType.STRIKE,
|
||||||
|
FlightType.SWEEP,
|
||||||
|
FlightType.ESCORT,
|
||||||
|
FlightType.SEAD,
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_aircraft_parking(self) -> int:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def can_operate(self, aircraft: FlyingType) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def heading(self) -> int:
|
||||||
|
return 0
|
||||||
|
|||||||
@ -45,6 +45,7 @@ from . import (
|
|||||||
ControlPoint,
|
ControlPoint,
|
||||||
ControlPointType,
|
ControlPointType,
|
||||||
OffMapSpawn,
|
OffMapSpawn,
|
||||||
|
Fob,
|
||||||
)
|
)
|
||||||
|
|
||||||
GroundObjectTemplates = Dict[str, Dict[str, Any]]
|
GroundObjectTemplates = Dict[str, Dict[str, Any]]
|
||||||
@ -537,7 +538,26 @@ class BaseDefenseGenerator:
|
|||||||
return
|
return
|
||||||
g.groups.append(group)
|
g.groups.append(group)
|
||||||
self.control_point.base_defenses.append(g)
|
self.control_point.base_defenses.append(g)
|
||||||
|
class FobDefenseGenerator(BaseDefenseGenerator):
|
||||||
|
def generate(self) -> None:
|
||||||
|
self.generate_garrison()
|
||||||
|
self.generate_fob_defenses()
|
||||||
|
|
||||||
|
def generate_fob_defenses(self):
|
||||||
|
# First group has a 1/2 chance of being a SHORAD,
|
||||||
|
# and a 1/2 chance of a garrison.
|
||||||
|
#
|
||||||
|
# Further groups have a 1/3 chance of being SHORAD and 2/3 chance of
|
||||||
|
# being a garrison.
|
||||||
|
for i in range(random.randint(2, 5)):
|
||||||
|
if i == 0 and random.randint(0, 1) == 0:
|
||||||
|
self.generate_shorad()
|
||||||
|
elif i == 0 and random.randint(0, 1) == 0:
|
||||||
|
self.generate_garrison()
|
||||||
|
elif random.randint(0, 2) == 1:
|
||||||
|
self.generate_shorad()
|
||||||
|
else:
|
||||||
|
self.generate_garrison()
|
||||||
|
|
||||||
class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
||||||
def __init__(self, game: Game, control_point: ControlPoint,
|
def __init__(self, game: Game, control_point: ControlPoint,
|
||||||
@ -679,6 +699,35 @@ class AirbaseGroundObjectGenerator(ControlPointGroundObjectGenerator):
|
|||||||
self.control_point.connected_objectives.append(g)
|
self.control_point.connected_objectives.append(g)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
class FobGroundObjectGenerator(AirbaseGroundObjectGenerator):
|
||||||
|
def generate(self) -> bool:
|
||||||
|
self.generate_fob()
|
||||||
|
FobDefenseGenerator(self.game, self.control_point).generate()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def generate_fob(self) -> None:
|
||||||
|
try:
|
||||||
|
category = self.faction.building_set[self.faction.building_set.index('fob')]
|
||||||
|
except IndexError:
|
||||||
|
logging.exception("Faction has no fob buildings defined")
|
||||||
|
return
|
||||||
|
|
||||||
|
obj_name = self.control_point.name
|
||||||
|
template = random.choice(list(self.templates[category].values()))
|
||||||
|
point = self.control_point.position
|
||||||
|
# Pick from preset locations
|
||||||
|
object_id = 0
|
||||||
|
group_id = self.game.next_group_id()
|
||||||
|
|
||||||
|
# TODO: Create only one TGO per objective, each with multiple units.
|
||||||
|
for unit in template:
|
||||||
|
object_id += 1
|
||||||
|
|
||||||
|
template_point = Point(unit["offset"].x, unit["offset"].y)
|
||||||
|
g = BuildingGroundObject(
|
||||||
|
obj_name, category, group_id, object_id, point + template_point,
|
||||||
|
unit["heading"], self.control_point, unit["type"], airbase_group=True)
|
||||||
|
self.control_point.connected_objectives.append(g)
|
||||||
|
|
||||||
class GroundObjectGenerator:
|
class GroundObjectGenerator:
|
||||||
def __init__(self, game: Game) -> None:
|
def __init__(self, game: Game) -> None:
|
||||||
@ -702,6 +751,9 @@ class GroundObjectGenerator:
|
|||||||
generator = LhaGroundObjectGenerator(self.game, control_point)
|
generator = LhaGroundObjectGenerator(self.game, control_point)
|
||||||
elif isinstance(control_point, OffMapSpawn):
|
elif isinstance(control_point, OffMapSpawn):
|
||||||
generator = NoOpGroundObjectGenerator(self.game, control_point)
|
generator = NoOpGroundObjectGenerator(self.game, control_point)
|
||||||
|
elif isinstance(control_point, Fob):
|
||||||
|
generator = FobGroundObjectGenerator(self.game, control_point,
|
||||||
|
self.templates)
|
||||||
else:
|
else:
|
||||||
generator = AirbaseGroundObjectGenerator(self.game, control_point,
|
generator = AirbaseGroundObjectGenerator(self.game, control_point,
|
||||||
self.templates)
|
self.templates)
|
||||||
|
|||||||
@ -140,7 +140,7 @@ class TheaterGroundObject(MissionTarget):
|
|||||||
class BuildingGroundObject(TheaterGroundObject):
|
class BuildingGroundObject(TheaterGroundObject):
|
||||||
def __init__(self, name: str, category: str, group_id: int, object_id: int,
|
def __init__(self, name: str, category: str, group_id: int, object_id: int,
|
||||||
position: Point, heading: int, control_point: ControlPoint,
|
position: Point, heading: int, control_point: ControlPoint,
|
||||||
dcs_identifier: str) -> None:
|
dcs_identifier: str, airbase_group=False) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name=name,
|
name=name,
|
||||||
category=category,
|
category=category,
|
||||||
@ -149,7 +149,7 @@ class BuildingGroundObject(TheaterGroundObject):
|
|||||||
heading=heading,
|
heading=heading,
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
dcs_identifier=dcs_identifier,
|
dcs_identifier=dcs_identifier,
|
||||||
airbase_group=False,
|
airbase_group=airbase_group,
|
||||||
sea_object=False
|
sea_object=False
|
||||||
)
|
)
|
||||||
self.object_id = object_id
|
self.object_id = object_id
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user