SkillBase 技能「效果」字段配置指南
面向新策划的入门手册,帮助你读懂
SkillBase表中「效果」这一列在配什么, 以及这些效果最终如何作用到角色、如何显示在客户端。适用对象:技能策划、数值策划 关联文件:
tbl/SkillBase.xml、tbl/SkillBase.tbl2、ScenesServer/SkillStatusManager.cpp、base/Command.h
一、效果字段是什么?
SkillBase(技能基础表)的第 21 个字段名为「效果」,是一行技能全部效果的浓缩文本。
它不像「技能ID」「技能等级」那样是一个简单数字,而是一串用符号分隔的嵌套文本, 由服务端在启动时解析为「状态组(SkillStatus)× 效果元素(SkillElement)」两个层级。
核心模型:
一个技能 = 若干「状态组」 (每组描述一种攻击/施加方式)
一个状态组 = 若干「效果元素」 (每个元素描述一条具体的数值/状态效果)
直观理解:一个技能可以“先给自身加 buff,再对敌人造成物理伤害”, 这就是两个状态组;其中“给自身加物攻 +458”就是一组里的一个效果元素。
二、四级分隔符:. : ; -
效果文本用 4 种符号分隔,按层级从外到内:
| 分隔符 | 作用 | 层级 |
|---|---|---|
. | 分隔多个状态组(SkillStatus) | 第 1 层(外层) |
: | 状态组内,分隔「状态定义 | 效果元素列表」 | 第 2 层 |
; | 分隔组内多个效果元素(SkillElement) | 第 3 层 |
- | 分隔状态 / 元素内部的各数值字段 | 第 4 层(最内层) |
结构示意:
[状态定义]-[状态定义]...:[元素]-[元素]-[元素];[元素]-[元素]-[元素];.下一组...
│ └── 7 个 `-` 分隔的字段(SkillStatus) │ └── 5 个 `-` 分隔的字段(SkillElement)
└──────────────┬──────────────────────────┘
`:` 分隔状态与元素列表
└──────────────────────┬──────────────────────┘
`.` 分隔多个状态组
规则要点:
- 每组以
:分隔出「状态定义」和「元素列表」两部分,元素列表可能为空。 - 每个元素以
;分隔;元素内字段以-分隔。 - 末尾的
.常作为格式结束符(空状态组占位)。 - 效果为单个
0(或空)表示“无效果”占位。
三、状态定义 SkillStatus(7 个字段)
每个状态组开头的 7 个字段,描述“这一组效果对谁生效、怎么生效”。
A - B - C - D - E - F - G
id target center range mode clear isInjure
| 位置 | 字段 | 含义 | 取值说明 |
|---|---|---|---|
| 1 | id | 状态组标识 | 通常为 0,组间靠顺序区分 |
| 2 | target | 目标类型(位掩码) | 1=自身;2=友方;4=敌方;8=NPC;12=4+8(敌方+NPC);16=地表;32=宠物;64=召唤物。多个目标可用和值叠加 |
| 3 | center | 施法中心点 | 1=鼠标点;2=自身 |
| 4 | range | 攻击范围 | 1=单体目标;20/21/22/50 等=范围攻击 |
| 5 | mode | 飞行模式 | 0=近身(需相邻格);1=飞行(魔法弹道可跨格) |
| 6 | clear | 能否被清除 | 该状态可否被驱散 / 覆盖 |
| 7 | isInjure | 是否触发伤害判定 | 1=进入伤害结算;0=仅施加状态不直接掉血 |
四、效果元素 SkillElement(5 个字段)
状态组内每个元素,描述一条具体效果。
A - B - C - D - E
id percent value time state
| 位置 | 字段 | 含义 | 说明 |
|---|---|---|---|
| 1 | id | 效果状态 ID | 对应服务端 SkillStatusManager.cpp 中 SkillStatus_XX() 处理函数,即 funlist[XX],决定这条效果做什么 |
| 2 | percent | 触发百分比 | 按百分比概率触发(100=必定触发;2=2% 概率) |
| 3 | value | 效果数值 | 具体加成 / 伤害 / 数值 |
| 4 | time | 持续时间 | 状态持续时间(秒) |
| 5 | state | 状态表现 | 对应客户端 USTATE_* 状态,决定 buff 图标 / 特效显示(见第六节) |
五、完整示例解析:「逆手刺」(技能 ID = 12)
原始效果字段:
0-1-2-1-0-0-0:23-100-458-1-0;273-2-200-1-0;.0-12-2-1-0-0-1:133-0-0-0-0;.
拆分为 3 个状态组:
状态组 1:0-1-2-1-0-0-0 → 对自身施加 buff
- 状态定义:
id=0 target=1(自身) center=2(以自身为中心) range=1(单体) mode=0(近身) clear=0 isInjure=0 - 效果元素①
23-100-458-1-0SkillStatus_23():skillValue.updam = value→ 物理攻击力 +458percent=100必定触发,time=1
- 效果元素②
273-2-200-1-0SkillStatus_273():skillValue.nsc_updamp = value→ 隐身/刺客系物理攻击 +200percent=2,即 2% 概率额外触发(对应匕首系特有增益)
状态组 2:0-12-2-1-0-0-1 → 对敌方目标造成物理伤害
- 状态定义:
target=12(敌方+NPC) isInjure=1(触发伤害判定) - 效果元素
133-0-0-0-0SkillStatus_133():isPhysics = true→ 标记本次攻击为物理伤害,随后进入伤害结算
状态组 3:末尾 . → 空状态组(格式结束符)
整句含义:逆手刺是一个匕首系物理单体技能,命中时给自身附加 「物攻 +458」与「隐身系物攻 +200(2% 概率)」两个增益, 同时将本次攻击标记为物理伤害并结算。
六、效果如何与客户端关联
6.1 效果在服务端的运行路径
SkillBase.tbl2 → 服务端加载 → 解析为 zSkillB.skillStatus
│
角色使用技能 → putOperationToMe / putPassivenessOperationToMe
│
对每条 SkillElement 执行 SkillStatus_[id]()
│
runStatusElement 返回 SKILL_RECOVERY / SKILL_ACTIVE ...
6.2 SkillElement.id → SkillStatus_XX() 效果函数
SkillElement.id 是效果逻辑的入口,服务端通过 funlist[id] 调用对应的
SkillStatus_XX(entry, element) 处理函数。函数内部根据 percent(概率)、
value(数值)、time(时长) 落地具体属性 / 状态。
常用效果 ID 速查(部分):
| ID | SkillStatus_XX | 效果 |
|---|---|---|
| 23 | SkillStatus_23 | 物理攻击力 +value(updam) |
| 133 | SkillStatus_133 | 标记本次攻击为物理伤害 |
| 134 | SkillStatus_134 | 取消物理伤害标记 |
| 273 | SkillStatus_273 | 隐身/刺客系物理攻击 +value(nsc_updamp) |
完整的
SkillStatus_0~SkillStatus_2xx效果列表见ScenesServer/SkillStatusManager.cpp(每个函数上方都有中文注释说明用途)。 新增效果需要在funlist中登记,并同步客户端协议。
6.3 SkillElement.state → 客户端 USTATE_* 状态
当效果需要以“持续状态”形式显示给玩家时,用 state 字段指定一个客户端状态 ID。
- 服务端在效果生效时调用
sendSelectStates(state, value, time), 通过sendtoSelectedState/sendSevenStateToMe同步给客户端。 - 客户端用该 ID 对应
base/Command.h中的USTATE_*枚举,渲染 buff 图标 / 头顶特效 / 状态栏。
常用 USTATE 速查:
| USTATE 值 | 常量名 | 含义 |
|---|---|---|
| 0 | USTATE_DEATH | 死亡 |
| 1 | USTATE_POISON | 中毒 |
| 2 | USTATE_FREEZE | 冰冻 |
| 4 | USTATE_HIDE | 隐身 |
| 22 | USTATE_BLED | 流血 |
| 30 | USTATE_SLOW | 缓慢 |
| 48 | USTATE_BOMB | 诅咒炸弹 |
客户端
SkillBase表(skillbase_client.txt)里没有「效果」字段—— 效果数值与状态由服务端按本表的「效果」字段解析后计算,再通过状态同步 协议把state / value / time下发给客户端用于表现。因此策划只需在服务端SkillBase表配好「效果」列,客户端表现会随状态同步自动显示。
七、关于 tbl2 可变长主业务线(为什么不再截断)
历史上效果字段受定长 1024 字节限制:服务端把效果字符串拷贝进
SkillBase.strField21[1024],超过 1023 字节会被静默截断,导致技能实际效果不完整。
现已在代码层将整张 SkillBase 表迁移到 tbl2 可变长主业务线:
- 表格已使用 tbl2 池化格式(
stringPool="1"),字符串变长存储、无长度限制。 - 服务端加载 tbl2 时,整张表(名称、需要武器、效果及全部数值字段)统一从字符串池
直接解析进
zSkillB的可变长容器(skillStatus等),不再经由定长SkillBase(strField21[1024])中转,彻底消除超长截断风险。 - 旧版定长
.tbl格式仍被兼容(通过旧fill()路径映射进同一数据结构), 保证老数据不丢失。
对策划的意义:只要在 Excel/XML 里按规范书写「效果」字段,无论配多长、 多少个状态组和元素,都会完整生效,无需担心长度限制。 建议仍保持可读性:一行技能的效果尽量控制在 2~4 个状态组内。
八、配置速查清单
配「效果」字段时,自问几个问题:
- 对谁生效? → 填
target(自身/友方/敌方/NPC,可叠加) - 怎么施加? → 填
center、range、mode(近身/飞行、单体/范围) - 会造成伤害吗? → 填
isInjure(1 走伤害结算) - 加什么属性? → 用「效果元素」的
id选效果函数,value填数值 - 是否必定触发? → 填
percent - 持续多久? → 填
time - 要不要在客户端显示状态图标? → 填
state(对应USTATE_*)