Board logo

标题: 泛谈曹操传剧本 [打印本页]

作者: 岱瀛    时间: 2006-8-8 23:40     标题: 泛谈曹操传剧本

泛谈曹操传剧本的编写(序言)
所谓泛谈,就是泛泛而谈,大概接近于灌水,本文不会针对一个多具体的剧本编写去讲,也不会针对多具体的一条新指令的写法就描述,只是泛泛而谈,但求能给读者一点启发,依靠大家的智慧,由此变幻出无数奇妙的剧本,由此变化出无数的新剧本指令。
或许上篇更适合于MOD区,下篇才合适设计区,不过不想开两贴,这上下二篇就合并于此吧。
打破常规,发挥个人的主观能动性,是本文上下篇都贯穿的一个主体思维,因为确实最近在MOD区,MOD不少,却少有新意的MOD,比如胡不愁版有单挑随机结果,比如月月的那个MOD有雇佣兵的,都是一种创新,但是其他更多MOD则归于技术上的平淡,其实说岳的评分也是一个很好的创新,还有利用R形象作出的数字评分,更是一种天才的想象,遗憾的是,其他MOD的创新就少了。隋唐其实创新有很多,不过从仓促的5.1版中很难见到其特点,或许下一版才能给世人以震撼吧。
而下篇所言的修改剧本指令达到更高境界的创新的,目前似乎除了说岳和隋唐,已经没有任何MOD做到这点了,其实剧本指令的汇编代码很有相似性,规律单一,又方便调试,只要懂一点点汇编的朋友,都能玩出自己的花活,重要的是每个人自己的智慧。
打开每个人的智慧之门,创造一个一个MOD神话,必胜必胜必必胜。
作者: 岱瀛    时间: 2006-8-8 23:41     标题: 回复 #1 岱瀛 的帖子

泛谈曹操传剧本的编写(上篇)

曹操传的剧本,分为以剧情为主的R剧本和以战斗为主的S剧本,这已经是路人皆知道的事情了,曹操剧本的指令,总共有108条指令。要知道,C语言也才30几个关键字,却能作为一门计算机语言,编写出无数的五花八门的程序,那么凭着这108条指令,有什么理由说不能编写出各色各样的剧本呢?
不要墨守曹操传的剧本形式,不要看了几篇RS文件编写的文章就说能写RS剧本了,重要的是,你如何去发挥这108条指令,编写出你心中想到的东西,而不是你见过某某人这样做过,我要怎么样才能和他一样。
108条指令足够玩出你想玩的花样,只要你真正的去想,去用,而不是照帮某个人的剧本文件去套格式,只有你忘记了所有的条条框框,以我为主,以我的思考为主,然后去用,去探索,多不可能的事情都有可能成真。
那么,为什么说这108条指令有那么大的作用呢?首先我们从大的结构上来看。过去面向结构的编程语言里有三种经典的结构,顺序结构,分支结构和循环结构。而正巧,RS剧本文件同时具备了这三种结构。
曹操传的剧本是由多个Scene组成的。而每个Scene是由一个或多个Section构成的。
每个Scene之间,就是顺序执行的,这就是最基本的顺序结构,是不会乱跳的。
那么循环结构呢? 无论C/C++,Pascal,Basic,java,C#等各种各样的语言,都离不开for,while这些循环的,那么曹操传剧本文件的循环结构在哪呢?
当一个Scene包含多个Section时,这个Scene就是一个循环结构,当你没有执行0d指令结束Scene时,整个Scene里面始终是循环执行不会跳出的,这有点象while。
那分支呢?if ,else和switch case呢?
还记得剧本指令里一个一个的测试吗? 更何况还真的有else指令。
每一个Section,分为Section头和Section体两部分,Section头就是可以安排测试条件了,系统依次检查这些测试条件是否满足。一旦完全满足Section头的测试条件,就执行这个Section的内容了。
在一个Scene里面,有多个Section,每个Section用测试条件控制,这就成了典型的switch…case结构。R剧本里的军帐模式就是这种结构的典型应用。
每个Section里面,可以放顺序的添加多个事件,而每个事件内又还可以嵌套事件。不过每个事件的事件的事件头就只可以一条指令作为条件判断。如果子事件的测试条件不满足,则会跳过子事件而执行后面的代码。当然,如果后面接着一个else事件,那就会直接进入的了. 这就是典型的if … else 语句模式。
既然,曹操传剧本指令已经具备了结构化语言,那还不能成为一门独特的语言系统吗? 不行,还必须有变量和常量,所幸的是曹操剧本又具备了这两个。0-254正好是255个局部变量,255-999又是可用的全局变量,不过不幸的是这些变量都是不可赋值的,只有true和false. 不过,还记得电脑是什么编码吗? 二进制! 不错。一个全局变量不能表示什么,但是一串全局变量就不同了,你想用几位表示一个数字,这个随便,按照电脑本身的8位一个字节也可以,不过用10位也不错,比较好记。
还有一个具备明显数字特征的就是人物五围。当然我军的人物是不行的,但是敌军友军就不错,不过遗憾的是,这个只能在一关中设置,过了关数据就清掉了,回复为Data里面的数据,所以人物五围数字只能作为局部数据,但是要做为全局数据就不行(这点只有隋唐可以例外) 。
好了,现在已经具备了一门语言的各种特点,不过输入输出没那么自由而已,所以,要设计完美的变化多端的RS剧本,就看我们自己的智慧了。
运用好自己的智慧,把RS剧本指令的编写作为一门编程语言去掌握,去应用,则RS剧本会无穷无尽的奇妙的。
看说岳的评分,胡不愁的不定结果单挑等等原来曹操传没有的东西,都是巧妙利用RS指令的结果。
当然,还有各种各样的奇思异想,前段时间在隋唐的调查贴中看到有人想有随机相遇单挑和随机结果的宝物,

