Unified & generalized a few uniques (#6379)

* Generalized trade route percent bonuses

* Unified two uniques using populationFilter; deprecated a deprecated uniq

* Made some renamings to improve clarity & fixed tests

* Fixed tests again

* Fixed typo
This commit is contained in:
Xander Lenstra 2022-03-21 20:05:20 +01:00 committed by GitHub
parent 2b1251258c
commit 984c4d9b2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 103 additions and 71 deletions

View File

@ -30,7 +30,7 @@
{ {
"name": "God of Craftsman", "name": "God of Craftsman",
"type": "Pantheon", "type": "Pantheon",
"uniques": ["[+1 Production] in cities with [3] or more population"] "uniques": ["[+1 Production] <in cities with at least [3] [Population]>"]
}, },
{ {
"name": "God of the Open Sky", "name": "God of the Open Sky",
@ -55,7 +55,7 @@
{ {
"name": "Goddess of Love", "name": "Goddess of Love",
"type": "Pantheon", "type": "Pantheon",
"uniques": ["[+1 Happiness] in cities with [6] or more population"] "uniques": ["[+1 Happiness] <in cities with at least [6] [Population]>"]
}, },
{ {
"name": "Goddess of Protection", "name": "Goddess of Protection",
@ -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 with at least [3] [Followers of this Religion]>"]
}, },
{ {
"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 with at least [5] [Followers of this Religion]>"]
}, },
{ {
"name": "Divine inspiration", "name": "Divine inspiration",
@ -148,7 +148,7 @@
{ {
"name": "Guruship", "name": "Guruship",
"type": "Follower", "type": "Follower",
"uniques": ["[+2 Production] <if this city has at least [1] specialists>"] "uniques": ["[+2 Production] <in cities with at least [1] [Specialists]>"]
}, },
{ {
"name": "Holy Warriors", "name": "Holy Warriors",
@ -158,7 +158,7 @@
{ {
"name": "Liturgical Drama", "name": "Liturgical Drama",
"type": "Follower", "type": "Follower",
"uniques": ["[+1 Faith] from every [Amphitheater] <in cities where this religion has at least [3] followers>"] "uniques": ["[+1 Faith] from every [Amphitheater] <in cities with at least [3] [Followers of this Religion]>"]
}, },
{ {
"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 with at least [5] [Followers of this Religion]>"]
}, },
{ {
"name": "Religious Community", "name": "Religious Community",

View File

@ -354,7 +354,7 @@
"cost": 125, "cost": 125,
"culture": 1, "culture": 1,
"isNationalWonder": true, "isNationalWonder": true,
"uniques": ["Requires a [Monument] in all cities", "[+25]% great person generation [in this city]", "Cost increases by [30] per owned city"], "uniques": ["Requires a [Monument] in all cities", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
"requiredTech": "Drama and Poetry" "requiredTech": "Drama and Poetry"
}, },
{ {
@ -437,7 +437,7 @@
// Column 5 // Column 5
{ {
"name": "Garden", "name": "Garden",
"uniques": ["[+25]% great person generation [in this city]", "Must be next to [Fresh water]"], "uniques": ["[+25]% Great Person generation [in this city]", "Must be next to [Fresh water]"],
"hurryCostModifier": 25, "hurryCostModifier": 25,
"maintenance": 1, "maintenance": 1,
"requiredTech": "Theology" "requiredTech": "Theology"
@ -496,7 +496,7 @@
"greatPersonPoints": {"Great Merchant": 1}, "greatPersonPoints": {"Great Merchant": 1},
"culture": 1, "culture": 1,
"isWonder": true, "isWonder": true,
"uniques": ["Gold from all trade routes +25%","Must have an owned [Mountain] within [2] tiles"], "uniques": ["[+25]% [Gold] from Trade Routes","Must have an owned [Mountain] within [2] tiles"],
"requiredTech": "Guilds", "requiredTech": "Guilds",
"quote": "'Few romances can ever surpass that of the granite citadel on top of the beetling precipices of Machu Picchu, the crown of Inca Land.' - Hiram Bingham" "quote": "'Few romances can ever surpass that of the granite citadel on top of the beetling precipices of Machu Picchu, the crown of Inca Land.' - Hiram Bingham"
}, },
@ -725,7 +725,7 @@
"culture": 1, "culture": 1,
"isWonder": true, "isWonder": true,
"greatPersonPoints": {"Great Artist": 1}, "greatPersonPoints": {"Great Artist": 1},
"uniques": ["[-10]% unhappiness from population [in all cities]"], "uniques": ["[-10]% Unhappiness from [Population] [in all cities]"],
"requiredTech": "Banking", "requiredTech": "Banking",
"quote": "'Most of us can, as we choose, make of this world either a palace or a prison' - John Lubbock" "quote": "'Most of us can, as we choose, make of this world either a palace or a prison' - John Lubbock"
}, },
@ -742,7 +742,7 @@
"culture": 1, "culture": 1,
"isWonder": true, "isWonder": true,
"greatPersonPoints": {"Great Artist": 1}, "greatPersonPoints": {"Great Artist": 1},
"uniques": ["[+25]% great person generation [in all cities]", "Free Great Person"], "uniques": ["[+25]% Great Person generation [in all cities]", "Free Great Person"],
"requiredTech": "Printing Press", "requiredTech": "Printing Press",
"quote": "'Don't clap too hard - it's a very old building.' - John Osbourne" "quote": "'Don't clap too hard - it's a very old building.' - John Osbourne"
}, },
@ -812,7 +812,7 @@
"specialistSlots": {"Engineer": 1}, "specialistSlots": {"Engineer": 1},
"hurryCostModifier": 25, "hurryCostModifier": 25,
"maintenance": 2, "maintenance": 2,
"uniques": ["[+25]% great person generation [in this city]"], "uniques": ["[+25]% Great Person generation [in this city]"],
"requiredTech": "Economics" "requiredTech": "Economics"
}, },
{ {

View File

@ -326,7 +326,7 @@
"innerColor": [255,153,51], "innerColor": [255,153,51],
"favoredReligion": "Hinduism", "favoredReligion": "Hinduism",
"uniqueName": "Population Growth", "uniqueName": "Population Growth",
"uniques": ["Unhappiness from number of Cities doubled", "[-50]% unhappiness from population [in all cities]"], "uniques": ["Unhappiness from number of Cities doubled", "[-50]% Unhappiness from [Population] [in all cities]"],
"cities": ["Delhi","Mumbai","Vijayanagara","Pataliputra","Varanasi","Agra","Calcutta","Lahore","Bangalore","Hyderabad","Madurai","Ahmedabad", "cities": ["Delhi","Mumbai","Vijayanagara","Pataliputra","Varanasi","Agra","Calcutta","Lahore","Bangalore","Hyderabad","Madurai","Ahmedabad",
"Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur", "Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur",
"Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"] "Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"]

View File

@ -75,7 +75,7 @@
}, },
{ {
"name": "Meritocracy", "name": "Meritocracy",
"uniques": ["[+1 Happiness] [in all cities connected to capital]", "[-5]% unhappiness from population [in all non-occupied cities]"], "uniques": ["[+1 Happiness] [in all cities connected to capital]", "[-5]% Unhappiness from [Population] [in all non-occupied cities]"],
"requires": ["Citizenship"], "requires": ["Citizenship"],
"row": 2, "row": 2,
"column": 5 "column": 5
@ -323,7 +323,7 @@
{ {
"name": "Freedom", "name": "Freedom",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["[+25]% great person generation [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Order]>"], "uniques": ["[+25]% Great Person generation [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Order]>"],
"policies": [ "policies": [
{ {
"name": "Constitution", "name": "Constitution",
@ -352,7 +352,7 @@
}, },
{ {
"name": "Democracy", "name": "Democracy",
"uniques": ["[-50]% unhappiness from specialists [in all cities]"], "uniques": ["[-50]% Unhappiness from [Specialists] [in all cities]"],
"requires": ["Civil Society"], "requires": ["Civil Society"],
"row": 2, "row": 2,
"column": 5 "column": 5

View File

@ -316,7 +316,7 @@
"cost": 125, "cost": 125,
"culture": 1, "culture": 1,
"isNationalWonder": true, "isNationalWonder": true,
"uniques": ["Requires a [Monument] in all cities", "[+25]% great person generation [in this city]", "Cost increases by [30] per owned city"], "uniques": ["Requires a [Monument] in all cities", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
"requiredTech": "Philosophy" "requiredTech": "Philosophy"
}, },
{ {
@ -380,7 +380,7 @@
// Column 5 // Column 5
{ {
"name": "Garden", "name": "Garden",
"uniques": ["[+25]% great person generation [in this city]", "Must be next to [Fresh water]"], "uniques": ["[+25]% Great Person generation [in this city]", "Must be next to [Fresh water]"],
"hurryCostModifier": 25, "hurryCostModifier": 25,
"maintenance": 1, "maintenance": 1,
"requiredTech": "Theology" "requiredTech": "Theology"
@ -396,7 +396,7 @@
{ {
"name": "Hagia Sophia", "name": "Hagia Sophia",
"isWonder": true, "isWonder": true,
"uniques": ["[+25]% great person generation [in all cities]"], "uniques": ["[+25]% Great Person generation [in all cities]"],
"requiredTech": "Theology", "requiredTech": "Theology",
"quote": "'For it soars to a height to match the sky, and as if surging up from among the other buildings it stands on high and looks down upon the remainder of the city, adorning it, because it is a part of it, but glorying in its own beauty' - Procopius, De Aedificis" "quote": "'For it soars to a height to match the sky, and as if surging up from among the other buildings it stands on high and looks down upon the remainder of the city, adorning it, because it is a part of it, but glorying in its own beauty' - Procopius, De Aedificis"
}, },
@ -434,7 +434,7 @@
"greatPersonPoints": {"Great Merchant": 1}, "greatPersonPoints": {"Great Merchant": 1},
"culture": 1, "culture": 1,
"isWonder": true, "isWonder": true,
"uniques": ["Gold from all trade routes +25%","Must have an owned [Mountain] within [2] tiles"], "uniques": ["[+25]% [Gold] from Trade Routes","Must have an owned [Mountain] within [2] tiles"],
"requiredTech": "Currency", "requiredTech": "Currency",
"quote": "'Few romances can ever surpass that of the granite citadel on top of the beetling precipices of Machu Picchu, the crown of Inca Land.' - Hiram Bingham" "quote": "'Few romances can ever surpass that of the granite citadel on top of the beetling precipices of Machu Picchu, the crown of Inca Land.' - Hiram Bingham"
}, },
@ -627,7 +627,7 @@
"culture": 1, "culture": 1,
"isWonder": true, "isWonder": true,
"greatPersonPoints": {"Great Artist": 1}, "greatPersonPoints": {"Great Artist": 1},
"uniques": ["[-10]% unhappiness from population [in all cities]"], "uniques": ["[-10]% Unhappiness from [Population] [in all cities]"],
"requiredTech": "Banking", "requiredTech": "Banking",
"quote": "'Most of us can, as we choose, make of this world either a palace or a prison' - John Lubbock" "quote": "'Most of us can, as we choose, make of this world either a palace or a prison' - John Lubbock"
}, },

View File

@ -312,7 +312,7 @@
"outerColor": [16,126,5], "outerColor": [16,126,5],
"innerColor": [255,153,51], "innerColor": [255,153,51],
"uniqueName": "Population Growth", "uniqueName": "Population Growth",
"uniques": ["Unhappiness from number of Cities doubled", "[-50]% unhappiness from population [in all cities]"], "uniques": ["Unhappiness from number of Cities doubled", "[-50]% Unhappiness from [Population] [in all cities]"],
"cities": ["Delhi","Mumbai","Vijayanagara","Pataliputra","Varanasi","Agra","Calcutta","Lahore","Bangalore","Hyderabad","Madurai","Ahmedabad", "cities": ["Delhi","Mumbai","Vijayanagara","Pataliputra","Varanasi","Agra","Calcutta","Lahore","Bangalore","Hyderabad","Madurai","Ahmedabad",
"Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur", "Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur",
"Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"] "Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"]

View File

@ -76,7 +76,7 @@
}, },
{ {
"name": "Meritocracy", "name": "Meritocracy",
"uniques": ["[+1 Happiness] [in all cities connected to capital]", "[-5]% unhappiness from population [in all non-occupied cities]"], "uniques": ["[+1 Happiness] [in all cities connected to capital]", "[-5]% Unhappiness from [Population] [in all non-occupied cities]"],
"requires": ["Citizenship"], "requires": ["Citizenship"],
"row": 2, "row": 2,
"column": 5 "column": 5
@ -318,7 +318,7 @@
{ {
"name": "Freedom", "name": "Freedom",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["[+25]% great person generation [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Order]>"], "uniques": ["[+25]% Great Person generation [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Order]>"],
"policies": [ "policies": [
{ {
"name": "Constitution", "name": "Constitution",
@ -347,7 +347,7 @@
}, },
{ {
"name": "Democracy", "name": "Democracy",
"uniques": ["[-50]% unhappiness from specialists [in all cities]"], "uniques": ["[-50]% Unhappiness from [Specialists] [in all cities]"],
"requires": ["Civil Society"], "requires": ["Civil Society"],
"row": 2, "row": 2,
"column": 5 "column": 5

View File

@ -90,7 +90,15 @@ class CityStats(val cityInfo: CityInfo) {
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(UniqueType.StatsFromTradeRoute)) for (unique in cityInfo.getMatchingUniques(UniqueType.StatsFromTradeRoute))
stats.add(unique.stats) stats.add(unique.stats)
if (civInfo.hasUnique(UniqueType.GoldBonusFromTradeRouts)) stats.gold *= 1.25f // Machu Picchu speciality val percentageStats = Stats()
for (unique in cityInfo.getMatchingUniques(UniqueType.StatPercentFromTradeRoutes))
percentageStats[Stat.valueOf(unique.params[0])] += unique.params[0].toFloat()
// Deprecated as of 3.19.19
if (civInfo.hasUnique(UniqueType.GoldBonusFromTradeRoutesDeprecated)) percentageStats[Stat.Gold] += 25f // Machu Picchu speciality
//
for ((stat, value) in stats) {
stats[stat] *= percentageStats[stat].toPercent()
}
} }
return stats return stats
} }
@ -393,27 +401,31 @@ class CityStats(val cityInfo: CityInfo) {
unhappinessFromCity *= 2f //doubled for the Indian unhappinessFromCity *= 2f //doubled for the Indian
newHappinessList["Cities"] = unhappinessFromCity * unhappinessModifier newHappinessList["Cities"] = unhappinessFromCity * unhappinessModifier
var unhappinessFromCitizens = cityInfo.population.population.toFloat() var unhappinessFromCitizens = cityInfo.population.population.toFloat()
var unhappinessFromSpecialists = cityInfo.population.getNumberOfSpecialists().toFloat()
for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromPopulationTypePercentageChange))
for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromSpecialistsPercentageChange)) { if (cityInfo.matchesFilter(unique.params[2]))
if (cityInfo.matchesFilter(unique.params[1])) unhappinessFromCitizens += (unique.params[0].toFloat() / 100f) * cityInfo.population.getPopulationFilterAmount(unique.params[1])
unhappinessFromSpecialists *= unique.params[0].toPercent()
} // Deprecated as of 3.19.19
for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromSpecialistsPercentageChange)) {
unhappinessFromCitizens -= cityInfo.population.getNumberOfSpecialists() if (cityInfo.matchesFilter(unique.params[1]))
.toFloat() - unhappinessFromSpecialists unhappinessFromCitizens += unique.params[0].toFloat() / 100f * cityInfo.population.getNumberOfSpecialists()
}
for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromPopulationPercentageChange))
if (cityInfo.matchesFilter(unique.params[1]))
unhappinessFromCitizens += unique.params[0].toFloat() / 100f * cityInfo.population.population
//
if (cityInfo.isPuppet) if (cityInfo.isPuppet)
unhappinessFromCitizens *= 1.5f unhappinessFromCitizens *= 1.5f
else if (hasExtraAnnexUnhappiness()) else if (hasExtraAnnexUnhappiness())
unhappinessFromCitizens *= 2f unhappinessFromCitizens *= 2f
for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromPopulationPercentageChange)) if (unhappinessFromCitizens < 0) unhappinessFromCitizens = 0f
if (cityInfo.matchesFilter(unique.params[1]))
unhappinessFromCitizens *= unique.params[0].toPercent()
newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier
if (hasExtraAnnexUnhappiness()) newHappinessList["Occupied City"] = -2f //annexed city if (hasExtraAnnexUnhappiness()) newHappinessList["Occupied City"] = -2f //annexed city

View File

@ -49,9 +49,20 @@ class PopulationManager {
foodRequired *= cityInfo.civInfo.gameInfo.getDifficulty().aiCityGrowthModifier foodRequired *= cityInfo.civInfo.gameInfo.getDifficulty().aiCityGrowthModifier
return foodRequired.toInt() return foodRequired.toInt()
} }
//endregion //endregion
fun getPopulationFilterAmount(filter: String): Int {
return when (filter) {
"Specialists" -> getNumberOfSpecialists()
"Population" -> population
"Followers of the Majority Religion", "Followers of this Religion" -> cityInfo.religion.getFollowersOfMajorityReligion()
"Unemployed" -> getFreePopulation()
else -> 0
}
}
fun nextTurn(food: Int) { fun nextTurn(food: Int) {
foodStored += food foodStored += food
if (food < 0) if (food < 0)

View File

@ -171,6 +171,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
state.cityInfo != null && state.cityInfo.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) state.cityInfo != null && state.cityInfo.cityConstructions.containsBuildingOrEquivalent(condition.params[0])
UniqueType.ConditionalCityWithoutBuilding -> UniqueType.ConditionalCityWithoutBuilding ->
state.cityInfo != null && !state.cityInfo.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) state.cityInfo != null && !state.cityInfo.cityConstructions.containsBuildingOrEquivalent(condition.params[0])
UniqueType.ConditionalPopulationFilter ->
state.cityInfo != null && state.cityInfo.population.getPopulationFilterAmount(condition.params[1]) >= condition.params[0].toInt()
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 -> UniqueType.ConditionalFollowerCount ->

View File

@ -136,6 +136,16 @@ enum class UniqueParameterType(var parameterName:String) {
} }
}, },
// //
PopulationFilter("populationFilter") {
private val knownValues = setOf("Population", "Specialists", "Unemployed", "Followers of the Majority Religion", "Followers of this Religion")
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueComplianceErrorSeverity? {
if (parameterText in knownValues) return null
return UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
}
},
TerrainFilter("terrainFilter") { TerrainFilter("terrainFilter") {
private val knownValues = setOf("All", private val knownValues = setOf("All",
Constants.coastal, "River", "Open terrain", "Rough terrain", "Water resource", Constants.coastal, "River", "Open terrain", "Rough terrain", "Water resource",

View File

@ -73,12 +73,13 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
// region Stat providing uniques // region Stat providing uniques
Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief, UniqueTarget.Improvement), Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief, UniqueTarget.Improvement, UniqueTarget.Terrain),
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 // ToDo: Reword to `[stats] <in cities with [amount] or more population>` for consistency with other conditionals
@Deprecated("as of 3.19.19", ReplaceWith("[stats] <in cities with at least [amount] [Population]>"))
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),
@ -88,7 +89,6 @@ 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),
StatsFromTradeRoute("[stats] from each Trade Route", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsFromTradeRoute("[stats] from each Trade Route", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// Stat percentage boosts // Stat percentage boosts
@ -98,7 +98,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
AllStatsPercentFromObject("[amount]% Yield from every [tileFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global), AllStatsPercentFromObject("[amount]% Yield from every [tileFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
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),
GoldBonusFromTradeRouts("Gold from all trade routes +25%", UniqueTarget.Global), StatPercentFromTradeRoutes("[amount]% [stat] from Trade Routes", UniqueTarget.Global),
@Deprecated("as of 3.19.19", ReplaceWith("[+25]% [Gold] from Trade Routes"))
GoldBonusFromTradeRoutesDeprecated("Gold from all trade routes +25%", 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),
@ -154,12 +156,16 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
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), GreatPersonPointPercentage("[amount]% Great Person generation [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.19.19", ReplaceWith("[amount]% Great Person generation [cityFilter]"))
GreatPersonPointPercentageDeprecated("[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),
UnhappinessFromPopulationTypePercentageChange("[amount]% Unhappiness from [populationFilter] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.19.19", ReplaceWith("[amount]% Unhappiness from [Population] [cityFilter]"))
UnhappinessFromPopulationPercentageChange("[amount]% unhappiness from population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), UnhappinessFromPopulationPercentageChange("[amount]% unhappiness from population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 3.19.19", ReplaceWith("[amount]% Unhappiness from [Specialists] [cityFilter]"))
UnhappinessFromSpecialistsPercentageChange("[amount]% unhappiness from specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), UnhappinessFromSpecialistsPercentageChange("[amount]% unhappiness from specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
FoodConsumptionBySpecialists("[amount]% Food consumption by specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), FoodConsumptionBySpecialists("[amount]% Food consumption by specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
HappinessPer2Policies("Provides 1 happiness per 2 additional social policies adopted", UniqueTarget.Global), HappinessPer2Policies("Provides 1 happiness per 2 additional social policies adopted", UniqueTarget.Global),
@ -607,7 +613,10 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
/////// city conditionals /////// city conditionals
ConditionalCityWithBuilding("in cities with a [buildingFilter]", UniqueTarget.Conditional), ConditionalCityWithBuilding("in cities with a [buildingFilter]", UniqueTarget.Conditional),
ConditionalCityWithoutBuilding("in cities without a [buildingFilter]", UniqueTarget.Conditional), ConditionalCityWithoutBuilding("in cities without a [buildingFilter]", UniqueTarget.Conditional),
ConditionalPopulationFilter("in cities with at least [amount] [populationFilter]", UniqueTarget.Conditional),
@Deprecated("as of 3.19.19", ReplaceWith("in cities with at least [amount] [Specialists]"))
ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional), ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional),
@Deprecated("as of 3.19.19", ReplaceWith("in cities with at least [amount] [Followers of the Majority Religion]"))
ConditionalFollowerCount("in cities where this religion has at least [amount] followers", 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),

View File

@ -98,6 +98,12 @@ It can be any value noted in `baseUnitFilter` or one of the following:
- `Barbarians`, `Barbarian` - `Barbarians`, `Barbarian`
- Again, any combination of the above is also allowed, e.g. `[{Wounded} {Water}]` units. - Again, any combination of the above is also allowed, e.g. `[{Wounded} {Water}]` units.
## populationFilter
A filter determining a part of the population of a city. It can be any of the following values:
- `Population`
- `Specialists`
- `Unemployed`
- `Followers of the Majority Religion` or `Followers of this Religion`, both of which only apply when this religion is the majority religion in that city
## regionType ## regionType
Used for dividing the world into regions in each of which a single player is placed at the start of the game. Used for dividing the world into regions in each of which a single player is placed at the start of the game.

View File

@ -71,7 +71,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "[stats]" ??? example "[stats]"
Example: "[+1 Gold, +2 Production]" Example: "[+1 Gold, +2 Production]"
Applicable to: Global, FollowerBelief, Improvement Applicable to: Global, FollowerBelief, Terrain, Improvement
??? example "[stats] [cityFilter]" ??? example "[stats] [cityFilter]"
Example: "[+1 Gold, +2 Production] [in all cities]" Example: "[+1 Gold, +2 Production] [in all cities]"
@ -88,11 +88,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
??? example "[stats] in cities with [amount] or more population"
Example: "[+1 Gold, +2 Production] in cities with [20] or more population"
Applicable to: Global, FollowerBelief
??? example "[stats] in cities on [terrainFilter] tiles" ??? example "[stats] in cities on [terrainFilter] tiles"
Example: "[+1 Gold, +2 Production] in cities on [Forest] tiles" Example: "[+1 Gold, +2 Production] in cities on [Forest] tiles"
@ -153,7 +148,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global Applicable to: Global
??? example "Gold from all trade routes +25%" ??? example "[amount]% [stat] from Trade Routes"
Example: "[20]% [Culture] from Trade Routes"
Applicable to: Global Applicable to: Global
??? example "Nullifies [stat] [cityFilter]" ??? example "Nullifies [stat] [cityFilter]"
@ -273,11 +270,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
??? example "[amount]% great person generation [cityFilter]"
Example: "[20]% great person generation [in all cities]"
Applicable to: Global, FollowerBelief
??? example "May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion" ??? example "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"
@ -288,13 +280,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global Applicable to: Global
??? example "[amount]% unhappiness from population [cityFilter]" ??? example "[amount]% Unhappiness from [populationFilter] [cityFilter]"
Example: "[20]% unhappiness from population [in all cities]" Example: "[20]% Unhappiness from [populationFilter] [in all cities]"
Applicable to: Global, FollowerBelief
??? example "[amount]% unhappiness from specialists [cityFilter]"
Example: "[20]% unhappiness from specialists [in all cities]"
Applicable to: Global, FollowerBelief Applicable to: Global, FollowerBelief
@ -1555,13 +1542,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional Applicable to: Conditional
??? example "&lt;if this city has at least [amount] specialists&gt;" ??? example "&lt;in cities with at least [amount] [populationFilter]&gt;"
Example: "&lt;if this city has at least [20] specialists&gt;" Example: "&lt;in cities with at least [20] [populationFilter]&gt;"
Applicable to: Conditional
??? example "&lt;in cities where this religion has at least [amount] followers&gt;"
Example: "&lt;in cities where this religion has at least [20] followers&gt;"
Applicable to: Conditional Applicable to: Conditional