游侠NETSHOW论坛

标题: 汉之云脚本编写简明教程 [打印本页]

作者: vbvan    时间: 2008-1-12 15:01:25     标题: 汉之云脚本编写简明教程

汉之云脚本研究(附带MOD制作工具)
http://game.ali213.net/thread-1857825-1-4.html

建议大家在编写脚本之前先认真阅读一下原始的脚本代码,以便能够更好的理解整个游戏系统和如何实现各种效果。
下面就结合原始的脚本代码,介绍一下如何编写自己的MOD脚本。

首先,先来看一下原始的脚本文件各自的功能:

main目录
0000?:基础函数库
002??:主线序章
003??:主线第一章
004??:主线第二章
005??:主线第三章
006??:主线第四章
1000?:游戏基本元素
101??:普通支线剧情
108??:其它剧情(商人/迷宫/DOMO)
109??:伙伴支线剧情
110??:场景切换

fight目录
F001:基础函数
F002:普通战斗
F003:伙伴剧情战斗
F004:支线剧情战斗
F005:主线剧情战斗

一、基础修改

我们以“存档点”部分的代码为例,详细解析一下如何实现最基本的修改
打开10000c.lua,我们可以找到如下的代码:

  1. restore_motion = function()
  2.    local mainid = get_mainrole()
  3.    local mainname = get_rolename(mainid)
  4.    restore_team()
  5.    msginfo("全身籠罩一股清風")
  6. end

  7. restore_save = function()
  8.    restore_motion()
  9.    restore_save_q()
  10. end

  11. restore_save_q = function()
  12.    selmsg(2, "選項:")
  13.    setselect(1, "1.存檔")
  14.    setselect(2, "2.取消")
  15.    sleep(3)
  16.    waitanykey()
  17.    restore_save_ans(getselectanwser())
  18. end

  19. restore_save_ans = function(x)
  20.    local mainid = get_mainrole()
  21.    local mainname = get_rolename(mainid)
  22.    if x == 1 then
  23.       call_save()
  24.    elseif x == 2 then
  25.       restore_team()
  26.    else
  27.       restore_save_q()
  28.    end
  29. end
复制代码


当我们在存档点按空格键时,就会触发restore_save函数(具体参见10803c.lua中的t7901函数)
它一共做了两件事情。第一,调用restore_motion函数恢复全员的状态;第二,就是弹出选择框,提示你是否需要存档。
弹出对话框的函数是selmsg。它有两个参数,第一个指定对话框中有多少个选择项,第二个是对话框的标题
你可以使用setselect设置选择项的具体内容,getselectanswer函数用于获取用户的选择。
之后你就可以在restore_save_ans里根据用户的选择进行相应的处理了
在支线剧情中,我们会经常看到选择框的身影

