战斗状态机
每个战斗阶段、阶段内部的精确执行顺序,以及什么时候可以合法出牌。
UI 按钮在错误时机被启用、回合效果的执行顺序不符合预期、战斗没有结束时,用这一页检查阶段状态。战斗状态机拥有阶段转换。玩家什么时候能行动、敌人什么时候行动、延迟触发什么时候 tick、奖励选择什么时候阻塞战斗完成,都由它决定。在 Game Card Monitor 的 Phase 页签里可以实时看到每一次转换。

阶段列表
GCSApi.Phase 返回当前的 BattlePhase。没有活动战斗时返回 BattlePhase.None。
| 阶段 | 发生什么 | 玩家输入 |
|---|---|---|
| None | 没有活动战斗。 | 不能出牌。 |
| Initialize | 正在构建战斗状态。 | 不能出牌。 |
| PlayerTurnStart | 护甲衰减、能量补充、抽牌阶段、回合开始的状态/卡牌时机。 | 进入 PlayerPhase 前不能出牌。 |
| PlayerPhase | 玩家可以打出手牌并结束回合。 | 卡牌费用可支付且可打出时允许出牌。 |
| PlayerTurnEnd | 弃牌阶段、回合结束状态时机、状态衰减、hook ticking、延迟触发。 | 不能出牌。 |
| EnemyPhase | 每个存活敌人依次结算回合开始状态、行为、回合结束状态和间隔。 | 不能出牌。 |
| BattleWon | 战斗胜利,可能提供奖励。 | 可能需要选择奖励。 |
| BattleLost | 战斗失败。 | 不能出牌。 |
核心循环在四个阶段之间流转;胜负出口由阶段机制在回合转换和出牌之后评估:
战斗启动流程
GCSApi.StartBattle(encounter) 会委托给 manager 和状态机:
- 创建新的
BattleStateView。 - 从遭遇战玩家单位构建玩家状态。
- 从遭遇战敌人构建敌人状态。
- 从 run master deck 或玩家初始卡组构建初始抽牌堆。
- 洗抽牌堆。
- 优先把 Innate 卡放入开局手牌。
- 绑定可选的 GES event bridge。
- 抽起始手牌。
- 触发(Raise)
OnBattleStarted。 - 解析敌人意图。
- 运行 battle-start 状态行为。
- 进入
PlayerTurnStart。
如果 encounter 为 null,状态机会记录错误并且不启动战斗。
玩家回合开始
在 PlayerTurnStart 中,GCS 会:
- 把战斗标记为玩家所有。
- 对玩家应用护甲衰减。
- 解析最大能量并设置当前能量。
- Tick 安排在
PlayerTurnStart的延迟触发。 - 清空
PlayedThisTurn。 - 运行玩家状态的
OnTurnStart。 - 运行手牌卡牌的回合开始时机。
- 从第二回合起,触发
OnDrawPhase,运行 draw-phase 行为,并抽每回合应抽的牌。 - 重置每回合攻击标记。
- 触发
OnTurnStarted。 - 如果玩家有待跳过回合,直接跳到玩家回合结束。
- 进入
PlayerPhase。
护甲衰减遵循遭遇战的 BattleRules.ArmorDecayRule。默认的 ResetOnTurnStart 在单位每个回合开始时重置护甲,Armor Reset Hook 可以改写重置值;Persist 则让护甲原样跨回合保留。
第一回合的起始手牌在战斗启动期间抽取,发生在 PlayerTurnStart 之前。第 1 回合没有单独的抽牌阶段。
玩家行动阶段
TryPlayCard 只在 PlayerPhase 中可能成功。
以下情况会让一次出牌尝试失败:
- 当前阶段不是
PlayerPhase。 - 卡牌为 null。
- 玩家单位缺失。
- 卡牌当前不在手牌中。
- 卡牌没有 active card definition。
- 玩家付不起有效能量费用。
- On-play hook 取消了这次打出。
- 卡牌带有
Unplayablekeyword。 - Card playable hook 取消或返回 false。
出牌成功时,GCS 会:
- 消耗能量。
- 把卡牌加入
PlayedThisTurn。 - 解析目标;未提供目标时回退到第一个存活敌人。
- 触发
OnCardPlayed。 - 运行卡牌的 on-play FlowGraph。
- 注册卡牌 hooks。
- 把卡牌从手牌移到弃牌堆或消耗(exhaust)堆。
- 检查待处理的胜负转换。
- 如果某个效果请求了结束回合,则结束玩家回合。
启用卡牌按钮前先调用 GCSApi.CanPlayCard(card)。判断 UI 是否需要让玩家选目标时,把卡牌定义传给 GCSApi.RequiresTarget(GCSApi.GetActiveCard(instance))。
玩家回合结束
在 PlayerPhase 中调用 GCSApi.EndPlayerTurn() 后,状态机进入 PlayerTurnEnd:
- 触发
OnDiscardPhase。 - 运行 discard-phase 状态行为。
- 把普通手牌移到弃牌堆,保留带
Retain的卡牌,带Ethereal的卡牌移入消耗堆。 - 运行玩家状态的
OnTurnEnd。 - Tick 每回合状态。
- Tick active hooks。
- Tick 卡牌费用规则。
- Tick 安排在
PlayerTurnEnd的延迟触发。 - 触发
OnTurnEnded。 - 如果有待处理的额外回合,进入
PlayerTurnStart。 - 否则进入
EnemyPhase。
敌人阶段
在 EnemyPhase 中,GCS 会:
- 把战斗标记为不再由玩家所有。
- 触发
OnEnemyTurnStarted。 - 按顺序遍历存活敌人。
- 对当前行动的敌人应用护甲衰减。
- 运行敌人回合开始状态。
- 若未被跳过,结算敌人行为。
- 运行敌人回合结束状态。
- Tick 每回合状态和 hooks。
- 在可见的敌人行动之间等待。
- Tick 安排在
EnemyPhaseEnd的延迟触发。 - 为下一个玩家回合解析所有敌人意图。
- 递增
TurnNumber。 - 进入
PlayerTurnStart。
Demo 表现层可以给敌人加攻击前冲和间隔,但阶段逻辑始终归状态机所有。
选择与奖励等待
有些图节点和战斗结果会有意暂停推进。
| 等待状态 | API 指示器 | 含义 |
|---|---|---|
| Effect choice | GCSApi.IsWaitingForChoice | 一个 Choice 节点正在等玩家选择或跳过。 |
| Battle reward | GCSApi.IsWaitingForReward | 胜利的战斗已提供奖励,正在等 ApplyReward 或 SkipReward。 |
等待期间,排队的转换不会继续。自定义 UI 应禁用无关控件并显示对应的选择器。
战斗结束
战斗胜利时:
- 运行 battle-end 状态行为。
- 掷出奖励候选。
- 触发
OnBattleRewardOffered。 - 状态机等待奖励选择或跳过。
- 触发
OnBattleRewardSelected或OnBattleRewardSkipped。 - 触发
OnBattleEnded,Won = true。
战斗失败时:
- 运行 battle-end 状态行为。
- 触发
OnBattleEnded,Won = false。
GCSApi.IsBattleOver 在 BattleWon 或 BattleLost 中为 true。
安全的阶段检查
| 任务 | 检查 |
|---|---|
| 显示战斗 HUD | GCSApi.IsBattleActive |
| 启用卡牌按钮 | GCSApi.Phase == BattlePhase.PlayerPhase 且 GCSApi.CanPlayCard(card) |
| 显示结束回合按钮 | GCSApi.Phase == BattlePhase.PlayerPhase |
| 显示选择 UI | GCSApi.IsWaitingForChoice |
| 显示奖励 UI | GCSApi.IsWaitingForReward |
| 显示胜利/失败覆盖层 | GCSApi.IsBattleOver 加 OnBattleEnded payload |
不要从单个事件推断阶段。事件只是通知,当前阶段永远是权威状态。