Resolved #470 - can now click on a building in the city info table to display its effect

Organized city info table
This commit is contained in:
Yair Morgenstern
2019-03-07 23:05:48 +02:00
parent 6f46750c15
commit f15490d0ac
3 changed files with 92 additions and 67 deletions

View File

@ -74,6 +74,10 @@ open class Stats() {
Stat.Science to science)
}
fun get(stat:Stat):Float{
return this.toHashMap()[stat]!!
}
private fun setStats(hashMap:HashMap<Stat, Float>){
culture=hashMap[Stat.Culture]!!
gold=hashMap[Stat.Gold]!!

View File

@ -1,12 +1,15 @@
package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.GreatPersonManager
import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.tr
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.*
@ -15,15 +18,17 @@ import java.util.*
class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) {
val pad = 5f
init {
defaults().pad(10f)
defaults().pad(pad)
width = cityScreen.stage.width/4
}
internal fun update() {
clear()
val cityInfo = cityScreen.city
addBuildingInfo(cityInfo)
addBuildingsInfo(cityInfo)
addStatInfo()
@ -32,8 +37,36 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
pack()
}
private fun addTitle(str:String) {
val titleTable = Table().background(ImageGetter.getBackground(ImageGetter.getBlue()))
titleTable.add(str.toLabel().setFontSize(22))
add(titleTable).width(cityScreen.stage.width/4 - 2*pad).row()
}
private fun addBuildingInfo(cityInfo: CityInfo) {
fun addBuildingInfo(building: Building){
val wonderNameAndIconTable = Table()
wonderNameAndIconTable.touchable = Touchable.enabled
wonderNameAndIconTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
wonderNameAndIconTable.add(building.name.toLabel()).pad(5f)
add(wonderNameAndIconTable).pad(5f).fillX().row()
val wonderDetailsTable = Table()
add(wonderDetailsTable).pad(5f).align(Align.left).row()
wonderNameAndIconTable.onClick {
if(wonderDetailsTable.hasChildren())
wonderDetailsTable.clear()
else{
val detailsString = building.getDescription(true,
cityScreen.city.civInfo.policies.adoptedPolicies)
wonderDetailsTable.add(detailsString.toLabel().apply { setWrap(true)})
.width(cityScreen.stage.width/4 - 2*pad ) // when you set wrap, then you need to manually set the size of the label
wonderDetailsTable.addSeparator()
}
}
}
private fun addBuildingsInfo(cityInfo: CityInfo) {
val wonders = mutableListOf<Building>()
val specialistBuildings = mutableListOf<Building>()
val otherBuildings = mutableListOf<Building>()
@ -47,40 +80,32 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
}
if (!wonders.isEmpty()) {
val wondersExpander = ExpanderTab("Wonders".tr(), skin)
for (building in wonders) {
wondersExpander.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
wondersExpander.innerTable.add(building.name.toLabel()).pad(5f).align(Align.left).row()
}
add(wondersExpander).row()
addTitle("Wonders")
for (building in wonders) addBuildingInfo(building)
}
if (!specialistBuildings.isEmpty()) {
val specialistBuildingsExpander = ExpanderTab("Specialist Buildings".tr(), skin)
addTitle("Specialist Buildings")
for (building in specialistBuildings) {
specialistBuildingsExpander.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
specialistBuildingsExpander.innerTable.add(building.name.toLabel()).pad(5f)
addBuildingInfo(building)
val specialistIcons = Table()
specialistIcons.row().size(20f).pad(5f)
for (stat in building.specialistSlots!!.toHashMap())
for (i in 0 until stat.value.toInt())
specialistIcons.add(getSpecialistIcon(stat.key)).size(20f)
specialistBuildingsExpander.innerTable.add(specialistIcons).row()
add(specialistIcons).pad(0f).row()
}
add(specialistBuildingsExpander).row()
// specialist allocation
addSpecialistAllocation(skin, cityInfo)
}
if (!otherBuildings.isEmpty()) {
val buildingsExpanderTab = ExpanderTab("Buildings".tr(), skin)
for (building in otherBuildings) {
buildingsExpanderTab.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
buildingsExpanderTab.innerTable.add(building.name.toLabel()).pad(5f).row()
}
add(buildingsExpanderTab).row()
addTitle("Buildings")
for (building in wonders) addBuildingInfo(building)
}
}
@ -90,7 +115,6 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
for(stats in unifiedStatList.values) stats.happiness=0f
// add happiness to stat list
for(entry in cityStats.getCityHappiness().filter { it.value!=0f }){
if(!unifiedStatList.containsKey(entry.key))
@ -99,41 +123,40 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
}
for(stat in Stat.values()){
val expander = ExpanderTab(stat.name.tr(),skin)
expander.innerTable.defaults().pad(2f)
if(unifiedStatList.all { it.value.get(stat)==0f }) continue
addTitle(stat.name)
val statValuesTable = Table().apply { defaults().pad(2f) }
for(entry in unifiedStatList) {
val specificStatValue = entry.value.toHashMap()[stat]!!
val specificStatValue = entry.value.get(stat)
if(specificStatValue==0f) continue
expander.innerTable.add(entry.key.toLabel())
expander.innerTable.add(DecimalFormat("0.#").format(specificStatValue).toLabel()).row()
statValuesTable.add(entry.key.toLabel())
statValuesTable.add(DecimalFormat("0.#").format(specificStatValue).toLabel()).row()
}
for(entry in cityStats.statPercentBonusList){
val specificStatValue = entry.value.toHashMap()[stat]!!
if(specificStatValue==0f) continue
expander.innerTable.add(entry.key.toLabel())
statValuesTable.add(entry.key.toLabel())
val decimal = DecimalFormat("0.#").format(specificStatValue)
expander.innerTable.add("+$decimal%".toLabel()).row()
statValuesTable.add("+$decimal%".toLabel()).row()
}
if(stat==Stat.Gold){
val maintenance = cityStats.cityInfo.cityConstructions.getMaintenanceCosts()
if(maintenance>0){
expander.innerTable.add("Maintenance".toLabel())
expander.innerTable.add("-$maintenance".toLabel())
statValuesTable.add("Maintenance".toLabel())
statValuesTable.add("-$maintenance".toLabel())
}
}
if(stat==Stat.Food){
expander.innerTable.add("Food eaten".toLabel())
expander.innerTable.add(DecimalFormat("0.#").format(cityStats.foodEaten).toLabel()).row()
statValuesTable.add("Food eaten".toLabel())
statValuesTable.add(DecimalFormat("0.#").format(cityStats.foodEaten).toLabel()).row()
val growthBonus = cityStats.getGrowthBonusFromPolicies()
if(growthBonus>0){
expander.innerTable.add("Growth bonus".toLabel())
expander.innerTable.add((growthBonus*100).toInt().toString().toLabel())
statValuesTable.add("Growth bonus".toLabel())
statValuesTable.add((growthBonus*100).toInt().toString().toLabel())
}
}
if(expander.innerTable.hasChildren())
add(expander).row()
add(statValuesTable).row()
}
}
@ -142,76 +165,74 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
val statToGreatPerson = GreatPersonManager().statToGreatPersonMapping
for (stat in Stat.values()) {
if (!statToGreatPerson.containsKey(stat)) continue
if(greatPersonPoints.all { it.value.get(stat)==0f }) continue
val expanderName = "[" + statToGreatPerson[stat]!! + "] points"
val expanderTab = ExpanderTab(expanderName.tr(), skin)
expanderTab.innerTable.defaults().pad(3f)
addTitle(expanderName)
val greatPersonTable = Table()
for (entry in greatPersonPoints) {
val value = entry.value.toHashMap()[stat]!!
if (value == 0f) continue
expanderTab.innerTable.add(entry.key.toLabel())
expanderTab.innerTable.add(DecimalFormat("0.#").format(value).toLabel()).row()
greatPersonTable.add(entry.key.toLabel()).padRight(10f)
greatPersonTable.add(DecimalFormat("0.#").format(value).toLabel()).row()
}
if (expanderTab.innerTable.hasChildren())
add(expanderTab).row()
add(greatPersonTable).row()
}
}
private fun addSpecialistAllocation(skin: Skin, cityInfo: CityInfo) {
val specialistAllocationExpander = ExpanderTab("Specialist Allocation".tr(), skin)
specialistAllocationExpander.innerTable.defaults().pad(5f)
addTitle("Specialist Allocation")
val currentSpecialists = cityInfo.population.specialists.toHashMap()
val maximumSpecialists = cityInfo.population.getMaxSpecialists()
for (statToMaximumSpecialist in maximumSpecialists.toHashMap()) {
val specialistPickerTable = Table()
if (statToMaximumSpecialist.value == 0f) continue
val stat = statToMaximumSpecialist.key
// these two are conflictingly named compared to above...
val assignedSpecialists = currentSpecialists[statToMaximumSpecialist.key]!!.toInt()
val assignedSpecialists = currentSpecialists[stat]!!.toInt()
val maxSpecialists = statToMaximumSpecialist.value.toInt()
if (assignedSpecialists > 0) {
val unassignButton = TextButton("-", skin)
unassignButton.label.setFontSize(24)
unassignButton.onClick {
cityInfo.population.specialists.add(statToMaximumSpecialist.key, -1f)
cityInfo.population.specialists.add(stat, -1f)
cityInfo.cityStats.update()
cityScreen.update()
}
specialistAllocationExpander.innerTable.add(unassignButton)
} else specialistAllocationExpander.innerTable.add()
specialistPickerTable.add(unassignButton)
} else specialistPickerTable.add()
val specialistTable = Table()
val specialistIconTable = Table()
for (i in 1..maxSpecialists) {
val icon = getSpecialistIcon(stat, i <= assignedSpecialists)
specialistTable.add(icon).size(30f)
specialistIconTable.add(icon).size(30f)
}
specialistAllocationExpander.innerTable.add(specialistTable)
specialistPickerTable.add(specialistIconTable)
if (assignedSpecialists < maxSpecialists) {
val assignButton = TextButton("+", skin)
assignButton.label.setFontSize(24)
assignButton.onClick {
cityInfo.population.specialists.add(statToMaximumSpecialist.key, +1f)
cityInfo.population.specialists.add(statToMaximumSpecialist.key, 1f)
cityInfo.cityStats.update()
cityScreen.update()
}
if (cityInfo.population.getFreePopulation() == 0) assignButton.disable()
specialistAllocationExpander.innerTable.add(assignButton)
} else specialistAllocationExpander.innerTable.add()
specialistAllocationExpander.innerTable.row()
if (cityInfo.population.getFreePopulation() == 0)
assignButton.disable()
specialistPickerTable.add(assignButton)
} else specialistPickerTable.add()
add(specialistPickerTable).row()
val specialistStatTable = Table().apply { defaults().pad(5f) }
val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(stat, cityInfo.civInfo.policies.adoptedPolicies).toHashMap()
for (entry in specialistStats) {
if (entry.value == 0f) continue
specialistStatTable.add(ImageGetter.getStatIcon(entry.key.toString())).size(20f)
specialistStatTable.add(Label(entry.value.toInt().toString(), skin)).padRight(10f)
specialistStatTable.add(entry.value.toInt().toString().toLabel()).padRight(10f)
}
specialistAllocationExpander.innerTable.add()
specialistAllocationExpander.innerTable.add(specialistStatTable).row()
add(specialistStatTable).row()
}
add(specialistAllocationExpander).row()
}
private fun getSpecialistIcon(stat: Stat, isFilled: Boolean =true): Image {

View File

@ -27,7 +27,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
private var razeCityButtonHolder = Table() // sits on the top
/** Displays buildings, specialists and stats drilldown - sits on the top left of the city screen */
/** Displays buildings, specialists and stats drilldown - sits on the top right of the city screen */
private var cityInfoTable = CityInfoTable(this)
/** Displays tile info, sits on the bottom right */
@ -53,7 +53,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
cityInfoTable.update()
val buildingsScroll = ScrollPane(cityInfoTable)
buildingsTableContainer.add(buildingsScroll)
.height(stage.height / 2)
.size(stage.width/4,stage.height / 2)
buildingsTableContainer = buildingsTableContainer.addBorder(2f, Color.WHITE)
buildingsTableContainer.setPosition(stage.width - buildingsTableContainer.width-5,