mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Changed helipad generation structure as to not impact "Game" object, as suggested by Dan.
This commit is contained in:
parent
5412487178
commit
5e715daded
@ -1,25 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from dcs import Point
|
|
||||||
from dcs.unitgroup import StaticGroup
|
|
||||||
|
|
||||||
from game.point_with_heading import PointWithHeading
|
|
||||||
from game.utils import Heading
|
|
||||||
|
|
||||||
|
|
||||||
class Helipad(PointWithHeading):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super(Helipad, self).__init__()
|
|
||||||
self.heading = Heading.from_degrees(0)
|
|
||||||
self.occupied = False
|
|
||||||
self.static_unit: Optional[StaticGroup] = None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_point(point: Point, heading: Heading) -> Helipad:
|
|
||||||
h = Helipad()
|
|
||||||
h.x = point.x
|
|
||||||
h.y = point.y
|
|
||||||
h.heading = heading
|
|
||||||
return h
|
|
||||||
@ -375,6 +375,7 @@ class Operation:
|
|||||||
cls.laser_code_registry,
|
cls.laser_code_registry,
|
||||||
cls.unit_map,
|
cls.unit_map,
|
||||||
air_support=cls.airsupportgen.air_support,
|
air_support=cls.airsupportgen.air_support,
|
||||||
|
helipads=cls.groundobjectgen.helipads,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.airgen.clear_parking_slots()
|
cls.airgen.clear_parking_slots()
|
||||||
|
|||||||
@ -56,7 +56,6 @@ from .landmap import Landmap, load_landmap, poly_contains
|
|||||||
from .latlon import LatLon
|
from .latlon import LatLon
|
||||||
from .projections import TransverseMercator
|
from .projections import TransverseMercator
|
||||||
from .seasonalconditions import SeasonalConditions
|
from .seasonalconditions import SeasonalConditions
|
||||||
from ..helipad import Helipad
|
|
||||||
from ..point_with_heading import PointWithHeading
|
from ..point_with_heading import PointWithHeading
|
||||||
from ..positioned import Positioned
|
from ..positioned import Positioned
|
||||||
from ..profiling import logged_duration
|
from ..profiling import logged_duration
|
||||||
@ -482,7 +481,7 @@ class MizCampaignLoader:
|
|||||||
for static in self.helipads:
|
for static in self.helipads:
|
||||||
closest, distance = self.objective_info(static)
|
closest, distance = self.objective_info(static)
|
||||||
closest.helipads.append(
|
closest.helipads.append(
|
||||||
Helipad.from_point(
|
PointWithHeading.from_point(
|
||||||
static.position, Heading.from_degrees(static.units[0].heading)
|
static.position, Heading.from_degrees(static.units[0].heading)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -49,7 +49,6 @@ from .theatergroundobject import (
|
|||||||
)
|
)
|
||||||
from ..dcs.aircrafttype import AircraftType
|
from ..dcs.aircrafttype import AircraftType
|
||||||
from ..dcs.groundunittype import GroundUnitType
|
from ..dcs.groundunittype import GroundUnitType
|
||||||
from ..helipad import Helipad
|
|
||||||
from ..utils import nautical_miles
|
from ..utils import nautical_miles
|
||||||
from ..weather import Conditions
|
from ..weather import Conditions
|
||||||
|
|
||||||
@ -307,7 +306,7 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
self.at = at
|
self.at = at
|
||||||
self.connected_objectives: List[TheaterGroundObject[Any]] = []
|
self.connected_objectives: List[TheaterGroundObject[Any]] = []
|
||||||
self.preset_locations = PresetLocations()
|
self.preset_locations = PresetLocations()
|
||||||
self.helipads: List[Helipad] = []
|
self.helipads: List[PointWithHeading] = []
|
||||||
|
|
||||||
# TODO: Should be Airbase specific.
|
# TODO: Should be Airbase specific.
|
||||||
self.size = size
|
self.size = size
|
||||||
@ -400,22 +399,6 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
"""
|
"""
|
||||||
return len(self.helipads) > 0
|
return len(self.helipads) > 0
|
||||||
|
|
||||||
@property
|
|
||||||
def has_free_helipad(self) -> bool:
|
|
||||||
"""
|
|
||||||
Returns true if cp has a free helipad
|
|
||||||
"""
|
|
||||||
return not all(h.occupied for h in self.helipads)
|
|
||||||
|
|
||||||
def get_free_helipad(self) -> Optional[Helipad]:
|
|
||||||
"""
|
|
||||||
Returns the first free additional helipad
|
|
||||||
"""
|
|
||||||
for h in self.helipads:
|
|
||||||
if not h.occupied:
|
|
||||||
return h
|
|
||||||
return None
|
|
||||||
|
|
||||||
def can_recruit_ground_units(self, game: Game) -> bool:
|
def can_recruit_ground_units(self, game: Game) -> bool:
|
||||||
"""Returns True if this control point is capable of recruiting ground units."""
|
"""Returns True if this control point is capable of recruiting ground units."""
|
||||||
if not self.can_deploy_ground_units:
|
if not self.can_deploy_ground_units:
|
||||||
|
|||||||
@ -68,7 +68,6 @@ from game import db
|
|||||||
from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum
|
from game.data.weapons import Pylon, WeaponType as WeaponTypeEnum
|
||||||
from game.dcs.aircrafttype import AircraftType
|
from game.dcs.aircrafttype import AircraftType
|
||||||
from game.factions.faction import Faction
|
from game.factions.faction import Faction
|
||||||
from game.helipad import Helipad
|
|
||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
from game.squadrons import Pilot
|
from game.squadrons import Pilot
|
||||||
from game.theater.controlpoint import (
|
from game.theater.controlpoint import (
|
||||||
@ -229,6 +228,7 @@ class AircraftConflictGenerator:
|
|||||||
laser_code_registry: LaserCodeRegistry,
|
laser_code_registry: LaserCodeRegistry,
|
||||||
unit_map: UnitMap,
|
unit_map: UnitMap,
|
||||||
air_support: AirSupport,
|
air_support: AirSupport,
|
||||||
|
helipads: dict[ControlPoint, list[StaticGroup]],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.m = mission
|
self.m = mission
|
||||||
self.game = game
|
self.game = game
|
||||||
@ -239,6 +239,7 @@ class AircraftConflictGenerator:
|
|||||||
self.unit_map = unit_map
|
self.unit_map = unit_map
|
||||||
self.flights: List[FlightData] = []
|
self.flights: List[FlightData] = []
|
||||||
self.air_support = air_support
|
self.air_support = air_support
|
||||||
|
self.helipads = helipads
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def use_client(self) -> bool:
|
def use_client(self) -> bool:
|
||||||
@ -550,40 +551,37 @@ class AircraftConflictGenerator:
|
|||||||
unit_type, side.id, cp.name
|
unit_type, side.id, cp.name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
helipad = cp.get_free_helipad()
|
|
||||||
if helipad is not None and helipad.static_unit is not None:
|
try:
|
||||||
|
helipad = self.helipads[cp].pop()
|
||||||
|
except IndexError as ex:
|
||||||
|
raise RuntimeError(f"Not enough helipads available at {cp}") from ex
|
||||||
|
|
||||||
group = self._generate_at_group(
|
group = self._generate_at_group(
|
||||||
name=name,
|
name=name,
|
||||||
side=side,
|
side=side,
|
||||||
unit_type=unit_type,
|
unit_type=unit_type,
|
||||||
count=count,
|
count=count,
|
||||||
start_type=start_type,
|
start_type=start_type,
|
||||||
at=helipad.static_unit,
|
at=helipad,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Note : A bit dirty, need better support in pydcs
|
# Note : A bit dirty, need better support in pydcs
|
||||||
group.points[0].action = PointAction.FromGroundArea
|
group.points[0].action = PointAction.FromGroundArea
|
||||||
group.points[0].type = "TakeOffGround"
|
group.points[0].type = "TakeOffGround"
|
||||||
group.units[0].heading = helipad.heading
|
group.units[0].heading = helipad.units[0].heading
|
||||||
if start_type != "Cold":
|
if start_type != "Cold":
|
||||||
group.points[0].action = PointAction.FromGroundAreaHot
|
group.points[0].action = PointAction.FromGroundAreaHot
|
||||||
group.points[0].type = "TakeOffGroundHot"
|
group.points[0].type = "TakeOffGroundHot"
|
||||||
|
|
||||||
helipad.occupied = True
|
|
||||||
|
|
||||||
for i in range(count - 1):
|
for i in range(count - 1):
|
||||||
helipad = cp.get_free_helipad()
|
try:
|
||||||
if helipad is not None:
|
helipad = self.helipads[cp].pop()
|
||||||
helipad.occupied = True
|
|
||||||
group.units[1 + i].position = Point(helipad.x, helipad.y)
|
group.units[1 + i].position = Point(helipad.x, helipad.y)
|
||||||
group.units[1 + i].heading = helipad.heading
|
group.units[1 + i].heading = helipad.units[0].heading
|
||||||
else:
|
except IndexError as ex:
|
||||||
raise RuntimeError(
|
raise RuntimeError(f"Not enough helipads available at {cp}") from ex
|
||||||
f"Control Point {cp.name} does not have enough helipads"
|
|
||||||
)
|
|
||||||
return group
|
return group
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Control Point {cp.name} does not have enough helipads")
|
|
||||||
|
|
||||||
def _add_radio_waypoint(
|
def _add_radio_waypoint(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
from collections import defaultdict
|
||||||
from typing import (
|
from typing import (
|
||||||
Dict,
|
Dict,
|
||||||
Iterator,
|
Iterator,
|
||||||
@ -587,6 +588,7 @@ class HelipadGenerator:
|
|||||||
self.game = game
|
self.game = game
|
||||||
self.radio_registry = radio_registry
|
self.radio_registry = radio_registry
|
||||||
self.tacan_registry = tacan_registry
|
self.tacan_registry = tacan_registry
|
||||||
|
self.helipads: list[StaticGroup] = []
|
||||||
|
|
||||||
def generate(self) -> None:
|
def generate(self) -> None:
|
||||||
|
|
||||||
@ -595,7 +597,7 @@ class HelipadGenerator:
|
|||||||
country = self.m.country(self.game.coalition_for(self.cp.captured).country_name)
|
country = self.m.country(self.game.coalition_for(self.cp.captured).country_name)
|
||||||
for i, helipad in enumerate(self.cp.helipads):
|
for i, helipad in enumerate(self.cp.helipads):
|
||||||
name = self.cp.name + "_helipad_" + str(i)
|
name = self.cp.name + "_helipad_" + str(i)
|
||||||
logging.info("Generating helipad : " + name)
|
logging.info("Generating helipad static : " + name)
|
||||||
pad = InvisibleFARP(name=name)
|
pad = InvisibleFARP(name=name)
|
||||||
pad.position = Point(helipad.x, helipad.y)
|
pad.position = Point(helipad.x, helipad.y)
|
||||||
pad.heading = helipad.heading.degrees
|
pad.heading = helipad.heading.degrees
|
||||||
@ -606,8 +608,7 @@ class HelipadGenerator:
|
|||||||
sg.add_point(sp)
|
sg.add_point(sp)
|
||||||
neutral_country.add_static_group(sg)
|
neutral_country.add_static_group(sg)
|
||||||
|
|
||||||
helipad.static_unit = sg
|
self.helipads.append(sg)
|
||||||
helipad.occupied = False
|
|
||||||
|
|
||||||
# Generate a FARP Ammo and Fuel stack for each pad
|
# Generate a FARP Ammo and Fuel stack for each pad
|
||||||
self.m.static_group(
|
self.m.static_group(
|
||||||
@ -652,13 +653,18 @@ class GroundObjectsGenerator:
|
|||||||
self.unit_map = unit_map
|
self.unit_map = unit_map
|
||||||
self.icls_alloc = iter(range(1, 21))
|
self.icls_alloc = iter(range(1, 21))
|
||||||
self.runways: Dict[str, RunwayData] = {}
|
self.runways: Dict[str, RunwayData] = {}
|
||||||
|
self.helipads: dict[ControlPoint, list[StaticGroup]] = defaultdict(list)
|
||||||
|
|
||||||
def generate(self) -> None:
|
def generate(self) -> None:
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
country = self.m.country(self.game.coalition_for(cp.captured).country_name)
|
country = self.m.country(self.game.coalition_for(cp.captured).country_name)
|
||||||
HelipadGenerator(
|
|
||||||
|
# Generate helipads
|
||||||
|
helipad_gen = HelipadGenerator(
|
||||||
self.m, cp, self.game, self.radio_registry, self.tacan_registry
|
self.m, cp, self.game, self.radio_registry, self.tacan_registry
|
||||||
).generate()
|
)
|
||||||
|
helipad_gen.generate()
|
||||||
|
self.helipads[cp] = helipad_gen.helipads
|
||||||
|
|
||||||
for ground_object in cp.ground_objects:
|
for ground_object in cp.ground_objects:
|
||||||
generator: GenericGroundObjectGenerator[Any]
|
generator: GenericGroundObjectGenerator[Any]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user