Support planning TARCAP at last airfield.

This PR addresses #771 by adding special handling for the scenario where
there is only one remaining enemy airfield. An example of the race track
generated using this logic is shown below.

![Screenshot 2023-10-31
230938](https://github.com/dcs-liberation/dcs_liberation/assets/64713351/3fb2027e-f496-4325-a3c5-2abe2a45b58f)

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/771.
This commit is contained in:
zhexu14 2023-11-02 10:52:35 +11:00 committed by GitHub
parent da22b8ba43
commit ac2fbc2940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 1 deletions

View File

@ -37,6 +37,7 @@ Saves from 8.x are not compatible with 9.0.0.
* **[Mission Generation]** Fixed Recovery Tanker mission type intermittently failing due to not being able to find the CVN. * **[Mission Generation]** Fixed Recovery Tanker mission type intermittently failing due to not being able to find the CVN.
* **[Mission Generation]** Fixed "division by zero" error on mission generation when a flight has an "In-Flight" start type and starts on top of a mission waypoint. * **[Mission Generation]** Fixed "division by zero" error on mission generation when a flight has an "In-Flight" start type and starts on top of a mission waypoint.
* **[Mission Generation]** Fixed flights not being selectable in the mission editor if fast-forward was used and they were generated at a waypoint that had a fixed TOT (such as a BARCAP that was on-station). * **[Mission Generation]** Fixed flights not being selectable in the mission editor if fast-forward was used and they were generated at a waypoint that had a fixed TOT (such as a BARCAP that was on-station).
* **[Mission Generation]** Fixed error when planning TARCAPs on the sole remaining enemy airfield.
* **[Modding]** Unit variants can now actually override base unit type properties. * **[Modding]** Unit variants can now actually override base unit type properties.
* **[New Game Wizard]** Factions are reset to default after clicking "Back" to Theater Configuration screen. * **[New Game Wizard]** Factions are reset to default after clicking "Back" to Theater Configuration screen.
* **[Plugins]** Fixed Lua errors in Skynet plugin that would occur whenever one coalition had no IADS nodes. * **[Plugins]** Fixed Lua errors in Skynet plugin that would occur whenever one coalition had no IADS nodes.

View File

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import copy
import random import random
from abc import ABC from abc import ABC
from typing import Any, TYPE_CHECKING, TypeVar from typing import Any, TYPE_CHECKING, TypeVar
@ -26,6 +27,9 @@ class CapBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
self, location: MissionTarget, barcap: bool self, location: MissionTarget, barcap: bool
) -> tuple[Point, Point]: ) -> tuple[Point, Point]:
closest_cache = ObjectiveDistanceCache.get_closest_airfields(location) closest_cache = ObjectiveDistanceCache.get_closest_airfields(location)
closest_friendly_field = (
None # keep track of closest frieldly airfield in case we need it
)
for airfield in closest_cache.operational_airfields: for airfield in closest_cache.operational_airfields:
# If the mission is a BARCAP of an enemy airfield, find the *next* # If the mission is a BARCAP of an enemy airfield, find the *next*
# closest enemy airfield. # closest enemy airfield.
@ -34,8 +38,43 @@ class CapBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
if airfield.captured != self.is_player: if airfield.captured != self.is_player:
closest_airfield = airfield closest_airfield = airfield
break break
elif closest_friendly_field is None:
closest_friendly_field = airfield
else: else:
raise PlanningError("Could not find any enemy airfields") if barcap:
# If planning a BARCAP, we should be able to find at least one enemy
# airfield. If we can't, it's an error.
raise PlanningError("Could not find any enemy airfields")
else:
# if we cannot find any friendly or enemy airfields other than the target,
# there's nothing we can do
if closest_friendly_field is None:
raise PlanningError(
"Could not find any enemy or friendly airfields"
)
# If planning other race tracks (TARCAPs, currently), the target may be
# the only enemy airfield. In this case, set the race track orientation using
# a virtual point equi-distant from but opposite to the target from the closest
# friendly airfield like below, where F is the closest friendly airfield, T is
# the sole enemy airfield and V the virtual point
#
# F ---- T ----- V
#
# We need to create this virtual point, rather than using F to make sure
# the race track is aligned towards the target.
closest_friendly_field_position = copy.deepcopy(
closest_friendly_field.position
)
closest_airfield = closest_friendly_field
closest_airfield.position.x = (
2 * self.package.target.position.x
- closest_friendly_field_position.x
)
closest_airfield.position.y = (
2 * self.package.target.position.y
- closest_friendly_field_position.y
)
heading = Heading.from_degrees( heading = Heading.from_degrees(
location.position.heading_between_point(closest_airfield.position) location.position.heading_between_point(closest_airfield.position)