ClearBoostsBattleMutationInterceptor.kt

package io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow

import io.github.lishangbu.avalon.game.battle.engine.core.event.StandardHookNames
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.BattleMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ClearBoostsMutation
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.support.BattleBoostContextSupport
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.support.BattleStatStageSupport
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.support.MutationTargetSelectorResolver

/**
 * boost 清空 mutation 的生命周期拦截器。
 *
 * 设计意图:
 * - 在 `ClearBoostsMutation` 真正清空前派发 `on_clear_boosts`;
 * - 让目标可以拒绝被清能力阶级;
 * - 把清空前的 boosts 快照通过 attributes 透传给 hook,便于规则做精确判断。
 */
class ClearBoostsBattleMutationInterceptor : BattleMutationInterceptor {
    override val order: Int = 450

    override fun supports(mutation: BattleMutation): Boolean = mutation is ClearBoostsMutation

    override fun intercept(
        context: BattleMutationInterceptionContext,
        attachedEffectProcessor: BattleAttachedEffectProcessor,
    ): BattleMutationInterceptionResult {
        val mutation =
            context.mutation as? ClearBoostsMutation
                ?: return BattleMutationInterceptionResult(context.snapshot, true, context.mutation)
        val targetUnitIds =
            MutationTargetSelectorResolver.resolve(
                mutation.target,
                BattleMutationInterceptorSupport.mutationApplicationContext(context),
            )
        var currentSnapshot = context.snapshot
        var blocked = false

        targetUnitIds.forEach { affectedTargetId ->
            val affectedUnit = currentSnapshot.units[affectedTargetId] ?: return@forEach
            val currentBoosts = BattleStatStageSupport.normalizeStoredBoosts(affectedUnit.boosts)
            val boostChanged = currentBoosts.isNotEmpty()
            val result =
                attachedEffectProcessor.process(
                    snapshot = currentSnapshot,
                    unitId = affectedTargetId,
                    hookName = StandardHookNames.ON_CLEAR_BOOSTS.value,
                    targetId = affectedTargetId,
                    sourceId = context.sourceId,
                    relay = true,
                    attributes =
                        BattleBoostContextSupport.createOnClearBoostsAttributes(
                            currentBoosts = currentBoosts,
                            targetRelation =
                                BattleMutationInterceptorSupport.resolveTargetRelation(
                                    currentSnapshot,
                                    context.sourceId,
                                    affectedTargetId,
                                ),
                        ),
                )
            currentSnapshot = result.snapshot
            if (boostChanged && (result.cancelled || result.relay == false)) {
                blocked = true
            }
        }

        return BattleMutationInterceptionResult(
            snapshot = currentSnapshot,
            allowed = !blocked,
            mutation = mutation,
        )
    }
}