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 typing import Iterator, TYPE_CHECKING, Type
|
||||
|
||||
from game.ato.flightplans.airlift import AirliftLayout
|
||||
from game.ato.flightplans.standard import StandardFlightPlan
|
||||
from game.ato.flightplans.standard import StandardFlightPlan, StandardLayout
|
||||
from game.theater.controlpoint import ControlPointType
|
||||
from game.theater.missiontarget import MissionTarget
|
||||
from game.utils import Distance, feet, meters
|
||||
@ -17,13 +16,18 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
@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
|
||||
nav_to_home: list[FlightWaypoint]
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
yield from self.nav_to_pickup
|
||||
if self.pickup:
|
||||
if self.pickup is not None:
|
||||
yield self.pickup
|
||||
yield from self.nav_to_drop_off
|
||||
yield self.drop_off
|
||||
@ -81,19 +85,27 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
||||
pickup_position = self.flight.departure.position
|
||||
else:
|
||||
# Create a special pickup zone for Helos from Airbase / FOB
|
||||
pickup = builder.pickup(
|
||||
pickup = builder.cargo_pickup(
|
||||
MissionTarget(
|
||||
"Pickup Zone",
|
||||
self.flight.departure.position.random_point_within(1200, 600),
|
||||
)
|
||||
),
|
||||
self.flight.is_helo,
|
||||
)
|
||||
pickup_position = pickup.position
|
||||
assault_area = builder.assault_area(self.package.target)
|
||||
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(
|
||||
"Dropoff zone",
|
||||
self.package.target.position.point_from_heading(heading, 1200),
|
||||
)
|
||||
drop_off = builder.cargo_dropoff(drop_off_zone, self.flight.is_helo)
|
||||
|
||||
return AirAssaultLayout(
|
||||
departure=builder.takeoff(self.flight.departure),
|
||||
@ -110,8 +122,7 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
||||
altitude,
|
||||
altitude_is_agl,
|
||||
),
|
||||
drop_off=builder.drop_off(drop_off_zone),
|
||||
refuel=None,
|
||||
drop_off=drop_off,
|
||||
target=assault_area,
|
||||
nav_to_home=builder.nav_path(
|
||||
drop_off_zone.position,
|
||||
|
||||
@ -21,7 +21,7 @@ class AirliftLayout(StandardLayout):
|
||||
nav_to_pickup: list[FlightWaypoint]
|
||||
pickup: FlightWaypoint | None
|
||||
nav_to_drop_off: list[FlightWaypoint]
|
||||
drop_off: FlightWaypoint
|
||||
drop_off: FlightWaypoint | None
|
||||
refuel: FlightWaypoint | None
|
||||
nav_to_home: list[FlightWaypoint]
|
||||
|
||||
@ -31,6 +31,7 @@ class AirliftLayout(StandardLayout):
|
||||
if self.pickup is not None:
|
||||
yield self.pickup
|
||||
yield from self.nav_to_drop_off
|
||||
if self.drop_off is not None:
|
||||
yield self.drop_off
|
||||
if self.refuel is not None:
|
||||
yield self.refuel
|
||||
@ -48,7 +49,7 @@ class AirliftFlightPlan(StandardFlightPlan[AirliftLayout]):
|
||||
|
||||
@property
|
||||
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:
|
||||
# TOT planning isn't really useful for transports. They're behind the front
|
||||
@ -78,12 +79,13 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
||||
|
||||
pickup = None
|
||||
refuel = None
|
||||
drop_off = None
|
||||
if self.flight.is_helo:
|
||||
# Create a pickupzone where the cargo will be spawned
|
||||
pickup_zone = MissionTarget(
|
||||
"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
|
||||
# only be created for client flights
|
||||
pickup.only_for_player = cargo.origin == self.flight.departure
|
||||
@ -93,15 +95,16 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
||||
"Dropoff zone",
|
||||
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)
|
||||
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:
|
||||
pickup = builder.land_refuel(cargo.origin)
|
||||
drop_off = builder.land_refuel(cargo.next_stop)
|
||||
pickup = builder.cargo_pickup(cargo.origin, False)
|
||||
if cargo.next_stop != self.flight.arrival:
|
||||
drop_off = builder.cargo_dropoff(cargo.next_stop, False)
|
||||
|
||||
nav_to_pickup = builder.nav_path(
|
||||
self.flight.departure.position,
|
||||
@ -114,7 +117,7 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
|
||||
# Normal Landing Waypoint
|
||||
arrival = builder.land(self.flight.arrival)
|
||||
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
|
||||
# AI will end its mission there instead of flying back.
|
||||
# https://forum.dcs.world/topic/211775-landing-to-refuel-and-rearm-the-landingrefuar-waypoint/
|
||||
|
||||
@ -526,40 +526,65 @@ class WaypointBuilder:
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def pickup(pick_up: MissionTarget) -> FlightWaypoint:
|
||||
def cargo_pickup(pick_up: MissionTarget, is_helo: bool) -> FlightWaypoint:
|
||||
"""Creates a cargo pickup waypoint.
|
||||
|
||||
Args:
|
||||
control_point: Pick up location.
|
||||
"""
|
||||
control_point = pick_up if isinstance(pick_up, ControlPoint) else None
|
||||
if is_helo:
|
||||
return FlightWaypoint(
|
||||
"PICKUP",
|
||||
FlightWaypointType.PICKUP,
|
||||
FlightWaypointType.PICKUP_ZONE,
|
||||
pick_up.position,
|
||||
meters(0),
|
||||
"RADIO",
|
||||
description=f"Pick up cargo from {pick_up.name}",
|
||||
pretty_name="Pick up location",
|
||||
pretty_name="Pick-up zone",
|
||||
control_point=control_point,
|
||||
)
|
||||
return FlightWaypoint(
|
||||
"PICKUP",
|
||||
FlightWaypointType.LAND_REFUEL,
|
||||
pick_up.position,
|
||||
meters(0),
|
||||
"RADIO",
|
||||
description=f"Pick up cargo from {pick_up.name}",
|
||||
pretty_name="Cargo pick-up",
|
||||
control_point=control_point,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def drop_off(drop_off: MissionTarget) -> FlightWaypoint:
|
||||
def cargo_dropoff(drop_off: MissionTarget, is_helo: bool) -> FlightWaypoint:
|
||||
"""Creates a cargo drop-off waypoint.
|
||||
This waypoint is used by AirLift and AirAssault to drop cargo or troops
|
||||
at the given location
|
||||
|
||||
Args:
|
||||
control_point: Drop-off location.
|
||||
is_helo: Differentiate behaviour between plane and helo
|
||||
"""
|
||||
control_point = drop_off if isinstance(drop_off, ControlPoint) else None
|
||||
if is_helo:
|
||||
return FlightWaypoint(
|
||||
"DROPOFF",
|
||||
FlightWaypointType.DROP_OFF,
|
||||
FlightWaypointType.DROPOFF_ZONE,
|
||||
drop_off.position,
|
||||
meters(0),
|
||||
"RADIO",
|
||||
description=f"Drop off cargo at {drop_off.name}",
|
||||
pretty_name="Drop off location",
|
||||
pretty_name="Drop-off zone",
|
||||
control_point=control_point,
|
||||
)
|
||||
return FlightWaypoint(
|
||||
"DROPOFF",
|
||||
FlightWaypointType.LAND_REFUEL,
|
||||
drop_off.position,
|
||||
meters(0),
|
||||
"RADIO",
|
||||
description=f"Drop off cargo at {drop_off.name}",
|
||||
pretty_name="Cargo drop-off",
|
||||
control_point=control_point,
|
||||
)
|
||||
|
||||
|
||||
@ -43,8 +43,8 @@ class FlightWaypointType(IntEnum):
|
||||
DIVERT = 23
|
||||
INGRESS_OCA_RUNWAY = 24
|
||||
INGRESS_OCA_AIRCRAFT = 25
|
||||
PICKUP = 26
|
||||
DROP_OFF = 27
|
||||
PICKUP_ZONE = 26 # Pickup Zone for cargo or troops
|
||||
DROPOFF_ZONE = 27 # Dropoff Zone for cargo or troops
|
||||
BULLSEYE = 28
|
||||
REFUEL = 29 # Should look for nearby tanker to refuel from.
|
||||
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.utils import pairwise
|
||||
from .baiingress import BaiIngressBuilder
|
||||
from .cargostop import CargoStopBuilder
|
||||
from .landingzone import LandingZoneBuilder
|
||||
from .casingress import CasIngressBuilder
|
||||
from .deadingress import DeadIngressBuilder
|
||||
from .default import DefaultWaypointBuilder
|
||||
@ -118,7 +118,6 @@ class WaypointGenerator:
|
||||
|
||||
def builder_for_waypoint(self, waypoint: FlightWaypoint) -> PydcsWaypointBuilder:
|
||||
builders = {
|
||||
FlightWaypointType.DROP_OFF: CargoStopBuilder,
|
||||
FlightWaypointType.INGRESS_BAI: BaiIngressBuilder,
|
||||
FlightWaypointType.INGRESS_CAS: CasIngressBuilder,
|
||||
FlightWaypointType.INGRESS_DEAD: DeadIngressBuilder,
|
||||
@ -133,7 +132,8 @@ class WaypointGenerator:
|
||||
FlightWaypointType.LOITER: HoldPointBuilder,
|
||||
FlightWaypointType.PATROL: RaceTrackEndBuilder,
|
||||
FlightWaypointType.PATROL_TRACK: RaceTrackBuilder,
|
||||
FlightWaypointType.PICKUP: CargoStopBuilder,
|
||||
FlightWaypointType.PICKUP_ZONE: LandingZoneBuilder,
|
||||
FlightWaypointType.DROPOFF_ZONE: LandingZoneBuilder,
|
||||
FlightWaypointType.REFUEL: RefuelPointBuilder,
|
||||
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
|
||||
}
|
||||
|
||||
@ -56,8 +56,8 @@ class LogisticsGenerator:
|
||||
if (
|
||||
waypoint.waypoint_type
|
||||
not in [
|
||||
FlightWaypointType.PICKUP,
|
||||
FlightWaypointType.DROP_OFF,
|
||||
FlightWaypointType.PICKUP_ZONE,
|
||||
FlightWaypointType.DROPOFF_ZONE,
|
||||
]
|
||||
or waypoint.only_for_player
|
||||
and not self.flight.client_count
|
||||
@ -68,7 +68,7 @@ class LogisticsGenerator:
|
||||
self.mission.triggers.add_triggerzone(
|
||||
waypoint.position, ZONE_RADIUS, False, zone_name
|
||||
)
|
||||
if waypoint.waypoint_type == FlightWaypointType.PICKUP:
|
||||
if waypoint.waypoint_type == FlightWaypointType.PICKUP_ZONE:
|
||||
pickup_point = waypoint.position
|
||||
logistics_info.pickup_zone = zone_name
|
||||
else:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user