mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
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
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Iterator
|
|
from typing import Any, Optional, TYPE_CHECKING
|
|
|
|
from dcs import Point
|
|
from shapely.ops import unary_union
|
|
|
|
from game.utils import dcs_to_shapely_point, meters
|
|
|
|
if TYPE_CHECKING:
|
|
from game.theater import ConflictTheater, TheaterGroundObject
|
|
from game.threatzones import ThreatPoly
|
|
|
|
|
|
class SamEngagementZones:
|
|
def __init__(
|
|
self,
|
|
threat_zones: ThreatPoly,
|
|
individual_zones: list[tuple[TheaterGroundObject[Any], ThreatPoly]],
|
|
) -> None:
|
|
self.threat_zones = threat_zones
|
|
self.individual_zones = individual_zones
|
|
|
|
def covers(self, position: Point) -> bool:
|
|
return self.threat_zones.intersects(dcs_to_shapely_point(position))
|
|
|
|
def iter_threatening_sams(
|
|
self, position: Point
|
|
) -> Iterator[TheaterGroundObject[Any]]:
|
|
for tgo, zone in self.individual_zones:
|
|
if zone.intersects(dcs_to_shapely_point(position)):
|
|
yield tgo
|
|
|
|
@classmethod
|
|
def from_theater(cls, theater: ConflictTheater, player: bool) -> SamEngagementZones:
|
|
commit_regions = []
|
|
individual_zones = []
|
|
for cp in theater.control_points_for(player):
|
|
for tgo in cp.connected_objectives:
|
|
if (region := cls.threat_region(tgo)) is not None:
|
|
commit_regions.append(region)
|
|
individual_zones.append((tgo, region))
|
|
return SamEngagementZones(unary_union(commit_regions), individual_zones)
|
|
|
|
@classmethod
|
|
def threat_region(cls, tgo: TheaterGroundObject[Any]) -> Optional[ThreatPoly]:
|
|
threat_range = tgo.max_threat_range()
|
|
if threat_range <= meters(0):
|
|
return None
|
|
return dcs_to_shapely_point(tgo.position).buffer(threat_range.meters)
|