diff --git a/core/src/com/unciv/logic/city/IConstruction.kt b/core/src/com/unciv/logic/city/IConstruction.kt index 9f67ae945c..e0238247c6 100644 --- a/core/src/com/unciv/logic/city/IConstruction.kt +++ b/core/src/com/unciv/logic/city/IConstruction.kt @@ -22,7 +22,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int? fun getRejectionReasons(cityConstructions: CityConstructions): RejectionReasons fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat? = null): Boolean // Yes I'm hilarious. - + fun canBePurchasedWithStat(cityInfo: CityInfo?, stat: Stat): Boolean { if (stat in listOf(Stat.Production, Stat.Happiness)) return false if ("Cannot be purchased" in uniques) return false @@ -47,12 +47,12 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { fun canBePurchasedWithAnyStat(cityInfo: CityInfo): Boolean { return Stat.values().any { canBePurchasedWithStat(cityInfo, it) } } - + fun getBaseGoldCost(civInfo: CivilizationInfo): Double { // https://forums.civfanatics.com/threads/rush-buying-formula.393892/ return (30.0 * getProductionCost(civInfo)).pow(0.75) * hurryCostModifier.toPercent() } - + fun getBaseBuyCost(cityInfo: CityInfo, stat: Stat): Int? { if (stat == Stat.Gold) return getBaseGoldCost(cityInfo.civInfo).toInt() @@ -73,20 +73,20 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { -class RejectionReasons(): HashSet() { - +class RejectionReasons: HashSet() { + fun filterTechPolicyEraWonderRequirements(): HashSet { return filterNot { it in techPolicyEraWonderRequirements }.toHashSet() } - + fun hasAReasonToBeRemovedFromQueue(): Boolean { return any { it in reasonsToDefinitivelyRemoveFromQueue } } - + fun getMostImportantRejectionReason(): String? { return orderOfErrorMessages.firstOrNull { it in this }?.errorMessage } - + // Used for constant variables in the functions above companion object { private val techPolicyEraWonderRequirements = hashSetOf( @@ -122,35 +122,35 @@ enum class RejectionReason(val shouldShow: Boolean, var errorMessage: String) { Unbuildable(false, "Unbuildable"), CanOnlyBePurchased(true, "Can only be purchased"), ShouldNotBeDisplayed(false, "Should not be displayed"), - + DisabledBySetting(false, "Disabled by setting"), HiddenWithoutVictory(false, "Hidden because a victory type has been disabled"), - + MustBeOnTile(false, "Must be on a specific tile"), MustNotBeOnTile(false, "Must not be on a specific tile"), MustBeNextToTile(false, "Must be next to a specific tile"), MustNotBeNextToTile(false, "Must not be next to a specific tile"), - MustOwnTile(false, "Must own a specific tile closeby"), + MustOwnTile(false, "Must own a specific tile close by"), WaterUnitsInCoastalCities(false, "May only built water units in coastal cities"), CanOnlyBeBuiltInSpecificCities(false, "Can only be built in specific cities"), - + UniqueToOtherNation(false, "Unique to another nation"), ReplacedByOurUnique(false, "Our unique replaces this"), - + Obsoleted(false, "Obsolete"), RequiresTech(false, "Required tech not researched"), RequiresPolicy(false, "Requires a specific policy!"), - UnlockedWithEra(false, "Unlocked when reacing a specific era"), + UnlockedWithEra(false, "Unlocked when reaching a specific era"), MorePolicyBranches(false, "Hidden until more policy branches are fully adopted"), - + RequiresNearbyResource(false, "Requires a certain resource being exploited nearby"), InvalidRequiredBuilding(false, "Required building does not exist in ruleSet!"), CannotBeBuiltWith(false, "Cannot be built at the same time as another building already built"), - + RequiresBuildingInThisCity(true, "Requires a specific building in this city!"), RequiresBuildingInAllCities(true, "Requires a specific building in all cities!"), RequiresBuildingInSomeCity(true, "Requires a specific building anywhere in your empire!"), - + WonderAlreadyBuilt(false, "Wonder already built"), NationalWonderAlreadyBuilt(false, "National Wonder already built"), WonderBeingBuiltElsewhere(true, "Wonder is being built elsewhere"), @@ -158,21 +158,19 @@ enum class RejectionReason(val shouldShow: Boolean, var errorMessage: String) { CityStateWonder(false, "No Wonders for city-states"), CityStateNationalWonder(false, "No National Wonders for city-states"), WonderDisabledEra(false, "This Wonder is disabled when starting in this era"), - + ReachedBuildCap(false, "Don't need to build any more of these!"), - + ConsumesResources(true, "Consumes resources which you are lacking"), - + PopulationRequirement(true, "Requires more population"), - - NoSettlerForOneCityPlayers(false, "No settlers for city-states or one-city challangers"); + + NoSettlerForOneCityPlayers(false, "No settlers for city-states or one-city challengers"); } - - open class PerpetualConstruction(override var name: String, val description: String) : IConstruction { - + override fun shouldBeDisplayed(cityConstructions: CityConstructions) = isBuildable(cityConstructions) open fun getProductionTooltip(cityInfo: CityInfo) : String = "\r\n${(cityInfo.cityStats.currentCityStats.production / CONVERSION_RATE).roundToInt()}/${Fonts.turn}" @@ -207,7 +205,7 @@ open class PerpetualConstruction(override var name: String, val description: Str override fun isBuildable(cityConstructions: CityConstructions): Boolean = throw Exception("Impossible!") - + override fun getResourceRequirements(): HashMap = hashMapOf() -} \ No newline at end of file +} diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index 04e6faad77..1785800197 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -1,7 +1,6 @@ package com.unciv.models.ruleset import com.unciv.Constants -import com.unciv.UncivGame import com.unciv.logic.city.* import com.unciv.logic.civilization.CivilizationInfo import com.unciv.models.Counter @@ -22,6 +21,7 @@ import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.toPercent import kotlin.collections.ArrayList import kotlin.collections.HashMap +import kotlin.math.pow class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { @@ -229,7 +229,9 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { if (cost > 0) { val stats = mutableListOf("$cost${Fonts.production}") if (canBePurchasedWithStat(null, Stat.Gold)) { - stats += "${getBaseGoldCost(UncivGame.Current.gameInfo.currentPlayerCiv).toInt() / 10 * 10}${Fonts.gold}" + // We need what INonPerpetualConstruction.getBaseGoldCost calculates but without any game- or civ-specific modifiers + val buyCost = 30.0 * cost.toFloat().pow(0.75f) * hurryCostModifier.toPercent() / 10 * 10 + stats += "$buyCost${Fonts.gold}" } textList += FormattedLine(stats.joinToString(", ", "{Cost}: ")) } @@ -403,7 +405,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { val cityCenter = cityConstructions.cityInfo.getCenterTile() val civInfo = cityConstructions.cityInfo.civInfo val ruleSet = civInfo.gameInfo.ruleSet - + if (cityConstructions.isBuilt(name)) rejectionReasons.add(RejectionReason.AlreadyBuilt) // for buildings that are created as side effects of other things, and not directly built, @@ -418,7 +420,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { if (!cityConstructions.containsBuildingOrEquivalent(unique.params[0])) rejectionReasons.add(RejectionReason.ShouldNotBeDisplayed) // - + "Not displayed as an available construction without []" -> if (unique.params[0] in ruleSet.tileResources && !civInfo.hasResource(unique.params[0]) || unique.params[0] in ruleSet.buildings && !cityConstructions.containsBuildingOrEquivalent(unique.params[0]) @@ -426,35 +428,35 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { || unique.params[0] in ruleSet.policies && !civInfo.policies.isAdopted(unique.params[0]) ) rejectionReasons.add(RejectionReason.ShouldNotBeDisplayed) - + "Enables nuclear weapon" -> if (!cityConstructions.cityInfo.civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled) rejectionReasons.add(RejectionReason.DisabledBySetting) - + "Must be on []" -> if (!cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) rejectionReasons.add(RejectionReason.MustBeOnTile.apply { errorMessage = unique.text }) - + "Must not be on []" -> if (cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) rejectionReasons.add(RejectionReason.MustNotBeOnTile.apply { errorMessage = unique.text }) - + "Must be next to []" -> if (// Fresh water is special, in that rivers are not tiles themselves but also fit the filter. !(unique.params[0] == "Fresh water" && cityCenter.isAdjacentToRiver()) && cityCenter.getTilesInDistance(1).none { it.matchesFilter(unique.params[0], civInfo) } ) rejectionReasons.add(RejectionReason.MustBeNextToTile.apply { errorMessage = unique.text }) - + "Must not be next to []" -> if (cityCenter.getTilesInDistance(1).any { it.matchesFilter(unique.params[0], civInfo) }) rejectionReasons.add(RejectionReason.MustNotBeNextToTile.apply { errorMessage = unique.text }) - + "Must have an owned [] within [] tiles" -> if (cityCenter.getTilesInDistance(unique.params[1].toInt()) .none { it.matchesFilter(unique.params[0], civInfo) && it.getOwner() == cityConstructions.cityInfo.civInfo } ) rejectionReasons.add(RejectionReason.MustOwnTile.apply { errorMessage = unique.text }) - + // Deprecated since 3.16.11 "Can only be built in annexed cities" -> if ( @@ -463,15 +465,15 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { ) rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text }) // - + "Can only be built []" -> if (!cityConstructions.cityInfo.matchesFilter(unique.params[0])) rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text }) - + "Obsolete with []" -> if (civInfo.tech.isResearched(unique.params[0])) rejectionReasons.add(RejectionReason.Obsoleted.apply { errorMessage = unique.text }) - + Constants.hiddenWithoutReligionUnique -> if (!civInfo.gameInfo.isReligionEnabled()) rejectionReasons.add(RejectionReason.DisabledBySetting) @@ -480,10 +482,10 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { if (uniqueTo != null && uniqueTo != civInfo.civName) rejectionReasons.add(RejectionReason.UniqueToOtherNation.apply { errorMessage = "Unique to $uniqueTo"}) - + if (civInfo.gameInfo.ruleSet.buildings.values.any { it.uniqueTo == civInfo.civName && it.replaces == name }) rejectionReasons.add(RejectionReason.ReplacedByOurUnique) - + if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) rejectionReasons.add(RejectionReason.RequiresTech.apply { "$requiredTech not researched!"}) @@ -527,7 +529,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { if (isNationalWonder) { if (civInfo.cities.any { it.cityConstructions.isBuilt(name) }) rejectionReasons.add(RejectionReason.NationalWonderAlreadyBuilt) - + if (requiredBuildingInAllCities != null && civInfo.gameInfo.ruleSet.buildings[requiredBuildingInAllCities!!] == null) { rejectionReasons.add(RejectionReason.InvalidRequiredBuilding) } else { @@ -540,10 +542,10 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { rejectionReasons.add(RejectionReason.RequiresBuildingInAllCities .apply { errorMessage = "Requires a [${civInfo.getEquivalentBuilding(requiredBuildingInAllCities!!)}] in all cities"}) } - + if (civInfo.cities.any { it != cityConstructions.cityInfo && it.cityConstructions.isBeingConstructedOrEnqueued(name) }) rejectionReasons.add(RejectionReason.NationalWonderBeingBuiltElsewhere) - + if (civInfo.isCityState()) rejectionReasons.add(RejectionReason.CityStateNationalWonder) } @@ -554,7 +556,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { rejectionReasons.add( RejectionReason.RequiresBuildingInSomeCity.apply { errorMessage = "Apollo project not built!" } ) - + if (civInfo.victoryManager.unconstructedSpaceshipParts()[name] == 0) rejectionReasons.add(RejectionReason.ReachedBuildCap) } @@ -584,7 +586,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { ) } } - + "Hidden until [] social policy branches have been completed" -> { if (cityConstructions.cityInfo.civInfo.getCompletedPolicyBranchesCount() < unique.params[0].toInt()) rejectionReasons.add(RejectionReason.MorePolicyBranches.apply { errorMessage = unique.text }) @@ -633,7 +635,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { if (!containsResourceWithImprovement) rejectionReasons.add(RejectionReason.RequiresNearbyResource.apply { errorMessage = "Nearby $requiredNearbyImprovedResources required" }) } - + return rejectionReasons } diff --git a/core/src/com/unciv/models/ruleset/Nation.kt b/core/src/com/unciv/models/ruleset/Nation.kt index 3f5702de6b..c94aab4a4e 100644 --- a/core/src/com/unciv/models/ruleset/Nation.kt +++ b/core/src/com/unciv/models/ruleset/Nation.kt @@ -99,104 +99,6 @@ class Nation : INamed, ICivilopediaText, IHasUniques { var cities: ArrayList = arrayListOf() - /** Used only by NewGame Nation picker */ - fun getUniqueString(ruleset: Ruleset): String { - val textList = ArrayList() - - if (uniqueName != "") textList += uniqueName.tr() + ":" - if (uniqueText != "") { - textList += " " + uniqueText.tr() - } else { - textList += " " + uniques.joinToString(", ") { it.tr() } - textList += "" - } - - if (startBias.isNotEmpty()) { - textList += "Start bias:".tr() + startBias.joinToString(", ", " ") { it.tr() } - textList += "" - } - addUniqueBuildingsText(textList, ruleset) - addUniqueUnitsText(textList, ruleset) - addUniqueImprovementsText(textList, ruleset) - - return textList.joinToString("\n") - } - - private fun addUniqueBuildingsText(textList: ArrayList, ruleset: Ruleset) { - for (building in ruleset.buildings.values - .filter { it.uniqueTo == name && Constants.hideFromCivilopediaUnique !in it.uniques }) { - if (building.replaces != null && ruleset.buildings.containsKey(building.replaces!!)) { - val originalBuilding = ruleset.buildings[building.replaces!!]!! - - textList += building.name.tr() + " - " + "Replaces [${originalBuilding.name}]".tr() - for ((key, value) in building) - if (value != originalBuilding[key]) - textList += " " + key.name.tr() + " " + "[${value.toInt()}] vs [${originalBuilding[key].toInt()}]".tr() - - for (unique in building.uniques.filter { it !in originalBuilding.uniques }) - textList += " " + unique.tr() - if (building.maintenance != originalBuilding.maintenance) - textList += " {Maintenance} " + "[${building.maintenance}] vs [${originalBuilding.maintenance}]".tr() - if (building.cost != originalBuilding.cost) - textList += " {Cost} " + "[${building.cost}] vs [${originalBuilding.cost}]".tr() - if (building.cityStrength != originalBuilding.cityStrength) - textList += " {City strength} " + "[${building.cityStrength}] vs [${originalBuilding.cityStrength}]".tr() - if (building.cityHealth != originalBuilding.cityHealth) - textList += " {City health} " + "[${building.cityHealth}] vs [${originalBuilding.cityHealth}]".tr() - textList += "" - } else if (building.replaces != null) { - textList += building.name.tr() + " - " + "Replaces [${building.replaces}], which is not found in the ruleset!".tr() - } else textList += building.getShortDescription(ruleset) - } - } - - private fun addUniqueUnitsText(textList: ArrayList, ruleset: Ruleset) { - for (unit in ruleset.units.values - .filter { it.uniqueTo == name && Constants.hideFromCivilopediaUnique !in it.uniques }) { - if (unit.replaces != null && ruleset.units.containsKey(unit.replaces!!)) { - val originalUnit = ruleset.units[unit.replaces!!]!! - textList += unit.name.tr() + " - " + "Replaces [${originalUnit.name}]".tr() - if (unit.cost != originalUnit.cost) - textList += " {Cost} " + "[${unit.cost}] vs [${originalUnit.cost}]".tr() - if (unit.strength != originalUnit.strength) - textList += " ${Fonts.strength} " + "[${unit.strength}] vs [${originalUnit.strength}]".tr() - if (unit.rangedStrength != originalUnit.rangedStrength) - textList += " ${Fonts.rangedStrength} " + "[${unit.rangedStrength}] vs [${originalUnit.rangedStrength}]".tr() - if (unit.range != originalUnit.range) - textList += " ${Fonts.range} " + "[${unit.range}] vs [${originalUnit.range}]".tr() - if (unit.movement != originalUnit.movement) - textList += " ${Fonts.movement} " + "[${unit.movement}] vs [${originalUnit.movement}]".tr() - for (resource in originalUnit.getResourceRequirements().keys) - if (!unit.getResourceRequirements().containsKey(resource)) - textList += " " + "[$resource] not required".tr() - for (unique in unit.uniques.filterNot { it in originalUnit.uniques }) - textList += " " + unique.tr() - for (unique in originalUnit.uniques.filterNot { it in unit.uniques }) - textList += " " + "Lost ability".tr() + "(" + "vs [${originalUnit.name}]".tr() + "): " + unique.tr() - for (promotion in unit.promotions.filter { it !in originalUnit.promotions }) - textList += " " + promotion.tr() + " (" + ruleset.unitPromotions[promotion]!!.uniquesWithEffect().joinToString(",") { it.tr() } + ")" - } else if (unit.replaces != null) { - textList += unit.name.tr() + " - " + "Replaces [${unit.replaces}], which is not found in the ruleset!".tr() - } else { - textList += unit.name.tr() - textList += " " + unit.getDescription().split("\n").joinToString("\n ") - } - - textList += "" - } - } - - private fun addUniqueImprovementsText(textList: ArrayList, ruleset: Ruleset) { - for (improvement in ruleset.tileImprovements.values - .filter { it.uniqueTo == name }) { - - textList += improvement.name.tr() - textList += " " + improvement.clone().toString() - for (unique in improvement.uniques) - textList += " " + unique.tr() - } - } - override fun makeLink() = "Nation/$name" override fun getSortGroup(ruleset: Ruleset) = when { isCityState() -> 1 @@ -250,8 +152,11 @@ class Nation : INamed, ICivilopediaText, IHasUniques { val textList = ArrayList() textList += FormattedLine("Type: [$cityStateType]", header = 4, color = cityStateType!!.color) - val viewingCiv = UncivGame.Current.gameInfo.currentPlayerCiv - val era = viewingCiv.getEra() + + val era = if (UncivGame.isCurrentInitialized() && UncivGame.Current.isGameInfoInitialized()) + UncivGame.Current.gameInfo.currentPlayerCiv.getEra() + else + ruleset.eras.values.first() var showResources = false val friendBonus = era.friendBonus[cityStateType!!.name] @@ -292,7 +197,6 @@ class Nation : INamed, ICivilopediaText, IHasUniques { return textList } - @JvmName("addUniqueBuildingsText1") // These overloads are too similar - but I hope to remove the other one soon private fun addUniqueBuildingsText(textList: ArrayList, ruleset: Ruleset) { for (building in ruleset.buildings.values) { if (building.uniqueTo != name || Constants.hideFromCivilopediaUnique in building.uniques) continue @@ -324,7 +228,6 @@ class Nation : INamed, ICivilopediaText, IHasUniques { } } - @JvmName("addUniqueUnitsText1") private fun addUniqueUnitsText(textList: ArrayList, ruleset: Ruleset) { for (unit in ruleset.units.values) { if (unit.uniqueTo != name || Constants.hideFromCivilopediaUnique in unit.uniques) continue @@ -373,7 +276,6 @@ class Nation : INamed, ICivilopediaText, IHasUniques { } } - @JvmName("addUniqueImprovementsText1") private fun addUniqueImprovementsText(textList: ArrayList, ruleset: Ruleset) { for (improvement in ruleset.tileImprovements.values) { if (improvement.uniqueTo != name ) continue diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index 9bd45ff2d3..423e644b2a 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -165,8 +165,15 @@ class TileImprovement : NamedStats(), ICivilopediaText, IHasUniques { } if (isAncientRuinsEquivalent() && ruleset.ruinRewards.isNotEmpty()) { - val difficulty = UncivGame.Current.gameInfo.gameParameters.difficulty - val religionEnabled = UncivGame.Current.gameInfo.isReligionEnabled() + val difficulty: String + val religionEnabled: Boolean + if (UncivGame.isCurrentInitialized() && UncivGame.Current.isGameInfoInitialized()) { + difficulty = UncivGame.Current.gameInfo.gameParameters.difficulty + religionEnabled = UncivGame.Current.gameInfo.isReligionEnabled() + } else { + difficulty = "Prince" // most factors == 1 + religionEnabled = true + } textList += FormattedLine() textList += FormattedLine("The possible rewards are:") ruleset.ruinRewards.values.asSequence() diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index ecbfd9ba20..ce8a68cd0a 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -1,7 +1,6 @@ package com.unciv.models.ruleset.unit import com.unciv.Constants -import com.unciv.UncivGame import com.unciv.logic.city.* import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.map.MapUnit @@ -127,8 +126,11 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText { if (cost > 0) { stats.clear() stats += "$cost${Fonts.production}" - if (canBePurchasedWithStat(null, Stat.Gold)) - stats += "${getBaseGoldCost(UncivGame.Current.gameInfo.currentPlayerCiv).toInt() / 10 * 10}${Fonts.gold}" + if (canBePurchasedWithStat(null, Stat.Gold)) { + // We need what INonPerpetualConstruction.getBaseGoldCost calculates but without any game- or civ-specific modifiers + val buyCost = 30.0 * cost.toFloat().pow(0.75f) * hurryCostModifier.toPercent() / 10 * 10 + stats += "$buyCost${Fonts.gold}" + } textList += FormattedLine(stats.joinToString(", ", "{Cost}: ")) } @@ -272,10 +274,10 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText { && it.params[2] == stat.name } ) return true - + return super.canBePurchasedWithStat(cityInfo, stat) } - + private fun getCostForConstructionsIncreasingInPrice(baseCost: Int, increaseCost: Int, previouslyBought: Int): Int { return (baseCost + increaseCost / 2f * ( previouslyBought * previouslyBought + previouslyBought )).toInt() } @@ -314,7 +316,7 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText { ) ).minOrNull() } - + override fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int? { var cost = getBaseBuyCost(cityInfo, stat)?.toDouble() if (cost == null) return null diff --git a/core/src/com/unciv/ui/civilopedia/CivilopediaText.kt b/core/src/com/unciv/ui/civilopedia/CivilopediaText.kt index 17c6533a29..68a78b7207 100644 --- a/core/src/com/unciv/ui/civilopedia/CivilopediaText.kt +++ b/core/src/com/unciv/ui/civilopedia/CivilopediaText.kt @@ -434,6 +434,9 @@ interface ICivilopediaText { /** Generate automatic lines from object metadata. * + * Please do not rely on a UncivGame.Current.gameInfo being initialized, this should be able to run from the main menu. + * (And the info displayed should be about the **ruleset**, not the player situation) + * * Default implementation is empty - no need to call super in overrides. * * @param ruleset The current ruleset for the Civilopedia viewer