mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-05 21:11:35 +07:00
Fix problems with stats from tiles and improvements (#10980)
* Fix problems with stats from tiles and improvements * Hold on, we can get the ruleset from the tile. And I was about to complain about that * Update docs * Funky null fix * if else chain doesn't make sense for percent changes on second thought * Incorporate suggestions * Use getUnpillagedImprovement functions in matchesFilter * We don't actually need the whole improvement here, just the name * Move Golden Age to after all other stats * Simplify percent stat adds
This commit is contained in:
parent
8d7e1a2a42
commit
4a72213cde
@ -576,7 +576,7 @@ class WorkerAutomation(
|
||||
var repairBonusPriority = tile.getImprovementToRepair()!!.getTurnsToBuild(unit.civ,unit) - UnitActionsFromUniques.getRepairTurns(unit)
|
||||
if (tile.improvementInProgress == Constants.repair) repairBonusPriority += UnitActionsFromUniques.getRepairTurns(unit) - tile.turnsToImprovement
|
||||
|
||||
val repairPriority = repairBonusPriority + Automation.rankStatsValue(TileStatFunctions(tile).getImprovementStats(tile.getTileImprovement()!!,unit.civ, tile.owningCity), unit.civ)
|
||||
val repairPriority = repairBonusPriority + Automation.rankStatsValue(TileStatFunctions(tile).getStatDiffForImprovement(tile.getTileImprovement()!!, unit.civ, tile.owningCity), unit.civ)
|
||||
if (repairPriority > rank.improvementPriority!!) {
|
||||
rank.improvementPriority = repairPriority
|
||||
rank.bestImprovement = null
|
||||
|
@ -475,11 +475,17 @@ open class Tile : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
/** Implements [UniqueParameterType.TileFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TileFilter] */
|
||||
fun matchesFilter(filter: String, civInfo: Civilization? = null): Boolean {
|
||||
fun matchesFilter(filter: String, civInfo: Civilization? = null, ignoreImprovement: Boolean = false): Boolean {
|
||||
return MultiFilter.multiFilter(filter, { matchesSingleFilter(it, civInfo, ignoreImprovement) })
|
||||
}
|
||||
|
||||
fun matchesSingleFilter(filter: String, civInfo: Civilization? = null, ignoreImprovement: Boolean = false): Boolean {
|
||||
if (matchesTerrainFilter(filter, civInfo)) return true
|
||||
if ((improvement == null || improvementIsPillaged) && filter == "unimproved") return true
|
||||
if (improvement != null && !improvementIsPillaged && filter == "improved") return true
|
||||
return improvement != null && !improvementIsPillaged && ruleset.tileImprovements[improvement]!!.matchesFilter(filter)
|
||||
if (ignoreImprovement) return false
|
||||
if (getUnpillagedTileImprovement()?.matchesFilter(filter) == true) return true
|
||||
return getUnpillagedRoadImprovement()?.matchesFilter(filter) == true
|
||||
}
|
||||
|
||||
fun matchesTerrainFilter(filter: String, observingCiv: Civilization? = null): Boolean {
|
||||
|
@ -27,16 +27,27 @@ class TileStatFunctions(val tile: Tile) {
|
||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
): Stats = getTileStats(tile.getCity(), observingCiv, localUniqueCache)
|
||||
|
||||
fun getTileStats(city: City?, observingCiv: Civilization?,
|
||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
fun getTileStats(
|
||||
city: City?, observingCiv: Civilization?,
|
||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
): Stats {
|
||||
val stats = getTileStatsBreakdown(city, observingCiv, localUniqueCache).toStats()
|
||||
val statsBreakdown = getTileStatsBreakdown(city, observingCiv, localUniqueCache)
|
||||
|
||||
for ((stat, value) in getTilePercentageStats(observingCiv, city, localUniqueCache)) {
|
||||
stats[stat] *= value.toPercent()
|
||||
val improvement = tile.getUnpillagedImprovement()
|
||||
val road = tile.getUnpillagedRoad()
|
||||
|
||||
val percentageStats = getTilePercentageStats(observingCiv, city, localUniqueCache)
|
||||
for (stats in statsBreakdown) {
|
||||
val tileType = when(stats.first) {
|
||||
improvement -> "Improvement"
|
||||
road.name -> "Road"
|
||||
else -> "Terrain"
|
||||
}
|
||||
for ((stat, value) in percentageStats[tileType]!!)
|
||||
stats.second[stat] *= value.toPercent()
|
||||
}
|
||||
|
||||
return stats
|
||||
return statsBreakdown.toStats()
|
||||
}
|
||||
|
||||
fun getTileStatsBreakdown(city: City?, observingCiv: Civilization?,
|
||||
@ -45,6 +56,12 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
val listOfStats = getTerrainStatsBreakdown(stateForConditionals)
|
||||
|
||||
val improvement = tile.getUnpillagedTileImprovement()
|
||||
val improvementStats = improvement?.cloneStats() ?: Stats()
|
||||
|
||||
val road = tile.getUnpillagedRoadImprovement()
|
||||
val roadStats = road?.cloneStats() ?: Stats()
|
||||
|
||||
if (city != null) {
|
||||
val statsFromTilesUniques =
|
||||
localUniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromTiles, stateForConditionals)
|
||||
@ -53,20 +70,18 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val statsFromObjectsUniques = localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromObject, stateForConditionals)
|
||||
|
||||
for (unique in statsFromTilesUniques + statsFromObjectsUniques) {
|
||||
val tileType = unique.params[1]
|
||||
if (!tile.matchesTerrainFilter(tileType, observingCiv)) continue
|
||||
listOfStats.add("{${unique.sourceObjectName}} ({${unique.text}})" to unique.stats)
|
||||
}
|
||||
val statsFromTilesWithoutUniques = localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromTilesWithout, stateForConditionals)
|
||||
.filter { city.matchesFilter(it.params[3]) && !tile.matchesFilter(it.params[2]) }
|
||||
|
||||
for (unique in localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromTilesWithout, stateForConditionals)) {
|
||||
if (
|
||||
tile.matchesTerrainFilter(unique.params[1]) &&
|
||||
!tile.matchesTerrainFilter(unique.params[2]) &&
|
||||
city.matchesFilter(unique.params[3])
|
||||
)
|
||||
for (unique in statsFromTilesUniques + statsFromObjectsUniques + statsFromTilesWithoutUniques) {
|
||||
val tileType = unique.params[1]
|
||||
if (tile.matchesFilter(tileType, observingCiv, true))
|
||||
listOfStats.add("{${unique.sourceObjectName}} ({${unique.text}})" to unique.stats)
|
||||
else if (improvement != null && improvement.matchesFilter(tileType))
|
||||
improvementStats.add(unique.stats)
|
||||
else if (road != null && road.matchesFilter(tileType))
|
||||
roadStats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,12 +101,11 @@ class TileStatFunctions(val tile: Tile) {
|
||||
// resource base
|
||||
if (tile.hasViewableResource(observingCiv)) listOfStats.add(tile.tileResource.name to tile.tileResource)
|
||||
|
||||
val improvement = tile.getUnpillagedTileImprovement()
|
||||
if (improvement != null)
|
||||
listOfStats.add(improvement.name to getImprovementStats(improvement, observingCiv, city, localUniqueCache))
|
||||
improvementStats.add(getExtraImprovementStats(improvement, observingCiv, city))
|
||||
|
||||
if (listOfStats.toStats().gold != 0f && observingCiv.goldenAges.isGoldenAge())
|
||||
listOfStats.add("Golden Age" to Stats(gold = 1f))
|
||||
if (road != null)
|
||||
roadStats.add(getExtraImprovementStats(road, observingCiv, city))
|
||||
|
||||
if (improvement != null) {
|
||||
val ensureMinUnique = improvement
|
||||
@ -101,9 +115,16 @@ class TileStatFunctions(val tile: Tile) {
|
||||
}
|
||||
}
|
||||
|
||||
if (road != null) listOfStats.add(road.name to roadStats)
|
||||
if (improvement != null) listOfStats.add(improvement.name to improvementStats)
|
||||
|
||||
val statsFromMinimum = missingFromMinimum(listOfStats.toStats(), minimumStats)
|
||||
listOfStats.add("Minimum" to statsFromMinimum)
|
||||
|
||||
if (observingCiv != null &&
|
||||
listOfStats.toStats().gold != 0f && observingCiv.goldenAges.isGoldenAge())
|
||||
listOfStats.add("Golden Age" to Stats(gold = 1f))
|
||||
|
||||
return listOfStats.filter { !it.second.isEmpty() }
|
||||
}
|
||||
|
||||
@ -150,51 +171,59 @@ class TileStatFunctions(val tile: Tile) {
|
||||
|
||||
// Only gets the tile percentage bonus, not the improvement percentage bonus
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getTilePercentageStats(observingCiv: Civilization?, city: City?, uniqueCache: LocalUniqueCache): Stats {
|
||||
val stats = Stats()
|
||||
fun getTilePercentageStats(observingCiv: Civilization?, city: City?, uniqueCache: LocalUniqueCache): HashMap<String, Stats> {
|
||||
val terrainStats = Stats()
|
||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
val improvement = tile.getUnpillagedTileImprovement()
|
||||
val improvementStats = Stats()
|
||||
|
||||
val road = tile.getUnpillagedRoadImprovement()
|
||||
val roadStats = Stats()
|
||||
|
||||
fun addStats(filter: String, stat: Stat, amount: Float) {
|
||||
if (tile.matchesFilter(filter, observingCiv, true))
|
||||
terrainStats.add(stat, amount)
|
||||
else if (improvement != null && improvement.matchesFilter(filter))
|
||||
improvementStats.add(stat, amount)
|
||||
else if (road != null && road.matchesFilter(filter))
|
||||
roadStats.add(stat, amount)
|
||||
}
|
||||
|
||||
if (city != null) {
|
||||
val cachedStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatPercentFromObject, stateForConditionals)
|
||||
|
||||
for (unique in cachedStatPercentFromObjectCityUniques) {
|
||||
val tileFilter = unique.params[2]
|
||||
if (tile.matchesTerrainFilter(tileFilter, observingCiv))
|
||||
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
||||
addStats(unique.params[2], Stat.valueOf(unique.params[1]), unique.params[0].toFloat())
|
||||
}
|
||||
|
||||
val cachedAllStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.AllStatsPercentFromObject, stateForConditionals)
|
||||
for (unique in cachedAllStatPercentFromObjectCityUniques) {
|
||||
val tileFilter = unique.params[1]
|
||||
if (!tile.matchesTerrainFilter(tileFilter, observingCiv)) continue
|
||||
val statPercentage = unique.params[0].toFloat()
|
||||
for (stat in Stat.values())
|
||||
stats[stat] += statPercentage
|
||||
addStats(unique.params[1], stat, unique.params[0].toFloat())
|
||||
}
|
||||
|
||||
} else if (observingCiv != null) {
|
||||
val cachedStatPercentFromObjectCivUniques = uniqueCache.forCivGetMatchingUniques(
|
||||
observingCiv, UniqueType.StatPercentFromObject, stateForConditionals)
|
||||
for (unique in cachedStatPercentFromObjectCivUniques) {
|
||||
val tileFilter = unique.params[2]
|
||||
if (tile.matchesTerrainFilter(tileFilter, observingCiv))
|
||||
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
||||
addStats(unique.params[2], Stat.valueOf(unique.params[1]), unique.params[0].toFloat())
|
||||
}
|
||||
|
||||
val cachedAllStatPercentFromObjectCivUniques = uniqueCache.forCivGetMatchingUniques(
|
||||
observingCiv, UniqueType.AllStatsPercentFromObject, stateForConditionals)
|
||||
for (unique in cachedAllStatPercentFromObjectCivUniques) {
|
||||
val tileFilter = unique.params[1]
|
||||
if (!tile.matchesTerrainFilter(tileFilter, observingCiv)) continue
|
||||
val statPercentage = unique.params[0].toFloat()
|
||||
for (stat in Stat.values())
|
||||
stats[stat] += statPercentage
|
||||
addStats(unique.params[1], stat, unique.params[0].toFloat())
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
return hashMapOf(
|
||||
Pair("Terrain", terrainStats),
|
||||
Pair("Improvement",improvementStats),
|
||||
Pair("Road", roadStats),
|
||||
)
|
||||
}
|
||||
|
||||
fun getTileStartScore(cityCenterMinStats: Stats): Float {
|
||||
@ -249,13 +278,13 @@ class TileStatFunctions(val tile: Tile) {
|
||||
}
|
||||
|
||||
// Also multiplies the stats by the percentage bonus for improvements (but not for tiles)
|
||||
fun getImprovementStats(
|
||||
private fun getExtraImprovementStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
city: City?
|
||||
): Stats {
|
||||
val stats = improvement.cloneStats()
|
||||
val stats = Stats()
|
||||
|
||||
if (tile.hasViewableResource(observingCiv) && tile.tileResource.isImprovedBy(improvement.name)
|
||||
&& tile.tileResource.improvementStats != null
|
||||
)
|
||||
@ -275,96 +304,12 @@ class TileStatFunctions(val tile: Tile) {
|
||||
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
|
||||
}
|
||||
|
||||
if (city != null) stats.add(getImprovementStatsForCity(improvement, city, conditionalState, cityUniqueCache))
|
||||
|
||||
for ((stat, value) in getImprovementPercentageStats(improvement, observingCiv, city, cityUniqueCache)) {
|
||||
stats[stat] *= value.toPercent()
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
private fun getImprovementStatsForCity(
|
||||
improvement: TileImprovement,
|
||||
city: City,
|
||||
conditionalState: StateForConditionals,
|
||||
uniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
|
||||
fun statsFromTiles() {
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)) {
|
||||
if (tile.matchesFilter(unique.params[1])
|
||||
|| unique.params[1] == Constants.freshWater && tile.isAdjacentTo(Constants.freshWater)
|
||||
|| unique.params[1] == "non-fresh water" && !tile.isAdjacentTo(Constants.freshWater)
|
||||
)
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
statsFromTiles()
|
||||
|
||||
fun statsFromObject() {
|
||||
val uniques = uniqueCache.forCityGetMatchingUniques(city,
|
||||
UniqueType.StatsFromObject, conditionalState) +
|
||||
uniqueCache.forCityGetMatchingUniques(city,
|
||||
UniqueType.StatsFromTiles, conditionalState).filter { city.matchesFilter(it.params[2]) }
|
||||
for (unique in uniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
}
|
||||
statsFromObject()
|
||||
return stats
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getImprovementPercentageStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
if (city != null) {
|
||||
val allStatPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
|
||||
city,
|
||||
UniqueType.AllStatsPercentFromObject,
|
||||
conditionalState
|
||||
)
|
||||
for (unique in allStatPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
val statPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
|
||||
city,
|
||||
UniqueType.StatPercentFromObject,
|
||||
conditionalState
|
||||
)
|
||||
|
||||
for (unique in statPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
|
||||
} else {
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)) {
|
||||
if (tile.matchesFilter(unique.params[1])
|
||||
|| unique.params[1] == Constants.freshWater && tile.isAdjacentTo(Constants.freshWater)
|
||||
|| unique.params[1] == "non-fresh water" && !tile.isAdjacentTo(Constants.freshWater)
|
||||
)
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
|
||||
return stats
|
||||
|
@ -134,7 +134,7 @@ For filtering a specific improvement.
|
||||
|
||||
Allowed values are:
|
||||
|
||||
- improvement name (Note that "Road" and "Railroad" _do_ work as improvementFilters, but not as tileFilters at the moment.)
|
||||
- improvement name
|
||||
- `All`
|
||||
- `Great Improvements`, `Great`
|
||||
- `All Road` - for Roads & Railroads
|
||||
|
Loading…
Reference in New Issue
Block a user