Readded stats drilldown

This commit is contained in:
Yair Morgenstern 2022-12-18 21:34:55 +02:00
parent f331ac69e4
commit 6104a25d91

View File

@ -2,6 +2,7 @@ package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Cell
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
@ -10,11 +11,15 @@ import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.city.CityFlags
import com.unciv.logic.city.CityFocus
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.CityStats
import com.unciv.logic.city.StatTreeNode
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.ExpanderTab
@ -24,6 +29,7 @@ import com.unciv.ui.utils.extensions.colorFromRGB
import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.utils.extensions.surroundWithCircle
import com.unciv.ui.utils.extensions.toLabel
import java.text.DecimalFormat
import kotlin.math.ceil
import kotlin.math.round
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
@ -103,6 +109,9 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
if (cityInfo.religion.getNumberOfFollowers().isNotEmpty() && cityInfo.civInfo.gameInfo.isReligionEnabled())
addReligionInfo()
addStatInfo()
addGreatPersonPointInfo(cityInfo)
addBuildingsInfo()
upperTable.pack()
@ -292,4 +301,151 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
lowerTable.add(expanderTab).growX().row()
}
private fun addStatsToHashmap(
statTreeNode: StatTreeNode,
hashMap: HashMap<String, Float>,
stat: Stat,
showDetails: Boolean,
indentation: Int = 0
) {
for ((name, child) in statTreeNode.children) {
val statAmount = child.totalStats[stat]
if (statAmount == 0f) continue
hashMap["- ".repeat(indentation) + name.tr()] = statAmount
if (showDetails) addStatsToHashmap(child, hashMap, stat, showDetails, indentation + 1)
}
}
private fun Table.addStatInfo() {
val cityStats = cityScreen.city.cityStats
val showFaith = cityScreen.city.civInfo.gameInfo.isReligionEnabled()
for (stat in Stat.values()) {
if (stat == Stat.Faith && !showFaith) continue
val statValuesTable = Table()
statValuesTable.touchable = Touchable.enabled
addCategory(stat.name, statValuesTable)
updateStatValuesTable(stat, cityStats, statValuesTable)
}
}
private fun updateStatValuesTable(
stat: Stat,
cityStats: CityStats,
statValuesTable: Table,
showDetails:Boolean = false
) {
statValuesTable.clear()
statValuesTable.defaults().pad(2f)
statValuesTable.onClick {
updateStatValuesTable(
stat,
cityStats,
statValuesTable,
!showDetails
)
onContentResize()
}
val relevantBaseStats = LinkedHashMap<String, Float>()
if (stat != Stat.Happiness)
addStatsToHashmap(cityStats.baseStatTree, relevantBaseStats, stat, showDetails)
else relevantBaseStats.putAll(cityStats.happinessList)
for (key in relevantBaseStats.keys.toList())
if (relevantBaseStats[key] == 0f) relevantBaseStats.remove(key)
if (relevantBaseStats.isEmpty()) return
statValuesTable.add("Base values".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).pad(4f)
.colspan(2).row()
var sumOfAllBaseValues = 0f
for (entry in relevantBaseStats) {
val specificStatValue = entry.value
if (!entry.key.startsWith('-'))
sumOfAllBaseValues += specificStatValue
statValuesTable.add(entry.key.toLabel()).left()
statValuesTable.add(specificStatValue.toOneDecimalLabel()).row()
}
statValuesTable.addSeparator()
statValuesTable.add("Total".toLabel())
statValuesTable.add(sumOfAllBaseValues.toOneDecimalLabel()).row()
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()
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(totalBonusStats[stat].toPercentLabel()).row() // negative bonus
statValuesTable.add("Final".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).colspan(2)
.padTop(20f).row()
var finalTotal = 0f
for (entry in cityStats.finalStatList) {
val specificStatValue = entry.value[stat]
finalTotal += specificStatValue
if (specificStatValue == 0f) continue
statValuesTable.add(entry.key.toLabel())
statValuesTable.add(specificStatValue.toOneDecimalLabel()).row()
}
statValuesTable.addSeparator()
statValuesTable.add("Total".toLabel())
statValuesTable.add(finalTotal.toOneDecimalLabel()).row()
}
statValuesTable.pack()
if (stat != Stat.Happiness) {
val toggleButton = getToggleButton(showDetails)
statValuesTable.addActor(toggleButton)
toggleButton.setPosition(0f, statValuesTable.height, Align.topLeft)
}
statValuesTable.padBottom(4f)
}
private fun getToggleButton(showDetails: Boolean): IconCircleGroup {
val label = (if (showDetails) "-" else "+").toLabel()
label.setAlignment(Align.center)
return label
.surroundWithCircle(25f, color = BaseScreen.skinStrings.skinConfig.baseColor)
.surroundWithCircle(27f, false)
}
private fun Table.addGreatPersonPointInfo(cityInfo: CityInfo) {
val greatPersonPoints = cityInfo.getGreatPersonPointsForNextTurn()
val allGreatPersonNames = greatPersonPoints.asSequence().flatMap { it.value.keys }.distinct()
for (greatPersonName in allGreatPersonNames) {
val expanderName = "[$greatPersonName] points"
val greatPersonTable = Table()
addCategory(expanderName, greatPersonTable)
for ((source, gppCounter) in greatPersonPoints) {
val gppPointsFromSource = gppCounter[greatPersonName]!!
if (gppPointsFromSource == 0) continue
greatPersonTable.add(source.toLabel()).padRight(10f)
greatPersonTable.add(gppPointsFromSource.toLabel()).row()
}
}
}
companion object {
private const val FONT_SIZE_STAT_INFO_HEADER = 22
private fun Float.toPercentLabel() =
"${if (this>0f) "+" else ""}${DecimalFormat("0.#").format(this)}%".toLabel()
private fun Float.toOneDecimalLabel() =
DecimalFormat("0.#").format(this).toLabel()
}
}