mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-21 10:25:10 -04:00
Every adjacent [mapUnitFilter] unit
This commit is contained in:
parent
e0ef4acb3f
commit
0a69cd0a0e
@ -1663,7 +1663,7 @@
|
||||
"unitType": "Civilian Water",
|
||||
"uniques": [
|
||||
"[+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",
|
||||
"Is part of Great Person group [Admiral]",
|
||||
"Great Person - [War]", "Unbuildable", "Uncapturable"],
|
||||
|
@ -19,7 +19,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
|
||||
override fun isDefeated(): Boolean = unit.health <= 0
|
||||
override fun isInvisible(to: Civilization): Boolean = unit.isInvisible(to)
|
||||
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 {
|
||||
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] */
|
||||
@Readonly
|
||||
fun matchesFilter(filter: String, multiFilter: Boolean = true): Boolean {
|
||||
return if (multiFilter) MultiFilter.multiFilter(filter, ::matchesSingleFilter) else matchesSingleFilter(filter)
|
||||
}
|
||||
fun matchesFilter(filter: String, state: GameContext? = cache.state, multiFilter: Boolean = true): Boolean =
|
||||
if (multiFilter) MultiFilter.multiFilter(filter, { matchesSingleFilter(it, state) })
|
||||
else matchesSingleFilter(filter, state)
|
||||
|
||||
@Readonly
|
||||
private fun matchesSingleFilter(filter: String): Boolean {
|
||||
private fun matchesSingleFilter(filter: String, state: GameContext? = cache.state): Boolean {
|
||||
return when (filter) {
|
||||
Constants.wounded, "wounded units" -> health < 100
|
||||
Constants.barbarians, "Barbarian" -> civ.isBarbarian
|
||||
@ -620,9 +620,9 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
Constants.embarked -> isEmbarked()
|
||||
"Non-City" -> true
|
||||
else -> {
|
||||
if (baseUnit.matchesFilter(filter, cache.state, false)) return true
|
||||
if (civ.matchesFilter(filter, cache.state, false)) return true
|
||||
if (nonUnitUniquesMap.hasUnique(filter, cache.state)) return true
|
||||
if (baseUnit.matchesFilter(filter, state, false)) return true
|
||||
if (civ.matchesFilter(filter, state, false)) return true
|
||||
if (nonUnitUniquesMap.hasUnique(filter, if (state == null) cache.state else state)) return true
|
||||
if (promotions.promotions.contains(filter)) return true
|
||||
if (hasStatus(filter)) return true
|
||||
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.stats.Stat
|
||||
import com.unciv.models.stats.SubStat
|
||||
import com.unciv.models.translations.getPlaceholderParameters
|
||||
import com.unciv.models.translations.TranslationFileWriter
|
||||
import yairm210.purity.annotations.Pure
|
||||
import yairm210.purity.annotations.Readonly
|
||||
@ -86,7 +87,7 @@ enum class UniqueParameterType(
|
||||
|
||||
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
|
||||
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] */
|
||||
@ -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 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. */
|
||||
|
@ -29,8 +29,10 @@ import com.unciv.models.ruleset.BeliefType
|
||||
import com.unciv.models.ruleset.Event
|
||||
import com.unciv.models.ruleset.tile.TerrainType
|
||||
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.Stats
|
||||
import com.unciv.models.translations.getPlaceholderParameters
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.translations.fillPlaceholders
|
||||
import com.unciv.models.translations.hasPlaceholderParameters
|
||||
@ -91,7 +93,7 @@ object UniqueTriggerActivation {
|
||||
tile: Tile? = city?.getCenterTile() ?: unit?.currentTile,
|
||||
notification: String? = null,
|
||||
triggerNotificationText: String? = null,
|
||||
ignoreMultiModifiers: Boolean = false
|
||||
unitTriggerableIteration: Boolean = false
|
||||
): (()->Boolean)? {
|
||||
|
||||
val relevantCity by lazy {
|
||||
@ -121,25 +123,24 @@ object UniqueTriggerActivation {
|
||||
else Random(-550) // Very random indeed
|
||||
val ruleset = civInfo.gameInfo.ruleset
|
||||
|
||||
// Modifier trigger to iterate through multiple units
|
||||
if (unique.hasModifier(UniqueType.TargetingUnitsWithinTiles) && !ignoreMultiModifiers) {
|
||||
val modifiers = unique.getModifiers(UniqueType.TargetingUnitsWithinTiles)
|
||||
if (tile != null) {
|
||||
val triggerFunctions = modifiers.flatMap {
|
||||
val mapUnitFilter = it.params[0]
|
||||
tile.getTilesInDistance(it.params[1].toInt())
|
||||
.flatMap { it.getUnits() }
|
||||
.filter { it.matchesFilter(mapUnitFilter) }
|
||||
.mapNotNull { getTriggerFunction(unique, civInfo, city, it, it.getTile(), notification, triggerNotificationText, true) }
|
||||
// Allow iterating through all unit targets, if needed.
|
||||
if (unique.type?.targetTypes?.contains(UniqueTarget.UnitTriggerable) == true && !unitTriggerableIteration && tile != null
|
||||
!UniqueParameterType.UnitTriggerTarget.staticKnownValues.contains(unique.params[0])) {
|
||||
// Every adjacent [mapUnitFilter] unit
|
||||
val triggerFunctions = tile.getTilesInDistance(1) // Adjacent
|
||||
.flatMap { it.getUnits() }
|
||||
.filter {
|
||||
val mapUnitFilter = unique.params[0]?.getPlaceholderParameters()?.firstOrNull()
|
||||
if (mapUnitFilter != null) it.matchesFilter(filterParam, gameContext) else false
|
||||
}
|
||||
if (triggerFunctions.none()) return null
|
||||
return {
|
||||
for (triggerFunction in triggerFunctions) {
|
||||
triggerFunction.invoke()
|
||||
}
|
||||
true
|
||||
.mapNotNull { getTriggerFunction(unique, civInfo, city, it, it.getTile(), notification, triggerNotificationText, true) }
|
||||
if (triggerFunctions.none()) return null
|
||||
return {
|
||||
for (triggerFunction in triggerFunctions) {
|
||||
triggerFunction.invoke()
|
||||
}
|
||||
} else return null
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
when (unique.type) {
|
||||
|
@ -959,9 +959,6 @@ enum class UniqueType(
|
||||
|
||||
///////////////////////////////////////////// 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,
|
||||
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
|
||||
|
||||
??? 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>"
|
||||
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.
|
||||
*[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'
|
||||
*[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.
|
||||
*[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.
|
Loading…
x
Reference in New Issue
Block a user