From 5e89e2f46d42b47e68171a33a217820955382d0c Mon Sep 17 00:00:00 2001 From: PLynx Date: Mon, 1 Apr 2024 11:01:20 +0200 Subject: [PATCH] Countable comparison conditional uniques (#11308) * Added the countable comparison conditional uniques * Applied the suggestions of yairm * Minor wording change --- .../models/ruleset/unique/Conditionals.kt | 77 +++++++++++++++++++ .../ruleset/unique/UniqueParameterType.kt | 22 ++++++ .../unciv/models/ruleset/unique/UniqueType.kt | 7 ++ docs/Modders/uniques.md | 26 +++++++ 4 files changed, 132 insertions(+) diff --git a/core/src/com/unciv/models/ruleset/unique/Conditionals.kt b/core/src/com/unciv/models/ruleset/unique/Conditionals.kt index cf6092eab5..b60b252041 100644 --- a/core/src/com/unciv/models/ruleset/unique/Conditionals.kt +++ b/core/src/com/unciv/models/ruleset/unique/Conditionals.kt @@ -99,6 +99,57 @@ object Conditionals { return compare(statReserve, lowerLimit * gameSpeedModifier, upperLimit * gameSpeedModifier) } + fun getCountableAmount(countable: String): Float? { + if (countable.toFloatOrNull() != null) return countable.toFloat() + + val relevantStat = Stat.safeValueOf(countable) + + if (relevantStat != null) { + return if (relevantCity != null) { + relevantCity!!.getStatReserve(relevantStat).toFloat() + } else if (relevantStat in Stat.statsWithCivWideField && relevantCiv != null) { + relevantCiv!!.getStatReserve(relevantStat).toFloat() + } else { + null + } + } + + if (gameInfo == null) return null + + if (countable == "year") return gameInfo!!.getYear(gameInfo!!.turns).toFloat() + if (gameInfo!!.ruleset.tileResources.containsKey(countable)) + return getResourceAmount(countable).toFloat() + + return null + } + + fun compareCountables( + first: String, + second: String, + compare: (first: Float, second: Float) -> Boolean): Boolean { + + val firstNumber = getCountableAmount(first) + val secondNumber = getCountableAmount(second) + + return if (firstNumber != null && secondNumber != null) + compare(firstNumber, secondNumber) + else + false + } + + fun compareCountables(first: String, second: String, third: String, + compare: (first: Float, second: Float, third: Float) -> Boolean): Boolean { + + val firstNumber = getCountableAmount(first) + val secondNumber = getCountableAmount(second) + val thirdNumber = getCountableAmount(third) + + return if (firstNumber != null && secondNumber != null && thirdNumber != null) + compare(firstNumber, secondNumber, thirdNumber) + else + false + } + return when (condition.type) { // These are 'what to do' and not 'when to do' conditionals UniqueType.ConditionalTimedUnique -> true @@ -286,6 +337,32 @@ object Conditionals { && it.policies.isAdopted(unique.sourceObjectName!!) // guarded by the sourceObjectType check } } + UniqueType.ConditionalCountableEqualTo -> + compareCountables(condition.params[0], condition.params[1]) { + first, second -> first == second + } + + UniqueType.ConditionalCountableDifferentThan -> + compareCountables(condition.params[0], condition.params[1]) { + first, second -> first != second + } + + UniqueType.ConditionalCountableGreaterThan -> + compareCountables(condition.params[0], condition.params[1]) { + first, second -> first > second + } + + UniqueType.ConditionalCountableLessThan -> + compareCountables(condition.params[0], condition.params[1]) { + first, second -> first < second + } + + UniqueType.ConditionalCountableBetween -> + compareCountables(condition.params[0], condition.params[1], condition.params[2]) { + first, second, third -> + first in second..third + } + else -> false } } diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt index befc2e2b4c..b98583b3d6 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueParameterType.kt @@ -75,6 +75,28 @@ enum class UniqueParameterType( } }, + Countable("countable", "1000", "This indicate 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 (parameterText.toFloatOrNull() != null) return true + if (Stat.isStat(parameterText)) return true + if (parameterText in ruleset.tileResources) return true + return false + } + + override fun getErrorSeverity( + parameterText: String, ruleset: Ruleset): UniqueType.UniqueParameterErrorSeverity? { + return if (isKnownValue(parameterText, ruleset)) null + else UniqueType.UniqueParameterErrorSeverity.RulesetSpecific + } + }, + // todo potentially remove if OneTimeRevealSpecificMapTiles changes KeywordAll("'all'", "All") { override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) = diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index b95d216163..f2e1708a08 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -742,6 +742,13 @@ enum class UniqueType( ConditionalInRegionOfType("in [regionType] Regions", UniqueTarget.Conditional), ConditionalInRegionExceptOfType("in all except [regionType] Regions", UniqueTarget.Conditional), + /////// countables conditionals + ConditionalCountableEqualTo("when number of [countable] is equal to [countable]", UniqueTarget.Conditional), + ConditionalCountableDifferentThan("when number of [countable] is different than [countable]", UniqueTarget.Conditional), + ConditionalCountableGreaterThan("when number of [countable] is greater than [countable]", UniqueTarget.Conditional), + ConditionalCountableLessThan("when number of [countable] is less than [countable]", UniqueTarget.Conditional), + ConditionalCountableBetween("when number of [countable] is between [countable] and [countable]", UniqueTarget.Conditional), + //endregion ///////////////////////////////////////// region 09 TRIGGERED ONE-TIME ///////////////////////////////////////// diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 5fb6e1a7a5..7b5c21afc5 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -2236,6 +2236,31 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Conditional +??? example "<when number of [countable] is equal to [countable]>" + Example: "<when number of [1000] is equal to [1000]>" + + Applicable to: Conditional + +??? example "<when number of [countable] is different than [countable]>" + Example: "<when number of [1000] is different than [1000]>" + + Applicable to: Conditional + +??? example "<when number of [countable] is greater than [countable]>" + Example: "<when number of [1000] is greater than [1000]>" + + Applicable to: Conditional + +??? example "<when number of [countable] is less than [countable]>" + Example: "<when number of [1000] is less than [1000]>" + + Applicable to: Conditional + +??? example "<when number of [countable] is between [countable] and [countable]>" + Example: "<when number of [1000] is between [1000] and [1000]>" + + Applicable to: Conditional + ## TriggerCondition uniques !!! note "" @@ -2406,6 +2431,7 @@ 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. *[era]: The name of any era. *[event]: The name of any event. *[foundingOrEnhancing]: `founding` or `enhancing`.