Unified "X is only available under Y conditions" into a single unique (#6133)

* Unified "X is only available under Y conditions" into a single unique

There were a few problems with existing uniques - they weren't really composable, the offered things they didn't keep, etc

For example, "Incompatible with [policy/tech/promotion]", UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion. In fact, promotions only checked promotion incompatibility, promotions - promotion incompat, etc

Additionally, with a few more changes, this could cover several other uniques - "Hidden until [amount] social policy branches have been completed", "Requires at least [amount] population", perhaps others

I have to say I think conditionals are the best thing ever and they make amazing composability possible :)

* Autoupdate correctly recognizes parameters
Updated ruleset jsons

* Deprecation texts should be allowed to forward to other deprecated uniques so we only need to change the leaves when introducing new uniques, not go through the whole tree
This commit is contained in:
Yair Morgenstern 2022-02-12 19:03:30 +02:00 committed by GitHub
parent 4fb4722e3a
commit e72dcc8b0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 74 additions and 33 deletions

View File

@ -136,7 +136,7 @@
"name": "Piety", "name": "Piety",
"era": "Classical era", "era": "Classical era",
"uniques": ["[+100]% Production when constructing [Shrine] buildings [in all cities]", "[+100]% Production when constructing [Temple] buildings [in all cities]", "uniques": ["[+100]% Production when constructing [Shrine] buildings [in all cities]", "[+100]% Production when constructing [Temple] buildings [in all cities]",
"Incompatible with [Rationalism]"], "Only available <before adopting [Rationalism]>"],
"policies": [ "policies": [
{ {
"name": "Organized Religion", "name": "Organized Religion",
@ -276,7 +276,7 @@
{ {
"name": "Rationalism", "name": "Rationalism",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["[+15]% [Science] <while the empire is happy>", "Incompatible with [Piety]"], "uniques": ["[+15]% [Science] <while the empire is happy>", "Only available <before adopting [Piety]>"],
"policies": [ "policies": [
{ {
"name": "Secularism", "name": "Secularism",
@ -323,7 +323,7 @@
{ {
"name": "Freedom", "name": "Freedom",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["[+25]% great person generation [in all cities]", "Incompatible with [Autocracy]", "Incompatible with [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",
@ -369,7 +369,7 @@
"name": "Autocracy", "name": "Autocracy",
"era": "Industrial era", "era": "Industrial era",
"uniques": ["[-33]% maintenance costs <for [All] units>", "Upon capturing a city, receive [10] times its [Culture] production as [Culture] immediately", "uniques": ["[-33]% maintenance costs <for [All] units>", "Upon capturing a city, receive [10] times its [Culture] production as [Culture] immediately",
"Incompatible with [Order]", "Incompatible with [Freedom]"], "Only available <before adopting [Order]>", "Only available <before adopting [Freedom]>"],
"policies": [ "policies": [
{ {
"name": "Populism", "name": "Populism",
@ -418,7 +418,7 @@
{ {
"name": "Order", "name": "Order",
"era": "Industrial era", "era": "Industrial era",
"uniques": ["[+1 Happiness] [in all cities]", "Incompatible with [Autocracy]", "Incompatible with [Freedom]"], "uniques": ["[+1 Happiness] [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Freedom]>"],
"policies": [ "policies": [
{ {
"name": "United Front", "name": "United Front",

View File

@ -136,7 +136,7 @@
},{ },{
"name": "Piety", "name": "Piety",
"era": "Classical era", "era": "Classical era",
"uniques": ["[+15]% Production when constructing [Culture] buildings [in all cities]", "Incompatible with [Rationalism]"], "uniques": ["[+15]% Production when constructing [Culture] buildings [in all cities]", "Only available <before adopting [Rationalism]>"],
"policies": [ "policies": [
{ {
"name": "Organized Religion", "name": "Organized Religion",
@ -231,8 +231,7 @@
{ {
"name": "Naval Tradition", "name": "Naval Tradition",
"uniques": ["[+1] Movement <for [{Military} {Water}] units>", "[+1] Sight <for [{Military} {Water}] units>", "uniques": ["[+1] Movement <for [{Military} {Water}] units>", "[+1] Sight <for [{Military} {Water}] units>",
"Free [Great General] appears", "[+2] Movement <for [Great Admiral] units>" "Free [Great General] appears" //, "[+2] Movement <for [Great Admiral] units>", "Free [Great Admiral] appears" - todo
// ToDo: Should be "Free [Great Admiral] appears"
], ],
"row": 1, "row": 1,
"column": 2 "column": 2
@ -274,7 +273,7 @@
{ {
"name": "Rationalism", "name": "Rationalism",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["Science gained from research agreements [+50]%", "Incompatible with [Piety]"], "uniques": ["Science gained from research agreements [+50]%", "Only available <before adopting [Piety]>"],
"policies": [ "policies": [
{ {
"name": "Secularism", "name": "Secularism",
@ -319,7 +318,7 @@
{ {
"name": "Freedom", "name": "Freedom",
"era": "Renaissance era", "era": "Renaissance era",
"uniques": ["[+25]% great person generation [in all cities]", "Incompatible with [Autocracy]", "Incompatible with [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",
@ -363,7 +362,7 @@
"name": "Autocracy", "name": "Autocracy",
"era": "Industrial era", "era": "Industrial era",
"uniques": ["[-33]% maintenance costs <for [All] units>", "Upon capturing a city, receive [10] times its [Culture] production as [Culture] immediately", "uniques": ["[-33]% maintenance costs <for [All] units>", "Upon capturing a city, receive [10] times its [Culture] production as [Culture] immediately",
"Incompatible with [Order]", "Incompatible with [Freedom]"], "Only available <before adopting [Order]>", "Only available <before adopting [Freedom]>"],
"policies": [ "policies": [
{ {
"name": "Populism", "name": "Populism",
@ -407,7 +406,7 @@
{ {
"name": "Order", "name": "Order",
"era": "Industrial era", "era": "Industrial era",
"uniques": ["[+1 Happiness] [in all cities]", "Incompatible with [Autocracy]", "Incompatible with [Freedom]"], "uniques": ["[+1 Happiness] [in all cities]", "Only available <before adopting [Autocracy]>", "Only available <before adopting [Freedom]>"],
"policies": [ "policies": [
{ {
"name": "United Front", "name": "United Front",

View File

@ -3,6 +3,7 @@ package com.unciv.logic.civilization
import com.unciv.logic.map.MapSize import com.unciv.logic.map.MapSize
import com.unciv.models.ruleset.Policy import com.unciv.models.ruleset.Policy
import com.unciv.models.ruleset.Policy.PolicyBranchType import com.unciv.models.ruleset.Policy.PolicyBranchType
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueMap import com.unciv.models.ruleset.unique.UniqueMap
import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
@ -118,6 +119,8 @@ class PolicyManager {
if (!getAdoptedPolicies().containsAll(policy.requires!!)) return false if (!getAdoptedPolicies().containsAll(policy.requires!!)) return false
if (checkEra && civInfo.gameInfo.ruleSet.eras[policy.branch.era]!!.eraNumber > civInfo.getEraNumber()) return false if (checkEra && civInfo.gameInfo.ruleSet.eras[policy.branch.era]!!.eraNumber > civInfo.getEraNumber()) return false
if (policy.getMatchingUniques(UniqueType.IncompatibleWith).any { adoptedPolicies.contains(it.params[0]) }) return false if (policy.getMatchingUniques(UniqueType.IncompatibleWith).any { adoptedPolicies.contains(it.params[0]) }) return false
if (policy.uniqueObjects.filter { it.type == UniqueType.OnlyAvailableWhen }
.any { !it.conditionalsApply(civInfo) }) return false
return true return true
} }

View File

@ -132,6 +132,7 @@ class TechManager {
fun canBeResearched(techName: String): Boolean { fun canBeResearched(techName: String): Boolean {
val tech = getRuleset().technologies[techName]!! val tech = getRuleset().technologies[techName]!!
if (tech.uniqueObjects.any { it.type == UniqueType.OnlyAvailableWhen && !it.conditionalsApply(civInfo) })
if (tech.getMatchingUniques(UniqueType.IncompatibleWith).any { isResearched(it.params[0]) }) if (tech.getMatchingUniques(UniqueType.IncompatibleWith).any { isResearched(it.params[0]) })
return false return false
if (isResearched(tech.name) && !tech.isContinuallyResearchable()) if (isResearched(tech.name) && !tech.isContinuallyResearchable())

View File

@ -454,6 +454,8 @@ open class TileInfo {
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty() && neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
) )
) -> false ) -> false
improvement.uniqueObjects.filter { it.type == UniqueType.OnlyAvailableWhen }
.any { !it.conditionalsApply(StateForConditionals(civInfo)) } -> false
improvement.getMatchingUniques(UniqueType.ObsoleteWith).any { improvement.getMatchingUniques(UniqueType.ObsoleteWith).any {
civInfo.tech.isResearched(it.params[0]) civInfo.tech.isResearched(it.params[0])
} -> return false } -> return false

View File

@ -1,5 +1,6 @@
package com.unciv.logic.map package com.unciv.logic.map
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.Promotion import com.unciv.models.ruleset.unit.Promotion
@ -97,6 +98,10 @@ class UnitPromotions {
unique -> !promotions.contains(unique.params[0]) unique -> !promotions.contains(unique.params[0])
} }
} }
.filter { promotion -> promotion.uniqueObjects
.none { it.type == UniqueType.OnlyAvailableWhen
&& !it.conditionalsApply(StateForConditionals(unit.civInfo, unit = unit)) }
}
} }
fun clone(): UnitPromotions { fun clone(): UnitPromotions {

View File

@ -469,6 +469,10 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
for (unique in uniqueObjects) { for (unique in uniqueObjects) {
when (unique.placeholderText) { // TODO: Lots of typification… when (unique.placeholderText) { // TODO: Lots of typification…
UniqueType.OnlyAvailableWhen.placeholderText->
if (!unique.conditionalsApply(civInfo, cityConstructions.cityInfo))
rejectionReasons.add(RejectionReason.ShouldNotBeDisplayed)
UniqueType.NotDisplayedWithout.placeholderText -> UniqueType.NotDisplayedWithout.placeholderText ->
if (unique.params[0] in ruleSet.tileResources && !civInfo.hasResource(unique.params[0]) if (unique.params[0] in ruleSet.tileResources && !civInfo.hasResource(unique.params[0])
|| unique.params[0] in ruleSet.buildings && !cityConstructions.containsBuildingOrEquivalent(unique.params[0]) || unique.params[0] in ruleSet.buildings && !cityConstructions.containsBuildingOrEquivalent(unique.params[0])

View File

@ -124,8 +124,9 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
UniqueType.ConditionalVsCity -> state.theirCombatant?.matchesCategory("City") == true UniqueType.ConditionalVsCity -> state.theirCombatant?.matchesCategory("City") == true
UniqueType.ConditionalVsUnits -> state.theirCombatant?.matchesCategory(condition.params[0]) == true UniqueType.ConditionalVsUnits -> state.theirCombatant?.matchesCategory(condition.params[0]) == true
UniqueType.ConditionalOurUnit -> UniqueType.ConditionalOurUnit ->
state.ourCombatant?.matchesCategory(condition.params[0]) == true relevantUnit?.matchesFilter(condition.params[0]) == true
|| state.unit?.matchesFilter(condition.params[0]) == true UniqueType.ConditionalUnitWithPromotion -> relevantUnit?.promotions?.promotions?.contains(params[0]) == true
UniqueType.ConditionalUnitWithoutPromotion -> relevantUnit?.promotions?.promotions?.contains(params[0]) == false
UniqueType.ConditionalAttacking -> state.combatAction == CombatAction.Attack UniqueType.ConditionalAttacking -> state.combatAction == CombatAction.Attack
UniqueType.ConditionalDefending -> state.combatAction == CombatAction.Defend UniqueType.ConditionalDefending -> state.combatAction == CombatAction.Defend
UniqueType.ConditionalAboveHP -> UniqueType.ConditionalAboveHP ->

View File

@ -29,7 +29,7 @@ object UniqueTriggerActivation {
if (tile != null) Random(tile.position.toString().hashCode()) if (tile != null) Random(tile.position.toString().hashCode())
else Random(-550) // Very random indeed else Random(-550) // Very random indeed
if (!unique.conditionalsApply(StateForConditionals(civInfo, cityInfo))) return false if (!unique.conditionalsApply(civInfo, cityInfo)) return false
val timingConditional = unique.conditionals.firstOrNull{it.type == ConditionalTimedUnique} val timingConditional = unique.conditionals.firstOrNull{it.type == ConditionalTimedUnique}
if (timingConditional!=null) { if (timingConditional!=null) {

View File

@ -279,10 +279,11 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
PopulationLossFromNukesDeprecated("Population loss from nuclear attacks -[amount]%", UniqueTarget.Global), PopulationLossFromNukesDeprecated("Population loss from nuclear attacks -[amount]%", UniqueTarget.Global),
NaturalReligionSpreadStrength("[amount]% Natural religion spread [cityFilter]", UniqueTarget.FollowerBelief, 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]>")) @Deprecated("as of 3.19.3", ReplaceWith("[amount]% Natural religion spread [cityFilter] <after discovering [tech/policy]> OR [amount]% natural religion spread [cityFilter] <after adopting [tech/policy]>"))
NaturalReligionSpreadStrengthWith("[amount]% Natural religion spread [cityFilter] with [tech/policy]", UniqueTarget.Global, UniqueTarget.FollowerBelief), 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), ReligionSpreadDistance("Religion naturally spreads to cities [amount] tiles away", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("as of 3.19.8", ReplaceWith("Only available <before adopting [policy/tech/promotion]> OR <before discovering [policy/tech/promotion]> OR <for units without [policy/tech/promotion]>"))
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),
@ -296,12 +297,17 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
///////////////////////////////////////// region CONSTRUCTION UNIQUES ///////////////////////////////////////// ///////////////////////////////////////// region CONSTRUCTION UNIQUES /////////////////////////////////////////
Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit), Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit),
CannotBePurchased("Cannot be purchased", UniqueTarget.Building, UniqueTarget.Unit), CannotBePurchased("Cannot be purchased", UniqueTarget.Building, UniqueTarget.Unit),
CanBePurchasedWithStat("Can be purchased with [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit), CanBePurchasedWithStat("Can be purchased with [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit),
CanBePurchasedForAmountStat("Can be purchased for [amount] [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit), CanBePurchasedForAmountStat("Can be purchased for [amount] [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit),
MaxNumberBuildable("Limited to [amount] per Civilization", UniqueTarget.Building, UniqueTarget.Unit), MaxNumberBuildable("Limited to [amount] per Civilization", UniqueTarget.Building, UniqueTarget.Unit),
HiddenBeforeAmountPolicies("Hidden until [amount] social policy branches have been completed", UniqueTarget.Building, UniqueTarget.Unit), HiddenBeforeAmountPolicies("Hidden until [amount] social policy branches have been completed", UniqueTarget.Building, UniqueTarget.Unit),
// Meant to be used together with conditionals, like "Only available <after adopting [policy]> <while the empire is happy>"
OnlyAvailableWhen("Only available", UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Improvement,
UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion),
@Deprecated("as of 3.19.8", ReplaceWith("Only available <after adopting [buildingName/tech/resource/policy]> OR <with [buildingName/tech/resource/policy]> OR <after discovering [buildingName/tech/resource/policy]>"))
NotDisplayedWithout("Not displayed as an available construction without [buildingName/tech/resource/policy]", UniqueTarget.Building, UniqueTarget.Unit), NotDisplayedWithout("Not displayed as an available construction without [buildingName/tech/resource/policy]", UniqueTarget.Building, UniqueTarget.Unit),
ConvertFoodToProductionWhenConstructed("Excess Food converted to Production when under construction", UniqueTarget.Building, UniqueTarget.Unit), ConvertFoodToProductionWhenConstructed("Excess Food converted to Production when under construction", UniqueTarget.Building, UniqueTarget.Unit),
RequiresPopulation("Requires at least [amount] population", UniqueTarget.Building, UniqueTarget.Unit), RequiresPopulation("Requires at least [amount] population", UniqueTarget.Building, UniqueTarget.Unit),
@ -557,6 +563,8 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
/////// unit conditionals /////// unit conditionals
ConditionalOurUnit("for [mapUnitFilter] units", UniqueTarget.Conditional), ConditionalOurUnit("for [mapUnitFilter] units", UniqueTarget.Conditional),
ConditionalUnitWithPromotion("for units with [promotion]", UniqueTarget.Conditional),
ConditionalUnitWithoutPromotion("for units without [promotion]", UniqueTarget.Conditional),
ConditionalVsCity("vs cities", UniqueTarget.Conditional), ConditionalVsCity("vs cities", UniqueTarget.Conditional),
ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional), ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional),
ConditionalVsLargerCiv("when fighting units from a Civilization with more Cities than you", UniqueTarget.Conditional), ConditionalVsLargerCiv("when fighting units from a Civilization with more Cities than you", UniqueTarget.Conditional),

View File

@ -351,6 +351,12 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
if (isWaterUnit() && !cityConstructions.cityInfo.isCoastal()) if (isWaterUnit() && !cityConstructions.cityInfo.isCoastal())
rejectionReasons.add(RejectionReason.WaterUnitsInCoastalCities) rejectionReasons.add(RejectionReason.WaterUnitsInCoastalCities)
val civInfo = cityConstructions.cityInfo.civInfo val civInfo = cityConstructions.cityInfo.civInfo
for (unique in uniqueObjects.filter { it.type == UniqueType.OnlyAvailableWhen }){
if (!unique.conditionalsApply(civInfo, cityConstructions.cityInfo))
rejectionReasons.add(RejectionReason.ShouldNotBeDisplayed)
}
for (unique in getMatchingUniques(UniqueType.NotDisplayedWithout)) { for (unique in getMatchingUniques(UniqueType.NotDisplayedWithout)) {
val filter = unique.params[0] val filter = unique.params[0]
if (filter in civInfo.gameInfo.ruleSet.tileResources && !civInfo.hasResource(filter) if (filter in civInfo.gameInfo.ruleSet.tileResources && !civInfo.hasResource(filter)

View File

@ -265,13 +265,20 @@ class TechPickerScreen(
} }
val pathToTech = civTech.getRequiredTechsToDestination(tech) val pathToTech = civTech.getRequiredTechsToDestination(tech)
for (requiredTech in pathToTech) for (requiredTech in pathToTech) {
for (unique in requiredTech.getMatchingUniques(UniqueType.IncompatibleWith)) for (unique in requiredTech.getMatchingUniques(UniqueType.IncompatibleWith))
if (civTech.isResearched(unique.params[0])) { if (civTech.isResearched(unique.params[0])) {
rightSideButton.setText(unique.text.tr()) rightSideButton.setText(unique.text.tr())
rightSideButton.disable() rightSideButton.disable()
return return
} }
for (unique in requiredTech.uniqueObjects
.filter { it.type == UniqueType.OnlyAvailableWhen && !it.conditionalsApply(civInfo) }) {
rightSideButton.setText(unique.text.tr())
rightSideButton.disable()
return
}
}
tempTechsToResearch.clear() tempTechsToResearch.clear()
tempTechsToResearch.addAll(pathToTech.map { it.name }) tempTechsToResearch.addAll(pathToTech.map { it.name })

View File

@ -647,14 +647,12 @@ Example: "Starts with [Agriculture]"
Applicable to: Nation Applicable to: Nation
## Tech uniques ## Tech uniques
#### Incompatible with [policy/tech/promotion]
Example: "Incompatible with [policy/tech/promotion]"
Applicable to: Tech, Policy, Promotion
#### Starting tech #### Starting tech
Applicable to: Tech Applicable to: Tech
#### Only available
Applicable to: Tech, Policy, Building, Unit, Promotion, Improvement
## FollowerBelief uniques ## FollowerBelief uniques
#### [amount]% [stat] from every follower, up to [amount]% #### [amount]% [stat] from every follower, up to [amount]%
Example: "[20]% [Culture] from every follower, up to [20]%" Example: "[20]% [Culture] from every follower, up to [20]%"
@ -703,11 +701,6 @@ Example: "Hidden until [20] social policy branches have been completed"
Applicable to: Building, Unit Applicable to: Building, Unit
#### Not displayed as an available construction without [buildingName/tech/resource/policy]
Example: "Not displayed as an available construction without [buildingName/tech/resource/policy]"
Applicable to: Building, Unit
#### Excess Food converted to Production when under construction #### Excess Food converted to Production when under construction
Applicable to: Building, Unit Applicable to: Building, Unit
@ -1369,6 +1362,16 @@ Example: "<for [Wounded] units>"
Applicable to: Conditional Applicable to: Conditional
#### <for units with [promotion]>
Example: "<for units with [Shock I]>"
Applicable to: Conditional
#### <for units without [promotion]>
Example: "<for units without [Shock I]>"
Applicable to: Conditional
#### <vs cities> #### <vs cities>
Applicable to: Conditional Applicable to: Conditional
@ -1477,7 +1480,7 @@ Applicable to: Conditional
- "[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]" - "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]>" - "[amount]% Natural religion spread [cityFilter] with [tech/policy]" - Deprecated as of 3.19.3, replace with "[amount]% Natural religion spread [cityFilter] <after discovering [tech/policy]> OR [amount]% natural religion spread [cityFilter] <after adopting [tech/policy]>"
- "[amount] HP when healing in [tileFilter] tiles" - Deprecated as of 3.19.4, replace with "[amount] HP when healing <in [tileFilter] tiles>" - "[amount] HP when healing in [tileFilter] tiles" - Deprecated as of 3.19.4, replace with "[amount] HP when healing <in [tileFilter] tiles>"
- "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>"
- "Heal adjacent units for an additional 15 HP per turn" - Deprecated as of 3.19.3, replace with "All adjacent units heal [+15] HP when healing" - "Heal adjacent units for an additional 15 HP per turn" - Deprecated as of 3.19.3, replace with "All adjacent units heal [+15] HP when healing"
@ -1521,6 +1524,8 @@ Applicable to: Conditional
- "-33% unit upkeep costs" - Deprecated Extremely old - used for auto-updates only, replace with "[-33]% maintenance costs <for [All] units>" - "-33% unit upkeep costs" - Deprecated Extremely old - used for auto-updates only, replace with "[-33]% maintenance costs <for [All] units>"
- "-50% food consumption by specialists" - Deprecated Extremely old - used for auto-updates only, replace with "[-50]% Food consumption by specialists [in all cities]" - "-50% food consumption by specialists" - Deprecated Extremely old - used for auto-updates only, replace with "[-50]% Food consumption by specialists [in all cities]"
- "+50% attacking strength for cities with garrisoned units" - Deprecated Extremely old - used for auto-updates only, replace with "[+50]% Strength for cities <with a garrison> <when attacking>" - "+50% attacking strength for cities with garrisoned units" - Deprecated Extremely old - used for auto-updates only, replace with "[+50]% Strength for cities <with a garrison> <when attacking>"
- "Incompatible with [policy/tech/promotion]" - Deprecated as of 3.19.8, replace with "Only available <before adopting [policy/tech/promotion]> OR <before discovering [policy/tech/promotion]> OR <for units without [policy/tech/promotion]>"
- "Not displayed as an available construction without [buildingName/tech/resource/policy]" - Deprecated as of 3.19.8, replace with "Only available <after adopting [buildingName/tech/resource/policy]> OR <with [buildingName/tech/resource/policy]> OR <after discovering [buildingName/tech/resource/policy]>"
- "[stats] with [resource]" - Deprecated as of 3.19.7, replace with "[stats] <with [resource]>" - "[stats] with [resource]" - Deprecated as of 3.19.7, replace with "[stats] <with [resource]>"
- "Not displayed as an available construction unless [buildingName] is built" - Deprecated as of 3.16.11, replace with "Not displayed as an available construction without [buildingName]" - "Not displayed as an available construction unless [buildingName] is built" - Deprecated as of 3.16.11, replace with "Not displayed as an available construction without [buildingName]"
- "[stats] once [tech] is discovered" - Deprecated as of 3.17.10 - removed 3.18.19, replace with "[stats] <after discovering [tech]>" - "[stats] once [tech] is discovered" - Deprecated as of 3.17.10 - removed 3.18.19, replace with "[stats] <after discovering [tech]>"

View File

@ -134,8 +134,8 @@ class BasicTests {
println("${uniqueType.name}'s deprecation text does not match any existing type!'") println("${uniqueType.name}'s deprecation text does not match any existing type!'")
allOK = false allOK = false
} }
if (replacementTextUnique.getDeprecationAnnotation() != null){ if (replacementTextUnique.type == uniqueType){
println("${uniqueType.name}'s deprecation text references another deprecated unique!'") println("${uniqueType.name}'s deprecation text references itself!'")
allOK = false allOK = false
} }
for (conditional in replacementTextUnique.conditionals){ for (conditional in replacementTextUnique.conditionals){