QUOTE:
具体效果是装备了这种武器的我军碰到敌人中带姓名的物理攻击最高(S)型具有一定几率的单挑概率(比如10%)
触发单挑后按照一定的算法根据两武将的武力(不是攻击力,因为曹操传中100武力跟90武力实战效果没有什么区别,但单挑中一定要体现出这种差距)和当前HP值决定胜负,设计时可以做成两个部队轮流进行攻击动作或进入单挑画面(我想这个要设计出来太困难哈)表现单挑效果。
看三国演义电视剧,单挑场面真多阿(尽管不符合史实),我想会有很多人像我一样因为喜欢武将单挑而喜欢三国的,可曹操传中单挑都是通过S剧本设定死的,谁跟谁单挑,谁赢谁负都是定死的(据说胡不愁达人做了个随机单挑胜负的S剧本,我觉得s/l的存在,使得该设计在技术上意义远大于其在实战上的意义,我方挑输s/l即可。另外单挑双方的人物还是固定的,不能带来随机对手单挑那种心惊胆跳的意外)。这样曹操传中被部份玩家称为鸡肋的典韦型的武将地位就有所提高,那武力100可不是摆着看的。这种单挑就像三国志系列中武将随机单挑一样,容易被玩家接受。当然,即便是能设置出如此武器,S/L大法也会使他逊色不少,所以个人感觉屏蔽掉即时存盘(一场战斗完成了才能存盘或一回合完成才能存盘--即我军只有全部行动完毕后才能存盘),很多兵种、武器效果、策略的实战效果和在实战中的地位都要重新洗牌,也更能体现出战棋游戏的特色,能给大家带来与曹操传完全不同的体验。这,我觉得比设置出一件兵器要有意义得多。因为就像前面的朋友所说的,属性强的宝物都在一定程度上削弱了兵种特性和人物个性,损伤了游戏特征。

其实做为一种宝物的话,单纯利用现有的剧本指令是不够的,但是要做出象三国志那样的随机出现单挑然后结果随机的效果还是可以的,具体怎么办?
这里岱瀛就把它做为本上篇的一个实例应用来讲解吧。
比如,我方有15个人,敌人有30个有名武将,则必须在剧本里设置我方和敌方武将两两相临测试。总共有15*30=450个Section。这显然比较多,局部变量不够,就必须要用到全局变量了。当然,也有变通的办法。什么办法? 比如设置周瑜的HP为1,然后在测试那里用测试其等于1,则条件真进入,然后在section里面把周瑜的HP+1,则其HP为2,显然一个循环过去,再判断等于则为false了,不会死循环了。看到了吗? 这样也是一样的局部变量测试的结果。
对于1024Data的话,乱七八糟的人物多的是,浪费几个人物的HP来测试也是很容易的,何况一个人还有HP,MP, 五围七个数据可以利用。
那么,如何答到随机结果呢? 这样15个我方,30个敌将,再弄45个人物的HP来作为这45人的体力,全部都设置为80(100也可以) 。然后每个回合这些数字可以+1,做为体力回复。单挑的时候,双方的武力是知道,可以这样设置,每次单挑设置10回合,每个回合双方的体力损失为一方的武力*2减去对方的武力做伤害,最后测试谁的体力为0就失败。这样,当一个武将的体力单挑过一个后,就缺少了,下次单挑的结果就不一定了。
对于随机单挑,则可以利用回合数,比如 A和B,第三回合,第九回合你想他们相遇就单挑,其他不单挑,你可以通过回合测试,然后配合人物数字来实现随机效果。
这样,就可以做到随机单挑随机结局。(要做到更好的话,可以设置一个人的HP做为全局,然后每个回合变化这个数字,每次触动了一个单挑再变化这个数字,甚至每次单挑的变化数字还不一样,这样就更加随机了,反正想怎么变就怎么变。)

利用好现成的剧本指令,无数的变化就看大家的脑子,看大家的思考了。
作者: 岱瀛    时间: 2006-8-8 23:42     标题: 回复 #2 岱瀛 的帖子

泛谈曹操传剧本的编写(下篇)

        上篇只是RS剧本的低级篇,只要大家会动脑筋就行,下篇则更加涉及技术性的内容,所以岱瀛准备讲述详细点。
        不错,108指令是能运用出很多变化,但是还是有些地方运用起来觉得别扭的,108条里面还有一些不好用怎么办? 一个字改,把不好的指令改掉,把缺少的指令改出来。
     怎么改,反汇编了,这就是本下篇重点讨论的内容。
     在曹操传的Exe以及其他一般MOD的Exe(说岳不是) ,剧本指令是从RS剧本里读进去后,有个switch的地方。
00410A1C  |.  FF248D 2F1141>JMP DWORD PTR DS:[ECX*4+41112F]
这条指令就是一个分支跳转,从41112F处有整个分支表,那里对应了108条指令的跳转位置。
先看小两条指令,
比如01和08指令,

01指令:

00410A2D  |> \B8 04000000   MOV EAX,4
00410A32  |.  E9 F4060000   JMP sui.0041112B

