diff --git a/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt index 26eccf1dad..039f0d2713 100644 --- a/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt @@ -61,7 +61,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { private var preferredBuyStat = Stat.Gold // Used for keyboard buy private val upperTable = Table(BaseScreen.skin) - private val showCityInfoTableButton = "Show stats drilldown".toTextButton() private val constructionsQueueScrollPane: ScrollPane private val constructionsQueueTable = Table() private val buyButtonsTable = Table() @@ -84,11 +83,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { } init { - showCityInfoTableButton.onClick { - cityScreen.showConstructionsTable = false - cityScreen.update() - } - constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE)) constructionsQueueScrollPane.setOverscroll(false, false) constructionsQueueTable.background = BaseScreen.skinStrings.getUiBackground( @@ -97,7 +91,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { ) upperTable.defaults().left().top() - upperTable.add(showCityInfoTableButton).padLeft(pad).padBottom(pad).row() upperTable.add(constructionsQueueScrollPane) .maxHeight(stageHeight / 3 - 10f) .padBottom(pad).row() diff --git a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt b/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt deleted file mode 100644 index 99f73acb4e..0000000000 --- a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt +++ /dev/null @@ -1,357 +0,0 @@ -package com.unciv.ui.cityscreen - -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.scenes.scene2d.Group -import com.badlogic.gdx.scenes.scene2d.Touchable -import com.badlogic.gdx.scenes.scene2d.ui.Cell -import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.utils.Align -import com.unciv.Constants -import com.unciv.UncivGame -import com.unciv.logic.city.CityInfo -import com.unciv.logic.city.CityStats -import com.unciv.logic.city.StatTreeNode -import com.unciv.models.UncivSound -import com.unciv.models.ruleset.Building -import com.unciv.models.stats.Stat -import com.unciv.models.translations.tr -import com.unciv.ui.images.IconCircleGroup -import com.unciv.ui.images.ImageGetter -import com.unciv.ui.popup.ConfirmPopup -import com.unciv.ui.popup.closeAllPopups -import com.unciv.ui.utils.BaseScreen -import com.unciv.ui.utils.ExpanderTab -import com.unciv.ui.utils.extensions.addBorder -import com.unciv.ui.utils.extensions.addSeparator -import com.unciv.ui.utils.extensions.darken -import com.unciv.ui.utils.extensions.disable -import com.unciv.ui.utils.extensions.onClick -import com.unciv.ui.utils.extensions.surroundWithCircle -import com.unciv.ui.utils.extensions.toLabel -import com.unciv.ui.utils.extensions.toTextButton -import java.text.DecimalFormat -import com.unciv.ui.utils.AutoScrollPane as ScrollPane - -class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin) { - private val pad = 10f - - private val showConstructionsTableButton = "Show construction queue".toTextButton() - private val scrollPane: ScrollPane - private val innerTable = Table(skin) - - private val allExpanders = mutableListOf() - private val hideShowAllCell: Cell - private var hideShowAllShouldClose = false - - init { - align(Align.topLeft) - - showConstructionsTableButton.onClick { - cityScreen.showConstructionsTable = true - cityScreen.update() - } - - innerTable.width = cityScreen.stage.width / 4 - innerTable.background = BaseScreen.skinStrings.getUiBackground( - "CityScreen/CityInfoTable", - tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) - ) - scrollPane = ScrollPane(innerTable.addBorder(2f, Color.WHITE)) - scrollPane.setOverscroll(false, false) - - val hideShowAllButton = Group() - add(showConstructionsTableButton).left().padLeft(pad).padBottom(pad) - hideShowAllCell = add(hideShowAllButton).size(30f) // size as the cell won't be resized when the actor is replaced - hideShowAllCell.left().padLeft(pad).padBottom(pad).expandX().row() - add(scrollPane).colspan(2).left().row() - } - - internal fun update() { - val cityInfo = cityScreen.city - - allExpanders.clear() - innerTable.clear() - - innerTable.apply { - addBuildingsInfo(cityInfo) - addStatInfo() - addGreatPersonPointInfo(cityInfo) - } - - updateHideShowAllButton() - - getCell(scrollPane).maxHeight(stage.height - showConstructionsTableButton.height - pad - 10f) - onContentResize() - } - - private fun updateHideShowAllButton() { - val anyExpanderOpen = allExpanders.map { it.isOpen }.maxOrNull() ?: false - if (anyExpanderOpen == hideShowAllShouldClose) return - hideShowAllShouldClose = anyExpanderOpen - val hideShowAllButton = getToggleButton(hideShowAllShouldClose) - hideShowAllButton.touchable = Touchable.enabled - hideShowAllButton.onClick { - for (expander in allExpanders) { - if (expander.isOpen == hideShowAllShouldClose) expander.toggle() - } - updateHideShowAllButton() - } - hideShowAllCell.setActor(hideShowAllButton) - } - - private fun onContentResize() { - pack() - setPosition(CityScreen.posFromEdge, stage.height - CityScreen.posFromEdge, Align.topLeft) - } - - private fun Table.addCategory(category: String, showHideTable: Table) { - val categoryWidth = cityScreen.stage.width / 4 - val expander = ExpanderTab(category, persistenceID = "CityInfo.$category" - , onChange = { - onContentResize() - updateHideShowAllButton() - } - ) { - it.add(showHideTable).minWidth(categoryWidth) - } - addSeparator() - add(expander).minWidth(categoryWidth).expandX().fillX().row() - allExpanders += expander - } - - private fun addBuildingInfo(building: Building, destinationTable: Table) { - val icon = ImageGetter.getPortraitImage(building.name, 30f) - val isFree = building.name in cityScreen.city.civInfo.civConstructions.getFreeBuildings(cityScreen.city.id) - val displayName = if (isFree) "{${building.name}} ({Free})" else building.name - val buildingNameAndIconTable = ExpanderTab( - displayName, Constants.defaultFontSize, icon, - startsOutOpened = false, defaultPad = 5f, - onChange = { onContentResize() } - ) { - val detailsString = building.getDescription(cityScreen.city, false) - it.add(detailsString.toLabel().apply { wrap = true }) - .width(cityScreen.stage.width / 4 - 2 * pad).row() // when you set wrap, then you need to manually set the size of the label - if (building.isSellable() && !isFree) { - val sellAmount = cityScreen.city.getGoldForSellingBuilding(building.name) - val sellText = "Sell for [$sellAmount] gold" - val sellBuildingButton = sellText.toTextButton() - it.add(sellBuildingButton).pad(5f).row() - - sellBuildingButton.onClick(UncivSound.Coin) { - sellBuildingButton.disable() - cityScreen.closeAllPopups() - - ConfirmPopup( - cityScreen, - "Are you sure you want to sell this [${building.name}]?", - sellText, - restoreDefault = { - cityScreen.update() - } - ) { - cityScreen.city.sellBuilding(building.name) - cityScreen.update() - }.open() - } - if (cityScreen.city.hasSoldBuildingThisTurn && !cityScreen.city.civInfo.gameInfo.gameParameters.godMode - || cityScreen.city.isPuppet - || !UncivGame.Current.worldScreen!!.isPlayersTurn || !cityScreen.canChangeState) - sellBuildingButton.disable() - } - it.addSeparator() - } - destinationTable.add(buildingNameAndIconTable).pad(5f).fillX().row() - } - - private fun Table.addBuildingsInfo(cityInfo: CityInfo) { - val wonders = mutableListOf() - val specialistBuildings = mutableListOf() - val otherBuildings = mutableListOf() - - for (building in cityInfo.cityConstructions.getBuiltBuildings()) { - when { - building.isAnyWonder() -> wonders.add(building) - !building.newSpecialists().isEmpty() -> specialistBuildings.add(building) - else -> otherBuildings.add(building) - } - } - - if (wonders.isNotEmpty()) { - val wondersTable = Table() - addCategory("Wonders", wondersTable) - for (building in wonders) addBuildingInfo(building, wondersTable) - } - - if (specialistBuildings.isNotEmpty()) { - val specialistBuildingsTable = Table() - addCategory("Specialist Buildings", specialistBuildingsTable) - - for (building in specialistBuildings) { - addBuildingInfo(building, specialistBuildingsTable) - val specialistIcons = Table() - specialistIcons.row().size(20f).pad(5f) - for ((specialistName, amount) in building.newSpecialists()) { - val specialist = cityInfo.getRuleset().specialists[specialistName] - ?: continue // probably a mod that doesn't have the specialist defined yet - for (i in 0 until amount) - specialistIcons.add(ImageGetter.getSpecialistIcon(specialist.colorObject)).size(20f) - } - - specialistBuildingsTable.add(specialistIcons).pad(0f).row() - } - } - - if (otherBuildings.isNotEmpty()) { - val regularBuildingsTable = Table() - addCategory("Buildings", regularBuildingsTable) - for (building in otherBuildings) addBuildingInfo(building, regularBuildingsTable) - } - } - - private fun addStatsToHashmap( - statTreeNode: StatTreeNode, - hashMap: HashMap, - 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() - - 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() - 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() - } - -} diff --git a/core/src/com/unciv/ui/cityscreen/CityScreen.kt b/core/src/com/unciv/ui/cityscreen/CityScreen.kt index 284a16948c..6c9dd05bc4 100644 --- a/core/src/com/unciv/ui/cityscreen/CityScreen.kt +++ b/core/src/com/unciv/ui/cityscreen/CityScreen.kt @@ -50,9 +50,6 @@ class CityScreen( /** Toggles or adds/removes all state changing buttons */ val canChangeState = UncivGame.Current.worldScreen!!.canChangeState - /** Toggle between Constructions and cityInfo (buildings, specialists etc. */ - var showConstructionsTable = true - // Clockwise from the top-left /** Displays current production, production queue and available productions list @@ -61,9 +58,6 @@ class CityScreen( */ private var constructionsTable = CityConstructionsTable(this) - /** Displays stats, buildings, specialists and stats drilldown - sits on TOP LEFT, can be toggled to */ - private var cityInfoTable = CityInfoTable(this) - /** Displays raze city button - sits on TOP CENTER */ private var razeCityButtonHolder = Table() @@ -129,7 +123,6 @@ class CityScreen( //stage.setDebugTableUnderMouse(true) stage.addActor(cityStatsTable) constructionsTable.addActorsToStage() - stage.addActor(cityInfoTable) stage.addActor(selectedConstructionTable) stage.addActor(tileTable) stage.addActor(cityPickerTable) // add late so it's top in Z-order and doesn't get covered in cramped portrait @@ -144,17 +137,8 @@ class CityScreen( // Recalculate Stats city.cityStats.update() - // Left side, top and bottom: Construction queue / details - if (showConstructionsTable) { - constructionsTable.isVisible = true - cityInfoTable.isVisible = false - constructionsTable.update(selectedConstruction) - } else { - constructionsTable.isVisible = false - cityInfoTable.isVisible = true - cityInfoTable.update() - // CityInfoTable sets its relative position itself - } + constructionsTable.isVisible = true + constructionsTable.update(selectedConstruction) // Bottom right: Tile or selected construction info tileTable.update(selectedTile) @@ -171,8 +155,7 @@ class CityScreen( } val leftMargin = when { !isPortrait() -> 0f - showConstructionsTable -> constructionsTable.getLowerWidth() - else -> cityInfoTable.packIfNeeded().width + else -> constructionsTable.getLowerWidth() } // Bottom center: Name, paging, exit city button @@ -434,7 +417,6 @@ class CityScreen( val indexOfCity = civInfo.cities.indexOf(city) val indexOfNextCity = (indexOfCity + delta + numCities) % numCities val newCityScreen = CityScreen(civInfo.cities[indexOfNextCity]) - newCityScreen.showConstructionsTable = showConstructionsTable // stay on stats drilldown between cities newCityScreen.update() game.replaceCurrentScreen(newCityScreen) } diff --git a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt index 8a5ae1ac02..1347183ee6 100644 --- a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt @@ -6,15 +6,18 @@ import com.badlogic.gdx.scenes.scene2d.ui.Cell import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align +import com.unciv.Constants import com.unciv.UncivGame import com.unciv.logic.city.CityFlags import com.unciv.logic.city.CityFocus +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.ImageGetter import com.unciv.ui.utils.BaseScreen +import com.unciv.ui.utils.ExpanderTab import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.extensions.addSeparator import com.unciv.ui.utils.extensions.colorFromRGB @@ -100,6 +103,8 @@ class CityStatsTable(val cityScreen: CityScreen): Table() { if (cityInfo.religion.getNumberOfFollowers().isNotEmpty() && cityInfo.civInfo.gameInfo.isReligionEnabled()) addReligionInfo() + addBuildingsInfo() + upperTable.pack() lowerTable.pack() lowerPane.layout() @@ -110,6 +115,15 @@ class CityStatsTable(val cityScreen: CityScreen): Table() { pack() // update self last } + private fun onContentResize() { + pack() + setPosition( + stage.width - CityScreen.posFromEdge, + stage.height - CityScreen.posFromEdge, + Align.topRight + ) + } + private fun addText() { val unassignedPopString = "{Unassigned population}: ".tr() + cityInfo.population.getFreePopulation().toString() + "/" + cityInfo.population.population @@ -171,36 +185,111 @@ class CityStatsTable(val cityScreen: CityScreen): Table() { } private fun addCitizenManagement() { - val expanderTab = CitizenManagementTable(cityScreen).asExpander { - pack() - setPosition( - stage.width - CityScreen.posFromEdge, - stage.height - CityScreen.posFromEdge, - Align.topRight - ) - } + val expanderTab = CitizenManagementTable(cityScreen).asExpander { onContentResize() } lowerTable.add(expanderTab).growX().row() } private fun addSpecialistInfo() { - val expanderTab = SpecialistAllocationTable(cityScreen).asExpander { - pack() - setPosition( - stage.width - CityScreen.posFromEdge, - stage.height - CityScreen.posFromEdge, - Align.topRight - ) - } + val expanderTab = SpecialistAllocationTable(cityScreen).asExpander { onContentResize() } lowerTable.add(expanderTab).growX().row() } private fun addReligionInfo() { - val expanderTab = CityReligionInfoTable(cityInfo.religion).asExpander { - pack() - // We have to re-anchor as our position in the city screen, otherwise it expands upwards. - // ToDo: This probably should be refactored so its placed somewhere else in due time - setPosition(stage.width - CityScreen.posFromEdge, stage.height - CityScreen.posFromEdge, Align.topRight) + val expanderTab = CityReligionInfoTable(cityInfo.religion).asExpander { onContentResize() } + lowerTable.add(expanderTab).growX().row() + } + + private fun addBuildingsInfo() { + val wonders = mutableListOf() + val specialistBuildings = mutableListOf() + val otherBuildings = mutableListOf() + + for (building in cityInfo.cityConstructions.getBuiltBuildings()) { + when { + building.isAnyWonder() -> wonders.add(building) + !building.newSpecialists().isEmpty() -> specialistBuildings.add(building) + else -> otherBuildings.add(building) + } + } + + if (specialistBuildings.isNotEmpty()) { + val specialistBuildingsTable = Table() + addCategory("Specialist Buildings", specialistBuildingsTable) + for (building in specialistBuildings) addBuildingButton(building, specialistBuildingsTable) + } + + if (wonders.isNotEmpty()) { + val wondersTable = Table() + addCategory("Wonders", wondersTable) + for (building in wonders) addBuildingButton(building, wondersTable) + } + + if (otherBuildings.isNotEmpty()) { + val regularBuildingsTable = Table() + addCategory("Buildings", regularBuildingsTable) + for (building in otherBuildings) addBuildingButton(building, regularBuildingsTable) + } + } + + private fun addBuildingButton(building: Building, destinationTable: Table) { + + val button = Table() + + val info = Table() + val statsAndSpecialists = Table() + + val icon = ImageGetter.getPortraitImage(building.name, 50f) + val isFree = building.name in cityScreen.city.civInfo.civConstructions.getFreeBuildings(cityScreen.city.id) + val displayName = if (isFree) "{${building.name}} ({Free})" else building.name + + info.add(displayName.toLabel(fontSize = Constants.defaultFontSize)).padBottom(5f).right().row() + + val stats = building.getStats(cityInfo).joinToString(separator = " ") { + "" + it.value.toInt() + it.key.character + } + statsAndSpecialists.add(stats.toLabel(fontSize = Constants.defaultFontSize)).right() + + val assignedSpec = cityInfo.population.getNewSpecialists().clone() + + val specialistIcons = Table() + for ((specialistName, amount) in building.newSpecialists()) { + val specialist = cityInfo.getRuleset().specialists[specialistName] + ?: continue // probably a mod that doesn't have the specialist defined yet + for (i in 0 until amount) { + if (assignedSpec[specialistName]!! > 0) { + specialistIcons.add(ImageGetter.getSpecialistIcon(specialist.colorObject)) + .size(20f) + assignedSpec.add(specialistName, -1) + } else { + specialistIcons.add(ImageGetter.getSpecialistIcon(Color.GRAY)).size(20f) + } + } + } + statsAndSpecialists.add(specialistIcons).right() + + info.add(statsAndSpecialists).right() + + button.add(info).right().top().padRight(10f).padTop(5f) + button.add(icon).right() + + button.onClick { + cityScreen.selectConstruction(building) + cityScreen.update() + } + + destinationTable.add(button).pad(1f).expandX().right().row() + } + + private fun addCategory(category: String, showHideTable: Table) { + val expanderTab = ExpanderTab( + title = category, + fontSize = Constants.defaultFontSize, + persistenceID = "CityInfo.$category", + onChange = { onContentResize() } + ) { + it.add(showHideTable).fillX().right() } lowerTable.add(expanderTab).growX().row() } + } diff --git a/core/src/com/unciv/ui/cityscreen/CityTileGroup.kt b/core/src/com/unciv/ui/cityscreen/CityTileGroup.kt index db44db7e6b..3f45805915 100644 --- a/core/src/com/unciv/ui/cityscreen/CityTileGroup.kt +++ b/core/src/com/unciv/ui/cityscreen/CityTileGroup.kt @@ -46,11 +46,11 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin when { tileInfo.getOwner() != city.civInfo -> { // outside of civ boundary dim(0.3f) - yieldGroup.isVisible = false + yieldGroup.isVisible = true } tileInfo !in city.tilesInRange -> { // within city but not close enough to be workable - yieldGroup.isVisible = false + yieldGroup.isVisible = true dim(0.5f) } @@ -74,7 +74,6 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin unitLayerGroup.isVisible = false terrainFeatureLayerGroup.color.a = 0.5f icons.improvementIcon?.setColor(1f, 1f, 1f, 0.5f) - resourceImage?.setColor(1f, 1f, 1f, 0.5f) updatePopulationIcon() updateYieldGroup() } @@ -94,7 +93,7 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin private fun updatePopulationIcon() { val populationIcon = icons.populationIcon if (populationIcon != null) { - populationIcon.setSize(30f, 30f) + populationIcon.setSize(25f, 25f) populationIcon.setPosition(width / 2 - populationIcon.width / 2, height * 0.85f - populationIcon.height / 2) diff --git a/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt b/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt index f55d93b1ea..36bd16efb3 100644 --- a/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt +++ b/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt @@ -8,16 +8,21 @@ import com.unciv.UncivGame import com.unciv.logic.city.IConstruction import com.unciv.logic.city.PerpetualConstruction import com.unciv.logic.city.PerpetualStatConversion +import com.unciv.models.UncivSound import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.IRulesetObject import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.translations.tr import com.unciv.ui.civilopedia.CivilopediaScreen import com.unciv.ui.images.ImageGetter +import com.unciv.ui.popup.ConfirmPopup +import com.unciv.ui.popup.closeAllPopups import com.unciv.ui.utils.BaseScreen +import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.extensions.darken +import com.unciv.ui.utils.extensions.disable import com.unciv.ui.utils.extensions.onClick -import com.unciv.ui.utils.extensions.surroundWithCircle +import com.unciv.ui.utils.extensions.toTextButton class ConstructionInfoTable(val cityScreen: CityScreen): Table() { private val selectedConstructionTable = Table() @@ -56,8 +61,14 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() { selectedConstructionTable.run { pad(10f) - add(ImageGetter.getPortraitImage(construction.name, 50f)) - .pad(5f) + add(ImageGetter.getPortraitImage(construction.name, 50f).apply { + val link = (construction as? IRulesetObject)?.makeLink() ?: return + if (link.isEmpty()) return + touchable = Touchable.enabled + this.onClick { + UncivGame.Current.pushScreen(CivilopediaScreen(city.getRuleset(), link = link)) + } + }).pad(5f) var buildingText = construction.name.tr() val specialConstruction = PerpetualConstruction.perpetualConstructionsMap[construction.name] @@ -78,11 +89,36 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() { descriptionLabel.wrap = true add(descriptionLabel).colspan(2).width(stage.width / 4) - val link = (construction as? IRulesetObject)?.makeLink() ?: return - if (link.isEmpty()) return - touchable = Touchable.enabled - onClick { - UncivGame.Current.pushScreen(CivilopediaScreen(city.getRuleset(), link = link)) + // Show sell button if construction is a currently sellable building + if (construction is Building && cityConstructions.isBuilt(construction.name) + && construction.isSellable()) { + val sellAmount = cityScreen.city.getGoldForSellingBuilding(construction.name) + val sellText = "Sell [$sellAmount] " + Fonts.gold + val sellBuildingButton = sellText.toTextButton() + row() + add(sellBuildingButton).padTop(5f).colspan(2).center() + + sellBuildingButton.onClick(UncivSound.Coin) { + sellBuildingButton.disable() + cityScreen.closeAllPopups() + + ConfirmPopup( + cityScreen, + "Are you sure you want to sell this [${construction.name}]?", + sellText, + restoreDefault = { + cityScreen.update() + } + ) { + cityScreen.city.sellBuilding(construction.name) + cityScreen.clearSelection() + cityScreen.update() + }.open() + } + if (cityScreen.city.hasSoldBuildingThisTurn && !cityScreen.city.civInfo.gameInfo.gameParameters.godMode + || cityScreen.city.isPuppet + || !UncivGame.Current.worldScreen!!.isPlayersTurn || !cityScreen.canChangeState) + sellBuildingButton.disable() } } }