mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Prevent transfer splitting from leaving empty units.
If the transport were able to move exactly the quantity of units of the
given type remaining in the transfer without moving the whole order, the
transfer order would be left with instructions to transfer zero of that
unit. That's an invariant violation, and was resulting in _later_
transfers attempting to create a convoy with zero units, which pydcs
rightly rejects.
For example: if 2 Abrams and 2 Paladins are ordered to transfer from a
disconnected FOB to a distant location that is connected by road, and
only two cargo slots are available, that transfer could be split into:
```
{
Abrams: 2
}
```
and
```
{
Abrams: 0,
Paladin: 2
}
```
Depending on the route, those airlifted units might end up still needing
road transit (we prefer short airlifts rather than direct routes because
it gives the player more opportunities to intercept enemy convoys). The
current turn would airlift the Abrams-only group and the Paladin group
would wait. On the next turn the Abrams would travel by road and the
Paladins would be airlifted. On the _third_ turn, the Paladins (and zero
Abrams) would generate an invalid convoy.
Fixes https://github.com/dcs-liberation/dcs_liberation/issues/2761.
This commit is contained in:
parent
bcb7d059c0
commit
b860d72c2d
@ -15,6 +15,8 @@ Saves from 6.x are not compatible with 7.0.
|
|||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
|
* **[Campaign]** Fixed a longstanding bug where oversized airlifts could corrupt a save with empty convoys.
|
||||||
|
|
||||||
# 6.1.1
|
# 6.1.1
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|||||||
@ -122,12 +122,19 @@ class TransferOrder:
|
|||||||
self.units.clear()
|
self.units.clear()
|
||||||
|
|
||||||
def kill_unit(self, unit_type: GroundUnitType) -> None:
|
def kill_unit(self, unit_type: GroundUnitType) -> None:
|
||||||
if unit_type not in self.units or not self.units[unit_type]:
|
self.take_units(unit_type, 1)
|
||||||
raise KeyError(f"{self} has no {unit_type} remaining")
|
|
||||||
if self.units[unit_type] == 1:
|
def take_units(self, unit_type: GroundUnitType, count: int) -> None:
|
||||||
|
"""Removes units from the transfer without returning them to inventory.
|
||||||
|
|
||||||
|
The caller takes ownership of the units.
|
||||||
|
"""
|
||||||
|
if unit_type not in self.units or self.units[unit_type] < count:
|
||||||
|
raise KeyError(f"{self} has fewer than {count} {unit_type} remaining")
|
||||||
|
|
||||||
|
self.units[unit_type] -= count
|
||||||
|
if not self.units[unit_type]:
|
||||||
del self.units[unit_type]
|
del self.units[unit_type]
|
||||||
else:
|
|
||||||
self.units[unit_type] -= 1
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self) -> int:
|
def size(self) -> int:
|
||||||
@ -612,7 +619,7 @@ class PendingTransfers:
|
|||||||
for unit_type, remaining in transfer.units.items():
|
for unit_type, remaining in transfer.units.items():
|
||||||
take = min(remaining, size)
|
take = min(remaining, size)
|
||||||
size -= take
|
size -= take
|
||||||
transfer.units[unit_type] -= take
|
transfer.take_units(unit_type, take)
|
||||||
units[unit_type] = take
|
units[unit_type] = take
|
||||||
if not size:
|
if not size:
|
||||||
break
|
break
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user