|  增加兵种相克的新思路 
 
 关于增加兵种相克的方法目前都是通过语句跳转到空白处来增加,这样的方法对于少量的相克关系尚可应付,但如果需要设置大量的相克关系,就非常不利于代码修改和维护,而且写出的代码的可读性极差,一旦以后又需要要增加新的兵种相克,又需要重新书写代码,修改和重写代码的工作量相当大。为了较好的解决这个问题,我通过反复测试,终于发现可以使用使用27*27=729共字节设置一个兵种相克表,再利用查表的方法来设置兵种相克,这样可以随意设置兵种相克,相当方便,现在把方法公布,希望能对大家有所帮助。
 以下代码和说明均以我发布的exe第四版为例。
 
 在CCZ原版exe中,兵种相克关系是在函数43BC4B中设置的,同时这个函数还有一些宝物的处理代码,比如减轻远距伤害,骑马攻击等,在我发布的exe第四版里,这个函数的地址没变,但新增了破甲攻击和减轻物理伤害的效果
 
 下面是我改写过的代码:(由于代码较多,只帖出了修改过的地方)
 
 0043BC4B      55            PUSH EBP                             '函数开始
 0043BC4C      8BEC          MOV EBP,ESP
 0043BC4E      83EC 3C       SUB ESP,3C
 .
 .
 .
 0043BC76     /E9 76020000   JMP 0043BEF1
 .
 .
 .
 0043BD06     /E9 E6010000   JMP 0043BEF1
 .
 .
 .
 0043BD5F  |.  E8 0CF7FFFF   CALL Ekd5.0043B470                                        ;  取得攻击方兵种
 0043BD64  |.  25 FF000000   AND EAX,0FF
 0043BD69  |.  6BC0 1B       IMUL EAX,EAX,1B                                               ;  攻击方兵种*1B(27) 这句是重点 确定某个兵种的查表开始位置
 0043BD6C  |.  33C9          XOR ECX,ECX
 0043BD6E  |.  33D2          XOR EDX,EDX
 0043BD70  |.  8A4D EC       MOV CL,BYTE PTR SS:[EBP-14]                           ;  被攻击方兵种
 0043BD73  |.  8A9408 D7094D>MOV DL,BYTE PTR DS:[EAX+ECX+4D09D7]     ;  通过查表得到伤害系数  4D09D7是相克表开始处
 0043BD7A  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]                              ;  伤害值入栈
 0043BD7D  |.  52            PUSH EDX                                                            ;  伤害系数入栈
 0043BD7E  |.  E8 74010000   CALL Ekd5.0043BEF7                                       ;  调用自定义函数 重新计算伤害
 0043BD83  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX                        ;  保存重新计算后的伤害值
 0043BD86  |.  8B4D D4       MOV ECX,DWORD PTR SS:[EBP-2C]                      ;  取出攻击方内存 4B****
 0043BD89  |.  E8 CF420000   CALL Ekd5.0044005D                                       ;  判断攻击方是否为远程兵种
 0043BD8E  |.  84C0          TEST AL,AL
 0043BD90  |.  74 2E         JE SHORT Ekd5.0043BDC0                                    ;  不是远程 跳转
 0043BD92  |.  6A 3D         PUSH 3D                                                            ; /这里开始检查被攻击方是否有降低远程伤害的道具
 0043BD94  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
 0043BD97  |.  E8 6DBCFCFF   CALL Ekd5.00407A09                                        ; \Ekd5.00407A09
 0043BD9C  |.  85C0          TEST EAX,EAX
 0043BD9E  |.  74 20         JE SHORT Ekd5.0043BDC0                                    ;  没有装备 跳转
 0043BDA0  |.  6A 3D         PUSH 3D                                 ; /Arg1 = 0000003D
 0043BDA2  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]            ; |
 0043BDA5  |.  E8 48BDFCFF   CALL Ekd5.00407AF2                                        ; \如果有装备 取得特殊效果值
 0043BDAA  |.  25 FF000000   AND EAX,0FF
 0043BDAF  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]
 0043BDB2  |.  50            PUSH EAX
 0043BDB3  |.  E8 3F010000   CALL Ekd5.0043BEF7                                        ;  自定义函数 计算能降低多少伤害
 0043BDB8  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
 0043BDBB  |.  2BD0          SUB EDX,EAX                             ;  减法
 0043BDBD  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX                     ;  保存降低后的伤害
 0043BDC0  |>  837D FC 00    CMP DWORD PTR SS:[EBP-4],0
 0043BDC4  |.  75 07         JNZ SHORT Ekd5.0043BDCD
 0043BDC6  |.  C745 FC 01000>MOV DWORD PTR SS:[EBP-4],1
 0043BDCD  |>  FF75 D4       PUSH DWORD PTR SS:[EBP-2C]
 0043BDD0  |.  FF75 DC       PUSH DWORD PTR SS:[EBP-24]
 0043BDD3  |.  6A 00         PUSH 0
 0043BDD5  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
 0043BDD8  |.  E8 8F52FDFF   CALL Ekd5.0041106C                                        ;  这个是原来的骑马攻击,现在是加强攻击
 0043BDDD  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX
 0043BDE0  |.  6A 2C         PUSH 2C                                                            ; /这个是减轻物理伤害
 0043BDE2  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]                     ; |
 0043BDE5  |.  E8 1FBCFCFF   CALL Ekd5.00407A09                                        ; \Ekd5.00407A09
 0043BDEA  |.  85C0          TEST EAX,EAX
 0043BDEC  |.  74 20         JE SHORT Ekd5.0043BE0E
 0043BDEE  |.  6A 2C         PUSH 2C                                 ; /Arg1 = 0000002C
 0043BDF0  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]            ; |
 0043BDF3  |.  E8 FABCFCFF   CALL Ekd5.00407AF2                      ; \Ekd5.00407AF2
 0043BDF8  |.  25 FF000000   AND EAX,0FF
 0043BDFD  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]
 0043BE00  |.  50            PUSH EAX
 0043BE01  |.  E8 F1000000   CALL Ekd5.0043BEF7                                          ;  自定义函数 计算能降低多少伤害
 0043BE06  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
 0043BE09  |.  2BD0          SUB EDX,EAX
 0043BE0B  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX
 0043BE0E  |>  837D 10 00    CMP DWORD PTR SS:[EBP+10],0
 0043BE12  |.  74 29         JE SHORT Ekd5.0043BE3D
 0043BE14  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
 0043BE17  |.  6BC0 03       IMUL EAX,EAX,3
 0043BE1A  |.  C1E8 02       SHR EAX,2
 0043BE1D  |.  83F8 01       CMP EAX,1
 0043BE20  |.  73 09         JNB SHORT Ekd5.0043BE2B
 0043BE22  |.  C745 C8 01000>MOV DWORD PTR SS:[EBP-38],1
 0043BE29  |.  EB 0C         JMP SHORT Ekd5.0043BE37
 0043BE2B  |>  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
 0043BE2E  |.  6BC9 03       IMUL ECX,ECX,3
 0043BE31  |.  C1E9 02       SHR ECX,2
 0043BE34  |.  894D C8       MOV DWORD PTR SS:[EBP-38],ECX
 0043BE37  |>  8B55 C8       MOV EDX,DWORD PTR SS:[EBP-38]
 0043BE3A  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX
 0043BE3D  |>  8B4D D4       MOV ECX,DWORD PTR SS:[EBP-2C]
 0043BE40  |.  E8 7B4B0900   CALL Ekd5.004D09C0                      ;  这里又是一个自定义函数 由4b****得到D6**** 很多地方要用到这个函数的代码,所以弄出来单独写了一个函数  传入ecx--传出ecx
 0043BE45  |.  894D F8       MOV DWORD PTR SS:[EBP-8],ECX
 0043BE48  |.  6A 17         PUSH 17                                          ; /这里是破甲攻击
 0043BE4A  |.  E8 BABBFCFF   CALL Ekd5.00407A09                      ; \Ekd5.00407A09
 0043BE4F  |.  85C0          TEST EAX,EAX
 0043BE51  |.  74 30         JE SHORT Ekd5.0043BE83
 0043BE53  |.  6A 17         PUSH 17                                 ; /Arg1 = 00000017
 0043BE55  |.  8B4D F8       MOV ECX,DWORD PTR SS:[EBP-8]            ; |
 0043BE58  |.  E8 95BCFCFF   CALL Ekd5.00407AF2                      ; \Ekd5.00407AF2
 0043BE5D  |.  33C9          XOR ECX,ECX
 0043BE5F  |.  8AC8          MOV CL,AL
 0043BE61  |.  894D FC       MOV DWORD PTR SS:[EBP-4],ECX
 0043BE64  |.  803D 70234600>CMP BYTE PTR DS:[462370],1                       ;  如果462370 为1 就是固定伤害
 0043BE6B  |.  74 69         JE SHORT Ekd5.0043BED6
 0043BE6D  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]                     ;  否则为百分数伤害
 0043BE70  |.  E8 B7B3FCFF   CALL Ekd5.0040722C
 0043BE75  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]
 0043BE78  |.  50              PUSH EAX
 0043BE79  |.  E8 79000000   CALL Ekd5.0043BEF7                                     ; 当破甲攻击为百分数伤害时,再次调用自定义函数
 0043BE7E  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
 0043BE81  |.  EB 53         JMP SHORT Ekd5.0043BED6
 0043BE83  |>  837D 0C 00    CMP DWORD PTR SS:[EBP+C],0
 0043BE87  |.  74 4D         JE SHORT Ekd5.0043BED6
 0043BE89  |.  6A 07         PUSH 7                                  ; /Arg1 = 00000007
 0043BE8B  |.  E8 833C0400   CALL Ekd5.0047FB13                      ; \Ekd5.0047FB13
 0043BE90  |.  83C4 04       ADD ESP,4
 0043BE93  |.  8945 D8       MOV DWORD PTR SS:[EBP-28],EAX
 0043BE96  |.  83F8 02       CMP EAX,2
 0043BE99  |.  76 0F         JBE SHORT Ekd5.0043BEAA
 0043BE9B  |.  8B45 D8       MOV EAX,DWORD PTR SS:[EBP-28]
 0043BE9E  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
 0043BEA1  |.  8D5401 FE     LEA EDX,DWORD PTR DS:[ECX+EAX-2]
 0043BEA5  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX
 0043BEA8  |.  EB 2C         JMP SHORT Ekd5.0043BED6
 0043BEAA  |>  FF75 D8       PUSH DWORD PTR SS:[EBP-28]              ; /Arg2
 0043BEAD  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]               ; |Arg1
 0043BEB0  |.  E8 E93B0400   CALL Ekd5.0047FA9E                      ; \Ekd5.0047FA9E
 0043BEB5  |.  83C4 08       ADD ESP,8
 0043BEB8  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
 0043BEBB  |.  837D FC 00    CMP DWORD PTR SS:[EBP-4],0
 0043BEBF  |.  75 09         JNZ SHORT Ekd5.0043BECA
 0043BEC1  |.  C745 C4 01000>MOV DWORD PTR SS:[EBP-3C],1
 0043BEC8  |.  EB 06         JMP SHORT Ekd5.0043BED0
 0043BECA  |>  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
 0043BECD  |.  8955 C4       MOV DWORD PTR SS:[EBP-3C],EDX
 0043BED0  |>  8B45 C4       MOV EAX,DWORD PTR SS:[EBP-3C]
 0043BED3  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
 0043BED6  |>  8B4D DC       MOV ECX,DWORD PTR SS:[EBP-24]
 0043BED9  |.  E8 B26D0300   CALL Ekd5.00472C90
 0043BEDE  |.  3945 FC       CMP DWORD PTR SS:[EBP-4],EAX
 0043BEE1  |.  76 0B         JBE SHORT Ekd5.0043BEEE
 0043BEE3  |.  8B4D DC       MOV ECX,DWORD PTR SS:[EBP-24]
 0043BEE6  |.  E8 A56D0300   CALL Ekd5.00472C90
 0043BEEB  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
 0043BEEE  |>  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
 0043BEF1  |>  8BE5          MOV ESP,EBP
 0043BEF3  |.  5D            POP EBP
 0043BEF4  \.  C2 0C00       RETN 0C
 
 上面的代码都加了注释,最关键的地方就是 0043BD5F 到0043BD83之间的代码
 
 
 0043BEF7  /$  55            PUSH EBP                                                 ;重新计算伤害的自定义函数,上面的代码共调用此函数4次
 0043BEF8  |.  8BEC          MOV EBP,ESP
 0043BEFA  |.  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]            ;  取出伤害值
 0043BEFD  |.  8B55 08       MOV EDX,DWORD PTR SS:[EBP+8]            ;  取出伤害系数
 0043BF00  |.  0FAFC2        IMUL EAX,EDX
 0043BF03  |.  33D2          XOR EDX,EDX
 0043BF05  |.  8BCA          MOV ECX,EDX
 0043BF07  |.  B1 64         MOV CL,64
 0043BF09  |.  F7F1          DIV ECX
 0043BF0B  |.  8BE5          MOV ESP,EBP
 0043BF0D  |.  5D            POP EBP
 0043BF0E  \.  C3            RETN                                    ;  计算后的伤害值在eax中 返回
 
 PS:在上面的代码中,每一行中间的部分就是UE代码,只会用UE的朋友也能自己修改,这里的UE 地址=OB地址-400C00
 例如这个自定义函数的UE地址就是43BEF7-400C00=3B2F7,从这个位置开始把 55 8B EC 8B 45 0C... 等代码写入exe就行了
 
 从这个函数可以看出兵种相克是按百分数来计算的,也就是说如果要设置为正常伤害,就要设置相应的相克系数为64(100)。利用这个信息就可以设置相克表了
 
 相克表的设置其实相当简单,先找27*27=729字节的空间,我现在使用了4D09D7--4D0CAF处的位置(UE地址 A1DD7--A20AF,这里UE地址=OB地址-42EC00),首先把这里的数据全部设为64,这样所有兵种间就是正常伤害了。
 
 下面用两个例子说明这个表的设置方法:
 
 首先一个要注意的是设置这个表应按16进制数来使用
 
 在ccz原版有几个兵种相克,以步兵对骑兵60%的伤害为例
 
 我们知道步兵的职业号是01(注意这里要使用16进制数据),而ccz共有27(1B)个职业。那么步兵系对其他兵种的伤害系数的地址就是从  (01×1B)+4d09d7=4D09F2开始
 
 骑兵系的职业号是03,这样我们就得到了步兵对骑兵的伤害系数的地址: (01×1b)+4d09d7+03=4D09F5,下面只要把这个地址的值改为3C(60)即可。
 
 
 以弓兵对骑兵150%的伤害为例
 弓兵的职业号是02,用上面的方法得到弓兵对骑兵的伤害系数的地址: (02×1B)+4d09d7+03=4D0A10,把这个地址的值改为96(150)即可。
 
 用这个方法我们就可以随意修改兵种相克了,彻底告别以前的那种复杂的设置方法,只会用Ue的朋友也可以方便的改出自己需要的兵种相克了。
 
 [ 本帖最后由 star175 于 2008-6-6 20:35 编辑 ]
 
 |