mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 15:27:50 +07:00
Fix aircraft disappearing when their carrier is teleported (#7035)
* Fix carrier teleporting without moving airplanes * Unit test to ensure aircraft and carriers are teleported togother * Fix other cases where teleportation may occur * Simplify unit test condition * Update linting and move return condition * Allow override for teleporting transported units * Make sure test catches if transported units get deleted * Reviews
This commit is contained in:

committed by
GitHub

parent
02226018fa
commit
12674ed69e
@ -370,10 +370,12 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
* Displace a unit - choose a viable tile close by if possible and 'teleport' the unit there.
|
||||
* This will not use movement points or check for a possible route.
|
||||
* It is used e.g. if an enemy city expands its borders, or trades or diplomacy change a unit's
|
||||
* allowed position.
|
||||
* allowed position. Does not teleport transported units on their own, these are teleported when
|
||||
* the transporting unit is moved.
|
||||
* CAN DESTROY THE UNIT.
|
||||
*/
|
||||
fun teleportToClosestMoveableTile() {
|
||||
if (unit.isTransported) return // handled when carrying unit is teleported
|
||||
var allowedTile: TileInfo? = null
|
||||
var distance = 0
|
||||
// When we didn't limit the allowed distance the game would sometimes spend a whole minute looking for a suitable tile.
|
||||
@ -394,6 +396,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (allowedTile != null) break
|
||||
}
|
||||
}
|
||||
val origin = unit.getTile()
|
||||
if (allowedTile != null) {
|
||||
unit.removeFromTile() // we "teleport" them away
|
||||
unit.putInTile(allowedTile)
|
||||
@ -401,6 +404,15 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (unit.isSleeping() || unit.isFortified())
|
||||
unit.action = null
|
||||
unit.mostRecentMoveType = UnitMovementMemoryType.UnitTeleported
|
||||
|
||||
// bring along the payloads
|
||||
val payloadUnits = origin.getUnits().filter { it.isTransported && unit.canTransport(it) }.toList()
|
||||
for (payload in payloadUnits) {
|
||||
payload.removeFromTile()
|
||||
payload.putInTile(allowedTile)
|
||||
payload.isTransported = true // restore the flag to not leave the payload in the city
|
||||
payload.mostRecentMoveType = UnitMovementMemoryType.UnitTeleported
|
||||
}
|
||||
}
|
||||
// it's possible that there is no close tile, and all the guy's cities are full.
|
||||
// Nothing we can do.
|
||||
|
@ -100,7 +100,7 @@ class UnitMovementAlgorithmsTests {
|
||||
if (terrain.impassable) continue
|
||||
tile.baseTerrain = terrain.name
|
||||
tile.setTransients()
|
||||
|
||||
|
||||
for (type in ruleSet.unitTypes) {
|
||||
unit.baseUnit = BaseUnit().apply { unitType = type.key; ruleset = ruleSet }
|
||||
Assert.assertTrue("%s cannot be at %s".format(type.key, terrain.name),
|
||||
@ -197,7 +197,7 @@ class UnitMovementAlgorithmsTests {
|
||||
civInfo.tech.techsResearched.remove("Astronomy")
|
||||
|
||||
Assert.assertTrue("$type cannot be in Ocean until Astronomy",
|
||||
(unit.baseUnit.isMelee() || unit.baseUnit.isRanged())
|
||||
(unit.baseUnit.isMelee() || unit.baseUnit.isRanged())
|
||||
!= unit.movement.canPassThrough(tile))
|
||||
|
||||
civInfo.tech.techsResearched.add("Astronomy")
|
||||
@ -208,7 +208,7 @@ class UnitMovementAlgorithmsTests {
|
||||
fun canNOTPassThroughTileWithEnemyUnits() {
|
||||
tile.baseTerrain = Constants.grassland
|
||||
tile.setTransients()
|
||||
|
||||
|
||||
unit.currentTile = tile
|
||||
|
||||
val otherCiv = CivilizationInfo()
|
||||
@ -451,4 +451,41 @@ class UnitMovementAlgorithmsTests {
|
||||
unit.currentTile == newTiles.last() && otherUnit.civInfo == unit.civInfo)
|
||||
}
|
||||
|
||||
}
|
||||
@Test
|
||||
fun `can teleport transport and its transported units to the same tile`() {
|
||||
civInfo.nation.name = Constants.spectator
|
||||
|
||||
tile.baseTerrain = Constants.ocean
|
||||
tile.position.set(0f, 0f)
|
||||
tile.setTransients()
|
||||
createOpponentCivAndCity()
|
||||
val newTiles = generateTileCopies(3)
|
||||
|
||||
setupMilitaryUnitInTheCurrentTile("Aircraft Carrier")
|
||||
unit.owner = civInfo.civName
|
||||
unit.civInfo = civInfo
|
||||
unit.baseUnit.uniques.add("Can carry [2] [Aircraft] units")
|
||||
unit.updateUniques(ruleSet)
|
||||
civInfo.addUnit(unit, false)
|
||||
|
||||
val fighters = ArrayList<MapUnit>()
|
||||
for (i in 0..1) {
|
||||
val newFighter = MapUnit()
|
||||
newFighter.baseUnit = BaseUnit().apply { unitType = "Fighter"; ruleset = ruleSet }
|
||||
newFighter.owner = civInfo.civName
|
||||
newFighter.civInfo = civInfo
|
||||
newFighter.currentTile = unit.getTile()
|
||||
tile.airUnits += newFighter
|
||||
newFighter.name = "Fighter"
|
||||
newFighter.isTransported = true
|
||||
civInfo.addUnit(newFighter, false)
|
||||
fighters += newFighter
|
||||
}
|
||||
|
||||
// simulate ejecting all units within foreign territory
|
||||
for (unit in civInfo.getCivUnits()) unit.movement.teleportToClosestMoveableTile()
|
||||
Assert.assertTrue("Transport and transported units must be teleported to the same tile",
|
||||
civInfo.getCivUnits().toList().size == 3 && civInfo.getCivUnits().all { it.getTile() == newTiles.last() })
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user