2024-10-12 17:33:01 +02:00

84 lines
2.7 KiB
Python

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Generic, TYPE_CHECKING, TypeVar
from game.navmesh import NavMeshError
from .flightplan import FlightPlan, Layout
from .planningerror import PlanningError
from ..packagewaypoints import PackageWaypoints
if TYPE_CHECKING:
from game.coalition import Coalition
from game.data.doctrine import Doctrine
from game.theater import ConflictTheater
from game.threatzones import ThreatZones
from ..flight import Flight
from ..package import Package
FlightPlanT = TypeVar("FlightPlanT", bound=FlightPlan[Any])
LayoutT = TypeVar("LayoutT", bound=Layout)
class IBuilder(ABC, Generic[FlightPlanT, LayoutT]):
def __init__(self, flight: Flight) -> None:
self.flight = flight
self._flight_plan: FlightPlanT | None = None
self.settings = self.flight.coalition.game.settings
def get_or_build(self) -> FlightPlanT:
if self._flight_plan is None:
self.regenerate()
assert self._flight_plan is not None
return self._flight_plan
def regenerate(self, dump_debug_info: bool = False) -> None:
try:
self._generate_package_waypoints_if_needed(dump_debug_info)
self._flight_plan = self.build(dump_debug_info)
except NavMeshError as ex:
color = "blue" if self.flight.squadron.player else "red"
raise PlanningError(
f"Could not plan {color} {self.flight.flight_type.value} from "
f"{self.flight.departure} to {self.package.target}"
) from ex
def _generate_package_waypoints_if_needed(self, dump_debug_info: bool) -> None:
# Package waypoints are only valid for offensive missions. Skip this if the
# target is friendly.
if self.package.target.is_friendly(self.is_player):
return
if self.package.waypoints is None or dump_debug_info:
self.package.waypoints = PackageWaypoints.create(
self.package, self.coalition, dump_debug_info
)
@property
def theater(self) -> ConflictTheater:
return self.flight.departure.theater
@abstractmethod
def build(self, dump_debug_info: bool = False) -> FlightPlanT: ...
@property
def package(self) -> Package:
return self.flight.package
@property
def coalition(self) -> Coalition:
return self.flight.coalition
@property
def is_player(self) -> bool:
return self.coalition.player
@property
def doctrine(self) -> Doctrine:
return self.coalition.doctrine
@property
def threat_zones(self) -> ThreatZones:
return self.coalition.opponent.threat_zone