diff --git a/core/src/com/unciv/logic/battle/ICombatant.kt b/core/src/com/unciv/logic/battle/ICombatant.kt
index 41a76537da..fc7a857c16 100644
--- a/core/src/com/unciv/logic/battle/ICombatant.kt
+++ b/core/src/com/unciv/logic/battle/ICombatant.kt
@@ -18,6 +18,7 @@ interface ICombatant {
fun getTile(): TileInfo
fun isInvisible(to: CivilizationInfo): Boolean
fun canAttack(): Boolean
+ /** Implements [UniqueParameterType.CombatantFilter][com.unciv.models.ruleset.unique.UniqueParameterType.CombatantFilter] */
fun matchesCategory(category:String): Boolean
fun getAttackSound(): UncivSound
diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt
index 036e7408b3..2a8491a107 100644
--- a/core/src/com/unciv/logic/city/CityInfo.kt
+++ b/core/src/com/unciv/logic/city/CityInfo.kt
@@ -827,7 +827,7 @@ class CityInfo {
}
}
- // When adding here, add to UniqueParameterType.cityFilterStrings
+ /** Implements [UniqueParameterType.CityFilter][com.unciv.models.ruleset.unique.UniqueParameterType.CityFilter] */
fun matchesFilter(filter: String, viewingCiv: CivilizationInfo = civInfo): Boolean {
return when (filter) {
"in this city" -> true
diff --git a/core/src/com/unciv/logic/city/PopulationManager.kt b/core/src/com/unciv/logic/city/PopulationManager.kt
index 0716777f22..c48eac9573 100644
--- a/core/src/com/unciv/logic/city/PopulationManager.kt
+++ b/core/src/com/unciv/logic/city/PopulationManager.kt
@@ -49,9 +49,10 @@ class PopulationManager {
foodRequired *= cityInfo.civInfo.gameInfo.getDifficulty().aiCityGrowthModifier
return foodRequired.toInt()
}
-
+
//endregion
+ /** Implements [UniqueParameterType.PopulationFilter][com.unciv.models.ruleset.unique.UniqueParameterType.PopulationFilter] */
fun getPopulationFilterAmount(filter: String): Int {
return when (filter) {
"Specialists" -> getNumberOfSpecialists()
diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt
index 5a8662f4aa..1e8cf1cbb5 100644
--- a/core/src/com/unciv/logic/map/MapUnit.kt
+++ b/core/src/com/unciv/logic/map/MapUnit.kt
@@ -23,6 +23,7 @@ import com.unciv.models.ruleset.unique.UniqueMapTyped
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.ruleset.unit.UnitType
+import com.unciv.ui.utils.filterAndLogic
import com.unciv.ui.utils.toPercent
import java.text.DecimalFormat
import kotlin.math.pow
@@ -177,18 +178,16 @@ class MapUnit {
/**
* Container class to represent a single instant in a [MapUnit]'s recent movement history.
*
- * @property position Position on the map at this instant.
+ * @property position Position on the map at this instant, cloned on instantiation.
* @property type Category of the last change in position that brought the unit to this position.
* @see [movementMemories]
* */
- class UnitMovementMemory() {
- constructor(position: Vector2, type: UnitMovementMemoryType): this() {
- this.position = position
- this.type = type
- }
- lateinit var position: Vector2
- lateinit var type: UnitMovementMemoryType
- fun clone() = UnitMovementMemory(Vector2(position), type)
+ class UnitMovementMemory(position: Vector2, val type: UnitMovementMemoryType) {
+ @Suppress("unused") // needed because this is part of a save and gets deserialized
+ constructor(): this(Vector2.Zero, UnitMovementMemoryType.UnitMoved)
+ val position = Vector2(position)
+
+ fun clone() = UnitMovementMemory(position, type)
override fun toString() = "${this::class.simpleName}($position, $type)"
}
@@ -200,7 +199,7 @@ class MapUnit {
/** Add the current position and the most recent movement type to [movementMemories]. Called once at end and once at start of turn, and at unit creation. */
fun addMovementMemory() {
- movementMemories.add(UnitMovementMemory(Vector2(getTile().position), mostRecentMoveType))
+ movementMemories.add(UnitMovementMemory(getTile().position, mostRecentMoveType))
while (movementMemories.size > 2) { // O(n) but n == 2.
// Keep at most one arrow segment— A lot of the time even that won't be rendered because the two positions will be the same.
// When in the unit's turn— I.E. For a player unit— The last two entries will be from .endTurn() followed by from .startTurn(), so the segment from .movementMemories will have zero length. Instead, what gets seen will be the segment from the end of .movementMemories to the unit's current position.
@@ -1090,12 +1089,11 @@ class MapUnit {
)
}
+ /** Implements [UniqueParameterType.MapUnitFilter][com.unciv.models.ruleset.unique.UniqueParameterType.MapUnitFilter] */
fun matchesFilter(filter: String): Boolean {
- if (filter.contains('{')) // multiple types at once - AND logic. Looks like:"{Military} {Land}"
- return filter.removePrefix("{").removeSuffix("}").split("} {")
- .all { matchesFilter(it) }
-
- return when (filter) {
+ return filter.filterAndLogic { matchesFilter(it) } // multiple types at once - AND logic. Looks like:"{Military} {Land}"
+ ?: when (filter) {
+
// todo: unit filters should be adjectives, fitting "[filterType] units"
// This means converting "wounded units" to "Wounded", "Barbarians" to "Barbarian"
"Wounded", "wounded units" -> health < 100
diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt
index e9f7961337..c1ddec6a00 100644
--- a/core/src/com/unciv/logic/map/TileInfo.kt
+++ b/core/src/com/unciv/logic/map/TileInfo.kt
@@ -543,16 +543,14 @@ open class TileInfo {
}
}
- /**
- * Implementation of _`tileFilter`_
- * @see tileFilter
- */
+ /** Implements [UniqueParameterType.TileFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TileFilter] */
fun matchesFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean {
if (matchesTerrainFilter(filter, civInfo)) return true
if (improvement != null && ruleset.tileImprovements[improvement]!!.matchesFilter(filter)) return true
return improvement == null && filter == "unimproved"
}
+ /** Implements [UniqueParameterType.TerrainFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TerrainFilter] */
fun matchesTerrainFilter(filter: String, observingCiv: CivilizationInfo? = null): Boolean {
return when (filter) {
"All" -> true
diff --git a/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt b/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt
index 7a299470a6..d5d2b6bc2f 100644
--- a/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt
+++ b/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt
@@ -176,6 +176,7 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
tile.setTerrainTransients()
}
+ /** Implements [UniqueParameterType.SimpleTerrain][com.unciv.models.ruleset.unique.UniqueParameterType.SimpleTerrain] */
private fun TileInfo.matchesWonderFilter(filter: String) = when (filter) {
"Elevated" -> baseTerrain == Constants.mountain || isHill()
"Water" -> isWater
diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt
index 51d9c9f685..c78e60a1ae 100644
--- a/core/src/com/unciv/models/ruleset/Building.kt
+++ b/core/src/com/unciv/models/ruleset/Building.kt
@@ -706,6 +706,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
return true
}
+ /** Implements [UniqueParameterType.BuildingFilter] */
fun matchesFilter(filter: String): Boolean {
return when (filter) {
"All" -> true
diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt
index b34ce6f349..1d6f48156d 100644
--- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt
+++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt
@@ -77,6 +77,7 @@ class TileImprovement : RulesetStatsObject() {
*/
fun isAllowedOnFeature(name: String) = getMatchingUniques(UniqueType.NoFeatureRemovalNeeded).any { it.params[0] == name }
+ /** Implements [UniqueParameterType.ImprovementFilter][com.unciv.models.ruleset.unique.UniqueParameterType.ImprovementFilter] */
fun matchesFilter(filter: String): Boolean {
return when (filter) {
name -> true
diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt
index 061610510a..95cd7d78a6 100644
--- a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt
+++ b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt
@@ -8,7 +8,9 @@ import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.stats.Stat
import com.unciv.models.translations.TranslationFileWriter // for Kdoc only
+import com.unciv.ui.utils.filterCompositeLogic
+// 'region' names beginning with an underscore are used here for a prettier "Structure window" - they go in front ot the rest.
/**
* These manage validation of parameters in [Unique]s and
@@ -21,15 +23,30 @@ import com.unciv.models.translations.TranslationFileWriter // for Kdoc only
* Legacy placeholder guessing for untyped uniques in [TranslationFileWriter] is done by
* [guessTypeForTranslationWriter] utilizing the [isTranslationWriterGuess] overloads.
*
- * @param parameterName placeholder name used by [UniqueType] for matching
- * @param displayName used by [TranslationFileWriter] for section header comments
+ * @param parameterName placeholder name used by [UniqueType] for matching.
+ * @param docExample used by UniqueDocsWriter to fill parameters with plausible values for the examples.
+ * @param docDescription used by UniqueDocsWriter to generate the Abbreviations list at the end for types that can be explained in one long line. Should be omitted when the Wiki contains a paragraph for this type.
+ * @param displayName used by [TranslationFileWriter] for section header comments - needed _only_ if [getTranslationWriterStringsForOutput] returns a non-empty list.
*/
+//region _Fields
@Suppress("unused") // Some are used only via enumerating the enum matching on parameterName
enum class UniqueParameterType(
- var parameterName:String,
+ var parameterName: String,
+ val docExample: String,
+ val docDescription: String? = null,
val displayName: String = parameterName
) {
- Number("amount") {
+ //endregion
+
+ Number("amount", "3", "This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`") {
+ override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
+ UniqueType.UniqueComplianceErrorSeverity? {
+ return if (parameterText.toIntOrNull() == null) UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
+ else null
+ }
+ },
+
+ RelativeNumber("relativeAmount", "+20", "This indicates a number, usually with a + or - sign, such as `+25` (this kind of parameter is often followed by '%' which is nevertheless not part of the value)") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
return if (parameterText.toIntOrNull() == null) UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
@@ -38,44 +55,48 @@ enum class UniqueParameterType(
},
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
- KeywordAll("'all'") {
+ KeywordAll("'all'", "All") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
if (parameterText == "All") null else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
},
- CombatantFilter("combatantFilter") {
+ /** Implemented by [ICombatant.matchesCategory][com.unciv.logic.battle.ICombatant.matchesCategory] */
+ CombatantFilter("combatantFilter", "City", "This indicates a combatant, which can either be a unit or a city (when bombarding). Must either be `City` or a `mapUnitFilter`") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
- if (parameterText == "City") return null
+ if (parameterText == "City") return null // City also recognizes "All" but that's covered by UnitTypeFilter too
return MapUnitFilter.getErrorSeverity(parameterText, ruleset)
}
-
},
- MapUnitFilter("mapUnitFilter", "Map Unit Filters") {
+ /** Implemented by [MapUnit.matchesFilter][com.unciv.logic.map.MapUnit.matchesFilter] */
+ MapUnitFilter("mapUnitFilter", "Wounded", null, "Map Unit Filters") {
private val knownValues = setOf("Wounded", Constants.barbarians, "City-State", "Embarked", "Non-City")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if ('{' in parameterText) // "{filter} {filter}" for and logic
- return parameterText.removePrefix("{").removeSuffix("}").split("} {")
- .mapNotNull { getErrorSeverity(it, ruleset) }
- .maxByOrNull { it.ordinal }
+ return parameterText.filterCompositeLogic({ getErrorSeverity(it, ruleset) }) { a, b -> maxOf(a, b) }
if (parameterText in knownValues) return null
return BaseUnitFilter.getErrorSeverity(parameterText, ruleset)
}
override fun getTranslationWriterStringsForOutput() = knownValues
},
- BaseUnitFilter("baseUnitFilter") {
+ /** Implemented by [BaseUnit.matchesFilter][com.unciv.models.ruleset.unit.BaseUnit.matchesFilter] */
+ BaseUnitFilter("baseUnitFilter", "Melee") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
+ if ('{' in parameterText) // "{filter} {filter}" for and logic
+ return parameterText.filterCompositeLogic({ getErrorSeverity(it, ruleset) }) { a, b -> maxOf(a, b) }
if (UnitName.getErrorSeverity(parameterText, ruleset) == null) return null
if (ruleset.units.values.any { it.uniques.contains(parameterText) }) return null
return UnitTypeFilter.getErrorSeverity(parameterText, ruleset)
}
},
- UnitTypeFilter("unitType", "Unit Type Filters") {
+ /** Implemented by [UnitType.matchesFilter][com.unciv.models.ruleset.unit.UnitType.matchesFilter] */
+ //todo there is a large discrepancy between this parameter type and the actual filter, most of these are actually implemented by BaseUnitFilter
+ UnitTypeFilter("unitType", "Water", null, "Unit Type Filters") {
// As you can see there is a difference between these and what's in unitTypeStrings (for translation) -
// the goal is to unify, but for now this is the "real" list
// Note: this can't handle combinations of parameters (e.g. [{Military} {Water}])
@@ -101,7 +122,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- UnitName("unit") {
+ /** Only used by [BaseUnitFilter] */
+ UnitName("unit", "Musketman") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (ruleset.units.containsKey(parameterText)) return null
@@ -109,7 +131,8 @@ enum class UniqueParameterType(
}
},
- GreatPerson("greatPerson") {
+ /** Used by [UniqueType.GreatPersonEarnedFaster] */
+ GreatPerson("greatPerson", "Great General") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
@@ -119,7 +142,8 @@ enum class UniqueParameterType(
}
},
- Stats("stats") {
+ /** Implemented in [Unique.stats][com.unciv.models.ruleset.unique.Unique.stats] */
+ Stats("stats", "+1 Gold, +2 Production", "For example: `+2 Production, +3 Food`. Note that the stat names need to be capitalized!") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (com.unciv.models.stats.Stats.isStats(parameterText)) return null
@@ -127,7 +151,8 @@ enum class UniqueParameterType(
}
},
- StatName("stat") {
+ /** Many UniqueTypes like [UniqueType.StatPercentBonus] */
+ StatName("stat", "Culture", "This is one of the 7 major stats in the game - `Gold`, `Science`, `Production`, `Food`, `Happiness`, `Culture` and `Faith`. Note that the stat names need to be capitalized!") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (Stat.values().any { it.name == parameterText }) return null
@@ -135,7 +160,8 @@ enum class UniqueParameterType(
}
},
- PlunderableStatName("plunderableStat") {
+ /** [UniqueType.DamageUnitsPlunder] and others near that one */
+ PlunderableStatName("plunderableStat", "Gold", "All the following stats can be plundered: `Gold`, `Science`, `Culture`, `Faith`") {
private val knownValues = setOf(Stat.Gold.name, Stat.Science.name, Stat.Culture.name, Stat.Faith.name)
override fun getErrorSeverity(
parameterText: String,
@@ -146,7 +172,8 @@ enum class UniqueParameterType(
}
},
- CityFilter("cityFilter", "City filters") {
+ /** Implemented by [CityInfo.matchesFilter][com.unciv.logic.city.CityInfo.matchesFilter] */
+ CityFilter("cityFilter", "in all cities", null, "City filters") {
private val cityFilterStrings = setOf(
"in this city",
"in all cities",
@@ -175,7 +202,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = cityFilterStrings
},
- BuildingName("buildingName") {
+ /** Used by [BuildingFilter] and e.g. [UniqueType.ConditionalCityWithBuilding] */
+ BuildingName("buildingName", "Library", "The name of any building") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
@@ -185,7 +213,8 @@ enum class UniqueParameterType(
}
},
- BuildingFilter("buildingFilter") {
+ /** Implemented by [Building.matchesFilter][com.unciv.models.ruleset.Building.matchesFilter] */
+ BuildingFilter("buildingFilter", "Culture") {
private val knownValues = mutableSetOf("All","Building","Buildings","Wonder","Wonders","National Wonder","World Wonder")
.apply { addAll(Stat.values().map { it.name }) }
override fun getErrorSeverity(
@@ -201,8 +230,9 @@ enum class UniqueParameterType(
parameterText != "All" && getErrorSeverity(parameterText, ruleset) == null
},
- // Only used in values deprecated in 3.17.10
- ConstructionFilter("constructionFilter") {
+ /** [UniqueType.PercentProductionConstructions], [UniqueType.PercentProductionConstructionsCities] */
+ @Deprecated("as of 3.17.10 - removed 3.18.5")
+ ConstructionFilter("constructionFilter", "Spaceship Part") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
@@ -212,9 +242,9 @@ enum class UniqueParameterType(
return UniqueType.UniqueComplianceErrorSeverity.WarningOnly
}
},
- //
- PopulationFilter("populationFilter", "Population Filters") {
+ /** Implemented by [PopulationManager.getPopulationFilterAmount][com.unciv.logic.city.PopulationManager.getPopulationFilterAmount] */
+ PopulationFilter("populationFilter", "Followers of this Religion", null, "Population Filters") {
private val knownValues = setOf("Population", "Specialists", "Unemployed", "Followers of the Majority Religion", "Followers of this Religion")
override fun getErrorSeverity(
parameterText: String,
@@ -226,7 +256,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- TerrainFilter("terrainFilter", "Terrain Filters") {
+ /** Implemented by [TileInfo.matchesTerrainFilter][com.unciv.logic.map.TileInfo.matchesTerrainFilter] */
+ TerrainFilter("terrainFilter", Constants.freshWaterFilter, null, "Terrain Filters") {
private val knownValues = setOf("All",
Constants.coastal, "River", "Open terrain", "Rough terrain", "Water resource",
"Foreign Land", "Foreign", "Friendly Land", "Friendly", "Enemy Land", "Enemy",
@@ -246,7 +277,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- TileFilter("tileFilter", "Tile Filters") {
+ /** Implemented by [TileInfo.matchesFilter][com.unciv.logic.map.TileInfo.matchesFilter] */
+ TileFilter("tileFilter", "Farm", "Anything that can be used either in an improvementFilter or in a terrainFilter can be used here, plus 'unimproved'", "Tile Filters") {
private val knownValues = setOf("unimproved", "All Road", "Great Improvement")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
@@ -257,8 +289,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- /** Used by NaturalWonderGenerator, only tests base terrain or a feature */
- SimpleTerrain("simpleTerrain") {
+ /** Used by [NaturalWonderGenerator][com.unciv.logic.map.mapgenerator.NaturalWonderGenerator], only tests base terrain or a feature */
+ SimpleTerrain("simpleTerrain", "Elevated") {
private val knownValues = setOf("Elevated", "Water", "Land")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
@@ -268,8 +300,8 @@ enum class UniqueParameterType(
}
},
- /** Used by NaturalWonderGenerator, only tests base terrain */
- BaseTerrain("baseTerrain") {
+ /** Used by [NaturalWonderGenerator.trySpawnOnSuitableLocation][com.unciv.logic.map.mapgenerator.NaturalWonderGenerator.trySpawnOnSuitableLocation], only tests base terrain */
+ BaseTerrain("baseTerrain", Constants.grassland, "The name of any terrain that is a base terrain according to the json file") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (ruleset.terrains[parameterText]?.type?.isBaseTerrain == true) return null
@@ -277,7 +309,9 @@ enum class UniqueParameterType(
}
},
- TerrainName("terrainName") {
+ /** Used by: [UniqueType.LandUnitsCrossTerrainAfterUnitGained] (CivilizationInfo.addUnit),
+ * [UniqueType.ChangesTerrain] (MapGenerator.convertTerrains) */
+ TerrainName("terrainName", Constants.forest) {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (ruleset.terrains.containsKey(parameterText)) return null
@@ -285,8 +319,10 @@ enum class UniqueParameterType(
}
},
- /** Used for region definitions, can be a terrain type with region unique, or "Hybrid" */
- RegionType("regionType", "Region Types") {
+ /** Used for region definitions, can be a terrain type with region unique, or "Hybrid"
+ *
+ * See also: [UniqueType.ConditionalInRegionOfType], [UniqueType.ConditionalInRegionExceptOfType], [MapRegions][com.unciv.logic.map.mapgenerator.MapRegions] */
+ RegionType("regionType", "Hybrid", null, "Region Types") {
private val knownValues = setOf("Hybrid")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
@@ -299,8 +335,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- /** Used for start placements */
- TerrainQuality("terrainQuality", "Terrain Quality") {
+ /** Used for start placements: [UniqueType.HasQuality], MapRegions.MapGenTileData.evaluate */
+ TerrainQuality("terrainQuality", "Undesirable", null, "Terrain Quality") {
private val knownValues = setOf("Undesirable", "Food", "Desirable", "Production")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
@@ -310,7 +346,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- Promotion("promotion") {
+ /** [UniqueType.UnitStartingPromotions], [UniqueType.TerrainGrantsPromotion], [UniqueType.ConditionalUnitWithPromotion] and others */
+ Promotion("promotion", "Shock I", "The name of any promotion") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.unitPromotions -> null
@@ -318,7 +355,8 @@ enum class UniqueParameterType(
}
},
- Era("era") {
+ /** [UniqueType.OneTimeFreeTechRuins], [UniqueType.ConditionalDuringEra] and similar */
+ Era("era", "Ancient era", "The name of any era") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.eras -> null
@@ -326,7 +364,8 @@ enum class UniqueParameterType(
}
},
- ImprovementName("improvementName"){
+ /** [UniqueType.ConstructImprovementConsumingUnit] */
+ ImprovementName("improvementName", "Trading Post", "The name of any improvement"){
override fun getErrorSeverity(parameterText: String,ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (ruleset.tileImprovements.containsKey(parameterText)) return null
@@ -334,8 +373,8 @@ enum class UniqueParameterType(
}
},
- /** should mirror TileImprovement.matchesFilter exactly */
- ImprovementFilter("improvementFilter", "Improvement Filters") {
+ /** Implemented by [TileImprovement.matchesFilter][com.unciv.models.ruleset.tile.TileImprovement.matchesFilter] */
+ ImprovementFilter("improvementFilter", "All Road", null, "Improvement Filters") {
private val knownValues = setOf("All", "All Road", "Great Improvement", "Great")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
@@ -349,7 +388,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- Resource("resource") {
+ /** Used by [UniqueType.ConsumesResources] and others, implementation not centralized */
+ Resource("resource", "Iron", "The name of any resource") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.tileResources -> null
@@ -357,7 +397,8 @@ enum class UniqueParameterType(
}
},
- BeliefTypeName("beliefType") {
+ /** Used by [UniqueType.FreeExtraBeliefs], see ReligionManager.getBeliefsToChooseAt* functions */
+ BeliefTypeName("beliefType", "Follower", "'Pantheon', 'Follower', 'Founder' or 'Enhancer'") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in BeliefType.values().map { it.name } -> null
@@ -365,7 +406,8 @@ enum class UniqueParameterType(
}
},
- Belief("belief") {
+ /** unused at the moment with vanilla rulesets */
+ Belief("belief", "God of War", "The name of any belief") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.beliefs -> null
@@ -373,7 +415,8 @@ enum class UniqueParameterType(
}
},
- FoundingOrEnhancing("foundingOrEnhancing", "Prophet Action Filters") {
+ /** Used by [UniqueType.FreeExtraBeliefs] and its any variant, see ReligionManager.getBeliefsToChooseAt* functions */
+ FoundingOrEnhancing("foundingOrEnhancing", "founding", "`founding` or `enhancing`", "Prophet Action Filters") {
// Used in FreeExtraBeliefs, FreeExtraAnyBeliefs
private val knownValues = setOf("founding", "enhancing")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
@@ -384,18 +427,8 @@ enum class UniqueParameterType(
override fun getTranslationWriterStringsForOutput() = knownValues
},
- //TODO the Unique "Can [] [] times" that should use this isn't typed yet
- ReligiousAction("religiousAction", "Religious Action Filters") {
- private val knownValues = setOf(Constants.spreadReligionAbilityCount, Constants.removeHeresyAbilityCount)
- override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
- UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
- in knownValues -> null
- else -> UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
- }
- override fun getTranslationWriterStringsForOutput() = knownValues
- },
-
- Technology("tech") {
+ /** [UniqueType.ConditionalTech] and others, no central implementation */
+ Technology("tech", "Agriculture", "The name of any tech") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.technologies -> null
@@ -403,7 +436,8 @@ enum class UniqueParameterType(
}
},
- Specialist("specialist") {
+ /** unused at the moment with vanilla rulesets */
+ Specialist("specialist", "Merchant", "The name of any specialist") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
in ruleset.specialists -> null
@@ -411,7 +445,8 @@ enum class UniqueParameterType(
}
},
- Policy("policy") {
+ /** [UniqueType.ConditionalPolicy] and others, no central implementation */
+ Policy("policy", "Oligarchy", "The name of any policy") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
@@ -423,7 +458,8 @@ enum class UniqueParameterType(
}
},
- VictoryT("victoryType") {
+ /** Used by [UniqueType.HiddenWithoutVictoryType], implementation in Civilopedia and OverviewScreen */
+ VictoryT("victoryType", "Domination", "The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
@@ -433,7 +469,8 @@ enum class UniqueParameterType(
}
},
- CostOrStrength("costOrStrength") {
+ /** Used by [UniqueType.KillUnitPlunder] and [UniqueType.KillUnitPlunderNearCity], implementation in [Battle.tryEarnFromKilling][com.unciv.logic.battle.Battle.tryEarnFromKilling] */
+ CostOrStrength("costOrStrength", "Cost", "`Cost` or `Strength`") {
private val knownValues = setOf("Cost", "Strength")
override fun getErrorSeverity(
parameterText: String,
@@ -444,7 +481,8 @@ enum class UniqueParameterType(
}
},
- Action("action") {
+ /** For untyped "Can [] [] times" unique */
+ Action("action", Constants.spreadReligionAbilityCount, "An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'", "Religious Action Filters") {
private val knownValues = setOf(Constants.spreadReligionAbilityCount, Constants.removeHeresyAbilityCount)
override fun getErrorSeverity(
parameterText: String,
@@ -453,21 +491,23 @@ enum class UniqueParameterType(
return if (parameterText in knownValues) null
else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
}
+ override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
- Comment("comment", "Unique Specials") {
+ Comment("comment", "comment", null, "Unique Specials") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = null
override fun getTranslationWriterStringsForOutput() = scanExistingValues(this)
},
- Unknown("param") {
+ Unknown("param", "Unknown") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? = null
};
+ //region _Internals
/** Validate a [Unique] parameter */
abstract fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueComplianceErrorSeverity?
@@ -518,6 +558,8 @@ enum class UniqueParameterType(
fun safeValueOf(param: String) = values().firstOrNull { it.parameterName == param }
?: Unknown.apply { this.parameterName = param } //TODO Danger: There is only one instance of Unknown!
}
+
+ //endregion
}
diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt
index 8b101bbcac..091042e780 100644
--- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt
+++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt
@@ -409,6 +409,7 @@ object UniqueTriggerActivation {
val revealedTiles = nearbyRevealableTiles
.shuffled(tileBasedRandom)
.apply {
+ // Implements [UniqueParameterType.CombatantFilter] - At the moment the only use
if (unique.params[0] != "All") this.take(unique.params[0].toInt())
}
for (position in revealedTiles) {
diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt
index 736957b4c6..a337a7697d 100644
--- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt
+++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt
@@ -92,23 +92,23 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
StatsFromTradeRoute("[stats] from each Trade Route", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// Stat percentage boosts
- StatPercentBonus("[amount]% [stat]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- StatPercentBonusCities("[amount]% [stat] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- StatPercentFromObject("[amount]% [stat] from every [tileFilter/specialist/buildingName]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- 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),
- StatPercentFromTradeRoutes("[amount]% [stat] from Trade Routes", UniqueTarget.Global),
+ StatPercentBonus("[relativeAmount]% [stat]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ StatPercentBonusCities("[relativeAmount]% [stat] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ StatPercentFromObject("[relativeAmount]% [stat] from every [tileFilter/specialist/buildingName]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ AllStatsPercentFromObject("[relativeAmount]% Yield from every [tileFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
+ StatPercentFromReligionFollowers("[relativeAmount]% [stat] from every follower, up to [relativeAmount]%", UniqueTarget.FollowerBelief),
+ BonusStatsFromCityStates("[relativeAmount]% [stat] from City-States", UniqueTarget.Global),
+ StatPercentFromTradeRoutes("[relativeAmount]% [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),
- PercentProductionWonders("[amount]% Production when constructing [buildingFilter] wonders [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),
- PercentProductionBuildingsInCapital("[amount]% Production towards any buildings that already exist in the Capital", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ PercentProductionWonders("[relativeAmount]% Production when constructing [buildingFilter] wonders [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ PercentProductionBuildings("[relativeAmount]% Production when constructing [buildingFilter] buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ PercentProductionUnits("[relativeAmount]% Production when constructing [baseUnitFilter] units [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ PercentProductionBuildingsInCapital("[relativeAmount]% Production towards any buildings that already exist in the Capital", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// todo: maybe should be converted to "[+100]% Yield from every [Natural Wonder]"?
DoubleStatsFromNaturalWonders("Tile yields from Natural Wonders doubled", UniqueTarget.Global),
@@ -127,18 +127,18 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
CityStateGiftedUnitsStartWithXp("Military Units gifted from City-States start with [amount] XP", UniqueTarget.Global),
CityStateMoreGiftedUnits("Militaristic City-States grant units [amount] times as fast when you are at war with a common nation", UniqueTarget.Global),
- CityStateGoldGiftsProvideMoreInfluence("Gifts of Gold to City-States generate [amount]% more Influence", UniqueTarget.Global),
+ CityStateGoldGiftsProvideMoreInfluence("Gifts of Gold to City-States generate [relativeAmount]% more Influence", UniqueTarget.Global),
CityStateCanBeBoughtForGold("Can spend Gold to annex or puppet a City-State that has been your ally for [amount] turns.", UniqueTarget.Global),
CityStateTerritoryAlwaysFriendly("City-State territory always counts as friendly territory", UniqueTarget.Global),
CityStateCanGiftGreatPeople("Allied City-States will occasionally gift Great People", UniqueTarget.Global), // used in Policy
CityStateDeprecated("Will not be chosen for new games", UniqueTarget.Nation), // implemented for CS only for now
- CityStateInfluenceDegradation("[amount]% City-State Influence degradation", UniqueTarget.Global),
+ CityStateInfluenceDegradation("[relativeAmount]% City-State Influence degradation", UniqueTarget.Global),
CityStateRestingPoint("Resting point for Influence with City-States is increased by [amount]", UniqueTarget.Global),
- CityStateStatPercent("Allied City-States provide [stat] equal to [amount]% of what they produce for themselves", UniqueTarget.Global),
- CityStateResources("[amount]% resources gifted by City-States", UniqueTarget.Global),
- CityStateLuxuryHappiness("[amount]% Happiness from luxury resources gifted by City-States", UniqueTarget.Global),
+ CityStateStatPercent("Allied City-States provide [stat] equal to [relativeAmount]% of what they produce for themselves", UniqueTarget.Global),
+ CityStateResources("[relativeAmount]% resources gifted by City-States", UniqueTarget.Global),
+ CityStateLuxuryHappiness("[relativeAmount]% Happiness from luxury resources gifted by City-States", UniqueTarget.Global),
CityStateInfluenceRecoversTwiceNormalRate("City-State Influence recovers at twice the normal rate", UniqueTarget.Global),
// endregion
@@ -151,28 +151,28 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
ConsumesResources("Consumes [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit),
ProvidesResources("Provides [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building),
- GrowthPercentBonus("[amount]% growth [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- CarryOverFood("[amount]% Food is carried over after population increases [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ GrowthPercentBonus("[relativeAmount]% growth [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ CarryOverFood("[relativeAmount]% Food is carried over after population increases [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
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),
+ GreatPersonPointPercentage("[relativeAmount]% Great Person generation [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ @Deprecated("As of 3.19.19", ReplaceWith("[relativeAmount]% Great Person generation [cityFilter]"))
+ GreatPersonPointPercentageDeprecated("[relativeAmount]% 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),
+ UnhappinessFromPopulationTypePercentageChange("[relativeAmount]% Unhappiness from [populationFilter] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ @Deprecated("As of 3.19.19", ReplaceWith("[relativeAmount]% Unhappiness from [Population] [cityFilter]"))
+ UnhappinessFromPopulationPercentageChange("[relativeAmount]% unhappiness from population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ @Deprecated("As of 3.19.19", ReplaceWith("[relativeAmount]% Unhappiness from [Specialists] [cityFilter]"))
+ UnhappinessFromSpecialistsPercentageChange("[relativeAmount]% unhappiness from specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ FoodConsumptionBySpecialists("[relativeAmount]% Food consumption by specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
HappinessPer2Policies("Provides 1 happiness per 2 additional social policies adopted", UniqueTarget.Global),
- ExcessHappinessToGlobalStat("[amount]% of excess happiness converted to [stat]", UniqueTarget.Global),
+ ExcessHappinessToGlobalStat("[relativeAmount]% of excess happiness converted to [stat]", UniqueTarget.Global),
- BorderGrowthPercentage("[amount]% Culture cost of natural border growth [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- TileCostPercentage("[amount]% Gold cost of acquiring tiles [cityFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
+ BorderGrowthPercentage("[relativeAmount]% Culture cost of natural border growth [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ TileCostPercentage("[relativeAmount]% Gold cost of acquiring tiles [cityFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
// There is potential to merge these
BuyUnitsIncreasingCost("May buy [baseUnitFilter] units for [amount] [stat] [cityFilter] at an increasing price ([amount])", UniqueTarget.Global, UniqueTarget.FollowerBelief),
BuyBuildingsIncreasingCost("May buy [buildingFilter] buildings for [amount] [stat] [cityFilter] at an increasing price ([amount])", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@@ -189,28 +189,29 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
EnablesGoldProduction("Enables conversion of city production to gold", UniqueTarget.Global),
EnablesScienceProduction("Enables conversion of city production to science", UniqueTarget.Global),
- BuyItemsDiscount("[stat] cost of purchasing items in cities [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- BuyBuildingsDiscount("[stat] cost of purchasing [buildingFilter] buildings [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
- BuyUnitsDiscount("[stat] cost of purchasing [baseUnitFilter] units [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ BuyItemsDiscount("[stat] cost of purchasing items in cities [relativeAmount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ BuyBuildingsDiscount("[stat] cost of purchasing [buildingFilter] buildings [relativeAmount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ BuyUnitsDiscount("[stat] cost of purchasing [baseUnitFilter] units [relativeAmount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// Should be replaced with moddable improvements when roads become moddable
RoadMovementSpeed("Improves movement speed on roads",UniqueTarget.Global),
RoadsConnectAcrossRivers("Roads connect tiles across rivers", UniqueTarget.Global),
- RoadMaintenance("[amount]% maintenance on road & railroads", UniqueTarget.Global),
- BuildingMaintenance("[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ RoadMaintenance("[relativeAmount]% maintenance on road & railroads", UniqueTarget.Global),
+ BuildingMaintenance("[relativeAmount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
// This should probably support conditionals, e.g.
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),
MayanCalendarDisplay("Once The Long Count activates, the year on the world screen displays as the traditional Mayan Long Count.", UniqueTarget.Global),
- RetainHappinessFromLuxury("Retain [amount]% of the happiness from a luxury after the last copy has been traded away", UniqueTarget.Global),
+ RetainHappinessFromLuxury("Retain [relativeAmount]% of the happiness from a luxury after the last copy has been traded away", UniqueTarget.Global),
BonusHappinessFromLuxury("[amount] Happiness from each type of luxury resource", UniqueTarget.Global),
- LessPolicyCostFromCities("Each city founded increases culture cost of policies [amount]% less than normal", UniqueTarget.Global),
- LessPolicyCost("[amount]% Culture cost of adopting new Policies", UniqueTarget.Global),
+ LessPolicyCostFromCities("Each city founded increases culture cost of policies [relativeAmount]% less than normal", UniqueTarget.Global),
+ LessPolicyCost("[relativeAmount]% Culture cost of adopting new Policies", UniqueTarget.Global),
- StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[amount]%", UniqueTarget.Global), // used in Policy
+ // Todo: Sign should not be part of the unique placeholder
+ StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[relativeAmount]%", UniqueTarget.Global), // used in Policy
DoubleResourceProduced("Double quantity of [resource] produced", UniqueTarget.Global),
// Todo: should probably be changed to "[stats] from every known Natural Wonder", and that'll give us the global unique as well
DoubleHappinessFromNaturalWonders("Double Happiness from Natural Wonders", UniqueTarget.Global),
@@ -238,16 +239,16 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
GainFromDefeatingUnit("When defeating a [mapUnitFilter] unit, earn [amount] Gold and recruit it", UniqueTarget.Global),
TripleGoldFromEncampmentsAndCities("Receive triple Gold from Barbarian encampments and pillaging Cities", UniqueTarget.Global),
CitiesAreRazedXTimesFaster("Cities are razed [amount] times as fast", UniqueTarget.Global),
- GreatPersonBoostWithFriendship("When declaring friendship, both parties gain a [amount]% boost to great person generation", UniqueTarget.Global),
+ GreatPersonBoostWithFriendship("When declaring friendship, both parties gain a [relativeAmount]% boost to great person generation", UniqueTarget.Global),
NoImprovementMaintenanceInSpecificTiles("No Maintenance costs for improvements in [tileFilter] tiles", UniqueTarget.Global),
- OtherCivsCityStateRelationsDegradeFaster("Influence of all other civilizations with all city-states degrades [amount]% faster", UniqueTarget.Global),
+ OtherCivsCityStateRelationsDegradeFaster("Influence of all other civilizations with all city-states degrades [relativeAmount]% faster", UniqueTarget.Global),
LandUnitsCrossTerrainAfterUnitGained("Land units may cross [terrainName] tiles after the first [baseUnitFilter] is earned", UniqueTarget.Global),
GainInfluenceWithUnitGiftToCityState("Gain [amount] Influence with a [baseUnitFilter] gift to a City-State", UniqueTarget.Global),
- FaithCostOfGreatProphetChange("[amount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global),
+ FaithCostOfGreatProphetChange("[relativeAmount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global),
RestingPointOfCityStatesFollowingReligionChange("Resting point for Influence with City-States following this religion [amount]", UniqueTarget.Global),
@Deprecated("as of 4.0.3", ReplaceWith("[+amount]% Strength "))
StrengthWithinTilesOfTile("+[amount]% Strength if within [amount2] tiles of a [tileFilter]", UniqueTarget.Global),
- StatBonusPercentFromCityStates("[amount]% [stat] from City-States", UniqueTarget.Global),
+ StatBonusPercentFromCityStates("[relativeAmount]% [stat] from City-States", UniqueTarget.Global),
ProvidesGoldWheneverGreatPersonExpended("Provides a sum of gold each time you spend a Great Person", UniqueTarget.Global),
ProvidesStatsWheneverGreatPersonExpended("[stats] whenever a Great Person is expended", UniqueTarget.Global),
@@ -259,19 +260,19 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
EnablesOpenBorders("Enables Open Borders agreements", UniqueTarget.Global),
// Should the 'R' in 'Research agreements' be capitalized?
EnablesResearchAgreements("Enables Research agreements", UniqueTarget.Global),
- ScienceFromResearchAgreements("Science gained from research agreements [amount]%", UniqueTarget.Global),
+ ScienceFromResearchAgreements("Science gained from research agreements [relativeAmount]%", UniqueTarget.Global),
TriggersVictory("Triggers victory", UniqueTarget.Global),
TriggersCulturalVictory("Triggers a Cultural Victory upon completion", UniqueTarget.Global),
- BetterDefensiveBuildings("[amount]% City Strength from defensive buildings", UniqueTarget.Global),
- TileImprovementTime("[amount]% tile improvement construction time", UniqueTarget.Global, UniqueTarget.Unit),
- PercentGoldFromTradeMissions("[amount]% Gold from Great Merchant trade missions", UniqueTarget.Global),
+ BetterDefensiveBuildings("[relativeAmount]% City Strength from defensive buildings", UniqueTarget.Global),
+ TileImprovementTime("[relativeAmount]% tile improvement construction time", UniqueTarget.Global, UniqueTarget.Unit),
+ PercentGoldFromTradeMissions("[relativeAmount]% 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),
- GoldenAgeLength("[amount]% Golden Age length", UniqueTarget.Global),
+ GoldenAgeLength("[relativeAmount]% Golden Age length", UniqueTarget.Global),
- StrengthForCities("[amount]% Strength for cities", UniqueTarget.Global, UniqueTarget.FollowerBelief),
+ StrengthForCities("[relativeAmount]% Strength for cities", 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),
@@ -284,9 +285,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
@Deprecated("as of 3.19.9", ReplaceWith("Enables embarkation for land units \", \"Enables [All] units to enter ocean tiles "))
EmbarkAndEnterOcean("Can embark and move over Coasts and Oceans immediately", UniqueTarget.Global),
- PopulationLossFromNukes("Population loss from nuclear attacks [amount]% [cityFilter]", UniqueTarget.Global),
+ PopulationLossFromNukes("Population loss from nuclear attacks [relativeAmount]% [cityFilter]", UniqueTarget.Global),
- NaturalReligionSpreadStrength("[amount]% Natural religion spread [cityFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
+ NaturalReligionSpreadStrength("[relativeAmount]% Natural religion spread [cityFilter]", UniqueTarget.FollowerBelief, UniqueTarget.Global),
ReligionSpreadDistance("Religion naturally spreads to cities [amount] tiles away", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("as of 3.19.8", ReplaceWith("Only available " +
@@ -399,9 +400,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
BuildImprovements("Can build [improvementFilter/terrainFilter] improvements on tiles", UniqueTarget.Unit),
CreateWaterImprovements("May create improvements on water resources", UniqueTarget.Unit),
- Strength("[amount]% Strength", UniqueTarget.Unit, UniqueTarget.Global),
- StrengthNearCapital("[amount]% Strength decreasing with distance from the capital", UniqueTarget.Unit, UniqueTarget.Global),
- FlankAttackBonus("[amount]% to Flank Attack bonuses", UniqueTarget.Unit, UniqueTarget.Global),
+ Strength("[relativeAmount]% Strength", UniqueTarget.Unit, UniqueTarget.Global),
+ StrengthNearCapital("[relativeAmount]% Strength decreasing with distance from the capital", UniqueTarget.Unit, UniqueTarget.Global),
+ FlankAttackBonus("[relativeAmount]% to Flank Attack bonuses", UniqueTarget.Unit, UniqueTarget.Global),
// There's currently no conditional that would allow you strength vs city-state *cities* and that's why this isn't deprecated yet
StrengthBonusVsCityStates("+30% Strength when fighting City-State units and cities", UniqueTarget.Global),
@@ -409,7 +410,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
Sight("[amount] Sight", UniqueTarget.Unit, UniqueTarget.Global, UniqueTarget.Terrain),
Range("[amount] Range", UniqueTarget.Unit, UniqueTarget.Global),
Heal("[amount] HP when healing", UniqueTarget.Unit, UniqueTarget.Global),
- SpreadReligionStrength("[amount]% Spread Religion Strength", UniqueTarget.Unit, UniqueTarget.Global),
+ SpreadReligionStrength("[relativeAmount]% Spread Religion Strength", UniqueTarget.Unit, UniqueTarget.Global),
MayFoundReligion("May found a religion", UniqueTarget.Unit),
MayEnhanceReligion("May enhance a religion", UniqueTarget.Unit),
@@ -458,9 +459,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
CarryExtraAirUnits("Can carry [amount] extra [mapUnitFilter] units", UniqueTarget.Unit),
CannotBeCarriedBy("Cannot be carried by [mapUnitFilter] units", UniqueTarget.Unit),
- UnitMaintenanceDiscount("[amount]% maintenance costs", UniqueTarget.Unit, UniqueTarget.Global),
- UnitUpgradeCost("[amount]% Gold cost of upgrading", UniqueTarget.Unit, UniqueTarget.Global),
- GreatPersonEarnedFaster("[greatPerson] is earned [amount]% faster", UniqueTarget.Unit, UniqueTarget.Global),
+ UnitMaintenanceDiscount("[relativeAmount]% maintenance costs", UniqueTarget.Unit, UniqueTarget.Global),
+ UnitUpgradeCost("[relativeAmount]% Gold cost of upgrading", UniqueTarget.Unit, UniqueTarget.Global),
+ GreatPersonEarnedFaster("[greatPerson] is earned [relativeAmount]% faster", UniqueTarget.Unit, UniqueTarget.Global),
DamageUnitsPlunder("Earn [amount]% of the damage done to [combatantFilter] units as [plunderableStat]", UniqueTarget.Unit, UniqueTarget.Global),
CaptureCityPlunder("Upon capturing a city, receive [amount] times its [stat] production as [plunderableStat] immediately", UniqueTarget.Unit, UniqueTarget.Global),
@@ -469,7 +470,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
KillUnitCapture("May capture killed [mapUnitFilter] units", UniqueTarget.Unit),
FlatXPGain("[amount] XP gained from combat", UniqueTarget.Unit, UniqueTarget.Global),
- PercentageXPGain("[amount]% XP gained from combat", UniqueTarget.Unit, UniqueTarget.Global),
+ PercentageXPGain("[relativeAmount]% XP gained from combat", UniqueTarget.Unit, UniqueTarget.Global),
Invisible("Invisible to others", UniqueTarget.Unit),
InvisibleToNonAdjacent("Invisible to non-adjacent units", UniqueTarget.Unit),
@@ -584,7 +585,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
CannotBuildOnTile("Cannot be built on [tileFilter] tiles", UniqueTarget.Improvement),
NoFeatureRemovalNeeded("Does not need removal of [tileFilter]", UniqueTarget.Improvement),
- DefensiveBonus("Gives a defensive bonus of [amount]%", UniqueTarget.Improvement),
+ DefensiveBonus("Gives a defensive bonus of [relativeAmount]%", UniqueTarget.Improvement),
ImprovementMaintenance("Costs [amount] gold per turn when in your territory", UniqueTarget.Improvement), // Unused
DamagesAdjacentEnemyUnits("Adjacent enemy units ending their turn take [amount] damage", UniqueTarget.Improvement),
@@ -621,7 +622,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
ConditionalFirstCivToResearch("if no other Civilization has researched this", UniqueTarget.Conditional),
ConditionalTech("after discovering [tech]", UniqueTarget.Conditional),
ConditionalNoTech("before discovering [tech]", UniqueTarget.Conditional),
- ConditionalWhenTech("upon discovering [tech]", UniqueTarget.Conditional),
+ ConditionalWhenTech("upon discovering [tech]", UniqueTarget.Conditional), //todo no references anywhere
ConditionalPolicy("after adopting [policy]", UniqueTarget.Conditional),
ConditionalNoPolicy("before adopting [policy]", UniqueTarget.Conditional),
ConditionalBuildingBuilt("if [buildingName] is constructed", UniqueTarget.Conditional),
@@ -680,7 +681,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
OneTimeGainPopulationRandomCity("[amount] population in a random city", UniqueTarget.Ruins),
OneTimeFreeTech("Free Technology", UniqueTarget.Triggerable), // used in Buildings
OneTimeAmountFreeTechs("[amount] Free Technologies", UniqueTarget.Triggerable), // used in Policy
- OneTimeFreeTechRuins("[amount] free random researchable Tech(s) from the [era]", UniqueTarget.Ruins), // todo: Not picked up by TranslationFileWriter?
+ OneTimeFreeTechRuins("[amount] free random researchable Tech(s) from the [era]", UniqueTarget.Ruins),
OneTimeRevealEntireMap("Reveals the entire map", UniqueTarget.Triggerable), // used in tech
OneTimeGainStat("Gain [amount] [stat]", UniqueTarget.Ruins),
OneTimeGainStatRange("Gain [amount]-[amount] [stat]", UniqueTarget.Ruins),
@@ -958,18 +959,24 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
;
+ /** A map of allowed [UniqueParameterType]s per parameter position. Initialized from overridable function [parameterTypeMapInitializer]. */
+ val parameterTypeMap = parameterTypeMapInitializer()
+
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually
* For 95% of cases, auto-matching is fine. */
- val parameterTypeMap = ArrayList>()
- val targetTypes = HashSet()
-
- init {
+ open fun parameterTypeMapInitializer(): ArrayList> {
+ val map = ArrayList>()
for (placeholder in text.getPlaceholderParameters()) {
val matchingParameterTypes = placeholder
.split('/')
.map { UniqueParameterType.safeValueOf(it.replace(numberRegex, "")) }
- parameterTypeMap.add(matchingParameterTypes)
+ map.add(matchingParameterTypes)
}
+ return map
+ }
+ val targetTypes = HashSet()
+
+ init {
targetTypes.addAll(targets)
}
diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt
index 9a0679e8d7..9e05a65655 100644
--- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt
+++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt
@@ -13,6 +13,7 @@ import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.utils.Fonts
+import com.unciv.ui.utils.filterAndLogic
import com.unciv.ui.utils.toPercent
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
@@ -534,12 +535,11 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
else ruleset.units[replaces!!]!!
}
+ /** Implements [UniqueParameterType.BaseUnitFilter][com.unciv.models.ruleset.unique.UniqueParameterType.BaseUnitFilter] */
fun matchesFilter(filter: String): Boolean {
- if (filter.contains('{')) // multiple types at once - AND logic. Looks like:"{Military} {Land}"
- return filter.removePrefix("{").removeSuffix("}").split("} {")
- .all { matchesFilter(it) }
+ return filter.filterAndLogic { matchesFilter(it) } // multiple types at once - AND logic. Looks like:"{Military} {Land}"
+ ?: when (filter) {
- return when (filter) {
unitType -> true
name -> true
replaces -> true
diff --git a/core/src/com/unciv/models/ruleset/unit/UnitType.kt b/core/src/com/unciv/models/ruleset/unit/UnitType.kt
index 42d7c38d82..54a92ffb7e 100644
--- a/core/src/com/unciv/models/ruleset/unit/UnitType.kt
+++ b/core/src/com/unciv/models/ruleset/unit/UnitType.kt
@@ -27,13 +27,14 @@ class UnitType() : RulesetObject() {
this.name = name
this.movementType = domain
}
-
+
fun getMovementType() = unitMovementType
-
+
fun isLandUnit() = unitMovementType == UnitMovementType.Land
fun isWaterUnit() = unitMovementType == UnitMovementType.Water
fun isAirUnit() = unitMovementType == UnitMovementType.Air
-
+
+ /** Implements [UniqueParameterType.UnitTypeFilter][com.unciv.models.ruleset.unique.UniqueParameterType.UnitTypeFilter] */
fun matchesFilter(filter: String): Boolean {
return when (filter) {
"Land" -> isLandUnit()
@@ -44,7 +45,7 @@ class UnitType() : RulesetObject() {
}
}
}
-
+
companion object {
val City = UnitType("City", "Land")
}
diff --git a/core/src/com/unciv/ui/utils/ExtensionFunctions.kt b/core/src/com/unciv/ui/utils/ExtensionFunctions.kt
index 3d9b8b5df0..b23ba65a6f 100644
--- a/core/src/com/unciv/ui/utils/ExtensionFunctions.kt
+++ b/core/src/com/unciv/ui/utils/ExtensionFunctions.kt
@@ -358,4 +358,17 @@ fun (() -> Unit).wrapCrashHandlingUnit(
val wrappedReturning = this.wrapCrashHandling(postToMainThread)
// Don't instantiate a new lambda every time the return get called.
return { wrappedReturning() ?: Unit }
-}
\ No newline at end of file
+}
+
+/** For filters containing '{', apply the [predicate] to each part inside "{}" and aggregate using [operation];
+ * otherwise return `null` for Elvis chaining of the individual filter. */
+fun String.filterCompositeLogic(predicate: (String) -> T?, operation: (T, T) -> T): T? {
+ val elements: List = removePrefix("{").removeSuffix("}").split("} {")
+ .mapNotNull(predicate)
+ if (elements.isEmpty()) return null
+ return elements.reduce(operation)
+}
+/** If a filter string contains '{', apply the [predicate] to each part inside "{}" then 'and' (`&&`) them together;
+ * otherwise return `null` for Elvis chaining of the individual filter. */
+fun String.filterAndLogic(predicate: (String) -> Boolean): Boolean? =
+ if (contains('{')) filterCompositeLogic(predicate) { a, b -> a && b } else null
diff --git a/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt b/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt
index 03b6244199..9cedf344e0 100644
--- a/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt
+++ b/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt
@@ -1,103 +1,92 @@
package com.unciv.app.desktop
-import com.unciv.models.ruleset.Ruleset
+import com.unciv.models.ruleset.unique.UniqueParameterType
import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType
+import com.unciv.models.translations.fillPlaceholders
import java.io.File
class UniqueDocsWriter {
+ companion object {
+ /**
+ * Switch from each Unique shown once under one UniqueTarget heading chosen from targetTypes (`true`)
+ * to showing each Unique repeatedly under each UniqueTarget heading it applies to (`false`).
+ */
+ private const val showUniqueOnOneTarget = true
+
+ /** Switch **on** the display of _inherited_ UniqueTargets in "Applicable to:" */
+ private const val showInheritedTargets = false
+
+ private fun UniqueTarget.allTargets(): Sequence = sequence {
+ if (showInheritedTargets && inheritsFrom != null) yieldAll(inheritsFrom!!.allTargets())
+ yield(this@allTargets)
+ }
+ private fun UniqueType.allTargets(): Sequence =
+ targetTypes.asSequence().flatMap { it.allTargets() }.distinct()
+ private fun UniqueTarget.allUniqueTypes(): Sequence =
+ UniqueType.values().asSequence().filter {
+ this in it.targetTypes
+ }
+ }
fun toLink(string: String): String {
return "#" + string.split(' ').joinToString("-") { it.lowercase() }
}
fun write() {
- val lines = ArrayList()
- val targetTypesToUniques = UniqueType.values().groupBy { it.targetTypes.minOrNull()!! }
- .toSortedMap()
+ // This will output each unique only once, even if it has several targets.
+ // Each is grouped under the UniqueTarget is is allowed for with the lowest enum ordinal.
+ // UniqueTarget.inheritsFrom is _not_ resolved for this.
+ // The UniqueType are shown in enum order within their group, and groups are ordered
+ // by their UniqueTarget.ordinal as well - source code order.
+ val targetTypesToUniques: Map> =
+ if(showUniqueOnOneTarget)
+ UniqueType.values().asSequence()
+ .groupBy { it.targetTypes.minOrNull()!! }
+ .toSortedMap()
+ else
+ // if, on the other hand, we wish to list every UniqueType with multiple targets under
+ // _each_ of the groups it is applicable to, then this might do:
+ UniqueTarget.values().asSequence().associateWith { target ->
+ target.allTargets().flatMap { inheritedTarget ->
+ inheritedTarget.allUniqueTypes()
+ }.distinct().toList()
+ }
- fun replaceExamples(text:String):String {
- return text
- .replace("[amount]", "[20]")
- .replace("[combatantFilter]", "[City]")
- .replace("[mapUnitFilter]", "[Wounded]")
- .replace("[baseUnitFilter]", "[Melee]")
- .replace("[unit]","[Musketman]")
- .replace("[great person]", "[Great Scientist]")
- .replace("[stats]", "[+1 Gold, +2 Production]")
- .replace("[stat]", "[Culture]")
- .replace("[plunderableStat]", "[Gold]")
- .replace("[cityFilter]", "[in all cities]")
- .replace("[buildingName]", "[Library]")
- .replace("[buildingFilter]", "[Culture]")
- .replace("[constructionFilter]", "[Spaceship Part]")
- .replace("[terrainFilter]", "[Forest]")
- .replace("[tileFilter]", "[Farm]")
- .replace("[simpleTerrain]", "[Elevated]")
- .replace("[baseTerrain]", "[Grassland]")
- .replace("[regionType]", "[Hybrid]")
- .replace("[terrainQuality]","[Undesirable]")
- .replace("[promotion]","[Shock I]")
- .replace("[era]", "[Ancient era]")
- .replace("[improvementName]", "[Trading Post]")
- .replace("[improvementFilter]", "[All Road]")
- .replace("[resource]", "[Iron]")
- .replace("[beliefType]", "[Follower]")
- .replace("[belief]","[God of War]")
- .replace("[foundingOrEnhancing]", "[founding]")
- .replace("[tech]", "[Agriculture]")
- .replace("[specialist]","[Merchant]")
- .replace("[policy]", "[Oligarchy]")
- .replace("[victoryType]", "[Domination]")
- .replace("[costOrStrength]", "[Cost]")
- }
-
- lines += "# Uniques\n" +
- "Simple unique parameters are explained by mouseover. Complex parameters are explained in [Unique parameter types](../unique parameters)"
+ val capacity = 25 + targetTypesToUniques.size + UniqueType.values().size * (if (showUniqueOnOneTarget) 3 else 16)
+ val lines = ArrayList(capacity)
+ lines += "# Uniques"
+ lines += "Simple unique parameters are explained by mouseover. Complex parameters are explained in [Unique parameter types](../unique parameters)"
-
- val deprecatedUniques = ArrayList()
- for (targetType in targetTypesToUniques) {
- lines += "## " + targetType.key.name + " uniques"
- for (uniqueType in targetType.value) {
+ for ((targetType, uniqueTypes) in targetTypesToUniques) {
+ if (uniqueTypes.isEmpty()) continue
+ lines += "## " + targetType.name + " uniques"
+ for (uniqueType in uniqueTypes) {
if (uniqueType.getDeprecationAnnotation() != null) continue
- val uniqueText = if (targetType.key == UniqueTarget.Conditional) "<${uniqueType.text}>"
+ val uniqueText = if (targetType == UniqueTarget.Conditional) "<${uniqueType.text}>"
else uniqueType.text
lines += "??? example \"$uniqueText\"" // collapsable material mkdocs block, see https://squidfunk.github.io/mkdocs-material/reference/admonitions/?h=%3F%3F%3F#collapsible-blocks
- if (uniqueType.text.contains('['))
- lines += "\tExample: \"${replaceExamples(uniqueText)}\"\n"
- lines += "\tApplicable to: " + uniqueType.targetTypes.sorted().joinToString()
+ if (uniqueType.parameterTypeMap.isNotEmpty()) {
+ // This one will give examples for _each_ filter in a "tileFilter/specialist/buildingFilter" kind of parameter e.g. "Farm/Merchant/Library":
+ // `val paramExamples = uniqueType.parameterTypeMap.map { it.joinToString("/") { pt -> pt.docExample } }.toTypedArray()`
+ // Might confuse modders to think "/" can go into the _actual_ unique and mean "or", so better show just one ("Farm" in the example above):
+ val paramExamples = uniqueType.parameterTypeMap.map { it.first().docExample }.toTypedArray()
+ lines += "\tExample: \"${uniqueText.fillPlaceholders(*paramExamples)}\"\n"
+ }
+ lines += "\tApplicable to: " + uniqueType.allTargets().sorted().joinToString()
lines += ""
}
}
-
- // Abbreviations, for adding short unique parameter help - see https://squidfunk.github.io/mkdocs-material/reference/abbreviations/
+ // Abbreviations, for adding short unique parameter help - see https://squidfunk.github.io/mkdocs-material/reference/abbreviations/
lines += ""
- lines += "*[amount]: This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`."
- lines += "*[baseTerrain]: The name of any terrain that is a base terrain according to the json file."
- lines += "*[action]: An action that a unit can preform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'"
- lines += "*[belief]: The name of any belief"
- lines += "*[beliefType]: 'Pantheon', 'Follower', 'Founder' or 'Enhancer'."
- lines += "*[victoryType]: The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'"
- lines += "*[tech]: The name of any tech"
- lines += "*[resource]: The name of any resource"
- lines += "*[specialist]: The name of any specialist"
- lines += "*[promotion]: The name of any promotion"
- lines += "*[policy]: The name of any policy"
- lines += "*[improvementName]: The name of any improvement"
- lines += "*[buildingName]: The name of any building"
- lines += "*[era]: The name of any era"
- lines += "*[constructionFilter]: A filter for used when testing the current construction of a city. All values of `baseUnitFilter` and `buildingFilter` are allowed."
- lines += "*[foundingOrEnhancing]: `founding` or `enhancing`"
- lines += "*[costOrStrength]: `Cost` or `Strength`"
- lines += "*[combatantFilter]: This indicates a combatant, which can either be a unit or a city (when bombarding). Must either be `City` or a `mapUnitFilter`."
- lines += "*[plunderableStat]: All the following stats can be plundered: `Gold`, `Science`, `Culture`, `Faith`"
- lines += "*[tileFilter]: Anything that can be used either in an improvementFilter or in a tileFilter can be used here"
- lines += "*[stat]: This is one of the 7 major stats in the game - `Gold`, `Science`, `Production`, `Food`, `Happiness`, `Culture` and `Faith`. Note that the stat names need to be capitalized!"
- lines += "*[stats]: For example: `+2 Production, +3 Food`. Note that the stat names need to be capitalized!"
-
-
+ // order irrelevant for rendered wiki, but could potentially reduce source control differences
+ for (paramType in UniqueParameterType.values().asSequence().sortedBy { it.parameterName }) {
+ if (paramType.docDescription == null) continue
+ val punctuation = if (paramType.docDescription!!.last().category == '.'.category) "" else "."
+ lines += "*[${paramType.parameterName}]: ${paramType.docDescription}$punctuation"
+ }
+
File("../../docs/Modders/uniques.md").writeText(lines.joinToString("\n"))
}
-}
\ No newline at end of file
+}
diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md
index 4fcdde3c5c..2604250a73 100644
--- a/docs/Modders/uniques.md
+++ b/docs/Modders/uniques.md
@@ -7,7 +7,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "[amount] free [baseUnitFilter] units appear"
- Example: "[20] free [Melee] units appear"
+ Example: "[3] free [Melee] units appear"
Applicable to: Triggerable
@@ -15,7 +15,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "[amount] Free Social Policies"
- Example: "[20] Free Social Policies"
+ Example: "[3] Free Social Policies"
Applicable to: Triggerable
@@ -26,7 +26,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "[amount] population [cityFilter]"
- Example: "[20] population [in all cities]"
+ Example: "[3] population [in all cities]"
Applicable to: Triggerable
@@ -34,7 +34,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "[amount] Free Technologies"
- Example: "[20] Free Technologies"
+ Example: "[3] Free Technologies"
Applicable to: Triggerable
@@ -55,12 +55,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "Provides the cheapest [stat] building in your first [amount] cities for free"
- Example: "Provides the cheapest [Culture] building in your first [20] cities for free"
+ Example: "Provides the cheapest [Culture] building in your first [3] cities for free"
Applicable to: Triggerable
??? example "Provides a [buildingName] in your first [amount] cities for free"
- Example: "Provides a [Library] in your first [20] cities for free"
+ Example: "Provides a [Library] in your first [3] cities for free"
Applicable to: Triggerable
@@ -84,12 +84,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief
??? example "[stats] per [amount] population [cityFilter]"
- Example: "[+1 Gold, +2 Production] per [20] population [in all cities]"
+ Example: "[+1 Gold, +2 Production] per [3] population [in all cities]"
Applicable to: Global, FollowerBelief
??? 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 [Fresh Water] tiles"
Applicable to: Global, FollowerBelief
@@ -114,7 +114,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief
??? example "[stats] from every [tileFilter/specialist/buildingFilter]"
- Example: "[+1 Gold, +2 Production] from every [tileFilter/specialist/buildingFilter]"
+ Example: "[+1 Gold, +2 Production] from every [Farm]"
Applicable to: Global, FollowerBelief
@@ -123,33 +123,33 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief
-??? example "[amount]% [stat]"
- Example: "[20]% [Culture]"
+??? example "[relativeAmount]% [stat]"
+ Example: "[+20]% [Culture]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% [stat] [cityFilter]"
- Example: "[20]% [Culture] [in all cities]"
+??? example "[relativeAmount]% [stat] [cityFilter]"
+ Example: "[+20]% [Culture] [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% [stat] from every [tileFilter/specialist/buildingName]"
- Example: "[20]% [Culture] from every [tileFilter/specialist/buildingName]"
+??? example "[relativeAmount]% [stat] from every [tileFilter/specialist/buildingName]"
+ Example: "[+20]% [Culture] from every [Farm]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Yield from every [tileFilter]"
- Example: "[20]% Yield from every [Farm]"
+??? example "[relativeAmount]% Yield from every [tileFilter]"
+ Example: "[+20]% Yield from every [Farm]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% [stat] from City-States"
- Example: "[20]% [Culture] from City-States"
+??? example "[relativeAmount]% [stat] from City-States"
+ Example: "[+20]% [Culture] from City-States"
Applicable to: Global
-??? example "[amount]% [stat] from Trade Routes"
- Example: "[20]% [Culture] from Trade Routes"
+??? example "[relativeAmount]% [stat] from Trade Routes"
+ Example: "[+20]% [Culture] from Trade Routes"
Applicable to: Global
@@ -163,23 +163,23 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
-??? example "[amount]% Production when constructing [buildingFilter] wonders [cityFilter]"
- Example: "[20]% Production when constructing [Culture] wonders [in all cities]"
+??? example "[relativeAmount]% Production when constructing [buildingFilter] wonders [cityFilter]"
+ Example: "[+20]% Production when constructing [Culture] wonders [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Production when constructing [buildingFilter] buildings [cityFilter]"
- Example: "[20]% Production when constructing [Culture] buildings [in all cities]"
+??? example "[relativeAmount]% Production when constructing [buildingFilter] buildings [cityFilter]"
+ Example: "[+20]% Production when constructing [Culture] buildings [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Production when constructing [baseUnitFilter] units [cityFilter]"
- Example: "[20]% Production when constructing [Melee] units [in all cities]"
+??? example "[relativeAmount]% Production when constructing [baseUnitFilter] units [cityFilter]"
+ Example: "[+20]% Production when constructing [Melee] units [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Production towards any buildings that already exist in the Capital"
- Example: "[20]% Production towards any buildings that already exist in the Capital"
+??? example "[relativeAmount]% 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
@@ -187,22 +187,22 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "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 [3] XP"
Applicable to: Global
??? example "Militaristic City-States grant units [amount] times as fast when you are at war with a common nation"
- Example: "Militaristic City-States grant units [20] times as fast when you are at war with a common nation"
+ Example: "Militaristic City-States grant units [3] times as fast when you are at war with a common nation"
Applicable to: Global
-??? example "Gifts of Gold to City-States generate [amount]% more Influence"
- Example: "Gifts of Gold to City-States generate [20]% more Influence"
+??? example "Gifts of Gold to City-States generate [relativeAmount]% more Influence"
+ Example: "Gifts of Gold to City-States generate [+20]% more Influence"
Applicable to: Global
??? example "Can spend Gold to annex or puppet a City-State that has been your ally for [amount] turns."
- Example: "Can spend Gold to annex or puppet a City-State that has been your ally for [20] turns."
+ Example: "Can spend Gold to annex or puppet a City-State that has been your ally for [3] turns."
Applicable to: Global
@@ -212,28 +212,28 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Allied City-States will occasionally gift Great People"
Applicable to: Global
-??? example "[amount]% City-State Influence degradation"
- Example: "[20]% City-State Influence degradation"
+??? example "[relativeAmount]% City-State Influence degradation"
+ Example: "[+20]% City-State Influence degradation"
Applicable to: Global
??? example "Resting point for Influence with City-States is increased by [amount]"
- Example: "Resting point for Influence with City-States is increased by [20]"
+ Example: "Resting point for Influence with City-States is increased by [3]"
Applicable to: Global
-??? example "Allied City-States provide [stat] equal to [amount]% of what they produce for themselves"
- Example: "Allied City-States provide [Culture] equal to [20]% of what they produce for themselves"
+??? example "Allied City-States provide [stat] equal to [relativeAmount]% of what they produce for themselves"
+ Example: "Allied City-States provide [Culture] equal to [+20]% of what they produce for themselves"
Applicable to: Global
-??? example "[amount]% resources gifted by City-States"
- Example: "[20]% resources gifted by City-States"
+??? example "[relativeAmount]% resources gifted by City-States"
+ Example: "[+20]% resources gifted by City-States"
Applicable to: Global
-??? example "[amount]% Happiness from luxury resources gifted by City-States"
- Example: "[20]% Happiness from luxury resources gifted by City-States"
+??? example "[relativeAmount]% Happiness from luxury resources gifted by City-States"
+ Example: "[+20]% Happiness from luxury resources gifted by City-States"
Applicable to: Global
@@ -241,7 +241,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "[amount] units cost no maintenance"
- Example: "[20] units cost no maintenance"
+ Example: "[3] units cost no maintenance"
Applicable to: Global
@@ -250,13 +250,13 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
-??? example "[amount]% growth [cityFilter]"
- Example: "[20]% growth [in all cities]"
+??? example "[relativeAmount]% growth [cityFilter]"
+ Example: "[+20]% growth [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Food is carried over after population increases [cityFilter]"
- Example: "[20]% Food is carried over after population increases [in all cities]"
+??? example "[relativeAmount]% Food is carried over after population increases [cityFilter]"
+ Example: "[+20]% Food is carried over after population increases [in all cities]"
Applicable to: Global, FollowerBelief
@@ -265,66 +265,66 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
-??? example "[amount]% Great Person generation [cityFilter]"
- Example: "[20]% Great Person generation [in all cities]"
+??? example "[relativeAmount]% 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"
+ Example: "May choose [3] additional [Follower] beliefs when [founding] a religion"
Applicable to: Global
??? example "May choose [amount] additional belief(s) of any type when [foundingOrEnhancing] a religion"
- Example: "May choose [20] additional belief(s) of any type when [founding] a religion"
+ Example: "May choose [3] additional belief(s) of any type when [founding] a religion"
Applicable to: Global
-??? example "[amount]% Unhappiness from [populationFilter] [cityFilter]"
- Example: "[20]% Unhappiness from [populationFilter] [in all cities]"
+??? example "[relativeAmount]% Unhappiness from [populationFilter] [cityFilter]"
+ Example: "[+20]% Unhappiness from [Followers of this Religion] [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Food consumption by specialists [cityFilter]"
- Example: "[20]% Food consumption by specialists [in all cities]"
+??? example "[relativeAmount]% Food consumption by specialists [cityFilter]"
+ Example: "[+20]% Food consumption by specialists [in all cities]"
Applicable to: Global, FollowerBelief
??? example "Provides 1 happiness per 2 additional social policies adopted"
Applicable to: Global
-??? example "[amount]% of excess happiness converted to [stat]"
- Example: "[20]% of excess happiness converted to [Culture]"
+??? example "[relativeAmount]% of excess happiness converted to [stat]"
+ Example: "[+20]% of excess happiness converted to [Culture]"
Applicable to: Global
-??? example "[amount]% Culture cost of natural border growth [cityFilter]"
- Example: "[20]% Culture cost of natural border growth [in all cities]"
+??? example "[relativeAmount]% Culture cost of natural border growth [cityFilter]"
+ Example: "[+20]% Culture cost of natural border growth [in all cities]"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Gold cost of acquiring tiles [cityFilter]"
- Example: "[20]% Gold cost of acquiring tiles [in all cities]"
+??? example "[relativeAmount]% Gold cost of acquiring tiles [cityFilter]"
+ Example: "[+20]% Gold cost of acquiring tiles [in all cities]"
Applicable to: Global, FollowerBelief
??? example "May buy [baseUnitFilter] units for [amount] [stat] [cityFilter] at an increasing price ([amount])"
- Example: "May buy [Melee] units for [20] [Culture] [in all cities] at an increasing price ([20])"
+ Example: "May buy [Melee] units for [3] [Culture] [in all cities] at an increasing price ([3])"
Applicable to: Global, FollowerBelief
??? example "May buy [buildingFilter] buildings for [amount] [stat] [cityFilter] at an increasing price ([amount])"
- Example: "May buy [Culture] buildings for [20] [Culture] [in all cities] at an increasing price ([20])"
+ Example: "May buy [Culture] buildings for [3] [Culture] [in all cities] at an increasing price ([3])"
Applicable to: Global, FollowerBelief
??? example "May buy [baseUnitFilter] units for [amount] [stat] [cityFilter]"
- Example: "May buy [Melee] units for [20] [Culture] [in all cities]"
+ Example: "May buy [Melee] units for [3] [Culture] [in all cities]"
Applicable to: Global, FollowerBelief
??? example "May buy [buildingFilter] buildings for [amount] [stat] [cityFilter]"
- Example: "May buy [Culture] buildings for [20] [Culture] [in all cities]"
+ Example: "May buy [Culture] buildings for [3] [Culture] [in all cities]"
Applicable to: Global, FollowerBelief
@@ -339,12 +339,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief
??? example "May buy [baseUnitFilter] units with [stat] for [amount] times their normal Production cost"
- Example: "May buy [Melee] units with [Culture] for [20] times their normal Production cost"
+ Example: "May buy [Melee] units with [Culture] for [3] times their normal Production cost"
Applicable to: Global, FollowerBelief
??? example "May buy [buildingFilter] buildings with [stat] for [amount] times their normal Production cost"
- Example: "May buy [Culture] buildings with [Culture] for [20] times their normal Production cost"
+ Example: "May buy [Culture] buildings with [Culture] for [3] times their normal Production cost"
Applicable to: Global, FollowerBelief
@@ -354,18 +354,18 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Enables conversion of city production to science"
Applicable to: Global
-??? example "[stat] cost of purchasing items in cities [amount]%"
- Example: "[Culture] cost of purchasing items in cities [20]%"
+??? example "[stat] cost of purchasing items in cities [relativeAmount]%"
+ Example: "[Culture] cost of purchasing items in cities [+20]%"
Applicable to: Global, FollowerBelief
-??? example "[stat] cost of purchasing [buildingFilter] buildings [amount]%"
- Example: "[Culture] cost of purchasing [Culture] buildings [20]%"
+??? example "[stat] cost of purchasing [buildingFilter] buildings [relativeAmount]%"
+ Example: "[Culture] cost of purchasing [Culture] buildings [+20]%"
Applicable to: Global, FollowerBelief
-??? example "[stat] cost of purchasing [baseUnitFilter] units [amount]%"
- Example: "[Culture] cost of purchasing [Melee] units [20]%"
+??? example "[stat] cost of purchasing [baseUnitFilter] units [relativeAmount]%"
+ Example: "[Culture] cost of purchasing [Melee] units [+20]%"
Applicable to: Global, FollowerBelief
@@ -375,13 +375,13 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Roads connect tiles across rivers"
Applicable to: Global
-??? example "[amount]% maintenance on road & railroads"
- Example: "[20]% maintenance on road & railroads"
+??? example "[relativeAmount]% maintenance on road & railroads"
+ Example: "[+20]% maintenance on road & railroads"
Applicable to: Global
-??? example "[amount]% maintenance cost for buildings [cityFilter]"
- Example: "[20]% maintenance cost for buildings [in all cities]"
+??? example "[relativeAmount]% maintenance cost for buildings [cityFilter]"
+ Example: "[+20]% maintenance cost for buildings [in all cities]"
Applicable to: Global, FollowerBelief
@@ -393,28 +393,28 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Once The Long Count activates, the year on the world screen displays as the traditional Mayan Long Count."
Applicable to: Global
-??? example "Retain [amount]% of the happiness from a luxury after the last copy has been traded away"
- Example: "Retain [20]% of the happiness from a luxury after the last copy has been traded away"
+??? example "Retain [relativeAmount]% of the happiness from a luxury after the last copy has been traded away"
+ Example: "Retain [+20]% of the happiness from a luxury after the last copy has been traded away"
Applicable to: Global
??? example "[amount] Happiness from each type of luxury resource"
- Example: "[20] Happiness from each type of luxury resource"
+ Example: "[3] Happiness from each type of luxury resource"
Applicable to: Global
-??? example "Each city founded increases culture cost of policies [amount]% less than normal"
- Example: "Each city founded increases culture cost of policies [20]% less than normal"
+??? example "Each city founded increases culture cost of policies [relativeAmount]% less than normal"
+ Example: "Each city founded increases culture cost of policies [+20]% less than normal"
Applicable to: Global
-??? example "[amount]% Culture cost of adopting new Policies"
- Example: "[20]% Culture cost of adopting new Policies"
+??? example "[relativeAmount]% Culture cost of adopting new Policies"
+ Example: "[+20]% Culture cost of adopting new Policies"
Applicable to: Global
-??? example "Quantity of strategic resources produced by the empire +[amount]%"
- Example: "Quantity of strategic resources produced by the empire +[20]%"
+??? example "Quantity of strategic resources produced by the empire +[relativeAmount]%"
+ Example: "Quantity of strategic resources produced by the empire +[+20]%"
Applicable to: Global
@@ -457,12 +457,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "When conquering an encampment, earn [amount] Gold and recruit a Barbarian unit"
- Example: "When conquering an encampment, earn [20] Gold and recruit a Barbarian unit"
+ Example: "When conquering an encampment, earn [3] Gold and recruit a Barbarian unit"
Applicable to: Global
??? example "When defeating a [mapUnitFilter] unit, earn [amount] Gold and recruit it"
- Example: "When defeating a [Wounded] unit, earn [20] Gold and recruit it"
+ Example: "When defeating a [Wounded] unit, earn [3] Gold and recruit it"
Applicable to: Global
@@ -470,12 +470,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "Cities are razed [amount] times as fast"
- Example: "Cities are razed [20] times as fast"
+ Example: "Cities are razed [3] times as fast"
Applicable to: Global
-??? example "When declaring friendship, both parties gain a [amount]% boost to great person generation"
- Example: "When declaring friendship, both parties gain a [20]% boost to great person generation"
+??? example "When declaring friendship, both parties gain a [relativeAmount]% boost to great person generation"
+ Example: "When declaring friendship, both parties gain a [+20]% boost to great person generation"
Applicable to: Global
@@ -484,33 +484,33 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
-??? example "Influence of all other civilizations with all city-states degrades [amount]% faster"
- Example: "Influence of all other civilizations with all city-states degrades [20]% faster"
+??? example "Influence of all other civilizations with all city-states degrades [relativeAmount]% faster"
+ Example: "Influence of all other civilizations with all city-states degrades [+20]% faster"
Applicable to: Global
??? example "Land units may cross [terrainName] tiles after the first [baseUnitFilter] is earned"
- Example: "Land units may cross [terrainName] tiles after the first [Melee] is earned"
+ Example: "Land units may cross [Forest] tiles after the first [Melee] is earned"
Applicable to: Global
??? example "Gain [amount] Influence with a [baseUnitFilter] gift to a City-State"
- Example: "Gain [20] Influence with a [Melee] gift to a City-State"
+ Example: "Gain [3] Influence with a [Melee] gift to a City-State"
Applicable to: Global
-??? example "[amount]% Faith cost of generating Great Prophet equivalents"
- Example: "[20]% Faith cost of generating Great Prophet equivalents"
+??? example "[relativeAmount]% Faith cost of generating Great Prophet equivalents"
+ Example: "[+20]% Faith cost of generating Great Prophet equivalents"
Applicable to: Global
??? example "Resting point for Influence with City-States following this religion [amount]"
- Example: "Resting point for Influence with City-States following this religion [20]"
+ Example: "Resting point for Influence with City-States following this religion [3]"
Applicable to: Global
-??? example "[amount]% [stat] from City-States"
- Example: "[20]% [Culture] from City-States"
+??? example "[relativeAmount]% [stat] from City-States"
+ Example: "[+20]% [Culture] from City-States"
Applicable to: Global
@@ -533,8 +533,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Enables Research agreements"
Applicable to: Global
-??? example "Science gained from research agreements [amount]%"
- Example: "Science gained from research agreements [20]%"
+??? example "Science gained from research agreements [relativeAmount]%"
+ Example: "Science gained from research agreements [+20]%"
Applicable to: Global
@@ -544,38 +544,38 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Triggers a Cultural Victory upon completion"
Applicable to: Global
-??? example "[amount]% City Strength from defensive buildings"
- Example: "[20]% City Strength from defensive buildings"
+??? example "[relativeAmount]% City Strength from defensive buildings"
+ Example: "[+20]% City Strength from defensive buildings"
Applicable to: Global
-??? example "[amount]% tile improvement construction time"
- Example: "[20]% tile improvement construction time"
+??? example "[relativeAmount]% tile improvement construction time"
+ Example: "[+20]% tile improvement construction time"
Applicable to: Global, Unit
-??? example "[amount]% Gold from Great Merchant trade missions"
- Example: "[20]% Gold from Great Merchant trade missions"
+??? example "[relativeAmount]% Gold from Great Merchant trade missions"
+ Example: "[+20]% Gold from Great Merchant trade missions"
Applicable to: Global
??? example "[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"
+ Example: "[Wounded] Units adjacent to this city heal [3] HP per turn when healing"
Applicable to: Global, FollowerBelief
-??? example "[amount]% Golden Age length"
- Example: "[20]% Golden Age length"
+??? example "[relativeAmount]% Golden Age length"
+ Example: "[+20]% Golden Age length"
Applicable to: Global
-??? example "[amount]% Strength for cities"
- Example: "[20]% Strength for cities"
+??? example "[relativeAmount]% Strength for cities"
+ Example: "[+20]% Strength for cities"
Applicable to: Global, FollowerBelief
??? example "New [baseUnitFilter] units start with [amount] Experience [cityFilter]"
- Example: "New [Melee] units start with [20] Experience [in all cities]"
+ Example: "New [Melee] units start with [3] Experience [in all cities]"
Applicable to: Global, FollowerBelief
@@ -585,7 +585,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, FollowerBelief
??? example "[baseUnitFilter] units built [cityFilter] can [action] [amount] extra times"
- Example: "[Melee] units built [in all cities] can [action] [20] extra times"
+ Example: "[Melee] units built [in all cities] can [Spread Religion] [3] extra times"
Applicable to: Global, FollowerBelief
@@ -597,18 +597,18 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
-??? example "Population loss from nuclear attacks [amount]% [cityFilter]"
- Example: "Population loss from nuclear attacks [20]% [in all cities]"
+??? example "Population loss from nuclear attacks [relativeAmount]% [cityFilter]"
+ Example: "Population loss from nuclear attacks [+20]% [in all cities]"
Applicable to: Global
-??? example "[amount]% Natural religion spread [cityFilter]"
- Example: "[20]% Natural religion spread [in all cities]"
+??? example "[relativeAmount]% Natural religion spread [cityFilter]"
+ Example: "[+20]% Natural religion spread [in all cities]"
Applicable to: Global, FollowerBelief
??? example "Religion naturally spreads to cities [amount] tiles away"
- Example: "Religion naturally spreads to cities [20] tiles away"
+ Example: "Religion naturally spreads to cities [3] tiles away"
Applicable to: Global, FollowerBelief
@@ -616,17 +616,17 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "[amount] Unit Supply"
- Example: "[20] Unit Supply"
+ Example: "[3] Unit Supply"
Applicable to: Global
??? example "[amount] Unit Supply per [amount] population [cityFilter]"
- Example: "[20] Unit Supply per [20] population [in all cities]"
+ Example: "[3] Unit Supply per [3] population [in all cities]"
Applicable to: Global
??? example "[amount] Unit Supply per city"
- Example: "[20] Unit Supply per city"
+ Example: "[3] Unit Supply per city"
Applicable to: Global
@@ -636,18 +636,18 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Rebel units may spawn"
Applicable to: Global
-??? example "[amount]% Strength"
- Example: "[20]% Strength"
+??? example "[relativeAmount]% Strength"
+ Example: "[+20]% Strength"
Applicable to: Global, Unit
-??? example "[amount]% Strength decreasing with distance from the capital"
- Example: "[20]% Strength decreasing with distance from the capital"
+??? example "[relativeAmount]% Strength decreasing with distance from the capital"
+ Example: "[+20]% Strength decreasing with distance from the capital"
Applicable to: Global, Unit
-??? example "[amount]% to Flank Attack bonuses"
- Example: "[20]% to Flank Attack bonuses"
+??? example "[relativeAmount]% to Flank Attack bonuses"
+ Example: "[+20]% to Flank Attack bonuses"
Applicable to: Global, Unit
@@ -655,27 +655,27 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global
??? example "[amount] Movement"
- Example: "[20] Movement"
+ Example: "[3] Movement"
Applicable to: Global, Unit
??? example "[amount] Sight"
- Example: "[20] Sight"
+ Example: "[3] Sight"
Applicable to: Global, Unit, Terrain
??? example "[amount] Range"
- Example: "[20] Range"
+ Example: "[3] Range"
Applicable to: Global, Unit
??? example "[amount] HP when healing"
- Example: "[20] HP when healing"
+ Example: "[3] HP when healing"
Applicable to: Global, Unit
-??? example "[amount]% Spread Religion Strength"
- Example: "[20]% Spread Religion Strength"
+??? example "[relativeAmount]% Spread Religion Strength"
+ Example: "[+20]% Spread Religion Strength"
Applicable to: Global, Unit
@@ -698,7 +698,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global, Unit
??? example "Heals [amount] damage if it kills a unit"
- Example: "Heals [20] damage if it kills a unit"
+ Example: "Heals [3] damage if it kills a unit"
Applicable to: Global, Unit
@@ -711,53 +711,53 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Defense bonus when embarked"
Applicable to: Global, Unit
-??? example "[amount]% maintenance costs"
- Example: "[20]% maintenance costs"
+??? example "[relativeAmount]% maintenance costs"
+ Example: "[+20]% maintenance costs"
Applicable to: Global, Unit
-??? example "[amount]% Gold cost of upgrading"
- Example: "[20]% Gold cost of upgrading"
+??? example "[relativeAmount]% Gold cost of upgrading"
+ Example: "[+20]% Gold cost of upgrading"
Applicable to: Global, Unit
-??? example "[greatPerson] is earned [amount]% faster"
- Example: "[greatPerson] is earned [20]% faster"
+??? example "[greatPerson] is earned [relativeAmount]% faster"
+ Example: "[Great General] is earned [+20]% faster"
Applicable to: Global, Unit
-??? example "Earn [amount]% of the damage done to [combatantFilter] units as [plunderableStat]"
+??? example "Earn [relativeAmount]% of the damage done to [combatantFilter] units as [plunderableStat]"
Example: "Earn [20]% of the damage done to [City] units as [Gold]"
Applicable to: Global, Unit
??? example "Upon capturing a city, receive [amount] times its [stat] production as [plunderableStat] immediately"
- Example: "Upon capturing a city, receive [20] times its [Culture] production as [Gold] immediately"
+ Example: "Upon capturing a city, receive [3] times its [Culture] production as [Gold] immediately"
Applicable to: Global, Unit
??? example "Earn [amount]% of killed [mapUnitFilter] unit's [costOrStrength] as [plunderableStat]"
- Example: "Earn [20]% of killed [Wounded] unit's [Cost] as [Gold]"
+ Example: "Earn [3]% of killed [Wounded] unit's [Cost] as [Gold]"
Applicable to: Global, Unit
??? example "[amount] XP gained from combat"
- Example: "[20] XP gained from combat"
+ Example: "[3] XP gained from combat"
Applicable to: Global, Unit
-??? example "[amount]% XP gained from combat"
- Example: "[20]% XP gained from combat"
+??? example "[relativeAmount]% XP gained from combat"
+ Example: "[+20]% XP gained from combat"
Applicable to: Global, Unit
??? example "[amount] Movement point cost to disembark"
- Example: "[20] Movement point cost to disembark"
+ Example: "[3] Movement point cost to disembark"
Applicable to: Global, Unit
??? example "[amount] Movement point cost to embark"
- Example: "[20] Movement point cost to embark"
+ Example: "[3] Movement point cost to embark"
Applicable to: Global, Unit
@@ -786,24 +786,24 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Tech, Policy, Building, Unit, Promotion, Improvement
## FollowerBelief uniques
-??? example "[amount]% [stat] from every follower, up to [amount]%"
- Example: "[20]% [Culture] from every follower, up to [20]%"
+??? example "[relativeAmount]% [stat] from every follower, up to [relativeAmount]%"
+ Example: "[+20]% [Culture] from every follower, up to [+20]%"
Applicable to: FollowerBelief
??? example "Earn [amount]% of [mapUnitFilter] unit's [costOrStrength] as [plunderableStat] when killed within 4 tiles of a city following this religion"
- Example: "Earn [20]% of [Wounded] unit's [Cost] as [Gold] when killed within 4 tiles of a city following this religion"
+ Example: "Earn [3]% of [Wounded] unit's [Cost] as [Gold] when killed within 4 tiles of a city following this religion"
Applicable to: FollowerBelief
## Building uniques
??? example "Consumes [amount] [resource]"
- Example: "Consumes [20] [Iron]"
+ Example: "Consumes [3] [Iron]"
Applicable to: Building, Unit, Improvement
??? example "Provides [amount] [resource]"
- Example: "Provides [20] [Iron]"
+ Example: "Provides [3] [Iron]"
Applicable to: Building, Improvement
@@ -819,17 +819,17 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building, Unit
??? example "Can be purchased for [amount] [stat] [cityFilter]"
- Example: "Can be purchased for [20] [Culture] [in all cities]"
+ Example: "Can be purchased for [3] [Culture] [in all cities]"
Applicable to: Building, Unit
??? example "Limited to [amount] per Civilization"
- Example: "Limited to [20] per Civilization"
+ Example: "Limited to [3] per Civilization"
Applicable to: Building, Unit
??? example "Hidden until [amount] social policy branches have been completed"
- Example: "Hidden until [20] social policy branches have been completed"
+ Example: "Hidden until [3] social policy branches have been completed"
Applicable to: Building, Unit
@@ -837,7 +837,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building, Unit
??? example "Requires at least [amount] population"
- Example: "Requires at least [20] population"
+ Example: "Requires at least [3] population"
Applicable to: Building, Unit
@@ -848,7 +848,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building, Unit
??? example "Cost increases by [amount] per owned city"
- Example: "Cost increases by [20] per owned city"
+ Example: "Cost increases by [3] per owned city"
Applicable to: Building
@@ -858,7 +858,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building
??? example "Requires a [buildingName] in at least [amount] cities"
- Example: "Requires a [Library] in at least [20] cities"
+ Example: "Requires a [Library] in at least [3] cities"
Applicable to: Building
@@ -868,7 +868,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building
??? example "Must have an owned [tileFilter] within [amount] tiles"
- Example: "Must have an owned [Farm] within [20] tiles"
+ Example: "Must have an owned [Farm] within [3] tiles"
Applicable to: Building
@@ -876,22 +876,22 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building
??? example "Must be on [terrainFilter]"
- Example: "Must be on [Forest]"
+ Example: "Must be on [Fresh Water]"
Applicable to: Building
??? example "Must not be on [terrainFilter]"
- Example: "Must not be on [Forest]"
+ Example: "Must not be on [Fresh Water]"
Applicable to: Building
??? example "Must be next to [terrainFilter]"
- Example: "Must be next to [Forest]"
+ Example: "Must be next to [Fresh Water]"
Applicable to: Building, Improvement
??? example "Must not be next to [terrainFilter]"
- Example: "Must not be next to [Forest]"
+ Example: "Must not be next to [Fresh Water]"
Applicable to: Building
@@ -942,7 +942,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "Can build [improvementFilter/terrainFilter] improvements on tiles"
- Example: "Can build [improvementFilter/terrainFilter] improvements on tiles"
+ Example: "Can build [All Road] improvements on tiles"
Applicable to: Unit
@@ -975,7 +975,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "Blast radius [amount]"
- Example: "Blast radius [20]"
+ Example: "Blast radius [3]"
Applicable to: Unit
@@ -986,7 +986,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "May withdraw before melee ([amount]%)"
- Example: "May withdraw before melee ([20]%)"
+ Example: "May withdraw before melee ([3]%)"
Applicable to: Unit
@@ -1003,7 +1003,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "All adjacent units heal [amount] HP when healing"
- Example: "All adjacent units heal [20] HP when healing"
+ Example: "All adjacent units heal [3] HP when healing"
Applicable to: Unit
@@ -1020,12 +1020,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "Can carry [amount] [mapUnitFilter] units"
- Example: "Can carry [20] [Wounded] units"
+ Example: "Can carry [3] [Wounded] units"
Applicable to: Unit
??? example "Can carry [amount] extra [mapUnitFilter] units"
- Example: "Can carry [20] extra [Wounded] units"
+ Example: "Can carry [3] extra [Wounded] units"
Applicable to: Unit
@@ -1056,7 +1056,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "Double movement in [terrainFilter]"
- Example: "Double movement in [Forest]"
+ Example: "Double movement in [Fresh Water]"
Applicable to: Unit
@@ -1085,7 +1085,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Unit
??? example "May enter foreign tiles without open borders, but loses [amount] religious strength each turn it ends there"
- Example: "May enter foreign tiles without open borders, but loses [20] religious strength each turn it ends there"
+ Example: "May enter foreign tiles without open borders, but loses [3] religious strength each turn it ends there"
Applicable to: Unit
@@ -1102,38 +1102,38 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
## Promotion uniques
??? example "Heal this unit by [amount] HP"
- Example: "Heal this unit by [20] HP"
+ Example: "Heal this unit by [3] HP"
Applicable to: Promotion
## Terrain uniques
??? example "Must be adjacent to [amount] [simpleTerrain] tiles"
- Example: "Must be adjacent to [20] [Elevated] tiles"
+ Example: "Must be adjacent to [3] [Elevated] tiles"
Applicable to: Terrain
??? example "Must be adjacent to [amount] to [amount] [simpleTerrain] tiles"
- Example: "Must be adjacent to [20] to [20] [Elevated] tiles"
+ Example: "Must be adjacent to [3] to [3] [Elevated] tiles"
Applicable to: Terrain
??? example "Must not be on [amount] largest landmasses"
- Example: "Must not be on [20] largest landmasses"
+ Example: "Must not be on [3] largest landmasses"
Applicable to: Terrain
??? example "Must be on [amount] largest landmasses"
- Example: "Must be on [20] largest landmasses"
+ Example: "Must be on [3] largest landmasses"
Applicable to: Terrain
??? example "Occurs on latitudes from [amount] to [amount] percent of distance equator to pole"
- Example: "Occurs on latitudes from [20] to [20] percent of distance equator to pole"
+ Example: "Occurs on latitudes from [3] to [3] percent of distance equator to pole"
Applicable to: Terrain
??? example "Occurs in groups of [amount] to [amount] tiles"
- Example: "Occurs in groups of [20] to [20] tiles"
+ Example: "Occurs in groups of [3] to [3] tiles"
Applicable to: Terrain
@@ -1151,7 +1151,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "Units ending their turn on this terrain take [amount] damage"
- Example: "Units ending their turn on this terrain take [20] damage"
+ Example: "Units ending their turn on this terrain take [3] damage"
Applicable to: Terrain
@@ -1161,7 +1161,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "[amount] Strength for cities built on this terrain"
- Example: "[20] Strength for cities built on this terrain"
+ Example: "[3] Strength for cities built on this terrain"
Applicable to: Terrain
@@ -1186,27 +1186,27 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "Has an elevation of [amount] for visibility calculations"
- Example: "Has an elevation of [20] for visibility calculations"
+ Example: "Has an elevation of [3] for visibility calculations"
Applicable to: Terrain
??? example "Always Fertility [amount] for Map Generation"
- Example: "Always Fertility [20] for Map Generation"
+ Example: "Always Fertility [3] for Map Generation"
Applicable to: Terrain
??? example "[amount] to Fertility for Map Generation"
- Example: "[20] to Fertility for Map Generation"
+ Example: "[3] to Fertility for Map Generation"
Applicable to: Terrain
??? example "A Region is formed with at least [amount]% [simpleTerrain] tiles, with priority [amount]"
- Example: "A Region is formed with at least [20]% [Elevated] tiles, with priority [20]"
+ Example: "A Region is formed with at least [3]% [Elevated] tiles, with priority [3]"
Applicable to: Terrain
??? example "A Region is formed with at least [amount]% [simpleTerrain] tiles and [simpleTerrain] tiles, with priority [amount]"
- Example: "A Region is formed with at least [20]% [Elevated] tiles and [Elevated] tiles, with priority [20]"
+ Example: "A Region is formed with at least [3]% [Elevated] tiles and [Elevated] tiles, with priority [3]"
Applicable to: Terrain
@@ -1227,7 +1227,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "Becomes [terrainName] when adjacent to [terrainFilter]"
- Example: "Becomes [terrainName] when adjacent to [Forest]"
+ Example: "Becomes [Forest] when adjacent to [Fresh Water]"
Applicable to: Terrain
@@ -1240,7 +1240,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain, Resource
??? example "Occurs at temperature between [amount] and [amount] and humidity between [amount] and [amount]"
- Example: "Occurs at temperature between [20] and [20] and humidity between [20] and [20]"
+ Example: "Occurs at temperature between [3] and [3] and humidity between [3] and [3]"
Applicable to: Terrain
@@ -1251,7 +1251,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "Every [amount] tiles with this terrain will receive a major deposit of a strategic resource."
- Example: "Every [20] tiles with this terrain will receive a major deposit of a strategic resource."
+ Example: "Every [3] tiles with this terrain will receive a major deposit of a strategic resource."
Applicable to: Terrain
@@ -1259,7 +1259,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Terrain
??? example "[amount]% Chance to be destroyed by nukes"
- Example: "[20]% Chance to be destroyed by nukes"
+ Example: "[3]% Chance to be destroyed by nukes"
Applicable to: Terrain
@@ -1304,18 +1304,18 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Improvement
-??? example "Gives a defensive bonus of [amount]%"
- Example: "Gives a defensive bonus of [20]%"
+??? example "Gives a defensive bonus of [relativeAmount]%"
+ Example: "Gives a defensive bonus of [+20]%"
Applicable to: Improvement
??? example "Costs [amount] gold per turn when in your territory"
- Example: "Costs [20] gold per turn when in your territory"
+ Example: "Costs [3] gold per turn when in your territory"
Applicable to: Improvement
??? example "Adjacent enemy units ending their turn take [amount] damage"
- Example: "Adjacent enemy units ending their turn take [20] damage"
+ Example: "Adjacent enemy units ending their turn take [3] damage"
Applicable to: Improvement
@@ -1336,7 +1336,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
## Resource uniques
??? example "Deposits in [tileFilter] tiles always provide [amount] resources"
- Example: "Deposits in [Farm] tiles always provide [20] resources"
+ Example: "Deposits in [Farm] tiles always provide [3] resources"
Applicable to: Resource
@@ -1344,17 +1344,17 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Resource
??? example "Generated with weight [amount]"
- Example: "Generated with weight [20]"
+ Example: "Generated with weight [3]"
Applicable to: Resource
??? example "Minor deposits generated with weight [amount]"
- Example: "Minor deposits generated with weight [20]"
+ Example: "Minor deposits generated with weight [3]"
Applicable to: Resource
??? example "Generated near City States with weight [amount]"
- Example: "Generated near City States with weight [20]"
+ Example: "Generated near City States with weight [3]"
Applicable to: Resource
@@ -1362,7 +1362,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Resource
??? example "Generated on every [amount] tiles"
- Example: "Generated on every [20] tiles"
+ Example: "Generated on every [3] tiles"
Applicable to: Resource
@@ -1376,22 +1376,22 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Ruins
??? example "[amount] population in a random city"
- Example: "[20] population in a random city"
+ Example: "[3] population in a random city"
Applicable to: Ruins
??? example "[amount] free random researchable Tech(s) from the [era]"
- Example: "[20] free random researchable Tech(s) from the [Ancient era]"
+ Example: "[3] free random researchable Tech(s) from the [Ancient era]"
Applicable to: Ruins
??? example "Gain [amount] [stat]"
- Example: "Gain [20] [Culture]"
+ Example: "Gain [3] [Culture]"
Applicable to: Ruins
??? example "Gain [amount]-[amount] [stat]"
- Example: "Gain [20]-[20] [Culture]"
+ Example: "Gain [3]-[3] [Culture]"
Applicable to: Ruins
@@ -1399,22 +1399,22 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Ruins
??? example "Gain enough Faith for [amount]% of a Great Prophet"
- Example: "Gain enough Faith for [20]% of a Great Prophet"
+ Example: "Gain enough Faith for [3]% of a Great Prophet"
Applicable to: Ruins
??? example "Reveal up to [amount/'all'] [tileFilter] within a [amount] tile radius"
- Example: "Reveal up to [amount/'all'] [Farm] within a [20] tile radius"
+ Example: "Reveal up to [3] [Farm] within a [3] tile radius"
Applicable to: Ruins
??? example "From a randomly chosen tile [amount] tiles away from the ruins, reveal tiles up to [amount] tiles away with [amount]% chance"
- Example: "From a randomly chosen tile [20] tiles away from the ruins, reveal tiles up to [20] tiles away with [20]% chance"
+ Example: "From a randomly chosen tile [3] tiles away from the ruins, reveal tiles up to [3] tiles away with [3]% chance"
Applicable to: Ruins
??? example "This Unit gains [amount] XP"
- Example: "This Unit gains [20] XP"
+ Example: "This Unit gains [3] XP"
Applicable to: Ruins
@@ -1422,7 +1422,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Ruins
??? example "Only available after [amount] turns"
- Example: "Only available after [20] turns"
+ Example: "Only available after [3] turns"
Applicable to: Ruins
@@ -1447,12 +1447,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: CityState
??? example "Provides [amount] Happiness"
- Example: "Provides [20] Happiness"
+ Example: "Provides [3] Happiness"
Applicable to: CityState
??? example "Provides military units every ≈[amount] turns"
- Example: "Provides military units every ≈[20] turns"
+ Example: "Provides military units every ≈[3] turns"
Applicable to: CityState
@@ -1461,7 +1461,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
## Conditional uniques
??? example "<for [amount] turns>"
- Example: "<for [20] turns>"
+ Example: "<for [3] turns>"
Applicable to: Conditional
@@ -1469,7 +1469,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
??? example "<with [amount]% chance>"
- Example: "<with [20]% chance>"
+ Example: "<with [3]% chance>"
Applicable to: Conditional
@@ -1491,12 +1491,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
??? example "<when between [amount] and [amount] Happiness>"
- Example: "<when between [20] and [20] Happiness>"
+ Example: "<when between [3] and [3] Happiness>"
Applicable to: Conditional
??? example "<when below [amount] Happiness>"
- Example: "<when below [20] Happiness>"
+ Example: "<when below [3] Happiness>"
Applicable to: Conditional
@@ -1559,7 +1559,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
??? example "<in cities with at least [amount] [populationFilter]>"
- Example: "<in cities with at least [20] [populationFilter]>"
+ Example: "<in cities with at least [3] [Followers of this Religion]>"
Applicable to: Conditional
@@ -1612,22 +1612,22 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
??? example "<when above [amount] HP>"
- Example: "<when above [20] HP>"
+ Example: "<when above [3] HP>"
Applicable to: Conditional
??? example "<when below [amount] HP>"
- Example: "<when below [20] HP>"
+ Example: "<when below [3] HP>"
Applicable to: Conditional
??? example "<with [amount] to [amount] neighboring [tileFilter] tiles>"
- Example: "<with [20] to [20] neighboring [Farm] tiles>"
+ Example: "<with [3] to [3] neighboring [Farm] tiles>"
Applicable to: Conditional
??? example "<with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles>"
- Example: "<with [20] to [20] neighboring [Farm] [Farm] tiles>"
+ Example: "<with [3] to [3] neighboring [Farm] [Farm] tiles>"
Applicable to: Conditional
@@ -1647,7 +1647,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
??? example "<within [amount] tiles of a [tileFilter]>"
- Example: "<within [20] tiles of a [Farm]>"
+ Example: "<within [3] tiles of a [Farm]>"
Applicable to: Conditional
@@ -1665,25 +1665,25 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Conditional
+*[action]: An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'
*[amount]: This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`.
*[baseTerrain]: The name of any terrain that is a base terrain according to the json file.
-*[action]: An action that a unit can preform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'
-*[belief]: The name of any belief
-*[beliefType]: 'Pantheon', 'Follower', 'Founder' or 'Enhancer'.
-*[victoryType]: The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'
-*[tech]: The name of any tech
-*[resource]: The name of any resource
-*[specialist]: The name of any specialist
-*[promotion]: The name of any promotion
-*[policy]: The name of any policy
-*[improvementName]: The name of any improvement
-*[buildingName]: The name of any building
-*[era]: The name of any era
-*[constructionFilter]: A filter for used when testing the current construction of a city. All values of `baseUnitFilter` and `buildingFilter` are allowed.
-*[foundingOrEnhancing]: `founding` or `enhancing`
-*[costOrStrength]: `Cost` or `Strength`
+*[belief]: The name of any belief.
+*[beliefType]: 'Pantheon', 'Follower', 'Founder' or 'Enhancer'
+*[buildingName]: The name of any building.
*[combatantFilter]: This indicates a combatant, which can either be a unit or a city (when bombarding). Must either be `City` or a `mapUnitFilter`.
-*[plunderableStat]: All the following stats can be plundered: `Gold`, `Science`, `Culture`, `Faith`
-*[tileFilter]: Anything that can be used either in an improvementFilter or in a tileFilter can be used here
+*[costOrStrength]: `Cost` or `Strength`.
+*[era]: The name of any era.
+*[foundingOrEnhancing]: `founding` or `enhancing`.
+*[improvementName]: The name of any improvement.
+*[plunderableStat]: All the following stats can be plundered: `Gold`, `Science`, `Culture`, `Faith`.
+*[policy]: The name of any policy.
+*[promotion]: The name of any promotion.
+*[relativeAmount]: This indicates a number, usually with a + or - sign, such as `+25` (this kind of parameter is often followed by '%' which is nevertheless not part of the value).
+*[resource]: The name of any resource.
+*[specialist]: The name of any specialist.
*[stat]: This is one of the 7 major stats in the game - `Gold`, `Science`, `Production`, `Food`, `Happiness`, `Culture` and `Faith`. Note that the stat names need to be capitalized!
-*[stats]: For example: `+2 Production, +3 Food`. Note that the stat names need to be capitalized!
\ No newline at end of file
+*[stats]: For example: `+2 Production, +3 Food`. Note that the stat names need to be capitalized!
+*[tech]: The name of any tech.
+*[tileFilter]: Anything that can be used either in an improvementFilter or in a terrainFilter can be used here, plus 'unimproved'
+*[victoryType]: The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'
\ No newline at end of file