08指令:
00410A9D  |> \8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]
00410AA0  |.  52            PUSH EDX                                 ; /Arg1
00410AA1  |.  E8 78380000   CALL sui.0041431E                      ; \sui.0041431E
00410AA6  |.  83C4 04       ADD ESP,4
00410AA9  |.  E9 7D060000   JMP sui.0041112B

显然01指令没有什么用处,直接就跳到0041112B处了,而08及其他有功能的指令,都是Call另外地方的指令,最后完成后也是跳转到0041112B结束。
接着看下他Call的地方0041431E
0041431E  /$  55            PUSH EBP
0041431F  |.  8BEC          MOV EBP,ESP
00414321  |.  51            PUSH ECX
00414322  |.  6A 2E         PUSH 2E
00414324  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
00414327  |.  E8 CB400000   CALL sui.004183F7
0041432C  |.  66:8945 FC    MOV WORD PTR SS:[EBP-4],AX
00414330      8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00414333      25 FFFF0000   AND EAX,0FFFF
00414338      3D 00800000   CMP EAX,8000
0041433D      75 07         JNZ SHORT sui.00414346
0041433F      B8 05000000   MOV EAX,5
00414344      EB 17         JMP SHORT sui.0041435D
00414346      8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00414349      81E1 FFFF0000 AND ECX,0FFFF
0041434F      51            PUSH ECX
00414350      E8 03850100   CALL sui.0042C858
00414355      83C4 04       ADD ESP,4
00414358      B8 01000000   MOV EAX,1
0041435D  |>  8BE5          MOV ESP,EBP
0041435F  |.  5D            POP EBP
00414360  \.  C3            RETN
这个是整个函数的内容。
注意004183F7,这其实是一个解析参数的函数。我们每一条剧本指令,除了指令代号之外,都是带参数的,至于如何解析这个参数,都是通过Call 004183F7实现的。注意前面的PUSH 2E, 这是Call 004183F7的一个重要参数,叫做参数前缀,对应的就是剧本里剧本指令代码中参数前两个字节的那个前缀。刚好这种True和False的设置2E,所以这里就Push 2E,其实这个是可以改的,Exe里改了,然后剧本指令里把这个地方也改了,就OK了,不过这样Van的剧本编辑器就打不开了,这也就有加密的效果了哦。如果你有兴趣把所有指令的剧本参数前缀改一遍,设置分支表位置倒换下,那则是更大的加密了,不过你也得开始考虑自己写一个剧本编辑器了,用UE写剧本那根本不是人干的活。
我们看到,光荣的程序员还是很职业的,对传入参数有很仔细的检查确认,解析出来的数字放到自己函数里的局部变量之后SS:[EBP-4], 还做了很仔细的比较判断。
00414333      25 FFFF0000   AND EAX,0FFFF
00414338      3D 00800000   CMP EAX,8000
0041433D      75 07         JNZ SHORT sui.00414346
0041433F      B8 05000000   MOV EAX,5
00414344      EB 17         JMP SHORT sui.0041435D
这一段代码就是这样的效果。
00414350      E8 03850100   CALL sui.0042C858这个地方才是真正完成调用对应功能函数的地方。
校验的代码,光荣的程序员很职业,但是中国的程序员通常都很天才,往往这种很职业的事是不干的,何况Van的编辑器对剧本指令和参数都有做合法性校验,有时候我们自己偷下懒,就悄悄把这个给改掉了,为什么要改掉,笨,如果要加一个参数,哪找空间,现成这里改最好。
当然,看过光荣的读参数那段代码确实很笨,当多个参数的时候,他是一个一个不厌其烦,其实可以用个循环搞定的,能省不少空间。
好了,大概的剧本修改指令的入门已经讲了,至于里面的内容,不同功能有不同代码,已经没办法这样泛谈了,要把108个谈一遍! 那不累死,再次佩服当年Van的研究。说说调试方法把,可以一层层追进去,追到调用API的地方,开个MSDN,查一下,你就知道API在干什么了,几个串起来,就更加明白了,再对应你在游戏里看的效果,我想该能清楚。
下面,学习上篇,也举个例子吧。举什么好呢,又不想在这里泄露隋唐的太多东西,选个有趣的讲吧,就是单挑场景的任意指定。那个由于说岳也已经用了,和大家也见过面了,我就不凡说说吧。这东东目前也就只有说岳和隋唐有,所以大家看看我想也是有点意思的吧。
话归正传:
且看68指令。单挑场景任意指定其实改的就是68指令,让其多了一个参数,指定哪张LOGO图片做为场景,然后我们扩展下LOGO,导多几个图进去也就OK了。
先全面看一下68指令原来的样子:
004110A8  |> \8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]                //参数进来
004110AB  |.  50            PUSH EAX                                 ; /Arg1
004110AC  |.  E8 84640000   CALL Ekd5.00417535                   ; \Ekd5.00417535
004110B1  |.  83C4 04       ADD ESP,4
004110B4  |.  EB 75         JMP SHORT Ekd5.0041112B

