mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Clean up aircraft allocation and procurement.
This also does improve the over-purchase problems, though I can't spot the behavior change that's causing that. Presumably the old implementation had a bug I can't spot and in rewriting it I solved the problem... Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1582
This commit is contained in:
@@ -2,20 +2,21 @@ from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
from collections import defaultdict
|
||||
from typing import Sequence, Iterator, TYPE_CHECKING
|
||||
from typing import Sequence, Iterator, TYPE_CHECKING, Optional
|
||||
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from gen.flights.ai_flight_planner_db import aircraft_for_task
|
||||
from gen.flights.closestairfields import ObjectiveDistanceCache
|
||||
from .squadron import Squadron
|
||||
from ..theater import ControlPoint
|
||||
from ..theater import ControlPoint, MissionTarget
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from gen.flights.flight import FlightType
|
||||
|
||||
|
||||
class AirWing:
|
||||
def __init__(self, game: Game) -> None:
|
||||
self.game = game
|
||||
def __init__(self, player: bool) -> None:
|
||||
self.player = player
|
||||
self.squadrons: dict[AircraftType, list[Squadron]] = defaultdict(list)
|
||||
|
||||
def add_squadron(self, squadron: Squadron) -> None:
|
||||
@@ -31,6 +32,35 @@ class AirWing:
|
||||
except StopIteration:
|
||||
return False
|
||||
|
||||
def best_squadrons_for(
|
||||
self, location: MissionTarget, task: FlightType, size: int, this_turn: bool
|
||||
) -> list[Squadron]:
|
||||
airfield_cache = ObjectiveDistanceCache.get_closest_airfields(location)
|
||||
best_aircraft = aircraft_for_task(task)
|
||||
ordered: list[Squadron] = []
|
||||
for control_point in airfield_cache.operational_airfields:
|
||||
if control_point.captured != self.player:
|
||||
continue
|
||||
capable_at_base = []
|
||||
for squadron in control_point.squadrons:
|
||||
if squadron.can_auto_assign_mission(location, task, size, this_turn):
|
||||
capable_at_base.append(squadron)
|
||||
|
||||
ordered.extend(
|
||||
sorted(
|
||||
capable_at_base,
|
||||
key=lambda s: best_aircraft.index(s.aircraft),
|
||||
)
|
||||
)
|
||||
return ordered
|
||||
|
||||
def best_squadron_for(
|
||||
self, location: MissionTarget, task: FlightType, size: int, this_turn: bool
|
||||
) -> Optional[Squadron]:
|
||||
for squadron in self.best_squadrons_for(location, task, size, this_turn):
|
||||
return squadron
|
||||
return None
|
||||
|
||||
@property
|
||||
def available_aircraft_types(self) -> Iterator[AircraftType]:
|
||||
for aircraft, squadrons in self.squadrons.items():
|
||||
@@ -51,17 +81,6 @@ class AirWing:
|
||||
if squadron.can_auto_assign(task) and squadron.location == base:
|
||||
yield squadron
|
||||
|
||||
def auto_assignable_for_task_with_type(
|
||||
self, aircraft: AircraftType, task: FlightType, base: ControlPoint
|
||||
) -> Iterator[Squadron]:
|
||||
for squadron in self.squadrons_for(aircraft):
|
||||
if (
|
||||
squadron.location == base
|
||||
and squadron.can_auto_assign(task)
|
||||
and squadron.has_available_pilots
|
||||
):
|
||||
yield squadron
|
||||
|
||||
def squadron_for(self, aircraft: AircraftType) -> Squadron:
|
||||
return self.squadrons_for(aircraft)[0]
|
||||
|
||||
|
||||
@@ -16,12 +16,13 @@ from gen.ato import Package
|
||||
from gen.flights.flight import FlightType, Flight
|
||||
from gen.flights.flightplan import FlightPlanBuilder
|
||||
from .pilot import Pilot, PilotStatus
|
||||
from ..utils import meters
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from game.coalition import Coalition
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.theater import ControlPoint, ConflictTheater
|
||||
from game.theater import ControlPoint, ConflictTheater, MissionTarget
|
||||
from .operatingbases import OperatingBases
|
||||
from .squadrondef import SquadronDef
|
||||
|
||||
@@ -252,6 +253,17 @@ class Squadron:
|
||||
def can_auto_assign(self, task: FlightType) -> bool:
|
||||
return task in self.auto_assignable_mission_types
|
||||
|
||||
def can_auto_assign_mission(
|
||||
self, location: MissionTarget, task: FlightType, size: int, this_turn: bool
|
||||
) -> bool:
|
||||
if not self.can_auto_assign(task):
|
||||
return False
|
||||
if this_turn and not self.can_fulfill_flight(size):
|
||||
return False
|
||||
|
||||
distance_to_target = meters(location.distance_to(self.location))
|
||||
return distance_to_target <= self.aircraft.max_mission_range
|
||||
|
||||
def operates_from(self, control_point: ControlPoint) -> bool:
|
||||
if control_point.is_carrier:
|
||||
return self.operating_bases.carrier
|
||||
|
||||
Reference in New Issue
Block a user