Helicopter waypoint altitude configurable (#207)

* Helicopter waypoint altitude configurable

Added a new option in Settings: Helicopter waypoint altitude (feet AGL).
It sets the waypoint altitude for helicopters in feet AGL. In campaigns in more mountainous areas, you might want to increase this setting to avoid the AI flying into the terrain.

* black?

* Distinguish cruise/combat altitudes for helicopters

Also includes a refactor for WaypointBuilder so it doesn't need a coalition. It can already reference the coalition from the flight.

* Update changelog.md

---------

Co-authored-by: Raffson <Raffson@users.noreply.github.com>
This commit is contained in:
MetalStormGhost 2023-10-02 19:54:21 +03:00 committed by GitHub
parent 226a171550
commit 54777a9045
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 123 additions and 50 deletions

View File

@ -19,6 +19,7 @@
* **[Campaign Management]** Improve squadron retreat logic to account for parking-slot sizes * **[Campaign Management]** Improve squadron retreat logic to account for parking-slot sizes
* **[Autoplanner]** Support for auto-planning Air Assaults * **[Autoplanner]** Support for auto-planning Air Assaults
* **[UI]** Improved frequency selector to support all modeled bands for every aircraft's intra-flight radio * **[UI]** Improved frequency selector to support all modeled bands for every aircraft's intra-flight radio
* **[Options]** New options in Settings: Helicopter waypoint altitude (feet AGL) for combat & cruise waypoints
## Fixes ## Fixes
* **[Mission Generation]** Anti-ship strikes should use "group attack" in their attack-task * **[Mission Generation]** Anti-ship strikes should use "group attack" in their attack-task

View File

@ -49,7 +49,7 @@ class Builder(IBuilder[AewcFlightPlan, PatrollingLayout]):
# Station 80nm outside the threat zone. # Station 80nm outside the threat zone.
threat_buffer = nautical_miles( threat_buffer = nautical_miles(
self.flight.coalition.game.settings.aewc_threat_buffer_min_distance self.coalition.game.settings.aewc_threat_buffer_min_distance
) )
if self.threat_zones.threatened(location.position): if self.threat_zones.threatened(location.position):
orbit_distance = distance_to_threat + threat_buffer orbit_distance = distance_to_threat + threat_buffer
@ -68,7 +68,7 @@ class Builder(IBuilder[AewcFlightPlan, PatrollingLayout]):
orbit_heading.left.degrees, racetrack_half_distance orbit_heading.left.degrees, racetrack_half_distance
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
if self.flight.unit_type.patrol_altitude is not None: if self.flight.unit_type.patrol_altitude is not None:
altitude = self.flight.unit_type.patrol_altitude altitude = self.flight.unit_type.patrol_altitude

View File

@ -105,10 +105,11 @@ class Builder(FormationAttackBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
) )
assert self.package.waypoints is not None assert self.package.waypoints is not None
altitude = feet(1500) if self.flight.is_helo else self.doctrine.ingress_altitude heli_alt = feet(self.coalition.game.settings.heli_cruise_alt_agl)
altitude = heli_alt if self.flight.is_helo else self.doctrine.ingress_altitude
altitude_is_agl = self.flight.is_helo altitude_is_agl = self.flight.is_helo
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
if self.flight.is_hercules or self.flight.departure.cptype in [ if self.flight.is_hercules or self.flight.departure.cptype in [
ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.AIRCRAFT_CARRIER_GROUP,

View File

@ -110,10 +110,11 @@ class Builder(IBuilder[AirliftFlightPlan, AirliftLayout]):
"Cannot plan transport mission for flight with no cargo." "Cannot plan transport mission for flight with no cargo."
) )
altitude = feet(1500) heli_alt = feet(self.coalition.game.settings.heli_cruise_alt_agl)
altitude_is_agl = True altitude = heli_alt if self.flight.is_helo else self.doctrine.ingress_altitude
altitude_is_agl = self.flight.is_helo
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
pickup = None pickup = None
drop_off = None drop_off = None

View File

