diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 05289aed8c..f5adadb3b1 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -764,6 +764,7 @@ Stopped population growth = In resistance for another [numberOfTurns] turns = Sell for [sellAmount] gold = Are you sure you want to sell this [building]? = +Free = [greatPerson] points = Great person points = Current points = diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index 39dc1074ae..452cfcdc89 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -325,7 +325,10 @@ object NextTurnAutomation { continue val buildingToSell = civInfo.gameInfo.ruleSet.buildings.values.filter { it.name in city.cityConstructions.builtBuildings - && it.requiresResource(resource) }.randomOrNull() + && it.requiresResource(resource) + && it.isSellable() + && it.name !in civInfo.civConstructions.getFreeBuildings(city.id) } + .randomOrNull() if (buildingToSell != null) { city.sellBuilding(buildingToSell.name) break diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 58fe2998ab..16db23e9ef 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -310,6 +310,9 @@ class CityInfo { } for (building in cityConstructions.getBuiltBuildings()) { + // Free buildings cost no resources + if (building.name in civInfo.civConstructions.getFreeBuildings(id)) + continue for ((resourceName, amount) in building.getResourceRequirements()) { val resource = getRuleset().tileResources[resourceName]!! cityResources.add(resource, -amount, "Buildings") diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index e8461b3720..8b772225b5 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -115,13 +115,17 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { fun getDescription(cityInfo: CityInfo?, ruleset: Ruleset): String { val stats = getStats(cityInfo) val lines = ArrayList() + val isFree = if (cityInfo == null) false + else (name in cityInfo.civInfo.civConstructions.getFreeBuildings(cityInfo.id)) if (uniqueTo != null) lines += if (replaces == null) "Unique to [$uniqueTo]" else "Unique to [$uniqueTo], replaces [$replaces]" if (isWonder) lines += "Wonder" if (isNationalWonder) lines += "National Wonder" - for ((resource, amount) in getResourceRequirements()) { - lines += if (amount == 1) "Consumes 1 [$resource]" // For now, to keep the existing translations - else "Consumes [$amount] [$resource]" + if (!isFree) { + for ((resource, amount) in getResourceRequirements()) { + lines += if (amount == 1) "Consumes 1 [$resource]" // For now, to keep the existing translations + else "Consumes [$amount] [$resource]" + } } if (uniques.isNotEmpty()) { if (replacementTextForUniques != "") lines += replacementTextForUniques @@ -144,7 +148,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { if (cityStrength != 0) lines += "{City strength} +$cityStrength" if (cityHealth != 0) lines += "{City health} +$cityHealth" - if (maintenance != 0) lines += "{Maintenance cost}: $maintenance {Gold}" + if (maintenance != 0 && !isFree) lines += "{Maintenance cost}: $maintenance {Gold}" return lines.joinToString("\n") { it.tr() }.trim() } diff --git a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt b/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt index 041051d273..647a6e02dc 100644 --- a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt @@ -63,11 +63,13 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS private fun addBuildingInfo(building: Building, destinationTable: Table) { val icon = ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f) - val buildingNameAndIconTable = ExpanderTab(building.name, 18, icon, false, 5f) { + val isFree = building.name in cityScreen.city.civInfo.civConstructions.getFreeBuildings(cityScreen.city.id) + val displayName = if (isFree) "{${building.name}} ({Free})" else building.name + val buildingNameAndIconTable = ExpanderTab(displayName, 18, icon, false, 5f) { val detailsString = building.getDescription(cityScreen.city, cityScreen.city.getRuleset()) it.add(detailsString.toLabel().apply { wrap = true }) .width(cityScreen.stage.width / 4 - 2 * pad).row() // when you set wrap, then you need to manually set the size of the label - if (building.isSellable()) { + if (building.isSellable() && !isFree) { val sellAmount = cityScreen.city.getGoldForSellingBuilding(building.name) val sellBuildingButton = "Sell for [$sellAmount] gold".toTextButton() it.add(sellBuildingButton).pad(5f).row()