mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-20 04:38:18 +07:00
chore: separated unit cached values into separate file
This commit is contained in:
@ -38,7 +38,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||
|
||||
private val civUnits = civInfo.units.getCivUnits()
|
||||
private val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
||||
private val workers = civUnits.count { it.hasUniqueToBuildImprovements && it.isCivilian() }.toFloat()
|
||||
private val workers = civUnits.count { it.cache.hasUniqueToBuildImprovements && it.isCivilian() }.toFloat()
|
||||
private val cities = civInfo.cities.size
|
||||
private val allTechsAreResearched = civInfo.gameInfo.ruleSet.technologies.values
|
||||
.all { civInfo.tech.isResearched(it.name) || !civInfo.tech.canBeResearched(it.name)}
|
||||
|
@ -108,7 +108,7 @@ object SpecificUnitAutomation {
|
||||
.sortedBy { it.aerialDistanceTo(unit.currentTile) }
|
||||
.firstOrNull { reachableTest(it) }
|
||||
?: return
|
||||
if (!unit.hasCitadelPlacementUnique) {
|
||||
if (!unit.cache.hasCitadelPlacementUnique) {
|
||||
unit.movement.headTowards(cityToGarrison)
|
||||
return
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ object UnitAutomation {
|
||||
if (unit.hasUnique(UniqueType.FoundCity))
|
||||
return SpecificUnitAutomation.automateSettlerActions(unit)
|
||||
|
||||
if (unit.hasUniqueToBuildImprovements)
|
||||
if (unit.cache.hasUniqueToBuildImprovements)
|
||||
return WorkerAutomation.automateWorkerAction(unit)
|
||||
|
||||
if (unit.hasUnique(UniqueType.MayFoundReligion)
|
||||
@ -248,12 +248,12 @@ object UnitAutomation {
|
||||
|
||||
//todo this now supports "Great General"-like mod units not combining 'aura' and citadel
|
||||
// abilities, but not additional capabilities if automation finds no use for those two
|
||||
if (unit.hasStrengthBonusInRadiusUnique
|
||||
if (unit.cache.hasStrengthBonusInRadiusUnique
|
||||
&& SpecificUnitAutomation.automateGreatGeneral(unit))
|
||||
return
|
||||
if (unit.hasCitadelPlacementUnique && SpecificUnitAutomation.automateCitadelPlacer(unit))
|
||||
if (unit.cache.hasCitadelPlacementUnique && SpecificUnitAutomation.automateCitadelPlacer(unit))
|
||||
return
|
||||
if (unit.hasCitadelPlacementUnique || unit.hasStrengthBonusInRadiusUnique)
|
||||
if (unit.cache.hasCitadelPlacementUnique || unit.cache.hasStrengthBonusInRadiusUnique)
|
||||
return SpecificUnitAutomation.automateGreatGeneralFallback(unit)
|
||||
|
||||
if (unit.civ.religionManager.maySpreadReligionAtAll(unit))
|
||||
|
@ -34,7 +34,7 @@ object GreatGeneralImplementation {
|
||||
val unit = ourUnitCombatant.unit
|
||||
val civInfo = ourUnitCombatant.unit.civ
|
||||
val allGenerals = civInfo.units.getCivUnits()
|
||||
.filter { it.hasStrengthBonusInRadiusUnique }
|
||||
.filter { it.cache.hasStrengthBonusInRadiusUnique }
|
||||
if (allGenerals.none()) return Pair("", 0)
|
||||
|
||||
val greatGeneral = allGenerals
|
||||
|
@ -15,7 +15,6 @@ import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.helpers.UnitMovementMemoryType
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.tile.TerrainType
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.Unique
|
||||
@ -52,83 +51,15 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
@Transient
|
||||
var isDestroyed = false
|
||||
|
||||
@Transient
|
||||
var cache = MapUnitCache(this)
|
||||
|
||||
// This is saved per each unit because if we need to recalculate viewable tiles every time a unit moves,
|
||||
// and we need to go over ALL the units, that's a lot of time spent on updating information we should already know!
|
||||
// About 10% of total NextTurn performance time, at the time of this change!
|
||||
@Transient
|
||||
var viewableTiles = HashSet<Tile>()
|
||||
|
||||
// These are for performance improvements to getMovementCostBetweenAdjacentTiles,
|
||||
// a major component of getDistanceToTilesWithinTurn,
|
||||
// which in turn is a component of getShortestPath and canReach
|
||||
@Transient
|
||||
var ignoresTerrainCost = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var ignoresZoneOfControl = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var allTilesCosts1 = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var canPassThroughImpassableTiles = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var roughTerrainPenalty = false
|
||||
private set
|
||||
|
||||
/** If set causes an early exit in getMovementCostBetweenAdjacentTiles
|
||||
* - means no double movement uniques, roughTerrainPenalty or ignoreHillMovementCost */
|
||||
@Transient
|
||||
var noTerrainMovementUniques = false
|
||||
private set
|
||||
|
||||
/** If set causes a second early exit in getMovementCostBetweenAdjacentTiles */
|
||||
@Transient
|
||||
var noBaseTerrainOrHillDoubleMovementUniques = false
|
||||
private set
|
||||
|
||||
/** If set skips tile.matchesFilter tests for double movement in getMovementCostBetweenAdjacentTiles */
|
||||
@Transient
|
||||
var noFilteredDoubleMovementUniques = false
|
||||
private set
|
||||
|
||||
/** Used for getMovementCostBetweenAdjacentTiles only, based on order of testing */
|
||||
enum class DoubleMovementTerrainTarget { Feature, Base, Hill, Filter }
|
||||
/** Mod-friendly cache of double-movement terrains */
|
||||
@Transient
|
||||
val doubleMovementInTerrain = HashMap<String, DoubleMovementTerrainTarget>()
|
||||
|
||||
@Transient
|
||||
var canEnterIceTiles = false
|
||||
|
||||
@Transient
|
||||
var cannotEnterOceanTiles = false
|
||||
|
||||
@Transient
|
||||
var canEnterForeignTerrain: Boolean = false
|
||||
|
||||
@Transient
|
||||
var costToDisembark: Float? = null
|
||||
|
||||
@Transient
|
||||
var costToEmbark: Float? = null
|
||||
|
||||
@Transient
|
||||
var paradropRange = 0
|
||||
|
||||
@Transient
|
||||
var hasUniqueToBuildImprovements = false // not canBuildImprovements to avoid confusion
|
||||
|
||||
@Transient
|
||||
var hasStrengthBonusInRadiusUnique = false
|
||||
@Transient
|
||||
var hasCitadelPlacementUnique = false
|
||||
|
||||
/** civName owning the unit */
|
||||
lateinit var owner: String
|
||||
|
||||
@ -285,7 +216,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
return getMatchingUniques(uniqueType, stateForConditionals, checkCivInfoUniques).any()
|
||||
}
|
||||
|
||||
fun updateUniques(ruleset: Ruleset) {
|
||||
fun updateUniques() {
|
||||
val uniques = ArrayList<Unique>()
|
||||
val baseUnit = baseUnit()
|
||||
uniques.addAll(baseUnit.uniqueObjects)
|
||||
@ -299,48 +230,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
addUniques(uniques)
|
||||
}
|
||||
|
||||
allTilesCosts1 = hasUnique(UniqueType.AllTilesCost1Move)
|
||||
canPassThroughImpassableTiles = hasUnique(UniqueType.CanPassImpassable)
|
||||
ignoresTerrainCost = hasUnique(UniqueType.IgnoresTerrainCost)
|
||||
ignoresZoneOfControl = hasUnique(UniqueType.IgnoresZOC)
|
||||
roughTerrainPenalty = hasUnique(UniqueType.RoughTerrainPenalty)
|
||||
|
||||
doubleMovementInTerrain.clear()
|
||||
for (unique in getMatchingUniques(UniqueType.DoubleMovementOnTerrain)) {
|
||||
val param = unique.params[0]
|
||||
val terrain = ruleset.terrains[param]
|
||||
doubleMovementInTerrain[param] = when {
|
||||
terrain == null -> DoubleMovementTerrainTarget.Filter
|
||||
terrain.name == Constants.hill -> DoubleMovementTerrainTarget.Hill
|
||||
terrain.type == TerrainType.TerrainFeature -> DoubleMovementTerrainTarget.Feature
|
||||
terrain.type.isBaseTerrain -> DoubleMovementTerrainTarget.Base
|
||||
else -> DoubleMovementTerrainTarget.Filter
|
||||
}
|
||||
}
|
||||
// Init shortcut flags
|
||||
noTerrainMovementUniques = doubleMovementInTerrain.isEmpty() &&
|
||||
!roughTerrainPenalty && !civ.nation.ignoreHillMovementCost
|
||||
noBaseTerrainOrHillDoubleMovementUniques = doubleMovementInTerrain
|
||||
.none { it.value != DoubleMovementTerrainTarget.Feature }
|
||||
noFilteredDoubleMovementUniques = doubleMovementInTerrain
|
||||
.none { it.value == DoubleMovementTerrainTarget.Filter }
|
||||
costToDisembark = (getMatchingUniques(UniqueType.ReducedDisembarkCost, checkCivInfoUniques = true))
|
||||
.minOfOrNull { it.params[0].toFloat() }
|
||||
costToEmbark = getMatchingUniques(UniqueType.ReducedEmbarkCost, checkCivInfoUniques = true)
|
||||
.minOfOrNull { it.params[0].toFloat() }
|
||||
|
||||
//todo: consider parameterizing [terrainFilter] in some of the following:
|
||||
canEnterIceTiles = hasUnique(UniqueType.CanEnterIceTiles)
|
||||
cannotEnterOceanTiles = hasUnique(UniqueType.CannotEnterOcean, StateForConditionals(civInfo=civ, unit=this))
|
||||
|
||||
hasUniqueToBuildImprovements = hasUnique(UniqueType.BuildImprovements)
|
||||
canEnterForeignTerrain = hasUnique(UniqueType.CanEnterForeignTiles)
|
||||
|| hasUnique(UniqueType.CanEnterForeignTilesButLosesReligiousStrength)
|
||||
|
||||
hasStrengthBonusInRadiusUnique = hasUnique(UniqueType.StrengthBonusInRadius)
|
||||
hasCitadelPlacementUnique = getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
|
||||
.mapNotNull { civ.gameInfo.ruleSet.tileImprovements[it.params[0]] }
|
||||
.any { it.hasUnique(UniqueType.TakesOverAdjacentTiles) }
|
||||
cache.updateUniques()
|
||||
}
|
||||
|
||||
fun copyStatisticsTo(newUnit: MapUnit) {
|
||||
@ -355,7 +245,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
|
||||
newUnit.promotions = promotions.clone()
|
||||
|
||||
newUnit.updateUniques(civ.gameInfo.ruleSet)
|
||||
newUnit.updateUniques()
|
||||
newUnit.updateVisibleTiles()
|
||||
}
|
||||
|
||||
@ -368,7 +258,6 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
movement += getMatchingUniques(UniqueType.Movement, checkCivInfoUniques = true)
|
||||
.sumOf { it.params[0].toInt() }
|
||||
|
||||
|
||||
if (movement < 1) movement = 1
|
||||
|
||||
return movement
|
||||
@ -533,7 +422,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
baseUnit = ruleset.units[name]
|
||||
?: throw java.lang.Exception("Unit $name is not found!")
|
||||
|
||||
updateUniques(ruleset)
|
||||
updateUniques()
|
||||
}
|
||||
|
||||
fun useMovementPoints(amount: Float) {
|
||||
|
128
core/src/com/unciv/logic/map/mapunit/MapUnitCache.kt
Normal file
128
core/src/com/unciv/logic/map/mapunit/MapUnitCache.kt
Normal file
@ -0,0 +1,128 @@
|
||||
package com.unciv.logic.map.mapunit
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.models.ruleset.tile.TerrainType
|
||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
|
||||
class MapUnitCache(val mapUnit: MapUnit) {
|
||||
// These are for performance improvements to getMovementCostBetweenAdjacentTiles,
|
||||
// a major component of getDistanceToTilesWithinTurn,
|
||||
// which in turn is a component of getShortestPath and canReach
|
||||
@Transient
|
||||
var ignoresTerrainCost = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var ignoresZoneOfControl = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var allTilesCosts1 = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var canPassThroughImpassableTiles = false
|
||||
private set
|
||||
|
||||
@Transient
|
||||
var roughTerrainPenalty = false
|
||||
private set
|
||||
|
||||
/** If set causes an early exit in getMovementCostBetweenAdjacentTiles
|
||||
* - means no double movement uniques, roughTerrainPenalty or ignoreHillMovementCost */
|
||||
@Transient
|
||||
var noTerrainMovementUniques = false
|
||||
private set
|
||||
|
||||
/** If set causes a second early exit in getMovementCostBetweenAdjacentTiles */
|
||||
@Transient
|
||||
var noBaseTerrainOrHillDoubleMovementUniques = false
|
||||
private set
|
||||
|
||||
/** If set skips tile.matchesFilter tests for double movement in getMovementCostBetweenAdjacentTiles */
|
||||
@Transient
|
||||
var noFilteredDoubleMovementUniques = false
|
||||
private set
|
||||
|
||||
/** Used for getMovementCostBetweenAdjacentTiles only, based on order of testing */
|
||||
enum class DoubleMovementTerrainTarget { Feature, Base, Hill, Filter }
|
||||
/** Mod-friendly cache of double-movement terrains */
|
||||
@Transient
|
||||
val doubleMovementInTerrain = HashMap<String, DoubleMovementTerrainTarget>()
|
||||
|
||||
@Transient
|
||||
var canEnterIceTiles = false
|
||||
|
||||
@Transient
|
||||
var cannotEnterOceanTiles = false
|
||||
|
||||
@Transient
|
||||
var canEnterForeignTerrain: Boolean = false
|
||||
|
||||
@Transient
|
||||
var costToDisembark: Float? = null
|
||||
|
||||
@Transient
|
||||
var costToEmbark: Float? = null
|
||||
|
||||
@Transient
|
||||
var paradropRange = 0
|
||||
|
||||
@Transient
|
||||
var hasUniqueToBuildImprovements = false // not canBuildImprovements to avoid confusion
|
||||
|
||||
@Transient
|
||||
var hasStrengthBonusInRadiusUnique = false
|
||||
@Transient
|
||||
var hasCitadelPlacementUnique = false
|
||||
|
||||
fun updateUniques(){
|
||||
|
||||
allTilesCosts1 = mapUnit.hasUnique(UniqueType.AllTilesCost1Move)
|
||||
canPassThroughImpassableTiles = mapUnit.hasUnique(UniqueType.CanPassImpassable)
|
||||
ignoresTerrainCost = mapUnit.hasUnique(UniqueType.IgnoresTerrainCost)
|
||||
ignoresZoneOfControl = mapUnit.hasUnique(UniqueType.IgnoresZOC)
|
||||
roughTerrainPenalty = mapUnit.hasUnique(UniqueType.RoughTerrainPenalty)
|
||||
|
||||
doubleMovementInTerrain.clear()
|
||||
for (unique in mapUnit.getMatchingUniques(UniqueType.DoubleMovementOnTerrain)) {
|
||||
val param = unique.params[0]
|
||||
val terrain = mapUnit.currentTile.ruleset.terrains[param]
|
||||
doubleMovementInTerrain[param] = when {
|
||||
terrain == null -> DoubleMovementTerrainTarget.Filter
|
||||
terrain.name == Constants.hill -> DoubleMovementTerrainTarget.Hill
|
||||
terrain.type == TerrainType.TerrainFeature -> DoubleMovementTerrainTarget.Feature
|
||||
terrain.type.isBaseTerrain -> DoubleMovementTerrainTarget.Base
|
||||
else -> DoubleMovementTerrainTarget.Filter
|
||||
}
|
||||
}
|
||||
// Init shortcut flags
|
||||
noTerrainMovementUniques = doubleMovementInTerrain.isEmpty() &&
|
||||
!roughTerrainPenalty && !mapUnit.civ.nation.ignoreHillMovementCost
|
||||
noBaseTerrainOrHillDoubleMovementUniques = doubleMovementInTerrain
|
||||
.none { it.value != DoubleMovementTerrainTarget.Feature }
|
||||
noFilteredDoubleMovementUniques = doubleMovementInTerrain
|
||||
.none { it.value == DoubleMovementTerrainTarget.Filter }
|
||||
costToDisembark = (mapUnit.getMatchingUniques(UniqueType.ReducedDisembarkCost, checkCivInfoUniques = true))
|
||||
.minOfOrNull { it.params[0].toFloat() }
|
||||
costToEmbark = mapUnit.getMatchingUniques(UniqueType.ReducedEmbarkCost, checkCivInfoUniques = true)
|
||||
.minOfOrNull { it.params[0].toFloat() }
|
||||
|
||||
//todo: consider parameterizing [terrainFilter] in some of the following:
|
||||
canEnterIceTiles = mapUnit.hasUnique(UniqueType.CanEnterIceTiles)
|
||||
cannotEnterOceanTiles = mapUnit.hasUnique(
|
||||
UniqueType.CannotEnterOcean,
|
||||
StateForConditionals(civInfo = mapUnit.civ, unit = mapUnit)
|
||||
)
|
||||
|
||||
hasUniqueToBuildImprovements = mapUnit.hasUnique(UniqueType.BuildImprovements)
|
||||
canEnterForeignTerrain = mapUnit.hasUnique(UniqueType.CanEnterForeignTiles)
|
||||
|| mapUnit.hasUnique(UniqueType.CanEnterForeignTilesButLosesReligiousStrength)
|
||||
|
||||
hasStrengthBonusInRadiusUnique = mapUnit.hasUnique(UniqueType.StrengthBonusInRadius)
|
||||
hasCitadelPlacementUnique = mapUnit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
|
||||
.mapNotNull { mapUnit.civ.gameInfo.ruleSet.tileImprovements[it.params[0]] }
|
||||
.any { it.hasUnique(UniqueType.TakesOverAdjacentTiles) }
|
||||
}
|
||||
}
|
@ -35,15 +35,15 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
): Float {
|
||||
|
||||
if (from.isLand != to.isLand && unit.baseUnit.isLandUnit())
|
||||
return if (from.isWater && to.isLand) unit.costToDisembark ?: 100f
|
||||
else unit.costToEmbark ?: 100f
|
||||
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.allTilesCosts1)
|
||||
if (unit.cache.allTilesCosts1)
|
||||
return 1f
|
||||
|
||||
val toOwner = to.getOwner()
|
||||
@ -65,36 +65,36 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (areConnectedByRoad && (!areConnectedByRiver || civInfo.tech.roadsConnectAcrossRivers))
|
||||
return unit.civ.tech.movementSpeedOnRoads + extraCost
|
||||
|
||||
if (unit.ignoresTerrainCost) return 1f + extraCost
|
||||
if (unit.cache.ignoresTerrainCost) return 1f + extraCost
|
||||
if (areConnectedByRiver) return 100f // Rivers take the entire turn to cross
|
||||
|
||||
val terrainCost = to.getLastTerrain().movementCost.toFloat()
|
||||
|
||||
if (unit.noTerrainMovementUniques)
|
||||
if (unit.cache.noTerrainMovementUniques)
|
||||
return terrainCost + extraCost
|
||||
|
||||
if (to.terrainFeatures.any { unit.doubleMovementInTerrain[it] == MapUnit.DoubleMovementTerrainTarget.Feature })
|
||||
if (to.terrainFeatures.any { unit.cache.doubleMovementInTerrain[it] == MapUnitCache.DoubleMovementTerrainTarget.Feature })
|
||||
return terrainCost * 0.5f + extraCost
|
||||
|
||||
if (unit.roughTerrainPenalty && to.isRoughTerrain())
|
||||
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.noBaseTerrainOrHillDoubleMovementUniques)
|
||||
if (unit.cache.noBaseTerrainOrHillDoubleMovementUniques)
|
||||
return terrainCost + extraCost
|
||||
|
||||
if (unit.doubleMovementInTerrain[to.baseTerrain] == MapUnit.DoubleMovementTerrainTarget.Base)
|
||||
if (unit.cache.doubleMovementInTerrain[to.baseTerrain] == MapUnitCache.DoubleMovementTerrainTarget.Base)
|
||||
return terrainCost * 0.5f + extraCost
|
||||
if (unit.doubleMovementInTerrain[Constants.hill] == MapUnit.DoubleMovementTerrainTarget.Hill && to.isHill())
|
||||
if (unit.cache.doubleMovementInTerrain[Constants.hill] == MapUnitCache.DoubleMovementTerrainTarget.Hill && to.isHill())
|
||||
return terrainCost * 0.5f + extraCost
|
||||
|
||||
if (unit.noFilteredDoubleMovementUniques)
|
||||
if (unit.cache.noFilteredDoubleMovementUniques)
|
||||
return terrainCost + extraCost
|
||||
if (unit.doubleMovementInTerrain.any {
|
||||
it.value == MapUnit.DoubleMovementTerrainTarget.Filter &&
|
||||
if (unit.cache.doubleMovementInTerrain.any {
|
||||
it.value == MapUnitCache.DoubleMovementTerrainTarget.Filter &&
|
||||
to.matchesFilter(it.key)
|
||||
})
|
||||
return terrainCost * 0.5f + extraCost
|
||||
@ -140,7 +140,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
// 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.ignoresZoneOfControl)
|
||||
if (unit.cache.ignoresZoneOfControl)
|
||||
return false
|
||||
return true
|
||||
}
|
||||
@ -355,7 +355,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (unit.baseUnit.movesLikeAirUnits())
|
||||
return unit.currentTile.aerialDistanceTo(destination) <= unit.getMaxMovementForAirUnits()
|
||||
if (unit.isPreparingParadrop())
|
||||
return getDistance(unit.currentTile.position, destination.position) <= unit.paradropRange && canParadropOn(destination)
|
||||
return getDistance(unit.currentTile.position, destination.position) <= unit.cache.paradropRange && canParadropOn(destination)
|
||||
return getDistanceToTiles().containsKey(destination)
|
||||
}
|
||||
|
||||
@ -365,7 +365,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
unit.baseUnit.movesLikeAirUnits() ->
|
||||
unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getMaxMovementForAirUnits()))
|
||||
unit.isPreparingParadrop() ->
|
||||
unit.getTile().getTilesInDistance(unit.paradropRange)
|
||||
unit.getTile().getTilesInDistance(unit.cache.paradropRange)
|
||||
.filter { unit.movement.canParadropOn(it) }
|
||||
else ->
|
||||
unit.movement.getDistanceToTiles().keys.asSequence()
|
||||
@ -589,7 +589,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
moveToTile(destination, considerZoneOfControl)
|
||||
}
|
||||
|
||||
unit.updateUniques(unit.currentTile.ruleset)
|
||||
unit.updateUniques()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -698,7 +698,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (tile.isImpassible()) {
|
||||
// special exception - ice tiles are technically impassible, but some units can move through them anyway
|
||||
// helicopters can pass through impassable tiles like mountains
|
||||
if (!unit.canPassThroughImpassableTiles && !(unit.canEnterIceTiles && tile.terrainFeatures.contains(Constants.ice))
|
||||
if (!unit.cache.canPassThroughImpassableTiles && !(unit.cache.canEnterIceTiles && tile.terrainFeatures.contains(Constants.ice))
|
||||
// carthage-like uniques sometimes allow passage through impassible tiles
|
||||
&& !(unit.civ.passThroughImpassableUnlocked && unit.civ.passableImpassables.contains(tile.getLastTerrain().name)))
|
||||
return false
|
||||
@ -719,10 +719,10 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
return false
|
||||
}
|
||||
if (tile.isOcean && !unit.civ.tech.allUnitsCanEnterOcean) { // Apparently all Polynesian naval units can enter oceans
|
||||
if (!unitSpecificAllowOcean && unit.cannotEnterOceanTiles) return false
|
||||
if (!unitSpecificAllowOcean && unit.cache.cannotEnterOceanTiles) return false
|
||||
}
|
||||
|
||||
if (!unit.canEnterForeignTerrain && !tile.canCivPassThrough(unit.civ)) return false
|
||||
if (!unit.cache.canEnterForeignTerrain && !tile.canCivPassThrough(unit.civ)) return false
|
||||
|
||||
// The first unit is:
|
||||
// 1. Either military unit
|
||||
@ -802,11 +802,11 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
* however ignores the diplomatic aspects of such movement like crossing closed borders.
|
||||
*/
|
||||
private fun getPathBetweenTiles(from: Tile, to: Tile): MutableSet<Tile> {
|
||||
val tmp = unit.canEnterForeignTerrain
|
||||
unit.canEnterForeignTerrain = true // the trick to ignore tiles owners
|
||||
val tmp = unit.cache.canEnterForeignTerrain
|
||||
unit.cache.canEnterForeignTerrain = true // the trick to ignore tiles owners
|
||||
val bfs = BFS(from) { canPassThrough(it) }
|
||||
bfs.stepUntilDestination(to)
|
||||
unit.canEnterForeignTerrain = tmp
|
||||
unit.cache.canEnterForeignTerrain = tmp
|
||||
return bfs.getReachedTiles()
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class UnitPromotions : IsPartOfGameInfoSerialization {
|
||||
// so this has to go after the `promotions.add(promotionname)` line.
|
||||
doDirectPromotionEffects(promotion)
|
||||
|
||||
unit.updateUniques(ruleset)
|
||||
unit.updateUniques()
|
||||
|
||||
// Since some units get promotions upon construction, they will get the addPromotion from the unit.postBuildEvent
|
||||
// upon creation, BEFORE they are assigned to a tile, so the updateVisibleTiles() would crash.
|
||||
|
@ -160,7 +160,7 @@ class UnitTurnManager(val unit: MapUnit) {
|
||||
|
||||
val tileOwner = unit.getTile().getOwner()
|
||||
if (tileOwner != null
|
||||
&& !unit.canEnterForeignTerrain
|
||||
&& !unit.cache.canEnterForeignTerrain
|
||||
&& !unit.civ.diplomacyFunctions.canPassThroughTiles(tileOwner)
|
||||
&& !tileOwner.isCityState()) // if an enemy city expanded onto this tile while I was in it
|
||||
unit.movement.teleportToClosestMoveableTile()
|
||||
|
@ -99,7 +99,7 @@ class TradeLogic(val ourCivilization:Civilization, val otherCivilization: Civili
|
||||
.forEach { it.movement.teleportToClosestMoveableTile() }
|
||||
for (tile in city.getTiles()) {
|
||||
for (unit in tile.getUnits().toList()) {
|
||||
if (!unit.civ.diplomacyFunctions.canPassThroughTiles(to) && !unit.canEnterForeignTerrain)
|
||||
if (!unit.civ.diplomacyFunctions.canPassThroughTiles(to) && !unit.cache.canEnterForeignTerrain)
|
||||
unit.movement.teleportToClosestMoveableTile()
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ import com.unciv.ui.worldscreen.status.MultiplayerStatusButton
|
||||
import com.unciv.ui.worldscreen.status.NextTurnAction
|
||||
import com.unciv.ui.worldscreen.status.NextTurnButton
|
||||
import com.unciv.ui.worldscreen.status.StatusButtons
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsTable
|
||||
import com.unciv.ui.worldscreen.unit.UnitTable
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsTable
|
||||
import com.unciv.utils.concurrency.Concurrency
|
||||
import com.unciv.utils.concurrency.launchOnGLThread
|
||||
import com.unciv.utils.concurrency.launchOnThreadPool
|
||||
@ -543,7 +543,7 @@ class WorldScreen(
|
||||
|
||||
displayTutorial(TutorialTrigger.Workers) {
|
||||
gameInfo.getCurrentPlayerCivilization().units.getCivUnits().any {
|
||||
it.hasUniqueToBuildImprovements && it.isCivilian() && !it.isGreatPerson()
|
||||
it.cache.hasUniqueToBuildImprovements && it.isCivilian() && !it.isGreatPerson()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ object UnitActions {
|
||||
addAirSweepAction(unit, actionList)
|
||||
addSetupAction(unit, actionList)
|
||||
addFoundCityAction(unit, actionList, tile)
|
||||
addBuildingImprovementsAction(unit, actionList, tile, worldScreen, unitTable)
|
||||
addBuildingImprovementsAction(unit, actionList, tile, worldScreen)
|
||||
addRepairAction(unit, actionList)
|
||||
addCreateWaterImprovements(unit, actionList)
|
||||
UnitActionsGreatPerson.addGreatPersonActions(unit, actionList, tile)
|
||||
@ -255,7 +255,7 @@ object UnitActions {
|
||||
val paradropUniques =
|
||||
unit.getMatchingUniques(UniqueType.MayParadrop)
|
||||
if (!paradropUniques.any() || unit.isEmbarked()) return
|
||||
unit.paradropRange = paradropUniques.maxOfOrNull { it.params[0] }!!.toInt()
|
||||
unit.cache.paradropRange = paradropUniques.maxOfOrNull { it.params[0] }!!.toInt()
|
||||
actionList += UnitAction(UnitActionType.Paradrop,
|
||||
isCurrentAction = unit.isPreparingParadrop(),
|
||||
action = {
|
||||
@ -356,8 +356,13 @@ object UnitActions {
|
||||
return transformList
|
||||
}
|
||||
|
||||
private fun addBuildingImprovementsAction(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile, worldScreen: WorldScreen, unitTable: UnitTable) {
|
||||
if (!unit.hasUniqueToBuildImprovements) return
|
||||
private fun addBuildingImprovementsAction(
|
||||
unit: MapUnit,
|
||||
actionList: ArrayList<UnitAction>,
|
||||
tile: Tile,
|
||||
worldScreen: WorldScreen
|
||||
) {
|
||||
if (!unit.cache.hasUniqueToBuildImprovements) return
|
||||
if (unit.isEmbarked()) return
|
||||
|
||||
val couldConstruct = unit.currentMovement > 0
|
||||
@ -390,7 +395,7 @@ object UnitActions {
|
||||
|
||||
private fun addRepairAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (unit.currentTile.ruleset.tileImprovements[Constants.repair] == null) return
|
||||
if (!unit.hasUniqueToBuildImprovements) return
|
||||
if (!unit.cache.hasUniqueToBuildImprovements) return
|
||||
if (unit.isEmbarked()) return
|
||||
val tile = unit.getTile()
|
||||
if (tile.isCityCenter()) return
|
||||
@ -416,7 +421,7 @@ object UnitActions {
|
||||
}
|
||||
|
||||
private fun addAutomateBuildingImprovementsAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (!unit.hasUniqueToBuildImprovements) return
|
||||
if (!unit.cache.hasUniqueToBuildImprovements) return
|
||||
if (unit.isAutomated()) return
|
||||
|
||||
actionList += UnitAction(UnitActionType.Automate,
|
||||
|
Reference in New Issue
Block a user