mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
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.  Fixes https://github.com/dcs-liberation/dcs_liberation/issues/771.
This commit is contained in:
parent
da22b8ba43
commit
ac2fbc2940
@ -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.
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user