mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-26 21:35:14 -04:00
chore: Separated movement cost from unit movement file
This commit is contained in:
parent
5b3c3f3aaf
commit
0d50b928ea
176
core/src/com/unciv/logic/map/mapunit/movement/MovementCost.kt
Normal file
176
core/src/com/unciv/logic/map/mapunit/movement/MovementCost.kt
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
package com.unciv.logic.map.mapunit.movement
|
||||||
|
|
||||||
|
import com.unciv.Constants
|
||||||
|
import com.unciv.logic.civilization.Civilization
|
||||||
|
import com.unciv.logic.map.mapunit.MapUnit
|
||||||
|
import com.unciv.logic.map.mapunit.MapUnitCache
|
||||||
|
import com.unciv.logic.map.tile.RoadStatus
|
||||||
|
import com.unciv.logic.map.tile.Tile
|
||||||
|
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
|
|
||||||
|
object MovementCost {
|
||||||
|
|
||||||
|
// This function is called ALL THE TIME and should be as time-optimal as possible!
|
||||||
|
fun getMovementCostBetweenAdjacentTiles(
|
||||||
|
unit: MapUnit,
|
||||||
|
from: Tile,
|
||||||
|
to: Tile,
|
||||||
|
considerZoneOfControl: Boolean = true
|
||||||
|
): Float {
|
||||||
|
val civ = unit.civ
|
||||||
|
|
||||||
|
if (unit.cache.cannotMove) return 100f
|
||||||
|
|
||||||
|
if (from.isLand != to.isLand && unit.baseUnit.isLandUnit() && !unit.cache.canMoveOnWater)
|
||||||
|
return if (from.isWater && to.isLand) unit.cache.costToDisembark ?: 100f
|
||||||
|
else unit.cache.costToEmbark ?: 100f
|
||||||
|
|
||||||
|
// If the movement is affected by a Zone of Control, all movement points are expended
|
||||||
|
if (considerZoneOfControl && isMovementAffectedByZoneOfControl(unit, from, to))
|
||||||
|
return 100f
|
||||||
|
|
||||||
|
// land units will still spend all movement points to embark even with this unique
|
||||||
|
if (unit.cache.allTilesCosts1)
|
||||||
|
return 1f
|
||||||
|
|
||||||
|
val toOwner = to.getOwner()
|
||||||
|
|
||||||
|
val extraCost = if (
|
||||||
|
toOwner != null &&
|
||||||
|
toOwner.hasActiveEnemyMovementPenalty &&
|
||||||
|
civ.isAtWarWith(toOwner)
|
||||||
|
) getEnemyMovementPenalty(toOwner, unit) else 0f
|
||||||
|
|
||||||
|
if (from.getUnpillagedRoad() == RoadStatus.Railroad && to.getUnpillagedRoad() == RoadStatus.Railroad)
|
||||||
|
return RoadStatus.Railroad.movement + extraCost
|
||||||
|
|
||||||
|
// Each of these two function calls `hasUnique(UniqueType.CityStateTerritoryAlwaysFriendly)`
|
||||||
|
// when entering territory of a city state
|
||||||
|
val areConnectedByRoad = from.hasConnection(civ) && to.hasConnection(civ)
|
||||||
|
|
||||||
|
// You might think "wait doesn't isAdjacentToRiver() call isConnectedByRiver() anyway, why have those checks?"
|
||||||
|
// The answer is that the isAdjacentToRiver values are CACHED per tile, but the isConnectedByRiver are not - this is an efficiency optimization
|
||||||
|
val areConnectedByRiver =
|
||||||
|
from.isAdjacentToRiver() && to.isAdjacentToRiver() && from.isConnectedByRiver(to)
|
||||||
|
|
||||||
|
if (areConnectedByRoad && (!areConnectedByRiver || civ.tech.roadsConnectAcrossRivers))
|
||||||
|
return unit.civ.tech.movementSpeedOnRoads + extraCost
|
||||||
|
|
||||||
|
if (unit.cache.ignoresTerrainCost) return 1f + extraCost
|
||||||
|
if (areConnectedByRiver) return 100f // Rivers take the entire turn to cross
|
||||||
|
|
||||||
|
val terrainCost = to.lastTerrain.movementCost.toFloat()
|
||||||
|
|
||||||
|
if (unit.cache.noTerrainMovementUniques)
|
||||||
|
return terrainCost + extraCost
|
||||||
|
|
||||||
|
val stateForConditionals = StateForConditionals(unit.civ, unit = unit, tile = to)
|
||||||
|
fun matchesTerrainTarget(
|
||||||
|
doubleMovement: MapUnitCache.DoubleMovement,
|
||||||
|
target: MapUnitCache.DoubleMovementTerrainTarget
|
||||||
|
): Boolean {
|
||||||
|
if (doubleMovement.terrainTarget != target) return false
|
||||||
|
if (doubleMovement.unique.conditionals.isNotEmpty()) {
|
||||||
|
if (!doubleMovement.unique.conditionalsApply(stateForConditionals)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matchesTerrainTarget(
|
||||||
|
terrainName: String,
|
||||||
|
target: MapUnitCache.DoubleMovementTerrainTarget
|
||||||
|
): Boolean {
|
||||||
|
val doubleMovement = unit.cache.doubleMovementInTerrain[terrainName] ?: return false
|
||||||
|
return matchesTerrainTarget(doubleMovement, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (to.terrainFeatures.any { matchesTerrainTarget(it, MapUnitCache.DoubleMovementTerrainTarget.Feature) })
|
||||||
|
return terrainCost * 0.5f + extraCost
|
||||||
|
|
||||||
|
if (unit.cache.roughTerrainPenalty && to.isRoughTerrain())
|
||||||
|
return 100f // units that have to spend all movement in rough terrain, have to spend all movement in rough terrain
|
||||||
|
// Placement of this 'if' based on testing, see #4232
|
||||||
|
|
||||||
|
if (civ.nation.ignoreHillMovementCost && to.isHill())
|
||||||
|
return 1f + extraCost // usually hills take 2 movements, so here it is 1
|
||||||
|
|
||||||
|
if (unit.cache.noBaseTerrainOrHillDoubleMovementUniques)
|
||||||
|
return terrainCost + extraCost
|
||||||
|
|
||||||
|
if (matchesTerrainTarget(to.baseTerrain, MapUnitCache.DoubleMovementTerrainTarget.Base))
|
||||||
|
return terrainCost * 0.5f + extraCost
|
||||||
|
if (matchesTerrainTarget(Constants.hill, MapUnitCache.DoubleMovementTerrainTarget.Hill)
|
||||||
|
&& to.isHill())
|
||||||
|
return terrainCost * 0.5f + extraCost
|
||||||
|
|
||||||
|
if (unit.cache.noFilteredDoubleMovementUniques)
|
||||||
|
return terrainCost + extraCost
|
||||||
|
if (unit.cache.doubleMovementInTerrain.any {
|
||||||
|
matchesTerrainTarget(it.value, MapUnitCache.DoubleMovementTerrainTarget.Filter)
|
||||||
|
&& to.matchesFilter(it.key)
|
||||||
|
})
|
||||||
|
return terrainCost * 0.5f + extraCost
|
||||||
|
|
||||||
|
return terrainCost + extraCost // no road or other movement cost reduction
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEnemyMovementPenalty(civInfo:Civilization, enemyUnit: MapUnit): Float {
|
||||||
|
if (civInfo.enemyMovementPenaltyUniques != null && civInfo.enemyMovementPenaltyUniques!!.any()) {
|
||||||
|
return civInfo.enemyMovementPenaltyUniques!!.sumOf {
|
||||||
|
if (it.type!! == UniqueType.EnemyUnitsSpendExtraMovement
|
||||||
|
&& enemyUnit.matchesFilter(it.params[0]))
|
||||||
|
it.params[1].toInt()
|
||||||
|
else 0
|
||||||
|
}.toFloat()
|
||||||
|
}
|
||||||
|
return 0f // should not reach this point
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns whether the movement between the adjacent tiles [from] and [to] is affected by Zone of Control */
|
||||||
|
private fun isMovementAffectedByZoneOfControl(unit: MapUnit, from: Tile, to: Tile): Boolean {
|
||||||
|
// Sources:
|
||||||
|
// - https://civilization.fandom.com/wiki/Zone_of_control_(Civ5)
|
||||||
|
// - https://forums.civfanatics.com/resources/understanding-the-zone-of-control-vanilla.25582/
|
||||||
|
//
|
||||||
|
// Enemy military units exert a Zone of Control over the tiles surrounding them. Moving from
|
||||||
|
// one tile in the ZoC of an enemy unit to another tile in the same unit's ZoC expends all
|
||||||
|
// movement points. Land units only exert a ZoC against land units. Sea units exert a ZoC
|
||||||
|
// against both land and sea units. Cities exert a ZoC as well, and it also affects both
|
||||||
|
// land and sea units. Embarked land units do not exert a ZoC. Finally, units that can move
|
||||||
|
// after attacking are not affected by zone of control if the movement is caused by killing
|
||||||
|
// a unit. This last case is handled in the movement-after-attacking code instead of here.
|
||||||
|
|
||||||
|
// We only need to check the two shared neighbors of [from] and [to]: the way of getting
|
||||||
|
// these two tiles can perhaps be optimized. Using a hex-math-based "commonAdjacentTiles"
|
||||||
|
// function is surprisingly less efficient than the current neighbor-intersection approach.
|
||||||
|
// See #4085 for more details.
|
||||||
|
val tilesExertingZoneOfControl = getTilesExertingZoneOfControl(unit, from)
|
||||||
|
if (tilesExertingZoneOfControl.none { to.neighbors.contains(it)})
|
||||||
|
return false
|
||||||
|
|
||||||
|
// Even though this is a very fast check, we perform it last. This is because very few units
|
||||||
|
// ignore zone of control, so the previous check has a much higher chance of yielding an
|
||||||
|
// early "false". If this function is going to return "true", the order doesn't matter
|
||||||
|
// anyway.
|
||||||
|
if (unit.cache.ignoresZoneOfControl)
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTilesExertingZoneOfControl(unit: MapUnit, tile: Tile) = sequence {
|
||||||
|
for (neighbor in tile.neighbors) {
|
||||||
|
if (neighbor.isCityCenter() && unit.civ.isAtWarWith(neighbor.getOwner()!!)) {
|
||||||
|
yield(neighbor)
|
||||||
|
}
|
||||||
|
else if (neighbor.militaryUnit != null && unit.civ.isAtWarWith(neighbor.militaryUnit!!.civ)) {
|
||||||
|
if (neighbor.militaryUnit!!.type.isWaterUnit() || (unit.type.isLandUnit() && !neighbor.militaryUnit!!.isEmbarked()))
|
||||||
|
yield(neighbor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,15 +2,11 @@ package com.unciv.logic.map.mapunit.movement
|
|||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.logic.civilization.Civilization
|
|
||||||
import com.unciv.logic.map.BFS
|
import com.unciv.logic.map.BFS
|
||||||
import com.unciv.logic.map.HexMath.getDistance
|
import com.unciv.logic.map.HexMath.getDistance
|
||||||
import com.unciv.logic.map.mapunit.MapUnit
|
import com.unciv.logic.map.mapunit.MapUnit
|
||||||
import com.unciv.logic.map.mapunit.MapUnitCache
|
|
||||||
import com.unciv.logic.map.tile.RoadStatus
|
|
||||||
import com.unciv.logic.map.tile.Tile
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.UnitActionType
|
import com.unciv.models.UnitActionType
|
||||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.ui.components.UnitMovementMemoryType
|
import com.unciv.ui.components.UnitMovementMemoryType
|
||||||
|
|
||||||
@ -18,164 +14,6 @@ class UnitMovement(val unit: MapUnit) {
|
|||||||
|
|
||||||
private val pathfindingCache = PathfindingCache(unit)
|
private val pathfindingCache = PathfindingCache(unit)
|
||||||
|
|
||||||
private fun getEnemyMovementPenalty(civInfo:Civilization, enemyUnit: MapUnit): Float {
|
|
||||||
if (civInfo.enemyMovementPenaltyUniques != null && civInfo.enemyMovementPenaltyUniques!!.any()) {
|
|
||||||
return civInfo.enemyMovementPenaltyUniques!!.sumOf {
|
|
||||||
if (it.type!! == UniqueType.EnemyUnitsSpendExtraMovement
|
|
||||||
&& enemyUnit.matchesFilter(it.params[0]))
|
|
||||||
it.params[1].toInt()
|
|
||||||
else 0
|
|
||||||
}.toFloat()
|
|
||||||
}
|
|
||||||
return 0f // should not reach this point
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is called ALL THE TIME and should be as time-optimal as possible!
|
|
||||||
private fun getMovementCostBetweenAdjacentTiles(
|
|
||||||
from: Tile,
|
|
||||||
to: Tile,
|
|
||||||
civInfo: Civilization,
|
|
||||||
considerZoneOfControl: Boolean = true
|
|
||||||
): Float {
|
|
||||||
if (unit.cache.cannotMove) return 100f
|
|
||||||
|
|
||||||
if (from.isLand != to.isLand && unit.baseUnit.isLandUnit() && !unit.cache.canMoveOnWater)
|
|
||||||
return if (from.isWater && to.isLand) unit.cache.costToDisembark ?: 100f
|
|
||||||
else unit.cache.costToEmbark ?: 100f
|
|
||||||
|
|
||||||
// If the movement is affected by a Zone of Control, all movement points are expended
|
|
||||||
if (considerZoneOfControl && isMovementAffectedByZoneOfControl(from, to, civInfo))
|
|
||||||
return 100f
|
|
||||||
|
|
||||||
// land units will still spend all movement points to embark even with this unique
|
|
||||||
if (unit.cache.allTilesCosts1)
|
|
||||||
return 1f
|
|
||||||
|
|
||||||
val toOwner = to.getOwner()
|
|
||||||
val extraCost = if (
|
|
||||||
toOwner != null &&
|
|
||||||
toOwner.hasActiveEnemyMovementPenalty &&
|
|
||||||
civInfo.isAtWarWith(toOwner)
|
|
||||||
) getEnemyMovementPenalty(toOwner, unit) else 0f
|
|
||||||
|
|
||||||
if (from.getUnpillagedRoad() == RoadStatus.Railroad && to.getUnpillagedRoad() == RoadStatus.Railroad)
|
|
||||||
return RoadStatus.Railroad.movement + extraCost
|
|
||||||
|
|
||||||
// Each of these two function calls `hasUnique(UniqueType.CityStateTerritoryAlwaysFriendly)`
|
|
||||||
// when entering territory of a city state
|
|
||||||
val areConnectedByRoad = from.hasConnection(civInfo) && to.hasConnection(civInfo)
|
|
||||||
|
|
||||||
// You might think "wait doesn't isAdjacentToRiver() call isConnectedByRiver() anyway, why have those checks?"
|
|
||||||
// The answer is that the isAdjacentToRiver values are CACHED per tile, but the isConnectedByRiver are not - this is an efficiency optimization
|
|
||||||
val areConnectedByRiver =
|
|
||||||
from.isAdjacentToRiver() && to.isAdjacentToRiver() && from.isConnectedByRiver(to)
|
|
||||||
|
|
||||||
if (areConnectedByRoad && (!areConnectedByRiver || civInfo.tech.roadsConnectAcrossRivers))
|
|
||||||
return unit.civ.tech.movementSpeedOnRoads + extraCost
|
|
||||||
|
|
||||||
if (unit.cache.ignoresTerrainCost) return 1f + extraCost
|
|
||||||
if (areConnectedByRiver) return 100f // Rivers take the entire turn to cross
|
|
||||||
|
|
||||||
val terrainCost = to.lastTerrain.movementCost.toFloat()
|
|
||||||
|
|
||||||
if (unit.cache.noTerrainMovementUniques)
|
|
||||||
return terrainCost + extraCost
|
|
||||||
|
|
||||||
val stateForConditionals = StateForConditionals(unit.civ, unit = unit, tile = to)
|
|
||||||
fun matchesTerrainTarget(
|
|
||||||
doubleMovement: MapUnitCache.DoubleMovement,
|
|
||||||
target: MapUnitCache.DoubleMovementTerrainTarget
|
|
||||||
): Boolean {
|
|
||||||
if (doubleMovement.terrainTarget != target) return false
|
|
||||||
if (doubleMovement.unique.conditionals.isNotEmpty()) {
|
|
||||||
if (!doubleMovement.unique.conditionalsApply(stateForConditionals)) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun matchesTerrainTarget(
|
|
||||||
terrainName: String,
|
|
||||||
target: MapUnitCache.DoubleMovementTerrainTarget
|
|
||||||
): Boolean {
|
|
||||||
val doubleMovement = unit.cache.doubleMovementInTerrain[terrainName] ?: return false
|
|
||||||
return matchesTerrainTarget(doubleMovement, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (to.terrainFeatures.any { matchesTerrainTarget(it, MapUnitCache.DoubleMovementTerrainTarget.Feature) })
|
|
||||||
return terrainCost * 0.5f + extraCost
|
|
||||||
|
|
||||||
if (unit.cache.roughTerrainPenalty && to.isRoughTerrain())
|
|
||||||
return 100f // units that have to spend all movement in rough terrain, have to spend all movement in rough terrain
|
|
||||||
// Placement of this 'if' based on testing, see #4232
|
|
||||||
|
|
||||||
if (civInfo.nation.ignoreHillMovementCost && to.isHill())
|
|
||||||
return 1f + extraCost // usually hills take 2 movements, so here it is 1
|
|
||||||
|
|
||||||
if (unit.cache.noBaseTerrainOrHillDoubleMovementUniques)
|
|
||||||
return terrainCost + extraCost
|
|
||||||
|
|
||||||
if (matchesTerrainTarget(to.baseTerrain, MapUnitCache.DoubleMovementTerrainTarget.Base))
|
|
||||||
return terrainCost * 0.5f + extraCost
|
|
||||||
if (matchesTerrainTarget(Constants.hill, MapUnitCache.DoubleMovementTerrainTarget.Hill)
|
|
||||||
&& to.isHill())
|
|
||||||
return terrainCost * 0.5f + extraCost
|
|
||||||
|
|
||||||
if (unit.cache.noFilteredDoubleMovementUniques)
|
|
||||||
return terrainCost + extraCost
|
|
||||||
if (unit.cache.doubleMovementInTerrain.any {
|
|
||||||
matchesTerrainTarget(it.value, MapUnitCache.DoubleMovementTerrainTarget.Filter)
|
|
||||||
&& to.matchesFilter(it.key)
|
|
||||||
})
|
|
||||||
return terrainCost * 0.5f + extraCost
|
|
||||||
|
|
||||||
return terrainCost + extraCost // no road or other movement cost reduction
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTilesExertingZoneOfControl(tile: Tile, civInfo: Civilization) = sequence {
|
|
||||||
for (neighbor in tile.neighbors) {
|
|
||||||
if (neighbor.isCityCenter() && civInfo.isAtWarWith(neighbor.getOwner()!!)) {
|
|
||||||
yield(neighbor)
|
|
||||||
}
|
|
||||||
else if (neighbor.militaryUnit != null && civInfo.isAtWarWith(neighbor.militaryUnit!!.civ)) {
|
|
||||||
if (neighbor.militaryUnit!!.type.isWaterUnit() || (unit.type.isLandUnit() && !neighbor.militaryUnit!!.isEmbarked()))
|
|
||||||
yield(neighbor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether the movement between the adjacent tiles [from] and [to] is affected by Zone of Control */
|
|
||||||
private fun isMovementAffectedByZoneOfControl(from: Tile, to: Tile, civInfo: Civilization): Boolean {
|
|
||||||
// Sources:
|
|
||||||
// - https://civilization.fandom.com/wiki/Zone_of_control_(Civ5)
|
|
||||||
// - https://forums.civfanatics.com/resources/understanding-the-zone-of-control-vanilla.25582/
|
|
||||||
//
|
|
||||||
// Enemy military units exert a Zone of Control over the tiles surrounding them. Moving from
|
|
||||||
// one tile in the ZoC of an enemy unit to another tile in the same unit's ZoC expends all
|
|
||||||
// movement points. Land units only exert a ZoC against land units. Sea units exert a ZoC
|
|
||||||
// against both land and sea units. Cities exert a ZoC as well, and it also affects both
|
|
||||||
// land and sea units. Embarked land units do not exert a ZoC. Finally, units that can move
|
|
||||||
// after attacking are not affected by zone of control if the movement is caused by killing
|
|
||||||
// a unit. This last case is handled in the movement-after-attacking code instead of here.
|
|
||||||
|
|
||||||
// We only need to check the two shared neighbors of [from] and [to]: the way of getting
|
|
||||||
// these two tiles can perhaps be optimized. Using a hex-math-based "commonAdjacentTiles"
|
|
||||||
// function is surprisingly less efficient than the current neighbor-intersection approach.
|
|
||||||
// See #4085 for more details.
|
|
||||||
val tilesExertingZoneOfControl = getTilesExertingZoneOfControl(from, civInfo)
|
|
||||||
if (tilesExertingZoneOfControl.none { to.neighbors.contains(it)})
|
|
||||||
return false
|
|
||||||
|
|
||||||
// Even though this is a very fast check, we perform it last. This is because very few units
|
|
||||||
// ignore zone of control, so the previous check has a much higher chance of yielding an
|
|
||||||
// early "false". If this function is going to return "true", the order doesn't matter
|
|
||||||
// anyway.
|
|
||||||
if (unit.cache.ignoresZoneOfControl)
|
|
||||||
return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
class ParentTileAndTotalDistance(val tile:Tile, val parentTile: Tile, val totalDistance: Float)
|
class ParentTileAndTotalDistance(val tile:Tile, val parentTile: Tile, val totalDistance: Float)
|
||||||
|
|
||||||
fun isUnknownTileWeShouldAssumeToBePassable(tile: Tile) = !unit.civ.hasExplored(tile)
|
fun isUnknownTileWeShouldAssumeToBePassable(tile: Tile) = !unit.civ.hasExplored(tile)
|
||||||
@ -220,7 +58,7 @@ class UnitMovement(val unit: MapUnit) {
|
|||||||
val key = Pair(tileToCheck, neighbor)
|
val key = Pair(tileToCheck, neighbor)
|
||||||
val movementCost =
|
val movementCost =
|
||||||
movementCostCache.getOrPut(key) {
|
movementCostCache.getOrPut(key) {
|
||||||
getMovementCostBetweenAdjacentTiles(tileToCheck, neighbor, unit.civ, considerZoneOfControl)
|
MovementCost.getMovementCostBetweenAdjacentTiles(unit, tileToCheck, neighbor, considerZoneOfControl)
|
||||||
}
|
}
|
||||||
distanceToTiles[tileToCheck]!!.totalDistance + movementCost
|
distanceToTiles[tileToCheck]!!.totalDistance + movementCost
|
||||||
}
|
}
|
||||||
@ -596,7 +434,7 @@ class UnitMovement(val unit: MapUnit) {
|
|||||||
|
|
||||||
// This fixes a bug where tiles in the fog of war would always only cost 1 mp
|
// This fixes a bug where tiles in the fog of war would always only cost 1 mp
|
||||||
if (!unit.civ.gameInfo.gameParameters.godMode)
|
if (!unit.civ.gameInfo.gameParameters.godMode)
|
||||||
passingMovementSpent += getMovementCostBetweenAdjacentTiles(previousTile, tile, unit.civ)
|
passingMovementSpent += MovementCost.getMovementCostBetweenAdjacentTiles(unit, previousTile, tile)
|
||||||
|
|
||||||
// In case something goes wrong, cache the last tile we were able to end on
|
// In case something goes wrong, cache the last tile we were able to end on
|
||||||
// We can assume we can pass through this tile, as we would have broken earlier
|
// We can assume we can pass through this tile, as we would have broken earlier
|
||||||
|
Loading…
x
Reference in New Issue
Block a user