mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
PBO: IADS
Finishes/Fixes part of advanced IADS in back-end
This commit is contained in:
parent
6e555167e0
commit
244415b721
@ -33,7 +33,6 @@ import { threatZonesUpdated } from "./threatZonesSlice";
|
||||
import { unculledZonesUpdated } from "./unculledZonesSlice";
|
||||
import { LatLng } from "leaflet";
|
||||
import { updateIadsConnection, removeIadsConnection } from "./iadsNetworkSlice";
|
||||
import { IadsConnection } from "./_liberationApi";
|
||||
import { supplyRoutesUpdated } from "./supplyRoutesSlice";
|
||||
|
||||
interface GameUpdateEvents {
|
||||
|
||||
@ -839,10 +839,9 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
# All the attached TGOs have either been depopulated or captured. Tell the UI to
|
||||
# update their state. Also update orientation and IADS state for specific tgos
|
||||
for tgo in self.connected_objectives:
|
||||
if isinstance(tgo, IadsGroundObject) or isinstance(
|
||||
tgo, VehicleGroupGroundObject
|
||||
):
|
||||
if isinstance(tgo, IadsGroundObject):
|
||||
is_vehicle_go = isinstance(tgo, VehicleGroupGroundObject)
|
||||
if tgo.is_iads or is_vehicle_go:
|
||||
if tgo.is_iads:
|
||||
game.theater.iads_network.update_tgo(tgo, events)
|
||||
conflict_heading = game.theater.heading_to_conflict_from(tgo.position)
|
||||
tgo.rotate(conflict_heading or tgo.heading)
|
||||
|
||||
@ -120,13 +120,6 @@ class IadsNetwork:
|
||||
# Skip culled ground objects
|
||||
continue
|
||||
|
||||
# HOTFIX! Skip non-static nodes with no alive units left
|
||||
# Delete this as soon as PRs #2285, #2286 & #2287 are merged
|
||||
unit_count = len(node.group.units)
|
||||
is_static = node.group.units[0].is_static if unit_count > 0 else False
|
||||
if node.group.alive_units == 0 and not is_static:
|
||||
continue
|
||||
|
||||
# SkynetNode.from_group(node.group) may raise an exception
|
||||
# (originating from SkynetNode.dcs_name_for_group)
|
||||
# but if it does, we want to know because it's supposed to be impossible afaict
|
||||
@ -141,8 +134,53 @@ class IadsNetwork:
|
||||
skynet_nodes.append(skynet_node)
|
||||
return skynet_nodes
|
||||
|
||||
def _update_iads_comms_and_power(
|
||||
self, tgo: TheaterGroundObject, events: GameUpdateEvents
|
||||
) -> None:
|
||||
assert self.advanced_iads, "_update_iads_comms_and_power requires advanced IADS"
|
||||
is_comm_or_power = IadsRole.for_category(tgo.category).is_comms_or_power
|
||||
assert is_comm_or_power, "Invalid TGO was given for _update_iads_building"
|
||||
|
||||
"""
|
||||
Delete/Update connections to the comm tower/power station
|
||||
If this function is called, it should imply only 2 possibilities (unless I missed one):
|
||||
1) A capture event occurred, thus the building now belongs to the capturing team
|
||||
=> All connections to this building are to the enemy, thus delete them
|
||||
(mind that no new connections could have been formed since all TGOs were depopulated)
|
||||
2) The building was destroyed during a mission
|
||||
=> In this case we don't need to delete the connections
|
||||
instead we just update the nodes that connect to this building
|
||||
because those connections are still coming from friendly TGOs
|
||||
Given the above, we should be able to use the following implications:
|
||||
If the building is friendly compared to the node that we're checking
|
||||
=> Building was destroyed during mission
|
||||
=> Update nodes that connect to this building
|
||||
Otherwise if the building is not friendly compared to the node we're checking
|
||||
=> Capture event occurred
|
||||
=> Delete all connections to this building
|
||||
|
||||
TODO: clean up the code below by wrapping comm towers and power stations
|
||||
preferably in a class like IadsNetworkNode, keeping a reference to connected nodes
|
||||
"""
|
||||
for node in self.nodes:
|
||||
to_delete = []
|
||||
for cID in node.connections:
|
||||
group = node.connections[cID]
|
||||
if group.ground_object is tgo:
|
||||
if self._is_friendly(node, tgo):
|
||||
events.update_iads_node(node)
|
||||
else:
|
||||
to_delete.append(cID)
|
||||
events.delete_iads_connection(cID)
|
||||
for cID in to_delete:
|
||||
del node.connections[cID]
|
||||
if not self.iads_config:
|
||||
self._update_network(tgo, events)
|
||||
|
||||
def update_tgo(self, tgo: TheaterGroundObject, events: GameUpdateEvents) -> None:
|
||||
"""Update the IADS Network for the given TGO"""
|
||||
if IadsRole.for_category(tgo.category).is_comms_or_power:
|
||||
return self._update_iads_comms_and_power(tgo, events)
|
||||
# Remove existing nodes for the given tgo
|
||||
for cn in self.nodes:
|
||||
if cn.group.ground_object == tgo:
|
||||
@ -275,3 +313,23 @@ class IadsNetwork:
|
||||
<= node.group.iads_role.connection_range.meters
|
||||
):
|
||||
node.add_connection_for_tgo(nearby_go)
|
||||
|
||||
def _is_friendly(self, node: IadsNetworkNode, tgo: TheaterGroundObject) -> bool:
|
||||
node_friendly = node.group.ground_object.is_friendly(True)
|
||||
tgo_friendly = tgo.is_friendly(True)
|
||||
return node_friendly == tgo_friendly
|
||||
|
||||
def _update_network(
|
||||
self, tgo: TheaterGroundObject, events: GameUpdateEvents
|
||||
) -> None:
|
||||
if tgo.is_dead:
|
||||
return
|
||||
iads_role = IadsRole.for_category(tgo.category)
|
||||
if not iads_role.is_comms_or_power:
|
||||
return
|
||||
for node in self.nodes:
|
||||
dist = node.group.ground_object.position.distance_to_point(tgo.position)
|
||||
in_range = dist < iads_role.connection_range.meters
|
||||
if in_range and self._is_friendly(node, tgo):
|
||||
node.add_connection_for_tgo(tgo)
|
||||
events.update_iads_node(node)
|
||||
|
||||
@ -79,3 +79,10 @@ class IadsRole(Enum):
|
||||
IadsRole.NO_BEHAVIOR,
|
||||
IadsRole.POINT_DEFENSE,
|
||||
]
|
||||
|
||||
@property
|
||||
def is_comms_or_power(self) -> bool:
|
||||
return self in [
|
||||
IadsRole.POWER_SOURCE,
|
||||
IadsRole.CONNECTION_NODE,
|
||||
]
|
||||
|
||||
@ -267,6 +267,10 @@ class TheaterGroundObject(MissionTarget, SidcDescribable, ABC):
|
||||
"""Should this TGO head towards the closest conflict to work properly?"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_iads(self) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
class BuildingGroundObject(TheaterGroundObject):
|
||||
def __init__(
|
||||
@ -353,6 +357,10 @@ class NavalGroundObject(TheaterGroundObject, ABC):
|
||||
def purchasable(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_iads(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class GenericCarrierGroundObject(NavalGroundObject, ABC):
|
||||
@property
|
||||
@ -490,6 +498,10 @@ class IadsGroundObject(TheaterGroundObject, ABC):
|
||||
def should_head_to_conflict(self) -> bool:
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_iads(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# The SamGroundObject represents all type of AA
|
||||
# The TGO can have multiple types of units (AAA,SAM,Support...)
|
||||
@ -630,3 +642,7 @@ class IadsBuildingGroundObject(BuildingGroundObject):
|
||||
for mission_type in super().mission_types(for_player):
|
||||
if mission_type not in skippers:
|
||||
yield mission_type
|
||||
|
||||
@property
|
||||
def is_iads(self) -> bool:
|
||||
return True
|
||||
|
||||
@ -63,6 +63,9 @@ class TheaterUnit:
|
||||
self.alive = False
|
||||
self.ground_object.invalidate_threat_poly()
|
||||
events.update_tgo(self.ground_object)
|
||||
if self.ground_object.is_iads:
|
||||
iads = self.ground_object.control_point.coalition.game.theater.iads_network
|
||||
iads.update_tgo(self.ground_object, events)
|
||||
|
||||
@property
|
||||
def unit_name(self) -> str:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user