Typed all remaining uniques using CityInfo.GetMatchingUniques and removed that function (#6071)

* Typed all remaining uniques using CityInfo.GetMatchingUniques and removed that function

* Fixed two NullPtrExceptions

* Fixed syntax
This commit is contained in:
Xander Lenstra 2022-01-29 22:27:48 +01:00 committed by GitHub
parent 39483d78bd
commit a237e7bf82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 205 additions and 103 deletions

View File

@ -123,7 +123,7 @@
{ {
"name": "Asceticism", "name": "Asceticism",
"type": "Follower", "type": "Follower",
"uniques": ["[+1 Happiness] from every [Shrine] in cities where this religion has at least [3] followers"] "uniques": ["[+1 Happiness] from every [Shrine] <in cities where this religion has at least [3] followers>"]
}, },
{ {
"name": "Cathedrals", "name": "Cathedrals",
@ -133,7 +133,7 @@
{ {
"name": "Choral Music", "name": "Choral Music",
"type": "Follower", "type": "Follower",
"uniques": ["[+2 Culture] from every [Temple] in cities where this religion has at least [5] followers"] "uniques": ["[+2 Culture] from every [Temple] <in cities where this religion has at least [5] followers>"]
}, },
{ {
"name": "Divine inspiration", "name": "Divine inspiration",
@ -158,7 +158,7 @@
{ {
"name": "Liturgical Drama", "name": "Liturgical Drama",
"type": "Follower", "type": "Follower",
"uniques": ["[+1 Faith] from every [Amphitheatre] in cities where this religion has at least [3] followers"] "uniques": ["[+1 Faith] from every [Amphitheatre] <in cities where this religion has at least [3] followers>"]
}, },
{ {
"name": "Monasteries", "name": "Monasteries",
@ -188,7 +188,7 @@
{ {
"name": "Religious Center", "name": "Religious Center",
"type": "Follower", "type": "Follower",
"uniques": ["[+2 Happiness] from every [Temple] in cities where this religion has at least [5] followers"] "uniques": ["[+2 Happiness] from every [Temple] <in cities where this religion has at least [5] followers>"]
}, },
{ {
"name": "Religious Community", "name": "Religious Community",
@ -285,12 +285,12 @@
{ {
"name": "Religious Texts", "name": "Religious Texts",
"type": "Enhancer", "type": "Enhancer",
"uniques": ["[+34]% Natural religion spread [in all cities]", "[+34]% Natural religion spread [in all cities] with [Printing Press]"] "uniques": ["[+34]% Natural religion spread [in all cities]", "[+34]% Natural religion spread [in all cities] <after discovering [Printing Press]>"]
}, },
{ {
"name": "Religious Unity", "name": "Religious Unity",
"type": "Enhancer", "type": "Enhancer",
"uniques": ["[+100]% Natural religion spread to [in City-State cities]"] "uniques": ["[+100]% Natural religion spread [in City-State cities]"]
}, },
{ {
"name": "Reliquary", "name": "Reliquary",

View File

@ -222,7 +222,7 @@
"innerColor": [238,201,9], "innerColor": [238,201,9],
"favoredReligion": "Christianity", "favoredReligion": "Christianity",
"uniqueName": "The Glory of Rome", "uniqueName": "The Glory of Rome",
"uniques": ["+25% Production towards any buildings that already exist in the Capital"], "uniques": ["[+25]% Production towards any buildings that already exist in the Capital"],
"cities": ["Rome","Antium","Cumae","Neapolis","Ravenna","Arretium","Mediolanum","Arpinum","Circei","Setia", "cities": ["Rome","Antium","Cumae","Neapolis","Ravenna","Arretium","Mediolanum","Arpinum","Circei","Setia",
"Satricum","Ardea","Ostia","Velitrae","Viroconium","Tarentum","Brundisium","Caesaraugusta","Caesarea","Palmyra", "Satricum","Ardea","Ostia","Velitrae","Viroconium","Tarentum","Brundisium","Caesaraugusta","Caesarea","Palmyra",
"Signia","Aquileia","Clusium","Sutrium","Cremona","Placentia","Hispalis","Artaxata","Aurelianorum","Nicopolis", "Signia","Aquileia","Clusium","Sutrium","Cremona","Placentia","Hispalis","Artaxata","Aurelianorum","Nicopolis",

View File

@ -214,7 +214,7 @@
"outerColor": [ 53,0,87], "outerColor": [ 53,0,87],
"innerColor": [238,201,9], "innerColor": [238,201,9],
"uniqueName": "The Glory of Rome", "uniqueName": "The Glory of Rome",
"uniques": ["+25% Production towards any buildings that already exist in the Capital"], "uniques": ["[+25]% Production towards any buildings that already exist in the Capital"],
"cities": ["Rome","Antium","Cumae","Neapolis","Ravenna","Arretium","Mediolanum","Arpinum","Circei","Setia", "cities": ["Rome","Antium","Cumae","Neapolis","Ravenna","Arretium","Mediolanum","Arpinum","Circei","Setia",
"Satricum","Ardea","Ostia","Velitrae","Viroconium","Tarentum","Brundisium","Caesaraugusta","Caesarea","Palmyra", "Satricum","Ardea","Ostia","Velitrae","Viroconium","Tarentum","Brundisium","Caesaraugusta","Caesarea","Palmyra",
"Signia","Aquileia","Clusium","Sutrium","Cremona","Placentia","Hispalis","Artaxata","Aurelianorum","Nicopolis", "Signia","Aquileia","Clusium","Sutrium","Cremona","Placentia","Hispalis","Artaxata","Aurelianorum","Nicopolis",

View File

@ -67,7 +67,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
addCultureBuildingChoice() addCultureBuildingChoice()
addSpaceshipPartChoice() addSpaceshipPartChoice()
addOtherBuildingChoice() addOtherBuildingChoice()
addReligousUnit() addReligiousUnit()
if (!cityInfo.isPuppet) { if (!cityInfo.isPuppet) {
addWondersChoice() addWondersChoice()
@ -342,9 +342,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
} }
} }
private fun addReligousUnit(){ private fun addReligiousUnit() {
// these 4 if conditions are used to determine if an AI should buy units to spread religion, or spend faith to buy things like new military units or new buildings. // these 4 if conditions are used to determine if an AI should buy units to spread religion, or spend faith to buy things like new military units or new buildings.
// currently this AI can only buy inquisitors and missionaries with faith // currently this AI can only buy inquisitors and missionaries with faith
// this system will have to be reengineered to support buying other stuff with faith // this system will have to be reengineered to support buying other stuff with faith

View File

@ -734,11 +734,11 @@ object Battle {
else -> 1f else -> 1f
} }
// Deprecated since 3.16.11 // Deprecated since 3.16.11
for (unique in targetedCity.getLocalMatchingUniques("Population loss from nuclear attacks -[]%")) { for (unique in targetedCity.getLocalMatchingUniques(UniqueType.PopulationLossFromNukesDeprecated)) {
populationLoss *= 1 - unique.params[0].toFloat() / 100f populationLoss *= 1 - unique.params[0].toFloat() / 100f
} }
// //
for (unique in targetedCity.getMatchingUniques("Population loss from nuclear attacks []% []")) { for (unique in targetedCity.getMatchingUniques(UniqueType.PopulationLossFromNukes)) {
if (!targetedCity.matchesFilter(unique.params[1])) continue if (!targetedCity.matchesFilter(unique.params[1])) continue
populationLoss *= unique.params[0].toPercent() populationLoss *= unique.params[0].toPercent()
} }

View File

@ -435,7 +435,9 @@ class CityInfo {
} }
var allGppPercentageBonus = 0 var allGppPercentageBonus = 0
for (unique in getMatchingUniques("[]% great person generation []")) { for (unique in getMatchingUniques(UniqueType.GreatPersonPointPercentage)
+ getMatchingUniques(UniqueType.GreatPersonPointPercentageDeprecated)
) {
if (!matchesFilter(unique.params[1])) continue if (!matchesFilter(unique.params[1])) continue
allGppPercentageBonus += unique.params[0].toInt() allGppPercentageBonus += unique.params[0].toInt()
} }
@ -484,6 +486,33 @@ class CityInfo {
200 + cityConstructions.getBuiltBuildings().sumOf { it.cityHealth } 200 + cityConstructions.getBuiltBuildings().sumOf { it.cityHealth }
override fun toString() = name // for debug override fun toString() = name // for debug
fun isHolyCity(): Boolean = religion.religionThisIsTheHolyCityOf != null
fun canBeDestroyed(justCaptured: Boolean = false): Boolean {
return !isOriginalCapital && !isHolyCity() && (!isCapital() || justCaptured)
}
fun getForceEvaluation(): Int {
// Same as for units, so higher values count more
return CityCombatant(this).getDefendingStrength().toFloat().pow(1.5f).toInt()
}
fun getNeighbouringCivs(): Set<String> {
val tilesList: HashSet<TileInfo> = getTiles().toHashSet()
val cityPositionList: ArrayList<TileInfo> = arrayListOf()
for (tiles in tilesList)
for (tile in tiles.neighbors)
if (!tilesList.contains(tile))
cityPositionList.add(tile)
return cityPositionList
.asSequence()
.mapNotNull { it.getOwner()?.civName }
.toSet()
}
//endregion //endregion
//region state-changing functions //region state-changing functions
@ -799,19 +828,6 @@ class CityInfo {
// Looking at all the use cases, the following functions were written to handle all findMatchingUniques() problems. // Looking at all the use cases, the following functions were written to handle all findMatchingUniques() problems.
// Sadly, due to the large disparity between use cases, there needed to be lots of functions. // Sadly, due to the large disparity between use cases, there needed to be lots of functions.
// Finds matching uniques provided from both local and non-local sources.
fun getMatchingUniques(
placeholderText: String,
// We might have this cached to avoid concurrency problems. If we don't, just get it directly
localUniques: Sequence<Unique> = getLocalMatchingUniques(placeholderText),
): Sequence<Unique> {
// The localUniques might not be filtered when passed as a parameter, so we filter it anyway
// The time loss shouldn't be that large I don't think
return civInfo.getMatchingUniques(placeholderText, this) +
localUniques.filter { it.placeholderText == placeholderText }
}
// Finds matching uniques provided from both local and non-local sources. // Finds matching uniques provided from both local and non-local sources.
fun getMatchingUniques( fun getMatchingUniques(
uniqueType: UniqueType, uniqueType: UniqueType,
@ -822,13 +838,6 @@ class CityInfo {
localUniques.filter { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) } localUniques.filter { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) }
} }
// Matching uniques provided by sources in the city itself
fun getLocalMatchingUniques(placeholderText: String): Sequence<Unique> {
return cityConstructions.builtBuildingUniqueMap.getUniques(placeholderText)
.filter { !it.isAntiLocalEffect } +
religion.getUniques().filter { it.placeholderText == placeholderText }
}
fun getLocalMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null): Sequence<Unique> { fun getLocalMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null): Sequence<Unique> {
return ( return (
cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType) cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType)
@ -859,33 +868,6 @@ class CityInfo {
.filter { !it.isLocalEffect } .filter { !it.isLocalEffect }
// Note that we don't query religion here, as those only have local effects // Note that we don't query religion here, as those only have local effects
} }
fun isHolyCity(): Boolean = religion.religionThisIsTheHolyCityOf != null
fun canBeDestroyed(justCaptured: Boolean = false): Boolean {
return !isOriginalCapital && !isHolyCity() && (!isCapital() || justCaptured)
}
fun getForceEvaluation(): Int {
// Same as for units, so higher values count more
return CityCombatant(this).getDefendingStrength().toFloat().pow(1.5f).toInt()
}
fun getNeighbouringCivs(): Set<String> {
val tilesList: HashSet<TileInfo> = getTiles().toHashSet()
val cityPositionList: ArrayList<TileInfo> = arrayListOf()
for (tiles in tilesList)
for (tile in tiles.neighbors)
if (!tilesList.contains(tile))
cityPositionList.add(tile)
return cityPositionList
.asSequence()
.mapNotNull { it.getOwner()?.civName }
.toSet()
}
//endregion //endregion
} }

View File

@ -6,6 +6,8 @@ import com.unciv.models.Counter
import com.unciv.models.Religion import com.unciv.models.Religion
import com.unciv.models.metadata.GameSpeed import com.unciv.models.metadata.GameSpeed
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.utils.toPercent
class CityInfoReligionManager { class CityInfoReligionManager {
@Transient @Transient
@ -113,7 +115,7 @@ class CityInfoReligionManager {
if (newMajorityReligion in religionsAtSomePointAdopted) return if (newMajorityReligion in religionsAtSomePointAdopted) return
val religionOwningCiv = cityInfo.civInfo.gameInfo.getCivilization(newMajorityReligionObject.foundingCivName) val religionOwningCiv = newMajorityReligionObject.getFounder()
for (unique in newMajorityReligionObject.getFounderUniques()) { for (unique in newMajorityReligionObject.getFounderUniques()) {
val statsGranted = when (unique.placeholderText) { val statsGranted = when (unique.placeholderText) {
"[] when a city adopts this religion for the first time (modified by game speed)" -> "[] when a city adopts this religion for the first time (modified by game speed)" ->
@ -254,13 +256,15 @@ class CityInfoReligionManager {
private fun getSpreadRange(): Int { private fun getSpreadRange(): Int {
var spreadRange = 10 var spreadRange = 10
for (unique in cityInfo.getMatchingUniques("Religion naturally spreads to cities [] tiles away"))
spreadRange += unique.params[0].toInt()
if (getMajorityReligion() != null) for (unique in cityInfo.getLocalMatchingUniques(UniqueType.ReligionSpreadDistance)) {
for (unique in getMajorityReligion()!!.getFounderUniques() spreadRange += unique.params[0].toInt()
.filter { it.placeholderText == "Religion naturally spreads to cities [] tiles away"} }
) spreadRange += unique.params[0].toInt()
if (getMajorityReligion() != null) {
for (unique in getMajorityReligion()!!.getFounder().getMatchingUniques(UniqueType.ReligionSpreadDistance))
spreadRange += unique.params[0].toInt()
}
return spreadRange return spreadRange
} }
@ -295,17 +299,27 @@ class CityInfoReligionManager {
private fun pressureAmountToAdjacentCities(pressuredCity: CityInfo): Int { private fun pressureAmountToAdjacentCities(pressuredCity: CityInfo): Int {
var pressure = pressureFromAdjacentCities.toFloat() var pressure = pressureFromAdjacentCities.toFloat()
for (unique in cityInfo.getMatchingUniques("[]% Natural religion spread []")) { // Follower beliefs of this religion
for (unique in cityInfo.getLocalMatchingUniques(UniqueType.NaturalReligionSpreadStrength)) {
if (pressuredCity.matchesFilter(unique.params[1])) if (pressuredCity.matchesFilter(unique.params[1]))
pressure *= 1f + unique.params[0].toFloat() / 100f pressure *= unique.params[0].toPercent()
} }
for (unique in cityInfo.getMatchingUniques("[]% Natural religion spread [] with []")) // Founder beliefs of this religion
if (pressuredCity.matchesFilter(unique.params[1]) if (getMajorityReligion() != null) {
&& cityInfo.civInfo.hasTechOrPolicy(unique.params[2]) for (unique in getMajorityReligion()!!.getFounder().getMatchingUniques(UniqueType.NaturalReligionSpreadStrength))
) pressure *= 1f + unique.params[0].toFloat() / 100f if (pressuredCity.matchesFilter(unique.params[1]))
pressure *= unique.params[0].toPercent()
}
// Deprecated since 3.19.3
for (unique in cityInfo.getLocalMatchingUniques(UniqueType.NaturalReligionSpreadStrengthWith))
if (pressuredCity.matchesFilter(unique.params[1])
&& cityInfo.civInfo.hasTechOrPolicy(unique.params[2])
) pressure *= unique.params[0].toPercent()
//
return pressure.toInt() return pressure.toInt()
} }
} }

View File

@ -88,7 +88,7 @@ class CityStats(val cityInfo: CityInfo) {
if (!cityInfo.isCapital() && cityInfo.isConnectedToCapital()) { if (!cityInfo.isCapital() && cityInfo.isConnectedToCapital()) {
val civInfo = cityInfo.civInfo val civInfo = cityInfo.civInfo
stats.gold = civInfo.getCapital().population.population * 0.15f + cityInfo.population.population * 1.1f - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5) stats.gold = civInfo.getCapital().population.population * 0.15f + cityInfo.population.population * 1.1f - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5)
for (unique in cityInfo.getMatchingUniques("[] from each Trade Route")) for (unique in cityInfo.getMatchingUniques(UniqueType.StatsFromTradeRoute))
stats.add(unique.stats) stats.add(unique.stats)
if (civInfo.hasUnique("Gold from all trade routes +25%")) stats.gold *= 1.25f // Machu Picchu speciality if (civInfo.hasUnique("Gold from all trade routes +25%")) stats.gold *= 1.25f // Machu Picchu speciality
} }
@ -314,13 +314,17 @@ class CityStats(val cityInfo: CityInfo) {
unique.params[0].toFloat() * cityInfo.religion.getFollowersOfMajorityReligion(), unique.params[0].toFloat() * cityInfo.religion.getFollowersOfMajorityReligion(),
unique.params[2].toFloat() unique.params[2].toFloat()
)) ))
if (currentConstruction is Building if (currentConstruction is Building
&& cityInfo.civInfo.cities.isNotEmpty() && cityInfo.civInfo.cities.isNotEmpty()
&& cityInfo.civInfo.getCapital().cityConstructions.builtBuildings.contains(currentConstruction.name) && cityInfo.civInfo.getCapital().cityConstructions.builtBuildings.contains(currentConstruction.name)
) { ) {
for (unique in cityInfo.getMatchingUniques("+25% Production towards any buildings that already exist in the Capital")) // Deprecated since 3.19.3
addUniqueStats(unique, Stat.Production, 25f) for (unique in cityInfo.getMatchingUniques(UniqueType.PercentProductionBuildingsInCapitalDeprecated))
addUniqueStats(unique, Stat.Production, 25f)
//
for (unique in cityInfo.getMatchingUniques(UniqueType.PercentProductionBuildingsInCapital))
addUniqueStats(unique, Stat.Production, unique.params[0].toFloat())
} }
return sourceToStats return sourceToStats
@ -361,7 +365,7 @@ class CityStats(val cityInfo: CityInfo) {
// e.g. "-[50]% maintenance costs for buildings [in this city]" // e.g. "-[50]% maintenance costs for buildings [in this city]"
// Deprecated since 3.18.17 // Deprecated since 3.18.17
for (unique in cityInfo.getMatchingUniques(UniqueType.DecrasedBuildingMaintenanceDeprecated)) { for (unique in cityInfo.getMatchingUniques(UniqueType.DecreasedBuildingMaintenanceDeprecated)) {
buildingsMaintenance *= (1f - unique.params[0].toFloat() / 100) buildingsMaintenance *= (1f - unique.params[0].toFloat() / 100)
} }
// //

View File

@ -739,10 +739,10 @@ class MapUnit {
} }
val healingCity = tileInfo.getTilesInDistance(1).firstOrNull { val healingCity = tileInfo.getTilesInDistance(1).firstOrNull {
it.isCityCenter() && it.getCity()!!.getMatchingUniques("[] Units adjacent to this city heal [] HP per turn when healing").any() it.isCityCenter() && it.getCity()!!.getMatchingUniques(UniqueType.CityHealingUnits).any()
}?.getCity() }?.getCity()
if (healingCity != null) { if (healingCity != null) {
for (unique in healingCity.getMatchingUniques("[] Units adjacent to this city heal [] HP per turn when healing")) { for (unique in healingCity.getMatchingUniques(UniqueType.CityHealingUnits)) {
if (!matchesFilter(unique.params[0])) continue if (!matchesFilter(unique.params[0])) continue
healing += unique.params[1].toInt() healing += unique.params[1].toInt()
} }
@ -1160,7 +1160,7 @@ class MapUnit {
val baseAmount = getBaseMaxActionUses(action) val baseAmount = getBaseMaxActionUses(action)
val additional = val additional =
if (buildCity == null) 0 if (buildCity == null) 0
else buildCity.getMatchingUniques("[] units built [] can [] [] extra times") else buildCity.getMatchingUniques(UniqueType.UnitStartingActions)
.filter { matchesFilter(it.params[0]) && buildCity.matchesFilter(it.params[1]) && it.params[2] == action } .filter { matchesFilter(it.params[0]) && buildCity.matchesFilter(it.params[1]) && it.params[2] == action }
.sumOf { it.params[3].toInt() } .sumOf { it.params[3].toInt() }

View File

@ -91,4 +91,6 @@ class Religion() : INamed {
fun isMajorReligion() = getBeliefs(BeliefType.Founder).any() fun isMajorReligion() = getBeliefs(BeliefType.Founder).any()
fun isEnhancedReligion() = getBeliefs(BeliefType.Enhancer).any() fun isEnhancedReligion() = getBeliefs(BeliefType.Enhancer).any()
fun getFounder() = gameInfo.civilizations.first { it.civName == foundingCivName }
} }

View File

@ -173,9 +173,11 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
stats.add(unique.stats) stats.add(unique.stats)
} }
for (unique in city.getMatchingUniques("[] from every [] in cities where this religion has at least [] followers")) // Deprecated since 3.19.3
if (unique.params[2].toInt() <= city.religion.getFollowersOfMajorityReligion() && matchesFilter(unique.params[1])) for (unique in city.getMatchingUniques(UniqueType.StatsForBuildingsWithFollowers))
stats.add(unique.stats) if (unique.params[2].toInt() <= city.religion.getFollowersOfMajorityReligion() && matchesFilter(unique.params[1]))
stats.add(unique.stats)
//
@Suppress("RemoveRedundantQualifierName") // make it clearer Building inherits Stats @Suppress("RemoveRedundantQualifierName") // make it clearer Building inherits Stats
for (unique in getMatchingUniques(UniqueType.StatsWithResource)) for (unique in getMatchingUniques(UniqueType.StatsWithResource))

View File

@ -83,6 +83,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
UniqueType.ConditionalSpecialistCount -> UniqueType.ConditionalSpecialistCount ->
state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt() state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt()
UniqueType.ConditionalFollowerCount ->
state.cityInfo != null && state.cityInfo.religion.getFollowersOfMajorityReligion() >= condition.params[0].toInt()
UniqueType.ConditionalWhenGarrisoned -> UniqueType.ConditionalWhenGarrisoned ->
state.cityInfo != null && state.cityInfo.getCenterTile().militaryUnit != null && state.cityInfo.getCenterTile().militaryUnit!!.canGarrison() state.cityInfo != null && state.cityInfo.getCenterTile().militaryUnit != null && state.cityInfo.getCenterTile().militaryUnit!!.canGarrison()

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset.unique package com.unciv.models.ruleset.unique
import com.unciv.Constants
import com.unciv.models.ruleset.BeliefType import com.unciv.models.ruleset.BeliefType
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.VictoryType import com.unciv.models.ruleset.VictoryType
@ -302,6 +303,16 @@ enum class UniqueParameterType(val parameterName:String) {
else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
} }
}, },
Action("action") {
private val knownValues = setOf(Constants.spreadReligionAbilityCount, Constants.removeHeresyAbilityCount)
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueComplianceErrorSeverity? {
return if (parameterText in knownValues) null
else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
}
},
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */ /** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
Comment("comment") { Comment("comment") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset): override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):

View File

@ -70,9 +70,10 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
StatsFromSpecialist("[stats] from every specialist [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromSpecialist("[stats] from every specialist [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
StatsPerPopulation("[stats] per [amount] population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsPerPopulation("[stats] per [amount] population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// ToDo: Reword to `[stats] <in cities with [amount] or more population>` for consistency with other conditionals
StatsFromXPopulation("[stats] in cities with [amount] or more population", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromXPopulation("[stats] in cities with [amount] or more population", UniqueTarget.Global, UniqueTarget.FollowerBelief),
StatsFromCitiesOnSpecificTiles("[stats] in cities on [terrainFilter] tiles", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromCitiesOnSpecificTiles("[stats] in cities on [terrainFilter] tiles", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.18.14", ReplaceWith("[stats] [in all cities] <before discovering [tech]> OR [stats] [in all cities] <before adopting [policy]>")) @Deprecated("As of 3.18.14", ReplaceWith("[stats] [in all cities] <before discovering [tech]> OR [stats] [in all cities] <before adopting [policy]>"))
StatsFromCitiesBefore("[stats] per turn from cities before [tech/policy]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromCitiesBefore("[stats] per turn from cities before [tech/policy]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@ -84,7 +85,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
StatsFromTilesWithout("[stats] from [tileFilter] tiles without [tileFilter] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromTilesWithout("[stats] from [tileFilter] tiles without [tileFilter] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// This is a doozy // This is a doozy
StatsFromObject("[stats] from every [tileFilter/specialist/buildingFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromObject("[stats] from every [tileFilter/specialist/buildingFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.19.3", ReplaceWith("[stats] from every [buildingFilter] <in cities where this religion has at least [amount] followers>"))
StatsForBuildingsWithFollowers("[stats] from every [buildingFilter] in cities where this religion has at least [amount] followers", UniqueTarget.Global, UniqueTarget.FollowerBelief),
StatsFromTradeRoute("[stats] from each Trade Route", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// Stat percentage boosts // Stat percentage boosts
StatPercentBonus("[amount]% [stat]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatPercentBonus("[amount]% [stat]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@ -97,12 +100,16 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
AllStatsSignedPercentFromObject("+[amount]% yield from every [tileFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), AllStatsSignedPercentFromObject("+[amount]% yield from every [tileFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
StatPercentFromReligionFollowers("[amount]% [stat] from every follower, up to [amount]%", UniqueTarget.FollowerBelief), StatPercentFromReligionFollowers("[amount]% [stat] from every follower, up to [amount]%", UniqueTarget.FollowerBelief),
BonusStatsFromCityStates("[amount]% [stat] from City-States", UniqueTarget.Global), BonusStatsFromCityStates("[amount]% [stat] from City-States", UniqueTarget.Global),
NullifiesStat("Nullifies [stat] [cityFilter]", UniqueTarget.Global), NullifiesStat("Nullifies [stat] [cityFilter]", UniqueTarget.Global),
NullifiesGrowth("Nullifies Growth [cityFilter]", UniqueTarget.Global), NullifiesGrowth("Nullifies Growth [cityFilter]", UniqueTarget.Global),
PercentProductionWonders("[amount]% Production when constructing [buildingFilter] wonders [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), PercentProductionWonders("[amount]% Production when constructing [buildingFilter] wonders [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
PercentProductionBuildings("[amount]% Production when constructing [buildingFilter] buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), PercentProductionBuildings("[amount]% Production when constructing [buildingFilter] buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
PercentProductionUnits("[amount]% Production when constructing [baseUnitFilter] units [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), PercentProductionUnits("[amount]% Production when constructing [baseUnitFilter] units [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
PercentProductionBuildingsInCapital("[amount]% Production towards any buildings that already exist in the Capital", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.19.3", ReplaceWith("[amount]% Production towards any buildings that already exist in the Capital"))
PercentProductionBuildingsInCapitalDeprecated("+25% Production towards any buildings that already exist in the Capital", UniqueTarget.Global, UniqueTarget.FollowerBelief),
//endregion Stat providing uniques //endregion Stat providing uniques
@ -143,6 +150,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
/////// region Other global uniques /////// region Other global uniques
FreeUnits("[amount] units cost no maintenance", UniqueTarget.Global), FreeUnits("[amount] units cost no maintenance", UniqueTarget.Global),
CannotBuildUnits("Cannot build [baseUnitFilter] units", UniqueTarget.Global),
ConsumesResources("Consumes [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit), ConsumesResources("Consumes [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit),
ProvidesResources("Provides [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building), ProvidesResources("Provides [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building),
@ -155,6 +163,8 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
CarryOverFoodAlsoDeprecated("[amount]% of food is carried over [cityFilter] after population increases", UniqueTarget.Global, UniqueTarget.FollowerBelief), CarryOverFoodAlsoDeprecated("[amount]% of food is carried over [cityFilter] after population increases", UniqueTarget.Global, UniqueTarget.FollowerBelief),
GainFreeBuildings("Gain a free [buildingName] [cityFilter]", UniqueTarget.Global), GainFreeBuildings("Gain a free [buildingName] [cityFilter]", UniqueTarget.Global),
GreatPersonPointPercentage("[amount]% Great Person generation [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
GreatPersonPointPercentageDeprecated("[amount]% great person generation [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
FreeExtraBeliefs("May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion", UniqueTarget.Global), FreeExtraBeliefs("May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion", UniqueTarget.Global),
FreeExtraAnyBeliefs("May choose [amount] additional belief(s) of any type when [foundingOrEnhancing] a religion", UniqueTarget.Global), FreeExtraAnyBeliefs("May choose [amount] additional belief(s) of any type when [foundingOrEnhancing] a religion", UniqueTarget.Global),
@ -209,7 +219,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
BuildingMaintenance("[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), BuildingMaintenance("[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.18.17", ReplaceWith("[-amount]% maintenace cost for buildings [cityFilter]")) @Deprecated("As of 3.18.17", ReplaceWith("[-amount]% maintenace cost for buildings [cityFilter]"))
DecrasedBuildingMaintenanceDeprecated("-[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), DecreasedBuildingMaintenanceDeprecated("-[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// This should probably support conditionals, e.g. <after discovering [tech]> // This should probably support conditionals, e.g. <after discovering [tech]>
MayanGainGreatPerson("Receive a free Great Person at the end of every [comment] (every 394 years), after researching [tech]. Each bonus person can only be chosen once.", UniqueTarget.Global), MayanGainGreatPerson("Receive a free Great Person at the end of every [comment] (every 394 years), after researching [tech]. Each bonus person can only be chosen once.", UniqueTarget.Global),
@ -233,14 +243,14 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
TriggersVictory("Triggers victory", UniqueTarget.Global), TriggersVictory("Triggers victory", UniqueTarget.Global),
TriggersCulturalVictory("Triggers a Cultural Victory upon completion", UniqueTarget.Global), TriggersCulturalVictory("Triggers a Cultural Victory upon completion", UniqueTarget.Global),
CannotBuildUnits("Cannot build [baseUnitFilter] units", UniqueTarget.Global),
BetterDefensiveBuildings("[amount]% City Strength from defensive buildings", UniqueTarget.Global), BetterDefensiveBuildings("[amount]% City Strength from defensive buildings", UniqueTarget.Global),
@Deprecated("As of 3.18.17", ReplaceWith("[+25]% City Strength from defensive buildings")) @Deprecated("As of 3.18.17", ReplaceWith("[+25]% City Strength from defensive buildings"))
DefensiveBuilding25("Defensive buildings in all cities are 25% more effective", UniqueTarget.Global), DefensiveBuilding25("Defensive buildings in all cities are 25% more effective", UniqueTarget.Global),
TileImprovementTime("[amount]% tile improvement construction time", UniqueTarget.Global), TileImprovementTime("[amount]% tile improvement construction time", UniqueTarget.Global),
PercentGoldFromTradeMissions("[amount]% Gold from Great Merchant trade missions", UniqueTarget.Global), PercentGoldFromTradeMissions("[amount]% Gold from Great Merchant trade missions", UniqueTarget.Global),
// Todo: Lowercase the 'U' of 'Units' in this unique
CityHealingUnits("[mapUnitFilter] Units adjacent to this city heal [amount] HP per turn when healing", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.18.17", ReplaceWith("[amount]% Strength <for [mapUnitFilter] units> <when adjacent to a [mapUnitFilter] unit>")) @Deprecated("As of 3.18.17", ReplaceWith("[amount]% Strength <for [mapUnitFilter] units> <when adjacent to a [mapUnitFilter] unit>"))
StrengthFromAdjacentUnits("[amount]% Strength for [mapUnitFilter] units which have another [mapUnitFilter] unit in an adjacent tile", UniqueTarget.Unit, UniqueTarget.Global), StrengthFromAdjacentUnits("[amount]% Strength for [mapUnitFilter] units which have another [mapUnitFilter] unit in an adjacent tile", UniqueTarget.Unit, UniqueTarget.Global),
@ -262,10 +272,21 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
StrengthForGarrisonedCitiesAttacking("+[amount]% attacking strength for cities with garrisoned units", UniqueTarget.Global), StrengthForGarrisonedCitiesAttacking("+[amount]% attacking strength for cities with garrisoned units", UniqueTarget.Global),
UnitStartingExperience("New [baseUnitFilter] units start with [amount] Experience [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), UnitStartingExperience("New [baseUnitFilter] units start with [amount] Experience [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
UnitStartingPromotions("All newly-trained [baseUnitFilter] units [cityFilter] receive the [promotion] promotion", UniqueTarget.Global, UniqueTarget.FollowerBelief),
UnitStartingActions("[baseUnitFilter] units built [cityFilter] can [action] [amount] extra times", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// ToDo: make per unit and use unit filters? // ToDo: make per unit and use unit filters?
LandUnitEmbarkation("Enables embarkation for land units", UniqueTarget.Global), LandUnitEmbarkation("Enables embarkation for land units", UniqueTarget.Global),
EmbarkedUnitsMayEnterOcean("Enables embarked units to enter ocean tiles", UniqueTarget.Global), EmbarkedUnitsMayEnterOcean("Enables embarked units to enter ocean tiles", UniqueTarget.Global),
PopulationLossFromNukes("Population loss from nuclear attacks [amount]% [cityFilter]", UniqueTarget.Global),
@Deprecated("As of 3.19.2", ReplaceWith("Population loss from nuclear attacks [-amount]% [in this city]"))
PopulationLossFromNukesDeprecated("Population loss from nuclear attacks -[amount]%", UniqueTarget.Global),
NaturalReligionSpreadStrength("[amount]% Natural religion spread [cityFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
@Deprecated("As of 3.19.3", ReplaceWith("[amount]% Natural religion spread [cityFilter] <after discovering [tech]> OR [amount]% natural religion spread [cityFilter] <after adopting [policy]>"))
NaturalReligionSpreadStrengthWith("[amount]% Natural religion spread [cityFilter] with [tech/policy]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
ReligionSpreadDistance("Religion naturally spreads to cities [amount] tiles away", UniqueTarget.Global, UniqueTarget.FollowerBelief),
IncompatibleWith("Incompatible with [policy/tech/promotion]", UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion), IncompatibleWith("Incompatible with [policy/tech/promotion]", UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion),
StartingTech("Starting tech", UniqueTarget.Tech), StartingTech("Starting tech", UniqueTarget.Tech),
StartsWithTech("Starts with [tech]", UniqueTarget.Nation), StartsWithTech("Starts with [tech]", UniqueTarget.Nation),
@ -538,6 +559,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
/////// city conditionals /////// city conditionals
ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional), ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional),
ConditionalFollowerCount("in cities where this religion has at least [amount] followers", UniqueTarget.Conditional),
ConditionalWhenGarrisoned("with a garrison", UniqueTarget.Conditional), ConditionalWhenGarrisoned("with a garrison", UniqueTarget.Conditional),
/////// unit conditionals /////// unit conditionals

View File

@ -482,7 +482,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
} }
unit.promotions.XP = XP unit.promotions.XP = XP
for (unique in cityConstructions.cityInfo.getMatchingUniques("All newly-trained [] units [] receive the [] promotion") for (unique in cityConstructions.cityInfo.getMatchingUniques(UniqueType.UnitStartingPromotions)
.filter { cityConstructions.cityInfo.matchesFilter(it.params[1]) }) { .filter { cityConstructions.cityInfo.matchesFilter(it.params[1]) }) {
val filter = unique.params[0] val filter = unique.params[0]
val promotion = unique.params.last() val promotion = unique.params.last()

View File

@ -74,7 +74,7 @@ class ReligionOverviewTable(
val button: Button val button: Button
if (religion.isPantheon()) { if (religion.isPantheon()) {
val image = if (viewingPlayer.knows(religion.foundingCivName) || viewingPlayer.civName == religion.foundingCivName) val image = if (viewingPlayer.knows(religion.foundingCivName) || viewingPlayer.civName == religion.foundingCivName)
ImageGetter.getNationIndicator(gameInfo.getCivilization(religion.foundingCivName).nation, 60f) ImageGetter.getNationIndicator(religion.getFounder().nation, 60f)
else else
ImageGetter.getRandomNationIndicator(60f) ImageGetter.getRandomNationIndicator(60f)
button = Button(image, BaseScreen.skin) button = Button(image, BaseScreen.skin)
@ -126,7 +126,7 @@ class ReligionOverviewTable(
} }
} }
statsTable.add("Cities following this religion:".toLabel()).left() statsTable.add("Cities following this religion:".toLabel()).left()
statsTable.add(gameInfo.getCivilization(religion.foundingCivName).religionManager.numberOfCitiesFollowingThisReligion().toString()).right().pad(5f).row() statsTable.add(religion.getFounder().religionManager.numberOfCitiesFollowingThisReligion().toString()).right().pad(5f).row()
val minWidth = max(statsTable.minWidth, beliefsTable.minWidth) + 5 val minWidth = max(statsTable.minWidth, beliefsTable.minWidth) + 5

View File

@ -6,6 +6,12 @@ These are split into two categories:
Note that all of these are case-sensitive! Note that all of these are case-sensitive!
## action
An action that a unit can preform. Currently, there are only two actions part of this:
- `Spread Religion`
- `Remove Foreign religions from your own cities`
## amount ## amount
This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`. This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`.

View File

@ -71,6 +71,11 @@ Example: "[+1 Gold, +2 Production] from every [tileFilter/specialist/buildingFil
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
#### [stats] from each Trade Route
Example: "[+1 Gold, +2 Production] from each Trade Route"
Applicable to: Global, FollowerBelief
#### [amount]% [stat] #### [amount]% [stat]
Example: "[20]% [Culture]" Example: "[20]% [Culture]"
@ -121,6 +126,11 @@ Example: "[20]% Production when constructing [Melee] units [in all cities]"
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
#### [amount]% Production towards any buildings that already exist in the Capital
Example: "[20]% Production towards any buildings that already exist in the Capital"
Applicable to: Global, FollowerBelief
#### Military Units gifted from City-States start with [amount] XP #### Military Units gifted from City-States start with [amount] XP
Example: "Military Units gifted from City-States start with [20] XP" Example: "Military Units gifted from City-States start with [20] XP"
@ -177,6 +187,11 @@ Example: "[20] units cost no maintenance"
Applicable to: Global Applicable to: Global
#### Cannot build [baseUnitFilter] units
Example: "Cannot build [Melee] units"
Applicable to: Global
#### [amount]% growth [cityFilter] #### [amount]% growth [cityFilter]
Example: "[20]% growth [in all cities]" Example: "[20]% growth [in all cities]"
@ -192,6 +207,16 @@ Example: "Gain a free [Library] [in all cities]"
Applicable to: Global Applicable to: Global
#### [amount]% Great Person generation [cityFilter]
Example: "[20]% Great Person generation [in all cities]"
Applicable to: Global, FollowerBelief
#### [amount]% great person generation [cityFilter]
Example: "[20]% great person generation [in all cities]"
Applicable to: Global, FollowerBelief
#### May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion #### May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion
Example: "May choose [20] additional [Follower] beliefs when [founding] a religion" Example: "May choose [20] additional [Follower] beliefs when [founding] a religion"
@ -354,11 +379,6 @@ Applicable to: Global
#### Triggers a Cultural Victory upon completion #### Triggers a Cultural Victory upon completion
Applicable to: Global Applicable to: Global
#### Cannot build [baseUnitFilter] units
Example: "Cannot build [Melee] units"
Applicable to: Global
#### [amount]% City Strength from defensive buildings #### [amount]% City Strength from defensive buildings
Example: "[20]% City Strength from defensive buildings" Example: "[20]% City Strength from defensive buildings"
@ -374,6 +394,11 @@ Example: "[20]% Gold from Great Merchant trade missions"
Applicable to: Global Applicable to: Global
#### [mapUnitFilter] Units adjacent to this city heal [amount] HP per turn when healing
Example: "[Wounded] Units adjacent to this city heal [20] HP per turn when healing"
Applicable to: Global, FollowerBelief
#### [amount]% Golden Age length #### [amount]% Golden Age length
Example: "[20]% Golden Age length" Example: "[20]% Golden Age length"
@ -389,12 +414,37 @@ Example: "New [Melee] units start with [20] Experience [in all cities]"
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
#### All newly-trained [baseUnitFilter] units [cityFilter] receive the [promotion] promotion
Example: "All newly-trained [Melee] units [in all cities] receive the [Shock I] promotion"
Applicable to: Global, FollowerBelief
#### [baseUnitFilter] units built [cityFilter] can [action] [amount] extra times
Example: "[Melee] units built [in all cities] can [action] [20] extra times"
Applicable to: Global, FollowerBelief
#### Enables embarkation for land units #### Enables embarkation for land units
Applicable to: Global Applicable to: Global
#### Enables embarked units to enter ocean tiles #### Enables embarked units to enter ocean tiles
Applicable to: Global Applicable to: Global
#### Population loss from nuclear attacks [amount]% [cityFilter]
Example: "Population loss from nuclear attacks [20]% [in all cities]"
Applicable to: Global
#### [amount]% Natural religion spread [cityFilter]
Example: "[20]% Natural religion spread [in all cities]"
Applicable to: Global, FollowerBelief
#### Religion naturally spreads to cities [amount] tiles away
Example: "Religion naturally spreads to cities [20] tiles away"
Applicable to: Global, FollowerBelief
#### Can be continually researched #### Can be continually researched
Applicable to: Global Applicable to: Global
@ -1275,6 +1325,11 @@ Example: "<if this city has at least [20] specialists>"
Applicable to: Conditional Applicable to: Conditional
#### <in cities where this religion has at least [amount] followers>
Example: "<in cities where this religion has at least [20] followers>"
Applicable to: Conditional
#### <with a garrison> #### <with a garrison>
Applicable to: Conditional Applicable to: Conditional
@ -1364,8 +1419,10 @@ Applicable to: Conditional
## Deprecated uniques ## Deprecated uniques
- "[stats] per turn from cities before [tech/policy]" - Deprecated As of 3.18.14, replace with "[stats] [in all cities] <before discovering [tech]> OR [stats] [in all cities] <before adopting [policy]>" - "[stats] per turn from cities before [tech/policy]" - Deprecated As of 3.18.14, replace with "[stats] [in all cities] <before discovering [tech]> OR [stats] [in all cities] <before adopting [policy]>"
- "[stats] from every Wonder" - Deprecated As of 3.19.1, replace with "[stats] from every [Wonder]" - "[stats] from every Wonder" - Deprecated As of 3.19.1, replace with "[stats] from every [Wonder]"
- "[stats] from every [buildingFilter] in cities where this religion has at least [amount] followers" - Deprecated As of 3.19.3, replace with "[stats] from every [buildingFilter] <in cities where this religion has at least [amount] followers>"
- "+[amount]% [stat] from every [tileFilter/specialist/buildingName]" - Deprecated As of 3.18.17, replace with "[amount]% [stat] from every [tileFilter/specialist/buildingName]" - "+[amount]% [stat] from every [tileFilter/specialist/buildingName]" - Deprecated As of 3.18.17, replace with "[amount]% [stat] from every [tileFilter/specialist/buildingName]"
- "+[amount]% yield from every [tileFilter]" - Deprecated As of 3.18.17, replace with "[+amount]% Yield from every [tileFilter]" - "+[amount]% yield from every [tileFilter]" - Deprecated As of 3.18.17, replace with "[+amount]% Yield from every [tileFilter]"
- "+25% Production towards any buildings that already exist in the Capital" - Deprecated As of 3.19.3, replace with "[amount]% Production towards any buildings that already exist in the Capital"
- "City-State Influence degrades [amount]% slower" - Deprecated As of 3.18.17, replace with "[-amount]% City-State Influence degradation" - "City-State Influence degrades [amount]% slower" - Deprecated As of 3.18.17, replace with "[-amount]% City-State Influence degradation"
- "Quantity of Resources gifted by City-States increased by [amount]%" - Deprecated As of 3.18.17, replace with "[+amount]% resources gifted by City-States" - "Quantity of Resources gifted by City-States increased by [amount]%" - Deprecated As of 3.18.17, replace with "[+amount]% resources gifted by City-States"
- "Happiness from Luxury Resources gifted by City-States increased by [amount]%" - Deprecated As of 3.18.17, replace with "[+amount]% Happiness from luxury resources gifted by City-States" - "Happiness from Luxury Resources gifted by City-States increased by [amount]%" - Deprecated As of 3.18.17, replace with "[+amount]% Happiness from luxury resources gifted by City-States"
@ -1390,6 +1447,8 @@ Applicable to: Conditional
- "+[amount]% Defensive Strength for cities" - Deprecated As of 3.18.17, replace with "[+amount]% Strength for cities <when defending>" - "+[amount]% Defensive Strength for cities" - Deprecated As of 3.18.17, replace with "[+amount]% Strength for cities <when defending>"
- "[amount]% Attacking Strength for cities" - Deprecated As of 3.18.17, replace with "[amount]% Strength for cities <when attacking>" - "[amount]% Attacking Strength for cities" - Deprecated As of 3.18.17, replace with "[amount]% Strength for cities <when attacking>"
- "+[amount]% attacking strength for cities with garrisoned units" - Deprecated As of 3.19.1, replace with "[amount]% Strength for cities <with a garrison> <when attacking>" - "+[amount]% attacking strength for cities with garrisoned units" - Deprecated As of 3.19.1, replace with "[amount]% Strength for cities <with a garrison> <when attacking>"
- "Population loss from nuclear attacks -[amount]%" - Deprecated As of 3.19.2, replace with "Population loss from nuclear attacks [-amount]% [in this city]"
- "[amount]% Natural religion spread [cityFilter] with [tech/policy]" - Deprecated As of 3.19.3, replace with "[amount]% Natural religion spread [cityFilter] <after discovering [tech]> OR [amount]% natural religion spread [cityFilter] <after adopting [policy]>"
- "Melee units pay no movement cost to pillage" - Deprecated As of 3.18.17, replace with "No movement cost to pillage <for [Melee] units>" - "Melee units pay no movement cost to pillage" - Deprecated As of 3.18.17, replace with "No movement cost to pillage <for [Melee] units>"
- "[mapUnitFilter] units gain [amount]% more Experience from combat" - Deprecated As of 3.18.12, replace with "[amount]% XP gained from combat <for [mapUnitFilter] units>" - "[mapUnitFilter] units gain [amount]% more Experience from combat" - Deprecated As of 3.18.12, replace with "[amount]% XP gained from combat <for [mapUnitFilter] units>"
- "[amount]% maintenance costs for [mapUnitFilter] units" - Deprecated As of 3.18.14, replace with "[amount]% maintenance costs <for [mapUnitFilter] units>" - "[amount]% maintenance costs for [mapUnitFilter] units" - Deprecated As of 3.18.14, replace with "[amount]% maintenance costs <for [mapUnitFilter] units>"