00417535  /$  55            PUSH EBP
00417536  |.  8BEC          MOV EBP,ESP
00417538  |.  83EC 08       SUB ESP,8
0041753B  |.  6A 02         PUSH 2                     ; /这就是武将序号参数前缀
0041753D  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]   ; |   
00417540  |.  E8 B20E0000   CALL Ekd5.004183F7                ; 解析参数
00417545  |.  66:8945 FC  MOV WORD PTR SS:[EBP-4],AX   得到第一个单挑武将序号
00417549  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]      
0041754C  |.  25 FFFF0000   AND EAX,0FFFF
00417551  |.  3D 00800000   CMP EAX,8000
00417556  |.  75 0A         JNZ SHORT Ekd5.00417562
00417558  |.  B8 05000000   MOV EAX,5
0041755D  |.  E9 82000000   JMP Ekd5.004175E4
00417562  |>  6A 02         PUSH 2                     ; /武将序号参数前缀
00417564  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]             ; |   
00417567  |.  E8 8B0E0000   CALL Ekd5.004183F7                      ; \解析参数
0041756C  |.  66:8945 F8    MOV WORD PTR SS:[EBP-8],AX 得到第二个单挑武将序号
00417570  |.  8B4D F8       MOV ECX,DWORD PTR SS:[EBP-8]
00417573  |.  81E1 FFFF0000 AND ECX,0FFFF
00417579  |.  81F9 00800000 CMP ECX,8000                               
0041757F  |.  75 07         JNZ SHORT Ekd5.00417588
00417581  |.  B8 05000000   MOV EAX,5
00417586  |.  EB 5C         JMP SHORT Ekd5.004175E4
00417588  |>  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
0041758B  |.  81E2 FFFF0000 AND EDX,0FFFF
00417591  |.  81FA 00040000 CMP EDX,400
00417597  |.  7D 25         JGE SHORT Ekd5.004175BE
00417599  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
0041759C  |.  25 FFFF0000   AND EAX,0FFFF
004175A1  |.  3D 00040000   CMP EAX,400
004175A6  |.  7D 16         JGE SHORT Ekd5.004175BE
004175A8  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
004175AB  |.  81E1 FFFF0000 AND ECX,0FFFF
004175B1  |.  8B55 F8       MOV EDX,DWORD PTR SS:[EBP-8]
004175B4  |.  81E2 FFFF0000 AND EDX,0FFFF
004175BA  |.  3BCA          CMP ECX,EDX
004175BC  |.  75 04         JNZ SHORT Ekd5.004175C2
004175BE  |>  33C0          XOR EAX,EAX
004175C0  |.  EB 22         JMP SHORT Ekd5.004175E4
004175C2  |>  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
004175C5  |.  25 FFFF0000   AND EAX,0FFFF
004175CA  |.  50            PUSH EAX               ; /Arg2   第二个武将序号
004175CB  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]             ; |
004175CE  |.  81E1 FFFF0000 AND ECX,0FFFF                            ; |
004175D4  |.  51            PUSH ECX                ; |Arg1  第一个武将序号
004175D5  |.  B9 803C4B00   MOV ECX,Ekd5.004B3C80                    ; |
004175DA  |.  E8 C0230300   CALL Ekd5.0044999F     ; \关键的功能函数
004175DF  |.  B8 01000000   MOV EAX,1
004175E4  |>  8BE5          MOV ESP,EBP
004175E6  |.  5D            POP EBP
004175E7  \.  C3            RETN


0044999F  /$  55            PUSH EBP
004499A0  |.  8BEC          MOV EBP,ESP
004499A2  |.  51            PUSH ECX
004499A3  |.  894D FC       MOV DWORD PTR SS:[EBP-4],ECX
004499A6  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]         拿出第一个武将序号
004499A9  |.  50            PUSH EAX             ; /Arg1
004499AA |.  E8 E107FDFF   CALL Ekd5.0041A190       ; \Ekd5.0041A190
004499AF  |.  83C4 04       ADD ESP,4
004499B2  |.  85C0          TEST EAX,EAX
004499B4  |.  74 14         JE SHORT Ekd5.004499CA
004499B6  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
004499B9  |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]
004499BC  |.  8951 0C       MOV DWORD PTR DS:[ECX+C],EDX
004499BF  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004499C2  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
004499C5  |.  8948 38       MOV DWORD PTR DS:[EAX+38],ECX
004499C8  |.  EB 75         JMP SHORT Ekd5.00449A3F
004499CA  |>  8B55 0C      MOV EDX,DWORD PTR SS:[EBP+C] 拿出第二个武将序号
004499CD  |.  52            PUSH EDX                                 ; /Arg1
004499CE |.  E8 BD07FDFF   CALL Ekd5.0041A190                       
004499D3  |.  83C4 04       ADD ESP,4
004499D6  |.  85C0          TEST EAX,EAX
004499D8  |.  74 14         JE SHORT Ekd5.004499EE
004499DA  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
004499DD  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
004499E0  |.  8948 0C       MOV DWORD PTR DS:[EAX+C],ECX
004499E3  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
004499E6  |.  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]
004499E9  |.  8942 38       MOV DWORD PTR DS:[EDX+38],EAX
004499EC |.  EB 51         JMP SHORT Ekd5.00449A3F
004499EE  |>  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
004499F1  |.  6BC9 48       IMUL ECX,ECX,48
004499F4  |.  81C1 0000D600 ADD ECX,0D60000
004499FA  |.  E8 DDE00200   CALL Ekd5.00477ADC
004499FF  |.  8AC8          MOV CL,AL
00449A01  |.  81E1 FF000000 AND ECX,0FF
00449A07  |.  6BC9 24       IMUL ECX,ECX,24
00449A0A  |.  81C1 502C4B00 ADD ECX,Ekd5.004B2C50
00449A10  |.  E8 FBCCFBFF   CALL Ekd5.00406710
00449A15  |.  85C0          TEST EAX,EAX
00449A17  |.  74 14         JE SHORT Ekd5.00449A2D
00449A19  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A1C |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]
00449A1F  |.  8951 0C       MOV DWORD PTR DS:[ECX+C],EDX
00449A22  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00449A25 |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
00449A28 |.  8948 38       MOV DWORD PTR DS:[EAX+38],ECX
00449A2B |.  EB 12         JMP SHORT Ekd5.00449A3F
00449A2D  |>  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
00449A30  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
00449A33 |.  8942 0C       MOV DWORD PTR DS:[EDX+C],EAX
00449A36 |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A39 |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]
00449A3C |.  8951 38       MOV DWORD PTR DS:[ECX+38],EDX
00449A3F |>  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A42 |.  E8 B1FBFFFF   CALL Ekd5.004495F8
00449A47 |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A4A |.  8901          MOV DWORD PTR DS:[ECX],EAX
00449A4C |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
00449A4F . |. 833A 00       CMP DWORD PTR DS:[EDX],0       /////////EDX 00 4B 3c 80
00449A52  |.  74 30         JE SHORT Ekd5.00449A84
00449A54  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A57 |.E8 98ECFFFF   CALL Ekd5.004486F4 ///重要的地方
00449A5C  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00449A5F  |.  C640 12 01    MOV BYTE PTR DS:[EAX+12],1
00449A63  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]
00449A66  |.  C641 3E 03    MOV BYTE PTR DS:[ECX+3E],3
00449A6A |.  6A 01         PUSH 1                             ; /Arg1 = 00000001
00449A6C  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]             ; |
00449A6F  |.  8B4A 08       MOV ECX,DWORD PTR DS:[EDX+8]             ; |
00449A72 |.  E8 BD62FFFF   CALL Ekd5.0043FD34             ; \Ekd5.0043FD34
00449A77  |.  6A 00         PUSH 0                        ; /Arg1 = 00000000
00449A79   |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]             ; |
00449A7C  |.  8B48 34       MOV ECX,DWORD PTR DS:[EAX+34]            ; |
00449A7F |.  E8 B062FFFF   CALL Ekd5.0043FD34                   \Ekd5.0043FD34
00449A84  |>  8BE5          MOV ESP,EBP
00449A86  |.  5D            POP EBP
00449A87  \.  C2 0800       RETN 8

