Fixed a crash when a plane tried to enter a full city (#6652)

This would only occur if the plane was damaged and looking for a spot to 
heal, and had no tile to go to with >0 healing. It would then try to 
head towards the nearest city, regardless of whether it could enter 
that. As it's an air unit, 'head towards' means 'fly there directly this 
turn', which obviously caused crashes if the unit couldn't enter that 
tile.
This commit is contained in:
Xander Lenstra 2022-04-30 22:08:48 +02:00 committed by GitHub
parent 8133f40f74
commit 1a050bdaa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 8 deletions

View File

@ -280,17 +280,36 @@ object UnitAutomation {
.filter { it !in dangerousTiles && unit.movement.canMoveTo(it) }
val tilesByHealingRate = viableTilesForHealing.groupBy { unit.rankTileForHealing(it) }
if (tilesByHealingRate.keys.none { it != 0 }) { // We can't heal here at all! We're probably embarked
val reachableCityTile = unit.civInfo.cities.asSequence().map { it.getCenterTile() }
if (tilesByHealingRate.keys.all { it == 0 }) { // We can't heal here at all! We're probably embarked
if (!unit.baseUnit.movesLikeAirUnits()) {
val reachableCityTile = unit.civInfo.cities.asSequence()
.map { it.getCenterTile() }
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
.firstOrNull { unit.movement.canReach(it) }
if (reachableCityTile != null) unit.movement.headTowards(reachableCityTile)
else wander(unit)
if (reachableCityTile != null) unit.movement.headTowards(reachableCityTile)
else wander(unit)
return true
}
// Try to get closer to an empty city
val emptyCities = unit.civInfo.cities.asSequence()
.map { it.getCenterTile() }
.filter { unit.movement.canMoveTo(it) }
if (emptyCities.none()) return false // Nowhere to move to heal
val nextTileToMove = unitDistanceToTiles.keys
.filter { unit.movement.canMoveTo(it) }
.minByOrNull { tile ->
emptyCities.minOf { city ->
city.aerialDistanceTo(tile)
}
} ?: return false
unit.movement.moveToTile(nextTileToMove)
return true
}
val bestTilesForHealing = tilesByHealingRate.maxByOrNull { it.key }!!.value
val bestTileForHealing = bestTilesForHealing.maxByOrNull { it.getDefensiveBonus() }!!
val bestTilesForHealing = tilesByHealingRate.maxByOrNull { it.key }!!.value
val bestTileForHealing = bestTilesForHealing.maxByOrNull { it.getDefensiveBonus() }!!
val bestTileForHealingRank = unit.rankTileForHealing(bestTileForHealing)
if (currentUnitTile != bestTileForHealing

View File

@ -889,7 +889,7 @@ class MapUnit {
fun putInTile(tile: TileInfo) {
when {
!movement.canMoveTo(tile) ->
throw Exception("I can't go there!")
throw Exception("Unit $name at $currentTile can't be put in tile ${tile.position}!")
baseUnit.movesLikeAirUnits() -> tile.airUnits.add(this)
isCivilian() -> tile.civilianUnit = this
else -> tile.militaryUnit = this

View File

@ -261,7 +261,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
if (currentTile == finalDestination) return currentTile
// If we can fly, head there directly
if (unit.baseUnit.movesLikeAirUnits() || unit.isPreparingParadrop()) return finalDestination
if ((unit.baseUnit.movesLikeAirUnits() || unit.isPreparingParadrop()) && canMoveTo(finalDestination)) return finalDestination
val distanceToTiles = getDistanceToTiles()