核心定位EFFECTSLIST.DAT 是效果系统的类型注册表。 技能与词缀 dat 里每个 [EFFECT] 块的 TYPE 键,写的就是这张表某一行的 NAME; 那一行的行号会成为 CEffect+0x1C,进而决定这个效果做什么、五个数值槽分别叫什么、 缺省时套哪条曲线、tooltip 里怎么排版。本文档把这 239 行完整摊开,并把加载器逐指令拆到底。

分析依据:基于 IDA 对 32 位可执行文件 Torchlight2.exe(基址 0x400000)的逐指令反汇编分析。文中所有 0x…… 均为绝对内存地址。 用量数据来自实机样本统计:原版 E:/Torchlight 2/MEDIA 的 16084 个 .DAT 文件共 9984 个可解析 [EFFECT] 块, MOD 库 D:/WizardProject/TL2 的 157950 个 .DAT 文件共 200352 个。 MOD 库是会变的——本系列三篇的用量数字已统一到同一次全量扫描; 原版侧(16084 个文件 / 9984 个块)在整个分析期间保持不变。 EFFECTSLIST.DAT 自身的 239 行属类型注册、不计入效果块,已排除。

关联文档:效果对象本身参见 CEffect 参考手册,词缀容器参见 CAffix 参考手册, 挂载调度参见 CEffectManager 参考手册,状态栏显示参见 CEffectDisplayMgr 参考手册。 本文档不重复那四篇的内容,只负责「239 行本身」这一层。 每个类型实际做什么(走哪条执行路径、DURATION 该怎么填、写错会不会静默失效)见 239 个 TYPE 的行为解释; 每个类型的真实数据样例239 个 TYPE 的实例速查

1. 这张表怎么进内存

加载器是 EffectsList_dat_load_239,起始 0x401000,读取路径硬编码为字符串 "media/EffectsList.dat"0x401068)。 它把文件解析成一串 [EFFECT] 子节点,然后按行号顺序把 19 个键分别灌进 13 张平行的全局数组。

DAT 键标签运行期全局地址元素写入点读取点
NAME<STRING>g_EffectTypeNames_2390x28A28D8wstring×2390x40113A0x7AABBD0x531D740x7A4C090x7C8FAA
VALUE1VALUE5<STRING>g_EffectParamNames_239x50x28AABA0wstring[239][5]0x4012F10x7A5F46CEffect__readValueSlot
GRAPH1GRAPH2<STRING>g_EffectGraphNames_239x50x28B2E58wstring[239][5]0x4014AA0x4015030x7A606ECEffect__bindGraphs
TYPE<STRING>g_EffectDisplayKind_2390x28A1D80int×2390x4017920x4017B70x7A71D4
MINVAL<INTEGER>g_EffectMinVal_2390x28A2500int×2390x4017FD
MAXVAL<INTEGER>g_EffectMaxVal_2390x28A2140int×2390x4018570x7A71FD
DISPLAYPRECISION<INTEGER>dword_28A19C00x28A19C0int×2390x4016670x7A72370x7A727B0x7A7318
DISPLAYPRECISIONMAXVAL<FLOAT>flt_28A16000x28A1600float×2390x4016B70x7A72290x7A72740x7A730E
AFFIX_MODIFIES<BOOL>g_EffectAffixModifies_2390x28A1510bool×2390x40170B0x7A4247
GOODDES<TRANSLATE>g_EffectGoodDes_2390x28A4300wstring×2390x4011930x7A73BF
GOODDESOT<TRANSLATE>byte_28A5D280x28A5D28wstring×2390x4011EC0x7A7394
BADDES<TRANSLATE>g_EffectBadDes_2390x28A7750wstring×2390x4012450x7A73D1
BADDESOT<TRANSLATE>byte_28A91780x28A9178wstring×2390x40129E0x7A73A6

EFFECT 键(值形如 KEFFECT_TYPE_MELEEDAMAGEBONUS)在整个加载器里没有对应的写入指令—— 它是给人看的枚举名注记,引擎从不解析。真正决定行为的是行号。

1.1 239 这个数字是怎么把自己锁死的

加载完成后有一道校验(0x40109E):

asm
0040109E  cmp  [esp+0D4h+var_74], 0EFh   ; 0xEF = 239,子节点数量
004010A6  jz   short loc_4010E6          ; 正好 239 → 静默通过
004010A8  push offset aTheEffectFileM    ; 否则打一条日志

日志原文是 The effect file( media/effectslist.dat ) appears to no longer match up with the internal effect list. Please revert this file.

CAUTION

这道校验只写日志,不截断,也不中止加载。 紧接着的填表循环(0x4011000x40188D)用的上界是 var_74,也就是文件里实际的块数, 而不是常量 239:

asm
0040187D  add  [esp+0D8h+var_AC], 1Ch   ; 描述串行指针 += 28
00401882  inc  esi                      ; 行号
00401883  add  ebp, 8Ch                 ; 槽数组行偏移 += 140
00401889  cmp  esi, [esp+0D8h+var_74]   ; ← 文件实际块数
0040188D  jb   loc_401100

后果分两种,都不是「多出来的行被忽略」:

  • 少于 239 行esi 到不了的那些行保持空 wstringNAME 为空串。 由于 [EFFECT] 块的 TYPE 是拿大写化后的值去和 NAME 逐个比较(见 9.1 节), 空 NAME 永远匹配不上,这些类型号就此全部失效。
  • 多于 239 行esiebp 继续往后走,越界写进紧邻的全局数组g_EffectParamNames_239x5 的基址是 0x28AABA0,239 行 × 140 字节 = 33460 字节, 末尾落在 0x28B2E54;而 g_EffectGraphNames_239x5 的基址是 0x28B2E58, 两者只隔 4 个字节。第 240 行的 VALUE1 会直接盖在第 0 行的 GRAPH1 上。 再往后 g_EffectGraphNames_239x5 的末尾同样紧邻别的全局对象。

换句话说,这个 239 不是「建议值」,而是一个既不能减也不能加的硬编号空间。 至于为什么连行序都不能动(存档里存的是索引而非名字),见 CEffect §8

2. 五个数值槽是怎么对上名字的

槽名表的行偏移由 ebp 携带,每行递增 0x8C = 140 = 5 × 28(wstring 在这个二进制里是 28 字节)。 加载器先算出该行的槽 1 地址,再用相对位移填其余四个:

asm
004012F1  lea  edi, g_EffectParamNames_slot2[ebp]  ; edi = 基址 + 0x1C + 行偏移
004012FD  lea  ecx, [edi-1Ch]                      ; VALUE1 → 槽 0
              (VALUE2 直接用 edi)                   ; VALUE2 → 槽 1
004013A8  lea  ecx, [edi+1Ch]                      ; VALUE3 → 槽 2
004013FE  lea  ecx, [edi+38h]                      ; VALUE4 → 槽 3
00401454  lea  ecx, [edi+54h]                      ; VALUE5 → 槽 4

映射是直白的 VALUEn → 槽 n-1,没有重排。数组总跨度 239 × 140 = 33460 字节,与实测的符号间距一致。 读取侧只有一个函数:CEffect__readValueSlot0x7A5F46), 它按 CEffect+0x1C(类型号)与槽号取出别名字符串,再拿这个别名去 [EFFECT] 块里查键。

IMPORTANT

[EFFECT] 块里能写哪些数值键,完全由这张表该行的 VALUE1VALUE5 决定。 比如第 55 行 CRITICAL CHANCE 的槽名是 MINMAXNANANA, 那么 <FLOAT>MIN:<FLOAT>MAX: 有效,写 <FLOAT>CHANCE: 则不会被任何代码读到。 而第 156 行 DAMAGE CHANCE 的槽 4 恰好叫 CHANCE,同一个键名在那里就是有效的。 键名不是全局约定,是逐类型的。

2.1 NA 的含义

NA 是「这个槽没有别名」的占位写法,在 239 × 5 = 1195 个槽位里占了 676 个。 剩下 519 个槽位上共出现 62 个不同的别名。 下表按使用频次列出全部别名,以及它们各自出现在哪个槽位、哪些行:

别名出现槽位行数用在哪些行
MAX槽 12020、1、2、3、4、5、6、7、8、9、10、11、13、14…
MIN槽 02020、1、2、3、4、5、6、7、8、9、10、11、13、14…
CHANCE槽 0/槽 2/槽 417157、158、213、214、235、236、144、146、147、148、149、150、151、160…
MAXFORCE槽 360、1、7、52、156、237
MAXRANGE槽 3/槽 46157、158、235、236、160、161
MINFORCE槽 260、1、7、52、156、237
MINRANGE槽 2/槽 36157、158、235、236、160、161
COOLDOWN槽 44157、158、235、236
RANGE槽 1/槽 23213、231、234
COUNT槽 02160、161
FORCE槽 0212、43
MAXTIME槽 12227、228
MAX_COUNT槽 32231、234
MAX_PER槽 12231、234
MAX_TARGETS槽 42229、230
MINTIME槽 02227、228
MIN_PER槽 02231、234
NO_LOOT槽 2/槽 3267、110
PULSE_RATE槽 22229、230
RADIUS槽 32229、230
RESISTANCE槽 0253、121
TIME槽 02223、225
VALUE槽 22181、182
ANGLE槽 21163
CHANCE%槽 11164
CHANCE_TO_100槽 01187
DESTROY_BODY槽 4167
DESTROY_WEAPONS槽 41163
DMGPCT槽 2161
DMGPCTMAX槽 3160
DMGPCTMIN槽 2160
EFFECT_DURATION槽 11223
ENDSCALE槽 1159
EXPLODE槽 21110
GOLD%槽 01164
HP%槽 01163
HPOVERRIDE槽 11163
HPPCT槽 11161
IGNORE_RESISTANCE槽 2164
INVISIBLE槽 01155
MAXSCALE槽 01184
MAX_DEPTH槽 11113
MAX_PER_HEALTH槽 11229
MAX_PER_MANA槽 11230
MAX_STOP_AT槽 41185
MINSCALE槽 11184
MIN_DEPTH槽 01113
MIN_PER_HEALTH槽 01229
MIN_PER_MANA槽 01230
MIN_STOP_AT槽 31185
NO_DIE_ANIM槽 3167
OFFSET槽 31163
PERCENT_TO_100槽 01186
PERCENT_TO_HEAL槽 01185
PETINDEX槽 01142
POI槽 01162
STARTSCALE槽 0159
TARGET_SKILL_TARGET槽 21213
TIMETOSCALE槽 2159
TIMETOSCALEBACK槽 3159
TIME_TO_HEAL槽 11185
TIME_TO_HEAL_MAX槽 21185

MINMAX 这一对占了绝对多数(各 202 行的槽 0/槽 1), 这也是「效果数值写成一个区间」成为默认写法的原因——但区间的含义因场景而异: 装备词缀里它是品质插值的两端(见 CAffix), 技能效果里它是随机滚动的两端,而只有在该行注册了默认曲线时才需要 NOGRAPH:true 才能拿到真随机(见下节与 CEffect §6.1)。

3. 曲线槽:表里有五个位置,只有两个填得上

g_EffectGraphNames_239x50x28B2E58)与槽名表同构——同样 239 行、同样 0x8C 行距、同样 5 个 28 字节的 wstring。 但加载器只写前两个:

asm
004014AA  lea  ecx, g_EffectGraphNames_239x5[ebp]  ; GRAPH1 → 曲线槽 0
00401503  lea  ecx, unk_28B2E74[ebp]               ; GRAPH2 → 曲线槽 1(+0x1C)

EFFECTSLIST.DAT根本不存在 GRAPH3GRAPH4GRAPH5 这三个键(全表 19 个键,已在第 1 节列全)。

NOTE

这张表的形状说明设计意图曾是「五个数值槽各配一条曲线」, 但落地的数据格式只提供了两个入口,于是每一行的曲线槽 2/3/4 永久为空。 这正是为什么曲线插值只作用于槽 0 与槽 1(也就是绝大多数行的 MINMAX), 槽 2–4 上的数值(MINFORCECHANCERANGE 之类)从不参与曲线求值。

全表 239 行里只有 36 行注册了默认曲线。 另一个实测结论:这 36 行的 GRAPH1GRAPH2 完全相同,无一例外, 所以两列的区分在原版数据里从未体现过。

