mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-11 11:28:03 +07:00
Stat bonus drilldown (#6053)
* Step 1 - converted stat bonus list to tree. No visual difference yet, since the stat bonus list is still generated in the same way. * Step 2 - updateStatPercentBonusList converted to tree form * Step 3 - buildings converted to tree form - now user visible! * Step 4 - Bonuses from uniques are now drilldownable * Removed unneeded todo * Welp, turns out I forgot to apply conditionals
This commit is contained in:
parent
824efcb1a9
commit
84ef8944d0
@ -253,9 +253,7 @@ object SpecificUnitAutomation {
|
||||
val relatedStat = improvement.maxByOrNull { it.value }?.key ?: Stat.Culture
|
||||
|
||||
val citiesByStatBoost = unit.civInfo.cities.sortedByDescending {
|
||||
val stats = Stats()
|
||||
for (bonus in it.cityStats.statPercentBonusList.values) stats.add(bonus)
|
||||
stats[relatedStat]
|
||||
it.cityStats.statPercentBonusTree.totalStats[relatedStat]
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,16 +107,6 @@ class CityConstructions {
|
||||
return maintenanceCost
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bonus (%) [Stats] provided by all built buildings in city
|
||||
*/
|
||||
fun getStatPercentBonuses(): Stats {
|
||||
val stats = Stats()
|
||||
for (building in getBuiltBuildings())
|
||||
stats.add(building.getStatPercentageBonuses(cityInfo))
|
||||
return stats
|
||||
}
|
||||
|
||||
fun getCityProductionTextForCityButton(): String {
|
||||
val currentConstructionSnapshot = currentConstructionFromQueue // See below
|
||||
var result = currentConstructionSnapshot.tr()
|
||||
|
@ -45,12 +45,13 @@ class StatTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
val totalStats: Stats by lazy {
|
||||
val toReturn = Stats()
|
||||
if (innerStats != null) toReturn.add(innerStats!!)
|
||||
for (child in children.values) toReturn.add(child.totalStats)
|
||||
toReturn
|
||||
}
|
||||
val totalStats: Stats
|
||||
get() {
|
||||
val toReturn = Stats()
|
||||
if (innerStats != null) toReturn.add(innerStats!!)
|
||||
for (child in children.values) toReturn.add(child.totalStats)
|
||||
return toReturn
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds and calculates [Stats] for a city.
|
||||
@ -63,10 +64,10 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
|
||||
var baseStatTree = StatTreeNode()
|
||||
|
||||
var baseStatList = LinkedHashMap<String, Stats>()
|
||||
|
||||
var statPercentBonusList = LinkedHashMap<String, Stats>()
|
||||
|
||||
var statPercentBonusTree = StatTreeNode()
|
||||
|
||||
// Computed from baseStatList and statPercentBonusList - this is so the players can see a breakdown
|
||||
var finalStatList = LinkedHashMap<String, Stats>()
|
||||
|
||||
@ -124,6 +125,12 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
return stats
|
||||
}
|
||||
|
||||
private fun addStatPercentBonusesFromBuildings(statPercentBonusTree: StatTreeNode) {
|
||||
for (building in cityInfo.cityConstructions.getBuiltBuildings())
|
||||
statPercentBonusTree.addStats(building.getStatPercentageBonuses(cityInfo), "Buildings", building.name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun getStatsFromCityStates(): Stats {
|
||||
val stats = Stats()
|
||||
@ -265,10 +272,11 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
return stats
|
||||
}
|
||||
|
||||
private fun getStatsPercentBonusesFromUniquesBySource(currentConstruction: IConstruction):StatMap {
|
||||
val sourceToStats = StatMap()
|
||||
fun addUniqueStats(unique: Unique, stat:Stat, amount:Float) {
|
||||
sourceToStats.add(getSourceNameForUnique(unique), Stats().add(stat, amount))
|
||||
private fun getStatsPercentBonusesFromUniquesBySource(currentConstruction: IConstruction): StatTreeNode {
|
||||
val sourceToStats = StatTreeNode()
|
||||
|
||||
fun addUniqueStats(unique:Unique, stat:Stat, amount:Float) {
|
||||
sourceToStats.addStats(Stats().add(stat, amount), getSourceNameForUnique(unique), unique.sourceObjectName ?: "")
|
||||
}
|
||||
|
||||
for (unique in cityInfo.getMatchingUniques(UniqueType.StatPercentBonus)) {
|
||||
@ -472,25 +480,24 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
}
|
||||
|
||||
|
||||
private fun updateStatPercentBonusList(currentConstruction: IConstruction, localBuildingUniques: Sequence<Unique>) {
|
||||
val newStatPercentBonusList = StatMap()
|
||||
private fun updateStatPercentBonusList(currentConstruction: IConstruction) {
|
||||
val newStatsBonusTree = StatTreeNode()
|
||||
|
||||
newStatPercentBonusList["Golden Age"] = getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge())
|
||||
.plus(cityInfo.cityConstructions.getStatPercentBonuses()) // This function is to be deprecated but it'll take a while.
|
||||
newStatPercentBonusList["Railroads"] = getStatPercentBonusesFromRailroad() // Name chosen same as tech, for translation, but theoretically independent
|
||||
newStatPercentBonusList["Puppet City"] = getStatPercentBonusesFromPuppetCity()
|
||||
newStatPercentBonusList["Unit Supply"] = getStatPercentBonusesFromUnitSupply()
|
||||
newStatsBonusTree.addStats(getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge()),"Golden Age")
|
||||
addStatPercentBonusesFromBuildings(newStatsBonusTree)
|
||||
newStatsBonusTree.addStats(getStatPercentBonusesFromRailroad(), "Railroad")
|
||||
newStatsBonusTree.addStats(getStatPercentBonusesFromPuppetCity(), "Puppet City")
|
||||
newStatsBonusTree.addStats(getStatPercentBonusesFromUnitSupply(), "Unit Supply")
|
||||
|
||||
for ((source, stats) in getStatsPercentBonusesFromUniquesBySource(currentConstruction))
|
||||
newStatPercentBonusList.add(source, stats)
|
||||
newStatsBonusTree.add(getStatsPercentBonusesFromUniquesBySource(currentConstruction))
|
||||
|
||||
if (UncivGame.Current.superchargedForDebug) {
|
||||
val stats = Stats()
|
||||
for (stat in Stat.values()) stats[stat] = 10000f
|
||||
newStatPercentBonusList["Supercharged"] = stats
|
||||
newStatsBonusTree.addStats(stats, "Supercharged")
|
||||
}
|
||||
|
||||
statPercentBonusList = newStatPercentBonusList
|
||||
statPercentBonusTree = newStatsBonusTree
|
||||
}
|
||||
|
||||
/** Does not update tile stats - instead, updating tile stats updates this */
|
||||
@ -498,17 +505,12 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
updateTileStats:Boolean = true) {
|
||||
if (updateTileStats) updateTileStats()
|
||||
|
||||
// We calculate this here for concurrency reasons
|
||||
// If something needs this, we pass this through as a parameter
|
||||
val localBuildingUniques = cityInfo.cityConstructions.builtBuildingUniqueMap.getAllUniques()
|
||||
|
||||
|
||||
// We need to compute Tile yields before happiness
|
||||
|
||||
val statsFromBuildings = cityInfo.cityConstructions.getStats() // this is performance heavy, so calculate once
|
||||
updateBaseStatList(statsFromBuildings)
|
||||
updateCityHappiness(statsFromBuildings)
|
||||
updateStatPercentBonusList(currentConstruction, localBuildingUniques)
|
||||
updateStatPercentBonusList(currentConstruction)
|
||||
|
||||
updateFinalStatList(currentConstruction) // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions
|
||||
|
||||
@ -525,8 +527,7 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
for ((key, value) in baseStatTree.children)
|
||||
newFinalStatList[key] = value.totalStats.clone()
|
||||
|
||||
val statPercentBonusesSum = Stats()
|
||||
for (bonus in statPercentBonusList.values) statPercentBonusesSum.add(bonus)
|
||||
val statPercentBonusesSum = statPercentBonusTree.totalStats
|
||||
|
||||
for (entry in newFinalStatList.values)
|
||||
entry.production *= statPercentBonusesSum.production.toPercent()
|
||||
|
@ -168,7 +168,8 @@ class TechManager {
|
||||
var allCitiesScience = 0f
|
||||
civInfo.cities.forEach { it ->
|
||||
val totalBaseScience = it.cityStats.baseStatTree.totalStats.science
|
||||
val totalBonusPercents = it.cityStats.statPercentBonusList.filter { it.key != "Policies" }.values.map { it.science }.sum()
|
||||
val totalBonusPercents = it.cityStats.statPercentBonusTree.children.asSequence()
|
||||
.filter { it.key != "Policies" }.map { it.value.totalStats.science }.sum()
|
||||
allCitiesScience += totalBaseScience * totalBonusPercents.toPercent()
|
||||
}
|
||||
scienceOfLast8Turns[civInfo.gameInfo.turns % 8] = allCitiesScience.toInt()
|
||||
|
@ -19,7 +19,7 @@ interface IHasUniques {
|
||||
* But making this a function is relevant for future "unify Unciv object" plans ;)
|
||||
* */
|
||||
fun getUniqueTarget(): UniqueTarget
|
||||
|
||||
|
||||
fun getMatchingUniques(uniqueTemplate: String, stateForConditionals: StateForConditionals? = null): Sequence<Unique> {
|
||||
val matchingUniques = uniqueMap[uniqueTemplate] ?: return sequenceOf()
|
||||
return matchingUniques.asSequence().filter { it.conditionalsApply(stateForConditionals) }
|
||||
|
@ -149,7 +149,9 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin)
|
||||
private fun addStatsToHashmap(statTreeNode: StatTreeNode, hashMap: HashMap<String, Float>, stat:Stat,
|
||||
showDetails:Boolean, indentation:Int=0) {
|
||||
for ((name, child) in statTreeNode.children) {
|
||||
hashMap["- ".repeat(indentation) + name] = child.totalStats[stat]
|
||||
val statAmount = child.totalStats[stat]
|
||||
if (statAmount == 0f) continue
|
||||
hashMap["- ".repeat(indentation) + name] = statAmount
|
||||
if (showDetails) addStatsToHashmap(child, hashMap, stat, showDetails, indentation + 1)
|
||||
}
|
||||
}
|
||||
@ -207,23 +209,22 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin)
|
||||
statValuesTable.add("Total".toLabel())
|
||||
statValuesTable.add(sumOfAllBaseValues.toOneDecimalLabel()).row()
|
||||
|
||||
val relevantBonuses = cityStats.statPercentBonusList.filter { it.value[stat] != 0f }
|
||||
if (relevantBonuses.isNotEmpty()) {
|
||||
val relevantBonuses = LinkedHashMap<String, Float>()
|
||||
addStatsToHashmap(cityStats.statPercentBonusTree, relevantBonuses, stat, showDetails)
|
||||
|
||||
val totalBonusStats = cityStats.statPercentBonusTree.totalStats
|
||||
if (totalBonusStats[stat] != 0f) {
|
||||
statValuesTable.add("Bonuses".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).colspan(2)
|
||||
.padTop(20f).row()
|
||||
var sumOfBonuses = 0f
|
||||
for (entry in relevantBonuses) {
|
||||
val specificStatValue = entry.value[stat]
|
||||
sumOfBonuses += specificStatValue
|
||||
statValuesTable.add(entry.key.toLabel())
|
||||
statValuesTable.add(specificStatValue.toPercentLabel()).row() // negative bonus
|
||||
for ((source, bonusAmount) in relevantBonuses) {
|
||||
statValuesTable.add(source.toLabel()).left()
|
||||
statValuesTable.add(bonusAmount.toPercentLabel()).row() // negative bonus
|
||||
}
|
||||
statValuesTable.addSeparator()
|
||||
statValuesTable.add("Total".toLabel())
|
||||
statValuesTable.add(sumOfBonuses.toPercentLabel()).row() // negative bonus
|
||||
}
|
||||
statValuesTable.add(totalBonusStats[stat].toPercentLabel()).row() // negative bonus
|
||||
|
||||
|
||||
if (stat != Stat.Happiness) {
|
||||
statValuesTable.add("Final".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).colspan(2)
|
||||
.padTop(20f).row()
|
||||
var finalTotal = 0f
|
||||
|
Loading…
Reference in New Issue
Block a user