mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +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]** 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]** 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]** 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.
|
* **[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 tick marks are now always integers.
|
||||||
* **[UI]** Statistics window now shows the correct info for the turn
|
* **[UI]** Statistics window now shows the correct info for the turn
|
||||||
|
|||||||
@ -166,21 +166,58 @@ class TransferOrder:
|
|||||||
return self.transport.find_escape_route()
|
return self.transport.find_escape_route()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def proceed(self) -> None:
|
def disband(self) -> None:
|
||||||
if not self.destination.is_friendly(self.player):
|
"""
|
||||||
logging.info(f"Transfer destination {self.destination} was captured.")
|
Disbands the specific transfer at the current position if friendly, at a
|
||||||
if self.position.is_friendly(self.player):
|
possible escape route or kills all units if none is possible
|
||||||
self.disband_at(self.position)
|
"""
|
||||||
elif (escape_route := self.find_escape_route()) is not None:
|
if self.position.is_friendly(self.player):
|
||||||
self.disband_at(escape_route)
|
self.disband_at(self.position)
|
||||||
else:
|
elif (escape_route := self.find_escape_route()) is not None:
|
||||||
logging.info(
|
self.disband_at(escape_route)
|
||||||
f"No escape route available. Units were surrounded and destroyed "
|
else:
|
||||||
"during transfer."
|
logging.info(
|
||||||
)
|
f"No escape route available. Units were surrounded and destroyed "
|
||||||
self.kill_all()
|
"during transfer."
|
||||||
return
|
)
|
||||||
|
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:
|
if self.transport is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -637,6 +674,12 @@ class PendingTransfers:
|
|||||||
transfer.origin.base.commission_units(transfer.units)
|
transfer.origin.base.commission_units(transfer.units)
|
||||||
|
|
||||||
def perform_transfers(self) -> None:
|
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 = []
|
incomplete = []
|
||||||
for transfer in self.pending_transfers:
|
for transfer in self.pending_transfers:
|
||||||
transfer.proceed()
|
transfer.proceed()
|
||||||
@ -647,10 +690,31 @@ class PendingTransfers:
|
|||||||
self.cargo_ships.disband_all()
|
self.cargo_ships.disband_all()
|
||||||
|
|
||||||
def plan_transports(self) -> None:
|
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:
|
for transfer in self.pending_transfers:
|
||||||
if transfer.transport is None:
|
if transfer.transport is None:
|
||||||
self.arrange_transport(transfer)
|
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:
|
def order_airlift_assets(self) -> None:
|
||||||
for control_point in self.game.theater.control_points_for(self.player):
|
for control_point in self.game.theater.control_points_for(self.player):
|
||||||
if self.game.air_wing_for(control_point.captured).can_auto_plan(
|
if self.game.air_wing_for(control_point.captured).can_auto_plan(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user