mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Handle threat/detection per group.
Some SAMs have multiple groups (such as an SA-10 group with its accompanying SA-15 and SA-19 groups). This shows each group's threat and detection separately on the map, and also makes it so that an SA-10 with dead radars will no longer contribute to the threat zone just because the shilka next to it still has a functioning radar. https://github.com/Khopa/dcs_liberation/issues/647 Fixes https://github.com/Khopa/dcs_liberation/issues/672
This commit is contained in:
parent
d946a9e526
commit
a6dc3d2aff
@ -15,6 +15,7 @@ Saves from 2.3 are not compatible with 2.4.
|
||||
* **[Balance]** Opfor now gains income using the same rules as the player, significantly increasing their income relative to the player for most campaigns.
|
||||
* **[Economy]** FOBs generate only $10M per turn (previously $20M like airbases).
|
||||
* **[Economy]** Carriers and off-map spawns generate no income (previously $20M like airbases).
|
||||
* **[UI]** Multi-SAM objectives now show threat and detection rings per group.
|
||||
|
||||
# 2.3.3
|
||||
|
||||
|
||||
@ -157,12 +157,11 @@ class TheaterGroundObject(MissionTarget):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _max_range_of_type(self, range_type: str) -> Distance:
|
||||
def _max_range_of_type(self, group: Group, range_type: str) -> Distance:
|
||||
if not self.might_have_aa:
|
||||
return meters(0)
|
||||
|
||||
max_range = meters(0)
|
||||
for group in self.groups:
|
||||
for u in group.units:
|
||||
unit = db.unit_type_from_name(u.type)
|
||||
if unit is None:
|
||||
@ -176,20 +175,18 @@ class TheaterGroundObject(MissionTarget):
|
||||
max_range = max(max_range, meters(unit_range))
|
||||
return max_range
|
||||
|
||||
@property
|
||||
def detection_range(self) -> Distance:
|
||||
return self._max_range_of_type("detection_range")
|
||||
def detection_range(self, group: Group) -> Distance:
|
||||
return self._max_range_of_type(group, "detection_range")
|
||||
|
||||
@property
|
||||
def threat_range(self) -> Distance:
|
||||
if not self.detection_range:
|
||||
def threat_range(self, group: Group) -> Distance:
|
||||
if not self.detection_range(group):
|
||||
# For simple SAMs like shilkas, the unit has both a threat and
|
||||
# detection range. For complex sites like SA-2s, the launcher has a
|
||||
# threat range and the search/track radars have detection ranges. If
|
||||
# the site has no detection range it has no radars and can't fire,
|
||||
# so it's not actually a threat even if it still has launchers.
|
||||
return meters(0)
|
||||
return self._max_range_of_type("threat_range")
|
||||
return self._max_range_of_type(group, "threat_range")
|
||||
|
||||
|
||||
class BuildingGroundObject(TheaterGroundObject):
|
||||
|
||||
@ -95,9 +95,10 @@ class ThreatZones:
|
||||
airbases.append(point.buffer(cap_threat_range.meters))
|
||||
|
||||
for tgo in control_point.ground_objects:
|
||||
threat_range = tgo.threat_range
|
||||
# Any system with a shorter range than this is not worth even
|
||||
# avoiding.
|
||||
for group in tgo.groups:
|
||||
threat_range = tgo.threat_range(group)
|
||||
# Any system with a shorter range than this is not worth
|
||||
# even avoiding.
|
||||
if threat_range > nautical_miles(3):
|
||||
point = ShapelyPoint(tgo.position.x, tgo.position.y)
|
||||
threat_zone = point.buffer(threat_range.meters)
|
||||
|
||||
@ -28,6 +28,7 @@ from PySide2.QtWidgets import (
|
||||
from dcs import Point
|
||||
from dcs.planes import F_16C_50
|
||||
from dcs.mapping import point_from_heading
|
||||
from dcs.unitgroup import Group
|
||||
from shapely.geometry import (
|
||||
LineString,
|
||||
MultiPolygon,
|
||||
@ -36,7 +37,7 @@ from shapely.geometry import (
|
||||
)
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game import Game, db
|
||||
from game import Game
|
||||
from game.navmesh import NavMesh
|
||||
from game.theater import ControlPoint, Enum
|
||||
from game.theater.conflicttheater import FrontLine, ReferencePoint
|
||||
@ -446,10 +447,10 @@ class QLiberationMap(QGraphicsView):
|
||||
return ((DisplayOptions.sam_ranges and cp.captured) or
|
||||
(DisplayOptions.enemy_sam_ranges and not cp.captured))
|
||||
|
||||
def draw_threat_range(self, scene: QGraphicsScene, ground_object: TheaterGroundObject, cp: ControlPoint) -> None:
|
||||
def draw_threat_range(self, scene: QGraphicsScene, group: Group, ground_object: TheaterGroundObject, cp: ControlPoint) -> None:
|
||||
go_pos = self._transform_point(ground_object.position)
|
||||
detection_range = ground_object.detection_range
|
||||
threat_range = ground_object.threat_range
|
||||
detection_range = ground_object.detection_range(group)
|
||||
threat_range = ground_object.threat_range(group)
|
||||
if threat_range:
|
||||
threat_pos = self._transform_point(
|
||||
ground_object.position + Point(threat_range.meters,
|
||||
@ -482,7 +483,8 @@ class QLiberationMap(QGraphicsView):
|
||||
|
||||
should_display = self.should_display_ground_objects_at(cp)
|
||||
if ground_object.might_have_aa and should_display:
|
||||
self.draw_threat_range(scene, ground_object, cp)
|
||||
for group in ground_object.groups:
|
||||
self.draw_threat_range(scene, group, ground_object, cp)
|
||||
added_objects.append(ground_object.obj_name)
|
||||
|
||||
def reload_scene(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user