getProductionCost can receive city - this will allow us to control city-specific production cost changes!

This commit is contained in:
Yair Morgenstern
2024-02-27 11:05:50 +02:00
parent fd428ce606
commit b4cb0e3d75
7 changed files with 25 additions and 22 deletions

View File

@ -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<String>()
@ -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<Building>) {
val buildingsToRemove = buildings.map { it.name }.toSet()
builtBuildings.removeIf {
builtBuildings.removeAll {
it in buildingsToRemove
}
setTransients()

View File

@ -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 {

View File

@ -35,7 +35,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
override fun legacyRequiredTechs(): Sequence<String> = 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<RejectionReason>
@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)
}