mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Cleanup and refine airlift and airassault waypoints
- Drop Off and Pickup now correctly worded - Helo waypoints now represent LandingZones for pickup and dropoff
This commit is contained in:
parent
a47cb865fb
commit
b4b9bbf476
@ -4,8 +4,7 @@ from dataclasses import dataclass
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Iterator, TYPE_CHECKING, Type
|
from typing import Iterator, TYPE_CHECKING, Type
|
||||||
|
|
||||||
from game.ato.flightplans.airlift import AirliftLayout
|
from game.ato.flightplans.standard import StandardFlightPlan, StandardLayout
|
||||||
from game.ato.flightplans.standard import StandardFlightPlan
|
|
||||||
from game.theater.controlpoint import ControlPointType
|
from game.theater.controlpoint import ControlPointType
|
||||||
from game.theater.missiontarget import MissionTarget
|
from game.theater.missiontarget import MissionTarget
|
||||||
from game.utils import Distance, feet, meters
|
from game.utils import Distance, feet, meters
|
||||||
@ -17,13 +16,18 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class AirAssaultLayout(AirliftLayout):
|
class AirAssaultLayout(StandardLayout):
|
||||||
|
nav_to_pickup: list[FlightWaypoint]
|
||||||
|
pickup: FlightWaypoint | None
|
||||||
|
nav_to_drop_off: list[FlightWaypoint]
|
||||||
|
drop_off: FlightWaypoint
|
||||||
target: FlightWaypoint
|
target: FlightWaypoint
|
||||||
|
nav_to_home: list[FlightWaypoint]
|
||||||
|
|
||||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
yield self.departure
|
yield self.departure
|
||||||
yield from self.nav_to_pickup
|
yield from self.nav_to_pickup
|
||||||
if self.pickup:
|
if self.pickup is not None:
|
||||||
yield self.pickup
|
yield self.pickup
|
||||||
yield from self.nav_to_drop_off
|
yield from self.nav_to_drop_off
|
||||||
yield self.drop_off
|
yield self.drop_off
|
||||||
@ -81,19 +85,27 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
|||||||
pickup_position = self.flight.departure.position
|
pickup_position = self.flight.departure.position
|
||||||
else:
|
else:
|
||||||
# Create a special pickup zone for Helos from Airbase / FOB
|
# Create a special pickup zone for Helos from Airbase / FOB
|
||||||
pickup = builder.pickup(
|
pickup = builder.cargo_pickup(
|
||||||
MissionTarget(
|
MissionTarget(
|
||||||
"Pickup Zone",
|
"Pickup Zone",
|
||||||
self.flight.departure.position.random_point_within(1200, 600),
|
self.flight.departure.position.random_point_within(1200, 600),
|
||||||
)
|
),
|
||||||
|
self.flight.is_helo,
|
||||||
)
|
)
|
||||||
pickup_position = pickup.position
|
pickup_position = pickup.position
|
||||||
assault_area = builder.assault_area(self.package.target)
|
assault_area = builder.assault_area(self.package.target)
|
||||||
heading = self.package.target.position.heading_between_point(pickup_position)
|
heading = self.package.target.position.heading_between_point(pickup_position)
|
||||||
|
|
||||||
|
# Once there is a plane which is capable of AirDrop Paratrooper
|
||||||
|
# we can make use of the AIRDROP Wayppoint type.
|
||||||
|
# This would also need a special Waypointbuilder.
|
||||||
|
# Currently AirAssault can only be used by Helos so we just create
|
||||||
|
# the drop_off Landing Zone
|
||||||
drop_off_zone = MissionTarget(
|
drop_off_zone = MissionTarget(
|
||||||
"Dropoff zone",
|
"Dropoff zone",
|
||||||
self.package.target.position.point_from_heading(heading, 1200),
|
self.package.target.position.point_from_heading(heading, 1200),
|
||||||
)
|
)
|
||||||
|
drop_off = builder.cargo_dropoff(drop_off_zone, self.flight.is_helo)
|
||||||
|
|
||||||
return AirAssaultLayout(
|
return AirAssaultLayout(
|
||||||
departure=builder.takeoff(self.flight.departure),
|
departure=builder.takeoff(self.flight.departure),
|
||||||
@ -110,8 +122,7 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
|||||||
altitude,
|
altitude,
|
||||||
altitude_is_agl,
|
altitude_is_agl,
|
||||||
),
|
),
|
||||||
drop_off=builder.drop_off(drop_off_zone),
|
drop_off=drop_off,
|
||||||
refuel=None,
|
|
||||||
target=assault_area,
|
target=assault_area,
|
||||||
nav_to_home=builder.nav_path(
|
nav_to_home=builder.nav_path(
|
||||||
drop_off_zone.position,
|
drop_off_zone.position,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class AirliftLayout(StandardLayout):
|
|||||||
nav_to_pickup: list[FlightWaypoint]
|
nav_to_pickup: list[FlightWaypoint]
|
||||||
pickup: FlightWaypoint | None
|
pickup: FlightWaypoint | None
|
||||||
nav_to_drop_off: list[FlightWaypoint]
|
nav_to_drop_off: list[FlightWaypoint]
|
||||||
drop_off: FlightWaypoint
|
drop_off: FlightWaypoint | None
|
||||||
refuel: FlightWaypoint | None
|
refuel: FlightWaypoint | None
|
||||||
nav_to_home: list[FlightWaypoint]
|
nav_to_home: list[FlightWaypoint]
|
||||||
|
|
||||||
@ -31,7 +31,8 @@ class AirliftLayout(StandardLayout):
|
|||||||
if self.pickup is not None:
|
if self.pickup is not None:
|
||||||
yield self.pickup
|
yield self.pickup
|
||||||
yield from self.nav_to_drop_off
|
yield from self.nav_to_drop_off
|
||||||
yield self.drop_off
|
if self.drop_off is not None:
|
||||||
|
yield self.drop_off
|
||||||
if self.refuel is not None:
|
if self.refuel is not None:
|
||||||
yield self.refuel
|
yield self.refuel
|
||||||
yield from self.nav_to_home
|
yield from self.nav_to_home
|
||||||
@ -48,7 +49,7 @@ class AirliftFlightPlan(StandardFlightPlan[AirliftLayout]):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def tot_waypoint(self) -> FlightWaypoint:
|
def tot_waypoint(self) -> FlightWaypoint:
|
||||||
return self.layout.drop_off
|
return self.layout.drop_off or self.layout.arrival
|
||||||
|
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||||
# TOT planning isn't really useful for transports. They're behind the front
|
# TOT planning isn't really useful for transports. They're behind the front
|
||||||
@ -78,12 +79,13 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
|||||||
|
|
||||||
pickup = None
|
pickup = None
|
||||||
refuel = None
|
refuel = None
|
||||||
|
drop_off = None
|
||||||
if self.flight.is_helo:
|
if self.flight.is_helo:
|
||||||
# Create a pickupzone where the cargo will be spawned
|
# Create a pickupzone where the cargo will be spawned
|
||||||
pickup_zone = MissionTarget(
|
pickup_zone = MissionTarget(
|
||||||
"Pickup Zone", cargo.origin.position.random_point_within(1000, 200)
|
"Pickup Zone", cargo.origin.position.random_point_within(1000, 200)
|
||||||
)
|
)
|
||||||
pickup = builder.pickup(pickup_zone)
|
pickup = builder.cargo_pickup(pickup_zone, True)
|
||||||
# If The cargo is at the departure controlpoint, the pickup waypoint should
|
# If The cargo is at the departure controlpoint, the pickup waypoint should
|
||||||
# only be created for client flights
|
# only be created for client flights
|
||||||
pickup.only_for_player = cargo.origin == self.flight.departure
|
pickup.only_for_player = cargo.origin == self.flight.departure
|
||||||
@ -93,15 +95,16 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
|||||||
"Dropoff zone",
|
"Dropoff zone",
|
||||||
cargo.next_stop.position.random_point_within(1000, 200),
|
cargo.next_stop.position.random_point_within(1000, 200),
|
||||||
)
|
)
|
||||||
drop_off = builder.drop_off(drop_off_zone)
|
drop_off = builder.cargo_dropoff(drop_off_zone, True)
|
||||||
|
|
||||||
# Add an additional stopover point so that the flight can refuel
|
# Add an additional refuel waypoint
|
||||||
refuel = builder.land_refuel(cargo.next_stop)
|
refuel = builder.land_refuel(cargo.next_stop)
|
||||||
else:
|
else:
|
||||||
# Fixed Wing will get stopover points for pickup and dropoff
|
# Fixed Wing will get landing&refuel waypoints for pickup and dropoff
|
||||||
if cargo.origin != self.flight.departure:
|
if cargo.origin != self.flight.departure:
|
||||||
pickup = builder.land_refuel(cargo.origin)
|
pickup = builder.cargo_pickup(cargo.origin, False)
|
||||||
drop_off = builder.land_refuel(cargo.next_stop)
|
if cargo.next_stop != self.flight.arrival:
|
||||||
|
drop_off = builder.cargo_dropoff(cargo.next_stop, False)
|
||||||
|
|
||||||
nav_to_pickup = builder.nav_path(
|
nav_to_pickup = builder.nav_path(
|
||||||
self.flight.departure.position,
|
self.flight.departure.position,
|
||||||
@ -114,7 +117,7 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
|||||||
# Normal Landing Waypoint
|
# Normal Landing Waypoint
|
||||||
arrival = builder.land(self.flight.arrival)
|
arrival = builder.land(self.flight.arrival)
|
||||||
else:
|
else:
|
||||||
# The AI Needs another Stopover point to actually fly back to the original
|
# The AI Needs another landing&refuel point to actually fly back to the original
|
||||||
# base. Otherwise the Cargo drop will be the new Landing Waypoint and the
|
# base. Otherwise the Cargo drop will be the new Landing Waypoint and the
|
||||||
# AI will end its mission there instead of flying back.
|
# AI will end its mission there instead of flying back.
|
||||||
# https://forum.dcs.world/topic/211775-landing-to-refuel-and-rearm-the-landingrefuar-waypoint/
|
# https://forum.dcs.world/topic/211775-landing-to-refuel-and-rearm-the-landingrefuar-waypoint/
|
||||||
|
|||||||
@ -526,40 +526,65 @@ class WaypointBuilder:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pickup(pick_up: MissionTarget) -> FlightWaypoint:
|
def cargo_pickup(pick_up: MissionTarget, is_helo: bool) -> FlightWaypoint:
|
||||||
"""Creates a cargo pickup waypoint.
|
"""Creates a cargo pickup waypoint.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
control_point: Pick up location.
|
control_point: Pick up location.
|
||||||
"""
|
"""
|
||||||
control_point = pick_up if isinstance(pick_up, ControlPoint) else None
|
control_point = pick_up if isinstance(pick_up, ControlPoint) else None
|
||||||
|
if is_helo:
|
||||||
|
return FlightWaypoint(
|
||||||
|
"PICKUP",
|
||||||
|
FlightWaypointType.PICKUP_ZONE,
|
||||||
|
pick_up.position,
|
||||||
|
meters(0),
|
||||||
|
"RADIO",
|
||||||
|
description=f"Pick up cargo from {pick_up.name}",
|
||||||
|
pretty_name="Pick-up zone",
|
||||||
|
control_point=control_point,
|
||||||
|
)
|
||||||
return FlightWaypoint(
|
return FlightWaypoint(
|
||||||
"PICKUP",
|
"PICKUP",
|
||||||
FlightWaypointType.PICKUP,
|
FlightWaypointType.LAND_REFUEL,
|
||||||
pick_up.position,
|
pick_up.position,
|
||||||
meters(0),
|
meters(0),
|
||||||
"RADIO",
|
"RADIO",
|
||||||
description=f"Pick up cargo from {pick_up.name}",
|
description=f"Pick up cargo from {pick_up.name}",
|
||||||
pretty_name="Pick up location",
|
pretty_name="Cargo pick-up",
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def drop_off(drop_off: MissionTarget) -> FlightWaypoint:
|
def cargo_dropoff(drop_off: MissionTarget, is_helo: bool) -> FlightWaypoint:
|
||||||
"""Creates a cargo drop-off waypoint.
|
"""Creates a cargo drop-off waypoint.
|
||||||
|
This waypoint is used by AirLift and AirAssault to drop cargo or troops
|
||||||
|
at the given location
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
control_point: Drop-off location.
|
control_point: Drop-off location.
|
||||||
|
is_helo: Differentiate behaviour between plane and helo
|
||||||
"""
|
"""
|
||||||
control_point = drop_off if isinstance(drop_off, ControlPoint) else None
|
control_point = drop_off if isinstance(drop_off, ControlPoint) else None
|
||||||
|
if is_helo:
|
||||||
|
return FlightWaypoint(
|
||||||
|
"DROPOFF",
|
||||||
|
FlightWaypointType.DROPOFF_ZONE,
|
||||||
|
drop_off.position,
|
||||||
|
meters(0),
|
||||||
|
"RADIO",
|
||||||
|
description=f"Drop off cargo at {drop_off.name}",
|
||||||
|
pretty_name="Drop-off zone",
|
||||||
|
control_point=control_point,
|
||||||
|
)
|
||||||
return FlightWaypoint(
|
return FlightWaypoint(
|
||||||
"DROP OFF",
|
"DROPOFF",
|
||||||
FlightWaypointType.DROP_OFF,
|
FlightWaypointType.LAND_REFUEL,
|
||||||
drop_off.position,
|
drop_off.position,
|
||||||
meters(0),
|
meters(0),
|
||||||
"RADIO",
|
"RADIO",
|
||||||
description=f"Drop off cargo at {drop_off.name}",
|
description=f"Drop off cargo at {drop_off.name}",
|
||||||
pretty_name="Drop off location",
|
pretty_name="Cargo drop-off",
|
||||||
control_point=control_point,
|
control_point=control_point,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -43,8 +43,8 @@ class FlightWaypointType(IntEnum):
|
|||||||
DIVERT = 23
|
DIVERT = 23
|
||||||
INGRESS_OCA_RUNWAY = 24
|
INGRESS_OCA_RUNWAY = 24
|
||||||
INGRESS_OCA_AIRCRAFT = 25
|
INGRESS_OCA_AIRCRAFT = 25
|
||||||
PICKUP = 26
|
PICKUP_ZONE = 26 # Pickup Zone for cargo or troops
|
||||||
DROP_OFF = 27
|
DROPOFF_ZONE = 27 # Dropoff Zone for cargo or troops
|
||||||
BULLSEYE = 28
|
BULLSEYE = 28
|
||||||
REFUEL = 29 # Should look for nearby tanker to refuel from.
|
REFUEL = 29 # Should look for nearby tanker to refuel from.
|
||||||
CARGO_STOP = 30 # Stopover landing point using the LandingReFuAr waypoint type
|
CARGO_STOP = 30 # Stopover landing point using the LandingReFuAr waypoint type
|
||||||
|
|||||||
17
game/missiongenerator/aircraft/waypoints/landingzone.py
Normal file
17
game/missiongenerator/aircraft/waypoints/landingzone.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from dcs.point import MovingPoint
|
||||||
|
from dcs.task import Land
|
||||||
|
|
||||||
|
|
||||||
|
from .pydcswaypointbuilder import PydcsWaypointBuilder
|
||||||
|
|
||||||
|
|
||||||
|
class LandingZoneBuilder(PydcsWaypointBuilder):
|
||||||
|
def build(self) -> MovingPoint:
|
||||||
|
waypoint = super().build()
|
||||||
|
# Create a landing task, currently only for Helos!
|
||||||
|
# Calculate a landing point with a small buffer to prevent AI from landing
|
||||||
|
# directly at the static ammo depot and exploding
|
||||||
|
landing_point = waypoint.position.random_point_within(15, 5)
|
||||||
|
# Use Land Task with 30s duration for helos
|
||||||
|
waypoint.add_task(Land(landing_point, duration=30))
|
||||||
|
return waypoint
|
||||||
@ -21,7 +21,7 @@ from game.missiongenerator.missiondata import MissionData
|
|||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
from game.utils import pairwise
|
from game.utils import pairwise
|
||||||
from .baiingress import BaiIngressBuilder
|
from .baiingress import BaiIngressBuilder
|
||||||
from .cargostop import CargoStopBuilder
|
from .landingzone import LandingZoneBuilder
|
||||||
from .casingress import CasIngressBuilder
|
from .casingress import CasIngressBuilder
|
||||||
from .deadingress import DeadIngressBuilder
|
from .deadingress import DeadIngressBuilder
|
||||||
from .default import DefaultWaypointBuilder
|
from .default import DefaultWaypointBuilder
|
||||||
@ -118,7 +118,6 @@ class WaypointGenerator:
|
|||||||
|
|
||||||
def builder_for_waypoint(self, waypoint: FlightWaypoint) -> PydcsWaypointBuilder:
|
def builder_for_waypoint(self, waypoint: FlightWaypoint) -> PydcsWaypointBuilder:
|
||||||
builders = {
|
builders = {
|
||||||
FlightWaypointType.DROP_OFF: CargoStopBuilder,
|
|
||||||
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
||||||
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
||||||
@ -133,7 +132,8 @@ class WaypointGenerator:
|
|||||||
FlightWaypointType.LOITER: HoldPointBuilder,
|
FlightWaypointType.LOITER: HoldPointBuilder,
|
||||||
FlightWaypointType.PATROL: RaceTrackEndBuilder,
|
FlightWaypointType.PATROL: RaceTrackEndBuilder,
|
||||||
FlightWaypointType.PATROL_TRACK: RaceTrackBuilder,
|
FlightWaypointType.PATROL_TRACK: RaceTrackBuilder,
|
||||||
FlightWaypointType.PICKUP: CargoStopBuilder,
|
FlightWaypointType.PICKUP_ZONE: LandingZoneBuilder,
|
||||||
|
FlightWaypointType.DROPOFF_ZONE: LandingZoneBuilder,
|
||||||
FlightWaypointType.REFUEL: RefuelPointBuilder,
|
FlightWaypointType.REFUEL: RefuelPointBuilder,
|
||||||
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
|
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,8 +56,8 @@ class LogisticsGenerator:
|
|||||||
if (
|
if (
|
||||||
waypoint.waypoint_type
|
waypoint.waypoint_type
|
||||||
not in [
|
not in [
|
||||||
FlightWaypointType.PICKUP,
|
FlightWaypointType.PICKUP_ZONE,
|
||||||
FlightWaypointType.DROP_OFF,
|
FlightWaypointType.DROPOFF_ZONE,
|
||||||
]
|
]
|
||||||
or waypoint.only_for_player
|
or waypoint.only_for_player
|
||||||
and not self.flight.client_count
|
and not self.flight.client_count
|
||||||
@ -68,7 +68,7 @@ class LogisticsGenerator:
|
|||||||
self.mission.triggers.add_triggerzone(
|
self.mission.triggers.add_triggerzone(
|
||||||
waypoint.position, ZONE_RADIUS, False, zone_name
|
waypoint.position, ZONE_RADIUS, False, zone_name
|
||||||
)
|
)
|
||||||
if waypoint.waypoint_type == FlightWaypointType.PICKUP:
|
if waypoint.waypoint_type == FlightWaypointType.PICKUP_ZONE:
|
||||||
pickup_point = waypoint.position
|
pickup_point = waypoint.position
|
||||||
logistics_info.pickup_zone = zone_name
|
logistics_info.pickup_zone = zone_name
|
||||||
else:
|
else:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user