接下来的代码太长了,不贴了,反正就是00486F4函数里面的,把关键地点的东西弄出来就好了。
00448AB7|.  6A 0A         PUSH 0A                        ; /Arg1 = 0000000A
00448AB9   |.  B9 B8694B00   MOV ECX,Ekd5.004B69B8                    ; |
00448ABE |.  E8 3BBB0200   CALL Ekd5.004745FE                     
00448AC3   |.  6A 0A         PUSH 0A                         ; /Arg1 = 0000000A
00448AC5    |.  B9 181B4B00   MOV ECX,Ekd5.004B1B18                    ; |
00448ACA   |.  E8 71A8FBFF   CALL Ekd5.00403340              0403340
00448ACF             |.  E8 0C3AFEFF   CALL Ekd5.0042C4E0
00448AD4             |.  E8 025BFDFF   CALL Ekd5.0041E5DB
00448AD9             |.  6A 00         PUSH 0                                   ; /Arg2 = 00000000
00448ADB             |.  6A 00         PUSH 0                                   ; |Arg1 = 00000000
00448ADD             |.  8B8D E8FEFFFF MOV ECX,DWORD PTR SS:[EBP-118]           ; |
00448AE3             |.  E8 25AFFFFF   CALL Ekd5.00443A0D                       ; \Ekd5.00443A0D
00448AE8             |.  6A 00         PUSH 0                                   ; /Arg2 = 00000000
00448AEA             |.  6A 00         PUSH 0                                   ; |Arg1 = 00000000
00448AEC             |.  8B8D E8FEFFFF MOV ECX,DWORD PTR SS:[EBP-118]           ; |
00448AF2             |.  E8 7CACFFFF   CALL Ekd5.00443773                       ; \Ekd5.00443773  (左上角头相)
00448AF7             |.  E8 FA5AFDFF   CALL Ekd5.0041E5F6                                                        //画人物头象
00448AFC             |.  6A 14         PUSH 14                                  ; /Arg1 = 00000014
00448AFE             |.  B9 181B4B00   MOV ECX,Ekd5.004B1B18                    ; |
00448B03             |.  E8 38A8FBFF   CALL Ekd5.00403340                       ; \Ekd5.00403340
00448B08             |.  E8 D339FEFF   CALL Ekd5.0042C4E0
00448B0D             |.  8B8D E8FEFFFF MOV ECX,DWORD PTR SS:[EBP-118]
00448B13             |.  E8 1CAAFFFF   CALL Ekd5.00443534
00448B18             |.  6A 14         PUSH 14                                  ; /Arg1 = 00000014
00448B1A             |.  B9 181B4B00   MOV ECX,Ekd5.004B1B18                    ; |
00448B1F             |.  E8 1CA8FBFF   CALL Ekd5.00403340                       ; \Ekd5.00403340
00448B24             |.  E8 B739FEFF   CALL Ekd5.0042C4E0
00448B29             |.  E8 AD5AFDFF   CALL Ekd5.0041E5DB
00448B2E             |.  6A 00         PUSH 0                                   ; /Arg2 = 00000000
00448B30             |.  6A 01         PUSH 1                                   ; |Arg1 = 00000001
00448B32             |.  8B8D E8FEFFFF MOV ECX,DWORD PTR SS:[EBP-118]           ; |
00448B38             |.  E8 D0AEFFFF   CALL Ekd5.00443A0D                       ; \Ekd5.00443A0D
00448B3D             |.  6A 00         PUSH 0                                   ; /Arg2 = 00000000
00448B3F             |.  6A 01         PUSH 1                                   ; |Arg1 = 00000001
00448B41             |.  8B8D E8FEFFFF MOV ECX,DWORD PTR SS:[EBP-118]           ; |
00448B47             |.  E8 27ACFFFF   CALL Ekd5.00443773                       ; \Ekd5.00443773
00448B4C             |.  E8 A55AFDFF   CALL Ekd5.0041E5F6                                                                //画人物头像
00448B51             |.  6A 4B         PUSH 4B                                  ; /Arg1 = 0000004B
00448B53             |.  B9 181B4B00   MOV ECX,Ekd5.004B1B18                    ; |
00448B58             |.  E8 E3A7FBFF   CALL Ekd5.00403340                       ; \Ekd5.00403340
00448B5D             |.  E8 7E39FEFF   CALL Ekd5.0042C4E0
00448B62             |.  E8 745AFDFF   CALL Ekd5.0041E5DB
00448B67             |.  68 F0BA4800   PUSH Ekd5.0048BAF0                       ; /Arg1 = 0048BAF0 ASCII "LOGO.E5"
00448B6C             |.  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-110]           ; |
00448B72             |.  E8 BE6FFDFF   CALL Ekd5.0041FB35                       ; \Ekd5.0041FB35
00448B77             |.  6A 04         PUSH 4                                   ; /Arg3 = 00000004
00448B79             |.  6A 00         PUSH 0                                   ; |Arg2 = 00000000
00448B7B             |.  6A 00         PUSH 0                                   ; |Arg1 = 00000000
00448B7D             |.  B9 68AB4A00   MOV ECX,Ekd5.004AAB68                    ; |
00448B82             |.  E8 B96E0300   CALL Ekd5.0047FA40                       ; \Ekd5.0047FA40
00448B87             |.  50            PUSH EAX                                 ; /Arg2
00448B88             |.  6A 05         PUSH 5                             ; |Arg1 = 00000005    //第几张LOGO图
00448B8A             |.  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-110]           ; |
00448B90             |.  E8 F470FDFF   CALL Ekd5.0041FC89                       ; \Ekd5.0041FC89  //单挑背景



