mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Merge branch 'develop' into frontline
This commit is contained in:
@@ -70,6 +70,12 @@ from dcs.unittype import FlyingType, UnitType
|
||||
from game import db
|
||||
from game.data.cap_capabilities_db import GUNFIGHTERS
|
||||
from game.settings import Settings
|
||||
from game.theater.controlpoint import (
|
||||
ControlPoint,
|
||||
ControlPointType,
|
||||
OffMapSpawn,
|
||||
)
|
||||
from game.theater.theatergroundobject import TheaterGroundObject
|
||||
from game.utils import knots_to_kph, nm_to_meter
|
||||
from gen.airsupportgen import AirSupport
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
@@ -83,12 +89,6 @@ from gen.flights.flight import (
|
||||
)
|
||||
from gen.radios import MHz, Radio, RadioFrequency, RadioRegistry, get_radio
|
||||
from gen.runways import RunwayData
|
||||
from theater import TheaterGroundObject
|
||||
from game.theater.controlpoint import (
|
||||
ControlPoint,
|
||||
ControlPointType,
|
||||
OffMapSpawn,
|
||||
)
|
||||
from .conflictgen import Conflict
|
||||
from .flights.flightplan import (
|
||||
CasFlightPlan,
|
||||
@@ -695,6 +695,18 @@ class AircraftConflictGenerator:
|
||||
return StartType.Cold
|
||||
return StartType.Warm
|
||||
|
||||
def determine_runway(self, cp: ControlPoint, dynamic_runways) -> RunwayData:
|
||||
fallback = RunwayData(cp.full_name, runway_heading=0, runway_name="")
|
||||
if cp.cptype == ControlPointType.AIRBASE:
|
||||
assigner = RunwayAssigner(self.game.conditions)
|
||||
return assigner.get_preferred_runway(cp.airport)
|
||||
elif cp.is_fleet:
|
||||
return dynamic_runways.get(cp.name, fallback)
|
||||
else:
|
||||
logging.warning(
|
||||
f"Unhandled departure/arrival control point: {cp.cptype}")
|
||||
return fallback
|
||||
|
||||
def _setup_group(self, group: FlyingGroup, for_task: Type[Task],
|
||||
package: Package, flight: Flight,
|
||||
dynamic_runways: Dict[str, RunwayData]) -> None:
|
||||
@@ -752,19 +764,9 @@ class AircraftConflictGenerator:
|
||||
channel = self.get_intra_flight_channel(unit_type)
|
||||
group.set_frequency(channel.mhz)
|
||||
|
||||
# TODO: Support for different departure/arrival airfields.
|
||||
cp = flight.from_cp
|
||||
fallback_runway = RunwayData(cp.full_name, runway_heading=0,
|
||||
runway_name="")
|
||||
if cp.cptype == ControlPointType.AIRBASE:
|
||||
assigner = RunwayAssigner(self.game.conditions)
|
||||
departure_runway = assigner.get_preferred_runway(
|
||||
flight.from_cp.airport)
|
||||
elif cp.is_fleet:
|
||||
departure_runway = dynamic_runways.get(cp.name, fallback_runway)
|
||||
else:
|
||||
logging.warning(f"Unhandled departure control point: {cp.cptype}")
|
||||
departure_runway = fallback_runway
|
||||
divert = None
|
||||
if flight.divert is not None:
|
||||
divert = self.determine_runway(flight.divert, dynamic_runways)
|
||||
|
||||
self.flights.append(FlightData(
|
||||
package=package,
|
||||
@@ -774,10 +776,9 @@ class AircraftConflictGenerator:
|
||||
friendly=flight.from_cp.captured,
|
||||
# Set later.
|
||||
departure_delay=timedelta(),
|
||||
departure=departure_runway,
|
||||
arrival=departure_runway,
|
||||
# TODO: Support for divert airfields.
|
||||
divert=None,
|
||||
departure=self.determine_runway(flight.departure, dynamic_runways),
|
||||
arrival=self.determine_runway(flight.arrival, dynamic_runways),
|
||||
divert=divert,
|
||||
# Waypoints are added later, after they've had their TOTs set.
|
||||
waypoints=[],
|
||||
intra_flight_channel=channel
|
||||
|
||||
@@ -5,7 +5,8 @@ from typing import Tuple
|
||||
from dcs.country import Country
|
||||
from dcs.mapping import Point
|
||||
|
||||
from theater import ConflictTheater, ControlPoint, FrontLine
|
||||
from game.theater.conflicttheater import ConflictTheater, FrontLine
|
||||
from game.theater.controlpoint import ControlPoint
|
||||
|
||||
AIR_DISTANCE = 40000
|
||||
|
||||
|
||||
@@ -16,11 +16,24 @@ from typing import (
|
||||
Type,
|
||||
)
|
||||
|
||||
from dcs.unittype import FlyingType, UnitType
|
||||
from dcs.unittype import FlyingType
|
||||
|
||||
from game import db
|
||||
from game.data.radar_db import UNITS_WITH_RADAR
|
||||
from game.infos.information import Information
|
||||
from game.theater import (
|
||||
ControlPoint,
|
||||
FrontLine,
|
||||
MissionTarget,
|
||||
OffMapSpawn,
|
||||
SamGroundObject,
|
||||
TheaterGroundObject,
|
||||
)
|
||||
# Avoid importing some types that cause circular imports unless type checking.
|
||||
from game.theater.theatergroundobject import (
|
||||
EwrGroundObject,
|
||||
NavalGroundObject, VehicleGroupGroundObject,
|
||||
)
|
||||
from game.utils import nm_to_meter
|
||||
from gen import Conflict
|
||||
from gen.ato import Package
|
||||
@@ -46,19 +59,6 @@ from gen.flights.flight import (
|
||||
)
|
||||
from gen.flights.flightplan import FlightPlanBuilder
|
||||
from gen.flights.traveltime import TotEstimator
|
||||
from theater import (
|
||||
ControlPoint,
|
||||
FrontLine,
|
||||
MissionTarget,
|
||||
OffMapSpawn, TheaterGroundObject,
|
||||
SamGroundObject,
|
||||
)
|
||||
|
||||
# Avoid importing some types that cause circular imports unless type checking.
|
||||
from game.theater.theatergroundobject import (
|
||||
EwrGroundObject,
|
||||
NavalGroundObject, VehicleGroupGroundObject,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@@ -119,7 +119,7 @@ class AircraftAllocator:
|
||||
|
||||
def find_aircraft_for_flight(
|
||||
self, flight: ProposedFlight
|
||||
) -> Optional[Tuple[ControlPoint, UnitType]]:
|
||||
) -> Optional[Tuple[ControlPoint, FlyingType]]:
|
||||
"""Finds aircraft suitable for the given mission.
|
||||
|
||||
Searches for aircraft capable of performing the given mission within the
|
||||
@@ -190,7 +190,7 @@ class AircraftAllocator:
|
||||
|
||||
def find_aircraft_of_type(
|
||||
self, flight: ProposedFlight, types: List[Type[FlyingType]],
|
||||
) -> Optional[Tuple[ControlPoint, UnitType]]:
|
||||
) -> Optional[Tuple[ControlPoint, FlyingType]]:
|
||||
airfields_in_range = self.closest_airfields.airfields_within(
|
||||
flight.max_distance
|
||||
)
|
||||
@@ -214,6 +214,8 @@ class PackageBuilder:
|
||||
global_inventory: GlobalAircraftInventory,
|
||||
is_player: bool,
|
||||
start_type: str) -> None:
|
||||
self.closest_airfields = closest_airfields
|
||||
self.is_player = is_player
|
||||
self.package = Package(location)
|
||||
self.allocator = AircraftAllocator(closest_airfields, global_inventory,
|
||||
is_player)
|
||||
@@ -236,11 +238,28 @@ class PackageBuilder:
|
||||
start_type = "In Flight"
|
||||
else:
|
||||
start_type = self.start_type
|
||||
flight = Flight(self.package, aircraft, plan.num_aircraft, airfield,
|
||||
plan.task, start_type)
|
||||
|
||||
flight = Flight(self.package, aircraft, plan.num_aircraft, plan.task,
|
||||
start_type, departure=airfield, arrival=airfield,
|
||||
divert=self.find_divert_field(aircraft, airfield))
|
||||
self.package.add_flight(flight)
|
||||
return True
|
||||
|
||||
def find_divert_field(self, aircraft: FlyingType,
|
||||
arrival: ControlPoint) -> Optional[ControlPoint]:
|
||||
divert_limit = nm_to_meter(150)
|
||||
for airfield in self.closest_airfields.airfields_within(divert_limit):
|
||||
if airfield.captured != self.is_player:
|
||||
continue
|
||||
if airfield == arrival:
|
||||
continue
|
||||
if not airfield.can_land(aircraft):
|
||||
continue
|
||||
if isinstance(airfield, OffMapSpawn):
|
||||
continue
|
||||
return airfield
|
||||
return None
|
||||
|
||||
def build(self) -> Package:
|
||||
"""Returns the built package."""
|
||||
return self.package
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Objective adjacency lists."""
|
||||
from typing import Dict, Iterator, List, Optional
|
||||
|
||||
from theater import ConflictTheater, ControlPoint, MissionTarget
|
||||
from game.theater import ConflictTheater, ControlPoint, MissionTarget
|
||||
|
||||
|
||||
class ClosestAirfields:
|
||||
|
||||
@@ -65,6 +65,7 @@ class FlightWaypointType(Enum):
|
||||
INGRESS_DEAD = 20
|
||||
INGRESS_SWEEP = 21
|
||||
INGRESS_BAI = 22
|
||||
DIVERT = 23
|
||||
|
||||
|
||||
class FlightWaypoint:
|
||||
@@ -133,12 +134,15 @@ class FlightWaypoint:
|
||||
class Flight:
|
||||
|
||||
def __init__(self, package: Package, unit_type: FlyingType, count: int,
|
||||
from_cp: ControlPoint, flight_type: FlightType,
|
||||
start_type: str) -> None:
|
||||
flight_type: FlightType, start_type: str,
|
||||
departure: ControlPoint, arrival: ControlPoint,
|
||||
divert: Optional[ControlPoint]) -> None:
|
||||
self.package = package
|
||||
self.unit_type = unit_type
|
||||
self.count = count
|
||||
self.from_cp = from_cp
|
||||
self.departure = departure
|
||||
self.arrival = arrival
|
||||
self.divert = divert
|
||||
self.flight_type = flight_type
|
||||
# TODO: Replace with FlightPlan.
|
||||
self.targets: List[MissionTarget] = []
|
||||
@@ -157,6 +161,10 @@ class Flight:
|
||||
custom_waypoints=[]
|
||||
)
|
||||
|
||||
@property
|
||||
def from_cp(self) -> ControlPoint:
|
||||
return self.departure
|
||||
|
||||
@property
|
||||
def points(self) -> List[FlightWaypoint]:
|
||||
return self.flight_plan.waypoints[1:]
|
||||
|
||||
@@ -7,20 +7,19 @@ generating the waypoints for the mission.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
import logging
|
||||
import math
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
|
||||
|
||||
from dcs.mapping import Point
|
||||
from dcs.unit import Unit
|
||||
|
||||
from game.data.doctrine import Doctrine
|
||||
from game.utils import nm_to_meter
|
||||
from theater import (
|
||||
from game.theater import (
|
||||
ControlPoint,
|
||||
FrontLine,
|
||||
MissionTarget,
|
||||
@@ -28,6 +27,7 @@ from theater import (
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.theater.theatergroundobject import EwrGroundObject
|
||||
from game.utils import nm_to_meter
|
||||
from .closestairfields import ObjectiveDistanceCache
|
||||
from .flight import Flight, FlightType, FlightWaypoint, FlightWaypointType
|
||||
from .traveltime import GroundSpeed, TravelTime
|
||||
@@ -68,6 +68,10 @@ class FlightPlan:
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
"""A list of all waypoints in the flight plan, in order."""
|
||||
return list(self.iter_waypoints())
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
"""Iterates over all waypoints in the flight plan, in order."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@@ -166,8 +170,7 @@ class FlightPlan:
|
||||
class LoiterFlightPlan(FlightPlan):
|
||||
hold: FlightWaypoint
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@@ -193,8 +196,7 @@ class FormationFlightPlan(LoiterFlightPlan):
|
||||
join: FlightWaypoint
|
||||
split: FlightWaypoint
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@@ -295,8 +297,7 @@ class PatrollingFlightPlan(FlightPlan):
|
||||
return self.patrol_end_time
|
||||
return None
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@@ -312,15 +313,17 @@ class PatrollingFlightPlan(FlightPlan):
|
||||
class BarCapFlightPlan(PatrollingFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return [
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from [
|
||||
self.takeoff,
|
||||
self.patrol_start,
|
||||
self.patrol_end,
|
||||
self.land,
|
||||
]
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -328,16 +331,18 @@ class CasFlightPlan(PatrollingFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
target: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return [
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from [
|
||||
self.takeoff,
|
||||
self.patrol_start,
|
||||
self.target,
|
||||
self.patrol_end,
|
||||
self.land,
|
||||
]
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
||||
return self.patrol_start
|
||||
@@ -350,16 +355,18 @@ class CasFlightPlan(PatrollingFlightPlan):
|
||||
class TarCapFlightPlan(PatrollingFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
lead_time: timedelta
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return [
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from [
|
||||
self.takeoff,
|
||||
self.patrol_start,
|
||||
self.patrol_end,
|
||||
self.land,
|
||||
]
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
@property
|
||||
def tot_offset(self) -> timedelta:
|
||||
@@ -386,10 +393,6 @@ class TarCapFlightPlan(PatrollingFlightPlan):
|
||||
return super().patrol_end_time
|
||||
|
||||
|
||||
# TODO: Remove when breaking save compat.
|
||||
FrontLineCapFlightPlan = TarCapFlightPlan
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StrikeFlightPlan(FormationFlightPlan):
|
||||
takeoff: FlightWaypoint
|
||||
@@ -400,19 +403,23 @@ class StrikeFlightPlan(FormationFlightPlan):
|
||||
egress: FlightWaypoint
|
||||
split: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return [
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from [
|
||||
self.takeoff,
|
||||
self.hold,
|
||||
self.join,
|
||||
self.ingress
|
||||
] + self.targets + [
|
||||
]
|
||||
yield from self.targets
|
||||
yield from[
|
||||
self.egress,
|
||||
self.split,
|
||||
self.land,
|
||||
]
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
@property
|
||||
def package_speed_waypoints(self) -> Set[FlightWaypoint]:
|
||||
@@ -511,17 +518,19 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
sweep_start: FlightWaypoint
|
||||
sweep_end: FlightWaypoint
|
||||
land: FlightWaypoint
|
||||
divert: Optional[FlightWaypoint]
|
||||
lead_time: timedelta
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return [
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from [
|
||||
self.takeoff,
|
||||
self.hold,
|
||||
self.sweep_start,
|
||||
self.sweep_end,
|
||||
self.land,
|
||||
]
|
||||
if self.divert is not None:
|
||||
yield self.divert
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||
@@ -567,9 +576,8 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
class CustomFlightPlan(FlightPlan):
|
||||
custom_waypoints: List[FlightWaypoint]
|
||||
|
||||
@property
|
||||
def waypoints(self) -> List[FlightWaypoint]:
|
||||
return self.custom_waypoints
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield from self.custom_waypoints
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||
@@ -774,10 +782,11 @@ class FlightPlanBuilder:
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
patrol_duration=self.doctrine.cap_duration,
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
patrol_start=start,
|
||||
patrol_end=end,
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
def generate_sweep(self, flight: Flight) -> SweepFlightPlan:
|
||||
@@ -800,11 +809,12 @@ class FlightPlanBuilder:
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
lead_time=timedelta(minutes=5),
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
hold=builder.hold(self._hold_point(flight)),
|
||||
sweep_start=start,
|
||||
sweep_end=end,
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
def racetrack_for_objective(self,
|
||||
@@ -900,10 +910,11 @@ class FlightPlanBuilder:
|
||||
# requests an escort the CAP flight will remain on station for the
|
||||
# duration of the escorted mission, or until it is winchester/bingo.
|
||||
patrol_duration=self.doctrine.cap_duration,
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
patrol_start=start,
|
||||
patrol_end=end,
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
def generate_dead(self, flight: Flight,
|
||||
@@ -965,14 +976,15 @@ class FlightPlanBuilder:
|
||||
return StrikeFlightPlan(
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
hold=builder.hold(self._hold_point(flight)),
|
||||
join=builder.join(self.package.waypoints.join),
|
||||
ingress=ingress,
|
||||
targets=[target],
|
||||
egress=egress,
|
||||
split=builder.split(self.package.waypoints.split),
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
def generate_cas(self, flight: Flight) -> CasFlightPlan:
|
||||
@@ -999,11 +1011,12 @@ class FlightPlanBuilder:
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
patrol_duration=self.doctrine.cas_duration,
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
patrol_start=builder.ingress_cas(ingress, location),
|
||||
target=builder.cas(center),
|
||||
patrol_end=builder.egress(egress, location),
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -1030,7 +1043,7 @@ class FlightPlanBuilder:
|
||||
|
||||
def _hold_point(self, flight: Flight) -> Point:
|
||||
assert self.package.waypoints is not None
|
||||
origin = flight.from_cp.position
|
||||
origin = flight.departure.position
|
||||
target = self.package.target.position
|
||||
join = self.package.waypoints.join
|
||||
origin_to_target = origin.distance_to_point(target)
|
||||
@@ -1118,14 +1131,15 @@ class FlightPlanBuilder:
|
||||
return StrikeFlightPlan(
|
||||
package=self.package,
|
||||
flight=flight,
|
||||
takeoff=builder.takeoff(flight.from_cp),
|
||||
takeoff=builder.takeoff(flight.departure),
|
||||
hold=builder.hold(self._hold_point(flight)),
|
||||
join=builder.join(self.package.waypoints.join),
|
||||
ingress=ingress,
|
||||
targets=target_waypoints,
|
||||
egress=builder.egress(self.package.waypoints.egress, location),
|
||||
split=builder.split(self.package.waypoints.split),
|
||||
land=builder.land(flight.from_cp)
|
||||
land=builder.land(flight.arrival),
|
||||
divert=builder.divert(flight.divert)
|
||||
)
|
||||
|
||||
def _retreating_rendezvous_point(self, attack_transition: Point) -> Point:
|
||||
@@ -1201,7 +1215,7 @@ class FlightPlanBuilder:
|
||||
)
|
||||
for airfield in cache.closest_airfields:
|
||||
for flight in self.package.flights:
|
||||
if flight.from_cp == airfield:
|
||||
if flight.departure == airfield:
|
||||
return airfield
|
||||
raise RuntimeError(
|
||||
"Could not find any airfield assigned to this package"
|
||||
|
||||
@@ -8,14 +8,13 @@ from dcs.unit import Unit
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game.data.doctrine import Doctrine
|
||||
from game.utils import feet_to_meter
|
||||
from game.weather import Conditions
|
||||
from theater import (
|
||||
from game.theater import (
|
||||
ControlPoint,
|
||||
MissionTarget,
|
||||
OffMapSpawn,
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.weather import Conditions
|
||||
from .flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
|
||||
|
||||
@@ -104,6 +103,40 @@ class WaypointBuilder:
|
||||
waypoint.pretty_name = "Land"
|
||||
return waypoint
|
||||
|
||||
def divert(self,
|
||||
divert: Optional[ControlPoint]) -> Optional[FlightWaypoint]:
|
||||
"""Create divert waypoint for the given arrival airfield or carrier.
|
||||
|
||||
Args:
|
||||
divert: Divert airfield or carrier.
|
||||
"""
|
||||
if divert is None:
|
||||
return None
|
||||
|
||||
position = divert.position
|
||||
if isinstance(divert, OffMapSpawn):
|
||||
if self.is_helo:
|
||||
altitude = 500
|
||||
else:
|
||||
altitude = self.doctrine.rendezvous_altitude
|
||||
altitude_type = "BARO"
|
||||
else:
|
||||
altitude = 0
|
||||
altitude_type = "RADIO"
|
||||
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.DIVERT,
|
||||
position.x,
|
||||
position.y,
|
||||
altitude
|
||||
)
|
||||
waypoint.alt_type = altitude_type
|
||||
waypoint.name = "DIVERT"
|
||||
waypoint.description = "Divert"
|
||||
waypoint.pretty_name = "Divert"
|
||||
waypoint.only_for_player = True
|
||||
return waypoint
|
||||
|
||||
def hold(self, position: Point) -> FlightWaypoint:
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.LOITER,
|
||||
|
||||
@@ -2,12 +2,12 @@ import random
|
||||
from enum import Enum
|
||||
from typing import Dict, List
|
||||
|
||||
from dcs.vehicles import Armor, Artillery, Infantry, Unarmed
|
||||
from dcs.unittype import VehicleType
|
||||
from dcs.vehicles import Armor, Artillery, Infantry, Unarmed
|
||||
|
||||
import pydcs_extensions.frenchpack.frenchpack as frenchpack
|
||||
from game.theater import ControlPoint
|
||||
from gen.ground_forces.combat_stance import CombatStance
|
||||
from theater import ControlPoint
|
||||
|
||||
TYPE_TANKS = [
|
||||
Armor.MBT_T_55,
|
||||
|
||||
@@ -20,14 +20,14 @@ from dcs.task import (
|
||||
EPLRS,
|
||||
OptAlarmState,
|
||||
)
|
||||
from dcs.unit import Ship, Vehicle, Unit
|
||||
from dcs.unit import Ship, Unit, Vehicle
|
||||
from dcs.unitgroup import Group, ShipGroup, StaticGroup
|
||||
from dcs.unittype import StaticType, UnitType
|
||||
|
||||
from game import db
|
||||
from game.data.building_data import FORTIFICATION_UNITS, FORTIFICATION_UNITS_ID
|
||||
from game.db import unit_type_from_name
|
||||
from theater import ControlPoint, TheaterGroundObject
|
||||
from game.theater import ControlPoint, TheaterGroundObject
|
||||
from game.theater.theatergroundobject import (
|
||||
BuildingGroundObject, CarrierGroundObject,
|
||||
GenericCarrierGroundObject,
|
||||
|
||||
@@ -7,8 +7,8 @@ from typing import Iterator, Optional
|
||||
|
||||
from dcs.terrain.terrain import Airport
|
||||
|
||||
from game.theater import ControlPoint, ControlPointType
|
||||
from game.weather import Conditions
|
||||
from theater import ControlPoint, ControlPointType
|
||||
from .airfields import AIRFIELD_DATA
|
||||
from .radios import RadioFrequency
|
||||
from .tacan import TacanChannel
|
||||
|
||||
Reference in New Issue
Block a user