请记住下面这行代码,很简单,这个的作用就是将DI寄存器的值设为0。
seg002:D33C 33 FF xor di, di
接下来的内容,我在请教,怎么修改三国志英杰传的基本策略伤害?这个帖子中的看到孝直和godtype两位前辈的回答,我把他俩回答贴一下。
原帖由
阿尔法孝直 于 2015-2-8 18:33 发表
从main.exe的0x30C5E开始:
30C5E:mov al, [si+0Bh] ;[si+0Bh]的高4位是策略类型,值为0=火,1=水,2=山;低4位是策略威力基数,值为0=低级策略(例如焦热、大漩涡),1=中级策略,2=高级策略
30C61:shr al, 4
30C64:sub ah, ah ;获得AX=策略类型
30C66:mov cl, [si+0Bh]
30C69:and cx, 0Fh ;获得CX=策略威力基数
30C6C:shl cx, 2
30C6F:add cx, ax
30C71:inc cx
30C72:inc cx
30C73:imul ax, cx, 100 ;结果是策略基本威力=(策略威力基数*4+2+策略类型)*100
30C76:mov [bp+var_8], ax
如果是焦热(或大焦热),策略类型=0,策略威力基数=0,策略基本威力=(0*4+2+0)*100=200
如果是海啸,策略类型=1,策略威力基数=2,策略基本威力=(2*4+2+1)*100=1100 ...
原帖由 godtype 于 2015-2-8 20:08 发表
0x30C5E 8A 44 0B mov al, [si+0Bh] ;[si+0Bh]的高4位是策略类型,值为0=火,1=水,2=山;低4位是策略威力基数,值为0=低级策略(例如焦热、大漩涡),1=中级策略,2=高级策略
0x30C61 C0 E8 04 shr al, 4
0x30C64 2A E4 sub ah, ah ;获得AX=策略类型
0x30C66 8A 4C 0B mov cl, [si+0Bh]
0x30C69 83 E1 0F and cx, 0Fh ;获得CX=策略威力基数
0x30C6C C1 E1 02 shl cx, 2
0x30C6F 03 C8 add cx, ax
0x30C71 41 inc cx
0x30C72 41 inc cx
0x30C73 6B C1 64 imul ax, cx, 64 ;结果是策略基本威力=(策略威力基数*4+2+策略类型)*100
其实就是代码中seg002: D33E-D353的内容,最后将这个结果保存到var_8中,当时就是看到俩位的回答,就在此基础上反向查找,找到了计算si+0B的过程也就是上2节的介绍的。
seg002:D33E 8A 44 0B mov al, [si+0Bh] ; [si+0Bh]的高4位是策略的类型, 0火, 1水, 2山
seg002:D33E ; 低4位是策略指向范围
seg002:D341 C0 E8 04 shr al, 4
seg002:D344 2A E4 sub ah, ah
seg002:D346 8A 4C 0B mov cl, [si+0Bh]
seg002:D349 83 E1 0F and cx, 0Fh
seg002:D34C C1 E1 02 shl cx, 2
seg002:D34F 03 C8 add cx, ax
seg002:D351 41 inc cx
seg002:D352 41 inc cx
seg002:D353 6B C1 64 imul ax, cx, 100 ; 策略基本威力=(策略指向范围*4+2+策略类型)*100
seg002:D356 89 46 F8 mov [bp+var_8], ax
接下来是一个判断,就是根据si+0A判断使用的道具还是策略,使用的道具就跳到seg002: D39F,seg002: D35F-D39D的内容就是计算行动方的策略能力,因为道具的公式不包括行动方的策略能力所以跳过了。
seg002:D359 80 7C 0A 02 cmp byte ptr [si+0Ah], 2 ; 判断是使用策略还是道具
seg002:D35D 75 40 jnz short loc_3A2BF
然后就是计算-目标方的策略能力,并且将最终保存在var_C,var_A中,这个结果也称为伤害(无随机结果),可以看到seg002: D3C9是di-目标方的策略能力,由于前面di设为0,所以这步的结果肯定是个负数。
seg002:D39F loc_3A2BF: ; CODE XREF: sub_3A060+21D↑j
seg002:D39F 8A 5C 09 mov bl, [si+9]
seg002:D3A2 2A FF sub bh, bh
seg002:D3A4 03 DB add bx, bx
seg002:D3A6 FF 70 04 push word ptr [bx+si+4]
seg002:D3A9 89 5E E0 mov [bp+var_20], bx
seg002:D3AC 9A DA 6A F6 1C call sub_23A3A ; 获取目标方的等级
seg002:D3B1 8B 5E E0 mov bx, [bp+var_20]
seg002:D3B4 FF 70 04 push word ptr [bx+si+4]
seg002:D3B7 89 46 DE mov [bp+var_22], ax
seg002:D3BA 9A 90 C5 F6 1C call sub_294F0
seg002:D3BF F6 66 DE mul byte ptr [bp+var_22]
seg002:D3C2 B9 32 00 mov cx, 50
seg002:D3C5 2B D2 sub dx, dx
seg002:D3C7 F7 F1 div cx ; 等级*智力÷50
seg002:D3C9 2B F8 sub di, ax ; di-等级*智力÷50
seg002:D3CB 8B 5E E0 mov bx, [bp+var_20]
seg002:D3CE FF 70 04 push word ptr [bx+si+4]
seg002:D3D1 9A 90 C5 F6 1C call sub_294F0
seg002:D3D6 2A E4 sub ah, ah
seg002:D3D8 2B F8 sub di, ax ; di-智力
seg002:D3DA 03 7E F8 add di, [bp+var_8] ; di+策略基本威力
seg002:D3DD 89 7E F4 mov [bp+var_C], di
seg002:D3E0 C7 46 F6 00 00 mov [bp+var_A], 0
接下来就是伤害计算中第一次随机数消耗可以看到,虽然道具是百分之百命中的,但像前面计算行动方策略命中一样,仍然产生了随机数消耗,有可能一开始游戏的设计中并没有规定道具是百分之百命中的。
seg002:D3E5 8B 46 FA mov ax, word ptr [bp+var_6] ; 行动方策略命中
seg002:D3E8 9A E0 3D F6 1C call sub_20D40 ; 策略命中随机数
seg002:D3ED 88 46 FD mov [bp+var_3], al
seg002: D3F0-D448的内容是判断目标方是否是文官(军乐队/运输队/妖术师,策略闪避*2,伤害÷2),判断是否要增加四分之一的伤害(火道具目标方在森林,水道具雨天),后续会介绍。
然后就是第二次随机数消耗,可以看到是先消耗策略命中随机数,再消耗道具伤害随机数。如果道具伤害小于50,并不会消耗道具伤害随机数,如果道具伤害大于等于50且小于100,虽然结果必然是0,但是也消耗了随机数。随后将伤害随机数与道具伤害(无随机结果)相加,最终结果的结果就是有伤害的。
seg002:D44B 8B 46 F4 mov ax, [bp+var_C]
seg002:D44E B9 32 00 mov cx, 50
seg002:D451 2B D2 sub dx, dx
seg002:D453 F7 F1 div cx
seg002:D455 9A E0 3D F6 1C call sub_20D40 ; 道具伤害随机数
seg002:D45A 2B D2 sub dx, dx
seg002:D45C 01 46 F4 add [bp+var_C], ax
seg002:D45F 11 56 F6 adc [bp+var_A], dx
最后是一个伤害与目标方兵力的比较,防止伤害超出目标方兵力,如果伤害超出目标方兵力,将最终伤害修改为目标方兵力,将最终伤害保存在si+1F中。
seg002:D477 FF 76 F6 push [bp+var_A]
seg002:D47A FF 76 F4 push [bp+var_C]
seg002:D47D 8A 5C 09 mov bl, [si+9]
seg002:D480 2A FF sub bh, bh
seg002:D482 03 DB add bx, bx
seg002:D484 2B D2 sub dx, dx
seg002:D486 8B 40 0F mov ax, [bx+si+0Fh] ; 目标方兵力
seg002:D489 9A 44 3C F6 1C call sub_20BA4
seg002:D48E 89 44 1F mov [si+1Fh], ax
这便是道具伤害的完整计算过程,这其中的计算又有怎样的问题,为什么会导致焦热书秒杀的BUG,下一节再重新回顾整个过程,找出BUG的根源在哪里。
[ 本帖最后由 漫漫苦短 于 2026-5-19 20:52 编辑 ]