跳到主要内容

战斗状态机

GCS · Runtime

每个战斗阶段、阶段内部的精确执行顺序,以及什么时候可以合法出牌。

UI 按钮在错误时机被启用、回合效果的执行顺序不符合预期、战斗没有结束时,用这一页检查阶段状态。

战斗状态机拥有阶段转换。玩家什么时候能行动、敌人什么时候行动、延迟触发什么时候 tick、奖励选择什么时候阻塞战斗完成,都由它决定。在 Game Card Monitor 的 Phase 页签里可以实时看到每一次转换。

Game Card Monitor 的 Phase 页签,Play Mode 下显示当前战斗阶段与转换历史

阶段列表

GCSApi.Phase 返回当前的 BattlePhase。没有活动战斗时返回 BattlePhase.None

阶段发生什么玩家输入
None没有活动战斗。不能出牌。
Initialize正在构建战斗状态。不能出牌。
PlayerTurnStart护甲衰减、能量补充、抽牌阶段、回合开始的状态/卡牌时机。进入 PlayerPhase 前不能出牌。
PlayerPhase玩家可以打出手牌并结束回合。卡牌费用可支付且可打出时允许出牌。
PlayerTurnEnd弃牌阶段、回合结束状态时机、状态衰减、hook ticking、延迟触发。不能出牌。
EnemyPhase每个存活敌人依次结算回合开始状态、行为、回合结束状态和间隔。不能出牌。
BattleWon战斗胜利,可能提供奖励。可能需要选择奖励。
BattleLost战斗失败。不能出牌。

核心循环在四个阶段之间流转;胜负出口由阶段机制在回合转换和出牌之后评估:


战斗启动流程

GCSApi.StartBattle(encounter) 会委托给 manager 和状态机:

  1. 创建新的 BattleStateView
  2. 从遭遇战玩家单位构建玩家状态。
  3. 从遭遇战敌人构建敌人状态。
  4. 从 run master deck 或玩家初始卡组构建初始抽牌堆。
  5. 洗抽牌堆。
  6. 优先把 Innate 卡放入开局手牌。
  7. 绑定可选的 GES event bridge。
  8. 抽起始手牌。
  9. 触发(Raise) OnBattleStarted
  10. 解析敌人意图。
  11. 运行 battle-start 状态行为。
  12. 进入 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 取消了这次打出。
  • 卡牌带有 Unplayable keyword。
  • Card playable hook 取消或返回 false。

出牌成功时,GCS 会:

  1. 消耗能量。
  2. 把卡牌加入 PlayedThisTurn
  3. 解析目标;未提供目标时回退到第一个存活敌人。
  4. 触发 OnCardPlayed
  5. 运行卡牌的 on-play FlowGraph。
  6. 注册卡牌 hooks。
  7. 把卡牌从手牌移到弃牌堆或消耗(exhaust)堆。
  8. 检查待处理的胜负转换。
  9. 如果某个效果请求了结束回合,则结束玩家回合。
提示

启用卡牌按钮前先调用 GCSApi.CanPlayCard(card)。判断 UI 是否需要让玩家选目标时,把卡牌定义传给 GCSApi.RequiresTarget(GCSApi.GetActiveCard(instance))


玩家回合结束

PlayerPhase 中调用 GCSApi.EndPlayerTurn() 后,状态机进入 PlayerTurnEnd

  1. 触发 OnDiscardPhase
  2. 运行 discard-phase 状态行为。
  3. 把普通手牌移到弃牌堆,保留带 Retain 的卡牌,带 Ethereal 的卡牌移入消耗堆。
  4. 运行玩家状态的 OnTurnEnd
  5. Tick 每回合状态。
  6. Tick active hooks。
  7. Tick 卡牌费用规则。
  8. Tick 安排在 PlayerTurnEnd 的延迟触发。
  9. 触发 OnTurnEnded
  10. 如果有待处理的额外回合,进入 PlayerTurnStart
  11. 否则进入 EnemyPhase

敌人阶段

EnemyPhase 中,GCS 会:

  • 把战斗标记为不再由玩家所有。
  • 触发 OnEnemyTurnStarted
  • 按顺序遍历存活敌人。
  • 对当前行动的敌人应用护甲衰减。
  • 运行敌人回合开始状态。
  • 若未被跳过,结算敌人行为。
  • 运行敌人回合结束状态。
  • Tick 每回合状态和 hooks。
  • 在可见的敌人行动之间等待。
  • Tick 安排在 EnemyPhaseEnd 的延迟触发。
  • 为下一个玩家回合解析所有敌人意图。
  • 递增 TurnNumber
  • 进入 PlayerTurnStart

Demo 表现层可以给敌人加攻击前冲和间隔,但阶段逻辑始终归状态机所有。


选择与奖励等待

有些图节点和战斗结果会有意暂停推进。

等待状态API 指示器含义
Effect choiceGCSApi.IsWaitingForChoice一个 Choice 节点正在等玩家选择或跳过。
Battle rewardGCSApi.IsWaitingForReward胜利的战斗已提供奖励,正在等 ApplyRewardSkipReward

等待期间,排队的转换不会继续。自定义 UI 应禁用无关控件并显示对应的选择器。


战斗结束

战斗胜利时:

  1. 运行 battle-end 状态行为。
  2. 掷出奖励候选。
  3. 触发 OnBattleRewardOffered
  4. 状态机等待奖励选择或跳过。
  5. 触发 OnBattleRewardSelectedOnBattleRewardSkipped
  6. 触发 OnBattleEndedWon = true

战斗失败时:

  1. 运行 battle-end 状态行为。
  2. 触发 OnBattleEndedWon = false

GCSApi.IsBattleOverBattleWonBattleLost 中为 true。


安全的阶段检查

任务检查
显示战斗 HUDGCSApi.IsBattleActive
启用卡牌按钮GCSApi.Phase == BattlePhase.PlayerPhaseGCSApi.CanPlayCard(card)
显示结束回合按钮GCSApi.Phase == BattlePhase.PlayerPhase
显示选择 UIGCSApi.IsWaitingForChoice
显示奖励 UIGCSApi.IsWaitingForReward
显示胜利/失败覆盖层GCSApi.IsBattleOverOnBattleEnded payload

不要从单个事件推断阶段。事件只是通知,当前阶段永远是权威状态。