@ -48,7 +48,7 @@ class Builder(CapBuilder[BarCapFlightPlan, PatrollingLayout]):
min(self.doctrine.max_patrol_altitude, randomized_alt), min(self.doctrine.max_patrol_altitude, randomized_alt),
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
start, end = builder.race_track(start_pos, end_pos, patrol_alt) start, end = builder.race_track(start_pos, end_pos, patrol_alt)
return PatrollingLayout( return PatrollingLayout(

View File

@ -6,7 +6,7 @@ from datetime import timedelta
from typing import TYPE_CHECKING, Type from typing import TYPE_CHECKING, Type
from game.theater import FrontLine from game.theater import FrontLine
from game.utils import Distance, Speed, kph, meters, nautical_miles from game.utils import Distance, Speed, kph, feet, nautical_miles
from .ibuilder import IBuilder from .ibuilder import IBuilder
from .invalidobjectivelocation import InvalidObjectiveLocation from .invalidobjectivelocation import InvalidObjectiveLocation
from .patrolling import PatrollingFlightPlan, PatrollingLayout from .patrolling import PatrollingFlightPlan, PatrollingLayout
@ -97,11 +97,13 @@ class Builder(IBuilder[CasFlightPlan, CasLayout]):
if egress_distance < ingress_distance: if egress_distance < ingress_distance:
ingress, egress = egress, ingress ingress, egress = egress, ingress
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
is_helo = self.flight.unit_type.dcs_unit_type.helicopter is_helo = self.flight.unit_type.dcs_unit_type.helicopter
ingress_egress_altitude = ( ingress_egress_altitude = (
self.doctrine.ingress_altitude if not is_helo else meters(50) self.doctrine.ingress_altitude
if not is_helo
else feet(self.coalition.game.settings.heli_combat_alt_agl)
) )
use_agl_ingress_egress = is_helo use_agl_ingress_egress = is_helo

View File

@ -69,7 +69,7 @@ class Builder(IBuilder[CustomFlightPlan, CustomLayout]):
self.waypoints = waypoints self.waypoints = waypoints
def layout(self) -> CustomLayout: def layout(self) -> CustomLayout:
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
return CustomLayout(builder.takeoff(self.flight.departure), self.waypoints) return CustomLayout(builder.takeoff(self.flight.departure), self.waypoints)
def build(self) -> CustomFlightPlan: def build(self) -> CustomFlightPlan:

View File

@ -39,7 +39,7 @@ class Builder(FormationAttackBuilder[EscortFlightPlan, FormationAttackLayout]):
def layout(self) -> FormationAttackLayout: def layout(self) -> FormationAttackLayout:
assert self.package.waypoints is not None assert self.package.waypoints is not None
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
ingress, target = builder.escort( ingress, target = builder.escort(
self.package.waypoints.ingress, self.package.target self.package.waypoints.ingress, self.package.target
) )
@ -58,11 +58,11 @@ class Builder(FormationAttackBuilder[EscortFlightPlan, FormationAttackLayout]):
split = builder.split(self.package.waypoints.split) split = builder.split(self.package.waypoints.split)
ingress_alt = self.doctrine.ingress_altitude ingress_alt = self.doctrine.ingress_altitude
is_helo = builder.flight.is_helo
heli_alt = feet(self.coalition.game.settings.heli_combat_alt_agl)
initial = builder.escort_hold( initial = builder.escort_hold(
target.position target.position if is_helo else self.package.waypoints.initial,
if builder.flight.is_helo min(heli_alt, ingress_alt) if is_helo else ingress_alt,
else self.package.waypoints.initial,
min(feet(500), ingress_alt) if builder.flight.is_helo else ingress_alt,
) )
pf = self.package.primary_flight pf = self.package.primary_flight

View File

@ -56,14 +56,14 @@ class Builder(IBuilder[FerryFlightPlan, FerryLayout]):
f"{self.flight.departure}" f"{self.flight.departure}"
) )
altitude_is_agl = self.flight.unit_type.dcs_unit_type.helicopter altitude_is_agl = self.flight.is_helo
altitude = ( altitude = (
feet(1500) feet(self.coalition.game.settings.heli_cruise_alt_agl)
if altitude_is_agl if altitude_is_agl
else self.flight.unit_type.preferred_patrol_altitude else self.flight.unit_type.preferred_patrol_altitude
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
return FerryLayout( return FerryLayout(
departure=builder.takeoff(self.flight.departure), departure=builder.takeoff(self.flight.departure),
nav_to=builder.nav_path( nav_to=builder.nav_path(

View File

@ -10,7 +10,7 @@ from dcs import Point
from game.flightplan import HoldZoneGeometry from game.flightplan import HoldZoneGeometry
from game.theater import MissionTarget from game.theater import MissionTarget
from game.utils import Speed, meters, nautical_miles from game.utils import Speed, meters, nautical_miles, feet
from .flightplan import FlightPlan from .flightplan import FlightPlan
from .formation import FormationFlightPlan, FormationLayout from .formation import FormationFlightPlan, FormationLayout
from .ibuilder import IBuilder from .ibuilder import IBuilder
@ -170,7 +170,7 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
targets: list[StrikeTarget] | None = None, targets: list[StrikeTarget] | None = None,
) -> FormationAttackLayout: ) -> FormationAttackLayout:
assert self.package.waypoints is not None assert self.package.waypoints is not None
builder = WaypointBuilder(self.flight, self.coalition, targets) builder = WaypointBuilder(self.flight, targets)
target_waypoints: list[FlightWaypoint] = [] target_waypoints: list[FlightWaypoint] = []
if targets is not None: if targets is not None:
@ -209,13 +209,22 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
pos = ingress.position.point_from_heading(hdg, nautical_miles(10).meters) pos = ingress.position.point_from_heading(hdg, nautical_miles(10).meters)
lineup = builder.nav(pos, self.flight.coalition.doctrine.ingress_altitude) lineup = builder.nav(pos, self.flight.coalition.doctrine.ingress_altitude)
is_helo = self.flight.is_helo
ingress_egress_altitude = (
self.doctrine.ingress_altitude
if not is_helo
else feet(self.coalition.game.settings.heli_combat_alt_agl)
)
use_agl_ingress_egress = is_helo
return FormationAttackLayout( return FormationAttackLayout(
departure=builder.takeoff(self.flight.departure), departure=builder.takeoff(self.flight.departure),
hold=hold, hold=hold,
nav_to=builder.nav_path( nav_to=builder.nav_path(
hold.position if hold else self.flight.departure.position, hold.position if hold else self.flight.departure.position,
join.position if join else ingress.position, join.position if join else ingress.position,
self.doctrine.ingress_altitude, ingress_egress_altitude,
use_agl_ingress_egress,
), ),
join=join, join=join,
lineup=lineup, lineup=lineup,
@ -227,7 +236,8 @@ class FormationAttackBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
nav_from=builder.nav_path( nav_from=builder.nav_path(
refuel.position if refuel else split.position, refuel.position if refuel else split.position,
self.flight.arrival.position, self.flight.arrival.position,
self.doctrine.ingress_altitude, ingress_egress_altitude,
use_agl_ingress_egress,
), ),
arrival=builder.land(self.flight.arrival), arrival=builder.land(self.flight.arrival),
divert=builder.divert(self.flight.divert), divert=builder.divert(self.flight.divert),

View File

@ -96,7 +96,7 @@ class Builder(IBuilder[PackageRefuelingFlightPlan, PatrollingLayout]):
home_heading.degrees, racetrack_half_distance home_heading.degrees, racetrack_half_distance
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
tanker_type = self.flight.unit_type tanker_type = self.flight.unit_type
if tanker_type.patrol_altitude is not None: if tanker_type.patrol_altitude is not None:

View File

@ -61,13 +61,13 @@ class Builder(IBuilder[RtbFlightPlan, RtbLayout]):
current_position = self.flight.state.estimate_position() current_position = self.flight.state.estimate_position()
current_altitude, altitude_reference = self.flight.state.estimate_altitude() current_altitude, altitude_reference = self.flight.state.estimate_altitude()
altitude_is_agl = self.flight.unit_type.dcs_unit_type.helicopter altitude_is_agl = self.flight.is_helo
altitude = ( altitude = (
feet(1500) feet(self.coalition.game.settings.heli_cruise_alt_agl)
if altitude_is_agl if altitude_is_agl
else self.flight.unit_type.preferred_patrol_altitude else self.flight.unit_type.preferred_patrol_altitude
) )
builder = WaypointBuilder(self.flight, self.flight.coalition) builder = WaypointBuilder(self.flight)
abort_point = builder.nav( abort_point = builder.nav(
current_position, current_altitude, altitude_reference == "RADIO" current_position, current_altitude, altitude_reference == "RADIO"
) )

View File

@ -101,7 +101,7 @@ class Builder(IBuilder[SweepFlightPlan, SweepLayout]):
heading.degrees, -self.doctrine.sweep_distance.meters heading.degrees, -self.doctrine.sweep_distance.meters
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
start, end = builder.sweep(start_pos, target, self.doctrine.ingress_altitude) start, end = builder.sweep(start_pos, target, self.doctrine.ingress_altitude)
hold = builder.hold(self._hold_point()) hold = builder.hold(self._hold_point())

View File

@ -102,7 +102,7 @@ class Builder(CapBuilder[TarCapFlightPlan, TarCapLayout]):
min(self.doctrine.max_patrol_altitude, randomized_alt), min(self.doctrine.max_patrol_altitude, randomized_alt),
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
orbit0p, orbit1p = self.cap_racetrack_for_objective(location, barcap=False) orbit0p, orbit1p = self.cap_racetrack_for_objective(location, barcap=False)
start, end = builder.race_track(orbit0p, orbit1p, patrol_alt) start, end = builder.race_track(orbit0p, orbit1p, patrol_alt)

View File

@ -37,7 +37,7 @@ class Builder(IBuilder[TheaterRefuelingFlightPlan, PatrollingLayout]):
# Station 70nm outside the threat zone. # Station 70nm outside the threat zone.
threat_buffer = nautical_miles( threat_buffer = nautical_miles(
self.flight.coalition.game.settings.tanker_threat_buffer_min_distance self.coalition.game.settings.tanker_threat_buffer_min_distance
) )
if self.threat_zones.threatened(location.position): if self.threat_zones.threatened(location.position):
orbit_distance = distance_to_threat + threat_buffer orbit_distance = distance_to_threat + threat_buffer
@ -56,7 +56,7 @@ class Builder(IBuilder[TheaterRefuelingFlightPlan, PatrollingLayout]):
orbit_heading.left.degrees, racetrack_half_distance orbit_heading.left.degrees, racetrack_half_distance
) )
builder = WaypointBuilder(self.flight, self.coalition) builder = WaypointBuilder(self.flight)
tanker_type = self.flight.unit_type tanker_type = self.flight.unit_type
if tanker_type.patrol_altitude is not None: if tanker_type.patrol_altitude is not None:

View File

@ -29,7 +29,6 @@ from game.theater.interfaces.CTLD import CTLD
from game.utils import Distance, meters, nautical_miles, feet from game.utils import Distance, meters, nautical_miles, feet
if TYPE_CHECKING: if TYPE_CHECKING:
from game.coalition import Coalition
from game.transfers import MultiGroupTransport from game.transfers import MultiGroupTransport
from game.theater.theatergroup import TheaterGroup from game.theater.theatergroup import TheaterGroup
from game.ato.flight import Flight from game.ato.flight import Flight
@ -45,9 +44,9 @@ class WaypointBuilder:
def __init__( def __init__(
self, self,
flight: Flight, flight: Flight,
coalition: Coalition,
targets: Optional[List[StrikeTarget]] = None, targets: Optional[List[StrikeTarget]] = None,
) -> None: ) -> None:
coalition = flight.coalition
self.flight = flight self.flight = flight
self.doctrine = coalition.doctrine self.doctrine = coalition.doctrine
self.threat_zones = coalition.opponent.threat_zone self.threat_zones = coalition.opponent.threat_zone
@ -75,7 +74,9 @@ class WaypointBuilder:
"NAV", "NAV",
FlightWaypointType.NAV, FlightWaypointType.NAV,
position, position,
meters(500) if self.is_helo else self.doctrine.rendezvous_altitude, feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.rendezvous_altitude,
description="Enter theater", description="Enter theater",
pretty_name="Enter theater", pretty_name="Enter theater",
) )
@ -102,7 +103,9 @@ class WaypointBuilder:
"NAV", "NAV",
FlightWaypointType.NAV, FlightWaypointType.NAV,
position, position,
meters(500) if self.is_helo else self.doctrine.rendezvous_altitude, feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.rendezvous_altitude,
description="Exit theater", description="Exit theater",
pretty_name="Exit theater", pretty_name="Exit theater",
) )
@ -131,7 +134,9 @@ class WaypointBuilder:
altitude_type: AltitudeReference altitude_type: AltitudeReference
if isinstance(divert, OffMapSpawn): if isinstance(divert, OffMapSpawn):
altitude = ( altitude = (
meters(500) if self.is_helo else self.doctrine.rendezvous_altitude feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.rendezvous_altitude
) )
altitude_type = "BARO" altitude_type = "BARO"
else: else:
@ -170,7 +175,9 @@ class WaypointBuilder:
"HOLD", "HOLD",
FlightWaypointType.LOITER, FlightWaypointType.LOITER,
position, position,
feet(1000) if self.is_helo else self.doctrine.rendezvous_altitude, feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description="Wait until push time", description="Wait until push time",
pretty_name="Hold", pretty_name="Hold",
@ -185,7 +192,9 @@ class WaypointBuilder:
"JOIN", "JOIN",
FlightWaypointType.JOIN, FlightWaypointType.JOIN,
position, position,
meters(80) if self.is_helo else self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description="Rendezvous with package", description="Rendezvous with package",
pretty_name="Join", pretty_name="Join",
@ -200,7 +209,9 @@ class WaypointBuilder:
"REFUEL", "REFUEL",
FlightWaypointType.REFUEL, FlightWaypointType.REFUEL,
position, position,
meters(80) if self.is_helo else self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_cruise_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description="Refuel from tanker", description="Refuel from tanker",
pretty_name="Refuel", pretty_name="Refuel",
@ -215,7 +226,9 @@ class WaypointBuilder:
"SPLIT", "SPLIT",
FlightWaypointType.SPLIT, FlightWaypointType.SPLIT,
position, position,
meters(80) if self.is_helo else self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description="Depart from package", description="Depart from package",
pretty_name="Split", pretty_name="Split",
@ -231,7 +244,11 @@ class WaypointBuilder:
alt_type: AltitudeReference = "BARO" alt_type: AltitudeReference = "BARO"
if self.is_helo or self.flight.is_hercules: if self.is_helo or self.flight.is_hercules:
alt_type = "RADIO" alt_type = "RADIO"
alt = meters(60) if self.is_helo else feet(1000) alt = (
feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else feet(1000)
)
return FlightWaypoint( return FlightWaypoint(
"INGRESS", "INGRESS",
@ -253,7 +270,9 @@ class WaypointBuilder:
"EGRESS", "EGRESS",
FlightWaypointType.EGRESS, FlightWaypointType.EGRESS,
position, position,
meters(60) if self.is_helo else self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description=f"EGRESS from {target.name}", description=f"EGRESS from {target.name}",
pretty_name=f"EGRESS from {target.name}", pretty_name=f"EGRESS from {target.name}",
@ -350,7 +369,9 @@ class WaypointBuilder:
"CAS", "CAS",
FlightWaypointType.CAS, FlightWaypointType.CAS,
position, position,
meters(60) if self.is_helo else meters(1000), feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else meters(1000),
"RADIO", "RADIO",
description="Provide CAS", description="Provide CAS",
pretty_name="CAS", pretty_name="CAS",
@ -430,7 +451,9 @@ class WaypointBuilder:
"SEAD Search", "SEAD Search",
FlightWaypointType.NAV, FlightWaypointType.NAV,
hold, hold,
self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type="BARO", alt_type="BARO",
description="Anchor and search from this point", description="Anchor and search from this point",
pretty_name="SEAD Search", pretty_name="SEAD Search",
@ -443,7 +466,9 @@ class WaypointBuilder:
"SEAD Sweep", "SEAD Sweep",
FlightWaypointType.NAV, FlightWaypointType.NAV,
hold, hold,
self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type="BARO", alt_type="BARO",
description="Anchor and search from this point", description="Anchor and search from this point",
pretty_name="SEAD Sweep", pretty_name="SEAD Sweep",
@ -565,7 +590,9 @@ class WaypointBuilder:
"TARGET", "TARGET",
FlightWaypointType.TARGET_GROUP_LOC, FlightWaypointType.TARGET_GROUP_LOC,
target.position, target.position,
meters(60) if self.is_helo else self.doctrine.ingress_altitude, feet(self.flight.coalition.game.settings.heli_combat_alt_agl)
if self.is_helo
else self.doctrine.ingress_altitude,
alt_type, alt_type,
description="Escort the package", description="Escort the package",
pretty_name="Target area", pretty_name="Target area",

View File

@ -255,6 +255,33 @@ class Settings:
"within threatened airspace." "within threatened airspace."
), ),
) )
heli_combat_alt_agl: int = bounded_int_option(
"Helicopter combat altitude (feet AGL)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=GENERAL_SECTION,
default=200,
min=1,
max=10000,
detail=(
"Altitude for helicopters in feet AGL while flying between combat waypoints."
" Combat waypoints are considered INGRESS, CAS, TGT, EGRESS & SPLIT."
" In campaigns in more mountainous areas, you might want to increase this "
"setting to avoid the AI flying into the terrain."
),
)
heli_cruise_alt_agl: int = bounded_int_option(
"Helicopter cruise altitude (feet AGL)",
page=CAMPAIGN_DOCTRINE_PAGE,
section=GENERAL_SECTION,
default=500,
min=1,
max=10000,
detail=(
"Altitude for helicopters in feet AGL while flying between non-combat waypoints."
" In campaigns in more mountainous areas, you might want to increase this "
"setting to avoid the AI flying into the terrain."
),
)
airbase_threat_range: int = bounded_int_option( airbase_threat_range: int = bounded_int_option(
"Airbase threat range (nmi)", "Airbase threat range (nmi)",
page=CAMPAIGN_DOCTRINE_PAGE, page=CAMPAIGN_DOCTRINE_PAGE,

View File

@ -84,7 +84,9 @@ class PilotSelector(QComboBox):
self.roster.set_pilot(self.pilot_index, pilot) self.roster.set_pilot(self.pilot_index, pilot)
self.available_pilots_changed.emit() self.available_pilots_changed.emit()
def replace(self, squadron: Optional[Squadron], new_roster: Optional[FlightRoster]) -> None: def replace(
self, squadron: Optional[Squadron], new_roster: Optional[FlightRoster]
) -> None:
self.squadron = squadron self.squadron = squadron
self.roster = new_roster self.roster = new_roster
self.rebuild() self.rebuild()
@ -159,7 +161,9 @@ class PilotControls(QHBoxLayout):
finally: finally:
self.player_checkbox.blockSignals(False) self.player_checkbox.blockSignals(False)
def replace(self, squadron: Optional[Squadron], new_roster: Optional[FlightRoster]) -> None: def replace(
self, squadron: Optional[Squadron], new_roster: Optional[FlightRoster]
) -> None:
self.roster = new_roster self.roster = new_roster
if self.roster is None or self.pilot_index >= self.roster.max_size: if self.roster is None or self.pilot_index >= self.roster.max_size:
self.disable_and_clear() self.disable_and_clear()

View File

@ -194,7 +194,7 @@ class QFlightWaypointTab(QFrame):
self.on_change() self.on_change()
def on_rtb_waypoint(self): def on_rtb_waypoint(self):
rtb = WaypointBuilder(self.flight, self.coalition).land(self.flight.arrival) rtb = WaypointBuilder(self.flight).land(self.flight.arrival)
self.degrade_to_custom_flight_plan() self.degrade_to_custom_flight_plan()
assert isinstance(self.flight.flight_plan, CustomFlightPlan) assert isinstance(self.flight.flight_plan, CustomFlightPlan)
self.flight.flight_plan.layout.custom_waypoints.append(rtb) self.flight.flight_plan.layout.custom_waypoints.append(rtb)