#TYPE曲线名原版MOD
0MELEEDAMAGEBONUSBASE_WEAPON_DAMAGE151
1RANGEDDAMAGEBONUSBASE_WEAPON_DAMAGE11
2DEFENSEATTRIBUTE_BONUS24624
3MAGICATTRIBUTE_BONUS24881
4MAX MANAMANA_PLAYER_GENERIC181139
5MAX HPHEALTH_PLAYER_GENERIC231657
7HP RECHARGEHEALTH_MONSTER_BYLEVEL34884
8ARMOR BONUSARMOR_PLAYER_BYLEVEL_FORSET851730
10DAMAGE BONUSBASE_WEAPON_DAMAGE1243865
35PHYSICAL DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·44
36MAGICAL DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·50
37FIRE DEFENSEARMOR_PLAYER_BYLEVEL_FORSET43409
38ICE DEFENSEARMOR_PLAYER_BYLEVEL_FORSET42417
39ELECTRICAL DEFENSEARMOR_PLAYER_BYLEVEL_FORSET43435
40POISON DEFENSEARMOR_PLAYER_BYLEVEL_FORSET38468
47SUMMON DURATIONSUMMONDURATION88909
48DAMAGE REFLECTIONBASE_WEAPON_DAMAGE40581
49LIFE STEALSTEAL_HEALTH_AND_MANA29721
50MANA STEALSTEAL_MANA23514
52DAMAGEDAMAGE_MONSTER106718351
54DEGRADE ARMORARMOR_MONSTER_BYLEVEL45841
69STRENGTH BONUSATTRIBUTE_BONUS24657
70DEXTERITY BONUSATTRIBUTE_BONUS24535
93REDUCED ITEM REQUIREMENTSITEM_DEFENSE_REQUIREMENTS541
122SHIELD BUFFERHEALTH_MONSTER_BYLEVEL621556
123MANA RECHARGE PLAYERMANA_PLAYER_GENERIC871562
124HP RECHARGE PLAYERHEALTH_PLAYER_GENERIC1642856
125LIFE STEAL MASTERSTEAL_HEALTH_AND_MANA7118
156DAMAGE CHANCEDAMAGE_MONSTER16703
218INNATE ICE DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·1
219INNATE FIRE DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·1
220INNATE ELECTRIC DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·1
221INNATE POISON DEFENSEARMOR_PLAYER_BYLEVEL_FORSET·1
229DRAW HEALTHHEALTH_PLAYER_GENERIC10208
230DRAW MANAMANA_PLAYER_GENERIC10205
237MINIONDAMAGEDAMAGE_MONSTER9801

WARNING

只有上表这 36 行需要靠 <BOOL>NOGRAPH:true 才能让 MINMAX 退化成真随机。 其余 203 行没有默认曲线,NOGRAPH 写与不写没有区别。 把这条规律说成「MINMAX 随机需要 NOGRAPH」是过度推广。

4. MINVALMAXVAL:一列是死数据,一列只贡献符号

这两列长期被理解成「数值的合法范围」或「UI 钳位」。逐指令核对的结果是两者都不成立。

立即数字节扫描 0x4010000x2200000(不依赖 IDA 的交叉引用,避免漏掉 SIB 寻址形式):

  • g_EffectMinVal_2390x28A2500)全程出现 1 次,就是加载器 0x4017FD 的那次写入。 没有任何读取点。MINVAL 是一列纯粹的死数据。
  • g_EffectMaxVal_2390x28A2140)出现 2 次:写入 0x401857,读取 0x7A71FD。 而那唯一的读取长这样:
asm
007A71FD  fild  g_EffectMaxVal_239[ebx*4]   ; 整数载入
007A7204  fstp  dword ptr [esp+164h+X+4]
007A7207  call  ds:?Sign@Math@Ogre@@SAMM@Z  ; Ogre::Math::Sign —— 只留符号

量级被 Ogre::Math::Sign 丢弃了。 这一列实际编码的是「这个属性往哪个方向变算好事」。

4.1 好/坏描述串的完整选择链

读取点位于 CEffect__build_tooltip_desc(函数起始 0x7A70B0)。两个栈变量控制最终取哪个串:

asm
007A71A9  mov   [esp+160h+var_10C], 1       ; var_10C = 1 → 默认「好」
007A71AE  mov   byte ptr [...var_14A], 0    ; var_14A = 0 → 默认非「持续」措辞

; ── var_14A:是否用 OT(over time)措辞 ──
007A719C  fld   dword ptr [esi+24h]         ; CEffect+0x24 = DURATION
007A719F  fld   ds:flt_219A6E0              ; = -900.0
007A71B8  jnp   loc_7A71D1                  ; 相等 → 保持 0
007A71BA  fld   dword ptr [esi+24h]
007A71BD  fld   ds:flt_219A6E4              ; = -1000.0
007A71CA  jnp   loc_7A71D1                  ; 相等 → 保持 0
007A71CC  mov   byte ptr [...var_14A], 1    ; 两个哨兵都不是 → 用 OT 措辞

; ── var_10C:好还是坏 ──
007A71D1  mov   ebx, [esi+1Ch]              ; 类型号
007A71D4  cmp   g_EffectDisplayKind_239[ebx*4], 2
007A71DC  jz    short loc_7A7226            ; TYPE:None → 整段跳过,保持「好」
007A71E4  fucom st(1)                       ; 数值 vs 0.0
007A71ED  jnp   short loc_7A7224            ; 数值为 0 → 跳过,保持「好」
          s1 = Sign(数值)
          s2 = Sign((float)MAXVAL[类型号])
007A7214  fucompp
007A721B  jnp   short loc_7A7226            ; 符号相同 → 保持「好」
007A721D  mov   [esp+160h+var_10C], 0       ; 符号不同 → 改判「坏」

test ah, 44hjnp 是 MSVC 的浮点相等判定惯用式:fucom 相等时置 C3,ah & 0x44 == 0x40, 奇校验使 PF = 0,于是 jnp 在相等时跳转。)

四路选择在 0x7A73710x7A73D8

var_14A(DURATION 非哨兵)var_10C取用的串取址指令
1≠0(好)GOODDESOT0x7A7394
10(坏)BADDESOT0x7A73A6
0≠0(好)GOODDES0x7A73BF
00(坏)BADDES0x7A73D1

索引算法是 ecx = 类型号 * 8 - 类型号(即 ×7)后取 [基址 + ecx*4],等价于 基址 + 类型号 * 28,与 wstring 步长吻合。

