All stat-based uniques are parsed EXACTLY once, for performance reasons and to avoid ANRs

This commit is contained in:
Yair Morgenstern 2020-10-26 23:38:29 +02:00
parent a3bed178d0
commit b2c6cc59b7
5 changed files with 20 additions and 16 deletions

View File

@ -73,8 +73,8 @@ class CityConstructions {
stats.add(building.getStats(cityInfo.civInfo))
for (unique in builtBuildingUniqueMap.getAllUniques()) when (unique.placeholderText) {
"[] Per [] Population in this city" -> stats.add(Stats.parse(unique.params[0]).times(cityInfo.population.population / unique.params[1].toFloat()))
"[] once [] is discovered" -> if (cityInfo.civInfo.tech.isResearched(unique.params[1])) stats.add(Stats.parse(unique.params[0]))
"[] Per [] Population in this city" -> stats.add(unique.stats!!.times(cityInfo.population.population / unique.params[1].toFloat()))
"[] once [] is discovered" -> if (cityInfo.civInfo.tech.isResearched(unique.params[1])) stats.add(unique.stats!!)
}
// This is to be deprecated and converted to "[stats] Per [N] Population in this city" - keeping it here to that mods with this can still work for now

View File

@ -50,7 +50,7 @@ class CityStats {
val civInfo = cityInfo.civInfo
stats.gold = civInfo.getCapital().population.population * 0.15f + cityInfo.population.population * 1.1f - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5)
for (unique in civInfo.getMatchingUniques("[] from each Trade Route"))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
if (civInfo.hasUnique("Gold from all trade routes +25%")) stats.gold *= 1.25f // Machu Pichu speciality
}
return stats
@ -215,7 +215,7 @@ class CityStats {
if (cityInfo.getCenterTile().militaryUnit != null)
for (unique in civInfo.getMatchingUniques("[] in all cities with a garrison"))
happinessFromPolicies += Stats.parse(unique.params[0]).happiness
happinessFromPolicies += unique.stats!!.happiness
newHappinessList["Policies"] = happinessFromPolicies
@ -247,7 +247,7 @@ class CityStats {
else stats.add(stat, 2f) // science and gold specialists
for(unique in cityInfo.civInfo.getMatchingUniques("[] from every specialist"))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
return stats
}
@ -257,7 +257,7 @@ class CityStats {
if (specialist == null) return Stats()
val stats = specialist.clone()
for (unique in cityInfo.civInfo.getMatchingUniques("[] from every specialist"))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
return stats
}
@ -275,10 +275,10 @@ class CityStats {
if ((unique.placeholderText == "[] in capital" && cityInfo.isCapital())
|| unique.placeholderText == "[] in all cities"
|| (unique.placeholderText == "[] in all cities with a garrison" && cityInfo.getCenterTile().militaryUnit != null))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
if (unique.placeholderText == "[] per [] population in all cities") {
val amountOfEffects = (cityInfo.population.population / unique.params[1].toInt()).toFloat()
stats.add(Stats.parse(unique.params[0]).times(amountOfEffects))
stats.add(unique.stats!!.times(amountOfEffects))
}
if (unique.text == "+1 gold and -1 unhappiness for every 2 citizens in capital" && cityInfo.isCapital()) {
stats.gold += (cityInfo.population.population / 2).toFloat()

View File

@ -194,7 +194,7 @@ open class TileInfo {
|| (resource == tileType && hasViewableResource(observingCiv))
|| (tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic)
|| (tileType == "Water resource" && isWater && hasViewableResource(observingCiv))
) stats.add(Stats.parse(unique.params[0]))
) stats.add(unique.stats!!)
}
}
@ -247,7 +247,7 @@ open class TileInfo {
for (unique in improvement.uniqueObjects)
if (unique.placeholderText == "[] once [] is discovered" && observingCiv.tech.isResearched(unique.params[1]))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
if (city != null) {
val cityWideUniques = city.cityConstructions.builtBuildingUniqueMap.getUniques("[] from [] tiles in this city")
@ -262,7 +262,7 @@ open class TileInfo {
|| (unique.params[1] == "fresh water" && isAdjacentToFreshwater)
|| (unique.params[1] == "non-fresh water" && !isAdjacentToFreshwater)
)
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
}
}
@ -278,7 +278,7 @@ open class TileInfo {
|| it.matchesUniqueFilter(adjacent)
|| it.roadStatus.name == adjacent
}
stats.add(Stats.parse(unique.params[0]).times(numberOfBonuses.toFloat()))
stats.add(unique.stats!!.times(numberOfBonuses.toFloat()))
}
return stats

View File

@ -143,21 +143,21 @@ class Building : NamedStats(), IConstruction {
for (unique in civInfo.getMatchingUniques("[] from every []")) {
if (unique.params[1] != baseBuildingName) continue
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
}
for (unique in uniqueObjects)
if (unique.placeholderText == "[] with []" && civInfo.hasResource(unique.params[1]) && Stats.isStats(unique.params[0]))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
if (!isWonder)
for (unique in civInfo.getMatchingUniques("[] from all [] buildings")) {
if (isStatRelated(Stat.valueOf(unique.params[1])))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
}
else
for (unique in civInfo.getMatchingUniques("[] from every Wonder"))
stats.add(Stats.parse(unique.params[0]))
stats.add(unique.stats!!)
}
return stats

View File

@ -2,12 +2,16 @@ package com.unciv.models.ruleset
import com.unciv.Constants
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.stats.Stats
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
class Unique(val text:String){
val placeholderText = text.getPlaceholderText()
val params = text.getPlaceholderParameters()
/** This is so the heavy regex-based parsing is only activated once per unique, instead of every time it's called
* - for instance, in the city screen, we call every tile unique for every tile, which can lead to ANRs */
val stats = params.firstOrNull { Stats.isStats(it) }?.let { Stats.parse(it) }
}
class UniqueMap:HashMap<String, ArrayList<Unique>>() {