可以看出,原来代码里面是写死了第五张,我们只要把这个5变成一个变量,然后变量的值由剧本里的参数传进来不就行了吗?
没错。只要剧本里的68指令再多做一个参数就OK了,整个思路有了,改起来也就十分简单,纯粹是苦力活而已了。

我就把我的修改贴一下吧,功能是实现了,如果说改得不好,那也请各路大侠指点指点。
00417535   $  55            PUSH EBP
00417536   .  8BEC          MOV EBP,ESP
00417538   .  83EC 10       SUB ESP,10
0041753B   .  33D2          XOR EDX,EDX
0041753D   >  8955 F0       MOV DWORD PTR SS:[EBP-10],EDX
00417540   .  8A92 78754100 MOV DL,BYTE PTR DS:[EDX+417578]
00417546   .  81E2 FF000000 AND EDX,0FF
0041754C   .  52            PUSH EDX
0041754D   .  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
00417550   .  E8 A20E0000   CALL sui.004183F7
00417555   .  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]
00417558   .  66:894495 F4  MOV WORD PTR SS:[EBP+EDX*4-C],AX
0041755D   .  25 FFFF0000   AND EAX,0FFFF
00417562   .  3D 00800000   CMP EAX,8000
00417567   .  75 07         JNZ SHORT sui.00417570
00417569   .  B8 05000000   MOV EAX,5
0041756E   .  EB 37         JMP SHORT sui.004175A7
00417570   >  83FA 02       CMP EDX,2
00417573   .  7D 06         JGE SHORT sui.0041757B
00417575   .  42            INC EDX
00417576   .^ EB C5         JMP SHORT sui.0041753D
00417578   .  0202          ADD AL,BYTE PTR DS:[EDX]
0041757A   .  4F            DEC EDI                //这里是反汇编错误的翻译,其实应该是DB 02 DB 02 DB 4F这三条伪指令,三个前缀参数
0041757B   >  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
0041757E   .  25 FFFF0000   AND EAX,0FFFF
00417583   .  50            PUSH EAX
00417584   .  8B4D F8       MOV ECX,DWORD PTR SS:[EBP-8]
00417587   .  81E1 FFFF0000 AND ECX,0FFFF
0041758D   .  51            PUSH ECX
0041758E   .  8B55 F4       MOV EDX,DWORD PTR SS:[EBP-C]
00417591   .  81E2 FFFF0000 AND EDX,0FFFF
00417597   .  52            PUSH EDX
00417598   .  B9 803C4B00   MOV ECX,sui.004B3C80
0041759D   .  E8 FD230300   CALL sui.0044999F
004175A2   .  B8 01000000   MOV EAX,1
004175A7   >  8BE5          MOV ESP,EBP
004175A9   .  5D            POP EBP
004175AA   .  C3            RETN

这个地方改了一下,跳转到一个空白地点,那里新写了我加的代码,这也是一招经常用的方法.
00449A57   .^\E9 4FDBFCFF   JMP Ekd5.004175AB