NOTE

由此可读出两条非直觉的行为:

  1. 数值恰好为 0 的效果一律用「好」措辞0x7A71ED 跳过判定)。
  2. TYPE:None 的 14 行一律用「好」措辞0x7A71DC 跳过判定), 与「不显示数值」是同一个分支的副作用。

4.2 MAXVAL 符号为负的行

全表 220 行是标准的 MINVAL:-100MAXVAL:100。剩下 19 行如下, 其中 4 行的 MAXVAL 为负——这正是「数值越低越好」的属性,符号翻转后 Sign 判定才正确:

#TYPEMINVALMAXVALMAXVAL 符号 → 好的方向
11DAMAGE TAKEN20-20负向为好
26PERCENT DAMAGE TAKEN50-50负向为好
45OPEN WAYPOINT PORTAL-1100000正向为好
48DAMAGE REFLECTION0100正向为好
49LIFE STEAL-99999999正向为好
52DAMAGE-1000010000正向为好
53PERCENT KNOCK BACK RESISTANCE0100正向为好
59SCALE010正向为好
66DEGRADE ARMOR EFFECT100-100负向为好
113WARP-10001000正向为好
125LIFE STEAL MASTER-99999999正向为好
155SET MESH INVISIBLE01正向为好
156DAMAGE CHANCE-1000010000正向为好
184SCALE BY HP010正向为好
185HP MOD OVER TIME-10001000正向为好
186TRANSFORMATION TIME-10001000正向为好
187TRAP DISARM CHANCE0100正向为好
231PERCENT DAMAGE TAKEN BY MONSTER COUNT100-100负向为好
237MINIONDAMAGE-1000010000正向为好

MINVAL 一列在这 19 行里也出现了与 MAXVAL 倒挂的写法(如第 11 行 MINVAL:20MAXVAL:-20), 但既然它没有读取点,这种倒挂纯属数据侧的书写惯例,不产生任何行为。

5. 显示形态与精度

5.1 TYPE 列:只有 None 有意义

加载器把这一列归一化成一个整数(0x401748 起,缺省实参是字面量 "VALUE",随后 toUpperW):

asm
00401792  mov  g_EffectDisplayKind_239[esi*4], 1   ; == "PERCENT"
;  否则:
004017AB  movzx edx, al                            ; al = (值 == "NONE")
004017AE  neg   edx
004017B3  sbb   edx, edx                           ; edx = 相等 ? -1 : 0
004017B5  and   edx, ebx                           ; ebx = 2(0x40104F 处 mov ebx, 2)
004017B7  mov  g_EffectDisplayKind_239[esi*4], edx ; NONE → 2,其余 → 0
DAT 写法表值原版行数
Percent159
None214
Value、缺省、或任何拼错的值0166

WARNING

PercentValue 对引擎完全等价,百分号不是这一列画出来的。 立即数扫描显示 g_EffectDisplayKind_239 全程只有 3 处:两处写入加一处读取, 而那唯一的读取是 cmp …, 20x7A71D4)——只判断「是不是 None」,从不区分 0 与 1。

百分号来自 GOODDES 等描述串里写死的字面 %。实测反证两条: 原版有 56 行标着 TYPE:Value、描述里却带 % (第 33、55、56、60、64、68、80、88 行……), 而第 44 行 PERCENT ACTIVE DISTANCE BONUS 标着 Percent,四个描述串却全是 NA。 这一列在原版数据里更接近一份给人看的分类注记。

5.2 精度两列

DISPLAYPRECISION0x28A19C0int)与 DISPLAYPRECISIONMAXVAL0x28A1600float) 成对传给同一个格式化函数 sub_7A6760,在 build_tooltip_desc 里被调用四次 (0x7A72690x7A72C30x7A7303,以及 0x7A733F 之后一处), 分别对应「数值」「上限数值」「时长」「区间上界」四个待排版的数字。

DISPLAYPRECISION 全表 222 行为 0,14 行为 1,3 行为 2

#TYPEDISPLAYPRECISION
6MANA RECHARGE1
7HP RECHARGE1
21PERCENT SPEED1
22PERCENT ATTACK SPEED1
43KNOCK BACK EFFECT1
47SUMMON DURATION1
57TRANSFORM2
78MISSILE RANGE BONUS2
123MANA RECHARGE PLAYER1
124HP RECHARGE PLAYER1
152CAST SKILL ON STRIKE1
168ADD CHARGE PERCENT2
196IMMOBILIZE1
229DRAW HEALTH1
230DRAW MANA1
231PERCENT DAMAGE TAKEN BY MONSTER COUNT1
234PERCENT DAMAGE BONUS BY MONSTER COUNT1

DISPLAYPRECISIONMAXVAL 的取值只有三种:0(226 行)、19(10 行)、9(3 行)。

6. 完整对照表

列的读法

  • # —— 行号,也就是 CEffect+0x1C 里存的类型号,以及存档里落盘的那个整数。
  • TYPE —— [EFFECT] 块的 TYPE 键要写的字面值,比较前会被大写化。
  • 槽 0–4 —— 该行 VALUE1VALUE5 注册的键名;· 表示该槽写的是占位值 NA,无可用键名。
  • —— g_EffectDisplayKind_239 的值: = 0,% = 1(与 0 等价), = 2。
  • 默认曲线 —— GRAPH1(该行 GRAPH2 与之相同)。留空表示无默认曲线,NOGRAPH 对该行无意义。
  • 特判 —— 引擎里针对该类型号硬编码的分支,代号见第 7 节。
  • 原版/MOD —— [EFFECT] 块里 TYPE 命中该行的次数;· 为 0。
