From ae28dca570b1fc1c6fb2107de53b1d93acbb96c1 Mon Sep 17 00:00:00 2001 From: SeventhM <127357473+SeventhM@users.noreply.github.com> Date: Mon, 16 Dec 2024 00:54:47 -0800 Subject: [PATCH] Add unified unique for gaining stats or stockpiles (#12642) * Add unified unique for gaining stats or stockpiles * Use IgnoreConditionals instead of EmptyState --- core/src/com/unciv/logic/city/City.kt | 30 +++++++++++++ .../com/unciv/logic/city/CityConstructions.kt | 4 +- .../src/com/unciv/logic/city/CityResources.kt | 4 +- .../unciv/logic/civilization/Civilization.kt | 42 ++++++++++++++++++- .../diplomacy/DiplomacyManager.kt | 2 +- .../diplomacy/DiplomacyTurnManager.kt | 2 +- .../civilization/managers/GoldenAgeManager.kt | 5 ++- .../civilization/managers/TurnManager.kt | 4 +- .../unciv/models/ruleset/tile/TileResource.kt | 9 ++-- .../ruleset/unique/UniqueParameterType.kt | 11 ++++- .../ruleset/unique/UniqueTriggerActivation.kt | 29 +++++++++++-- .../unciv/models/ruleset/unique/UniqueType.kt | 1 + .../ruleset/validation/UniqueValidator.kt | 2 +- .../com/unciv/models/stats/GameResource.kt | 4 ++ core/src/com/unciv/models/stats/Stat.kt | 4 +- core/src/com/unciv/models/stats/SubStat.kt | 20 +++++++++ .../BaseUnitDescriptions.kt | 4 +- .../BuildingDescriptions.kt | 4 +- .../cityscreen/CityConstructionsTable.kt | 2 +- .../ui/screens/cityscreen/CityStatsTable.kt | 2 +- .../overviewscreen/ResourcesOverviewTab.kt | 4 +- .../topbar/WorldScreenTopBarResources.kt | 4 +- .../unit/actions/UnitActionModifiers.kt | 2 +- 23 files changed, 162 insertions(+), 33 deletions(-) create mode 100644 core/src/com/unciv/models/stats/GameResource.kt create mode 100644 core/src/com/unciv/models/stats/SubStat.kt diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index 1a22019cc3..055dfc4e4f 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -17,12 +17,15 @@ import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.Tile import com.unciv.models.ruleset.Building +import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unit.BaseUnit +import com.unciv.models.stats.GameResource import com.unciv.models.stats.INamed import com.unciv.models.stats.Stat +import com.unciv.models.stats.SubStat import java.util.UUID import kotlin.math.roundToInt @@ -212,6 +215,19 @@ class City : IsPartOfGameInfoSerialization, INamed { } } + fun addGameResource(stat: GameResource, amount: Int) { + if (stat is TileResource) { + if (!stat.isStockpiled) return + if (!stat.isCityWide) civ.gainStockpiledResource(stat.name, amount) + else { /*TODO*/ } + } + when (stat) { + Stat.Production -> cityConstructions.addProductionPoints(amount) + Stat.Food, SubStat.StoredFood -> population.foodStored += amount + else -> civ.addGameResource(stat, amount) + } + } + fun getStatReserve(stat: Stat): Int { return when (stat) { Stat.Production -> cityConstructions.getWorkDone(cityConstructions.getCurrentConstruction().name) @@ -220,6 +236,20 @@ class City : IsPartOfGameInfoSerialization, INamed { } } + fun getReserve(stat: GameResource): Int { + if (stat is TileResource && stat.isCityWide) { + return if (stat.isStockpiled) { + // TODO + 0 + } else 0 + } + return when (stat) { + Stat.Production -> cityConstructions.getWorkDone(cityConstructions.getCurrentConstruction().name) + Stat.Food, SubStat.StoredFood -> population.foodStored + else -> civ.getReserve(stat) + } + } + fun hasStatToBuy(stat: Stat, price: Int): Boolean { return when { civ.gameInfo.gameParameters.godMode -> true diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index 63cda4ab33..dce5c5d994 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -435,7 +435,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { for (unique in costUniques) { val amount = unique.params[0].toInt() val resourceName = unique.params[1] - city.civ.resourceStockpiles.add(resourceName, -amount) + city.civ.gainStockpiledResource(resourceName, -amount) } if (construction !is Building) return @@ -705,7 +705,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { for (unique in costUniques) { val amount = unique.params[0].toInt() val resourceName = unique.params[1] - city.civ.resourceStockpiles.add(resourceName, -amount) + city.civ.gainStockpiledResource(resourceName, -amount) } } } diff --git a/core/src/com/unciv/logic/city/CityResources.kt b/core/src/com/unciv/logic/city/CityResources.kt index 1040f3b8a3..dfe0a2eb64 100644 --- a/core/src/com/unciv/logic/city/CityResources.kt +++ b/core/src/com/unciv/logic/city/CityResources.kt @@ -28,7 +28,7 @@ object CityResources { // This way we get them once, but it is ugly, I welcome other ideas :/ getCityResourcesFromCiv(city, cityResources, resourceModifers) - cityResources.removeAll { !it.resource.hasUnique(UniqueType.CityResource) } + cityResources.removeAll { !it.resource.isCityWide } return cityResources } @@ -69,7 +69,7 @@ object CityResources { fun getAvailableResourceAmount(city: City, resourceName: String): Int { val resource = city.getRuleset().tileResources[resourceName] ?: return 0 - if (resource.hasUnique(UniqueType.CityResource)) + if (resource.isCityWide) return getCityResourcesAvailableToCity(city).asSequence().filter { it.resource == resource }.sumOf { it.amount } return city.civ.getResourceAmount(resourceName) } diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index bda0869d3a..bb3811e680 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -48,8 +48,10 @@ import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.ruleset.unique.* import com.unciv.models.ruleset.unit.BaseUnit +import com.unciv.models.stats.GameResource import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats +import com.unciv.models.stats.SubStat import com.unciv.models.translations.tr import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.screens.victoryscreen.RankingType @@ -451,7 +453,7 @@ class Civilization : IsPartOfGameInfoSerialization { val newResourceSupplyList = ResourceSupplyList(keepZeroAmounts = true) for (resourceSupply in detailedCivResources) { - if (resourceSupply.resource.isStockpiled()) continue + if (resourceSupply.resource.isStockpiled) continue if (resourceSupply.resource.hasUnique(UniqueType.CannotBeTraded, state)) continue // If we got it from another trade or from a CS, preserve the origin if (resourceSupply.isCityStateOrTradeOrigin()) { @@ -475,7 +477,7 @@ class Civilization : IsPartOfGameInfoSerialization { val hashMap = HashMap(gameInfo.ruleset.tileResources.size) for (resource in gameInfo.ruleset.tileResources.keys) hashMap[resource] = 0 for (entry in getCivResourceSupply()) - if (!entry.resource.isStockpiled()) + if (!entry.resource.isStockpiled) hashMap[entry.resource.name] = entry.amount for ((key, value) in resourceStockpiles) hashMap[key] = value @@ -863,6 +865,26 @@ class Civilization : IsPartOfGameInfoSerialization { } } + fun addGameResource(stat: GameResource, amount: Int) { + if (stat is TileResource && !stat.isCityWide && stat.isStockpiled) gainStockpiledResource(stat.name, amount) + when (stat) { + Stat.Culture -> { policies.addCulture(amount) + if (amount > 0) totalCultureForContests += amount } + Stat.Science -> tech.addScience(amount) + Stat.Gold -> addGold(amount) + Stat.Faith -> { religionManager.storedFaith += amount + if (amount > 0) totalFaithForContests += amount } + SubStat.GoldenAgePoints -> goldenAges.addHappiness(amount) + else -> {} + // Food and Production wouldn't make sense to be added nationwide + // Happiness cannot be added as it is recalculated again, use a unique instead + } + } + + fun gainStockpiledResource(resourceName: String, amount: Int) { + resourceStockpiles.add(resourceName, amount) + } + fun getStatReserve(stat: Stat): Int { return when (stat) { Stat.Culture -> policies.storedCulture @@ -876,6 +898,22 @@ class Civilization : IsPartOfGameInfoSerialization { } } + fun getReserve(stat: GameResource): Int { + if (stat is TileResource && !stat.isCityWide && stat.isStockpiled) + return resourceStockpiles[stat.name] + return when (stat) { + Stat.Culture -> policies.storedCulture + Stat.Science -> { + if (tech.currentTechnology() == null) 0 + else tech.researchOfTech(tech.currentTechnology()!!.name) + } + Stat.Gold -> gold + Stat.Faith -> religionManager.storedFaith + SubStat.GoldenAgePoints -> goldenAges.storedHappiness + else -> 0 + } + } + // region addNotification fun addNotification(text: String, category: NotificationCategory, vararg notificationIcons: String) = addNotification(text, null, category, *notificationIcons) diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index f0eb6f5c75..2b1b4c04b8 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -432,7 +432,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization { val isResourceFilter: (TradeOffer) -> Boolean = { (it.type == TradeOfferType.Strategic_Resource || it.type == TradeOfferType.Luxury_Resource) && resourcesMap.containsKey(it.name) - && !resourcesMap[it.name]!!.isStockpiled() + && !resourcesMap[it.name]!!.isStockpiled } for (trade in trades) { for (offer in trade.ourOffers.filter(isResourceFilter)) diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyTurnManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyTurnManager.kt index 3047ebd2b0..ed3e9c4f0c 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyTurnManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyTurnManager.kt @@ -31,7 +31,7 @@ object DiplomacyTurnManager { // Every cancelled trade can change this - if 1 resource is missing, // don't cancel all trades of that resource, only cancel one (the first one, as it happens, since they're added chronologically) val negativeCivResources = civInfo.getCivResourceSupply() - .filter { it.amount < 0 && !it.resource.isStockpiled() }.map { it.resource.name } + .filter { it.amount < 0 && !it.resource.isStockpiled }.map { it.resource.name } for (offer in trade.ourOffers) { if (offer.type in listOf(TradeOfferType.Luxury_Resource, TradeOfferType.Strategic_Resource) diff --git a/core/src/com/unciv/logic/civilization/managers/GoldenAgeManager.kt b/core/src/com/unciv/logic/civilization/managers/GoldenAgeManager.kt index 6395d33a0c..54bd6e94d6 100644 --- a/core/src/com/unciv/logic/civilization/managers/GoldenAgeManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/GoldenAgeManager.kt @@ -9,7 +9,6 @@ import com.unciv.logic.civilization.PopupAlert import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unique.UniqueType import com.unciv.ui.components.extensions.toPercent -import kotlin.math.max class GoldenAgeManager : IsPartOfGameInfoSerialization { @Transient @@ -28,6 +27,10 @@ class GoldenAgeManager : IsPartOfGameInfoSerialization { } fun isGoldenAge(): Boolean = turnsLeftForCurrentGoldenAge > 0 + + fun addHappiness(amount: Int) { + storedHappiness += amount + } fun happinessRequiredForNextGoldenAge(): Int { var cost = (500 + numberOfGoldenAges * 250).toFloat() diff --git a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt index 8c0fdffd95..8fbd7f74bb 100644 --- a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt @@ -40,8 +40,8 @@ class TurnManager(val civInfo: Civilization) { civInfo.tech.updateResearchProgress() civInfo.cache.updateCivResources() // If you offered a trade last turn, this turn it will have been accepted/declined - for (stockpiledResource in civInfo.getCivResourceSupply().filter { it.resource.isStockpiled() }) - civInfo.resourceStockpiles.add(stockpiledResource.resource.name, stockpiledResource.amount) + for (stockpiledResource in civInfo.getCivResourceSupply().filter { it.resource.isStockpiled }) + civInfo.gainStockpiledResource(stockpiledResource.resource.name, stockpiledResource.amount) civInfo.civConstructions.startTurn() civInfo.attacksSinceTurnStart.clear() diff --git a/core/src/com/unciv/models/ruleset/tile/TileResource.kt b/core/src/com/unciv/models/ruleset/tile/TileResource.kt index 77ec4990c9..cc5757a265 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileResource.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileResource.kt @@ -9,11 +9,12 @@ import com.unciv.models.ruleset.RulesetStatsObject import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueType +import com.unciv.models.stats.GameResource import com.unciv.models.stats.Stats import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines import com.unciv.ui.screens.civilopediascreen.FormattedLine -class TileResource : RulesetStatsObject() { +class TileResource : RulesetStatsObject(), GameResource { var resourceType: ResourceType = ResourceType.Bonus var terrainsCanBeFoundOn: List = listOf() @@ -35,6 +36,10 @@ class TileResource : RulesetStatsObject() { var majorDepositAmount: DepositAmount = DepositAmount() var minorDepositAmount: DepositAmount = DepositAmount() + + val isCityWide by lazy { hasUnique(UniqueType.CityResource, StateForConditionals.IgnoreConditionals) } + + val isStockpiled by lazy { hasUnique(UniqueType.Stockpiled, StateForConditionals.IgnoreConditionals) } private var improvementsInitialized = false /** Cache collecting [improvement], [improvedBy] and [UniqueType.ImprovesResources] uniques on the improvements themselves. */ @@ -209,8 +214,6 @@ class TileResource : RulesetStatsObject() { return true } - fun isStockpiled() = hasUnique(UniqueType.Stockpiled) - class DepositAmount { var sparse: Int = 1 var default: Int = 2 diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt index b45e6691fa..90cb48c601 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt @@ -11,6 +11,7 @@ import com.unciv.models.ruleset.tile.TerrainType import com.unciv.models.ruleset.unique.UniqueParameterType.Companion.guessTypeForTranslationWriter import com.unciv.models.ruleset.validation.Suppression import com.unciv.models.stats.Stat +import com.unciv.models.stats.SubStat import com.unciv.models.translations.TranslationFileWriter import com.unciv.models.translations.equalsPlaceholderText @@ -468,7 +469,15 @@ enum class UniqueParameterType( /** Used by [UniqueType.OneTimeConsumeResources], [UniqueType.OneTimeProvideResources], [UniqueType.CostsResources], [UniqueType.UnitActionStockpileCost], implementation not centralized */ StockpiledResource("stockpiledResource", "Mana", "The name of any stockpiled resource") { - override fun getKnownValuesForAutocomplete(ruleset: Ruleset) = ruleset.tileResources.filter { it.value.isStockpiled() }.keys + override fun getKnownValuesForAutocomplete(ruleset: Ruleset) = ruleset.tileResources.filter { it.value.isStockpiled }.keys + }, + + /** Used by [UniqueType.OneTimeGainResource], implementation not centralized */ + Stockpile("stockpile", "Mana", "The name of any stockpiled resource") { + override fun getKnownValuesForAutocomplete(ruleset: Ruleset): Set { + return ruleset.tileResources.filter { it.value.isStockpiled }.keys + + Stat.entries.map { it.name } + SubStat.StoredFood.name + SubStat.GoldenAgePoints.name + } }, /** Used by [UniqueType.ImprovesResources], implemented by [com.unciv.models.ruleset.tile.TileResource.matchesFilter] */ diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt index b4235ae2a5..73e8a5b1a3 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt @@ -27,8 +27,10 @@ import com.unciv.models.UpgradeUnitAction import com.unciv.models.ruleset.BeliefType import com.unciv.models.ruleset.Event import com.unciv.models.ruleset.tile.TerrainType +import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats +import com.unciv.models.stats.SubStat import com.unciv.models.translations.fillPlaceholders import com.unciv.models.translations.hasPlaceholderParameters import com.unciv.models.translations.tr @@ -521,11 +523,11 @@ object UniqueTriggerActivation { UniqueType.OneTimeProvideResources -> { val resourceName = unique.params[1] val resource = ruleset.tileResources[resourceName] ?: return null - if (!resource.isStockpiled()) return null + if (!resource.isStockpiled) return null return { val amount = unique.params[0].toInt() - civInfo.resourceStockpiles.add(resourceName, amount) + civInfo.gainStockpiledResource(resourceName, amount) val notificationText = getNotificationText( notification, triggerNotificationText, @@ -540,11 +542,11 @@ object UniqueTriggerActivation { UniqueType.OneTimeConsumeResources -> { val resourceName = unique.params[1] val resource = ruleset.tileResources[resourceName] ?: return null - if (!resource.isStockpiled()) return null + if (!resource.isStockpiled) return null return { val amount = unique.params[0].toInt() - civInfo.resourceStockpiles.add(resourceName, -amount) + civInfo.gainStockpiledResource(resourceName, -amount) val notificationText = getNotificationText( notification, triggerNotificationText, @@ -556,6 +558,25 @@ object UniqueTriggerActivation { } } + UniqueType.OneTimeGainResource -> { + val resourceName = unique.params[1] + + val resource = Stat.safeValueOf(resourceName) ?: + SubStat.safeValueOf(resourceName) ?: + ruleset.tileResources[resourceName] ?: return null + if (resource is TileResource && !resource.isStockpiled) return null + + return { + var amount = unique.params[0].toInt() + if (unique.isModifiedByGameSpeed()) { + if (resource is Stat) amount = (amount * civInfo.gameInfo.speed.statCostModifiers[resource]!!).roundToInt() + else amount = (amount * civInfo.gameInfo.speed.modifier).roundToInt() + } + city?.addGameResource(resource, amount) ?: civInfo.addGameResource(resource, amount) + true + } + } + UniqueType.UnitsGainPromotion -> { val filter = unique.params[0] val promotionName = unique.params[1] diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index ed4ac3799c..d47b321883 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -809,6 +809,7 @@ enum class UniqueType( OneTimeConsumeResources("Instantly consumes [positiveAmount] [stockpiledResource]", UniqueTarget.Triggerable), OneTimeProvideResources("Instantly provides [positiveAmount] [stockpiledResource]", UniqueTarget.Triggerable), + OneTimeGainResource("Instantly gain [amount] [stockpile]", UniqueTarget.Triggerable, flags = setOf(UniqueFlag.AcceptsSpeedModifier)), OneTimeGainStat("Gain [amount] [stat]", UniqueTarget.Triggerable, flags = setOf(UniqueFlag.AcceptsSpeedModifier)), OneTimeGainStatRange("Gain [amount]-[amount] [stat]", UniqueTarget.Triggerable), OneTimeGainPantheon("Gain enough Faith for a Pantheon", UniqueTarget.Triggerable), diff --git a/core/src/com/unciv/models/ruleset/validation/UniqueValidator.kt b/core/src/com/unciv/models/ruleset/validation/UniqueValidator.kt index 35f776fb7c..e0e9218b14 100644 --- a/core/src/com/unciv/models/ruleset/validation/UniqueValidator.kt +++ b/core/src/com/unciv/models/ruleset/validation/UniqueValidator.kt @@ -170,7 +170,7 @@ class UniqueValidator(val ruleset: Ruleset) { ) if (unique.type in resourceUniques && conditional.type in resourceConditionals - && ruleset.tileResources[conditional.params.last()]?.hasUnique(UniqueType.CityResource) == true) + && ruleset.tileResources[conditional.params.last()]?.isCityWide == true) rulesetErrors.add( "$prefix contains the conditional \"${conditional.text}\"," + " which references a citywide resource. This is not a valid conditional for a resource uniques, " + diff --git a/core/src/com/unciv/models/stats/GameResource.kt b/core/src/com/unciv/models/stats/GameResource.kt new file mode 100644 index 0000000000..e3c0f679d3 --- /dev/null +++ b/core/src/com/unciv/models/stats/GameResource.kt @@ -0,0 +1,4 @@ +package com.unciv.models.stats + +interface GameResource { +} diff --git a/core/src/com/unciv/models/stats/Stat.kt b/core/src/com/unciv/models/stats/Stat.kt index 70612292c2..2a4a473bb6 100644 --- a/core/src/com/unciv/models/stats/Stat.kt +++ b/core/src/com/unciv/models/stats/Stat.kt @@ -11,7 +11,7 @@ enum class Stat( val purchaseSound: UncivSound, val character: Char, val color: Color -) { +) : GameResource { Production(NotificationIcon.Production, UncivSound.Click, Fonts.production, colorFromHex(0xc14d00)), Food(NotificationIcon.Food, UncivSound.Click, Fonts.food, colorFromHex(0x24A348)), Gold(NotificationIcon.Gold, UncivSound.Coin, Fonts.gold, colorFromHex(0xffeb7f)), @@ -22,7 +22,7 @@ enum class Stat( companion object { val statsUsableToBuy = setOf(Gold, Food, Science, Culture, Faith) - private val valuesAsMap = values().associateBy { it.name } + private val valuesAsMap = entries.associateBy { it.name } fun safeValueOf(name: String) = valuesAsMap[name] fun isStat(name: String) = name in valuesAsMap fun names() = valuesAsMap.keys diff --git a/core/src/com/unciv/models/stats/SubStat.kt b/core/src/com/unciv/models/stats/SubStat.kt new file mode 100644 index 0000000000..fd957733b9 --- /dev/null +++ b/core/src/com/unciv/models/stats/SubStat.kt @@ -0,0 +1,20 @@ +package com.unciv.models.stats + +enum class SubStat : GameResource { + GoldenAgePoints, + TotalCulture, + StoredFood, + ; + companion object { + val useableToBuy = setOf(GoldenAgePoints, StoredFood) + val civWideSubStats = setOf(GoldenAgePoints, TotalCulture) + fun safeValueOf(name: String): SubStat? { + return when (name) { + GoldenAgePoints.name -> GoldenAgePoints + TotalCulture.name -> TotalCulture + StoredFood.name -> StoredFood + else -> null + } + } + } +} diff --git a/core/src/com/unciv/ui/objectdescriptions/BaseUnitDescriptions.kt b/core/src/com/unciv/ui/objectdescriptions/BaseUnitDescriptions.kt index 2202f3cbd3..e90df4a0f5 100644 --- a/core/src/com/unciv/ui/objectdescriptions/BaseUnitDescriptions.kt +++ b/core/src/com/unciv/ui/objectdescriptions/BaseUnitDescriptions.kt @@ -44,7 +44,7 @@ object BaseUnitDescriptions { for ((resourceName, amount) in baseUnit.getResourceRequirementsPerTurn(city.civ.state)) { val available = availableResources[resourceName] ?: 0 val resource = baseUnit.ruleset.tileResources[resourceName] ?: continue - val consumesString = resourceName.getConsumesAmountString(amount, resource.isStockpiled()) + val consumesString = resourceName.getConsumesAmountString(amount, resource.isStockpiled) lines += "$consumesString ({[$available] available})".tr() } var strengthLine = "" @@ -112,7 +112,7 @@ object BaseUnitDescriptions { textList += FormattedLine() val resource = ruleset.tileResources[baseUnit.requiredResource] textList += FormattedLine( - baseUnit.requiredResource!!.getConsumesAmountString(1, resource!!.isStockpiled()), + baseUnit.requiredResource!!.getConsumesAmountString(1, resource!!.isStockpiled), link="Resources/${baseUnit.requiredResource}", color="#F42") } diff --git a/core/src/com/unciv/ui/objectdescriptions/BuildingDescriptions.kt b/core/src/com/unciv/ui/objectdescriptions/BuildingDescriptions.kt index 393c807f77..223b6f6dc3 100644 --- a/core/src/com/unciv/ui/objectdescriptions/BuildingDescriptions.kt +++ b/core/src/com/unciv/ui/objectdescriptions/BuildingDescriptions.kt @@ -50,7 +50,7 @@ object BuildingDescriptions { for ((resourceName, amount) in getResourceRequirementsPerTurn(city.state)) { val available = city.getAvailableResourceAmount(resourceName) val resource = city.getRuleset().tileResources[resourceName] ?: continue - val consumesString = resourceName.getConsumesAmountString(amount, resource.isStockpiled()) + val consumesString = resourceName.getConsumesAmountString(amount, resource.isStockpiled) translatedLines += if (showAdditionalInfo) "$consumesString ({[$available] available})".tr() else consumesString.tr() @@ -187,7 +187,7 @@ object BuildingDescriptions { textList += FormattedLine() val resource = ruleset.tileResources[requiredResource] textList += FormattedLine( - requiredResource!!.getConsumesAmountString(1, resource!!.isStockpiled()), + requiredResource!!.getConsumesAmountString(1, resource!!.isStockpiled), link="Resources/$requiredResource", color="#F42" ) } diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt index 3e67358749..b094a0f5d5 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt @@ -332,7 +332,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { else construction.getResourceRequirementsPerTurn(city.state) for ((resourceName, amount) in constructionResource) { val resource = cityConstructions.city.getRuleset().tileResources[resourceName] ?: continue - text += "\n" + resourceName.getConsumesAmountString(amount, resource.isStockpiled()).tr() + text += "\n" + resourceName.getConsumesAmountString(amount, resource.isStockpiled).tr() } table.defaults().pad(2f).minWidth(40f) diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityStatsTable.kt b/core/src/com/unciv/ui/screens/cityscreen/CityStatsTable.kt index 484ae7c523..22b07e26a7 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityStatsTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityStatsTable.kt @@ -198,7 +198,7 @@ class CityStatsTable(private val cityScreen: CityScreen) : Table() { for (resourceSupply in CityResources.getCityResourcesAvailableToCity(city)) resourceCounter.add(resourceSupply.resource, resourceSupply.amount) for ((resource, amount) in resourceCounter) - if (resource.hasUnique(UniqueType.CityResource)) { + if (resource.isCityWide) { resourceTable.add(amount.toLabel()) resourceTable.add(ImageGetter.getResourcePortrait(resource.name, 20f)) .padRight(5f) diff --git a/core/src/com/unciv/ui/screens/overviewscreen/ResourcesOverviewTab.kt b/core/src/com/unciv/ui/screens/overviewscreen/ResourcesOverviewTab.kt index a3e8dbea79..4f82851e69 100644 --- a/core/src/com/unciv/ui/screens/overviewscreen/ResourcesOverviewTab.kt +++ b/core/src/com/unciv/ui/screens/overviewscreen/ResourcesOverviewTab.kt @@ -81,7 +81,7 @@ class ResourcesOverviewTab( return tile.countAsUnimproved() } val amount = get(resource, origin)?.amount ?: return null - val label = if (resource.isStockpiled() && amount > 0) "+$amount".toLabel() + val label = if (resource.isStockpiled && amount > 0) "+$amount".toLabel() else amount.toLabel() if (origin == ExtraInfoOrigin.Unimproved.name) label.onClick { overviewScreen.showOneTimeNotification( @@ -92,7 +92,7 @@ class ResourcesOverviewTab( private fun ResourceSupplyList.getTotalLabel(resource: TileResource): Label { val total = filter { it.resource == resource }.sumOf { it.amount } - return if (resource.isStockpiled() && total > 0) "+$total".toLabel() + return if (resource.isStockpiled && total > 0) "+$total".toLabel() else total.toLabel() } diff --git a/core/src/com/unciv/ui/screens/worldscreen/topbar/WorldScreenTopBarResources.kt b/core/src/com/unciv/ui/screens/worldscreen/topbar/WorldScreenTopBarResources.kt index 4f0adb0639..fa842a5a08 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/topbar/WorldScreenTopBarResources.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/topbar/WorldScreenTopBarResources.kt @@ -62,7 +62,7 @@ internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : ScalingTa } val strategicResources = worldScreen.gameInfo.ruleset.tileResources.values - .filter { it.resourceType == ResourceType.Strategic && !it.hasUnique(UniqueType.CityResource) } + .filter { it.resourceType == ResourceType.Strategic && !it.isCityWide } for (resource in strategicResources) { val resourceImage = ImageGetter.getResourcePortrait(resource.name, iconSize) val resourceLabel = "0".toLabel() @@ -101,7 +101,7 @@ internal class WorldScreenTopBarResources(topbar: WorldScreenTopBar) : ScalingTa resourcesWrapper.add(icon).padLeft(if (index == 0) 0f else extraPadBetweenResources) - if (!resource.isStockpiled()) + if (!resource.isStockpiled) label.setText(amount.tr()) else { val perTurn = civResourceSupply.firstOrNull { it.resource == resource }?.amount ?: 0 diff --git a/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActionModifiers.kt b/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActionModifiers.kt index af51f39e83..a867d98652 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActionModifiers.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActionModifiers.kt @@ -116,7 +116,7 @@ object UnitActionModifiers { val amount = conditional.params[0].toInt() val resourceName = conditional.params[1] if(unit.civ.getCivResourcesByName()[resourceName] != null) - unit.civ.resourceStockpiles.add(resourceName, -amount) + unit.civ.gainStockpiledResource(resourceName, -amount) } UniqueType.UnitActionRemovingPromotion -> { val promotionName = conditional.params[0]