AttachedEffectDurationResolver.kt
package io.github.lishangbu.avalon.game.battle.engine.core.runtime.action
import io.github.lishangbu.avalon.game.battle.engine.core.dsl.EffectDefinition
import io.github.lishangbu.avalon.game.battle.engine.core.event.EventContext
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.support.BattleHeldItemRuntimeSupport
/**
* 附着效果持续回合解析器。
*
* 设计意图:
* - 优先尊重动作节点显式声明的 `duration`;
* - 当动作未显式声明时,再尝试从目标 effect 定义的 `data` 中读取默认持续回合;
* - 支持最小一档的“持有特定道具时延长持续回合”语义,避免把 5/8 之类常量继续散落在 move fixture 中。
*
* 当前约定的数据字段:
* - `defaultDuration`: 默认持续回合
* - `durationExtensionItemId`: 可延长该效果的道具 id
* - `extendedDuration`: 持有延长道具时的持续回合
*/
object AttachedEffectDurationResolver {
fun resolve(
explicitDuration: Int?,
effectId: String,
context: EventContext,
): Int? {
if (explicitDuration != null) {
return explicitDuration
}
val effectDefinition = context.effectLookup?.invoke(effectId) ?: return null
return resolveFromEffectDefinition(effectDefinition, context)
}
private fun resolveFromEffectDefinition(
effectDefinition: EffectDefinition,
context: EventContext,
): Int? {
val defaultDuration = (effectDefinition.data["defaultDuration"] as? Number)?.toInt() ?: return null
val extensionItemId = effectDefinition.data["durationExtensionItemId"]?.toString()
val extendedDuration = (effectDefinition.data["extendedDuration"] as? Number)?.toInt()
val field = context.field
val holderItemId =
if (field == null) {
context.source?.itemId ?: context.self?.itemId
} else {
BattleHeldItemRuntimeSupport.activeItemId(context.source, field)
?: BattleHeldItemRuntimeSupport.activeItemId(context.self, field)
}
return if (extensionItemId != null && extendedDuration != null && holderItemId == extensionItemId) {
extendedDuration
} else {
defaultDuration
}
}
}