#TYPE槽 0槽 1槽 2槽 3槽 4默认曲线特判原版MOD
0MELEEDAMAGEBONUSMINMAXMINFORCEMAXFORCE·BASE_WEAPON_DAMAGE151
1RANGEDDAMAGEBONUSMINMAXMINFORCEMAXFORCE·BASE_WEAPON_DAMAGE11
2DEFENSEMINMAX···ATTRIBUTE_BONUSM24623
3MAGICMINMAX···ATTRIBUTE_BONUS24880
4MAX MANAMINMAX···MANA_PLAYER_GENERIC181139
5MAX HPMINMAX···HEALTH_PLAYER_GENERIC231657
6MANA RECHARGEMINMAX···F24369
7HP RECHARGEMINMAXMINFORCEMAXFORCE·HEALTH_MONSTER_BYLEVELF34883
8ARMOR BONUSMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET851730
9TO HIT BONUSMINMAX·····
10DAMAGE BONUSMINMAX···BASE_WEAPON_DAMAGE1243865
11DAMAGE TAKENMINMAX····70
12KNOCK BACKFORCE····106760
13SIGHT BONUSMINMAX····8
14VIEW ANGLE BONUSMINMAX···1·
15PERCENT MELEEDAMAGEMINMAX···%17265
16PERCENT RANGEDDAMAGEMINMAX···%23246
17PERCENT DEFENSEMINMAX···%M·306
18PERCENT MAGICMINMAX···%·136
19PERCENT MANAMINMAX···%11545
20PERCENT HPMINMAX···%321639
21PERCENT SPEEDMINMAX···%2604654
22PERCENT ATTACK SPEEDMINMAX···%3034818
23PERCENT ARMOR BONUSMINMAX···%892940
24PERCENT TO HIT BONUSMINMAX···%·15
25PERCENT DAMAGE BONUSMINMAX···%3917179
26PERCENT DAMAGE TAKENMINMAX···%3896021
27PERCENT MAGICAL DROPMINMAX···%43439
28PERCENT GOLD DROPMINMAX···%37423
29PERCENT CAST SPEEDMINMAX···%1563690
30PERCENT LIFE STOLENMINMAX···%7325
31PERCENT MANA STOLENMINMAX···%4119
32PERCENT DAMAGE REFLECTEDMINMAX···%31785
33PERCENT BLOCK CHANCEMINMAX···23299
34PERCENT ITEM REQUIREMENTSMINMAX···%··
35PHYSICAL DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSETM·44
36MAGICAL DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET·50
37FIRE DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSETM43408
38ICE DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSETM42416
39ELECTRICAL DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSETM43434
40POISON DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSETM38467
41PERCENT SIGHT BONUSMINMAX···%126
42PERCENT VIEW ANGLE BONUSMINMAX···%··
43KNOCK BACK EFFECTFORCE····G6015771
44PERCENT ACTIVE DISTANCE BONUSMINMAX···%1361
45OPEN WAYPOINT PORTALMINMAX···22
46IDENTIFYMINMAX···22
47SUMMON DURATIONMINMAX···SUMMONDURATION88907
48DAMAGE REFLECTIONMINMAX···BASE_WEAPON_DAMAGE40580
49LIFE STEALMINMAX···STEAL_HEALTH_AND_MANA29716
50MANA STEALMINMAX···STEAL_MANA23510
51GOLD DROPMINMAX····39
52DAMAGEMINMAXMINFORCEMAXFORCE·DAMAGE_MONSTERXA106718348
53PERCENT KNOCK BACK RESISTANCERESISTANCE····%3023058
54DEGRADE ARMORMINMAX···ARMOR_MONSTER_BYLEVEL45840
55CRITICAL CHANCEMINMAX···3113979
56INTERRUPT CHANCEMINMAX···1201066
57TRANSFORMMINMAX···3772
58UNIT THEME·····2163178
59SCALESTARTSCALEENDSCALETIMETOSCALETIMETOSCALEBACK·Q21351
60MISSILE REFLECTMINMAXDMGPCTMINDMGPCTMAX·R691040
61MISSILE REFLECT VISUALMINMAXDMGPCT···8
62PERCENT BLOCK CHANCE BASEMINMAX···%S45437
63VELOCITY MULTMINMAX·····
64STUNMINMAXIGNORE_RESISTANCE··2253319
65LEARN SKILLMINMAX···197893
66DEGRADE ARMOR EFFECTMINMAX···1274
67DESUMMON MONSTERMINMAXNO_LOOTNO_DIE_ANIMDESTROY_BODY2712426
68XP GAIN BONUSMINMAX···19254
69STRENGTH BONUSMINMAX···ATTRIBUTE_BONUS24656
70DEXTERITY BONUSMINMAX···ATTRIBUTE_BONUS24534
71PERCENT STRENGTH BONUSMINMAX···%·221
72PERCENT DEXTERITY BONUSMINMAX···%·149
73TRANSFORM PERMANENTMINMAX···1663
74CAST SKILLMINMAX···%25810
75CAST SKILL ON TARGETMINMAX···%·49
76CAST SKILL AT TARGETMINMAX···%·11
77FAME GAIN BONUSMINMAX···%169
78MISSILE RANGE BONUSMINMAX···17174
79FLEE EFFECTMINMAX···%881017
80TURN ALIGNMENTMINMAX···27542
81CAST SKILL ON STRUCKMINMAX···%521242
82SKILL BONUSMINMAX···7215
83PRICE REDUCTIONMINMAX···%658
84FISHING LUCKMINMAX···%545
85ATTACK SPELL BONUSMINMAX···16
86DEFENSE SPELL BONUSMINMAX···M14
87CHARM SPELL BONUSMINMAX···14
88DUAL WIELDING BONUSMINMAX···23294
89PERCENT CRITICAL DAMAGEMINMAX···201444
90POTION EFFICIENCYMINMAX···15212
91PERCENT PET DAMAGEMINMAX···19422
92PERCENT PET VELOCITYMINMAX···587
93REDUCED ITEM REQUIREMENTSMINMAX···ITEM_DEFENSE_REQUIREMENTS541
94ARMOR ITEM REQUIREMENTSMINMAX···128
95SPELL REQUIREMENTSMINMAX····2
96PET DEPARTURE TIMEMINMAX···338
97PERCENT PET ARMORMINMAX···14221
98MARTIAL ITEM REQUIREMENTSMINMAX···159
99PERCENT MARTIAL ITEM DAMAGE BONUSMINMAX···178
100RANGED ITEM REQUIREMENTSMINMAX···120
101MAGIC ITEM REQUIREMENTSMINMAX···18
102PERCENT RANGED ITEM DAMAGE BONUSMINMAX···1102
103PERCENT MAGIC ITEM DAMAGE BONUSMINMAX···790
104PERCENT PET HEALTHMINMAX···10224
105CAST SKILL ON DEATHMINMAX···112529
106FREEZEMINMAX···1421151
107BURNMINMAX···821144
108POISONMINMAX···63914
109SHOCKMINMAX···62901
110KILLMINMAXEXPLODENO_LOOT·911279
111FADE OUTMINMAX···10444
112SET VISIBLEMINMAX···1860
113WARPMIN_DEPTHMAX_DEPTH···2118
114PERMANENT STRENGTHMINMAX···26
115PERMANENT DEXTERITYMINMAX···26
116PERMANENT MAGICMINMAX···26
117PERMANENT HEALTHMINMAX···17
118PERMANENT DEFENSEMINMAX···M37
119PERMANENT MANAMINMAX····2
120AWARD STATPOINTMINMAX····8
121FLEE RESISTRESISTANCE····60295
122SHIELD BUFFERMINMAX···HEALTH_MONSTER_BYLEVEL621543
123MANA RECHARGE PLAYERMINMAX···MANA_PLAYER_GENERICF871560
124HP RECHARGE PLAYERMINMAX···HEALTH_PLAYER_GENERICF1642837
125LIFE STEAL MASTERMINMAX···STEAL_HEALTH_AND_MANA7118
126PERCENT LIFE STOLEN MASTERMINMAX···%448
127STOP SKILLMINMAX···671867
128SILENCEMINMAX···35653
129DESUMMON ON DEATHMINMAX···29602
130EMOTIONAL DAMAGEMINMAX·····
131FUTURISTICNESSMINMAX····21
132JAUNTINESSMINMAX·····
133SOCKSMINMAX·····
134LOGIC RESISTANCEMINMAX·····
135NOODLE ARMSMINMAX···1·
136INTERRUPT RESISTANCEMINMAX···1301105
137CHARM RESISTANCEMINMAX···41459
138SILENCE_RESISTANCEMINMAX···388
139STUN RESISTANCEMINMAX···10497
140SLOW RESISTANCEMINMAX···32831
141OPEN PORTALMINMAX···721876
142SWAP POS WITH PETPETINDEX····11
143RESPECMINMAX···12
144PERCENT BLINDMINMAXCHANCE··40267
145EXPLODE DEADMINMAX···47596
146ADD STATMINMAXCHANCE··2785307
147ADD STAT TO LEVELMINMAXCHANCE····
148SET STATMINMAXCHANCE··83088
149SET STAT ON LEVELMINMAXCHANCE····
150CLEAR STATMINMAXCHANCE··281418
151CLEAR STAT ON LEVELMINMAXCHANCE····
152CAST SKILL ON STRIKEMINMAX···%261913
153PERCENT DUAL WIELDING ATTACKMINMAX···%22273
154DAMAGE BONUS SECONDARYMINMAX···23275
155SET MESH INVISIBLEINVISIBLE····583
156DAMAGE CHANCEMINMAXMINFORCEMAXFORCECHANCEDAMAGE_MONSTERX16703
157TELEPORT RANDOMCHANCE·MINRANGEMAXRANGECOOLDOWN11198
158TELEPORTCHANCE·MINRANGEMAXRANGECOOLDOWN68
159TELEPORT RESISTANCEMINMAX···439
160SPAWN UNITCOUNT·CHANCEMINRANGEMAXRANGE··
161SPAWN UNIT ON DEATHCOUNTHPPCTCHANCEMINRANGEMAXRANGEA1110
162WARP TO POIPOI····22
163DESTRUCTABLE SHIELDHP%HPOVERRIDEANGLEOFFSETDESTROY_WEAPONSQ32175
164DISENCHANTGOLD%CHANCE%···15
165ADD TRIGGERABLE··CHANCE··2713273
166REMOVE TRIGGERABLEMINMAX···E842345
167INTERRUPTMINMAX···17164
168ADD CHARGE PERCENTMINMAX···811390
169SET CHARGE PERCENTMINMAX···1780
170MAX CHARGESMINMAX····1
171ADD CHARGESMINMAX···1102525
172PERCENT CHARGE BAR DECAY RATEMINMAX···13161
173CHARGE BAR DECAY DELAYMINMAX···17
174PERCENT CHARGING BONUSMINMAX···40614
175PERCENT MANA COST BONUSMINMAX···3399
176CHARGE BAR DECAY RATEMINMAX····7
177EXPLODE ON DEATHMINMAX···77551
178DODGE CHANCE BONUSMINMAX···40783
179FUMBLE CHANCE REDUCTIONMINMAX···18311
180FUMBLE PENALTY REDUCTIONMINMAX···130
181CONVERT CHARGE TO STAT··VALUE··30314
182CONVERT CHARGE PERCENT TO STAT··VALUE···6
183CAST SKILL ON DEATH FROM EFFECT OWNERMINMAX···%41836
184SCALE BY HPMAXSCALEMINSCALE···620
185HP MOD OVER TIMEPERCENT_TO_HEALTIME_TO_HEALTIME_TO_HEAL_MAXMIN_STOP_ATMAX_STOP_ATA3411434
186TRANSFORMATION TIMEPERCENT_TO_100······
187TRAP DISARM CHANCECHANCE_TO_100······
188ELEMENTAL EFFECT DURATION BONUSMINMAX···471
189BURN DURATION BONUSMINMAX····57
190FREEZE DURATION BONUSMINMAX····40
191SHOCK DURATION BONUSMINMAX····18
192POISON DURATION BONUSMINMAX····42
193NONE·····19275
194CAST SKILL ON RANGED STRIKEMINMAX···%1555
195CAST SKILL ON MELEE STRIKEMINMAX···%·85
196IMMOBILIZEMINMAX···1171473
197IMMOBILIZE RESISTANCEMINMAX···20605
198CAST SKILL FROM TARGETMINMAX···%·75
199CAST SKILL ON MELEE STRIKE FROM TARGETMINMAX···%290
200CAST SKILL ON RANGED STRIKE FROM TARGETMINMAX···%·18
201CAST SKILL ON STRIKE FROM TARGETMINMAX···%521167
202BLINDMINMAX···%8614
203CAST SKILL ON KILLMINMAX···%11177
204CAST SKILL ON KILL AT TARGETMINMAX···%20275
205SHIELD BREAKMINMAX···%15456
206CAST SKILL ON MELEE SKILL STRIKEMINMAX···%·2
207CAST SKILL ON MELEE SKILL STRIKE FROM TARGETMINMAX···%118
208CAST SKILL ON RANGED SKILL STRIKEMINMAX···%··
209CAST SKILL ON RANGED SKILL STRIKE FROM TARGETMINMAX···%·3
210CAST SKILL ON SKILL STRIKEMINMAX···%·451
211CAST SKILL ON SKILL STRIKE FROM TARGETMINMAX···%·62
212TARGET LOCKED·····117
213RETARGETCHANCERANGETARGET_SKILL_TARGET··16
214AGROCHANCE····150
215SHIELD BREAK EFFECTMINMAX···%50821
216MODIFY SKILL COOLDOWN REMAININGMINMAX····103
217SET SKILL COOLDOWN REMAININGMINMAX···5318
218INNATE ICE DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET·1
219INNATE FIRE DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET·1
220INNATE ELECTRIC DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET·1
221INNATE POISON DEFENSEMINMAX···ARMOR_PLAYER_BYLEVEL_FORSET·1
222SET SKILL LEVELMINMAX···692306
223PULLTIMEEFFECT_DURATION···11304
224PULL RESISTANCEMINMAX···%45819
225PULL EFFECTTIME·····10
226MISS CHANCEMINMAX···%2177
227SKILL ENABLEMINTIMEMAXTIME···1011
228SKILL DISABLEMINTIMEMAXTIME···73
229DRAW HEALTHMIN_PER_HEALTHMAX_PER_HEALTHPULSE_RATERADIUSMAX_TARGETSHEALTH_PLAYER_GENERIC10208
230DRAW MANAMIN_PER_MANAMAX_PER_MANAPULSE_RATERADIUSMAX_TARGETSMANA_PLAYER_GENERIC10205
231PERCENT DAMAGE TAKEN BY MONSTER COUNTMIN_PERMAX_PERRANGEMAX_COUNT·%N31379
232REMOVE EFFECTMINMAX···8306
233BLIND RESISTANCEMINMAX···3452
234PERCENT DAMAGE BONUS BY MONSTER COUNTMIN_PERMAX_PERRANGEMAX_COUNT·%N15338
235TELEPORT NOPARTICLECHANCE·MINRANGEMAXRANGECOOLDOWN149
236TELEPORT RANDOM NOPARTICLECHANCE·MINRANGEMAXRANGECOOLDOWN·45
237MINIONDAMAGEMINMAXMINFORCEMAXFORCE·DAMAGE_MONSTERA9801
238CHEATEDMINMAX·····

