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 { unculledZonesUpdated } from "./unculledZonesSlice";
|
||||||
import { LatLng } from "leaflet";
|
import { LatLng } from "leaflet";
|
||||||
import { updateIadsConnection, removeIadsConnection } from "./iadsNetworkSlice";
|
import { updateIadsConnection, removeIadsConnection } from "./iadsNetworkSlice";
|
||||||
import { IadsConnection } from "./_liberationApi";
|
|
||||||
import { supplyRoutesUpdated } from "./supplyRoutesSlice";
|
import { supplyRoutesUpdated } from "./supplyRoutesSlice";
|
||||||
|
|
||||||
interface GameUpdateEvents {
|
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
|
# 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
|
# update their state. Also update orientation and IADS state for specific tgos
|
||||||
for tgo in self.connected_objectives:
|
for tgo in self.connected_objectives:
|
||||||
if isinstance(tgo, IadsGroundObject) or isinstance(
|
is_vehicle_go = isinstance(tgo, VehicleGroupGroundObject)
|
||||||
tgo, VehicleGroupGroundObject
|
if tgo.is_iads or is_vehicle_go:
|
||||||
):
|
if tgo.is_iads:
|
||||||
if isinstance(tgo, IadsGroundObject):
|
|
||||||
game.theater.iads_network.update_tgo(tgo, events)
|
game.theater.iads_network.update_tgo(tgo, events)
|
||||||
conflict_heading = game.theater.heading_to_conflict_from(tgo.position)
|
conflict_heading = game.theater.heading_to_conflict_from(tgo.position)
|
||||||
tgo.rotate(conflict_heading or tgo.heading)
|
tgo.rotate(conflict_heading or tgo.heading)
|
||||||
|
|||||||
@ -120,13 +120,6 @@ class IadsNetwork:
|
|||||||
# Skip culled ground objects
|
# Skip culled ground objects
|
||||||
continue
|
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
|
# SkynetNode.from_group(node.group) may raise an exception
|
||||||
# (originating from SkynetNode.dcs_name_for_group)
|
# (originating from SkynetNode.dcs_name_for_group)
|
||||||
# but if it does, we want to know because it's supposed to be impossible afaict
|
# 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)
|
skynet_nodes.append(skynet_node)
|
||||||
return skynet_nodes
|
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:
|
def update_tgo(self, tgo: TheaterGroundObject, events: GameUpdateEvents) -> None:
|
||||||
"""Update the IADS Network for the given TGO"""
|
"""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
|
# Remove existing nodes for the given tgo
|
||||||
for cn in self.nodes:
|
for cn in self.nodes:
|
||||||
if cn.group.ground_object == tgo:
|
if cn.group.ground_object == tgo:
|
||||||
@ -275,3 +313,23 @@ class IadsNetwork:
|
|||||||
<= node.group.iads_role.connection_range.meters
|
<= node.group.iads_role.connection_range.meters
|
||||||
):
|
):
|
||||||
node.add_connection_for_tgo(nearby_go)
|
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.NO_BEHAVIOR,
|
||||||
IadsRole.POINT_DEFENSE,
|
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?"""
|
"""Should this TGO head towards the closest conflict to work properly?"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_iads(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class BuildingGroundObject(TheaterGroundObject):
|
class BuildingGroundObject(TheaterGroundObject):
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -353,6 +357,10 @@ class NavalGroundObject(TheaterGroundObject, ABC):
|
|||||||
def purchasable(self) -> bool:
|
def purchasable(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_iads(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class GenericCarrierGroundObject(NavalGroundObject, ABC):
|
class GenericCarrierGroundObject(NavalGroundObject, ABC):
|
||||||
@property
|
@property
|
||||||
@ -490,6 +498,10 @@ class IadsGroundObject(TheaterGroundObject, ABC):
|
|||||||
def should_head_to_conflict(self) -> bool:
|
def should_head_to_conflict(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_iads(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# The SamGroundObject represents all type of AA
|
# The SamGroundObject represents all type of AA
|
||||||
# The TGO can have multiple types of units (AAA,SAM,Support...)
|
# 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):
|
for mission_type in super().mission_types(for_player):
|
||||||
if mission_type not in skippers:
|
if mission_type not in skippers:
|
||||||
yield mission_type
|
yield mission_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_iads(self) -> bool:
|
||||||
|
return True
|
||||||
|
|||||||
@ -63,6 +63,9 @@ class TheaterUnit:
|
|||||||
self.alive = False
|
self.alive = False
|
||||||
self.ground_object.invalidate_threat_poly()
|
self.ground_object.invalidate_threat_poly()
|
||||||
events.update_tgo(self.ground_object)
|
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
|
@property
|
||||||
def unit_name(self) -> str:
|
def unit_name(self) -> str:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user