mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 13:55:54 -04:00
Chore: Moved tile stat functions to separate class
This commit is contained in:
parent
98f64b1fd4
commit
801116551b
@ -324,7 +324,7 @@ object GameStarter {
|
|||||||
|
|
||||||
val startScores = HashMap<TileInfo, Float>(tileMap.values.size)
|
val startScores = HashMap<TileInfo, Float>(tileMap.values.size)
|
||||||
for (tile in tileMap.values) {
|
for (tile in tileMap.values) {
|
||||||
startScores[tile] = tile.getTileStartScore()
|
startScores[tile] = tile.stats.getTileStartScore()
|
||||||
}
|
}
|
||||||
val allCivs = gameInfo.civilizations.filter { !it.isBarbarian() }
|
val allCivs = gameInfo.civilizations.filter { !it.isBarbarian() }
|
||||||
val landTilesInBigEnoughGroup = getCandidateLand(allCivs.size, tileMap, startScores)
|
val landTilesInBigEnoughGroup = getCandidateLand(allCivs.size, tileMap, startScores)
|
||||||
|
@ -22,7 +22,7 @@ import com.unciv.ui.victoryscreen.RankingType
|
|||||||
object Automation {
|
object Automation {
|
||||||
|
|
||||||
fun rankTileForCityWork(tile: TileInfo, city: CityInfo, cityStats: Stats): Float {
|
fun rankTileForCityWork(tile: TileInfo, city: CityInfo, cityStats: Stats): Float {
|
||||||
val stats = tile.getTileStats(city, city.civInfo)
|
val stats = tile.stats.getTileStats(city, city.civInfo)
|
||||||
return rankStatsForCityWork(stats, city, cityStats)
|
return rankStatsForCityWork(stats, city, cityStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ object Automation {
|
|||||||
if (tile == null) return 0f
|
if (tile == null) return 0f
|
||||||
val tileOwner = tile.getOwner()
|
val tileOwner = tile.getOwner()
|
||||||
if (tileOwner != null && tileOwner != civInfo) return 0f // Already belongs to another civilization, useless to us
|
if (tileOwner != null && tileOwner != civInfo) return 0f // Already belongs to another civilization, useless to us
|
||||||
val stats = tile.getTileStats(null, civInfo)
|
val stats = tile.stats.getTileStats(null, civInfo)
|
||||||
var rank = rankStatsValue(stats, civInfo)
|
var rank = rankStatsValue(stats, civInfo)
|
||||||
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
||||||
if (tile.isPillaged()) rank += 0.6f
|
if (tile.isPillaged()) rank += 0.6f
|
||||||
@ -400,7 +400,7 @@ object Automation {
|
|||||||
if (tile.naturalWonder != null) score -= 105
|
if (tile.naturalWonder != null) score -= 105
|
||||||
|
|
||||||
// Straight up take the sum of all yields
|
// Straight up take the sum of all yields
|
||||||
score -= tile.getTileStats(cityInfo, cityInfo.civInfo, localUniqueCache).values.sum().toInt()
|
score -= tile.stats.getTileStats(cityInfo, cityInfo.civInfo, localUniqueCache).values.sum().toInt()
|
||||||
|
|
||||||
// Check if we get access to better tiles from this tile
|
// Check if we get access to better tiles from this tile
|
||||||
var adjacentNaturalWonder = false
|
var adjacentNaturalWonder = false
|
||||||
|
@ -363,7 +363,7 @@ class CityStats(val cityInfo: CityInfo) {
|
|||||||
|| it.terrainHasUnique(UniqueType.TileProvidesYieldWithoutPopulation))
|
|| it.terrainHasUnique(UniqueType.TileProvidesYieldWithoutPopulation))
|
||||||
}
|
}
|
||||||
for (cell in workedTiles) {
|
for (cell in workedTiles) {
|
||||||
val cellStats = cell.getTileStats(cityInfo, cityInfo.civInfo, localUniqueCache)
|
val cellStats = cell.stats.getTileStats(cityInfo, cityInfo.civInfo, localUniqueCache)
|
||||||
stats.add(cellStats)
|
stats.add(cellStats)
|
||||||
}
|
}
|
||||||
statsFromTiles = stats
|
statsFromTiles = stats
|
||||||
|
@ -175,7 +175,7 @@ class CityPopulationManager : IsPartOfGameInfoSerialization {
|
|||||||
if (valueBestTile > valueBestSpecialist) {
|
if (valueBestTile > valueBestSpecialist) {
|
||||||
if (bestTile != null) {
|
if (bestTile != null) {
|
||||||
cityInfo.workedTiles = cityInfo.workedTiles.withItem(bestTile.position)
|
cityInfo.workedTiles = cityInfo.workedTiles.withItem(bestTile.position)
|
||||||
cityStats[Stat.Food] += bestTile.getTileStats(cityInfo, cityInfo.civInfo)[Stat.Food]
|
cityStats[Stat.Food] += bestTile.stats.getTileStats(cityInfo, cityInfo.civInfo)[Stat.Food]
|
||||||
}
|
}
|
||||||
} else if (bestJob != null) {
|
} else if (bestJob != null) {
|
||||||
specialistAllocations.add(bestJob, 1)
|
specialistAllocations.add(bestJob, 1)
|
||||||
|
@ -3,12 +3,12 @@ package com.unciv.logic.map.mapgenerator
|
|||||||
import com.badlogic.gdx.math.Rectangle
|
import com.badlogic.gdx.math.Rectangle
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.logic.map.HexMath
|
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.logic.map.HexMath
|
||||||
import com.unciv.logic.map.MapResources
|
import com.unciv.logic.map.MapResources
|
||||||
import com.unciv.logic.map.MapShape
|
import com.unciv.logic.map.MapShape
|
||||||
import com.unciv.logic.map.tile.TileInfo
|
|
||||||
import com.unciv.logic.map.TileMap
|
import com.unciv.logic.map.TileMap
|
||||||
|
import com.unciv.logic.map.tile.TileInfo
|
||||||
import com.unciv.models.metadata.GameParameters
|
import com.unciv.models.metadata.GameParameters
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
@ -265,7 +265,7 @@ class MapRegions (val ruleset: Ruleset){
|
|||||||
// The rest are positive bias
|
// The rest are positive bias
|
||||||
val positiveBiasCivs = civilizations.filterNot { it in coastBiasCivs || it in negativeBiasCivs || it in randomCivs }
|
val positiveBiasCivs = civilizations.filterNot { it in coastBiasCivs || it in negativeBiasCivs || it in randomCivs }
|
||||||
.sortedBy { ruleset.nations[it.civName]!!.startBias.size } // civs with only one desired region go first
|
.sortedBy { ruleset.nations[it.civName]!!.startBias.size } // civs with only one desired region go first
|
||||||
val positiveBiasFallbackCivs = ArrayList<CivilizationInfo>() // Civs who couln't get their desired region at first pass
|
val positiveBiasFallbackCivs = ArrayList<CivilizationInfo>() // Civs who couldn't get their desired region at first pass
|
||||||
val unpickedRegions = regions.toMutableList()
|
val unpickedRegions = regions.toMutableList()
|
||||||
|
|
||||||
// First assign coast bias civs
|
// First assign coast bias civs
|
||||||
@ -711,7 +711,7 @@ class MapRegions (val ruleset: Ruleset){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPotentialYield(tile: TileInfo, stat: Stat, unimproved: Boolean = false): Float {
|
private fun getPotentialYield(tile: TileInfo, stat: Stat, unimproved: Boolean = false): Float {
|
||||||
val baseYield = tile.getTileStats(null)[stat]
|
val baseYield = tile.stats.getTileStats(null)[stat]
|
||||||
if (unimproved) return baseYield
|
if (unimproved) return baseYield
|
||||||
|
|
||||||
val bestImprovementYield = tile.tileMap.ruleset!!.tileImprovements.values
|
val bestImprovementYield = tile.tileMap.ruleset!!.tileImprovements.values
|
||||||
|
@ -17,17 +17,13 @@ import com.unciv.models.ruleset.tile.Terrain
|
|||||||
import com.unciv.models.ruleset.tile.TerrainType
|
import com.unciv.models.ruleset.tile.TerrainType
|
||||||
import com.unciv.models.ruleset.tile.TileImprovement
|
import com.unciv.models.ruleset.tile.TileImprovement
|
||||||
import com.unciv.models.ruleset.tile.TileResource
|
import com.unciv.models.ruleset.tile.TileResource
|
||||||
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
|
||||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.ruleset.unique.UniqueMap
|
import com.unciv.models.ruleset.unique.UniqueMap
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.stats.Stat
|
|
||||||
import com.unciv.models.stats.Stats
|
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.civilopedia.FormattedLine
|
import com.unciv.ui.civilopedia.FormattedLine
|
||||||
import com.unciv.ui.utils.Fonts
|
import com.unciv.ui.utils.Fonts
|
||||||
import com.unciv.ui.utils.extensions.toPercent
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -42,6 +38,9 @@ open class TileInfo : IsPartOfGameInfoSerialization {
|
|||||||
@Transient
|
@Transient
|
||||||
val improvementFunctions = TileInfoImprovementFunctions(this)
|
val improvementFunctions = TileInfoImprovementFunctions(this)
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
val stats = TileStatFunctions(this)
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private var isCityCenterInternal = false
|
private var isCityCenterInternal = false
|
||||||
|
|
||||||
@ -230,7 +229,7 @@ open class TileInfo : IsPartOfGameInfoSerialization {
|
|||||||
return tileResourceCache!!
|
return tileResourceCache!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getNaturalWonder(): Terrain =
|
internal fun getNaturalWonder(): Terrain =
|
||||||
if (naturalWonder == null) throw Exception("No natural wonder exists for this tile!")
|
if (naturalWonder == null) throw Exception("No natural wonder exists for this tile!")
|
||||||
else ruleset.terrains[naturalWonder!!]!!
|
else ruleset.terrains[naturalWonder!!]!!
|
||||||
|
|
||||||
@ -430,168 +429,6 @@ open class TileInfo : IsPartOfGameInfoSerialization {
|
|||||||
return workingCity != null && workingCity.lockedTiles.contains(position)
|
return workingCity != null && workingCity.lockedTiles.contains(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTileStats(observingCiv: CivilizationInfo?): Stats = getTileStats(getCity(), observingCiv)
|
|
||||||
|
|
||||||
fun getTileStats(city: CityInfo?, observingCiv: CivilizationInfo?,
|
|
||||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
|
||||||
): Stats {
|
|
||||||
var stats = getBaseTerrain().cloneStats()
|
|
||||||
|
|
||||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, cityInfo = city, tile = this)
|
|
||||||
|
|
||||||
for (terrainFeatureBase in terrainFeatureObjects) {
|
|
||||||
when {
|
|
||||||
terrainFeatureBase.hasUnique(UniqueType.NullifyYields) ->
|
|
||||||
return terrainFeatureBase.cloneStats()
|
|
||||||
terrainFeatureBase.overrideStats -> stats = terrainFeatureBase.cloneStats()
|
|
||||||
else -> stats.add(terrainFeatureBase)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (naturalWonder != null) {
|
|
||||||
val wonderStats = getNaturalWonder().cloneStats()
|
|
||||||
|
|
||||||
if (getNaturalWonder().overrideStats)
|
|
||||||
stats = wonderStats
|
|
||||||
else
|
|
||||||
stats.add(wonderStats)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (city != null) {
|
|
||||||
var tileUniques = city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
|
|
||||||
.filter { city.matchesFilter(it.params[2]) }
|
|
||||||
tileUniques += city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals)
|
|
||||||
for (unique in localUniqueCache.get("StatsFromTilesAndObjects", tileUniques)) {
|
|
||||||
if (!unique.conditionalsApply(stateForConditionals)) continue
|
|
||||||
val tileType = unique.params[1]
|
|
||||||
if (!matchesTerrainFilter(tileType, observingCiv)) continue
|
|
||||||
stats.add(unique.stats)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unique in localUniqueCache.get("StatsFromTilesWithout",
|
|
||||||
city.getMatchingUniques(UniqueType.StatsFromTilesWithout, StateForConditionals.IgnoreConditionals))
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
unique.conditionalsApply(stateForConditionals) &&
|
|
||||||
matchesTerrainFilter(unique.params[1]) &&
|
|
||||||
!matchesTerrainFilter(unique.params[2]) &&
|
|
||||||
city.matchesFilter(unique.params[3])
|
|
||||||
)
|
|
||||||
stats.add(unique.stats)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAdjacentToRiver()) stats.gold++
|
|
||||||
|
|
||||||
if (observingCiv != null) {
|
|
||||||
// resource base
|
|
||||||
if (hasViewableResource(observingCiv)) stats.add(tileResource)
|
|
||||||
|
|
||||||
val improvement = getUnpillagedTileImprovement()
|
|
||||||
if (improvement != null)
|
|
||||||
stats.add(improvementFunctions.getImprovementStats(improvement, observingCiv, city, localUniqueCache))
|
|
||||||
|
|
||||||
if (stats.gold != 0f && observingCiv.goldenAges.isGoldenAge())
|
|
||||||
stats.gold++
|
|
||||||
}
|
|
||||||
if (isCityCenter()) {
|
|
||||||
if (stats.food < 2) stats.food = 2f
|
|
||||||
if (stats.production < 1) stats.production = 1f
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((stat, value) in stats)
|
|
||||||
if (value < 0f) stats[stat] = 0f
|
|
||||||
|
|
||||||
for ((stat, value) in getTilePercentageStats(observingCiv, city)) {
|
|
||||||
stats[stat] *= value.toPercent()
|
|
||||||
}
|
|
||||||
|
|
||||||
return stats
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only gets the tile percentage bonus, not the improvement percentage bonus
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
fun getTilePercentageStats(observingCiv: CivilizationInfo?, city: CityInfo?): Stats {
|
|
||||||
val stats = Stats()
|
|
||||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, cityInfo = city, tile = this)
|
|
||||||
|
|
||||||
if (city != null) {
|
|
||||||
for (unique in city.getMatchingUniques(UniqueType.StatPercentFromObject, stateForConditionals)) {
|
|
||||||
val tileFilter = unique.params[2]
|
|
||||||
if (matchesTerrainFilter(tileFilter, observingCiv))
|
|
||||||
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unique in city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, stateForConditionals)) {
|
|
||||||
val tileFilter = unique.params[1]
|
|
||||||
if (!matchesTerrainFilter(tileFilter, observingCiv)) continue
|
|
||||||
val statPercentage = unique.params[0].toFloat()
|
|
||||||
for (stat in Stat.values())
|
|
||||||
stats[stat] += statPercentage
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (observingCiv != null) {
|
|
||||||
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, stateForConditionals)) {
|
|
||||||
val tileFilter = unique.params[2]
|
|
||||||
if (matchesTerrainFilter(tileFilter, observingCiv))
|
|
||||||
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, stateForConditionals)) {
|
|
||||||
val tileFilter = unique.params[1]
|
|
||||||
if (!matchesTerrainFilter(tileFilter, observingCiv)) continue
|
|
||||||
val statPercentage = unique.params[0].toFloat()
|
|
||||||
for (stat in Stat.values())
|
|
||||||
stats[stat] += statPercentage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stats
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTileStartScore(): Float {
|
|
||||||
var sum = 0f
|
|
||||||
for (tile in getTilesInDistance(2)) {
|
|
||||||
val tileYield = tile.getTileStartYield(tile == this)
|
|
||||||
sum += tileYield
|
|
||||||
if (tile in neighbors)
|
|
||||||
sum += tileYield
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isHill())
|
|
||||||
sum -= 2f
|
|
||||||
if (isAdjacentToRiver())
|
|
||||||
sum += 2f
|
|
||||||
if (neighbors.any { it.baseTerrain == Constants.mountain })
|
|
||||||
sum += 2f
|
|
||||||
if (isCoastalTile())
|
|
||||||
sum += 3f
|
|
||||||
if (!isCoastalTile() && neighbors.any { it.isCoastalTile() })
|
|
||||||
sum -= 7f
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTileStartYield(isCenter: Boolean): Float {
|
|
||||||
var stats = getBaseTerrain().cloneStats()
|
|
||||||
|
|
||||||
for (terrainFeatureBase in terrainFeatureObjects) {
|
|
||||||
if (terrainFeatureBase.overrideStats)
|
|
||||||
stats = terrainFeatureBase.cloneStats()
|
|
||||||
else
|
|
||||||
stats.add(terrainFeatureBase)
|
|
||||||
}
|
|
||||||
if (resource != null) stats.add(tileResource)
|
|
||||||
|
|
||||||
if (stats.production < 0) stats.production = 0f
|
|
||||||
if (isCenter) {
|
|
||||||
if (stats.food < 2) stats.food = 2f
|
|
||||||
if (stats.production < 1) stats.production = 1f
|
|
||||||
}
|
|
||||||
|
|
||||||
return stats.food + stats.production + stats.gold
|
|
||||||
}
|
|
||||||
|
|
||||||
// For dividing the map into Regions to determine start locations
|
// For dividing the map into Regions to determine start locations
|
||||||
fun getTileFertility(checkCoasts: Boolean): Int {
|
fun getTileFertility(checkCoasts: Boolean): Int {
|
||||||
var fertility = 0
|
var fertility = 0
|
||||||
|
177
core/src/com/unciv/logic/map/tile/TileStatFunctions.kt
Normal file
177
core/src/com/unciv/logic/map/tile/TileStatFunctions.kt
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package com.unciv.logic.map.tile
|
||||||
|
|
||||||
|
import com.unciv.Constants
|
||||||
|
import com.unciv.logic.city.CityInfo
|
||||||
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||||
|
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
|
import com.unciv.models.stats.Stat
|
||||||
|
import com.unciv.models.stats.Stats
|
||||||
|
import com.unciv.ui.utils.extensions.toPercent
|
||||||
|
|
||||||
|
class TileStatFunctions(val tileInfo: TileInfo) {
|
||||||
|
|
||||||
|
fun getTileStats(observingCiv: CivilizationInfo?): Stats = getTileStats(tileInfo.getCity(), observingCiv)
|
||||||
|
|
||||||
|
fun getTileStats(city: CityInfo?, observingCiv: CivilizationInfo?,
|
||||||
|
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||||
|
): Stats {
|
||||||
|
var stats = tileInfo.getBaseTerrain().cloneStats()
|
||||||
|
|
||||||
|
val stateForConditionals = StateForConditionals(civInfo = observingCiv, cityInfo = city, tile = tileInfo)
|
||||||
|
|
||||||
|
for (terrainFeatureBase in tileInfo.terrainFeatureObjects) {
|
||||||
|
when {
|
||||||
|
terrainFeatureBase.hasUnique(UniqueType.NullifyYields) ->
|
||||||
|
return terrainFeatureBase.cloneStats()
|
||||||
|
terrainFeatureBase.overrideStats -> stats = terrainFeatureBase.cloneStats()
|
||||||
|
else -> stats.add(terrainFeatureBase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileInfo.naturalWonder != null) {
|
||||||
|
val wonderStats = tileInfo.getNaturalWonder().cloneStats()
|
||||||
|
|
||||||
|
if (tileInfo.getNaturalWonder().overrideStats)
|
||||||
|
stats = wonderStats
|
||||||
|
else
|
||||||
|
stats.add(wonderStats)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (city != null) {
|
||||||
|
var tileUniques = city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
|
||||||
|
.filter { city.matchesFilter(it.params[2]) }
|
||||||
|
tileUniques += city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals)
|
||||||
|
for (unique in localUniqueCache.get("StatsFromTilesAndObjects", tileUniques)) {
|
||||||
|
if (!unique.conditionalsApply(stateForConditionals)) continue
|
||||||
|
val tileType = unique.params[1]
|
||||||
|
if (!tileInfo.matchesTerrainFilter(tileType, observingCiv)) continue
|
||||||
|
stats.add(unique.stats)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unique in localUniqueCache.get("StatsFromTilesWithout",
|
||||||
|
city.getMatchingUniques(UniqueType.StatsFromTilesWithout, StateForConditionals.IgnoreConditionals))
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
unique.conditionalsApply(stateForConditionals) &&
|
||||||
|
tileInfo.matchesTerrainFilter(unique.params[1]) &&
|
||||||
|
!tileInfo.matchesTerrainFilter(unique.params[2]) &&
|
||||||
|
city.matchesFilter(unique.params[3])
|
||||||
|
)
|
||||||
|
stats.add(unique.stats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileInfo.isAdjacentToRiver()) stats.gold++
|
||||||
|
|
||||||
|
if (observingCiv != null) {
|
||||||
|
// resource base
|
||||||
|
if (tileInfo.hasViewableResource(observingCiv)) stats.add(tileInfo.tileResource)
|
||||||
|
|
||||||
|
val improvement = tileInfo.getUnpillagedTileImprovement()
|
||||||
|
if (improvement != null)
|
||||||
|
stats.add(tileInfo.improvementFunctions.getImprovementStats(improvement, observingCiv, city, localUniqueCache))
|
||||||
|
|
||||||
|
if (stats.gold != 0f && observingCiv.goldenAges.isGoldenAge())
|
||||||
|
stats.gold++
|
||||||
|
}
|
||||||
|
if (tileInfo.isCityCenter()) {
|
||||||
|
if (stats.food < 2) stats.food = 2f
|
||||||
|
if (stats.production < 1) stats.production = 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((stat, value) in stats)
|
||||||
|
if (value < 0f) stats[stat] = 0f
|
||||||
|
|
||||||
|
for ((stat, value) in getTilePercentageStats(observingCiv, city)) {
|
||||||
|
stats[stat] *= value.toPercent()
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only gets the tile percentage bonus, not the improvement percentage bonus
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
fun getTilePercentageStats(observingCiv: CivilizationInfo?, city: CityInfo?): Stats {
|
||||||
|
val stats = Stats()
|
||||||
|
val stateForConditionals = StateForConditionals(civInfo = observingCiv, cityInfo = city, tile = tileInfo)
|
||||||
|
|
||||||
|
if (city != null) {
|
||||||
|
for (unique in city.getMatchingUniques(UniqueType.StatPercentFromObject, stateForConditionals)) {
|
||||||
|
val tileFilter = unique.params[2]
|
||||||
|
if (tileInfo.matchesTerrainFilter(tileFilter, observingCiv))
|
||||||
|
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unique in city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, stateForConditionals)) {
|
||||||
|
val tileFilter = unique.params[1]
|
||||||
|
if (!tileInfo.matchesTerrainFilter(tileFilter, observingCiv)) continue
|
||||||
|
val statPercentage = unique.params[0].toFloat()
|
||||||
|
for (stat in Stat.values())
|
||||||
|
stats[stat] += statPercentage
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (observingCiv != null) {
|
||||||
|
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, stateForConditionals)) {
|
||||||
|
val tileFilter = unique.params[2]
|
||||||
|
if (tileInfo.matchesTerrainFilter(tileFilter, observingCiv))
|
||||||
|
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, stateForConditionals)) {
|
||||||
|
val tileFilter = unique.params[1]
|
||||||
|
if (!tileInfo.matchesTerrainFilter(tileFilter, observingCiv)) continue
|
||||||
|
val statPercentage = unique.params[0].toFloat()
|
||||||
|
for (stat in Stat.values())
|
||||||
|
stats[stat] += statPercentage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTileStartScore(): Float {
|
||||||
|
var sum = 0f
|
||||||
|
for (closeTile in tileInfo.getTilesInDistance(2)) {
|
||||||
|
val tileYield = closeTile.stats.getTileStartYield(closeTile == tileInfo)
|
||||||
|
sum += tileYield
|
||||||
|
if (closeTile in tileInfo.neighbors)
|
||||||
|
sum += tileYield
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileInfo.isHill())
|
||||||
|
sum -= 2f
|
||||||
|
if (tileInfo.isAdjacentToRiver())
|
||||||
|
sum += 2f
|
||||||
|
if (tileInfo.neighbors.any { it.baseTerrain == Constants.mountain })
|
||||||
|
sum += 2f
|
||||||
|
if (tileInfo.isCoastalTile())
|
||||||
|
sum += 3f
|
||||||
|
if (!tileInfo.isCoastalTile() && tileInfo.neighbors.any { it.isCoastalTile() })
|
||||||
|
sum -= 7f
|
||||||
|
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTileStartYield(isCenter: Boolean): Float {
|
||||||
|
var stats = tileInfo.getBaseTerrain().cloneStats()
|
||||||
|
|
||||||
|
for (terrainFeatureBase in tileInfo.terrainFeatureObjects) {
|
||||||
|
if (terrainFeatureBase.overrideStats)
|
||||||
|
stats = terrainFeatureBase.cloneStats()
|
||||||
|
else
|
||||||
|
stats.add(terrainFeatureBase)
|
||||||
|
}
|
||||||
|
if (tileInfo.resource != null) stats.add(tileInfo.tileResource)
|
||||||
|
|
||||||
|
if (stats.production < 0) stats.production = 0f
|
||||||
|
if (isCenter) {
|
||||||
|
if (stats.food < 2) stats.food = 2f
|
||||||
|
if (stats.production < 1) stats.production = 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats.food + stats.production + stats.gold
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -49,7 +49,7 @@ class CityScreenTileTable(private val cityScreen: CityScreen): Table() {
|
|||||||
isVisible = true
|
isVisible = true
|
||||||
innerTable.clearChildren()
|
innerTable.clearChildren()
|
||||||
|
|
||||||
val stats = selectedTile.getTileStats(city, city.civInfo)
|
val stats = selectedTile.stats.getTileStats(city, city.civInfo)
|
||||||
innerTable.pad(5f)
|
innerTable.pad(5f)
|
||||||
|
|
||||||
innerTable.add( MarkupRenderer.render(selectedTile.toMarkup(city.civInfo), iconDisplay = IconDisplay.None) {
|
innerTable.add( MarkupRenderer.render(selectedTile.toMarkup(city.civInfo), iconDisplay = IconDisplay.None) {
|
||||||
@ -110,7 +110,7 @@ class CityScreenTileTable(private val cityScreen: CityScreen): Table() {
|
|||||||
* Used from onClick and keyboard dispatch, thus only minimal parameters are passed,
|
* Used from onClick and keyboard dispatch, thus only minimal parameters are passed,
|
||||||
* and it needs to do all checks and the sound as appropriate.
|
* and it needs to do all checks and the sound as appropriate.
|
||||||
*/
|
*/
|
||||||
fun askToBuyTile(selectedTile: TileInfo) {
|
private fun askToBuyTile(selectedTile: TileInfo) {
|
||||||
// These checks are redundant for the onClick action, but not for the keyboard binding
|
// These checks are redundant for the onClick action, but not for the keyboard binding
|
||||||
if (!isTilePurchaseShown(selectedTile)) return
|
if (!isTilePurchaseShown(selectedTile)) return
|
||||||
val goldCostOfTile = city.expansion.getGoldCostOfTile(selectedTile)
|
val goldCostOfTile = city.expansion.getGoldCostOfTile(selectedTile)
|
||||||
|
@ -78,7 +78,7 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateYieldGroup() {
|
private fun updateYieldGroup() {
|
||||||
yieldGroup.setStats(tileInfo.getTileStats(city, city.civInfo))
|
yieldGroup.setStats(tileInfo.stats.getTileStats(city, city.civInfo))
|
||||||
yieldGroup.setOrigin(Align.center)
|
yieldGroup.setOrigin(Align.center)
|
||||||
yieldGroup.setScale(0.7f)
|
yieldGroup.setScale(0.7f)
|
||||||
yieldGroup.toFront()
|
yieldGroup.toFront()
|
||||||
|
@ -6,11 +6,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.logic.map.tile.TileInfo
|
|
||||||
import com.unciv.logic.map.TileMap
|
import com.unciv.logic.map.TileMap
|
||||||
|
import com.unciv.logic.map.tile.TileInfo
|
||||||
import com.unciv.models.Counter
|
import com.unciv.models.Counter
|
||||||
import com.unciv.models.ruleset.nation.Nation
|
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
|
import com.unciv.models.ruleset.nation.Nation
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.civilopedia.CivilopediaScreen
|
import com.unciv.ui.civilopedia.CivilopediaScreen
|
||||||
@ -158,7 +158,7 @@ class MapEditorViewTab(
|
|||||||
editorScreen.tileClickHandler = null
|
editorScreen.tileClickHandler = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tileClickHandler(tile: TileInfo) {
|
private fun tileClickHandler(tile: TileInfo) {
|
||||||
if (tileDataCell == null) return
|
if (tileDataCell == null) return
|
||||||
|
|
||||||
val lines = ArrayList<FormattedLine>()
|
val lines = ArrayList<FormattedLine>()
|
||||||
@ -169,7 +169,7 @@ class MapEditorViewTab(
|
|||||||
lines.addAll(tile.toMarkup(null))
|
lines.addAll(tile.toMarkup(null))
|
||||||
|
|
||||||
val stats = try {
|
val stats = try {
|
||||||
tile.getTileStats(null, mockCiv)
|
tile.stats.getTileStats(null, mockCiv)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
// Maps aren't always fixed to remove dead references... like resource "Gold"
|
// Maps aren't always fixed to remove dead references... like resource "Gold"
|
||||||
if (ex.message != null)
|
if (ex.message != null)
|
||||||
|
@ -23,7 +23,7 @@ class TileGroupIcons(val tileGroup: TileGroup) {
|
|||||||
|
|
||||||
var improvementIcon: Actor? = null
|
var improvementIcon: Actor? = null
|
||||||
var populationIcon: Image? = null //reuse for acquire icon
|
var populationIcon: Image? = null //reuse for acquire icon
|
||||||
val startingLocationIcons = mutableListOf<Actor>()
|
private val startingLocationIcons = mutableListOf<Actor>()
|
||||||
|
|
||||||
var civilianUnitIcon: UnitGroup? = null
|
var civilianUnitIcon: UnitGroup? = null
|
||||||
var militaryUnitIcon: UnitGroup? = null
|
var militaryUnitIcon: UnitGroup? = null
|
||||||
@ -142,7 +142,7 @@ class TileGroupIcons(val tileGroup: TileGroup) {
|
|||||||
|
|
||||||
if (showTileYields) {
|
if (showTileYields) {
|
||||||
// Setting up YieldGroup Icon
|
// Setting up YieldGroup Icon
|
||||||
tileGroup.tileYieldGroup.setStats(tileGroup.tileInfo.getTileStats(viewingCiv))
|
tileGroup.tileYieldGroup.setStats(tileGroup.tileInfo.stats.getTileStats(viewingCiv))
|
||||||
tileGroup.tileYieldGroup.setOrigin(Align.center)
|
tileGroup.tileYieldGroup.setOrigin(Align.center)
|
||||||
tileGroup.tileYieldGroup.setScale(0.7f)
|
tileGroup.tileYieldGroup.setScale(0.7f)
|
||||||
tileGroup.tileYieldGroup.toFront()
|
tileGroup.tileYieldGroup.toFront()
|
||||||
|
@ -45,7 +45,7 @@ class TileInfoTable(private val viewingCiv :CivilizationInfo) : Table(BaseScreen
|
|||||||
|
|
||||||
// padLeft = padRight + 5: for symmetry. An extra 5 for the distance yield number to
|
// padLeft = padRight + 5: for symmetry. An extra 5 for the distance yield number to
|
||||||
// tile text comes from the pad up there in updateTileTable
|
// tile text comes from the pad up there in updateTileTable
|
||||||
for ((key, value) in tile.getTileStats(viewingCiv)) {
|
for ((key, value) in tile.stats.getTileStats(viewingCiv)) {
|
||||||
table.add(ImageGetter.getStatIcon(key.name))
|
table.add(ImageGetter.getStatIcon(key.name))
|
||||||
.size(20f).align(Align.right).padLeft(10f)
|
.size(20f).align(Align.right).padLeft(10f)
|
||||||
table.add(value.toInt().toLabel())
|
table.add(value.toInt().toLabel())
|
||||||
|
@ -133,7 +133,7 @@ class GlobalUniquesTests {
|
|||||||
cityInfo.cityConstructions.addBuilding(building.name)
|
cityInfo.cityConstructions.addBuilding(building.name)
|
||||||
|
|
||||||
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
||||||
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).gold == 4f)
|
Assert.assertTrue(tile2.stats.getTileStats(cityInfo, civInfo).gold == 4f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -147,11 +147,11 @@ class GlobalUniquesTests {
|
|||||||
|
|
||||||
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
||||||
game.addTileToCity(cityInfo, tile2)
|
game.addTileToCity(cityInfo, tile2)
|
||||||
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).gold == 4f)
|
Assert.assertTrue(tile2.stats.getTileStats(cityInfo, civInfo).gold == 4f)
|
||||||
|
|
||||||
val tile3 = game.setTileFeatures(Vector2(0f, 2f), Constants.grassland, listOf(Constants.forest))
|
val tile3 = game.setTileFeatures(Vector2(0f, 2f), Constants.grassland, listOf(Constants.forest))
|
||||||
game.addTileToCity(cityInfo, tile3)
|
game.addTileToCity(cityInfo, tile3)
|
||||||
Assert.assertFalse(tile3.getTileStats(cityInfo, civInfo).gold == 4f)
|
Assert.assertFalse(tile3.stats.getTileStats(cityInfo, civInfo).gold == 4f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -174,7 +174,7 @@ class GlobalUniquesTests {
|
|||||||
cityInfo.cityConstructions.addBuilding(building2.name)
|
cityInfo.cityConstructions.addBuilding(building2.name)
|
||||||
|
|
||||||
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
||||||
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).faith == 3f)
|
Assert.assertTrue(tile2.stats.getTileStats(cityInfo, civInfo).faith == 3f)
|
||||||
|
|
||||||
cityInfo.cityConstructions.removeBuilding(building2.name)
|
cityInfo.cityConstructions.removeBuilding(building2.name)
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ class GlobalUniquesTests {
|
|||||||
|
|
||||||
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
||||||
tile2.changeImprovement("Farm")
|
tile2.changeImprovement("Farm")
|
||||||
Assert.assertTrue(tile2.getTileStats(city, civInfo).faith == 9f)
|
Assert.assertTrue(tile2.stats.getTileStats(city, civInfo).faith == 9f)
|
||||||
|
|
||||||
city.cityConstructions.addBuilding(emptyBuilding.name)
|
city.cityConstructions.addBuilding(emptyBuilding.name)
|
||||||
city.cityStats.update()
|
city.cityStats.update()
|
||||||
@ -342,7 +342,7 @@ class GlobalUniquesTests {
|
|||||||
|
|
||||||
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
val tile2 = game.setTileFeatures(Vector2(0f,1f), Constants.grassland)
|
||||||
tile2.changeImprovement("Farm")
|
tile2.changeImprovement("Farm")
|
||||||
Assert.assertTrue(tile2.getTileStats(city, civInfo).faith == 9f)
|
Assert.assertTrue(tile2.stats.getTileStats(city, civInfo).faith == 9f)
|
||||||
|
|
||||||
city.cityConstructions.addBuilding(emptyBuilding.name)
|
city.cityConstructions.addBuilding(emptyBuilding.name)
|
||||||
city.cityStats.update()
|
city.cityStats.update()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user