7. 引擎里按类型号硬编码的分支

上表「特判」列的代号在此展开。这些判定不看数据,只看类型号,改 EFFECTSLIST.DAT 无法迁移它们。

代号类型号位置行为
X52、156CEffect__ctorFromDat构造时自动预置 EXCLUSIVE,无需在 dat 里写
M2、17、35、37–40、86、1180x7AABEF 的跳转表(落点 0x7AAC0A强制 DAMAGE_TYPE 为魔法系
F6、7、123、124数值换算路径每帧量按 值 × DURATION × 0.016 折算
A52、161、185、2370x7A4247该行 AFFIX_MODIFIES:false,词缀品质插值跳过
Q59、1630x7A42500x7A4255词缀品质插值的硬编码排除(与 A 是两套机制)
N231、234去重路径合并同类项时清空 NAME
G43UI 分组扫描跳过分组,见 CEffectDisplayMgr
R60accumMissileReflect单独累加通道
S62removeEffectsBySourceGuid按来源批量移除时被跳过
E166expireEffects过期处理特判

7.1 品质插值的完整门禁

CAffix__applyQualityPercentToEffects 里,一个效果要想被品质插值改写数值,得连过五道:

asm
007A4217  fld   dword ptr [ecx+0DCh]        ; MIN
007A421D  fcomp dword ptr [ecx+0E0h]        ; vs MAX
007A4228  jnp   loc_7A42AE                  ; ① MIN == MAX → 无区间,跳过
007A422E  xor   eax, eax
007A4230  lea   edx, [ecx+0F0h]
007A4236  cmp   dword ptr [edx], 0
007A4239  jnz   short loc_7A42AE            ; ② 五个槽任一被显式写过 → 跳过
007A423F  cmp   eax, 5
007A4242  jb    short loc_7A4236
007A4244  mov   eax, [ecx+1Ch]              ; 类型号
007A4247  cmp   g_EffectAffixModifies_239[eax], 0
007A424E  jz    short loc_7A42AE            ; ③ AFFIX_MODIFIES:false → 跳过
007A4250  cmp   eax, 3Bh
007A4253  jz    short loc_7A42AE            ; ④ 59  SCALE               → 跳过
007A4255  cmp   eax, 0A3h
007A425A  jz    short loc_7A42AE            ; ⑤ 163 DESTRUCTABLE SHIELD → 跳过
          ; 通过:值 = MIN + (MAX - MIN) × 品质百分比
007A4290  call  CEffect__setSlotAndReroll

第③道走数据(AFFIX_MODIFIES 列,共 4 行为 false),第④⑤道是写死的两个类型号。 所以一共 6 个类型的词缀数值不做品质插值,但成因分属两套机制,改数据只能影响其中 4 个。

8. 从未被使用的 16 行

原版用到 185/239 个类型,MOD 库用到 222/239,并集 223/239。 两边用量都为 0 的有 16 行:

#TYPE默认曲线描述串
9TO HIT BONUS四条全空
34PERCENT ITEM REQUIREMENTS%四条齐全
42PERCENT VIEW ANGLE BONUS%四条齐全
63VELOCITY MULT四条全空
130EMOTIONAL DAMAGE四条齐全
132JAUNTINESS四条齐全
133SOCKS四条齐全
134LOGIC RESISTANCE四条齐全
147ADD STAT TO LEVEL四条全空
149SET STAT ON LEVEL四条全空
151CLEAR STAT ON LEVEL四条全空
160SPAWN UNITBADDESBADDESOT
186TRANSFORMATION TIME四条齐全
187TRAP DISARM CHANCE四条齐全
208CAST SKILL ON RANGED SKILL STRIKE%四条齐全
238CHEATED四条齐全

其中 JAUNTINESS(轻快)、SOCKS(袜子)、LOGIC RESISTANCE(逻辑抗性)、EMOTIONAL DAMAGE(情感伤害)、CHEATED 明显是开发期的占位或玩笑行;TO HIT BONUSPERCENT ITEM REQUIREMENTSSPAWN UNIT 一类 则是有名有实、只是最终没进正式数据的功能。

NOTE

「从未使用」不等于「不可用」。这 16 行同样占着有效的类型号, NAME 也已进表,MOD 直接写它们的名字是能匹配上的。 但没有原版数据可参照,各槽的实际语义只能从引擎侧反推,风险自担。

9. 排错

9.1 TYPE 拼错会怎样:静默降级为第 193 行

匹配循环在 CEffect__ctorFromDat(函数起始 0x7AAA30):

asm
007AAB9E  call toUpperW                     ; dat 里的值先大写化
007AABBB  xor  ebx, ebx                     ; 候选行号 = 0
007AABBD  mov  ebp, offset g_EffectTypeNames_239
007AABC2  ...
007AABCB  call std::operator==<wchar_t>     ; 逐行比较
007AABD6  jnz  short loc_7AABE9             ; 命中
007AABD8  add  edi, 1Ch                     ; 下一行(wstring 步长 28)
007AABDB  inc  ebx
007AABDC  add  ebp, 1Ch
007AABDF  cmp  edi, 1A24h                   ; 0x1A24 = 239 × 28
007AABE5  jb   short loc_7AABC2
007AABE7  jmp  short loc_7AABEC             ; ← 全表未命中:直接跳过赋值
007AABE9  mov  [esi+1Ch], ebx               ; 命中才写类型号
007AABEC  mov  eax, [esi+1Ch]               ; 无论如何都要读它

未命中时 [esi+0x1C] 保持构造初值,而初值在同一函数开头就已定下:

asm
007AAA7E  mov  dword ptr [esi+1Ch], 0C1h    ; 0xC1 = 193

第 193 行是 NONE——TYPE:None、四个描述串全空、槽名全为 NA 的空操作行。

IMPORTANT

TYPE 写错不会报错、不会崩溃、也不会退化成第 0 行 MELEEDAMAGEBONUS, 而是静默变成第 193 行 NONE,即一个什么都不做、什么都不显示的空效果。

这是个体面的设计(比落到第 0 行白送近战伤害好得多),但对调试极不友好: 效果块语法完全合法、加载无声无息、游戏里就是不生效。

另需注意:NAME 列进表时没有做大写归一0x40113A 直接赋值,无 toUpperW), 而 dat 侧的 TYPE 值是大写化之后才比较的。 所以如果有人把 EFFECTSLIST.DAT 某行的 NAME 改成含小写字母的写法,那一行会就此永久失配。 原版 239 行的 NAME 全为大写、无空值、无重名,实测确认。

