mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
improved the validation for planned transfers
- instead of only checking if the transfer destination was captured it now checks if there is a valid route between origin and destination. This also ensures that there will be a check if the current position or next_stop was captured and therefore the transfer should be disbanded. - disband uncompletable transfer before planning or performing (also when user cheated a base capture)
This commit is contained in:
parent
2a5793e8ce
commit
ac088ea692
@ -47,6 +47,7 @@ Saves from 4.0.0 are compatible with 4.1.0.
|
||||
* **[Mission Generation]** Fixed problem with opfor planning missions against sold ground objects like SAMs
|
||||
* **[Mission Generation]** The legacy always-available tanker option no longer prevents mission creation.
|
||||
* **[Mission Generation]** Prevent the creation of a transfer order with 0 units for a rare situtation when a point was captured.
|
||||
* **[Mission Generation]** Planned transfers which will be impossible after a base capture will no longer prevent the mission result submit.
|
||||
* **[Mission Generation]** Fix occasional KeyError preventing mission generation when all units of the same type in a convoy were killed.
|
||||
* **[UI]** Statistics window tick marks are now always integers.
|
||||
* **[UI]** Statistics window now shows the correct info for the turn
|
||||
|
||||
@ -166,21 +166,58 @@ class TransferOrder:
|
||||
return self.transport.find_escape_route()
|
||||
return None
|
||||
|
||||
def proceed(self) -> None:
|
||||
if not self.destination.is_friendly(self.player):
|
||||
logging.info(f"Transfer destination {self.destination} was captured.")
|
||||
if self.position.is_friendly(self.player):
|
||||
self.disband_at(self.position)
|
||||
elif (escape_route := self.find_escape_route()) is not None:
|
||||
self.disband_at(escape_route)
|
||||
else:
|
||||
logging.info(
|
||||
f"No escape route available. Units were surrounded and destroyed "
|
||||
"during transfer."
|
||||
)
|
||||
self.kill_all()
|
||||
return
|
||||
def disband(self) -> None:
|
||||
"""
|
||||
Disbands the specific transfer at the current position if friendly, at a
|
||||
possible escape route or kills all units if none is possible
|
||||
"""
|
||||
if self.position.is_friendly(self.player):
|
||||
self.disband_at(self.position)
|
||||
elif (escape_route := self.find_escape_route()) is not None:
|
||||
self.disband_at(escape_route)
|
||||
else:
|
||||
logging.info(
|
||||
f"No escape route available. Units were surrounded and destroyed "
|
||||
"during transfer."
|
||||
)
|
||||
self.kill_all()
|
||||
|
||||
def is_completable(self, network: TransitNetwork) -> bool:
|
||||
"""
|
||||
Checks if the transfer can be completed with the current theater state / transit
|
||||
network to ensure that there is possible route between the current position and
|
||||
the planned destination. This also ensures that the points are friendly.
|
||||
"""
|
||||
if self.transport is None:
|
||||
# Check if unplanned transfers could be completed
|
||||
if not self.position.is_friendly(self.player):
|
||||
logging.info(
|
||||
f"Current position ({self.position}) "
|
||||
f"of the halting transfer was captured."
|
||||
)
|
||||
return False
|
||||
if not network.has_path_between(self.position, self.destination):
|
||||
logging.info(
|
||||
f"Destination of transfer ({self.destination}) "
|
||||
f"can not be reached anymore."
|
||||
)
|
||||
return False
|
||||
|
||||
if self.transport is not None and not self.next_stop.is_friendly(self.player):
|
||||
# check if already proceeding transfers can reach the next stop
|
||||
logging.info(
|
||||
f"The next stop of the transfer ({self.next_stop}) "
|
||||
f"was captured while transfer was on route."
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def proceed(self) -> None:
|
||||
"""
|
||||
Let the transfer proceed to the next stop and disbands it if the next stop
|
||||
is the destination
|
||||
"""
|
||||
if self.transport is None:
|
||||
return
|
||||
|
||||
@ -637,6 +674,12 @@ class PendingTransfers:
|
||||
transfer.origin.base.commission_units(transfer.units)
|
||||
|
||||
def perform_transfers(self) -> None:
|
||||
"""
|
||||
Performs completable transfers from the list of pending transfers and adds
|
||||
uncompleted transfers which are en route back to the list of pending transfers.
|
||||
Disbands all convoys and cargo ships
|
||||
"""
|
||||
self.disband_uncompletable_transfers()
|
||||
incomplete = []
|
||||
for transfer in self.pending_transfers:
|
||||
transfer.proceed()
|
||||
@ -647,10 +690,31 @@ class PendingTransfers:
|
||||
self.cargo_ships.disband_all()
|
||||
|
||||
def plan_transports(self) -> None:
|
||||
"""
|
||||
Plan transports for all pending and completable transfers which don't have a
|
||||
transport assigned already. This calculates the shortest path between current
|
||||
position and destination on every execution to ensure the route is adopted to
|
||||
recent changes in the theater state / transit network.
|
||||
"""
|
||||
self.disband_uncompletable_transfers()
|
||||
for transfer in self.pending_transfers:
|
||||
if transfer.transport is None:
|
||||
self.arrange_transport(transfer)
|
||||
|
||||
def disband_uncompletable_transfers(self) -> None:
|
||||
"""
|
||||
Disbands all transfers from the list of pending_transfers which can not be
|
||||
completed anymore because the theater state changed or the transit network does
|
||||
not allow a route to the destination anymore
|
||||
"""
|
||||
completable_transfers = []
|
||||
for transfer in self.pending_transfers:
|
||||
if not transfer.is_completable(self.network_for(transfer.position)):
|
||||
transfer.disband()
|
||||
else:
|
||||
completable_transfers.append(transfer)
|
||||
self.pending_transfers = completable_transfers
|
||||
|
||||
def order_airlift_assets(self) -> None:
|
||||
for control_point in self.game.theater.control_points_for(self.player):
|
||||
if self.game.air_wing_for(control_point.captured).can_auto_plan(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user