这里我给出一个修改的实例,大家可以借此熟悉一下lua脚本的语法(if、for、数组)和汉之云提供的一些函数(additem、addsprite、addmoney分别用于增加物品、怪物和金钱,join用于加入队员)

  1. restore_save_q = function()
  2.    selmsg(3, "選項:")
  3.    setselect(1, "1.存檔")
  4.    setselect(2, "2.作弊")
  5.    setselect(3, "3.取消")
  6.    sleep(3)
  7.    waitanykey()
  8.    restore_save_ans(getselectanwser())
  9. end

  10. restore_cheat_q = function()
  11.    selmsg(6, "選項:")
  12.    setselect(1, "1.怪物")
  13.    setselect(2, "2.物品")
  14.    setselect(3, "3.裝備")
  15.    setselect(4, "4.金錢")
  16.    setselect(5, "5.隊伍")
  17.    setselect(6, "6.取消")
  18.    sleep(3)
  19.    waitanykey()
  20.    restore_cheat_ans(getselectanwser())
  21. end

  22. restore_cheat_ans = function(x)
  23.    local mainid = get_mainrole()
  24.    local mainname = get_rolename(mainid)
  25.    if x == 1 then
  26.       local mon = {17, 14, 15, 15, 16, 16, 14, 12, 7, 6}
  27.       local a = table.getn(mon)
  28.       for i = 1, a do
  29.          for j = 1, mon[i] do
  30.             addsprite(i * 100 + 900 + j, 1)
  31.          end
  32.       end
  33.    elseif x == 2 then
  34.       for i = 6001, 6028 do
  35.          if i ~= 6024 then
  36.             additem(i, 99)
  37.          end
  38.       end
  39.       for i = 6039, 6046 do
  40.          if i ~= 6040 then
  41.             additem(i, 99)
  42.          end
  43.       end
  44.    elseif x == 3 then
  45.       local i1 = {3001, 3018, 3021, 3041, 3061, 3081, 3101, 4001, 4021, 4041, 5001, 5051}
  46.       local i2 = {3016, 3018, 3034, 3055, 3074, 3090, 3109, 4011, 4030, 4051, 5024, 5063}
  47.       local a = table.getn(i1)
  48.       local b = table.getn(i2)
  49.       local num = 11
  50.       if a == b then
  51.          for i = 1, a do
  52.             for j = i1[i], i2[i] do
  53.                additem(j, num)
  54.             end
  55.          end
  56.       end
  57.    elseif x == 4 then
  58.       addmoney(1000000)
  59.    elseif x == 5 then
  60.       for i = 1, 11 do
  61.          join(i)
  62.       end
  63.    elseif x == 6 then
  64.    else
  65.       restore_cheat_q()
  66.    end
  67. end

  68. restore_save_ans = function(x)
  69.    local mainid = get_mainrole()
  70.    local mainname = get_rolename(mainid)
  71.    if x == 1 then
  72.       call_save()
  73.    elseif x == 3 then
  74.       restore_team()
  75.    elseif x == 2 then
  76.       restore_cheat_q()
  77.    else
  78.       restore_save_q()
  79.    end
  80. end
复制代码


二、剧情修改
剧情修改相对比较复杂,所以我们先从人物对话开始介绍。
下面是飞羽军营中和“徐豐”对话的相应代码(简化过了):

  1. t341 = function()
  2.    local mainid = get_mainrole()
  3.    local mainname = get_rolename(mainid)
  4.    chang_role_dir_torole(mainid, 341, 0)
  5.    lock_player(1)
  6.    set_watch_each(mainid, 341)
  7.    if isfon(1002) == 1 and isfon(1017) == 0 then
  8.       local a = random(2)
  9.       if a == 0 then
  10.          facetotalk(341, "徐豐", "聽說供應曹賊糧草的是在邽嶺山中的砦堡!")
  11.       else
  12.          facetotalk(341, "徐豐", "邽嶺就在我軍營外幾里處。")
  13.       end
  14.    else
  15.       if isfon(1017) == 1 and isfon(1053) == 0 then
  16.          facetotalk(341, "徐豐", "我們的補給從漢中運來,路途遙遠。不像曹賊,邽嶺以北幾乎是援助他們的砦堡。")
  17.       else
  18.          if isfon(1101) == 1 and isfon(1151) == 0 then
  19.             facetotalk_noback(341, "徐豐", "我們現在就在賊將郭淮、費曜駐守的上邽城外。")
  20.             chatinfo(341, "徐豐", "料想他們怎麼也想不到,我們飛羽部隊會在這地方。")
  21.             chang_role_dir(341, 0, 1)
  22.          end
  23.       end
  24.    end
  25.    lock_player(0)
  26.    set_watch_back(mainid, 341)
  27. end
复制代码


我们可以看到,和NPC对话之前通常会作两件事情:
第一,调用chang_role_dir_torole,使得NPC朝向主角;第二,调用lock_player将主角锁定
然后就是一长串根据isfon的if...else...了。
isfon是is flag on的缩写。每当我们进行一次对话,完成一次任务的时候,系统都会使用fon函数进行记录。之后就可以使用isfon来判断对话是否发生,任务是否完成,等等。
这里,我们和"徐豐"对话的时候,系统会根据flag的值来推断玩家目前处于剧情的哪个阶段,并显示相应的对话
(比如,游戏一开始,和多聞使对话之后就会设置1002这个flag)

