From 4e62d0b722e195d662a88dd51fa87a41a681cde5 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Mon, 21 Dec 2020 20:56:02 +0200 Subject: [PATCH] Fixed starting positions not activating on new game --- core/src/com/unciv/logic/GameInfo.kt | 3 +- core/src/com/unciv/models/ruleset/Building.kt | 112 ++++++++++-------- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 383954778f..5f6a8d8c4a 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -260,7 +260,8 @@ class GameInfo { for (tile in tileMap.values) { if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!)) tile.resource = null - if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!)) + if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!) + && !tile.improvement!!.startsWith("StartingLocation ")) // To not remove the starting locations in GameStarter.startNewGame() tile.improvement = null for (unit in tile.getUnits()) diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index 8dc43b6289..10d662d974 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -35,27 +35,31 @@ class Building : NamedStats(), IConstruction { } return counter } + var greatPersonPoints: Stats? = null + /** Extra cost percentage when purchasing */ private var hurryCostModifier = 0 var isWonder = false var isNationalWonder = false private var requiredBuilding: String? = null var requiredBuildingInAllCities: String? = null + /** A strategic resource that will be consumed by this building */ var requiredResource: String? = null + /** City can only be built if one of these resources is nearby - it must be improved! */ private var requiredNearbyImprovedResources: List? = null private var cannotBeBuiltWith: String? = null - var cityStrength=0 - var cityHealth=0 - var xpForNewUnits=0 - var replaces:String?=null - var uniqueTo:String?=null - var quote:String="" + var cityStrength = 0 + var cityHealth = 0 + var xpForNewUnits = 0 + var replaces: String? = null + var uniqueTo: String? = null + var quote: String = "" private var providesFreeBuilding: String? = null var uniques = ArrayList() - val uniqueObjects:List by lazy { uniques.map { Unique(it) } } + val uniqueObjects: List by lazy { uniques.map { Unique(it) } } /** * The bonus stats that a resource gets when this building is built @@ -63,44 +67,44 @@ class Building : NamedStats(), IConstruction { var resourceBonusStats: Stats? = null fun getShortDescription(ruleset: Ruleset): String { // should fit in one line - val infoList= mutableListOf() + val infoList = mutableListOf() val str = getStats(null).toString() - if(str.isNotEmpty()) infoList += str - for(stat in getStatPercentageBonuses(null).toHashMap()) - if(stat.value!=0f) infoList+="+${stat.value.toInt()}% ${stat.key.toString().tr()}" + if (str.isNotEmpty()) infoList += str + for (stat in getStatPercentageBonuses(null).toHashMap()) + if (stat.value != 0f) infoList += "+${stat.value.toInt()}% ${stat.key.toString().tr()}" - val improvedResources = ruleset.tileResources.values.filter { it.building==name }.map { it.name.tr() } - if(improvedResources.isNotEmpty()){ + val improvedResources = ruleset.tileResources.values.filter { it.building == name }.map { it.name.tr() } + if (improvedResources.isNotEmpty()) { // buildings that improve resources - infoList += improvedResources.joinToString()+ " {provide} ".tr()+ resourceBonusStats.toString() + infoList += improvedResources.joinToString() + " {provide} ".tr() + resourceBonusStats.toString() } - if(requiredNearbyImprovedResources!=null) - infoList += ("Requires worked ["+requiredNearbyImprovedResources!!.joinToString("/"){it.tr()}+"] near city").tr() - if(uniques.isNotEmpty()) infoList += uniques.joinToString { it.tr() } - if(cityStrength!=0) infoList+="{City strength} +".tr()+cityStrength - if(cityHealth!=0) infoList+="{City health} +".tr()+cityHealth - if(xpForNewUnits!=0) infoList+= "+$xpForNewUnits {XP for new units}".tr() + if (requiredNearbyImprovedResources != null) + infoList += ("Requires worked [" + requiredNearbyImprovedResources!!.joinToString("/") { it.tr() } + "] near city").tr() + if (uniques.isNotEmpty()) infoList += uniques.joinToString { it.tr() } + if (cityStrength != 0) infoList += "{City strength} +".tr() + cityStrength + if (cityHealth != 0) infoList += "{City health} +".tr() + cityHealth + if (xpForNewUnits != 0) infoList += "+$xpForNewUnits {XP for new units}".tr() return infoList.joinToString() } fun getDescription(forBuildingPickerScreen: Boolean, civInfo: CivilizationInfo?, ruleset: Ruleset): String { val stats = getStats(civInfo) val stringBuilder = StringBuilder() - if(uniqueTo!=null) stringBuilder.appendln("Unique to [$uniqueTo], replaces [$replaces]".tr()) + if (uniqueTo != null) stringBuilder.appendln("Unique to [$uniqueTo], replaces [$replaces]".tr()) if (!forBuildingPickerScreen) stringBuilder.appendln("{Cost}: $cost".tr()) if (isWonder) stringBuilder.appendln("Wonder".tr()) - if(isNationalWonder) stringBuilder.appendln("National Wonder".tr()) + if (isNationalWonder) stringBuilder.appendln("National Wonder".tr()) if (!forBuildingPickerScreen && requiredTech != null) stringBuilder.appendln("Required tech: [$requiredTech]".tr()) if (!forBuildingPickerScreen && requiredBuilding != null) stringBuilder.appendln("Requires [$requiredBuilding] to be built in the city".tr()) if (!forBuildingPickerScreen && requiredBuildingInAllCities != null) stringBuilder.appendln("Requires [$requiredBuildingInAllCities] to be built in all cities".tr()) - if(requiredResource!=null) + if (requiredResource != null) stringBuilder.appendln("Consumes 1 [$requiredResource]".tr()) if (providesFreeBuilding != null) stringBuilder.appendln("Provides a free [$providesFreeBuilding] in the city".tr()) - if(uniques.isNotEmpty()) stringBuilder.appendln(uniques.asSequence().map { it.tr() }.joinToString("\n")) + if (uniques.isNotEmpty()) stringBuilder.appendln(uniques.asSequence().map { it.tr() }.joinToString("\n")) if (!stats.isEmpty()) stringBuilder.appendln(stats) @@ -113,26 +117,26 @@ class Building : NamedStats(), IConstruction { if (this.greatPersonPoints != null) { val gpp = this.greatPersonPoints!! - if (gpp.production != 0f) stringBuilder.appendln("+" + gpp.production.toInt()+" " + "[Great Engineer] points".tr()) - if (gpp.gold != 0f) stringBuilder.appendln("+" + gpp.gold.toInt() + " "+"[Great Merchant] points".tr()) - if (gpp.science != 0f) stringBuilder.appendln("+" + gpp.science.toInt() + " "+"[Great Scientist] points".tr()) - if (gpp.culture != 0f) stringBuilder.appendln("+" + gpp.culture.toInt() + " "+"[Great Artist] points".tr()) + if (gpp.production != 0f) stringBuilder.appendln("+" + gpp.production.toInt() + " " + "[Great Engineer] points".tr()) + if (gpp.gold != 0f) stringBuilder.appendln("+" + gpp.gold.toInt() + " " + "[Great Merchant] points".tr()) + if (gpp.science != 0f) stringBuilder.appendln("+" + gpp.science.toInt() + " " + "[Great Scientist] points".tr()) + if (gpp.culture != 0f) stringBuilder.appendln("+" + gpp.culture.toInt() + " " + "[Great Artist] points".tr()) } - for((specialistName, amount) in newSpecialists()) - stringBuilder.appendln("+$amount "+"[$specialistName] slots".tr()) + for ((specialistName, amount) in newSpecialists()) + stringBuilder.appendln("+$amount " + "[$specialistName] slots".tr()) if (resourceBonusStats != null) { val resources = ruleset.tileResources.values.filter { name == it.building }.joinToString { it.name.tr() } stringBuilder.appendln("$resources {provide} $resourceBonusStats".tr()) } - if(requiredNearbyImprovedResources!=null) - stringBuilder.appendln(("Requires worked ["+requiredNearbyImprovedResources!!.joinToString("/"){it.tr()}+"] near city").tr()) + if (requiredNearbyImprovedResources != null) + stringBuilder.appendln(("Requires worked [" + requiredNearbyImprovedResources!!.joinToString("/") { it.tr() } + "] near city").tr()) - if(cityStrength!=0) stringBuilder.appendln("{City strength} +".tr() + cityStrength) - if(cityHealth!=0) stringBuilder.appendln("{City health} +".tr() + cityHealth) - if(xpForNewUnits!=0) stringBuilder.appendln("+$xpForNewUnits {XP for new units}".tr()) + if (cityStrength != 0) stringBuilder.appendln("{City strength} +".tr() + cityStrength) + if (cityHealth != 0) stringBuilder.appendln("{City health} +".tr() + cityHealth) + if (xpForNewUnits != 0) stringBuilder.appendln("+$xpForNewUnits {XP for new units}".tr()) if (maintenance != 0) stringBuilder.appendln("{Maintenance cost}: $maintenance {Gold}".tr()) return stringBuilder.toString().trim() @@ -198,7 +202,7 @@ class Building : NamedStats(), IConstruction { if (!isWonder) productionCost *= civInfo.getDifficulty().buildingCostModifier } else { - productionCost *= if(isWonder) + productionCost *= if (isWonder) civInfo.gameInfo.getDifficulty().aiWonderCostModifier else civInfo.gameInfo.getDifficulty().aiBuildingCostModifier @@ -228,13 +232,13 @@ class Building : NamedStats(), IConstruction { if (cityConstructions.isBeingConstructedOrEnqueued(name)) return false val rejectionReason = getRejectionReason(cityConstructions) - return rejectionReason=="" + return rejectionReason == "" || rejectionReason.startsWith("Requires") || rejectionReason.startsWith("Consumes") || rejectionReason == "Wonder is being built elsewhere" } - fun getRejectionReason(construction: CityConstructions):String { + fun getRejectionReason(construction: CityConstructions): String { if (construction.isBuilt(name)) return "Already built" // for buildings that are created as side effects of other things, and not directly built if (uniques.contains("Unbuildable")) return "Unbuildable" @@ -243,28 +247,32 @@ class Building : NamedStats(), IConstruction { val civInfo = construction.cityInfo.civInfo // This overrides the others - if(uniqueObjects.any { it.placeholderText=="Not displayed as an available construction unless [] is built" - && !construction.containsBuildingOrEquivalent(it.params[0])} ) + if (uniqueObjects.any { + it.placeholderText == "Not displayed as an available construction unless [] is built" + && !construction.containsBuildingOrEquivalent(it.params[0]) + }) return "Should not be displayed" - - for (unique in uniqueObjects.filter { it.placeholderText == "Not displayed as an available construction without []"}) { + + for (unique in uniqueObjects.filter { it.placeholderText == "Not displayed as an available construction without []" }) { val filter = unique.params[0] if ((filter in civInfo.gameInfo.ruleSet.tileResources && !construction.cityInfo.civInfo.hasResource(filter)) || (filter in civInfo.gameInfo.ruleSet.buildings && !construction.containsBuildingOrEquivalent(filter))) return "Should not be displayed" } - for(unique in uniqueObjects) when (unique.placeholderText) { + for (unique in uniqueObjects) when (unique.placeholderText) { "Must be on []" -> if (!cityCenter.matchesUniqueFilter(unique.params[0])) return unique.text "Must not be on []" -> if (cityCenter.matchesUniqueFilter(unique.params[0])) return unique.text "Must be next to []" -> if (!(unique.params[0] == "Fresh water" && cityCenter.isAdjacentToRiver()) // Fresh water is special, in that rivers are not tiles themselves but also fit the filter.. - && cityCenter.getTilesInDistance(1).none { it.matchesUniqueFilter(unique.params[0])}) return unique.text + && cityCenter.getTilesInDistance(1).none { it.matchesUniqueFilter(unique.params[0]) }) return unique.text "Must not be next to []" -> if (cityCenter.getTilesInDistance(1).any { it.matchesUniqueFilter(unique.params[0]) }) return unique.text "Must have an owned [] within [] tiles" -> if (cityCenter.getTilesInDistance(unique.params[1].toInt()).none { - it.matchesUniqueFilter(unique.params[0]) && it.getOwner() == construction.cityInfo.civInfo }) return unique.text + it.matchesUniqueFilter(unique.params[0]) && it.getOwner() == construction.cityInfo.civInfo + }) return unique.text "Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == "" || construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text - "Requires []" -> { val filter = unique.params[0] + "Requires []" -> { + val filter = unique.params[0] if (filter in civInfo.gameInfo.ruleSet.buildings) { if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) }) return unique.text // Wonder is not built } else if (!civInfo.policies.adoptedPolicies.contains(filter)) return "Policy is not adopted" // this reason should not be displayed @@ -273,7 +281,7 @@ class Building : NamedStats(), IConstruction { "Requires a [] in this city" -> if (!construction.containsBuildingOrEquivalent(unique.params[0])) return "Requires a [${civInfo.getEquivalentBuilding(unique.params[0])}] in this city" // replace with civ-specific building for user - "Requires a [] in all cities" -> if (civInfo.cities.any { !it.cityConstructions.containsBuildingOrEquivalent(unique.params[0]) } ) + "Requires a [] in all cities" -> if (civInfo.cities.any { !it.cityConstructions.containsBuildingOrEquivalent(unique.params[0]) }) return "Requires a [${civInfo.getEquivalentBuilding(unique.params[0])}] in all cities" // replace with civ-specific building for user "Obsolete with []" -> if (civInfo.tech.isResearched(unique.params[0])) return unique.text @@ -287,7 +295,7 @@ class Building : NamedStats(), IConstruction { "Can only be built in coastal cities" -> // Deprecated as of 3.10.8 . Use "Must be next to [Coast]" instead if (!cityCenter.isCoastalTile()) return unique.text "Must border a source of fresh water" -> // Deprecated as of 3.10.8 . Use "Must be next to [Fresh water]" instead - if (!cityCenter.isAdjacentToFreshwater) return unique.text + if (!cityCenter.isAdjacentToFreshwater) return unique.text } if (uniqueTo != null && uniqueTo != civInfo.civName) return "Unique to $uniqueTo" @@ -357,7 +365,7 @@ class Building : NamedStats(), IConstruction { } override fun isBuildable(cityConstructions: CityConstructions): Boolean { - return getRejectionReason(cityConstructions)=="" + return getRejectionReason(cityConstructions) == "" } override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean { @@ -400,8 +408,8 @@ class Building : NamedStats(), IConstruction { fun isStatRelated(stat: Stat): Boolean { if (get(stat) > 0) return true - if (getStatPercentageBonuses(null).get(stat)>0) return true - if(resourceBonusStats!=null && resourceBonusStats!!.get(stat)>0) return true + if (getStatPercentageBonuses(null).get(stat) > 0) return true + if (resourceBonusStats != null && resourceBonusStats!!.get(stat) > 0) return true return false } @@ -409,4 +417,4 @@ class Building : NamedStats(), IConstruction { if (replaces == null) return this else return ruleset.buildings[replaces!!]!! } -} +} \ No newline at end of file