mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Change squadrons to operate out of a single base.
https://github.com/dcs-liberation/dcs_liberation/issues/1145 Currently this is fixed at the start of the campaign. The squadron locations are defined by the campaign file. Follow up work: * Track aircraft ownership per-squadron rather than per-airbase. * UI for relocating squadrons. * Ferry missions for squadrons that are relocating. * Auto-relocation (probably only for retreat handling). Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1138
This commit is contained in:
142
game/campaignloader/defaultsquadronassigner.py
Normal file
142
game/campaignloader/defaultsquadronassigner.py
Normal file
@@ -0,0 +1,142 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from game.squadrons import Squadron
|
||||
from game.squadrons.squadrondef import SquadronDef
|
||||
from game.squadrons.squadrondefloader import SquadronDefLoader
|
||||
from gen.flights.flight import FlightType
|
||||
from .campaignairwingconfig import CampaignAirWingConfig, SquadronConfig
|
||||
from .squadrondefgenerator import SquadronDefGenerator
|
||||
from ..dcs.aircrafttype import AircraftType
|
||||
from ..theater import ControlPoint
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from game.coalition import Coalition
|
||||
|
||||
|
||||
class DefaultSquadronAssigner:
|
||||
def __init__(
|
||||
self, config: CampaignAirWingConfig, game: Game, coalition: Coalition
|
||||
) -> None:
|
||||
self.config = config
|
||||
self.game = game
|
||||
self.coalition = coalition
|
||||
self.air_wing = coalition.air_wing
|
||||
self.squadron_defs = SquadronDefLoader(game, coalition).load()
|
||||
self.squadron_def_generator = SquadronDefGenerator(self.coalition)
|
||||
|
||||
def claim_squadron_def(self, squadron: SquadronDef) -> None:
|
||||
try:
|
||||
self.squadron_defs[squadron.aircraft].remove(squadron)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def assign(self) -> None:
|
||||
for control_point, squadron_configs in self.config.by_location.items():
|
||||
if not control_point.is_friendly(self.coalition.player):
|
||||
continue
|
||||
for squadron_config in squadron_configs:
|
||||
squadron_def = self.find_squadron_for(squadron_config, control_point)
|
||||
if squadron_def is None:
|
||||
logging.info(
|
||||
f"{self.coalition.faction.name} has no aircraft compatible "
|
||||
f"with {squadron_config.primary} at {control_point}"
|
||||
)
|
||||
continue
|
||||
|
||||
self.claim_squadron_def(squadron_def)
|
||||
squadron = Squadron.create_from(
|
||||
squadron_def, control_point, self.coalition, self.game
|
||||
)
|
||||
squadron.set_auto_assignable_mission_types(
|
||||
squadron_config.auto_assignable
|
||||
)
|
||||
self.air_wing.add_squadron(squadron)
|
||||
|
||||
def find_squadron_for(
|
||||
self, config: SquadronConfig, control_point: ControlPoint
|
||||
) -> Optional[SquadronDef]:
|
||||
for preferred_aircraft in config.aircraft:
|
||||
squadron_def = self.find_preferred_squadron(
|
||||
preferred_aircraft, config.primary, control_point
|
||||
)
|
||||
if squadron_def is not None:
|
||||
return squadron_def
|
||||
|
||||
# If we didn't find any of the preferred types we should use any squadron
|
||||
# compatible with the primary task.
|
||||
squadron_def = self.find_squadron_for_task(config.primary, control_point)
|
||||
if squadron_def is not None:
|
||||
return squadron_def
|
||||
|
||||
# If we can't find any squadron matching the requirement, we should
|
||||
# create one.
|
||||
return self.squadron_def_generator.generate_for_task(
|
||||
config.primary, control_point
|
||||
)
|
||||
|
||||
def find_preferred_squadron(
|
||||
self, preferred_aircraft: str, task: FlightType, control_point: ControlPoint
|
||||
) -> Optional[SquadronDef]:
|
||||
# Attempt to find a squadron with the name in the request.
|
||||
squadron_def = self.find_squadron_by_name(
|
||||
preferred_aircraft, task, control_point
|
||||
)
|
||||
if squadron_def is not None:
|
||||
return squadron_def
|
||||
|
||||
# If the name didn't match a squadron available to this coalition, try to find
|
||||
# an aircraft with the matching name that meets the requirements.
|
||||
try:
|
||||
aircraft = AircraftType.named(preferred_aircraft)
|
||||
except KeyError:
|
||||
# No aircraft with this name.
|
||||
return None
|
||||
|
||||
if aircraft not in self.coalition.faction.aircrafts:
|
||||
return None
|
||||
|
||||
squadron_def = self.find_squadron_for_airframe(aircraft, task, control_point)
|
||||
if squadron_def is not None:
|
||||
return squadron_def
|
||||
|
||||
# No premade squadron available for this aircraft that meets the requirements,
|
||||
# so generate one if possible.
|
||||
return self.squadron_def_generator.generate_for_aircraft(aircraft)
|
||||
|
||||
@staticmethod
|
||||
def squadron_compatible_with(
|
||||
squadron: SquadronDef, task: FlightType, control_point: ControlPoint
|
||||
) -> bool:
|
||||
return squadron.operates_from(control_point) and task in squadron.mission_types
|
||||
|
||||
def find_squadron_for_airframe(
|
||||
self, aircraft: AircraftType, task: FlightType, control_point: ControlPoint
|
||||
) -> Optional[SquadronDef]:
|
||||
for squadron in self.squadron_defs[aircraft]:
|
||||
if self.squadron_compatible_with(squadron, task, control_point):
|
||||
return squadron
|
||||
return None
|
||||
|
||||
def find_squadron_by_name(
|
||||
self, name: str, task: FlightType, control_point: ControlPoint
|
||||
) -> Optional[SquadronDef]:
|
||||
for squadrons in self.squadron_defs.values():
|
||||
for squadron in squadrons:
|
||||
if squadron.name == name and self.squadron_compatible_with(
|
||||
squadron, task, control_point
|
||||
):
|
||||
return squadron
|
||||
return None
|
||||
|
||||
def find_squadron_for_task(
|
||||
self, task: FlightType, control_point: ControlPoint
|
||||
) -> Optional[SquadronDef]:
|
||||
for squadrons in self.squadron_defs.values():
|
||||
for squadron in squadrons:
|
||||
if self.squadron_compatible_with(squadron, task, control_point):
|
||||
return squadron
|
||||
return None
|
||||
Reference in New Issue
Block a user