9.2 MOD 库里实测到的失效 TYPE

在 MOD 库的 200352 个效果块中,有 206 个块的 TYPE 对不上任何一行, 涉及 20 个不同的错误值。它们全部静默降级为 NONE

出现次数写成了大概想写的
66CAST SKILL ON KILL AT TARGECAST SKILL ON KILL AT TARGET(尾字母被截)
49PERCENT DAMAGEPERCENT DAMAGE BONUSPERCENT DAMAGE TAKEN
30PERCENT DEGRADE ARMOR无此行;应为 DEGRADE ARMORDEGRADE ARMOR EFFECT
28PHYSICALPHYSICAL DEFENSE
8POISONEDPOISON DEFENSE 一类
3DEXTERITYDEXTERITY BONUS
2MAGIC BONUSMAGIC
2CAST SKILL ON STRIKE ON STRIKECAST SKILL ON STRIKE(复制粘贴重复)
2SUMMONIU DURATIONSUMMON DURATION
2DESUMMONIU MONSTERDESUMMON MONSTER
2BLIND RESISTANCBLIND RESISTANCE
2AST SKILL ON RANGED STRIKECAST SKILL ON RANGED STRIKE(首字母被吞)
2VITALITY BONUS无此行
2(空串)——
1POSION DEFENSEPOISON DEFENSE
1ELECTRIC DEFENSEELECTRICAL DEFENSE
1CAST SKILL AFTER TIME无此行
1CUSTOM TEXT无此行
1STRENGTHSTRENGTH BONUS
1ATTACK SPEEDPERCENT ATTACK SPEED

