轩辕春秋文化论坛 » 曹操传MOD制作交流 » 增加兵种相克的新思路


2008-6-6 20:28 star175
增加兵种相克的新思路

关于增加兵种相克的方法目前都是通过语句跳转到空白处来增加,这样的方法对于少量的相克关系尚可应付,但如果需要设置大量的相克关系,就非常不利于代码修改和维护,而且写出的代码的可读性极差,一旦以后又需要要增加新的兵种相克,又需要重新书写代码,修改和重写代码的工作量相当大。为了较好的解决这个问题,我通过反复测试,终于发现可以使用使用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
[color=red]0043BD69  |.  6BC0 1B       IMUL EAX,EAX,1B                                               ;  攻击方兵种*1B(27) 这句是重点 确定某个兵种的查表开始位置
[/color]0043BD6C  |.  33C9          XOR ECX,ECX
0043BD6E  |.  33D2          XOR EDX,EDX
0043BD70  |.  8A4D EC       MOV CL,BYTE PTR SS:[EBP-14]                           ;  被攻击方兵种
[color=red]0043BD73  |.  8A9408 D7094D>MOV DL,BYTE PTR DS:[EAX+ECX+4D09D7]     ;  通过查表得到伤害系数  4D09D7是相克表开始处
[/color]0043BD7A  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]                              ;  伤害值入栈
0043BD7D  |.  52            PUSH EDX                                                            ;  伤害系数入栈
[color=blue]0043BD7E  |.  E8 74010000   CALL Ekd5.0043BEF7                                       ;  调用自定义函数 重新计算伤害
[/color]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
[color=blue]0043BDB3  |.  E8 3F010000   CALL Ekd5.0043BEF7                                        ;  自定义函数 计算能降低多少伤害
[/color]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
[color=blue]0043BE01  |.  E8 F1000000   CALL Ekd5.0043BEF7                                          ;  自定义函数 计算能降低多少伤害
[/color]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
[color=blue]0043BE79  |.  E8 79000000   CALL Ekd5.0043BEF7                                    [/color][color=blue] ; 当破甲攻击为百分数伤害时,再次调用自定义函数[/color][color=#333333]
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[/color]

上面的代码都加了注释,最关键的地方就是 0043BD5F 到0043BD83之间的代码


[color=blue]0043BEF7  /$  55            PUSH EBP                                                 ;重新计算伤害的自定义函数,上面的代码共调用此函数4次
[/color]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
[color=blue]0043BF0E  \.  C3            RETN                                    ;  计算后的伤害值在eax中 返回[/color]

[color=red][b]PS:在上面的代码中,每一行中间的部分就是UE代码,只会用UE的朋友也能自己修改,这里的UE 地址=OB地址-400C00[/b][/color]
[color=#ff0000][b]例如这个自定义函数的UE地址就是43BEF7-400C00=3B2F7,从这个位置开始把 55 8B EC 8B 45 0C... 等代码写入exe就行了[/b][/color]

从这个函数可以看出兵种相克是按百分数来计算的,也就是说如果要设置为正常伤害,就要设置相应的相克系数为64(100)。利用这个信息就可以设置相克表了

相克表的设置其实相当简单,先找27*27=729字节的空间,我现在使用了4D09D7--4D0CAF处的位置([color=blue]UE地址 A1DD7--A20AF,这里UE地址=OB地址-42EC00[/color]),首先把这里的数据全部设为64,这样所有兵种间就是正常伤害了。

下面用两个例子说明这个表的设置方法:

[color=red]首先一个要注意的是设置这个表应按16进制数来使用[/color]
[color=#ff0000][/color]
在ccz原版有几个兵种相克,以步兵对骑兵60%的伤害为例

我们知道步兵的职业号是01([color=red]注意这里要使用16进制数据[/color]),而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的朋友也可以方便的改出自己需要的兵种相克了。

[[i] 本帖最后由 star175 于 2008-6-6 20:35 编辑 [/i]]

2008-6-6 20:37 周瑜
貌似我就是这么做的,而且用的是一个字节表示两个相克的方法,可以节省一半空间,不过被克兵种数要是偶数才行。

2008-6-6 20:51 hhccz
看不懂。:q(+  还是支持,周大降临了。:wub:

2008-6-6 21:21 colalove12
强大啊~~~完全看不懂,看来只能做伸手党了

2008-6-6 22:09 godtype
终于发布出来了,昨天听你说过之后,我也尝试写了一段新代码,不过看完你这个之后,比我新写的要好得多呀,还是用你这个好。
另外想问一下,为什么破甲攻击要调用一次那个函数?

[[i] 本帖最后由 godtype 于 2008-6-6 22:13 编辑 [/i]]

2008-6-6 23:23 star175
回复 #5 godtype 的帖子

我的目的是要把这个自定义函数变为一个标准的通用函数,凡是需要计算百分数的地方都能使用这个函数,其实在exe中有很多类似的地方,只要重新设置一下两个入栈参数,都能直接调用这个函数,这样即节省空间,也便于代码维护

但破甲攻击为百分数伤害时完全可以适用这个函数

2008-6-7 00:28 godtype
0043BD69  |.  6BC0 1B       IMUL EAX,EAX,1B

0043BD73  |.  8A9408 D7094D>MOV DL,BYTE PTR DS:[EAX+ECX+4D09D7]

个人认为将上面的1B改成20,4D09D7改成4D09E0,相克表也改成从4D09E0开始,会适合一些用UE且比较懒和不想慢慢数数的人(例如本人)。
虽然这样会增加不少字节(5*27),而且每一个兵种的相克表最后5个字节变成无意义,但是这样就可以令到每一个兵种的相克表都是从A***0开始,例如00兵种从A1DE0开始,01兵种从A1E00开始……方便了用UE且比较懒和不想慢慢数数的人(再次例如本人)。而且我还喜欢将最后5个字节改成3030909090、3031909090等等,都是为了方便修改而已。

2008-6-7 15:07 paro
技术上又进了一步,呵呵!

2008-6-7 19:07 37610716
主要是不知道地址重复了没!

2008-6-7 20:15 godtype
回复 #9 37610716 的帖子

放心按教程改吧,没有重复的。

2008-6-8 03:46 天翼之神
又有个新的了, 我来看看.

2008-6-9 15:38 kaopamao
好深奥哦!!不过希望你们越做越好!永远支持创作者!!!!

2008-6-9 16:21 子·房
不是新人能看懂的

2008-6-18 18:06 三国赤壁周郎
这个设想不错,支持!

2010-6-18 08:24 513633522
:hz1017:收下仔细看吧……不是一天两天能学会的

页: [1]
查看完整版本: 增加兵种相克的新思路


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.