看这里
004175AB   > /8B55 10       MOV EDX,DWORD PTR SS:[EBP+10]
004175AE   . |52            PUSH EDX
004175AF   . |E8 40110300   CALL Ekd5.004486F4
004175B4   . |83C4 04       ADD ESP,4
004175B7   . |E9 A0240300   JMP Ekd5.00449A5C

这里我是看原来那段出现两个头相的代码写得太差,不爽,合并到一起来,改写了,还有就是看那个VS不爽,中国人的单挑,干麻弄个象街头霸王一样的VS啊,去掉了。这一改还省下了一大片的空间,给其他修改利用,呵呵。这也是改EXE的必须啊。看代码,想办法,省空间,找空间大概就这过程。
00448AB7  |.  6A 0A         PUSH 0A
00448AB9  |.  B9 B8694B00   MOV ECX,Ekd5.004B69B8
00448ABE  |.  E8 3BBB0200   CALL Ekd5.004745FE
00448AC3  |.  6A 0A         PUSH 0A
00448AC5  |>  B9 181B4B00   /MOV ECX,Ekd5.004B1B18
00448ACA  |.  E8 71A8FBFF   |CALL Ekd5.00403340
00448ACF  |.  E8 0C3AFEFF   |CALL Ekd5.0042C4E0
00448AD4  |.  E8 025BFDFF   |CALL Ekd5.0041E5DB
00448AD9  |.  6A 00         |PUSH 0
00448ADB  |.  FF75 FC       |PUSH DWORD PTR SS:[EBP-4]
00448ADE  |.  8B8D E8FEFFFF |MOV ECX,DWORD PTR SS:[EBP-118]
00448AE4  |.  E8 24AFFFFF   |CALL Ekd5.00443A0D
00448AE9  |.  6A 00         |PUSH 0
00448AEB  |.  FF75 FC       |PUSH DWORD PTR SS:[EBP-4]
00448AEE  |.  8B8D E8FEFFFF |MOV ECX,DWORD PTR SS:[EBP-118]
00448AF4  |.  E8 7AACFFFF   |CALL Ekd5.00443773
00448AF9  |.  E8 F85AFDFF   |CALL Ekd5.0041E5F6
00448AFE  |.  837D FC 00    |CMP DWORD PTR SS:[EBP-4],0
00448B02  |.  75 4B         |JNZ SHORT Ekd5.00448B4F
00448B04  |.  6A 14         |PUSH 14
00448B06  |.  8345 FC 01    |ADD DWORD PTR SS:[EBP-4],1
00448B0A  |.^ EB B9         \JMP SHORT Ekd5.00448AC5

00448B85  |.  50            PUSH EAX
00448B86  |.  8D8D F0FEFFFF LEA ECX,DWORD PTR SS:[EBP-110]
00448B8C  |.  8B55 08       MOV EDX,DWORD PTR SS:[EBP+8]
00448B8F  |.  52            PUSH EDX
00448B90  |.  E8 F470FDFF   CALL Ekd5.0041FC89

看到了吧,原来的Push改了,改成从[EBP+8] 拿了,对吧,这个值是从这里来的
(004175AB   > /8B55 10       MOV EDX,DWORD PTR SS:[EBP+10]
004175AE   . |52            PUSH EDX)

我想该明白了吧。好了就写到这了,睡觉去了。
作者: 烈烽    时间: 2006-8-9 00:56

看到這些編碼都快暈倒了

發一發自己在柔居的話~看看能不能實現
SL不用規限得太緊
只要規限不同戰爭有不同SL次數~那人們便不會因按錯而苦惱
如SL超過指定此數便不能在SL~如一些大型戰埸可SL較多等
此又因難度選擇而增加~不過最重要也是把命中率這東西弄好

多一些空間使遊戲不會太難~多一些束縛使遊戲不太無聊(SL多了便無聊!!)
只要在這空間弄得平衡~遊戲便好玩了

在格檔方面~~如果弄到拿盾牌(輔助道具)的人能格檔便較真實了
如將盾牌的效果改為X個機率格檔~盾牌可設有耐久度
高級盾牌可能格檔率較高(較大的盾牌格檔範圍較大)/較高的耐久
又可能一些兵種不能拿較利害的盾牌~如騎兵(太重了~馬兒撐不住)

這是小弟一些意見~有得罪的地方請多多包涵@@Qo4/
作者: 博雅张生    时间: 2006-8-9 01:03



QUOTE:
那么循环结构呢? 无论C/C++,Pascal,Basic,java,C#等各种各样的语言,都离不开for,while这些循环的,那么曹操传剧本文件的循环结构在哪呢?
当一个Scene包含多个Section时,这个Scene就是一个循环结构,当你没有执行0d指令结束Scene时,整个Scene里面始终是循环执行不会跳出的,这有点象while。

岳飞传里牛皋转参军和银瓶能力的计算就是用这样的循环完成的。实际上在一个Scene中,程序是从下到上判断Section的。如果不满足Section的条件,则会去判断上面一个Section。而如果满足了Section的条件,就会在执行了Section之后再次从最底下的Section开始判断。这个特点其实也可以利用。

QUOTE:
0-254正好是255个局部变量,255-999又是可用的全局变量

全局变量可以到2047

QUOTE:
你想用几位表示一个数字,这个随便,按照电脑本身的8位一个字节也可以,不过用10位也不错,比较好记。

岳飞传里用的是1,2,4,8,10,20,40,80,100,200,400,800……

