From 984c4d9b2dbc933df73667bb73ec7d2f0cd6bd44 Mon Sep 17 00:00:00 2001 From: Xander Lenstra <71121390+xlenstra@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:05:20 +0100 Subject: [PATCH] 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 --- .../jsons/Civ V - Gods & Kings/Beliefs.json | 14 +++---- .../jsons/Civ V - Gods & Kings/Buildings.json | 12 +++--- .../jsons/Civ V - Gods & Kings/Nations.json | 2 +- .../jsons/Civ V - Gods & Kings/Policies.json | 6 +-- .../jsons/Civ V - Vanilla/Buildings.json | 10 ++--- .../assets/jsons/Civ V - Vanilla/Nations.json | 2 +- .../jsons/Civ V - Vanilla/Policies.json | 6 +-- core/src/com/unciv/logic/city/CityStats.kt | 42 ++++++++++++------- .../com/unciv/logic/city/PopulationManager.kt | 13 +++++- .../com/unciv/models/ruleset/unique/Unique.kt | 2 + .../ruleset/unique/UniqueParameterType.kt | 10 +++++ .../unciv/models/ruleset/unique/UniqueType.kt | 15 +++++-- docs/Modders/unique parameters.md | 6 +++ docs/Modders/uniques.md | 34 ++++----------- 14 files changed, 103 insertions(+), 71 deletions(-) diff --git a/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json b/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json index 177e922512..11ebf89964 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json @@ -30,7 +30,7 @@ { "name": "God of Craftsman", "type": "Pantheon", - "uniques": ["[+1 Production] in cities with [3] or more population"] + "uniques": ["[+1 Production] "] }, { "name": "God of the Open Sky", @@ -55,7 +55,7 @@ { "name": "Goddess of Love", "type": "Pantheon", - "uniques": ["[+1 Happiness] in cities with [6] or more population"] + "uniques": ["[+1 Happiness] "] }, { "name": "Goddess of Protection", @@ -123,7 +123,7 @@ { "name": "Asceticism", "type": "Follower", - "uniques": ["[+1 Happiness] from every [Shrine] "] + "uniques": ["[+1 Happiness] from every [Shrine] "] }, { "name": "Cathedrals", @@ -133,7 +133,7 @@ { "name": "Choral Music", "type": "Follower", - "uniques": ["[+2 Culture] from every [Temple] "] + "uniques": ["[+2 Culture] from every [Temple] "] }, { "name": "Divine inspiration", @@ -148,7 +148,7 @@ { "name": "Guruship", "type": "Follower", - "uniques": ["[+2 Production] "] + "uniques": ["[+2 Production] "] }, { "name": "Holy Warriors", @@ -158,7 +158,7 @@ { "name": "Liturgical Drama", "type": "Follower", - "uniques": ["[+1 Faith] from every [Amphitheater] "] + "uniques": ["[+1 Faith] from every [Amphitheater] "] }, { "name": "Monasteries", @@ -188,7 +188,7 @@ { "name": "Religious Center", "type": "Follower", - "uniques": ["[+2 Happiness] from every [Temple] "] + "uniques": ["[+2 Happiness] from every [Temple] "] }, { "name": "Religious Community", diff --git a/android/assets/jsons/Civ V - Gods & Kings/Buildings.json b/android/assets/jsons/Civ V - Gods & Kings/Buildings.json index 9643f7b26a..80999e73a6 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Buildings.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Buildings.json @@ -354,7 +354,7 @@ "cost": 125, "culture": 1, "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" }, { @@ -437,7 +437,7 @@ // Column 5 { "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, "maintenance": 1, "requiredTech": "Theology" @@ -496,7 +496,7 @@ "greatPersonPoints": {"Great Merchant": 1}, "culture": 1, "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", "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, "isWonder": true, "greatPersonPoints": {"Great Artist": 1}, - "uniques": ["[-10]% unhappiness from population [in all cities]"], + "uniques": ["[-10]% Unhappiness from [Population] [in all cities]"], "requiredTech": "Banking", "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, "isWonder": true, "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", "quote": "'Don't clap too hard - it's a very old building.' - John Osbourne" }, @@ -812,7 +812,7 @@ "specialistSlots": {"Engineer": 1}, "hurryCostModifier": 25, "maintenance": 2, - "uniques": ["[+25]% great person generation [in this city]"], + "uniques": ["[+25]% Great Person generation [in this city]"], "requiredTech": "Economics" }, { diff --git a/android/assets/jsons/Civ V - Gods & Kings/Nations.json b/android/assets/jsons/Civ V - Gods & Kings/Nations.json index 2f854ff80b..f20ec8e2aa 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Nations.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Nations.json @@ -326,7 +326,7 @@ "innerColor": [255,153,51], "favoredReligion": "Hinduism", "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", "Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur", "Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"] diff --git a/android/assets/jsons/Civ V - Gods & Kings/Policies.json b/android/assets/jsons/Civ V - Gods & Kings/Policies.json index 2ddf187113..ed90c9e056 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Policies.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Policies.json @@ -75,7 +75,7 @@ }, { "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"], "row": 2, "column": 5 @@ -323,7 +323,7 @@ { "name": "Freedom", "era": "Renaissance era", - "uniques": ["[+25]% great person generation [in all cities]", "Only available ", "Only available "], + "uniques": ["[+25]% Great Person generation [in all cities]", "Only available ", "Only available "], "policies": [ { "name": "Constitution", @@ -352,7 +352,7 @@ }, { "name": "Democracy", - "uniques": ["[-50]% unhappiness from specialists [in all cities]"], + "uniques": ["[-50]% Unhappiness from [Specialists] [in all cities]"], "requires": ["Civil Society"], "row": 2, "column": 5 diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 6d199b7f7d..8ad6408b8a 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -316,7 +316,7 @@ "cost": 125, "culture": 1, "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" }, { @@ -380,7 +380,7 @@ // Column 5 { "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, "maintenance": 1, "requiredTech": "Theology" @@ -396,7 +396,7 @@ { "name": "Hagia Sophia", "isWonder": true, - "uniques": ["[+25]% great person generation [in all cities]"], + "uniques": ["[+25]% Great Person generation [in all cities]"], "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" }, @@ -434,7 +434,7 @@ "greatPersonPoints": {"Great Merchant": 1}, "culture": 1, "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", "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, "isWonder": true, "greatPersonPoints": {"Great Artist": 1}, - "uniques": ["[-10]% unhappiness from population [in all cities]"], + "uniques": ["[-10]% Unhappiness from [Population] [in all cities]"], "requiredTech": "Banking", "quote": "'Most of us can, as we choose, make of this world either a palace or a prison' - John Lubbock" }, diff --git a/android/assets/jsons/Civ V - Vanilla/Nations.json b/android/assets/jsons/Civ V - Vanilla/Nations.json index 165d50b882..b4c20af7d6 100644 --- a/android/assets/jsons/Civ V - Vanilla/Nations.json +++ b/android/assets/jsons/Civ V - Vanilla/Nations.json @@ -312,7 +312,7 @@ "outerColor": [16,126,5], "innerColor": [255,153,51], "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", "Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur", "Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"] diff --git a/android/assets/jsons/Civ V - Vanilla/Policies.json b/android/assets/jsons/Civ V - Vanilla/Policies.json index c4726007f5..90e868e07f 100644 --- a/android/assets/jsons/Civ V - Vanilla/Policies.json +++ b/android/assets/jsons/Civ V - Vanilla/Policies.json @@ -76,7 +76,7 @@ }, { "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"], "row": 2, "column": 5 @@ -318,7 +318,7 @@ { "name": "Freedom", "era": "Renaissance era", - "uniques": ["[+25]% great person generation [in all cities]", "Only available ", "Only available "], + "uniques": ["[+25]% Great Person generation [in all cities]", "Only available ", "Only available "], "policies": [ { "name": "Constitution", @@ -347,7 +347,7 @@ }, { "name": "Democracy", - "uniques": ["[-50]% unhappiness from specialists [in all cities]"], + "uniques": ["[-50]% Unhappiness from [Specialists] [in all cities]"], "requires": ["Civil Society"], "row": 2, "column": 5 diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 3eca817803..89d2c56b59 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -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) for (unique in cityInfo.getMatchingUniques(UniqueType.StatsFromTradeRoute)) 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 } @@ -393,27 +401,31 @@ class CityStats(val cityInfo: CityInfo) { unhappinessFromCity *= 2f //doubled for the Indian newHappinessList["Cities"] = unhappinessFromCity * unhappinessModifier - + var unhappinessFromCitizens = cityInfo.population.population.toFloat() - var unhappinessFromSpecialists = cityInfo.population.getNumberOfSpecialists().toFloat() - - for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromSpecialistsPercentageChange)) { - if (cityInfo.matchesFilter(unique.params[1])) - unhappinessFromSpecialists *= unique.params[0].toPercent() - } - - unhappinessFromCitizens -= cityInfo.population.getNumberOfSpecialists() - .toFloat() - unhappinessFromSpecialists + + for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromPopulationTypePercentageChange)) + if (cityInfo.matchesFilter(unique.params[2])) + unhappinessFromCitizens += (unique.params[0].toFloat() / 100f) * cityInfo.population.getPopulationFilterAmount(unique.params[1]) + + // Deprecated as of 3.19.19 + for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromSpecialistsPercentageChange)) { + if (cityInfo.matchesFilter(unique.params[1])) + 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) unhappinessFromCitizens *= 1.5f else if (hasExtraAnnexUnhappiness()) unhappinessFromCitizens *= 2f - for (unique in cityInfo.getMatchingUniques(UniqueType.UnhappinessFromPopulationPercentageChange)) - if (cityInfo.matchesFilter(unique.params[1])) - unhappinessFromCitizens *= unique.params[0].toPercent() - + if (unhappinessFromCitizens < 0) unhappinessFromCitizens = 0f + newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier if (hasExtraAnnexUnhappiness()) newHappinessList["Occupied City"] = -2f //annexed city diff --git a/core/src/com/unciv/logic/city/PopulationManager.kt b/core/src/com/unciv/logic/city/PopulationManager.kt index edad27760c..0716777f22 100644 --- a/core/src/com/unciv/logic/city/PopulationManager.kt +++ b/core/src/com/unciv/logic/city/PopulationManager.kt @@ -49,9 +49,20 @@ class PopulationManager { foodRequired *= cityInfo.civInfo.gameInfo.getDifficulty().aiCityGrowthModifier return foodRequired.toInt() } - + //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) { foodStored += food if (food < 0) diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index bd8860a67b..cd798c78e3 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -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]) UniqueType.ConditionalCityWithoutBuilding -> 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 -> state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt() UniqueType.ConditionalFollowerCount -> diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt index d59845e219..11c4d0a4e3 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt @@ -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") { private val knownValues = setOf("All", Constants.coastal, "River", "Open terrain", "Rough terrain", "Water resource", diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index a694fae9eb..551941c146 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -73,12 +73,13 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: // 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), StatsFromSpecialist("[stats] from every specialist [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), StatsPerPopulation("[stats] per [amount] population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), // ToDo: Reword to `[stats] ` for consistency with other conditionals + @Deprecated("as of 3.19.19", ReplaceWith("[stats] ")) StatsFromXPopulation("[stats] in cities with [amount] or more population", 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), // This is a doozy StatsFromObject("[stats] from every [tileFilter/specialist/buildingFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), - StatsFromTradeRoute("[stats] from each Trade Route", UniqueTarget.Global, UniqueTarget.FollowerBelief), // 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), StatPercentFromReligionFollowers("[amount]% [stat] from every follower, up to [amount]%", UniqueTarget.FollowerBelief), 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), 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), 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), 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), + 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), + @Deprecated("As of 3.19.19", ReplaceWith("[amount]% Unhappiness from [Specialists] [cityFilter]")) UnhappinessFromSpecialistsPercentageChange("[amount]% unhappiness from 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), @@ -607,7 +613,10 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: /////// city conditionals ConditionalCityWithBuilding("in cities with 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), + @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), ConditionalWhenGarrisoned("with a garrison", UniqueTarget.Conditional), diff --git a/docs/Modders/unique parameters.md b/docs/Modders/unique parameters.md index c6491a87ba..5a90c1a9b5 100644 --- a/docs/Modders/unique parameters.md +++ b/docs/Modders/unique parameters.md @@ -98,6 +98,12 @@ It can be any value noted in `baseUnitFilter` or one of the following: - `Barbarians`, `Barbarian` - 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 Used for dividing the world into regions in each of which a single player is placed at the start of the game. diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 2862c54d26..abe4ff2404 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -71,7 +71,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "[stats]" Example: "[+1 Gold, +2 Production]" - Applicable to: Global, FollowerBelief, Improvement + Applicable to: Global, FollowerBelief, Terrain, Improvement ??? example "[stats] [cityFilter]" 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 -??? 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: "[+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 -??? example "Gold from all trade routes +25%" +??? example "[amount]% [stat] from Trade Routes" + Example: "[20]% [Culture] from Trade Routes" + Applicable to: Global ??? example "Nullifies [stat] [cityFilter]" @@ -273,11 +270,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl 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 [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 -??? example "[amount]% unhappiness from population [cityFilter]" - Example: "[20]% unhappiness from population [in all cities]" - - Applicable to: Global, FollowerBelief - -??? example "[amount]% unhappiness from specialists [cityFilter]" - Example: "[20]% unhappiness from specialists [in all cities]" +??? example "[amount]% Unhappiness from [populationFilter] [cityFilter]" + Example: "[20]% Unhappiness from [populationFilter] [in all cities]" Applicable to: Global, FollowerBelief @@ -1555,13 +1542,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Conditional -??? example "<if this city has at least [amount] specialists>" - Example: "<if this city has at least [20] specialists>" - - Applicable to: Conditional - -??? example "<in cities where this religion has at least [amount] followers>" - Example: "<in cities where this religion has at least [20] followers>" +??? example "<in cities with at least [amount] [populationFilter]>" + Example: "<in cities with at least [20] [populationFilter]>" Applicable to: Conditional