isfon和fon对于主线或者支线的剧情非常重要。可以说是我们制作MOD剧情必不可少的函数
譬如,我们完成NPC交待的任务,返回领取奖励的时候,系统就会根据flag来测试相应任务是否完成。

[ 本帖最后由 vbvan 于 2008-1-13 12:51 编辑 ]
作者: 林碧    时间: 2008-1-12 15:02:25

沙发,顶神帖啊~~~~~~~~~~~~~
作者: tianwuld    时间: 2008-1-12 15:16:25

感觉上最难的还是里面一些参数的设定
尤其是镜头的…………
作者: 08msvs0079    时间: 2008-1-12 15:19:20

眼花了,只能精神上支持.........
作者: 素世还真    时间: 2008-1-12 15:36:53

必须先改为台湾区域才能修改了。。。。。。。。。。。
作者: liubig    时间: 2008-1-12 15:54:53

太好了!!!我要的就是這個!!!! [汗水] van大人,你的RPGViewer是不是對漢之云還不支持導入圖片。

[ 本帖最后由 liubig 于 2008-1-12 16:00 编辑 ]
作者: 游荡死神ZX    时间: 2008-1-12 15:59:58

看起来比较难啊
o(∩_∩)o...~~~~~
作者: kendogm    时间: 2008-1-12 16:15:12

實裝后如何馬上觀看效果?
例如改一段劇情 但我的存檔暫時是無法到達我所改的那段劇情-.-
作者: 79793281    时间: 2008-1-12 16:24:45

感谢楼主的劳动,我编译之后出现这样的错误,如何解决呢?谢谢
..\..\luac: 10000c.lua:988: `do' expected near `addsprite'
作者: vbvan    时间: 2008-1-12 16:34:40

回79793281
下面这行少了个空格
for j = 1, mondo -> for j = 1, mon do

回kendogm
你可以用修改器SWD5Editor修改flag,以保证事件能够被触发(当然,比如说对话,你得先找到那个NPC才行)

回liubig
是的,不支持

回素世还真
你可以试一下Applocale,或者用支持Encoding的编辑器(比如EditPlus,打开的时候选择Big5编码)
作者: kendogm    时间: 2008-1-12 16:50:29

vbvab

應該是 fon() 這里吧?

比如我想要直接觸發1007的事情。
那我是不是只需要開啟1007就可以了?

[ 本帖最后由 kendogm 于 2008-1-12 16:51 编辑 ]
作者: 79793281    时间: 2008-1-12 16:52:40

原帖由 vbvan 于 2008-1-12 16:34 发表
回79793281
下面这行少了个空格
for j = 1, mondo -> for j = 1, mon do

回kendogm
你可以用修改器SWD5Editor修改flag,以保证事件能够被触发(当然,比如说对话,你得先找到那个NPC才行)

回liubig
是的,不支持

回素世还真
...

好了,多谢楼主
作者: Gordo    时间: 2008-1-12 17:02:17

精神上支持吧~~~~~~~~~~~~~~~~~~~
作者: ctking    时间: 2008-1-12 17:04:41

我不行了...我实在是不行了....
这帖给我的压力太大了!!!!
作者: superbox    时间: 2008-1-12 17:05:18

灭时间研究      
作者: wuspring    时间: 2008-1-12 18:49:50

文中对数组的调用方法有错,会导致在第1及第3项作弊时游戏卡死
  1.        for j = 1, mon do   ->         for j = 1, mon[i] do
  2.             for j = i1, i2 do  ->               for j = i1[i], i2[i] do
复制代码