SUMMONIUDESUMMONIU 这两个错法值得单说:它们是把 MON 误替换成 IU 的批量查找替换事故, 两处成对出现,说明出自同一次操作。

NOTE

原版数据里也有一处同类问题CAST SKILL AFTER TIME 在原版出现 1 次,同样对不上任何行。 这份 20 项清单可以直接当拼写检查表用——写完效果块,把 TYPE 的值拿去和第 6 节的对照表核一遍, 比在游戏里找一个「加载成功但毫无反应」的效果快得多。

9.3 其他常见误判

「我在 [EFFECT] 里写了 CHANCE,但没生效。」 查第 6 节该行的槽 0–4。CHANCE 只在 17 行上注册过,其余行写它等于写注释。

NOGRAPH:true 加了,MINMAX 还是不随机。」 只有第 3 节那 36 行有默认曲线,NOGRAPH 对它们之外的 203 行无作用; 数值不随机是别的原因(词缀场景下是品质插值,见 7.1 节)。

「改了 MINVALMAXVAL,游戏里数值没被限制住。」MINVAL 没有读取点,MAXVAL 只贡献符号。这两列限制不了任何东西(第 4 节)。 真想限制数值范围,得在写数据时自己控制。

「把某行的 TYPE 列从 Value 改成 Percent,显示没变。」 这两个值对引擎等价(5.1 节)。百分号在 GOODDES 等描述串里。

「往 EFFECTSLIST.DAT 末尾加了一行新类型。」 文件块数不再等于 239,加载器会打一条日志然后继续越界写(1.1 节)。 这不是「新类型不可用」,是内存损坏。

10. 速查

想知道看哪
某类型能写哪些数值键第 6 节该行的槽 0–4
某类型需不需要 NOGRAPH第 3 节的 36 行清单
某类型的 tooltip 为什么显示「坏」措辞4.1 节的四路选择表
某类型是否被硬编码特判第 6 节「特判」列 + 第 7 节
效果加载成功但毫无反应9.1 节(静默降级为 NONE)+ 9.2 节的错误值清单
为什么行序和行数都不能动1.1 节 + CEffect §8