mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Ignore non-escorted regions when planning escorts.
We shouldn't consider the non-escorted parts of the flight path when checking for threats to determine if escorts should be used or not, since escorts can't help in those areas anyway. This was causing escorts to be overly requested since the bullseye is now a part of the "flight plan", but could have also triggered for divert waypoints, or for aircraft taking off in a retreat from a threatened location.
This commit is contained in:
parent
ddd6e7d18f
commit
eedb5c26a9
@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from functools import singledispatchmethod
|
from functools import singledispatchmethod
|
||||||
from typing import Optional, TYPE_CHECKING, Union
|
from typing import Optional, TYPE_CHECKING, Union, Iterable
|
||||||
|
|
||||||
from dcs.mapping import Point as DcsPoint
|
from dcs.mapping import Point as DcsPoint
|
||||||
from shapely.geometry import (
|
from shapely.geometry import (
|
||||||
@ -16,7 +16,7 @@ from shapely.ops import nearest_points, unary_union
|
|||||||
from game.theater import ControlPoint
|
from game.theater import ControlPoint
|
||||||
from game.utils import Distance, meters, nautical_miles
|
from game.utils import Distance, meters, nautical_miles
|
||||||
from gen.flights.closestairfields import ObjectiveDistanceCache
|
from gen.flights.closestairfields import ObjectiveDistanceCache
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight, FlightWaypoint
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game import Game
|
from game import Game
|
||||||
@ -71,6 +71,13 @@ class ThreatZones:
|
|||||||
LineString((self.dcs_to_shapely_point(p.position) for p in flight.points))
|
LineString((self.dcs_to_shapely_point(p.position) for p in flight.points))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def waypoints_threatened_by_aircraft(
|
||||||
|
self, waypoints: Iterable[FlightWaypoint]
|
||||||
|
) -> bool:
|
||||||
|
return self.threatened_by_aircraft(
|
||||||
|
LineString((self.dcs_to_shapely_point(p.position) for p in waypoints))
|
||||||
|
)
|
||||||
|
|
||||||
@singledispatchmethod
|
@singledispatchmethod
|
||||||
def threatened_by_air_defense(self, target) -> bool:
|
def threatened_by_air_defense(self, target) -> bool:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -99,6 +106,13 @@ class ThreatZones:
|
|||||||
LineString((self.dcs_to_shapely_point(p.position) for p in flight.points))
|
LineString((self.dcs_to_shapely_point(p.position) for p in flight.points))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def waypoints_threatened_by_radar_sam(
|
||||||
|
self, waypoints: Iterable[FlightWaypoint]
|
||||||
|
) -> bool:
|
||||||
|
return self.threatened_by_radar_sam(
|
||||||
|
LineString((self.dcs_to_shapely_point(p.position) for p in waypoints))
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def closest_enemy_airbase(
|
def closest_enemy_airbase(
|
||||||
cls, location: ControlPoint, max_distance: Distance
|
cls, location: ControlPoint, max_distance: Distance
|
||||||
|
|||||||
@ -831,9 +831,13 @@ class CoalitionMissionPlanner:
|
|||||||
def check_needed_escorts(self, builder: PackageBuilder) -> Dict[EscortType, bool]:
|
def check_needed_escorts(self, builder: PackageBuilder) -> Dict[EscortType, bool]:
|
||||||
threats = defaultdict(bool)
|
threats = defaultdict(bool)
|
||||||
for flight in builder.package.flights:
|
for flight in builder.package.flights:
|
||||||
if self.threat_zones.threatened_by_aircraft(flight):
|
if self.threat_zones.waypoints_threatened_by_aircraft(
|
||||||
|
flight.flight_plan.escorted_waypoints()
|
||||||
|
):
|
||||||
threats[EscortType.AirToAir] = True
|
threats[EscortType.AirToAir] = True
|
||||||
if self.threat_zones.threatened_by_radar_sam(flight):
|
if self.threat_zones.waypoints_threatened_by_radar_sam(
|
||||||
|
list(flight.flight_plan.escorted_waypoints())
|
||||||
|
):
|
||||||
threats[EscortType.Sead] = True
|
threats[EscortType.Sead] = True
|
||||||
return threats
|
return threats
|
||||||
|
|
||||||
|
|||||||
@ -198,6 +198,20 @@ class FlightPlan:
|
|||||||
def dismiss_escort_at(self) -> Optional[FlightWaypoint]:
|
def dismiss_escort_at(self) -> Optional[FlightWaypoint]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def escorted_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
|
begin = self.request_escort_at()
|
||||||
|
end = self.dismiss_escort_at()
|
||||||
|
if begin is None or end is None:
|
||||||
|
return
|
||||||
|
escorting = False
|
||||||
|
for waypoint in self.waypoints:
|
||||||
|
if waypoint == begin:
|
||||||
|
escorting = True
|
||||||
|
if escorting:
|
||||||
|
yield waypoint
|
||||||
|
if waypoint == end:
|
||||||
|
return
|
||||||
|
|
||||||
def takeoff_time(self) -> Optional[timedelta]:
|
def takeoff_time(self) -> Optional[timedelta]:
|
||||||
tot_waypoint = self.tot_waypoint
|
tot_waypoint = self.tot_waypoint
|
||||||
if tot_waypoint is None:
|
if tot_waypoint is None:
|
||||||
@ -600,10 +614,6 @@ class StrikeFlightPlan(FormationFlightPlan):
|
|||||||
)
|
)
|
||||||
return total
|
return total
|
||||||
|
|
||||||
@property
|
|
||||||
def mission_speed(self) -> Speed:
|
|
||||||
return GroundSpeed.for_flight(self.flight, self.ingress.alt)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def join_time(self) -> timedelta:
|
def join_time(self) -> timedelta:
|
||||||
travel_time = self.travel_time_between_waypoints(self.join, self.ingress)
|
travel_time = self.travel_time_between_waypoints(self.join, self.ingress)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user