全文:
  1. restore_save_q = function()
  2.    selmsg(3, "匡兜")
  3.    setselect(1, "1.絃")
  4.    setselect(2, "2.国")
  5.    setselect(3, "3.")
  6.    sleep(3)
  7.    waitanykey()
  8.    restore_save_ans(getselectanwser())
  9. end

  10. restore_cheat_q = function()
  11.    selmsg(6, "匡兜")
  12.    setselect(1, "1.┣")
  13.    setselect(2, "2.珇")
  14.    setselect(3, "3.杆称")
  15.    setselect(4, "4.窥")
  16.    setselect(5, "5.钉ヮ")
  17.    setselect(6, "6.")
  18.    sleep(3)
  19.    waitanykey()
  20.    restore_cheat_ans(getselectanwser())
  21. end

  22. restore_cheat_ans = function(x)
  23.    local mainid = get_mainrole()
  24.    local mainname = get_rolename(mainid)
  25.    if x == 1 then
  26.       local mon = {17, 14, 15, 15, 16, 16, 14, 12, 7, 6}
  27.       local a = table.getn(mon)
  28.       for i = 1, a do
  29.          for j = 1, mon[i] do
  30.             addsprite(i * 100 + 900 + j, 1)
  31.          end
  32.       end
  33.    elseif x == 2 then
  34.       for i = 6001, 6028 do
  35.          if i ~= 6024 then
  36.             additem(i, 99)
  37.          end
  38.       end
  39.       for i = 6039, 6046 do
  40.          if i ~= 6040 then
  41.             additem(i, 99)
  42.          end
  43.       end
  44.    elseif x == 3 then
  45.       local i1 = {3001, 3018, 3021, 3041, 3061, 3081, 3101, 4001, 4021, 4041, 5001, 5051}
  46.       local i2 = {3016, 3018, 3034, 3055, 3074, 3090, 3109, 4011, 4030, 4051, 5024, 5063}
  47.       local a = table.getn(i1)
  48.       local b = table.getn(i2)
  49.       local num = 11
  50.       if a == b then
  51.          for i = 1, a do
  52.             for j = i1[i], i2[i] do
  53.                additem(j, num)
  54.             end
  55.          end
  56.       end
  57.    elseif x == 4 then
  58.       addmoney(1000000)
  59.    elseif x == 5 then
  60.       for i = 1, 11 do
  61.          join(i)
  62.       end
  63.    elseif x == 6 then
  64.    else
  65.       restore_cheat_q()
  66.    end
  67. end

  68. restore_save_ans = function(x)
  69.    local mainid = get_mainrole()
  70.    local mainname = get_rolename(mainid)
  71.    if x == 1 then
  72.       call_save()
  73.    elseif x == 3 then
  74.       restore_team()
  75.    elseif x == 2 then
  76.       restore_cheat_q()
  77.    else
  78.       restore_save_q()
  79.    end
  80. end
复制代码

[ 本帖最后由 wuspring 于 2008-1-12 22:45 编辑 ]
作者: 8225720    时间: 2008-1-12 19:29:15

V大,您就是我心目中的偶像,您就是那红太阳,照耀俺们呀
作者: yf830830    时间: 2008-1-12 19:29:35

能不能改出个飞之部的剧情篇来
支持楼主的mod
希望见到新的剧情
作者: 天壤之劫火    时间: 2008-1-12 19:53:54

好吧。。。对于只粗浅学了C++的我来说这种东西只能看一看有没有认识的语句
然后支持。。。。
作者: nomadz    时间: 2008-1-12 20:06:52

最好能出专业的剧情编辑器

这样修改语句做mod 不是一般的花费精力
作者: vacuumtc    时间: 2008-1-12 20:28:51

楼主 和 楼上的 wuspring 帮了大忙,现在连怪物都能直接加进游戏了,这下子太激动了
作者: darkradx    时间: 2008-1-12 22:55:54

真是神作啊...............................
作者: vbvan    时间: 2008-1-13 13:00:29

原帖由 wuspring 于 2008-1-12 18:49 发表
文中对数组的调用方法有错,会导致在第1及第3项作弊时游戏卡死

       for j = 1, mon do   ->         for j = 1, mon do
            for j = i1, i2 do  ->               for j = i1, i2 do




全文:restore_save ...


多谢提醒,我是在所见即所得模式下粘贴的,没留意UBB还是会被解析。顶楼的代码已经更新
作者: jy01748948    时间: 2008-1-13 13:08:35

修改一下细微剧情.汉之云绝对是神作//..还有就是结局...
作者: wuspring    时间: 2008-1-13 13:13:33

