CityScreen Buy button rework (#4843)

* CityScreen Buy button rework
- e.g. "Buy" for Missionary
- Info pane staying even when building no longer offered
- Purchase Prompt a little prettier

* Urgent Fix - noMods switch default

* CityScreen Buy button rework - patch1
This commit is contained in:
SomeTroglodyte 2021-08-18 11:17:40 +02:00 committed by GitHub
parent ab69f75256
commit 03981c6242
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 50 deletions

View File

@ -634,8 +634,8 @@ Raze city = Stadt niederreißen
Stop razing city = Niederreißen der Stadt stoppen
Buy for [amount] gold = Für [amount] Gold kaufen
Buy = Kaufen
Currently you have [amount] gold. = Zur Zeit besitzt du [amount] Gold.
Would you like to purchase [constructionName] for [buildingGoldCost] gold? = [constructionName] für [buildingGoldCost] Gold kaufen?
Currently you have [amount] [stat]. = Zur Zeit besitzt du [amount] [stat].
Would you like to purchase [constructionName] for [buildingGoldCost] [stat]? = [constructionName] für [buildingGoldCost] [stat] kaufen?
No space available to place [unit] near [city] = Kein Platz verfügbar um [unit] nahe [city] zu platzieren
Maintenance cost = Wartungskosten
Pick construction = Produktion auswählen

View File

@ -631,8 +631,8 @@ Raze city =
Stop razing city =
Buy for [amount] gold =
Buy =
Currently you have [amount] gold. =
Would you like to purchase [constructionName] for [buildingGoldCost] gold? =
Currently you have [amount] [stat]. =
Would you like to purchase [constructionName] for [buildingGoldCost] [stat]? =
No space available to place [unit] near [city] =
Maintenance cost =
Pick construction =

View File

@ -16,4 +16,11 @@ enum class Stat(
Culture(NotificationIcon.Culture, UncivSound.Paper, Fonts.culture),
Happiness(NotificationIcon.Happiness, UncivSound.Click, Fonts.happiness),
Faith(NotificationIcon.Faith, UncivSound.Choir, Fonts.faith);
companion object {
val statsUsableToBuy = listOf(Gold, Food, Science, Culture, Faith)
}
}
// Should the well-known colours for these be needed:
// Production = "#c14d00", Food = "#38ff70", Gold = "#ffeb7f", Science = "#8c9dff", Culture = "#8b60ff", Happiness = "#ffd800", Faith = "#cbdfff"

View File

@ -120,28 +120,18 @@ class CityConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBase
val city = cityScreen.city
val cityConstructions = city.cityConstructions
for (unit in city.getRuleset().units.values.filter { it.shouldBeDisplayed(cityConstructions) }) {
val useStoredProduction = !cityConstructions.isBeingConstructedOrEnqueued(unit.name)
var buttonText = unit.name.tr() + cityConstructions.getTurnsToConstructionString(unit.name, useStoredProduction)
for ((resource, amount) in unit.getResourceRequirements()) {
if (amount == 1) buttonText += "\n" + "Consumes 1 [$resource]".tr()
else buttonText += "\n" + "Consumes [$amount] [$resource]".tr()
val constructionsSequence = city.getRuleset().units.values.asSequence() +
city.getRuleset().buildings.values.asSequence()
for (entry in constructionsSequence.filter { it.shouldBeDisplayed(cityConstructions) }) {
val useStoredProduction = entry is Building || !cityConstructions.isBeingConstructedOrEnqueued(entry.name)
var buttonText = entry.name.tr() + cityConstructions.getTurnsToConstructionString(entry.name, useStoredProduction)
for ((resource, amount) in entry.getResourceRequirements()) {
buttonText += "\n" + (if (amount == 1) "Consumes 1 [$resource]"
else "Consumes [$amount] [$resource]").tr()
}
constructionButtonDTOList.add(ConstructionButtonDTO(unit, buttonText,
unit.getRejectionReason(cityConstructions)))
}
for (building in city.getRuleset().buildings.values.filter { it.shouldBeDisplayed(cityConstructions) }) {
var buttonText = building.name.tr() + cityConstructions.getTurnsToConstructionString(building.name)
for ((resource, amount) in building.getResourceRequirements()) {
if (amount == 1) buttonText += "\n" + "Consumes 1 [$resource]".tr()
else buttonText += "\n" + "Consumes [$amount] [$resource]".tr()
}
constructionButtonDTOList.add(ConstructionButtonDTO(building, buttonText,
building.getRejectionReason(cityConstructions)))
constructionButtonDTOList.add(ConstructionButtonDTO(entry, buttonText,
entry.getRejectionReason(cityConstructions)))
}
for (specialConstruction in PerpetualConstruction.perpetualConstructionsMap.values
@ -376,7 +366,7 @@ class CityConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBase
}
}
fun purchaseConstruction(construction: INonPerpetualConstruction, stat: Stat = Stat.Gold) {
private fun purchaseConstruction(construction: INonPerpetualConstruction, stat: Stat = Stat.Gold) {
val city = cityScreen.city
if (!city.cityConstructions.purchaseConstruction(construction.name, selectedQueueEntry, false, stat)) {
Popup(cityScreen).apply {
@ -386,7 +376,7 @@ class CityConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBase
}
return
}
if (isSelectedQueueEntry()) {
if (isSelectedQueueEntry() || cityScreen.selectedConstruction?.isBuildable(city.cityConstructions) != true) {
selectedQueueEntry = -1
cityScreen.selectedConstruction = null
}
@ -394,38 +384,43 @@ class CityConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBase
}
private fun getBuyButtons(construction: INonPerpetualConstruction?): List<TextButton> {
return listOf(Stat.Gold, Stat.Faith, Stat.Culture, Stat.Science, Stat.Food)
.mapNotNull { getBuyButton(construction, it) }
return Stat.statsUsableToBuy.mapNotNull { getBuyButton(construction, it) }
}
private fun getBuyButton(construction: INonPerpetualConstruction?, stat: Stat = Stat.Gold): TextButton? {
if (stat !in listOf(Stat.Gold, Stat.Faith, Stat.Culture, Stat.Science, Stat.Food))
if (stat !in Stat.statsUsableToBuy || construction == null)
return null
val city = cityScreen.city
val city = cityScreen.city
val button = "".toTextButton()
if (construction == null || construction is PerpetualConstruction ||
(!construction.canBePurchasedWithStat(city, stat) && !city.civInfo.gameInfo.gameParameters.godMode)) {
// fully disable a "buy" button only for "priceless" buildings such as wonders
// for all other cases, the price should be displayed
if (stat == Stat.Gold) {
button.setText("Buy".tr())
button.disable()
}
else return null
if (!construction.canBePurchasedWithStat(city, stat) && !city.civInfo.gameInfo.gameParameters.godMode) {
// This can't ever be bought with the given currency.
// We want one disabled "buy" button without a price for "priceless" buildings such as wonders
// We don't want such a button when the construction can be bought using a different currency
if (stat != Stat.Gold || construction.canBePurchasedWithAnyStat(city))
return null
button.setText("Buy".tr())
button.disable()
} else {
val constructionBuyCost = construction.getStatBuyCost(city, stat)!!
button.setText("Buy".tr() + " " + constructionBuyCost)
button.add(ImageGetter.getStatIcon(stat.name)).size(20f).padBottom(2f)
button.setText("Buy".tr() + " " + constructionBuyCost + stat.character)
button.onClick(stat.purchaseSound) {
button.disable()
cityScreen.closeAllPopups()
val purchasePrompt = "Currently you have [${city.getStatReserve(stat)}] [${stat.name}].".tr() + "\n" +
"Would you like to purchase [${construction.name}] for [$constructionBuyCost] [${stat.name}]?".tr()
YesNoPopup(purchasePrompt, { purchaseConstruction(construction, stat) }, cityScreen, { cityScreen.update() }).open()
val purchasePrompt = "Currently you have [${city.getStatReserve(stat)}] [${stat.name}].".tr() + "\n\n" +
"Would you like to purchase [${construction.name}] for [$constructionBuyCost] [${stat.character}]?".tr()
YesNoPopup(
purchasePrompt,
action = { purchaseConstruction(construction, stat) },
screen = cityScreen,
restoreDefault = { cityScreen.update() }
).apply {
promptLabel.setAlignment(Align.center)
open()
}
}
if (!cityScreen.canChangeState

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame
import com.unciv.logic.map.TileInfo
import com.unciv.models.UncivSound
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaScreen
@ -47,8 +48,8 @@ class CityScreenTileTable(private val cityScreen: CityScreen): Table() {
val buyTileButton = "Buy for [$goldCostOfTile] gold".toTextButton()
buyTileButton.onClick(UncivSound.Coin) {
val purchasePrompt = "Currently you have [${city.civInfo.gold}] gold.".tr() + "\n" +
"Would you like to purchase [Tile] for [$goldCostOfTile] gold?".tr()
val purchasePrompt = "Currently you have [${city.civInfo.gold}] [Gold].".tr() + "\n\n" +
"Would you like to purchase [Tile] for [$goldCostOfTile] [${Stat.Gold.character}]?".tr()
YesNoPopup(purchasePrompt, { city.expansion.buyTile(selectedTile);UncivGame.Current.setScreen(CityScreen(city)) }, cityScreen).open()
}
val canPurchase = goldCostOfTile == 0 || city.civInfo.gold >= goldCostOfTile

View File

@ -1,6 +1,7 @@
package com.unciv.ui.utils
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.Align
import com.unciv.Constants
import com.unciv.UncivGame
@ -11,14 +12,18 @@ import com.unciv.UncivGame
* @param restoreDefault A lambda to execute when "No" is chosen
*/
open class YesNoPopup (
question:String,
action:()->Unit,
question: String,
action: ()->Unit,
screen: CameraStageBaseScreen = UncivGame.Current.worldScreen,
restoreDefault:()->Unit = {}
restoreDefault: ()->Unit = {}
) : Popup(screen) {
/** The [Label][com.badlogic.gdx.scenes.scene2d.ui.Label] created for parameter `question` for optional layout tweaking */
val promptLabel = question.toLabel()
init {
add(question.toLabel()).colspan(2).row()
promptLabel.setAlignment(Align.center)
add(promptLabel).colspan(2).row()
addOKButton(Constants.yes, KeyCharAndCode('y'), action)
addCloseButton(Constants.no, KeyCharAndCode('n'), restoreDefault)
equalizeLastTwoButtonWidths()