From b4cb0e3d757ad79bce8ff227eb0d1a7d56b4bf27 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Tue, 27 Feb 2024 11:05:50 +0200 Subject: [PATCH] getProductionCost can receive city - this will allow us to control city-specific production cost changes! --- core/src/com/unciv/logic/city/CityConstructions.kt | 10 +++++----- core/src/com/unciv/models/ruleset/Building.kt | 10 ++++++---- core/src/com/unciv/models/ruleset/IConstruction.kt | 8 ++++---- core/src/com/unciv/models/ruleset/unit/BaseUnit.kt | 4 ++-- core/src/com/unciv/models/ruleset/unit/BaseUnitCost.kt | 9 +++++---- .../com/unciv/ui/components/tilegroups/CityButton.kt | 4 ++-- .../ui/screens/cityscreen/CityConstructionsTable.kt | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index f175a18d87..9a434e7fa1 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -146,7 +146,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { /** @param construction needs to be a non-perpetual construction, else an empty string is returned */ internal fun getTurnsToConstructionString(construction: IConstruction, useStoredProduction:Boolean = true): String { if (construction !is INonPerpetualConstruction) return "" // shouldn't happen - val cost = construction.getProductionCost(city.civ) + val cost = construction.getProductionCost(city.civ, city) val turnsToConstruction = turnsToConstruction(construction.name, useStoredProduction) val currentProgress = if (useStoredProduction) getWorkDone(construction.name) else 0 val lines = ArrayList() @@ -254,8 +254,8 @@ class CityConstructions : IsPartOfGameInfoSerialization { val constr = getConstruction(constructionName) return when { constr is PerpetualConstruction -> 0 - useStoredProduction -> (constr as INonPerpetualConstruction).getProductionCost(city.civ) - getWorkDone(constructionName) - else -> (constr as INonPerpetualConstruction).getProductionCost(city.civ) + useStoredProduction -> (constr as INonPerpetualConstruction).getProductionCost(city.civ, city) - getWorkDone(constructionName) + else -> (constr as INonPerpetualConstruction).getProductionCost(city.civ, city) } } @@ -331,7 +331,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { val construction = getConstruction(currentConstructionFromQueue) if (construction is PerpetualConstruction) chooseNextConstruction() // check every turn if we could be doing something better, because this doesn't end by itself else { - val productionCost = (construction as INonPerpetualConstruction).getProductionCost(city.civ) + val productionCost = (construction as INonPerpetualConstruction).getProductionCost(city.civ, city) if (inProgressConstructions.containsKey(currentConstructionFromQueue) && inProgressConstructions[currentConstructionFromQueue]!! >= productionCost) { val potentialOverflow = inProgressConstructions[currentConstructionFromQueue]!! - productionCost @@ -584,7 +584,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { fun removeBuildings(buildings: Set) { val buildingsToRemove = buildings.map { it.name }.toSet() - builtBuildings.removeIf { + builtBuildings.removeAll { it in buildingsToRemove } setTransients() diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index e0f62969f6..4b36d42fa9 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -104,13 +104,14 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { return stats } - override fun getProductionCost(civInfo: Civilization): Int { + override fun getProductionCost(civInfo: Civilization, city: City?): Int { var productionCost = cost.toFloat() + val stateForConditionals = StateForConditionals(civInfo, city) - for (unique in getMatchingUniques(UniqueType.CostIncreasesWhenBuilt, StateForConditionals(civInfo))) + for (unique in getMatchingUniques(UniqueType.CostIncreasesWhenBuilt, stateForConditionals)) productionCost += civInfo.civConstructions.builtItemsWithIncreasingCost[name] * unique.params[0].toInt() - for (unique in getMatchingUniques(UniqueType.CostIncreasesPerCity, StateForConditionals(civInfo))) + for (unique in getMatchingUniques(UniqueType.CostIncreasesPerCity, stateForConditionals)) productionCost += civInfo.cities.size * unique.params[0].toInt() if (civInfo.isCityState()) @@ -126,6 +127,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { } productionCost *= civInfo.gameInfo.speed.productionCostModifier + return productionCost.toInt() } @@ -182,7 +184,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { ) yieldAll(city.getMatchingUniques(UniqueType.BuyBuildingsByProductionCost, conditionalState) .filter { it.params[1] == stat.name && matchesFilter(it.params[0]) } - .map { (getProductionCost(city.civ) * it.params[2].toInt()).toFloat() } + .map { (getProductionCost(city.civ, city) * it.params[2].toInt()).toFloat() } ) if (city.getMatchingUniques(UniqueType.BuyBuildingsWithStat, conditionalState) .any { diff --git a/core/src/com/unciv/models/ruleset/IConstruction.kt b/core/src/com/unciv/models/ruleset/IConstruction.kt index b3b3210649..28e67ad7b2 100644 --- a/core/src/com/unciv/models/ruleset/IConstruction.kt +++ b/core/src/com/unciv/models/ruleset/IConstruction.kt @@ -35,7 +35,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { override fun legacyRequiredTechs(): Sequence = if (requiredTech == null) sequenceOf() else sequenceOf(requiredTech!!) - fun getProductionCost(civInfo: Civilization): Int + fun getProductionCost(civInfo: Civilization, city: City?): Int fun getStatBuyCost(city: City, stat: Stat): Int? fun getRejectionReasons(cityConstructions: CityConstructions): Sequence @@ -74,9 +74,9 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { return ((30.0 * cost.toFloat()).pow(0.75) * hurryCostModifier.toPercent() / 10).toInt() * 10 } - fun getBaseGoldCost(civInfo: Civilization): Double { + fun getBaseGoldCost(civInfo: Civilization, city: City?): Double { // https://forums.civfanatics.com/threads/rush-buying-formula.393892/ - return (30.0 * getProductionCost(civInfo)).pow(0.75) * hurryCostModifier.toPercent() + return (30.0 * getProductionCost(civInfo, city)).pow(0.75) * hurryCostModifier.toPercent() } fun getBaseBuyCost(city: City, stat: Stat): Float? { @@ -88,7 +88,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { .minByOrNull { it.params[0].toInt() } if (lowestCostUnique != null) return lowestCostUnique.params[0].toInt() * city.civ.gameInfo.speed.statCostModifiers[stat]!! - if (stat == Stat.Gold) return getBaseGoldCost(city.civ).toFloat() + if (stat == Stat.Gold) return getBaseGoldCost(city.civ, city).toFloat() // Can be purchased with [Stat] [cityFilter] if (getMatchingUniques(UniqueType.CanBePurchasedWithStat, conditionalState) diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 07ac2b555d..83ec58ea44 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -116,7 +116,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { return ourUniques + type.getMatchingUniques(uniqueType, stateForConditionals) } - override fun getProductionCost(civInfo: Civilization): Int = costFunctions.getProductionCost(civInfo) + override fun getProductionCost(civInfo: Civilization, city: City?): Int = costFunctions.getProductionCost(civInfo, city) override fun canBePurchasedWithStat(city: City?, stat: Stat): Boolean { if (city == null) return super.canBePurchasedWithStat(null, stat) @@ -147,7 +147,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { override fun getStatBuyCost(city: City, stat: Stat): Int? = costFunctions.getStatBuyCost(city, stat) - fun getDisbandGold(civInfo: Civilization) = getBaseGoldCost(civInfo).toInt() / 20 + fun getDisbandGold(civInfo: Civilization) = getBaseGoldCost(civInfo, null).toInt() / 20 override fun shouldBeDisplayed(cityConstructions: CityConstructions): Boolean { val rejectionReasons = getRejectionReasons(cityConstructions) diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnitCost.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnitCost.kt index f59487094a..f9fa361017 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnitCost.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnitCost.kt @@ -9,13 +9,14 @@ import com.unciv.ui.components.extensions.toPercent class BaseUnitCost(val baseUnit: BaseUnit) { - fun getProductionCost(civInfo: Civilization): Int { + fun getProductionCost(civInfo: Civilization, city: City?): Int { var productionCost = baseUnit.cost.toFloat() - for (unique in baseUnit.getMatchingUniques(UniqueType.CostIncreasesPerCity, StateForConditionals(civInfo))) + val stateForConditionals = StateForConditionals(civInfo, city) + for (unique in baseUnit.getMatchingUniques(UniqueType.CostIncreasesPerCity, stateForConditionals)) productionCost += civInfo.cities.size * unique.params[0].toInt() - for (unique in baseUnit.getMatchingUniques(UniqueType.CostIncreasesWhenBuilt, StateForConditionals(civInfo))) + for (unique in baseUnit.getMatchingUniques(UniqueType.CostIncreasesWhenBuilt, stateForConditionals)) productionCost += civInfo.civConstructions.builtItemsWithIncreasingCost[baseUnit.name] * unique.params[0].toInt() if (civInfo.isCityState()) @@ -101,7 +102,7 @@ class BaseUnitCost(val baseUnit: BaseUnit) { ) yieldAll(city.getMatchingUniques(UniqueType.BuyUnitsByProductionCost, conditionalState) .filter { it.params[1] == stat.name && baseUnit.matchesFilter(it.params[0]) } - .map { (getProductionCost(city.civ) * it.params[2].toInt()).toFloat() } + .map { (getProductionCost(city.civ, city) * it.params[2].toInt()).toFloat() } ) if (city.getMatchingUniques(UniqueType.BuyUnitsWithStat, conditionalState) diff --git a/core/src/com/unciv/ui/components/tilegroups/CityButton.kt b/core/src/com/unciv/ui/components/tilegroups/CityButton.kt index 134de707da..d790b1044e 100644 --- a/core/src/com/unciv/ui/components/tilegroups/CityButton.kt +++ b/core/src/com/unciv/ui/components/tilegroups/CityButton.kt @@ -353,9 +353,9 @@ private class CityTable(city: City, forPopup: Boolean = false) : BorderedTable( if (turnsToConstruction < 100) turns = turnsToConstruction.toString() percentage = cityConstructions.getWorkDone(cityCurrentConstruction.name) / - (cityCurrentConstruction as INonPerpetualConstruction).getProductionCost(cityConstructions.city.civ).toFloat() + (cityCurrentConstruction as INonPerpetualConstruction).getProductionCost(cityConstructions.city.civ, cityConstructions.city).toFloat() nextTurnPercentage = (cityConstructions.getWorkDone(cityCurrentConstruction.name) + city.cityStats.currentCityStats.production) / - cityCurrentConstruction.getProductionCost(cityConstructions.city.civ).toFloat() + cityCurrentConstruction.getProductionCost(cityConstructions.city.civ, cityConstructions.city).toFloat() if (nextTurnPercentage > 1f) nextTurnPercentage = 1f if (nextTurnPercentage < 0f) nextTurnPercentage = 0f diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt index 18ec9a055d..871882a822 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt @@ -397,7 +397,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { if (cityConstructions.getWorkDone(constructionName) == 0) return Table() val constructionPercentage = cityConstructions.getWorkDone(constructionName) / - (construction as INonPerpetualConstruction).getProductionCost(cityConstructions.city.civ).toFloat() + (construction as INonPerpetualConstruction).getProductionCost(cityConstructions.city.civ, cityConstructions.city).toFloat() return ImageGetter.getProgressBarVertical(2f, 30f, constructionPercentage, Color.BROWN.brighten(0.5f), Color.WHITE) }