UniqueParameterType getErrorSeverity/isKnownValue architecture simplification (#11701)

* UniqueParameterType getErrorSeverity/isKnownValue simplification

* Minor changes to a few UniqueType documentations

* Allow UnitsGainPromotion e.g. "[Melee] units gain the [Morale] promotion"
This commit is contained in:
SomeTroglodyte 2024-06-08 20:58:38 +02:00 committed by GitHub
parent cf7f5a1c52
commit e276a08d61
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 244 additions and 366 deletions

View File

@ -12,7 +12,7 @@ import com.unciv.models.ruleset.validation.Suppression
import com.unciv.models.stats.Stat
import com.unciv.models.translations.TranslationFileWriter
// 'region' names beginning with an underscore are used here for a prettier "Structure window" - they go in front ot the rest.
// 'region' names beginning with an underscore are used here for a prettier "Structure window" - they go in front of the rest.
/**
* These manage validation of parameters in [Unique]s and
@ -29,6 +29,7 @@ import com.unciv.models.translations.TranslationFileWriter
* @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.
* @param severityDefault the default severity used by the [getErrorSeverityViaKnownValue] helper, but not the [getErrorSeverityForFilter] one. Change to [RulesetInvariant][UniqueType.UniqueParameterErrorSeverity.RulesetInvariant] if you override [isKnownValue] and the ruleset is unused.
*/
//region _Fields
@Suppress("unused") // Some are used only via enumerating the enum matching on parameterName
@ -36,84 +37,60 @@ enum class UniqueParameterType(
var parameterName: String,
val docExample: String,
val docDescription: String? = null,
val displayName: String = parameterName
val displayName: String = parameterName,
private val severityDefault: UniqueType.UniqueParameterErrorSeverity = UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
) {
//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.UniqueParameterErrorSeverity? {
return if (parameterText.toIntOrNull() == null) UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
else null
}
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
parameterText.getInvariantSeverityUnless { toIntOrNull() != null }
},
PositiveNumber("positiveAmount", "3", "This indicates a positive whole number, larger than zero, a '+' sign is optional") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
val amount = parameterText.toIntOrNull()
?: return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
if (amount <= 0) return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
return null
}
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
parameterText.getInvariantSeverityUnless { toIntOrNull()?.let { it > 0 } == true }
},
Fraction("fraction", docExample = "0.5", "Indicates a fractional number, which can be negative") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? {
return if (parameterText.toFloatOrNull () == null) UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
else null
}
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
parameterText.getInvariantSeverityUnless { toFloatOrNull() != 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.UniqueParameterErrorSeverity? {
return if (parameterText.toIntOrNull() == null) UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
else null
}
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
parameterText.getInvariantSeverityUnless { toIntOrNull() != null }
},
Countable("countable", "1000", "This indicate a number or a numeric variable") {
Countable("countable", "1000", "This indicates a number or a numeric variable") {
// todo add more countables
private val knownValues = setOf(
"year"
)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (parameterText.toIntOrNull() != null) return true
if (Stat.isStat(parameterText)) return true
if (parameterText in ruleset.tileResources) return true
if (parameterText in ruleset.units) return true
if (parameterText in ruleset.buildings) return true
return false
}
override fun getErrorSeverity(
parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? {
return if (isKnownValue(parameterText, ruleset)) null
else UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
parameterText.toIntOrNull() != null -> true
Stat.isStat(parameterText) -> true
parameterText in ruleset.tileResources -> true
parameterText in ruleset.units -> true
else -> parameterText in ruleset.buildings
}
},
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
KeywordAll("'all'", "All") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
if (parameterText in Constants.all) null else UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
KeywordAll("'all'", "All", severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in Constants.all
},
/** Implemented by [ICombatant.matchesCategory][com.unciv.logic.battle.ICombatant.matchesFilter] */
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.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText == "City") return true
if (MapUnitFilter.isKnownValue(parameterText, ruleset)) return true
if (CityFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText == "City" -> true
MapUnitFilter.isKnownValue(parameterText, ruleset) -> true
else -> CityFilter.isKnownValue(parameterText, ruleset)
}
override fun getTranslationWriterStringsForOutput() = setOf("City")
},
@ -123,15 +100,13 @@ enum class UniqueParameterType(
private val knownValues = setOf(Constants.wounded, Constants.barbarians, "Barbarian",
"City-State", Constants.embarked, "Non-City")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (ruleset.unitPromotions.values.any { it.hasUnique(parameterText) }) return true
if (CivFilter.isKnownValue(parameterText, ruleset)) return true
if (BaseUnitFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
ruleset.unitPromotions.values.any { it.hasUnique(parameterText) } -> true
CivFilter.isKnownValue(parameterText, ruleset) -> true
else -> BaseUnitFilter.isKnownValue(parameterText, ruleset)
}
override fun getTranslationWriterStringsForOutput() = knownValues
@ -144,104 +119,83 @@ enum class UniqueParameterType(
"Nuclear Weapon", "Great Person", "Religious",
"relevant", // used for UniqueType.UnitStartingPromotions
) + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (UnitName.getErrorSeverity(parameterText, ruleset) == null) return true
if (ruleset.units.values.any { it.uniques.contains(parameterText) }) return true
if (UnitTypeFilter.isKnownValue(parameterText, ruleset)) return true
if (TechFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
UnitName.getErrorSeverity(parameterText, ruleset) == null -> true
parameterText.isFilteringUniqueIn(ruleset.units) -> true
UnitTypeFilter.isKnownValue(parameterText, ruleset) -> true
TechFilter.isKnownValue(parameterText, ruleset) -> true
else -> false
}
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Implemented by [UnitType.matchesFilter][com.unciv.models.ruleset.unit.UnitType.matchesFilter] */
UnitTypeFilter("unitType", "Water", null, "Unit Type Filters") {
UnitTypeFilter("unitType", "Water", "Can be 'Land', 'Water', 'Air', any unit type, a filtering Unique on a unit type, or a multi-filter of these", "Unit Type Filters") {
private val knownValues = setOf(
"Land", "Water", "Air",
)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (ruleset.unitTypes.containsKey(parameterText)) return true
if (ruleset.unitTypes.values.any { it.uniques.contains(parameterText) }) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
parameterText in ruleset.unitTypes -> true
else -> parameterText.isFilteringUniqueIn(ruleset.unitTypes)
}
override fun isTranslationWriterGuess(parameterText: String, ruleset: Ruleset) =
parameterText in ruleset.unitTypes.keys || parameterText in getTranslationWriterStringsForOutput()
parameterText in ruleset.unitTypes || parameterText in knownValues
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Used by [BaseUnitFilter] and e.g. [UniqueType.OneTimeFreeUnit] */
UnitName("unit", "Musketman") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (ruleset.units.containsKey(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific // OneTimeFreeUnitRuins crashes with a bad parameter
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.units
},
/** Used by [UniqueType.GreatPersonEarnedFaster] */
GreatPerson("greatPerson", "Great General") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
if (ruleset.units[parameterText]?.hasUnique(UniqueType.GreatPerson) == true) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) =
ruleset.units[parameterText]?.hasUnique(UniqueType.GreatPerson) == true
},
/** 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.UniqueParameterErrorSeverity? {
if (com.unciv.models.stats.Stats.isStats(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
Stats("stats", "+1 Gold, +2 Production", "For example: `+2 Production, +3 Food`. Note that the stat names need to be capitalized!",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) =
com.unciv.models.stats.Stats.isStats(parameterText)
},
/** 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.UniqueParameterErrorSeverity? {
if (Stat.isStat(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
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!",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = Stat.isStat(parameterText)
},
/** [UniqueType.DamageUnitsPlunder] and others near that one */
CivWideStatName("civWideStat", "Gold", "All the following stats have civ-wide fields: `Gold`, `Science`, `Culture`, `Faith`") {
CivWideStatName("civWideStat", "Gold", "All the following stats have civ-wide fields: `Gold`, `Science`, `Culture`, `Faith`",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
private val knownValues = Stat.statsWithCivWideField.map { it.name }.toSet()
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in knownValues) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
},
/** Implemented by [Civ.matchesFilter][com.unciv.logic.civilization.Civilization.matchesFilter] */
CivFilter("civFilter", Constants.cityStates) {
private val knownValues = setOf("AI player", "Human player")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (NationFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
else -> NationFilter.isKnownValue(parameterText, ruleset)
}
},
@ -249,14 +203,12 @@ enum class UniqueParameterType(
NationFilter("nationFilter", Constants.cityStates) {
private val knownValues = setOf(Constants.cityStates, "Major") + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (ruleset.nations.containsKey(parameterText)) return true
if (ruleset.nations.values.any { it.hasUnique(parameterText) }) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
ruleset.nations.containsKey(parameterText) -> true
else -> ruleset.nations.values.any { it.hasUnique(parameterText) }
}
},
@ -287,42 +239,31 @@ enum class UniqueParameterType(
"in cities following our religion",
) + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
return false
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Used by [BuildingFilter] and e.g. [UniqueType.ConditionalCityWithBuilding] */
BuildingName("buildingName", "Library", "The name of any building") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in ruleset.buildings) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.buildings
},
/** Implemented by [Building.matchesFilter][com.unciv.models.ruleset.Building.matchesFilter] */
BuildingFilter("buildingFilter", "Culture") {
private val knownValues = mutableSetOf("Building", "Buildings", "Wonder", "Wonders", "National Wonder", "National", "World Wonder", "World")
.apply { addAll(Stat.names()); addAll(Constants.all) }
private val knownValues = setOf("Building", "Buildings", "Wonder", "Wonders", "National Wonder", "National", "World Wonder", "World") +
Stat.names() + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (BuildingName.getErrorSeverity(parameterText, ruleset) == null) return true
if (ruleset.buildings.values.any { it.hasUnique(parameterText) }) return true
if (TechFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
BuildingName.isKnownValue(parameterText, ruleset) -> true
ruleset.buildings.values.any { it.hasUnique(parameterText) } -> true
TechFilter.isKnownValue(parameterText, ruleset) -> true
else -> false
}
override fun isTranslationWriterGuess(parameterText: String, ruleset: Ruleset) =
@ -330,15 +271,11 @@ enum class UniqueParameterType(
},
/** Implemented by [PopulationManager.getPopulationFilterAmount][com.unciv.logic.city.managers.CityPopulationManager.getPopulationFilterAmount] */
PopulationFilter("populationFilter", "Followers of this Religion", null, "Population Filters") {
PopulationFilter("populationFilter", "Followers of this Religion", null, "Population Filters",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
private val knownValues = setOf("Population", "Specialists", "Unemployed", "Followers of the Majority Religion", "Followers of this Religion")
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in knownValues) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
override fun getTranslationWriterStringsForOutput() = knownValues
},
@ -352,18 +289,15 @@ enum class UniqueParameterType(
"Impassable", "Land", "Water"
) + ResourceType.values().map { it.name + " resource" } + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
return when (parameterText) {
in knownValues -> true
in ruleset.terrains -> true
in ruleset.tileResources -> true
in ruleset.terrains.values.asSequence().flatMap { it.uniques } -> true
in ruleset.tileResources.values.asSequence().flatMap { it.uniques } -> true
else -> false
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
parameterText in ruleset.terrains -> true
parameterText in ruleset.tileResources -> true
parameterText.isFilteringUniqueIn(ruleset.terrains) -> true
parameterText.isFilteringUniqueIn(ruleset.tileResources) -> true
else -> false
}
override fun isTranslationWriterGuess(parameterText: String, ruleset: Ruleset) =
@ -376,14 +310,13 @@ enum class UniqueParameterType(
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", "improved", "All Road", "Great Improvement")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (ImprovementFilter.isKnownValue(parameterText, ruleset)) return true
if (TerrainFilter.isKnownValue(parameterText, ruleset)) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
ImprovementFilter.isKnownValue(parameterText, ruleset) -> true
TerrainFilter.isKnownValue(parameterText, ruleset) -> true
else -> false
}
override fun getTranslationWriterStringsForOutput() = knownValues
@ -392,31 +325,20 @@ enum class UniqueParameterType(
/** 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.UniqueParameterErrorSeverity? {
if (parameterText in knownValues) return null
if (ruleset.terrains.containsKey(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) =
parameterText in knownValues || parameterText in ruleset.terrains
},
/** 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.UniqueParameterErrorSeverity? {
if (ruleset.terrains[parameterText]?.type?.isBaseTerrain == true) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) =
ruleset.terrains[parameterText]?.type?.isBaseTerrain == true
},
/** Used by: [UniqueType.LandUnitsCrossTerrainAfterUnitGained] (CivilizationInfo.addUnit),
* [UniqueType.ChangesTerrain] (MapGenerator.convertTerrains) */
TerrainName("terrainName", Constants.forest) {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (ruleset.terrains.containsKey(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.terrains
},
/** Used for region definitions, can be a terrain type with region unique, or "Hybrid"
@ -424,282 +346,231 @@ enum class UniqueParameterType(
* See also: [UniqueType.ConditionalInRegionOfType], [UniqueType.ConditionalInRegionExceptOfType], [MapRegions][com.unciv.logic.map.mapgenerator.mapregions.MapRegions] */
RegionType("regionType", "Hybrid", null, "Region Types") {
private val knownValues = setOf("Hybrid")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in knownValues) return null
if (ruleset.terrains[parameterText]?.hasUnique(UniqueType.RegionRequirePercentSingleType) == true ||
ruleset.terrains[parameterText]?.hasUnique(UniqueType.RegionRequirePercentTwoTypes) == true)
return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
else -> ruleset.terrains[parameterText]?.run {
hasUnique(UniqueType.RegionRequirePercentSingleType) || hasUnique(UniqueType.RegionRequirePercentTwoTypes)
} == true
}
// Doubtful any Unique using this is not hidden, but translation files have had this for a while anyway:
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Used for start placements: [UniqueType.HasQuality], MapRegions.MapGenTileData.evaluate */
TerrainQuality("terrainQuality", "Undesirable", null, "Terrain Quality") {
TerrainQuality("terrainQuality", "Undesirable", null, "Terrain Quality",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
private val knownValues = setOf("Undesirable", "Food", "Desirable", "Production")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in knownValues) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
// Doubtful any Unique using this is not hidden, but translation files have had this for a while anyway:
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** [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.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.unitPromotions -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.unitPromotions
},
/** [UniqueType.OneTimeFreeTechRuins], [UniqueType.ConditionalDuringEra] and similar */
Era("era", "Ancient era", "The name of any era") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.eras -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.eras
},
Speed("speed", "Quick", "The name of any speed") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.speeds -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.speeds
},
/** For [UniqueType.CreatesOneImprovement] */
ImprovementName("improvementName", "Trading Post", "The name of any improvement") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (parameterText == Constants.cancelImprovementOrder)
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
if (ruleset.tileImprovements.containsKey(parameterText)) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
ImprovementName("improvementName", "Trading Post", "The name of any improvement excluding 'Cancel improvement order'") {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) =
parameterText in ruleset.tileImprovements && parameterText != Constants.cancelImprovementOrder
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
if (parameterText == Constants.cancelImprovementOrder) UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
else getErrorSeverityViaKnownValue(parameterText, ruleset)
},
/** Implemented by [TileImprovement.matchesFilter][com.unciv.models.ruleset.tile.TileImprovement.matchesFilter] */
ImprovementFilter("improvementFilter", "All Road", null, "Improvement Filters") {
private val knownValues = setOf("Improvement", "All Road", "Great Improvement", "Great") + Constants.all
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (ImprovementName.getErrorSeverity(parameterText, ruleset) == null) return true
if (ruleset.tileImprovements.values.any { it.hasUnique(parameterText) }) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in knownValues -> true
ImprovementName.isKnownValue(parameterText, ruleset) -> true
ruleset.tileImprovements.values.any { it.hasUnique(parameterText) } -> true
else -> false
}
override fun isTranslationWriterGuess(parameterText: String, ruleset: Ruleset) =
parameterText !in Constants.all && getErrorSeverity(parameterText, ruleset) == null
parameterText !in Constants.all && getErrorSeverityForFilter(parameterText, ruleset) == null
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** 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.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.tileResources -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.tileResources
},
StockpiledResource("stockpiledResource", "StockpiledResource", "The name of any stockpiled") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = if (parameterText in ruleset.tileResources && ruleset.tileResources[parameterText]!!.isStockpiled()) null
else UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
/** Used by [UniqueType.OneTimeConsumeResources], [UniqueType.OneTimeProvideResources], [UniqueType.CostsResources], [UniqueType.UnitActionStockpileCost], implementation not centralized */
StockpiledResource("stockpiledResource", "Mana", "The name of any stockpiled resource") {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = ruleset.tileResources[parameterText]?.isStockpiled() == true
},
/** Used by [UniqueType.FreeExtraBeliefs], see ReligionManager.getBeliefsToChooseAt* functions */
BeliefTypeName("beliefType", "Follower", "'Pantheon', 'Follower', 'Founder' or 'Enhancer'") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in BeliefType.values().map { it.name } -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
BeliefTypeName("beliefType", "Follower", "'Pantheon', 'Follower', 'Founder' or 'Enhancer'",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = BeliefType.values().any { it.name == parameterText }
},
/** 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.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.beliefs -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.beliefs
},
/** 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
FoundingOrEnhancing("foundingOrEnhancing", "founding", "`founding` or `enhancing`", "Prophet Action Filters",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
private val knownValues = setOf("founding", "enhancing")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in knownValues -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** [UniqueType.ConditionalTech] and others, no central implementation */
Event("event", "Inspiration", "The name of any event") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.events -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.events
},
/** [UniqueType.ConditionalTech] and others, no central implementation */
Technology("tech", "Agriculture", "The name of any tech") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.technologies -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.technologies
},
/** Implemented by [Technology.matchesFilter][com.unciv.models.ruleset.tech.Technology.matchesFilter] */
TechFilter("techFilter", "Agriculture") {
private val knownValues = setOf("All", "all")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (parameterText in ruleset.technologies) return true
if (parameterText in ruleset.eras) return true
return false
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when (parameterText) {
in Constants.all -> true
in ruleset.technologies -> true
in ruleset.eras -> true
else -> false
}
override fun getTranslationWriterStringsForOutput() = knownValues
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
override fun getTranslationWriterStringsForOutput() = Constants.all
},
/** unused at the moment with vanilla rulesets */
Specialist("specialist", "Merchant", "The name of any specialist") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when (parameterText) {
in ruleset.specialists -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.specialists
},
/** [UniqueType.ConditionalAfterPolicyOrBelief] and others, no central implementation */
Policy("policy", "Oligarchy", "The name of any policy") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
return when (parameterText) {
in ruleset.policies -> null
else -> UniqueType.UniqueParameterErrorSeverity.RulesetSpecific
}
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.policies
},
/** Implemtented by [com.unciv.models.ruleset.Policy.matchesFilter] */
/** Implemented by [com.unciv.models.ruleset.Policy.matchesFilter] */
PolicyFilter("policyFilter", "Oligarchy", "The name of any policy") {
private val knownValues = Constants.all
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (parameterText in ruleset.policies) return true
if (ruleset.policies.values.any { it.hasUnique(parameterText) }) return true
return false
}
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
return getErrorSeverityForFilter(parameterText, ruleset)
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
parameterText in Constants.all -> true
parameterText in ruleset.policies -> true
ruleset.policies.values.any { it.hasUnique(parameterText) } -> true
else -> false
}
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = getErrorSeverityForFilter(parameterText, ruleset)
},
/** Used by [UniqueType.HiddenWithoutVictoryType], implementation in Civilopedia, OverviewScreen and to exclude e.g. from Quests */
VictoryT("victoryType", "Domination", "The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
return if (parameterText in ruleset.victories) null
else UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
VictoryT("victoryType",
"Domination", "The name of any victory type: 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time' or one of your mod's VictoryTypes.json names"
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in ruleset.victories
},
/** Used by [UniqueType.KillUnitPlunder] and [UniqueType.KillUnitPlunderNearCity], implementation in [Battle.tryEarnFromKilling][com.unciv.logic.battle.Battle.tryEarnFromKilling] */
CostOrStrength("costOrStrength", "Cost", "`Cost` or `Strength`") {
CostOrStrength("costOrStrength", "Cost", "`Cost` or `Strength`",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
private val knownValues = setOf("Cost", "Strength")
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueParameterErrorSeverity? {
return if (parameterText in knownValues) null
else UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = parameterText in knownValues
},
/** Mod declarative compatibility: Define Mod relations by their name. */
ModName("modFilter", "DeCiv Redux", """A Mod name, case-sensitive _or_ a simple wildcard filter beginning and ending in an Asterisk, case-insensitive""", "Mod name filter") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = when {
BaseRuleset.values().any { it.fullName == parameterText } -> null // Only Builtin ruleset names can contain '-'
parameterText == "*Civ V -*" || parameterText == "*Civ V - *" -> null // Wildcard filter for builtin
'-' in parameterText -> UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
parameterText.matches(Regex("""^\*[^*]+\*$""")) -> null
parameterText.startsWith('*') || parameterText.endsWith('*') -> UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
else -> null
ModName("modFilter",
"DeCiv Redux", """A Mod name, case-sensitive _or_ a simple wildcard filter beginning and ending in an Asterisk, case-insensitive""", "Mod name filter",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = when {
BaseRuleset.values().any { it.fullName == parameterText } -> true // Verbatim builtin
parameterText == "*Civ V -*" || parameterText == "*Civ V - *" -> true // Wildcard filter for builtin
'-' in parameterText -> false // Only Builtin ruleset names can contain '-'
parameterText.matches(Regex("""^\*[^*]+\*$""")) -> true // Wildcard on both ends and no wildcard in between
parameterText.startsWith('*') || parameterText.endsWith('*') -> true // one-sided wildcards aren't implemented (feel free to...)
else -> true
}
override fun getTranslationWriterStringsForOutput() = scanExistingValues(this)
},
/** Suppress RulesetValidator warnings: Parameter check delegated to RulesetValidator, and auto-translation off. */
ValidationWarning("validationWarning", Suppression.parameterDocExample, Suppression.parameterDocDescription, "Mod-check warning") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? =
if (Suppression.isValidFilter(parameterText)) null
else UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
ValidationWarning("validationWarning",
Suppression.parameterDocExample, Suppression.parameterDocDescription, "Mod-check warning",
severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
) {
override fun isKnownValue(parameterText: String, ruleset: Ruleset) = Suppression.isValidFilter(parameterText)
},
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
Comment("comment", "comment", null, "Unique Specials") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = null
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = null
override fun getTranslationWriterStringsForOutput() = scanExistingValues(this)
},
/** We don't know anything about this parameter - this needs to return
* [isTranslationWriterGuess]() == `true` for all inputs or TranslationFileWriter will have a problem! */
Unknown("param", "Unknown") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? = null
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = null
};
//region _Internals
/** Validate a [Unique] parameter */
abstract fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity?
/** Validate a [Unique] parameter.
* - The default implementation flags [severityDefault] when [isKnownValue] returns `false`.
* - This means [getErrorSeverity] or [isKnownValue] ***must*** be overridden or else the UniqueParameterType is never valid.
* - Can be delegated to helper [getErrorSeverityForFilter] for multiFilters (uses [isKnownValue]).
* - Can be delegated to helper [getErrorSeverityViaKnownValue] for simple filters (uses [isKnownValue]).
*/
open fun getErrorSeverity(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? =
getErrorSeverityViaKnownValue(parameterText, ruleset)
/** Checks if [parameterText] is a valid value.
* - The default implementation returns `false`, and controls the default implementation of [getErrorSeverity].
* - If this is overridden and [getErrorSeverity] is not, the "bad" outcome is [severityDefault].
* - [getErrorSeverity] takes precedence and chooses whether to call this or not.
* - This means [getErrorSeverity] or [isKnownValue] ***must*** be overridden or else the UniqueParameterType is never valid.
*/
open fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean = false
fun getErrorSeverityForFilter(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? {
protected fun getErrorSeverityForFilter(parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? {
val isKnown = MultiFilter.multiFilter(parameterText, { isKnownValue(it, ruleset) }, true)
if (isKnown) return null
return UniqueType.UniqueParameterErrorSeverity.PossibleFilteringUnique
}
protected fun getErrorSeverityViaKnownValue(
parameterText: String, ruleset: Ruleset,
errorSeverity: UniqueType.UniqueParameterErrorSeverity = severityDefault
) = if (isKnownValue(parameterText, ruleset)) null else errorSeverity
protected fun String.isFilteringUniqueIn(map: Map<String, IHasUniques>)
= map.values.any { this in it.uniques }
protected fun String.getInvariantSeverityUnless(predicate: String.() -> Boolean) =
if (predicate()) null else UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
/** Pick this type when [TranslationFileWriter] tries to guess for an untyped [Unique] */
open fun isTranslationWriterGuess(parameterText: String, ruleset: Ruleset): Boolean =
getErrorSeverity(parameterText, ruleset) == null

View File

@ -540,20 +540,19 @@ object UniqueTriggerActivation {
UniqueType.UnitsGainPromotion -> {
val filter = unique.params[0]
val promotion = unique.params[1]
val promotionName = unique.params[1]
val promotion = ruleset.unitPromotions[promotionName] ?: return null
val unitsToPromote = civInfo.units.getCivUnits().filter { it.matchesFilter(filter) }
.filter { unitToPromote ->
ruleset.unitPromotions.values.any {
it.name == promotion && unitToPromote.type.name in it.unitTypes
}
val unitsToPromote = civInfo.units.getCivUnits()
.filter {
it.matchesFilter(filter) && (it.type.name in promotion.unitTypes || promotion.unitTypes.isEmpty())
}.toList()
if (unitsToPromote.isEmpty()) return null
return {
val promotedUnitLocations: MutableList<Vector2> = mutableListOf()
for (civUnit in unitsToPromote) {
civUnit.promotions.addPromotion(promotion, isFree = true)
civUnit.promotions.addPromotion(promotionName, isFree = true)
promotedUnitLocations.add(civUnit.getTile().position)
}
@ -562,7 +561,7 @@ object UniqueTriggerActivation {
notification,
MapUnitAction(promotedUnitLocations),
NotificationCategory.Units,
"unitPromotionIcons/${unique.params[1]}"
"unitPromotionIcons/$promotionName"
)
}
true

View File

@ -189,7 +189,10 @@ enum class UniqueType(
/// Resource production & consumption
ConsumesResources("Consumes [amount] [resource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit),
ProvidesResources("Provides [amount] [resource]", UniqueTarget.Global, UniqueTarget.Improvement, UniqueTarget.FollowerBelief),
CostsResources("Costs [amount] [stockpiledResource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit),
//todo should these two be merged to avoid the confusion?
/** @see UnitActionStockpileCost */
CostsResources("Costs [amount] [stockpiledResource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit,
docDescription = "Do not confuse with \"costs [amount] [stockpiledResource]\" (lowercase 'c'), the Unit Action Modifier."),
// Todo: Get rid of forced sign (+[relativeAmount]) and unify these two, e.g.: "[relativeAmount]% [resource/resourceType] production"
// Note that the parameter type 'resourceType' (strategic, luxury, bonus) currently doesn't exist and should then be added as well
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[relativeAmount]%", UniqueTarget.Global), // used by Policies
@ -510,8 +513,9 @@ enum class UniqueType(
docDescription = "Requires [amount] of Movement to execute. Unit's Movement is rounded up"),
UnitActionStatsCost("costs [stats] stats", UniqueTarget.UnitActionModifier,
docDescription = "A positive Integer value will be subtracted from your stock. Food and Production will be removed from Closest City's current stock"),
/** @see CostsResources */
UnitActionStockpileCost("costs [amount] [stockpiledResource]", UniqueTarget.UnitActionModifier,
docDescription = "A positive Integer value will be subtracted from your stock."),
docDescription = "A positive Integer value will be subtracted from your stock. Do not confuse with \"Costs [amount] [stockpiledResource]\" (uppercase 'C') for Improvements, Buildings, and Units."),
UnitActionOnce("once", UniqueTarget.UnitActionModifier),
UnitActionLimitedTimes("[amount] times", UniqueTarget.UnitActionModifier),
UnitActionExtraLimitedTimes("[amount] additional time(s)", UniqueTarget.UnitActionModifier),
@ -802,7 +806,8 @@ enum class UniqueType(
OneTimeChangeTerrain("Turn this tile into a [terrainName] tile", UniqueTarget.Triggerable),
UnitsGainPromotion("[mapUnitFilter] units gain the [promotion] promotion", UniqueTarget.Triggerable), // Not used in Vanilla
UnitsGainPromotion("[mapUnitFilter] units gain the [promotion] promotion", UniqueTarget.Triggerable,
docDescription = "Works only with promotions that are valid for the unit's type - or for promotions that do not specify any."), // Not used in Vanilla
FreeStatBuildings("Provides the cheapest [stat] building in your first [positiveAmount] cities for free", UniqueTarget.Triggerable), // used in Policy
FreeSpecificBuildings("Provides a [buildingName] in your first [positiveAmount] cities for free", UniqueTarget.Triggerable), // used in Policy
TriggerEvent("Triggers a [event] event", UniqueTarget.Triggerable),

View File

@ -107,12 +107,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "Instantly consumes [positiveAmount] [stockpiledResource]"
Example: "Instantly consumes [3] [StockpiledResource]"
Example: "Instantly consumes [3] [Mana]"
Applicable to: Triggerable
??? example "Instantly provides [positiveAmount] [stockpiledResource]"
Example: "Instantly provides [3] [StockpiledResource]"
Example: "Instantly provides [3] [Mana]"
Applicable to: Triggerable
@ -163,6 +163,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Triggerable
??? example "[mapUnitFilter] units gain the [promotion] promotion"
Works only with promotions that are valid for the unit's type - or for promotions that do not specify any.
Example: "[Wounded] units gain the [Shock I] promotion"
Applicable to: Triggerable
@ -1068,7 +1069,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Building, Unit, Improvement
??? example "Costs [amount] [stockpiledResource]"
Example: "Costs [3] [StockpiledResource]"
Do not confuse with "costs [amount] [stockpiledResource]" (lowercase 'c'), the Unit Action Modifier.
Example: "Costs [3] [Mana]"
Applicable to: Building, Unit, Improvement
@ -2459,8 +2461,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: UnitActionModifier
??? example "&lt;costs [amount] [stockpiledResource]&gt;"
A positive Integer value will be subtracted from your stock.
Example: "&lt;costs [3] [StockpiledResource]&gt;"
A positive Integer value will be subtracted from your stock. Do not confuse with "Costs [amount] [stockpiledResource]" (uppercase 'C') for Improvements, Buildings, and Units.
Example: "&lt;costs [3] [Mana]&gt;"
Applicable to: UnitActionModifier
@ -2507,12 +2509,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
*[civWideStat]: All the following stats have civ-wide fields: `Gold`, `Science`, `Culture`, `Faith`.
*[combatantFilter]: This indicates a combatant, which can either be a unit or a city (when bombarding). Must either be `City` or a `mapUnitFilter`.
*[costOrStrength]: `Cost` or `Strength`.
*[countable]: This indicate a number or a numeric variable.
*[countable]: This indicates a number or a numeric variable.
*[era]: The name of any era.
*[event]: The name of any event.
*[foundingOrEnhancing]: `founding` or `enhancing`.
*[fraction]: Indicates a fractional number, which can be negative.
*[improvementName]: The name of any improvement.
*[improvementName]: The name of any improvement excluding 'Cancel improvement order'
*[modFilter]: A Mod name, case-sensitive _or_ a simple wildcard filter beginning and ending in an Asterisk, case-insensitive.
*[policy]: The name of any policy.
*[policyFilter]: The name of any policy.
@ -2524,8 +2526,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
*[speed]: The name of any speed.
*[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!
*[stockpiledResource]: The name of any stockpiled.
*[stockpiledResource]: The name of any stockpiled resource.
*[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'
*[unitType]: Can be 'Land', 'Water', 'Air', any unit type, a filtering Unique on a unit type, or a multi-filter of these.
*[validationWarning]: Suppresses one specific Ruleset validation warning. This can specify the full text verbatim including correct upper/lower case, or it can be a wildcard case-insensitive simple pattern starting and ending in an asterisk ('*'). If the suppression unique is used within an object or as modifier (not ModOptions), the wildcard symbols can be omitted, as selectivity is better due to the limited scope.
*[victoryType]: The name of any victory type: 'Neutral', 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time'
*[victoryType]: The name of any victory type: 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time' or one of your mod's VictoryTypes.json names.