增加兵种相克的新思路
关于增加兵种相克的方法目前都是通过语句跳转到空白处来增加,这样的方法对于少量的相克关系尚可应付,但如果需要设置大量的相克关系,就非常不利于代码修改和维护,而且写出的代码的可读性极差,一旦以后又需要要增加新的兵种相克,又需要重新书写代码,修改和重写代码的工作量相当大。为了较好的解决这个问题,我通过反复测试,终于发现可以使用使用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 编辑 ] | |