跳到主要内容

状态生命周期

Guide

从施加第一层到主动移除或自然过期,理解状态层数、行为入口、Hook 与事件的完整运行过程

状态进入单位后会形成独立的实时层数,并在施加、修改、回合衰减、主动移除或自然过期时触发对应 Behavior 与事件,Game Card Monitor 的 Unit 标签页可以直接核对每个单位此刻持有的状态

Game Card Monitor 的 Unit 页签,显示玩家和敌方单位的 HP、护甲与当前状态层数

上图把玩家与敌人的 HP、护甲和状态层数放在同一份运行快照中,状态定义决定叠加与衰减规则,单位状态则记录当前层数和施加者,两者不能混为同一层数据

状态定义与实时层数​

GameStatus 是创作定义,保存名称、图标、叠层方式、层数上限、衰减规则与 Behavior,战斗中,每个 UnitState 独立记录自己持有的状态、当前层数和已知施加者

修改某个单位的状态不会影响其他单位,也不会回写 GameStatus 资产,字段配置和完整创作流程见状态创作

需求API
读取当前层数GCSApi.GetStatusStacks(unit, status)
检查是否至少有 N 层GCSApi.HasStatus(unit, status, minStacks)
读取最近一次成功施加者GCSApi.GetStatusApplier(unit, status)
读取单位的全部状态GCSApi.StatusesOn(unit)

单位为 null 或没有状态时,这些方法会返回 0、false、null 或空映射,不需要调用方额外创建占位集合

施加状态​

使用 GCSApi.ApplyStatus(target, status, stacks, source) 或 FlowGraph 的 Change Status 节点施加正数层数,运行时按以下顺序处理:

  1. 检查目标、状态和传入层数
  2. 让来源单位的 OnInflictStatus Hook 修改或取消层数
  3. 让目标单位的 OnReceiveStatus Hook 继续修改或取消层数
  4. 按 Additive、Max 或 Replace 与现有层数合并
  5. MaxStacks > 0 时限制最终层数;0 和负数均不限制,其中 0 会触发编辑器警告
  6. 层数发生变化时保存结果与最近一次施加者,并发布状态变化事件
  7. 仅在最终层数实际变化后执行施加方与接收方的状态 Behavior 入口
提示

source 为空时,运行时把状态持有者记录为施加者;后续每次让已存储层数发生变化的成功施加都会用本次来源或持有者替换记录,Max 规则或 MaxStacks 上限造成的无变化结果、ModifyStatusStacks 与 RemoveStatus 都不会改写它;无变化结果也不会发布虚假的 OnStatusInflicted,或执行 On Inflicted、On Received 与 On Stacks Changed Entry

修改、移除与重新触发​

任务推荐入口
增加状态层数ApplyStatus() 或 Change Status 的正数 Delta
减少指定层数RemoveStatus() 或 Change Status 的负数 Delta
把层数调整到目标值ModifyStatusStacks() 或 Change Status 的 Set 模式
不改层数,重新执行状态行为Reapply Status 或 Controller 的 RetriggerStatus
提示
  • 状态不存在时,Set 到正数会执行完整施加流程,包括 Hook、叠层规则、施加者记录、事件与 OnApplied;已有状态使用 Set 时只精确调整层数,不会重复施加流程或 OnApplied
  • 主动把层数降至 0 会进入 Removed 生命周期,PerTurn 自然衰减到 0 会进入 Expired 生命周期,两者可以播放不同表现或触发不同规则

生命周期入口与 Hook​

状态 Behavior 包含两类入口

类型执行时机典型用途
生命周期 Entry某项变化已经发生后状态被施加、回合开始、回合结束、状态移除
Hook数值提交之前修改伤害、费用、抽牌数、护甲或状态层数
提示
  • 生命周期 Entry 使用普通 Action 节点完成后续效果,Hook 必须用 Write Hook 提交修改后的值
  • 在没有写回时,运行时继续使用原值
  • Status 与 Card 注册的 Hook 会按同一 Priority 排序,数字越小越先执行,同值保持注册顺序
  • Card Hook 使用 Scope = Turns 时按未来玩家回合开始计时,不会在中间的敌方阶段提前消失,例如 Aegis 的 Turns = 1 会覆盖随后的敌方阶段,并在下一个玩家回合开始时到期
  • Hook 控制必须同步完成,直接或经嵌套操作触达的 Wait、Choice 与 Delayed Trigger 都不能提供延迟返回的 Hook 结果

状态入口和 Hook 的可用范围见Entry 节点与Hook 节点

Status Behavior 中,Host 是状态持有者,Source 是最近一次成功施加者,未知时回退到持有者,Attacker 则保留伤害或反应上下文提供的实际攻击者;三者彼此独立,因此持有者可以响应当前攻击者,同时继续读取该状态记录的来源

回合时机与自动衰减​

上图展示了 PerTurn 状态的默认生命周期,玩家状态在玩家回合结束时衰减,敌人状态则在该敌人的行动和回合结束行为完成后衰减

时机状态可能执行的内容
Battle Start战斗开始行为
Player Turn Start玩家状态的回合开始行为
Draw / Discard抽牌或弃牌阶段行为
Player Turn End玩家状态的回合结束行为、Tick 与衰减
Enemy Turn当前敌人的回合开始、行动、回合结束、Tick 与衰减
Battle End所有单位的战斗结束行为

精确阶段顺序见战斗生命周期

同一持有者的多个状态收到相同时机时,GCS 按捕获的状态顺序执行;其中一个分支进入 Wait 或 Choice 后,后续状态分支会等它完成,捕获序列全部排空后才发出一次时机完成通知

状态变化事件​

事件适用场景
OnStatusChanged层数变化后重建状态列表
OnStatusTicked播放一次状态结算造成的 HP 或层数变化
OnStatusInflicted响应一次成功施加
OnStatusExpired播放自然到期反馈
OnStatusRemoved播放净化或主动移除反馈
提示
  • OnStatusChanged 是状态 UI 的主要刷新信号,Transition 事件适合动画、音效、统计或其他一次性处理,不应替代当前状态查询
  • 公共 OnDamageDealt、OnDamageTaken 事件与对应伤害 Entry 的 Amount 都是目标实际损失的 HP,已经经过 Hook、护甲与剩余 HP 边界处理,适合用于飘字、战斗日志和伤害后规则
  • 状态层数或 Card 注册的活动 Hook 发生变化时,GCS 会立即重新解析敌人公开意图并发布 OnEnemyUnitIntentChanged,意图 UI 应响应事件后读取新的 PendingIntents

状态 UI 的刷新方式​

状态 Widget 收到 OnStatusChanged 后,应使用 GCSApi.StatusesOn(unit) 重新读取该单位的完整状态映射,再根据 Icon、DisplayName、IsDebuff、ShowStackCount 和当前层数更新界面

提示

不要只修改本地缓存中的一项层数,一次 FlowGraph 可能同时改变多个状态,事件参数只说明哪项变化触发了通知

完整 UI 示例见自定义 UI 接入,事件参数见事件参考

常见错误​

错误正确做法
直接编辑 UnitState.Statuses使用状态 API、Controller 或 FlowGraph 节点
用生命周期 Entry 修改尚未提交的数值使用对应 Hook
期待已有状态的 Set 再次触发 OnApplied使用正数 Delta 或 ApplyStatus 表达重新施加
把 Removed 和 Expired 当作同一事件根据主动移除和自然到期分别处理
仅使用事件参数维护本地状态列表事件后重新读取 StatusesOn(unit)