QUOTE:
不过遗憾的是,这个只能在一关中设置,过了关数据就清掉了,回复为Data里面的数据,所以人物五围数字只能作为局部数据,但是要做为全局数据就不行(这点只有隋唐可以例外) 。

要保留为全局数据,其实就是要避免游戏从Data中读取那个人物的原数据。(36和38对人物数据的读取和赋值都是直接操作内存),因此似乎只要人物不入队出队,不上战场似乎就可以。
作者: 博雅张生    时间: 2006-8-9 01:09



QUOTE:
在曹操传的Exe以及其他一般MOD的Exe(说岳不是) ,剧本指令是从RS剧本里读进去后,有个switch的地方。
00410A1C  |.  FF248D 2F1141>JMP DWORD PTR DS:[ECX*4+41112F]

岳飞传把410A23-411124那一大段代码化简了,腾出1700多字节

QUOTE:
显然01指令没有什么用处,直接就跳到0041112B处了,而08及其他有功能的指令,都是Call另外地方的指令,最后完成后也是跳转到0041112B结束。

01是重要的结构指令啊。子事件的标志。MOV EAX,4就是这个标志吧。

QUOTE:
要把108个谈一遍! 那不累死

可惜当时不会反汇编。108个代码完全是通过试验确定功能的。当时可把我和幽幽累坏了。

QUOTE:
但是中国的程序员通常都很天才,往往这种很职业的事是不干的,何况Van的编辑器对剧本指令和参数都有做合法性校验,

van是很职业的

本贴加精华。

[ 本帖最后由 博雅张生 于 2006-8-9 04:23 编辑 ]
作者: 岱瀛    时间: 2006-8-9 14:02

没想到得精这么容易灌灌水得来第一精
01和00指令都没有call 函数,他们就是 mov eax 一个值,00用的是03,01用的是04,而所有指令出现参数异常的EAX好象都是用了05,这个会倒置重读这条剧本指令,好象是这样,只试过一次,不对的话张生说说看。
作者: 博雅张生    时间: 2006-8-9 14:34



QUOTE:
原帖由 岱瀛 于 2006-8-9 14:02 发表
没想到得精这么容易灌灌水得来第一精
01和00指令都没有call 函数,他们就是 mov eax 一个值,00用的是03,01用的是04,而所有指令出现参数异常的EAX好象都是用了05,这个会倒置重读这条剧本指令,好象是 ...

嗯。而且对于测试性质的指令来说,如果条件成立eax是1,条件不成立eax是0。
else 比较特殊,eax是6
作者: 司徒苍月    时间: 2006-8-9 15:11

丢人把月月那不成熟的雇佣兵系统搬出来干吗。

要提就提召唤兽啊


作者: hadeswwy    时间: 2006-8-9 16:30

召唤的张生熊猫还真有创意.
作者: 司徒苍月    时间: 2006-8-9 17:06



QUOTE:
原帖由 hadeswwy 于 2006-8-9 16:30 发表
召唤的张生熊猫还真有创意.

Demo只是写了最简单的召唤模式,
等正式版再说吧,模拟出经典的召唤模式
作者: 陆逊{伯言}    时间: 2006-8-16 01:10

更失落了,我绰号应改为“不知所云”
作者: hadeswwy    时间: 2006-8-17 23:04

这里反汇编的知识比较多,只要搞动反汇编就可以了,偶也是搞了很久才大概搞懂了.
作者: 司徒苍月    时间: 2006-9-1 11:15

回去又要啃汇编知识了,都放了几年没动了……

ps掌声的相对复活/移动能简化不少s剧本命令……不知道
作者: lonker    时间: 2007-2-10 19:30

怎么在剧本里设置读哪张单挑背景啊?
作者: likeflyer    时间: 2007-3-23 18:31

楼主好强……
作者: 2750066    时间: 2007-4-26 10:44

好多内容看不懂。。。
汇编。。。看来得研究下了。。。。
作者: 神的儿子    时间: 2007-7-20 01:52

一看到代码我就晕, 不过还能看懂一点.
作者: lachuqubile    时间: 2007-8-1 10:54

好东西!!!!比写什么攻略秘籍的强多了!!!
作者: 北岭怪侠    时间: 2007-8-3 21:22

晕,看不明白
作者: tuzi0840    时间: 2009-8-26 11:17

这水灌的……

你灌洪水啊!
作者: a284760754    时间: 2009-9-4 07:09

.............................
作者: zero5914    时间: 2009-9-19 23:23     标题: 汗一个版主- -

台风过去了吧- -你怎么还发洪水- -
作者: bao王孙策    时间: 2009-9-20 19:15

有点难懂
作者: happy29    时间: 2010-3-19 07:42

非常感谢楼主说的这些,我终于找到自己喜欢的了。
作者: wertyqy    时间: 2010-3-20 21:47

jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
作者: lym20    时间: 2010-8-14 00:52

谢谢LZ分享
作者: 513633522    时间: 2011-3-20 20:37

如此神贴,我竟然没发现

狂顶狂顶
作者: eastbreeze    时间: 2011-3-20 20:59     标题: 本论坛真是人才济济啊

随便灌水的、打酱油的、路过的都是高手啊,俺也要研究研究
作者: 513633522    时间: 2011-3-24 08:18

随便灌水的、打酱油的、路过的都是高手啊
看懂了教教我




欢迎光临 轩辕春秋文化论坛 (http://xycq.org.cn/forum/) Powered by Discuz! 5.0.0