diff --git a/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json b/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json index a11624d1dc..b5ed4cf1a2 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Beliefs.json @@ -30,7 +30,7 @@ { "name": "God of Craftsman", "type": "Pantheon", - "uniques": ["[+1 Production] "] + "uniques": ["[+1 Production] [in cities following this religion] "] }, { "name": "God of the Open Sky", @@ -55,7 +55,7 @@ { "name": "Goddess of Love", "type": "Pantheon", - "uniques": ["[+1 Happiness] "] + "uniques": ["[+1 Happiness] [in cities following this religion] "] }, { "name": "Goddess of Protection", diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 2da79a58dd..d6b628ab03 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -840,7 +840,7 @@ object NextTurnAutomation { val baseForce = 30f var ourCombatStrength = civInfo.getStatForRanking(RankingType.Force).toFloat() + baseForce - if (civInfo.getCapital()!= null) ourCombatStrength += CityCombatant(civInfo.getCapital()!!).getCityStrength() + if (civInfo.getCapital() != null) ourCombatStrength += CityCombatant(civInfo.getCapital()!!).getCityStrength() var theirCombatStrength = otherCiv.getStatForRanking(RankingType.Force).toFloat() + baseForce if(otherCiv.getCapital() != null) theirCombatStrength += CityCombatant(otherCiv.getCapital()!!).getCityStrength() diff --git a/core/src/com/unciv/models/Religion.kt b/core/src/com/unciv/models/Religion.kt index 21f377e53f..231b9ff296 100644 --- a/core/src/com/unciv/models/Religion.kt +++ b/core/src/com/unciv/models/Religion.kt @@ -65,11 +65,9 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { return mapToExistingBeliefs((founderBeliefs + followerBeliefs).toHashSet()).asSequence() val beliefs = - when (beliefType) { - BeliefType.Pantheon -> followerBeliefs - BeliefType.Follower -> followerBeliefs - BeliefType.Founder -> founderBeliefs - BeliefType.Enhancer -> founderBeliefs + when { + beliefType.isFollower -> followerBeliefs + beliefType.isFounder -> founderBeliefs else -> null!! // This is fine... } diff --git a/core/src/com/unciv/models/ruleset/Belief.kt b/core/src/com/unciv/models/ruleset/Belief.kt index 4879688b9d..ab52d3fee9 100644 --- a/core/src/com/unciv/models/ruleset/Belief.kt +++ b/core/src/com/unciv/models/ruleset/Belief.kt @@ -17,7 +17,7 @@ class Belief() : RulesetObject() { } override fun getUniqueTarget() = - if (type == BeliefType.Founder || type == BeliefType.Enhancer) UniqueTarget.FounderBelief + if (type.isFounder) UniqueTarget.FounderBelief else UniqueTarget.FollowerBelief override fun makeLink() = "Belief/$name" @@ -79,11 +79,15 @@ class Belief() : RulesetObject() { } } -enum class BeliefType(val color: String) { +/** Subtypes of Beliefs - directly deserialized. + * @param isFollower - Behaves as "follower" belief, Uniques processed per city + * @param isFounder - Behaves as "founder" belief, Uniques processed globally for founding civ only + * */ +enum class BeliefType(val color: String, val isFollower: Boolean = false, val isFounder: Boolean = false) { None(""), - Pantheon("#44c6cc"), - Founder("#c00000"), - Follower("#ccaa44"), - Enhancer("#72cc45"), + Pantheon("#44c6cc", isFollower = true), + Founder("#c00000", isFounder = true), + Follower("#ccaa44", isFollower = true), + Enhancer("#72cc45", isFounder = true), Any(""), } diff --git a/core/src/com/unciv/models/ruleset/RulesetValidator.kt b/core/src/com/unciv/models/ruleset/RulesetValidator.kt index fb82b06274..b8d83b4891 100644 --- a/core/src/com/unciv/models/ruleset/RulesetValidator.kt +++ b/core/src/com/unciv/models/ruleset/RulesetValidator.kt @@ -9,6 +9,7 @@ import com.unciv.models.ruleset.tile.TerrainType import com.unciv.models.ruleset.unique.IHasUniques import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.Unique +import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unit.Promotion import com.unciv.models.stats.INamed @@ -471,7 +472,7 @@ class RulesetValidator(val ruleset: Ruleset) { severityToReport: UniqueType.UniqueComplianceErrorSeverity ): List { var name = namedObj?.name ?: "" - if (namedObj!=null && namedObj is IRulesetObject) name = "${namedObj.originRuleset}: $name" + if (namedObj != null && namedObj is IRulesetObject) name = "${namedObj.originRuleset}: $name" if (unique.type == null) { if (!tryFixUnknownUniques) return emptyList() val similarUniques = UniqueType.values().filter { @@ -515,6 +516,9 @@ class RulesetValidator(val ruleset: Ruleset) { val rulesetErrors = RulesetErrorList() + if (namedObj is IHasUniques && !unique.type.canAcceptUniqueTarget(namedObj.getUniqueTarget())) + rulesetErrors.add(RulesetError("$name's unique \"${unique.text}\" is not allowed on its target type", RulesetErrorSeverity.Warning)) + val typeComplianceErrors = unique.type.getComplianceErrors(unique, ruleset) for (complianceError in typeComplianceErrors) { if (complianceError.errorSeverity <= severityToReport) @@ -533,6 +537,11 @@ class RulesetValidator(val ruleset: Ruleset) { RulesetErrorSeverity.Warning ) } else { + if (conditional.type.targetTypes.none { it.modifierType != UniqueTarget.ModifierType.None }) + rulesetErrors.add("$name's unique \"${unique.text}\" contains the conditional \"${conditional.text}\"," + + " which is a Unique type not allowed as conditional or trigger.", + RulesetErrorSeverity.Warning) + val conditionalComplianceErrors = conditional.type.getComplianceErrors(conditional, ruleset) for (complianceError in conditionalComplianceErrors) { diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index 7093522228..91f28b7e65 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -44,9 +44,11 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s fun hasTriggerConditional(): Boolean { if(conditionals.none()) return false - return conditionals.any{ conditional -> conditional.type?.targetTypes - ?.any{ it.canAcceptUniqueTarget(UniqueTarget.TriggerCondition) || it.canAcceptUniqueTarget(UniqueTarget.UnitActionModifier) } - ?: false + return conditionals.any { conditional -> + conditional.type?.targetTypes?.any { + it.canAcceptUniqueTarget(UniqueTarget.TriggerCondition) || it.canAcceptUniqueTarget(UniqueTarget.UnitActionModifier) + } + ?: false } } @@ -134,8 +136,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s state: StateForConditionals ): Boolean { - val nonConditionalConditionTypes = setOf(UniqueTarget.TriggerCondition, UniqueTarget.UnitTriggerCondition, UniqueTarget.UnitActionModifier) - if (condition.type?.targetTypes?.any { it in nonConditionalConditionTypes } == true) + if (condition.type?.targetTypes?.any { it.modifierType == UniqueTarget.ModifierType.Other } == true) return true // not a filtering condition fun ruleset() = state.civInfo!!.gameInfo.ruleset diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueFlag.kt b/core/src/com/unciv/models/ruleset/unique/UniqueFlag.kt new file mode 100644 index 0000000000..a17674ef71 --- /dev/null +++ b/core/src/com/unciv/models/ruleset/unique/UniqueFlag.kt @@ -0,0 +1,9 @@ +package com.unciv.models.ruleset.unique + +enum class UniqueFlag { + HiddenToUsers, + ; + companion object { + val setOfHiddenToUsers = listOf(HiddenToUsers) + } +} diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTarget.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTarget.kt new file mode 100644 index 0000000000..ff6afe36d5 --- /dev/null +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTarget.kt @@ -0,0 +1,79 @@ +package com.unciv.models.ruleset.unique + +/** + * Expresses which RulesetObject types a UniqueType is applicable to. + * + * @param documentationString Copied to uniques.md by `UniqueDocsWriter` + * @param inheritsFrom means that all such uniques are acceptable as well. For example, all Global uniques are acceptable for Nations, Eras, etc. + */ +enum class UniqueTarget( + val documentationString:String = "", + val inheritsFrom: UniqueTarget? = null, + val modifierType: ModifierType = ModifierType.None +) { + + /** Only includes uniques that have immediate effects, caused by UniqueTriggerActivation */ + Triggerable("Uniques that have immediate, one-time effects. " + + "These can be added to techs to trigger when researched, to policies to trigger when adopted, " + + "to eras to trigger when reached, to buildings to trigger when built. " + + "Alternatively, you can add a TriggerCondition to them to make them into Global uniques that activate upon a specific event." + + "They can also be added to units to grant them the ability to trigger this effect as an action, " + + "which can be modified with UnitActionModifier and UnitTriggerCondition conditionals."), + + UnitTriggerable("Uniques that have immediate, one-time effects on a unit." + + "They can be added to units (on unit, unit type, or promotion) to grant them the ability to trigger this effect as an action, " + + "which can be modified with UnitActionModifier and UnitTriggerCondition conditionals.", Triggerable), + + Global("Uniques that apply globally. " + + "Civs gain the abilities of these uniques from nation uniques, reached eras, researched techs, adopted policies, " + + "built buildings, religion 'founder' uniques, owned resources, and ruleset-wide global uniques.", Triggerable), + + // Civilization-specific + Nation(inheritsFrom = Global), + Era(inheritsFrom = Global), + Tech(inheritsFrom = Global), + Policy(inheritsFrom = Global), + FounderBelief("Uniques for Founder and Enhancer type Beliefs, that will apply to the founder of this religion", inheritsFrom = Global), + FollowerBelief("Uniques for Pantheon and Follower type beliefs, that will apply to each city where the religion is the majority religion"), + + // City-specific + Building(inheritsFrom = Global), + Wonder(inheritsFrom = Building), + + // Unit-specific + Unit("Uniques that can be added to units, unit types, or promotions", inheritsFrom = UnitTriggerable), + UnitType(inheritsFrom = Unit), + Promotion(inheritsFrom = Unit), + + // Tile-specific + Terrain, + Improvement, + Resource(inheritsFrom = Global), + Ruins(inheritsFrom = UnitTriggerable), + + // Other + Speed, + Tutorial, + CityState(inheritsFrom = Global), + ModOptions, + + // Modifiers + Conditional("Modifiers that can be added to other uniques to limit when they will be active", modifierType = ModifierType.Conditional), + TriggerCondition("Special conditionals that can be added to Triggerable uniques, to make them activate upon specific actions.", inheritsFrom = Global, modifierType = ModifierType.Other), + UnitTriggerCondition("Special conditionals that can be added to UnitTriggerable uniques, to make them activate upon specific actions.", inheritsFrom = TriggerCondition, modifierType = ModifierType.Other), + UnitActionModifier("Modifiers that can be added to unit action uniques as conditionals", modifierType = ModifierType.Other), + ; + + /** Whether a UniqueType is allowed in the `` part - or not. + * [None] ensures use *only* as leading Unique, [Conditional] / [Other] disallow use as leading Unique. */ + enum class ModifierType { None, Conditional, Other } + + /** Checks whether a specific UniqueTarget `this` as e.g. given by [IHasUniques.getUniqueTarget] works with [uniqueTarget] as e.g. declared in UniqueType */ + // Building.canAcceptUniqueTarget(Global) == true + // Global.canAcceptUniqueTarget(Building) == false + fun canAcceptUniqueTarget(uniqueTarget: UniqueTarget): Boolean { + if (this == uniqueTarget) return true + if (inheritsFrom != null) return inheritsFrom.canAcceptUniqueTarget(uniqueTarget) + return false + } +} diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 6b1c6255ba..75af3393da 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -6,86 +6,17 @@ import com.unciv.models.ruleset.RulesetErrorSeverity import com.unciv.models.translations.getPlaceholderParameters import com.unciv.models.translations.getPlaceholderText -/** inheritsFrom means that all such uniques are acceptable as well. - * For example, all Global uniques are acceptable for Nations, Eras, etc. */ -enum class UniqueTarget(val documentationString:String = "", val inheritsFrom: UniqueTarget? = null) { - - /** Only includes uniques that have immediate effects, caused by UniqueTriggerActivation */ - Triggerable("Uniques that have immediate, one-time effects. " + - "These can be added to techs to trigger when researched, to policies to trigger when adpoted, " + - "to eras to trigger when reached, to buildings to trigger when built. " + - "Alternatively, you can add a TriggerCondition to them to make them into Global uniques that activate upon a specific event." + - "They can also be added to units to grant them the ability to trigger this effect as an action, " + - "which can be modified with UnitActionModifier and UnitTriggerCondition conditionals."), - - UnitTriggerable("Uniques that have immediate, one-time effects on a unit." + - "They can be added to units (on unit, unit type, or promotion) to grant them the ability to trigger this effect as an action, " + - "which can be modified with UnitActionModifier and UnitTriggerCondition conditionals.", Triggerable), - - Global("Uniques that apply globally. " + - "Civs gain the abilities of these uniques from nation uniques, reached eras, researched techs, adopted policies, " + - "built buildings, religion 'founder' uniques, owned resources, and ruleset-wide global uniques.", Triggerable), - - // Civilization-specific - Nation(inheritsFrom = Global), - Era(inheritsFrom = Global), - Tech(inheritsFrom = Global), - Policy(inheritsFrom = Global), - FounderBelief("Uniques for Founder and Enhancer type Beliefs, that will apply to the founder of this religion", inheritsFrom = Global), - FollowerBelief("Uniques for Pantheon and Follower type beliefs, that will apply to each city where the religion is the majority religion"), - - // City-specific - Building(inheritsFrom = Global), - Wonder(inheritsFrom = Building), - - // Unit-specific - Unit("Uniques that can be added to units, unit types, or promotions", inheritsFrom = UnitTriggerable), - UnitType(inheritsFrom = Unit), - Promotion(inheritsFrom = Unit), - - // Tile-specific - Terrain, - Improvement, - Resource(inheritsFrom = Global), - Ruins(inheritsFrom = UnitTriggerable), - - // Other - Speed, - Tutorial, - CityState(inheritsFrom = Global), - ModOptions, - Conditional("Modifiers that can be added to other uniques to limit when they will be active"), - TriggerCondition("Special conditionals that can be added to Triggerable uniques, to make them activate upon specific actions.", inheritsFrom = Global), - UnitTriggerCondition("Special conditionals that can be added to UnitTriggerable uniques, to make them activate upon specific actions.", inheritsFrom = TriggerCondition), - UnitActionModifier("Modifiers that can be added to unit action uniques as conditionals"), - ; - - fun canAcceptUniqueTarget(uniqueTarget: UniqueTarget): Boolean { - if (this == uniqueTarget) return true - if (inheritsFrom != null) return inheritsFrom.canAcceptUniqueTarget(uniqueTarget) - return false - } -} - -enum class UniqueFlag { - HiddenToUsers, - ; - companion object { - val setOfHiddenToUsers = listOf(HiddenToUsers) - } -} - - // I didn't put this in a companion object because APPARENTLY doing that means you can't use it in the init function. -val numberRegex = Regex("\\d+$") // Any number of trailing digits +private val numberRegex = Regex("\\d+$") // Any number of trailing digits + enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: List = emptyList()) { - //////////////////////////////////////// region GLOBAL UNIQUES //////////////////////////////////////// + //////////////////////////////////////// region 01 GLOBAL UNIQUES //////////////////////////////////////// // region Stat providing uniques // Used for *global* bonuses and improvement/terrain bonuses - Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief, UniqueTarget.Improvement, UniqueTarget.Terrain), + Stats("[stats]", UniqueTarget.Global, UniqueTarget.Improvement, UniqueTarget.Terrain), // Used for city-wide bonuses StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), @@ -121,8 +52,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: PercentProductionWonders("[relativeAmount]% Production when constructing [buildingFilter] wonders [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), PercentProductionBuildingsInCapital("[relativeAmount]% Production towards any buildings that already exist in the Capital", UniqueTarget.Global, UniqueTarget.FollowerBelief), - //endregion Stat providing uniques - + // endregion Stat providing uniques // region City-State related uniques @@ -146,8 +76,8 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: 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 + // endregion /////// region Other global uniques @@ -314,13 +244,12 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: SpawnRebels("Rebel units may spawn", UniqueTarget.Global), + // endregion Other global uniques - //endregion + // endregion 01 Global uniques - //endregion Global uniques - - ///////////////////////////////////////// region CONSTRUCTION UNIQUES ///////////////////////////////////////// + ///////////////////////////////////////// region 02 CONSTRUCTION UNIQUES ///////////////////////////////////////// Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit, UniqueTarget.Improvement), CannotBePurchased("Cannot be purchased", UniqueTarget.Building, UniqueTarget.Unit), @@ -339,7 +268,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: TriggersAlertOnCompletion("Triggers a global alert upon completion", UniqueTarget.Building, UniqueTarget.Unit), //endregion - ///////////////////////////////////////// region BUILDING UNIQUES ///////////////////////////////////////// + ///////////////////////////////////////// region 03 BUILDING UNIQUES ///////////////////////////////////////// CostIncreasesPerCity("Cost increases by [amount] per owned city", UniqueTarget.Building), @@ -376,7 +305,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: CreatesOneImprovement("Creates a [improvementName] improvement on a specific tile", UniqueTarget.Building), //endregion - ///////////////////////////////////////// region UNIT UNIQUES ///////////////////////////////////////// + ///////////////////////////////////////// region 04 UNIT UNIQUES ///////////////////////////////////////// // Unit action uniques // Unit actions should look like: "Can {action description}, to allow them to be combined with modifiers @@ -538,7 +467,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: //endregion - ///////////////////////////////////////// region UNIT ACTION MODIFIERS ///////////////////////////////////////// + ///////////////////////////////////////// region 05 UNIT ACTION MODIFIERS ///////////////////////////////////////// UnitActionConsumeUnit("by consuming this unit", UniqueTarget.UnitActionModifier), UnitActionMovementCost("for [amount] movement", UniqueTarget.UnitActionModifier), @@ -549,7 +478,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: // endregion - ///////////////////////////////////////// region TILE UNIQUES ///////////////////////////////////////// + ///////////////////////////////////////// region 06 TILE UNIQUES ///////////////////////////////////////// // Natural wonders NaturalWonderNeighborCount("Must be adjacent to [amount] [simpleTerrain] tiles", UniqueTarget.Terrain, flags = UniqueFlag.setOfHiddenToUsers), @@ -650,7 +579,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: AutomatedWorkersWillReplace("Will be replaced by automated workers", UniqueTarget.Improvement), //endregion - ///////////////////////////////////////// region CONDITIONALS ///////////////////////////////////////// + ///////////////////////////////////////// region 07 CONDITIONALS ///////////////////////////////////////// /////// general conditionals @@ -739,7 +668,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: //endregion - ///////////////////////////////////////// region TRIGGERED ONE-TIME ///////////////////////////////////////// + ///////////////////////////////////////// region 08 TRIGGERED ONE-TIME ///////////////////////////////////////// OneTimeFreeUnit("Free [unit] appears", UniqueTarget.Triggerable), // used in Policies, Buildings @@ -789,7 +718,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: //endregion - ///////////////////////////////////////// region TRIGGERS ///////////////////////////////////////// + ///////////////////////////////////////// region 09 TRIGGERS ///////////////////////////////////////// TriggerUponResearch("upon discovering [tech]", UniqueTarget.TriggerCondition), TriggerUponEnteringEra("upon entering the [era]", UniqueTarget.TriggerCondition), @@ -813,7 +742,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: //endregion - ///////////////////////////////////////// region UNIT TRIGGERS ///////////////////////////////////////// + ///////////////////////////////////////// region 10 UNIT TRIGGERS ///////////////////////////////////////// TriggerUponDefeatingUnit("upon defeating a [mapUnitFilter] unit", UniqueTarget.UnitTriggerCondition), TriggerUponDefeat("upon being defeated", UniqueTarget.UnitTriggerCondition), @@ -823,7 +752,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: //endregion - ///////////////////////////////////////////// region META ///////////////////////////////////////////// + ///////////////////////////////////////////// region 90 META ///////////////////////////////////////////// HiddenWithoutReligion("Hidden when religion is disabled", UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Ruins, flags = UniqueFlag.setOfHiddenToUsers), HiddenAfterGreatProphet("Hidden after generating a Great Prophet", UniqueTarget.Ruins), @@ -834,7 +763,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: // endregion - // region DEPRECATED AND REMOVED + ///////////////////////////////////////////// region 99 DEPRECATED AND REMOVED ///////////////////////////////////////////// @Deprecated("as of 4.5.3", ReplaceWith("Empire enters a [amount]-turn Golden Age "), DeprecationLevel.ERROR) StartGoldenAge("Can start an [amount]-turn golden age", UniqueTarget.Unit), @@ -1184,9 +1113,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: @Deprecated("Extremely old - used for auto-updates only", ReplaceWith("[+50]% Strength for cities "), DeprecationLevel.ERROR) StrengthForGarrisonedCitiesAttackingDeprecated("+50% attacking strength for cities with garrisoned units", UniqueTarget.Global), - // endregion - + // Keep the endregion after the semicolon or it won't work ; + // endregion /** A map of allowed [UniqueParameterType]s per parameter position. Initialized from overridable function [parameterTypeMapInitializer]. */ val parameterTypeMap = parameterTypeMapInitializer() @@ -1203,7 +1132,8 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: } return map } - val targetTypes = HashSet() + + val targetTypes = HashSet(targets.size) init { targetTypes.addAll(targets) @@ -1264,4 +1194,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: fun getDeprecationAnnotation(): Deprecated? = declaringJavaClass.getField(name) .getAnnotation(Deprecated::class.java) + /** Checks whether a specific [uniqueTarget] as e.g. given by [IHasUniques.getUniqueTarget] works with `this` UniqueType */ + fun canAcceptUniqueTarget(uniqueTarget: UniqueTarget) = + targetTypes.any { uniqueTarget.canAcceptUniqueTarget(it) } } diff --git a/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt b/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt index 870aa3adcb..c8a879c149 100644 --- a/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt +++ b/desktop/src/com/unciv/app/desktop/UniqueDocsWriter.kt @@ -57,9 +57,6 @@ class UniqueDocsWriter { lines += "# Uniques" lines += "Simple unique parameters are explained by mouseover. Complex parameters are explained in [Unique parameter types](../Unique-parameters)" - val conditionalLikeUniqueTargets = setOf(UniqueTarget.Conditional, UniqueTarget.TriggerCondition, - UniqueTarget.UnitTriggerCondition, UniqueTarget.UnitActionModifier) - for ((targetType, uniqueTypes) in targetTypesToUniques) { if (uniqueTypes.isEmpty()) continue lines += "## " + targetType.name + " uniques" @@ -70,7 +67,7 @@ class UniqueDocsWriter { for (uniqueType in uniqueTypes) { if (uniqueType.getDeprecationAnnotation() != null) continue - val uniqueText = if (targetType in conditionalLikeUniqueTargets) + val uniqueText = if (targetType.modifierType != UniqueTarget.ModifierType.None) "<${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 diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 6fcf2bd92f..2aa27ce454 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -3,7 +3,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ## Triggerable uniques !!! note "" - Uniques that have immediate, one-time effects. These can be added to techs to trigger when researched, to policies to trigger when adpoted, to eras to trigger when reached, to buildings to trigger when built. Alternatively, you can add a TriggerCondition to them to make them into Global uniques that activate upon a specific event.They can also be added to units to grant them the ability to trigger this effect as an action, which can be modified with UnitActionModifier and UnitTriggerCondition conditionals. + Uniques that have immediate, one-time effects. These can be added to techs to trigger when researched, to policies to trigger when adopted, to eras to trigger when reached, to buildings to trigger when built. Alternatively, you can add a TriggerCondition to them to make them into Global uniques that activate upon a specific event.They can also be added to units to grant them the ability to trigger this effect as an action, which can be modified with UnitActionModifier and UnitTriggerCondition conditionals. ??? example "Free [unit] appears" Example: "Free [Musketman] appears" @@ -165,7 +165,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "[stats]" Example: "[+1 Gold, +2 Production]" - Applicable to: Global, FollowerBelief, Terrain, Improvement + Applicable to: Global, Terrain, Improvement ??? example "[stats] [cityFilter]" Example: "[+1 Gold, +2 Production] [in all cities]"