核心定位: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×2390x40113A0x7AABBD、0x531D74、0x7A4C09、0x7C8FAA
VALUE1–VALUE5<STRING>g_EffectParamNames_239x50x28AABA0wstring[239][5]0x4012F1 起0x7A5F46(CEffect__readValueSlot)
GRAPH1、GRAPH2<STRING>g_EffectGraphNames_239x50x28B2E58wstring[239][5]0x4014AA、0x4015030x7A606E(CEffect__bindGraphs)
TYPE<STRING>g_EffectDisplayKind_2390x28A1D80int×2390x401792、0x4017B70x7A71D4
MINVAL<INTEGER>g_EffectMinVal_2390x28A2500int×2390x4017FD无
MAXVAL<INTEGER>g_EffectMaxVal_2390x28A2140int×2390x4018570x7A71FD
DISPLAYPRECISION<INTEGER>dword_28A19C00x28A19C0int×2390x4016670x7A7237、0x7A727B、0x7A7318
DISPLAYPRECISIONMAXVAL<FLOAT>flt_28A16000x28A1600float×2390x4016B70x7A7229、0x7A7274、0x7A730E
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

这道校验只写日志,不截断,也不中止加载。 紧接着的填表循环(0x401100–0x40188D)用的上界是 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 到不了的那些行保持空 wstring,NAME 为空串。 由于 [EFFECT] 块的 TYPE 是拿大写化后的值去和 NAME 逐个比较(见 9.1 节), 空 NAME 永远匹配不上,这些类型号就此全部失效。
  • 多于 239 行:esi 与 ebp 继续往后走,越界写进紧邻的全局数组。 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__readValueSlot(0x7A5F46), 它按 CEffect+0x1C(类型号)与槽号取出别名字符串,再拿这个别名去 [EFFECT] 块里查键。

IMPORTANT

[EFFECT] 块里能写哪些数值键,完全由这张表该行的 VALUE1–VALUE5 决定。 比如第 55 行 CRITICAL CHANCE 的槽名是 MIN/MAX/NA/NA/NA, 那么 <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

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

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

g_EffectGraphNames_239x5(0x28B2E58)与槽名表同构——同样 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 里根本不存在 GRAPH3/GRAPH4/GRAPH5 这三个键(全表 19 个键,已在第 1 节列全)。

NOTE

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

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

#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 才能让 MIN~MAX 退化成真随机。 其余 203 行没有默认曲线,NOGRAPH 写与不写没有区别。 把这条规律说成「MIN~MAX 随机需要 NOGRAPH」是过度推广。

4. MINVAL 与 MAXVAL:一列是死数据,一列只贡献符号 ​

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

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

  • g_EffectMinVal_239(0x28A2500)全程出现 1 次,就是加载器 0x4017FD 的那次写入。 没有任何读取点。MINVAL 是一列纯粹的死数据。
  • g_EffectMaxVal_239(0x28A2140)出现 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, 44h + jnp 是 MSVC 的浮点相等判定惯用式:fucom 相等时置 C3,ah & 0x44 == 0x40, 奇校验使 PF = 0,于是 jnp 在相等时跳转。)

四路选择在 0x7A7371–0x7A73D8:

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:-100 / MAXVAL:100。剩下 19 行如下, 其中 4 行的 MAXVAL 为负——这正是「数值越低越好」的属性,符号翻转后 Sign 判定才正确:

#TYPE 名MINVALMAXVALMAXVAL 符号 → 好的方向
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:20 / MAXVAL:-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

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

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

5.2 精度两列 ​

DISPLAYPRECISION(0x28A19C0,int)与 DISPLAYPRECISIONMAXVAL(0x28A1600,float) 成对传给同一个格式化函数 sub_7A6760,在 build_tooltip_desc 里被调用四次 (0x7A7269、0x7A72C3、0x7A7303,以及 0x7A733F 之后一处), 分别对应「数值」「上限数值」「时长」「区间上界」四个待排版的数字。

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

#TYPE 名DISPLAYPRECISION
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 —— 该行 VALUE1–VALUE5 注册的键名;· 表示该槽写的是占位值 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_BODY无2712426
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 CHANCEMINMAXMINFORCEMAXFORCECHANCE值DAMAGE_MONSTERX16703
157TELEPORT RANDOMCHANCE·MINRANGEMAXRANGECOOLDOWN值11198
158TELEPORTCHANCE·MINRANGEMAXRANGECOOLDOWN值68
159TELEPORT RESISTANCEMINMAX···值439
160SPAWN UNITCOUNT·CHANCEMINRANGEMAXRANGE值··
161SPAWN UNIT ON DEATHCOUNTHPPCTCHANCEMINRANGEMAXRANGE值A1110
162WARP TO POIPOI····无22
163DESTRUCTABLE SHIELDHP%HPOVERRIDEANGLEOFFSETDESTROY_WEAPONS值Q32175
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_AT值A3411434
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_TARGETS值HEALTH_PLAYER_GENERIC10208
230DRAW MANAMIN_PER_MANAMAX_PER_MANAPULSE_RATERADIUSMAX_TARGETS值MANA_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·MINRANGEMAXRANGECOOLDOWN值149
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、1630x7A4250、0x7A4255词缀品质插值的硬编码排除(与 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 UNIT值—缺 BADDES、BADDESOT
186TRANSFORMATION TIME值—四条齐全
187TRAP DISARM CHANCE值—四条齐全
208CAST SKILL ON RANGED SKILL STRIKE%—四条齐全
238CHEATED值—四条齐全

其中 JAUNTINESS(轻快)、SOCKS(袜子)、LOGIC RESISTANCE(逻辑抗性)、EMOTIONAL DAMAGE(情感伤害)、CHEATED 明显是开发期的占位或玩笑行;TO HIT BONUS、PERCENT ITEM REQUIREMENTS、SPAWN 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 BONUS 或 PERCENT DAMAGE TAKEN
30PERCENT DEGRADE ARMOR无此行;应为 DEGRADE ARMOR 或 DEGRADE 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

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

NOTE

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

9.3 其他常见误判 ​

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

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

「改了 MINVAL/MAXVAL,游戏里数值没被限制住。」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