原帖由 vbvan 于 2008-1-13 13:00 发表


多谢提醒,我是在所见即所得模式下粘贴的,没留意UBB还是会被解析。顶楼的代码已经更新


:) 话说这个作弊太强大了,昨晚用这个去过剧情,了无乐趣了..hoho
作者: dr1989    时间: 2008-1-13 13:47:35

请问这个脚本是作弊器?
- - 汗~~~
作者: wuspring    时间: 2008-1-13 13:50:21

前头在改的脚本是作弊用的~~~~~~~~
作者: ~准~    时间: 2008-1-13 15:36:05

看不懂``` [汗水] [汗水]
作者: 幻影飓风    时间: 2008-1-21 19:54:31

555555......
希望出一个横艾跟焉逢的结局啊............!!!!
真的............!
很希望.......5555555
作者: 将疯    时间: 2008-1-25 16:06:56

牛人吖~

----------------

各位高手改到新剧情,记得上传分享吖~
作者: 偶爾口愛    时间: 2008-1-25 16:59:27

好好好好。。。。。好复杂啊。。。
偶真的不懂捏。。。
可是很希望赤衣和紫衣可以有个好结局
作者: liuyz0810    时间: 2008-1-25 17:09:10

直接眼花。。。PFLZ的NB但是不能理解。。
作者: shevacy    时间: 2008-1-26 03:01:01

学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习学习
作者: iamchenchao    时间: 2008-1-26 14:10:38

我是专程进来膜拜van大的   
作者: darkarthas    时间: 2008-1-26 14:54:01

完全看不懂  OY   
不过还是很佩服阿  
作者: x_t_j    时间: 2008-1-26 15:18:09

这样的话,单个人能做的不过就是改几个道具数值,让游戏比较容易一些。
至于修改剧情这么复杂的活,没有团队组织分工好像不现实啊。

PS:Lua语言就是C和basic的杂糅么?看着有一种似曾相识的感觉……
作者: xlt1987    时间: 2008-2-18 21:58:01

好强大的帖子啊,顶上
作者: kof-zly    时间: 2008-2-18 23:00:22

对van大顶礼膜拜......
作者: 小蚊子    时间: 2008-2-18 23:05:32

啥.......C++一样么
作者: brenda_st    时间: 2008-2-28 20:09:10

[害怕]
我那点底子阿。。。
怎么混。。。
作者: 大雄QQ    时间: 2008-2-28 21:35:38

参数的设定
平衡最重要@@@

镜头做好了一遍就可以了@
作者: dacdog    时间: 2008-3-17 01:27:11

盼望自定剧情早点出来 [舒服] [舒服] [舒服]
作者: peter824    时间: 2008-3-17 16:25:54

神贴,不懂编程的最好别去乱改。。
作者: ctking    时间: 2008-3-21 23:31:51

一直在玩FFX的模拟器,好久没来仙剑区了.
看到神帖,再顶一下.
作者: yost0120    时间: 2008-3-22 13:35:10

好强大 不过看不太懂 纯支持了... - -b
作者: solomleee    时间: 2008-7-25 20:07:06

van大的好东东,顶起!!

作者: hunterybj    时间: 2009-4-7 19:10:30     标题: 回复 #1 vbvan 的帖子

赞,技术贴

一直想可以自己修改剧情,终于有人值了条明路了

定一个
作者: xcz1984    时间: 2009-10-10 10:23:43

太难了,只能支持了。。。。。。。。。。。。。。。。。。。。。
作者: 静若澜泉    时间: 2009-12-16 17:54:54

哪位高手指点一下 怎样在游戏后期把游兆调出来呀?!!
作者: oY忆江南Yo    时间: 2009-12-17 13:35:15

看到代码之后两眼一抹黑!我要昏倒了!
作者: no4pt    时间: 2010-6-16 09:46:05

到底是封装到高级了,怪简单。闭包+面向过程函数式,没有OO嘛




欢迎光临 游侠NETSHOW论坛 (https://game.ali213.net/) Powered by Discuz! X2