mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
Every adjacent [mapUnitFilter] unit
This commit is contained in:
parent
e0ef4acb3f
commit
0a69cd0a0e
@ -1663,7 +1663,7 @@
|
|||||||
"unitType": "Civilian Water",
|
"unitType": "Civilian Water",
|
||||||
"uniques": [
|
"uniques": [
|
||||||
"[+15]% Strength bonus for [{Military} {Water}] units within [2] tiles",
|
"[+15]% Strength bonus for [{Military} {Water}] units within [2] tiles",
|
||||||
"[Target Unit] heals [100] HP <targeting [Water] units within [1] tiles> <by consuming this unit>",
|
"[Every adjacent [Water] unit] heals [100] HP <by consuming this unit>",
|
||||||
"Can be earned through combat",
|
"Can be earned through combat",
|
||||||
"Is part of Great Person group [Admiral]",
|
"Is part of Great Person group [Admiral]",
|
||||||
"Great Person - [War]", "Unbuildable", "Uncapturable"],
|
"Great Person - [War]", "Unbuildable", "Uncapturable"],
|
||||||
|
@ -19,7 +19,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
|
|||||||
override fun isDefeated(): Boolean = unit.health <= 0
|
override fun isDefeated(): Boolean = unit.health <= 0
|
||||||
override fun isInvisible(to: Civilization): Boolean = unit.isInvisible(to)
|
override fun isInvisible(to: Civilization): Boolean = unit.isInvisible(to)
|
||||||
override fun canAttack(): Boolean = unit.canAttack()
|
override fun canAttack(): Boolean = unit.canAttack()
|
||||||
override fun matchesFilter(filter: String, multiFilter: Boolean) = unit.matchesFilter(filter, multiFilter)
|
override fun matchesFilter(filter: String, multiFilter: Boolean) = unit.matchesFilter(filter, multiFilter=multiFilter)
|
||||||
override fun getAttackSound() = unit.baseUnit.attackSound.let {
|
override fun getAttackSound() = unit.baseUnit.attackSound.let {
|
||||||
if (it == null) UncivSound.Click else UncivSound(it)
|
if (it == null) UncivSound.Click else UncivSound(it)
|
||||||
}
|
}
|
||||||
|
@ -607,12 +607,12 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
/** Implements [UniqueParameterType.MapUnitFilter][com.unciv.models.ruleset.unique.UniqueParameterType.MapUnitFilter] */
|
/** Implements [UniqueParameterType.MapUnitFilter][com.unciv.models.ruleset.unique.UniqueParameterType.MapUnitFilter] */
|
||||||
@Readonly
|
@Readonly
|
||||||
fun matchesFilter(filter: String, multiFilter: Boolean = true): Boolean {
|
fun matchesFilter(filter: String, state: GameContext? = cache.state, multiFilter: Boolean = true): Boolean =
|
||||||
return if (multiFilter) MultiFilter.multiFilter(filter, ::matchesSingleFilter) else matchesSingleFilter(filter)
|
if (multiFilter) MultiFilter.multiFilter(filter, { matchesSingleFilter(it, state) })
|
||||||
}
|
else matchesSingleFilter(filter, state)
|
||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun matchesSingleFilter(filter: String): Boolean {
|
private fun matchesSingleFilter(filter: String, state: GameContext? = cache.state): Boolean {
|
||||||
return when (filter) {
|
return when (filter) {
|
||||||
Constants.wounded, "wounded units" -> health < 100
|
Constants.wounded, "wounded units" -> health < 100
|
||||||
Constants.barbarians, "Barbarian" -> civ.isBarbarian
|
Constants.barbarians, "Barbarian" -> civ.isBarbarian
|
||||||
@ -620,9 +620,9 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
|||||||
Constants.embarked -> isEmbarked()
|
Constants.embarked -> isEmbarked()
|
||||||
"Non-City" -> true
|
"Non-City" -> true
|
||||||
else -> {
|
else -> {
|
||||||
if (baseUnit.matchesFilter(filter, cache.state, false)) return true
|
if (baseUnit.matchesFilter(filter, state, false)) return true
|
||||||
if (civ.matchesFilter(filter, cache.state, false)) return true
|
if (civ.matchesFilter(filter, state, false)) return true
|
||||||
if (nonUnitUniquesMap.hasUnique(filter, cache.state)) return true
|
if (nonUnitUniquesMap.hasUnique(filter, if (state == null) cache.state else state)) return true
|
||||||
if (promotions.promotions.contains(filter)) return true
|
if (promotions.promotions.contains(filter)) return true
|
||||||
if (hasStatus(filter)) return true
|
if (hasStatus(filter)) return true
|
||||||
return false
|
return false
|
||||||
|
@ -12,6 +12,7 @@ import com.unciv.models.ruleset.unique.UniqueParameterType.Companion.guessTypeFo
|
|||||||
import com.unciv.models.ruleset.validation.Suppression
|
import com.unciv.models.ruleset.validation.Suppression
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.stats.SubStat
|
import com.unciv.models.stats.SubStat
|
||||||
|
import com.unciv.models.translations.getPlaceholderParameters
|
||||||
import com.unciv.models.translations.TranslationFileWriter
|
import com.unciv.models.translations.TranslationFileWriter
|
||||||
import yairm210.purity.annotations.Pure
|
import yairm210.purity.annotations.Pure
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
@ -86,7 +87,7 @@ enum class UniqueParameterType(
|
|||||||
|
|
||||||
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
|
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
|
||||||
KeywordAll("'all'", "All", severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant) {
|
KeywordAll("'all'", "All", severityDefault = UniqueType.UniqueParameterErrorSeverity.RulesetInvariant) {
|
||||||
override val staticKnownValues = Constants.all
|
override val staticKnownValues = Constants.all
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Implemented by [ICombatant.matchesCategory][com.unciv.logic.battle.ICombatant.matchesFilter] */
|
/** Implemented by [ICombatant.matchesCategory][com.unciv.logic.battle.ICombatant.matchesFilter] */
|
||||||
@ -596,8 +597,18 @@ enum class UniqueParameterType(
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
UnitTriggerTarget("unitTriggerTarget", Constants.thisUnit, "`${Constants.thisUnit}` or `${Constants.targetUnit}`") {
|
UnitTriggerTarget("unitTriggerTarget", Constants.thisUnit, "`${Constants.thisUnit}`, `${Constants.targetUnit}`, or `Every adjacent [mapUnitFilter] unit`") {
|
||||||
override val staticKnownValues = setOf(Constants.thisUnit, Constants.targetUnit)
|
override val staticKnownValues = setOf(Constants.thisUnit, Constants.targetUnit)
|
||||||
|
|
||||||
|
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
|
||||||
|
if (parameterText in staticKnownValues) return true
|
||||||
|
// Every adjacent [mapUnitFilter] unit
|
||||||
|
if (parameterText.startsWith("Every adjacent [") && parameterText.endsWith("] unit")) {
|
||||||
|
val params = parameterText.getPlaceholderParameters()
|
||||||
|
return MapUnitFilter.isKnownValue(params[0], ruleset)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Mod declarative compatibility: Define Mod relations by their name. */
|
/** Mod declarative compatibility: Define Mod relations by their name. */
|
||||||
|
@ -29,8 +29,10 @@ import com.unciv.models.ruleset.BeliefType
|
|||||||
import com.unciv.models.ruleset.Event
|
import com.unciv.models.ruleset.Event
|
||||||
import com.unciv.models.ruleset.tile.TerrainType
|
import com.unciv.models.ruleset.tile.TerrainType
|
||||||
import com.unciv.models.ruleset.tile.TileResource
|
import com.unciv.models.ruleset.tile.TileResource
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueParameterType
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
|
import com.unciv.models.translations.getPlaceholderParameters
|
||||||
import com.unciv.models.UncivSound
|
import com.unciv.models.UncivSound
|
||||||
import com.unciv.models.translations.fillPlaceholders
|
import com.unciv.models.translations.fillPlaceholders
|
||||||
import com.unciv.models.translations.hasPlaceholderParameters
|
import com.unciv.models.translations.hasPlaceholderParameters
|
||||||
@ -91,7 +93,7 @@ object UniqueTriggerActivation {
|
|||||||
tile: Tile? = city?.getCenterTile() ?: unit?.currentTile,
|
tile: Tile? = city?.getCenterTile() ?: unit?.currentTile,
|
||||||
notification: String? = null,
|
notification: String? = null,
|
||||||
triggerNotificationText: String? = null,
|
triggerNotificationText: String? = null,
|
||||||
ignoreMultiModifiers: Boolean = false
|
unitTriggerableIteration: Boolean = false
|
||||||
): (()->Boolean)? {
|
): (()->Boolean)? {
|
||||||
|
|
||||||
val relevantCity by lazy {
|
val relevantCity by lazy {
|
||||||
@ -121,25 +123,24 @@ object UniqueTriggerActivation {
|
|||||||
else Random(-550) // Very random indeed
|
else Random(-550) // Very random indeed
|
||||||
val ruleset = civInfo.gameInfo.ruleset
|
val ruleset = civInfo.gameInfo.ruleset
|
||||||
|
|
||||||
// Modifier trigger to iterate through multiple units
|
// Allow iterating through all unit targets, if needed.
|
||||||
if (unique.hasModifier(UniqueType.TargetingUnitsWithinTiles) && !ignoreMultiModifiers) {
|
if (unique.type?.targetTypes?.contains(UniqueTarget.UnitTriggerable) == true && !unitTriggerableIteration && tile != null
|
||||||
val modifiers = unique.getModifiers(UniqueType.TargetingUnitsWithinTiles)
|
!UniqueParameterType.UnitTriggerTarget.staticKnownValues.contains(unique.params[0])) {
|
||||||
if (tile != null) {
|
// Every adjacent [mapUnitFilter] unit
|
||||||
val triggerFunctions = modifiers.flatMap {
|
val triggerFunctions = tile.getTilesInDistance(1) // Adjacent
|
||||||
val mapUnitFilter = it.params[0]
|
.flatMap { it.getUnits() }
|
||||||
tile.getTilesInDistance(it.params[1].toInt())
|
.filter {
|
||||||
.flatMap { it.getUnits() }
|
val mapUnitFilter = unique.params[0]?.getPlaceholderParameters()?.firstOrNull()
|
||||||
.filter { it.matchesFilter(mapUnitFilter) }
|
if (mapUnitFilter != null) it.matchesFilter(filterParam, gameContext) else false
|
||||||
.mapNotNull { getTriggerFunction(unique, civInfo, city, it, it.getTile(), notification, triggerNotificationText, true) }
|
|
||||||
}
|
}
|
||||||
if (triggerFunctions.none()) return null
|
.mapNotNull { getTriggerFunction(unique, civInfo, city, it, it.getTile(), notification, triggerNotificationText, true) }
|
||||||
return {
|
if (triggerFunctions.none()) return null
|
||||||
for (triggerFunction in triggerFunctions) {
|
return {
|
||||||
triggerFunction.invoke()
|
for (triggerFunction in triggerFunctions) {
|
||||||
}
|
triggerFunction.invoke()
|
||||||
true
|
|
||||||
}
|
}
|
||||||
} else return null
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when (unique.type) {
|
when (unique.type) {
|
||||||
|
@ -959,9 +959,6 @@ enum class UniqueType(
|
|||||||
|
|
||||||
///////////////////////////////////////////// region 90 META /////////////////////////////////////////////
|
///////////////////////////////////////////// region 90 META /////////////////////////////////////////////
|
||||||
|
|
||||||
TargetingUnitsWithinTiles("targeting [mapUnitFilter] units within [positiveAmount] tiles", UniqueTarget.MetaModifier,
|
|
||||||
docDescription = "Modifies this unique to activate on each of the given units within the certain amount of tiles"),
|
|
||||||
|
|
||||||
ConditionalTimedUnique("for [nonNegativeAmount] turns", UniqueTarget.MetaModifier,
|
ConditionalTimedUnique("for [nonNegativeAmount] turns", UniqueTarget.MetaModifier,
|
||||||
docDescription = "Turns this unique into a trigger, activating this unique as a *global* unique for a number of turns"),
|
docDescription = "Turns this unique into a trigger, activating this unique as a *global* unique for a number of turns"),
|
||||||
|
|
||||||
|
@ -3874,13 +3874,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
|||||||
|
|
||||||
Modifiers that can be added to other uniques changing user experience, not their behavior
|
Modifiers that can be added to other uniques changing user experience, not their behavior
|
||||||
|
|
||||||
??? example "<targeting [mapUnitFilter] units within [positiveAmount] tiles>"
|
|
||||||
Modifies this unique to activate on each of the given units within the certain amount of tiles
|
|
||||||
|
|
||||||
Example: "<targeting [Wounded] units within [3] tiles>"
|
|
||||||
|
|
||||||
Applicable to: MetaModifier
|
|
||||||
|
|
||||||
??? example "<for [nonNegativeAmount] turns>"
|
??? example "<for [nonNegativeAmount] turns>"
|
||||||
Turns this unique into a trigger, activating this unique as a *global* unique for a number of turns
|
Turns this unique into a trigger, activating this unique as a *global* unique for a number of turns
|
||||||
|
|
||||||
@ -3971,7 +3964,7 @@ There is a conversion affecting dashes and leading/trailing blanks. Please make
|
|||||||
*[tech]: The name of any tech.
|
*[tech]: The name of any tech.
|
||||||
*[terrainFeature]: The name of any terrain that is a terrain feature according to the json file.
|
*[terrainFeature]: The name of any terrain that is a terrain feature according to the json file.
|
||||||
*[tileFilter]: Anything that can be used either in an improvementFilter or in a terrainFilter can be used here, plus 'unimproved'
|
*[tileFilter]: Anything that can be used either in an improvementFilter or in a terrainFilter can be used here, plus 'unimproved'
|
||||||
*[unitTriggerTarget]: `This Unit` or `Target Unit`.
|
*[unitTriggerTarget]: `This Unit`, `Target Unit`, or `Every adjacent [mapUnitFilter] unit`.
|
||||||
*[unitType]: Can be 'Land', 'Water', 'Air', any unit type, a filtering Unique on a unit type, or a multi-filter of these.
|
*[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.
|
*[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: 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time' or one of your mod's VictoryTypes.json names.
|
*[victoryType]: The name of any victory type: 'Cultural', 'Diplomatic', 'Domination', 'Scientific', 'Time' or one of your mod's VictoryTypes.json names.
|
Loading…
x
Reference in New Issue
Block a user