dcs_liberation/game/sim/combat/aircraftengagementzones.py
Dan Albert fb10a8d28e Add frozen combat modelling.
This doesn't do anything yet, but sets up the data model handling for
frozen combat. The next step is to show combat in the map view, since
that will be helpful when debugging the step after that one: resolving
frozen combat.

This would benefit from caching the Shapely data for SAM threat zones.
Right now it's generating them once per tick and the stuttering is
visible at max speed.

https://github.com/dcs-liberation/dcs_liberation/issues/1680
2021-12-21 14:52:28 -08:00

61 lines
2.0 KiB
Python

from __future__ import annotations
from collections.abc import Iterator
from typing import Optional, TYPE_CHECKING
from dcs import Point
from shapely.ops import unary_union
from game.utils import dcs_to_shapely_point
if TYPE_CHECKING:
from game.ato import Flight
from game.ato.airtaaskingorder import AirTaskingOrder
from game.threatzones import ThreatPoly
from game.sim.combat import FrozenCombat
class AircraftEngagementZones:
def __init__(self, individual_zones: dict[Flight, ThreatPoly]) -> None:
self.individual_zones = individual_zones
self.threat_zones = self._make_combined_zone()
def update_for_combat(self, combat: FrozenCombat) -> None:
for flight in combat.iter_flights():
try:
del self.individual_zones[flight]
except KeyError:
pass
self.threat_zones = self._make_combined_zone()
def remove_flight(self, flight: Flight) -> None:
try:
del self.individual_zones[flight]
except KeyError:
pass
self.threat_zones = self._make_combined_zone()
def _make_combined_zone(self) -> ThreatPoly:
return unary_union(self.individual_zones.values())
def covers(self, position: Point) -> bool:
return self.threat_zones.intersects(dcs_to_shapely_point(position))
def iter_intercepting_flights(self, position: Point) -> Iterator[Flight]:
for flight, zone in self.individual_zones.items():
if zone.intersects(dcs_to_shapely_point(position)):
yield flight
@classmethod
def from_ato(cls, ato: AirTaskingOrder) -> AircraftEngagementZones:
zones = {}
for package in ato.packages:
for flight in package.flights:
if (region := cls.commit_region(flight)) is not None:
zones[flight] = region
return AircraftEngagementZones(zones)
@classmethod
def commit_region(cls, flight: Flight) -> Optional[ThreatPoly]:
return flight.state.a2a_commit_region()