Fixed starting positions not activating on new game

This commit is contained in:
Yair Morgenstern 2020-12-21 20:56:02 +02:00
parent 213e71a97b
commit 4e62d0b722
2 changed files with 62 additions and 53 deletions

View File

@ -260,7 +260,8 @@ class GameInfo {
for (tile in tileMap.values) { for (tile in tileMap.values) {
if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!)) if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!))
tile.resource = null 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 tile.improvement = null
for (unit in tile.getUnits()) for (unit in tile.getUnits())

View File

@ -35,27 +35,31 @@ class Building : NamedStats(), IConstruction {
} }
return counter return counter
} }
var greatPersonPoints: Stats? = null var greatPersonPoints: Stats? = null
/** Extra cost percentage when purchasing */ /** Extra cost percentage when purchasing */
private var hurryCostModifier = 0 private var hurryCostModifier = 0
var isWonder = false var isWonder = false
var isNationalWonder = false var isNationalWonder = false
private var requiredBuilding: String? = null private var requiredBuilding: String? = null
var requiredBuildingInAllCities: String? = null var requiredBuildingInAllCities: String? = null
/** A strategic resource that will be consumed by this building */ /** A strategic resource that will be consumed by this building */
var requiredResource: String? = null var requiredResource: String? = null
/** City can only be built if one of these resources is nearby - it must be improved! */ /** City can only be built if one of these resources is nearby - it must be improved! */
private var requiredNearbyImprovedResources: List<String>? = null private var requiredNearbyImprovedResources: List<String>? = null
private var cannotBeBuiltWith: String? = null private var cannotBeBuiltWith: String? = null
var cityStrength=0 var cityStrength = 0
var cityHealth=0 var cityHealth = 0
var xpForNewUnits=0 var xpForNewUnits = 0
var replaces:String?=null var replaces: String? = null
var uniqueTo:String?=null var uniqueTo: String? = null
var quote:String="" var quote: String = ""
private var providesFreeBuilding: String? = null private var providesFreeBuilding: String? = null
var uniques = ArrayList<String>() var uniques = ArrayList<String>()
val uniqueObjects:List<Unique> by lazy { uniques.map { Unique(it) } } val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
/** /**
* The bonus stats that a resource gets when this building is built * The bonus stats that a resource gets when this building is built
@ -63,44 +67,44 @@ class Building : NamedStats(), IConstruction {
var resourceBonusStats: Stats? = null var resourceBonusStats: Stats? = null
fun getShortDescription(ruleset: Ruleset): String { // should fit in one line fun getShortDescription(ruleset: Ruleset): String { // should fit in one line
val infoList= mutableListOf<String>() val infoList = mutableListOf<String>()
val str = getStats(null).toString() val str = getStats(null).toString()
if(str.isNotEmpty()) infoList += str if (str.isNotEmpty()) infoList += str
for(stat in getStatPercentageBonuses(null).toHashMap()) for (stat in getStatPercentageBonuses(null).toHashMap())
if(stat.value!=0f) infoList+="+${stat.value.toInt()}% ${stat.key.toString().tr()}" 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() } val improvedResources = ruleset.tileResources.values.filter { it.building == name }.map { it.name.tr() }
if(improvedResources.isNotEmpty()){ if (improvedResources.isNotEmpty()) {
// buildings that improve resources // buildings that improve resources
infoList += improvedResources.joinToString()+ " {provide} ".tr()+ resourceBonusStats.toString() infoList += improvedResources.joinToString() + " {provide} ".tr() + resourceBonusStats.toString()
} }
if(requiredNearbyImprovedResources!=null) if (requiredNearbyImprovedResources != null)
infoList += ("Requires worked ["+requiredNearbyImprovedResources!!.joinToString("/"){it.tr()}+"] near city").tr() infoList += ("Requires worked [" + requiredNearbyImprovedResources!!.joinToString("/") { it.tr() } + "] near city").tr()
if(uniques.isNotEmpty()) infoList += uniques.joinToString { it.tr() } if (uniques.isNotEmpty()) infoList += uniques.joinToString { it.tr() }
if(cityStrength!=0) infoList+="{City strength} +".tr()+cityStrength if (cityStrength != 0) infoList += "{City strength} +".tr() + cityStrength
if(cityHealth!=0) infoList+="{City health} +".tr()+cityHealth if (cityHealth != 0) infoList += "{City health} +".tr() + cityHealth
if(xpForNewUnits!=0) infoList+= "+$xpForNewUnits {XP for new units}".tr() if (xpForNewUnits != 0) infoList += "+$xpForNewUnits {XP for new units}".tr()
return infoList.joinToString() return infoList.joinToString()
} }
fun getDescription(forBuildingPickerScreen: Boolean, civInfo: CivilizationInfo?, ruleset: Ruleset): String { fun getDescription(forBuildingPickerScreen: Boolean, civInfo: CivilizationInfo?, ruleset: Ruleset): String {
val stats = getStats(civInfo) val stats = getStats(civInfo)
val stringBuilder = StringBuilder() 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 (!forBuildingPickerScreen) stringBuilder.appendln("{Cost}: $cost".tr())
if (isWonder) stringBuilder.appendln("Wonder".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) if (!forBuildingPickerScreen && requiredTech != null)
stringBuilder.appendln("Required tech: [$requiredTech]".tr()) stringBuilder.appendln("Required tech: [$requiredTech]".tr())
if (!forBuildingPickerScreen && requiredBuilding != null) if (!forBuildingPickerScreen && requiredBuilding != null)
stringBuilder.appendln("Requires [$requiredBuilding] to be built in the city".tr()) stringBuilder.appendln("Requires [$requiredBuilding] to be built in the city".tr())
if (!forBuildingPickerScreen && requiredBuildingInAllCities != null) if (!forBuildingPickerScreen && requiredBuildingInAllCities != null)
stringBuilder.appendln("Requires [$requiredBuildingInAllCities] to be built in all cities".tr()) stringBuilder.appendln("Requires [$requiredBuildingInAllCities] to be built in all cities".tr())
if(requiredResource!=null) if (requiredResource != null)
stringBuilder.appendln("Consumes 1 [$requiredResource]".tr()) stringBuilder.appendln("Consumes 1 [$requiredResource]".tr())
if (providesFreeBuilding != null) if (providesFreeBuilding != null)
stringBuilder.appendln("Provides a free [$providesFreeBuilding] in the city".tr()) 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()) if (!stats.isEmpty())
stringBuilder.appendln(stats) stringBuilder.appendln(stats)
@ -113,26 +117,26 @@ class Building : NamedStats(), IConstruction {
if (this.greatPersonPoints != null) { if (this.greatPersonPoints != null) {
val gpp = this.greatPersonPoints!! val gpp = this.greatPersonPoints!!
if (gpp.production != 0f) stringBuilder.appendln("+" + gpp.production.toInt()+" " + "[Great Engineer] 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.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.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.culture != 0f) stringBuilder.appendln("+" + gpp.culture.toInt() + " " + "[Great Artist] points".tr())
} }
for((specialistName, amount) in newSpecialists()) for ((specialistName, amount) in newSpecialists())
stringBuilder.appendln("+$amount "+"[$specialistName] slots".tr()) stringBuilder.appendln("+$amount " + "[$specialistName] slots".tr())
if (resourceBonusStats != null) { if (resourceBonusStats != null) {
val resources = ruleset.tileResources.values.filter { name == it.building }.joinToString { it.name.tr() } val resources = ruleset.tileResources.values.filter { name == it.building }.joinToString { it.name.tr() }
stringBuilder.appendln("$resources {provide} $resourceBonusStats".tr()) stringBuilder.appendln("$resources {provide} $resourceBonusStats".tr())
} }
if(requiredNearbyImprovedResources!=null) if (requiredNearbyImprovedResources != null)
stringBuilder.appendln(("Requires worked ["+requiredNearbyImprovedResources!!.joinToString("/"){it.tr()}+"] near city").tr()) stringBuilder.appendln(("Requires worked [" + requiredNearbyImprovedResources!!.joinToString("/") { it.tr() } + "] near city").tr())
if(cityStrength!=0) stringBuilder.appendln("{City strength} +".tr() + cityStrength) if (cityStrength != 0) stringBuilder.appendln("{City strength} +".tr() + cityStrength)
if(cityHealth!=0) stringBuilder.appendln("{City health} +".tr() + cityHealth) if (cityHealth != 0) stringBuilder.appendln("{City health} +".tr() + cityHealth)
if(xpForNewUnits!=0) stringBuilder.appendln("+$xpForNewUnits {XP for new units}".tr()) if (xpForNewUnits != 0) stringBuilder.appendln("+$xpForNewUnits {XP for new units}".tr())
if (maintenance != 0) if (maintenance != 0)
stringBuilder.appendln("{Maintenance cost}: $maintenance {Gold}".tr()) stringBuilder.appendln("{Maintenance cost}: $maintenance {Gold}".tr())
return stringBuilder.toString().trim() return stringBuilder.toString().trim()
@ -198,7 +202,7 @@ class Building : NamedStats(), IConstruction {
if (!isWonder) if (!isWonder)
productionCost *= civInfo.getDifficulty().buildingCostModifier productionCost *= civInfo.getDifficulty().buildingCostModifier
} else { } else {
productionCost *= if(isWonder) productionCost *= if (isWonder)
civInfo.gameInfo.getDifficulty().aiWonderCostModifier civInfo.gameInfo.getDifficulty().aiWonderCostModifier
else else
civInfo.gameInfo.getDifficulty().aiBuildingCostModifier civInfo.gameInfo.getDifficulty().aiBuildingCostModifier
@ -228,13 +232,13 @@ class Building : NamedStats(), IConstruction {
if (cityConstructions.isBeingConstructedOrEnqueued(name)) if (cityConstructions.isBeingConstructedOrEnqueued(name))
return false return false
val rejectionReason = getRejectionReason(cityConstructions) val rejectionReason = getRejectionReason(cityConstructions)
return rejectionReason=="" return rejectionReason == ""
|| rejectionReason.startsWith("Requires") || rejectionReason.startsWith("Requires")
|| rejectionReason.startsWith("Consumes") || rejectionReason.startsWith("Consumes")
|| rejectionReason == "Wonder is being built elsewhere" || rejectionReason == "Wonder is being built elsewhere"
} }
fun getRejectionReason(construction: CityConstructions):String { fun getRejectionReason(construction: CityConstructions): String {
if (construction.isBuilt(name)) return "Already built" if (construction.isBuilt(name)) return "Already built"
// for buildings that are created as side effects of other things, and not directly built // for buildings that are created as side effects of other things, and not directly built
if (uniques.contains("Unbuildable")) return "Unbuildable" if (uniques.contains("Unbuildable")) return "Unbuildable"
@ -243,28 +247,32 @@ class Building : NamedStats(), IConstruction {
val civInfo = construction.cityInfo.civInfo val civInfo = construction.cityInfo.civInfo
// This overrides the others // This overrides the others
if(uniqueObjects.any { it.placeholderText=="Not displayed as an available construction unless [] is built" if (uniqueObjects.any {
&& !construction.containsBuildingOrEquivalent(it.params[0])} ) it.placeholderText == "Not displayed as an available construction unless [] is built"
&& !construction.containsBuildingOrEquivalent(it.params[0])
})
return "Should not be displayed" 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] val filter = unique.params[0]
if ((filter in civInfo.gameInfo.ruleSet.tileResources && !construction.cityInfo.civInfo.hasResource(filter)) if ((filter in civInfo.gameInfo.ruleSet.tileResources && !construction.cityInfo.civInfo.hasResource(filter))
|| (filter in civInfo.gameInfo.ruleSet.buildings && !construction.containsBuildingOrEquivalent(filter))) || (filter in civInfo.gameInfo.ruleSet.buildings && !construction.containsBuildingOrEquivalent(filter)))
return "Should not be displayed" 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 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 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.. "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 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 { "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 == "" "Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == ""
|| construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text || 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 (filter in civInfo.gameInfo.ruleSet.buildings) {
if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) }) return unique.text // Wonder is not built 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 } 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])) "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 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 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 "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 "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 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 "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" if (uniqueTo != null && uniqueTo != civInfo.civName) return "Unique to $uniqueTo"
@ -357,7 +365,7 @@ class Building : NamedStats(), IConstruction {
} }
override fun isBuildable(cityConstructions: CityConstructions): Boolean { override fun isBuildable(cityConstructions: CityConstructions): Boolean {
return getRejectionReason(cityConstructions)=="" return getRejectionReason(cityConstructions) == ""
} }
override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean { override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean {
@ -400,8 +408,8 @@ class Building : NamedStats(), IConstruction {
fun isStatRelated(stat: Stat): Boolean { fun isStatRelated(stat: Stat): Boolean {
if (get(stat) > 0) return true if (get(stat) > 0) return true
if (getStatPercentageBonuses(null).get(stat)>0) return true if (getStatPercentageBonuses(null).get(stat) > 0) return true
if(resourceBonusStats!=null && resourceBonusStats!!.get(stat)>0) return true if (resourceBonusStats != null && resourceBonusStats!!.get(stat) > 0) return true
return false return false
} }
@ -409,4 +417,4 @@ class Building : NamedStats(), IConstruction {
if (replaces == null) return this if (replaces == null) return this
else return ruleset.buildings[replaces!!]!! else return ruleset.buildings[replaces!!]!!
} }
} }