mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Set preferred mission types for aircraft.
This commit is contained in:
parent
93db1254ec
commit
023925d741
@ -3,9 +3,9 @@ from __future__ import annotations
|
||||
import logging
|
||||
import operator
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
|
||||
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple, Type
|
||||
|
||||
from dcs.unittype import UnitType
|
||||
from dcs.unittype import FlyingType, UnitType
|
||||
|
||||
from game import db
|
||||
from game.data.radar_db import UNITS_WITH_RADAR
|
||||
@ -15,9 +15,13 @@ from gen import Conflict
|
||||
from gen.ato import Package
|
||||
from gen.flights.ai_flight_planner_db import (
|
||||
CAP_CAPABLE,
|
||||
CAP_PREFERRED,
|
||||
CAS_CAPABLE,
|
||||
CAS_PREFERRED,
|
||||
SEAD_CAPABLE,
|
||||
SEAD_PREFERRED,
|
||||
STRIKE_CAPABLE,
|
||||
STRIKE_PREFERRED,
|
||||
)
|
||||
from gen.flights.closestairfields import (
|
||||
ClosestAirfields,
|
||||
@ -102,30 +106,63 @@ class AircraftAllocator:
|
||||
maximum allowed range. If insufficient aircraft are available for the
|
||||
mission, None is returned.
|
||||
|
||||
Airfields are searched ordered nearest to farthest from the target and
|
||||
searched twice. The first search looks for aircraft which prefer the
|
||||
mission type, and the second search looks for any aircraft which are
|
||||
capable of the mission type. For example, an F-14 from a nearby carrier
|
||||
will be preferred for the CAP of an airfield that has only F-16s, but if
|
||||
the carrier has only F/A-18s the F-16s will be used for CAP instead.
|
||||
|
||||
Note that aircraft *will* be removed from the global inventory on
|
||||
success. This is to ensure that the same aircraft are not matched twice
|
||||
on subsequent calls. If the found aircraft are not used, the caller is
|
||||
responsible for returning them to the inventory.
|
||||
"""
|
||||
cap_missions = (FlightType.BARCAP, FlightType.CAP, FlightType.TARCAP)
|
||||
if flight.task in cap_missions:
|
||||
types = CAP_CAPABLE
|
||||
elif flight.task == FlightType.CAS:
|
||||
types = CAS_CAPABLE
|
||||
elif flight.task in (FlightType.DEAD, FlightType.SEAD):
|
||||
types = SEAD_CAPABLE
|
||||
elif flight.task == FlightType.STRIKE:
|
||||
types = STRIKE_CAPABLE
|
||||
elif flight.task == FlightType.ESCORT:
|
||||
types = CAP_CAPABLE
|
||||
else:
|
||||
logging.error(f"Unplannable flight type: {flight.task}")
|
||||
return None
|
||||
result = self.find_aircraft_of_type(
|
||||
flight, self.preferred_aircraft_for_task(flight.task)
|
||||
)
|
||||
if result is not None:
|
||||
return result
|
||||
return self.find_aircraft_of_type(
|
||||
flight, self.capable_aircraft_for_task(flight.task)
|
||||
)
|
||||
|
||||
# TODO: Implement mission type weighting for aircraft.
|
||||
# We should avoid assigning F/A-18s to CAP missions when there are F-15s
|
||||
# available, since the F/A-18 is capable of performing other tasks that
|
||||
# the F-15 is not capable of.
|
||||
@staticmethod
|
||||
def preferred_aircraft_for_task(task: FlightType) -> List[Type[FlyingType]]:
|
||||
cap_missions = (FlightType.BARCAP, FlightType.CAP, FlightType.TARCAP)
|
||||
if task in cap_missions:
|
||||
return CAP_PREFERRED
|
||||
elif task == FlightType.CAS:
|
||||
return CAS_PREFERRED
|
||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||
return SEAD_PREFERRED
|
||||
elif task == FlightType.STRIKE:
|
||||
return STRIKE_PREFERRED
|
||||
elif task == FlightType.ESCORT:
|
||||
return CAP_PREFERRED
|
||||
else:
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def capable_aircraft_for_task(task: FlightType) -> List[Type[FlyingType]]:
|
||||
cap_missions = (FlightType.BARCAP, FlightType.CAP, FlightType.TARCAP)
|
||||
if task in cap_missions:
|
||||
return CAP_CAPABLE
|
||||
elif task == FlightType.CAS:
|
||||
return CAS_CAPABLE
|
||||
elif task in (FlightType.DEAD, FlightType.SEAD):
|
||||
return SEAD_CAPABLE
|
||||
elif task == FlightType.STRIKE:
|
||||
return STRIKE_CAPABLE
|
||||
elif task == FlightType.ESCORT:
|
||||
return CAP_CAPABLE
|
||||
else:
|
||||
logging.error(f"Unplannable flight type: {task}")
|
||||
return []
|
||||
|
||||
def find_aircraft_of_type(
|
||||
self, flight: ProposedFlight, types: List[Type[FlyingType]],
|
||||
) -> Optional[Tuple[ControlPoint, UnitType]]:
|
||||
airfields_in_range = self.closest_airfields.airfields_within(
|
||||
flight.max_distance
|
||||
)
|
||||
@ -312,7 +349,8 @@ class ObjectiveFinder:
|
||||
yield from cp.ground_objects
|
||||
yield from self.front_lines()
|
||||
|
||||
def closest_airfields_to(self, location: MissionTarget) -> ClosestAirfields:
|
||||
@staticmethod
|
||||
def closest_airfields_to(location: MissionTarget) -> ClosestAirfields:
|
||||
"""Returns the closest airfields to the given location."""
|
||||
return ObjectiveDistanceCache.get_closest_airfields(location)
|
||||
|
||||
|
||||
@ -80,6 +80,10 @@ from pydcs_extensions.a4ec.a4ec import A_4E_C
|
||||
from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M
|
||||
|
||||
# TODO: These lists really ought to be era (faction) dependent.
|
||||
# Factions which have F-5s, F-86s, and A-4s will should prefer F-5s for CAP, but
|
||||
# factions that also have F-4s should not.
|
||||
|
||||
INTERCEPT_CAPABLE = [
|
||||
MiG_21Bis,
|
||||
MiG_25PD,
|
||||
@ -150,6 +154,42 @@ CAP_CAPABLE = [
|
||||
Rafale_M,
|
||||
]
|
||||
|
||||
CAP_PREFERRED = [
|
||||
MiG_15bis,
|
||||
MiG_19P,
|
||||
MiG_21Bis,
|
||||
MiG_23MLD,
|
||||
MiG_25PD,
|
||||
MiG_29A,
|
||||
MiG_29G,
|
||||
MiG_29S,
|
||||
MiG_31,
|
||||
|
||||
Su_27,
|
||||
J_11A,
|
||||
Su_30,
|
||||
Su_33,
|
||||
|
||||
M_2000C,
|
||||
Mirage_2000_5,
|
||||
|
||||
F_86F_Sabre,
|
||||
F_14B,
|
||||
F_15C,
|
||||
|
||||
P_51D_30_NA,
|
||||
P_51D,
|
||||
|
||||
SpitfireLFMkIXCW,
|
||||
SpitfireLFMkIX,
|
||||
|
||||
Bf_109K_4,
|
||||
FW_190D9,
|
||||
FW_190A8,
|
||||
|
||||
Rafale_M,
|
||||
]
|
||||
|
||||
# Used for CAS (Close air support) and BAI (Battlefield Interdiction)
|
||||
CAS_CAPABLE = [
|
||||
|
||||
@ -228,6 +268,59 @@ CAS_CAPABLE = [
|
||||
RQ_1A_Predator
|
||||
]
|
||||
|
||||
CAS_PREFERRED = [
|
||||
Su_17M4,
|
||||
Su_24M,
|
||||
Su_24MR,
|
||||
Su_25,
|
||||
Su_25T,
|
||||
Su_25TM,
|
||||
Su_34,
|
||||
|
||||
JF_17,
|
||||
|
||||
A_10A,
|
||||
A_10C,
|
||||
A_10C_2,
|
||||
AV8BNA,
|
||||
|
||||
F_15E,
|
||||
|
||||
Tornado_GR4,
|
||||
|
||||
C_101CC,
|
||||
MB_339PAN,
|
||||
L_39ZA,
|
||||
AJS37,
|
||||
|
||||
SA342M,
|
||||
SA342L,
|
||||
OH_58D,
|
||||
|
||||
AH_64A,
|
||||
AH_64D,
|
||||
AH_1W,
|
||||
|
||||
UH_1H,
|
||||
|
||||
Mi_8MT,
|
||||
Mi_28N,
|
||||
Mi_24V,
|
||||
Ka_50,
|
||||
|
||||
P_47D_30,
|
||||
P_47D_30bl1,
|
||||
P_47D_40,
|
||||
A_20G,
|
||||
|
||||
A_4E_C,
|
||||
Rafale_A_S,
|
||||
|
||||
WingLoong_I,
|
||||
MQ_9_Reaper,
|
||||
RQ_1A_Predator
|
||||
]
|
||||
|
||||
# Aircraft used for SEAD / DEAD tasks
|
||||
SEAD_CAPABLE = [
|
||||
F_4E,
|
||||
@ -252,6 +345,12 @@ SEAD_CAPABLE = [
|
||||
Rafale_A_S
|
||||
]
|
||||
|
||||
SEAD_PREFERRED = [
|
||||
F_4E,
|
||||
Su_25T,
|
||||
Tornado_IDS,
|
||||
]
|
||||
|
||||
# Aircraft used for Strike mission
|
||||
STRIKE_CAPABLE = [
|
||||
MiG_15bis,
|
||||
@ -309,6 +408,15 @@ STRIKE_CAPABLE = [
|
||||
|
||||
]
|
||||
|
||||
STRIKE_PREFERRED = [
|
||||
AJS37,
|
||||
F_15E,
|
||||
Tornado_GR4,
|
||||
|
||||
A_20G,
|
||||
B_17G,
|
||||
]
|
||||
|
||||
ANTISHIP_CAPABLE = [
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user