核心概念
这一页讲架构——给"想先搞懂再配置"的你。读完你会明白:一次按键在 QS 内部到底经历了什么、状态机为什么存在、技能为什么有"两套字段"、QS 到底做什么不做什么。
🎯 运行管线:一次按键的 7 个阶段
QS 的核心是一条固定的运行管线。无论触发来自物品、命令、API 还是被动事件,都走这同一条路:
① 输入 玩家按键 / 命令 / API / 被动事件
│ 统一归一成标准触发信号
▼
② 状态机(State) 现在是什么状态?空闲?连招窗口?被封锁?
│ 决定这次输入能不能进、走哪条路
▼
③ 图解析(Graph)+连招 在当前状态下,这个键命中哪个节点?
│ (Combo) 是不是某段连招序列的一环?
▼
④ 执行计划(Plan) 拼出"放哪个 MM 技能、目标是谁、带哪些参数"
│
▼
⑤ 门控(Gate) 逐项检查:解锁?冷却?充能?GCD?资源?血祭?冲突?条件?
│ 任一不过 → 拦下并提示,管线在此中止
▼
⑥ 执行(Exec) MythicExecutor 把计划交给 MythicMobs 演出
│
▼
⑦ 后处理(Post) 进冷却 / 改状态 / 推进连招 / 刷 actionbar💡 为什么要"一条管线管所有触发"? 这样冷却、充能、连招、目标这些规则只写一遍,对"物品放""命令放""被动放"一视同仁。你永远不会遇到"命令能放但物品放不了"这种两套逻辑打架的问题。
记住这条管线的固定顺序——门控在执行之前。所以"明明 MM 技能写好了却放不出来",几乎总是卡在第 ⑤ 步门控(没解锁 / 在冷却 / 资源不够),而不是 MM 的问题。
🔄 状态机:6 个状态
QS 给每个玩家维护一个技能状态机。它存在的意义:让"连招""续段""被沉默"这类有时序的事变得可判定。
| 状态 | 中文 | 含义 |
|---|---|---|
IDLE | 空闲 | 默认态,可以正常起手放技能 |
CASTING | 施放中 | 技能正在放出 |
COMBO_WINDOW | 连招窗口 | 起手成功后短暂开窗,此窗内的输入算"续段" |
RECOVERY | 恢复 | 预留状态(后摇 / 硬直,暂未启用具体逻辑) |
LOCKED | 被封锁 | 被沉默(silence),放不出任何技能 |
INTERRUPTED | 中断 | 吟唱 / 施放被打断 |
状态什么时候转换
IDLE ──首次按键起手成功──► CASTING
CASTING ──成功且该技能有连招──► COMBO_WINDOW
COMBO_WINDOW ──超过 combo_window_ms(默认800) 没续上──► IDLE (连招断)
任意状态 ──/qs silence N──► LOCKED ──N 秒后──► IDLE
吟唱/施放被位移或受伤打断 ──► INTERRUPTED ──► IDLE要点:
- 起手 vs 续段靠状态区分。 同一个右键,在
IDLE走起手节点,在COMBO_WINDOW走续段节点(graph 节点用require_state标谁是谁)。这就是连招能成立的底层机制。 - 连招窗口会超时。
combo_window_ms(默认 800ms)内没按出下一段,状态回IDLE,连招断。 - 被沉默 =
LOCKED。/qs silence 5让玩家 5 秒内进LOCKED,所有技能放不出;/qs silence 0解除。这是技能封锁 / 沉默 debuff 的实现入口。
📑 技能的"两套字段":生态校验 vs 运行期读取
打开任何技能 yml,你会看到字段分成两半。这是 QS 的一个刻意设计,搞懂它能少踩大坑。
| 这套字段 | 作用 | 谁来读 |
|---|---|---|
meta / trigger / state / graph / execution | 生态信息 —— 分类归档、reload 时一致性校验、连招编排参照 | schema 校验器 |
type / cooldown / resource / cast_mode / levels / variables … | 运行期实际读取 —— 真正决定行为 | runtime loader |
举例对照(来自 fire_wave):
meta:
type: active # 生态标签:归类用
trigger:
primary: RIGHT_CLICK # 生态:声明主触发键(校验时比对 graph)
state:
required: IDLE # 生态:声明所需状态(校验时比对入口节点)
execution:
mythic_skill: fire_wave # 生态:声明执行哪个 MM 技能
type: active # ← 运行期真正决定主动/被动的是这一行
mythic_skill: fire_wave # ← 运行期实际用的(execution.mythic_skill 优先)⚠️ 两套必须保持一致。 比如
state.required: IDLE要和 graph 入口节点的require_state: IDLE一致;execution.mythic_skill要和入口节点的mythic_skill一致。/qs reload会做一致性校验,对不上会报 schema 警告。
为什么要分两套? 上半套让生态(校验器、连招编排、未来的编辑器 GUI)能在不跑技能的情况下读懂"这技能长什么样、归哪类、连不连招";下半套是引擎运行时真正吃的配置。一个供"理解",一个供"执行"。
🚪 门控(Gate):放行前的有序闸门
门控是管线第 ⑤ 步,也是 QS 最核心的价值之一。它是一串按固定顺序执行的检查,任一不过就拦下技能并给玩家提示:
| 闸门 | 检查什么 |
|---|---|
| 解锁 | 这个玩家解锁这技能了吗? |
| 冷却 / 冷却组 | 在 CD 里吗?同冷却组的技能是否共享了 CD? |
| 充能 | 充能层数还有吗(充能技能用层数替代二元冷却)? |
| 全局冷却 GCD | 刚放过别的技能、还在全局冷却里吗? |
| 资源 | mana 够吗(临时占位,将来归 QC)? |
| 生命 / 饥饿(血祭) | 扣血扣饿够吗?血量太低不让放? |
| 冲突组 | 短期内放过同冲突组的技能吗(gate.conflict_window_ms 默认 1000ms)? |
| 声明式条件 | conditions: 里的条件全满足吗? |
💡 门控是"判定层",不是"表现层"。 它只回答能不能放,从不画任何东西。所以技能放不出来时,先想门控(哪道闸没过),别一头扎进 MM 排查。各闸门详细配置见 冷却充能GCD与冲突、消耗条件与变量。
🌉 桥(Bridge):QS → MythicMobs
门控通过后,QS 要把执行计划交给 MM。这条交接缝叫桥(Bridge)。
桥模式(config.yml 的 mythic.bridge_mode) | 行为 |
|---|---|
AUTO(推荐 / 默认) | 优先用 MM API 注册技能 → 校验 → 失败则降级写 YAML 并 loadSkills() |
API_MODE | 只走 API,不降级(开发 / 测试用) |
YAML_STUB | 只写 MM 技能文件夹 + 走加载生命周期 |
关于桥,记住三件事:
- 没装 MM 也能跑。 桥进占位模式,触发技能 → 聊天栏
[QinhSkills] 技能名。看到它就证明 QS 这侧全通。 - 永不覆盖你的同名 MM 技能。 占位只在"你没写同名技能"时存在;你写了真技能,桥就用你的。
/qs bridge看桥状态,诊断 MM 是否在场、注册是否成功。
详见 对接 MythicMobs。
🧭 职责边界:QS 做什么 / 不做什么
最后把边界钉死,这是理解整个秦淮生态的关键。
QS 做: cast 逻辑 / 触发归一 / 目标索敌 / 门控(解锁·冷却·充能·冷却组·GCD·冲突·资源·血祭·条件·cast_mode·吟唱读条与打断)/ 把变量参数透传给 MM / JS 脚本出口(pre_js / post_js)。
QS 不做:
| 不做的事 | 归谁 |
|---|---|
| 粒子 / 位移 / 表现 / 机制本体 | MythicMobs |
| 伤害数值结算 | AttributePlus 等属性插件(在 MM 那侧) |
| 玩家职业 / 玩家等级 / 法力·耐力资源池 / 冷却缩减(CDR) / 玩家属性 | QinhClass(QC) |
🔑 关于 mana: 技能 yml 里的
resource.mana、config.yml里的resources.default_mana/max_mana都是 QC 接管前的临时占位。资源扣费走的是 QS 既有的玩家档案缝(PlayerSkillProfile),不另造池子;将来 QC 接管资源时只改这一处,技能 yml 不用动。
这条边界和 QS 第一条设计哲学一脉相承:QS 只管逻辑,不管表现、不管数值、不管玩家成长。 各司其职,谁的活谁干。
继续阅读
- 把技能接到物品 / 命令 / API → 对接总览
- 为什么要在物品和 MM 之间插一层 QS → 对接 MythicMobs
- 动手写技能 YAML(全字段) → 技能文件结构 · 技能定义全字段
- 服主运营向 → 服主指南