Fix several cases of wrongly using broken runways.

The usual symptom here was the game breaking when a carrier is
destroyed. The carrier would no longer be operational but missions would
be assigned there that could not generate flight plans.
This commit is contained in:
Dan Albert
2021-05-31 14:11:13 -07:00
parent f6909d2f98
commit 355e6e1d15
7 changed files with 38 additions and 17 deletions

View File

@@ -162,7 +162,7 @@ class AircraftAllocator:
self, flight: ProposedFlight, task: FlightType
) -> Optional[Tuple[ControlPoint, Squadron]]:
types = aircraft_for_task(task)
airfields_in_range = self.closest_airfields.airfields_within(
airfields_in_range = self.closest_airfields.operational_airfields_within(
flight.max_distance
)
@@ -258,7 +258,9 @@ class PackageBuilder:
self, aircraft: Type[FlyingType], arrival: ControlPoint
) -> Optional[ControlPoint]:
divert_limit = nautical_miles(150)
for airfield in self.closest_airfields.airfields_within(divert_limit):
for airfield in self.closest_airfields.operational_airfields_within(
divert_limit
):
if airfield.captured != self.is_player:
continue
if airfield == arrival:
@@ -467,8 +469,10 @@ class ObjectiveFinder:
# Off-map spawn locations don't need protection.
continue
airfields_in_proximity = self.closest_airfields_to(cp)
airfields_in_threat_range = airfields_in_proximity.airfields_within(
self.AIRFIELD_THREAT_RANGE
airfields_in_threat_range = (
airfields_in_proximity.operational_airfields_within(
self.AIRFIELD_THREAT_RANGE
)
)
for airfield in airfields_in_threat_range:
if not airfield.is_friendly(self.is_player):

View File

@@ -27,17 +27,35 @@ class ClosestAirfields:
def operational_airfields(self) -> Iterator[ControlPoint]:
return (c for c in self.closest_airfields if c.runway_is_operational())
def airfields_within(self, distance: Distance) -> Iterator[ControlPoint]:
def _airfields_within(
self, distance: Distance, operational: bool
) -> Iterator[ControlPoint]:
airfields = (
self.operational_airfields if operational else self.closest_airfields
)
for cp in airfields:
if cp.distance_to(self.target) < distance.meters:
yield cp
else:
break
def operational_airfields_within(
self, distance: Distance
) -> Iterator[ControlPoint]:
"""Iterates over all airfields within the given range of the target.
Note that this iterates over *all* airfields, not just friendly
airfields.
"""
for cp in self.closest_airfields:
if cp.distance_to(self.target) < distance.meters:
yield cp
else:
break
return self._airfields_within(distance, operational=True)
def all_airfields_within(self, distance: Distance) -> Iterator[ControlPoint]:
"""Iterates over all airfields within the given range of the target.
Note that this iterates over *all* airfields, not just friendly
airfields.
"""
return self._airfields_within(distance, operational=False)
class ObjectiveDistanceCache:

View File

@@ -1807,7 +1807,7 @@ class FlightPlanBuilder:
# We'll always have a package, but if this is being planned via the UI
# it could be the first flight in the package.
if not self.package.flights:
raise RuntimeError(
raise PlanningError(
"Cannot determine source airfield for package with no flights"
)
@@ -1819,4 +1819,4 @@ class FlightPlanBuilder:
for flight in self.package.flights:
if flight.departure == airfield:
return airfield
raise RuntimeError("Could not find any airfield assigned to this package")
raise PlanningError("Could not find any airfield assigned to this package")