SnapshotCaptureFormulaInputResolver.kt
package io.github.lishangbu.avalon.game.battle.engine.core.capture
import io.github.lishangbu.avalon.game.battle.engine.core.capture.CaptureContext
import io.github.lishangbu.avalon.game.battle.engine.core.capture.CaptureFormulaInput
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionCaptureAction
import io.github.lishangbu.avalon.game.battle.engine.spi.capture.CaptureFormulaInputResolver
/**
* 基于当前 battle snapshot 直接组装捕捉公式输入的默认 resolver。
*
* 设计意图:
* - 让 battle-engine 在不额外依赖业务仓储的前提下,直接使用当前会话快照里的结构化单位元数据;
* - 把 `hp / status / type / metadata.captureRate / metadata.captureContext` 这一组输入统一收口;
* - 作为引擎内置的正式默认实现,替代测试和装配中到处回退到 `UnsupportedCaptureActionResolver` 的状态。
*
* 当前约定:
* - `ballItemInternalName` 直接沿用 capture action 传入的 `ballItemId`;
* - `alreadyCaught` 暂时仍由业务层扩展 resolver 覆盖,内置实现默认 `false`;
* - 若目标单位缺失、或没有 `captureRate`,会立即抛出清晰错误,避免静默使用错误默认值。
*/
class SnapshotCaptureFormulaInputResolver : CaptureFormulaInputResolver {
override fun resolve(
sessionId: String,
snapshot: BattleRuntimeSnapshot,
action: BattleSessionCaptureAction,
): CaptureFormulaInput {
val targetUnit =
requireNotNull(snapshot.units[action.targetId]) {
"Capture target '${action.targetId}' was not found in battle '$sessionId'."
}
val captureRate =
requireNotNull(targetUnit.metadata.captureRate) {
"Capture target '${action.targetId}' is missing metadata.captureRate in battle '$sessionId'."
}
val captureContext = targetUnit.metadata.captureContext
return CaptureFormulaInput(
currentHp = targetUnit.currentHp,
maxHp = targetUnit.maxHp,
captureRate = captureRate,
statusState = targetUnit.statusState,
ballItemInternalName = action.ballItemId,
turn = snapshot.battle.turn,
battleContext =
CaptureContext(
alreadyCaught = false,
isFishingEncounter = captureContext.isFishingEncounter,
isSurfEncounter = captureContext.isSurfEncounter,
isNight = captureContext.isNight,
isCave = captureContext.isCave,
isUltraBeast = captureContext.isUltraBeast,
targetLevel = targetUnit.metadata.level,
targetWeight = captureContext.targetWeight ?: targetUnit.metadata.weight,
targetTypes = targetUnit.typeIds,
),
)
}
}