嗯……看了上个帖子的人应该多少对文章有一定了解了,这个教程就是对软件pokescript的一番讲解。pokescript是什么呢?它是老外开发的一款剧情编辑工具,输入脚本,就可以直接操作ROM,相当方便。
本文是我liuyanghejerry在看了软件作者Irish witch的教程之后翻译+修改的,使得文章能让我们看的更顺眼,部分教程还做了调整,不过有些不好翻译的地方我仍旧保持着原文(看目录就知道了),如果有什么地方看不懂,大家可以跟帖表示,我会尽我所能回答的。
OK以下开始正文:
Pokescript教程
我注意到许多人来到我们论坛都会问道一个共同的问题:如何利用Pokescript制作改版?那么现在就让我来完整的回答这个问题吧.
当然,我所讲的一切都基于我的软件──Pokescript.
首先,我们需要下载两样东西:Pokescript(见附件),以及一个数据库,PkmAdv(见附件).
PokeScript的安装相当简单,通常会安装在c:/pokewitch,而PkmAdv也是一样的,注意保持它们在相同的文件夹内即可.
下面我们来看看教程的安排,也就是目录:
0. 准备知识
1. 基础内容
1.1 开始学习
1.2 显示一段文字
1.3 写入ROM
1.4 真正显示于游戏
2. 关于物品赠送
2.1 只给一次的情形处理(使用标识)
2.2 是或不是的问题处理
2.3 接收物品
2.4 检查物品
2.5 删除物品
3. 关于精灵赠送
3.1 让精灵消失
3.2 给予精灵的情形处理
3.3 给精灵起个昵称
3.4 让图鉴工作起来
3.5 统计精灵
3.6 选择精灵
4. 野外的场景
4.1 控制NPC移动
4.2 计算路线
4.3 开始移动
4.4 设置路标
4.5 跟随NPC
5. 道馆中的情形
5.1 地图中的人物
5.2 与野生精灵战斗
5.3 寻找训练师
5.4 基本的训练师战斗
5.5 双人战斗
5.6 道馆馆主
5.7 再次相遇的战斗
5.8 训练师的可视范围
0.准备知识
现在让我们来接触一下需要了解的一些基础知识吧.
十六进制数字
十六进制数字是相对于十进制的一种数字表达方法,它用的不是0,1,2,3,4,5,6,7,8,9而是0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F这十六个字符.使用十六进制数字更有利于和二进制的处理器交换数据,但我们不需要深入了解.通常,我们表示时在前面加上"&H"或者"0x".
你无需使用十六进制数字去做什么艰难的工作,顶多,就是用它们写写地址之类的东西.
那么接下来要说的就是地址.
地址是什么?我没法具体的去说明它,而且也没有必要,我们只需要知道它长这样:0x800100.
但实际上在Pokescript当中我们并不(或者说很少)用到这种表达方式,我们会用到这个:$Offset,来看一段简单的示例:
code:
#inline $Variable 1 = Hi I'm John!
$Variable 1 = Hi I'm John!
以上说的什么?你完全不用理会,你需要注意的是这个$Variable.在Pokescript当中,一个英文词语前加$就可以表示一个地址,当然,这个词语当中不允许有任何符号.至于它表示的地址具体是什么,完全不必理会(至少现在如此),那是程序的任务.
注:在一些特别的时候,我们需要将地址表示为0x800100的形式,因为这是所有工具都认识的格式
下面开始进入正题:
1. 基础内容
在我的教程中,我们时刻都要考虑你的脚本需要做什么,比如现在正要说的显示信息和道具给予.
1.1开始学习
通常在整个改版过程中,我们得有一套完整的事件流程,就像一个剧本,比如:
1. 你在地图上激活一个NPC.
2. NPC将会问你一个问题.
3. 如果你回答是,那么他将会给你一块饼干.
4. 如果你已经要过饼干了,那么他会说另一段话
以上是一个很基本的例子,但我们现在还不到那个地步,我们得先来点更简单的:显示信息,也就是让NPC对你说一句话,然后来看看脚本是如何输出并写入ROM的.
首先打开记事本,并在其中输入以下的内容:
Code:
#ORG $ShowText
Lock
Faceplayer
以上是几条最为基本的命令,最开始的是地址标志,也就是$ShowText,前面我们曾经说过.而#ORG则表示脚本开始.这两个命令相当重要,因为它们不仅在这里要用到,而且以后几乎所有的脚本中都要用到,我们把它们看做一条命令,必须牢记.
第二行的命令Lock表示将NPC锁定,而不是让他跑动.
第三行命令更好理解,它表示面对主角.
通常开始一段对话的时候都要写以上的部分,这几乎成了惯例.
那么下一步就是:
1.2 显示一段文字
以上的那些命令在每次显示一段文字时都要用到,那么来看看下面的代码:
message $NoCookie
$NoCookie 1 = I'm not made of cookies!\lYou only get one.
boxset 6
$NoCookie的格式前面已经说过,是一个地址,但不仅仅表示地址,此处我们认为它是一个变量.(变量是编程中用到的词语,完全不懂的话可以百度一下,当然,你跟着教程也能自己悟出)
而I'm not made of cookies!\lYou only get one.则是我们想要显示的信息,其中\l表示换行.与\l类似的还有\n和\p ,区别大家可以自己体会.
boxset 是设置对话框的意思,表示这里的内容在对话框中显示,6表示普通的文本对话框.
看起来我们已经完成了所要做的,但请等一下,在末尾加上:
release
end
表示恢复NPC原始形态,并结束脚本.这样整个脚本就是:
#ORG $ShowText
Lock
Faceplayer
message $NoCookie
$NoCookie 1 = I'm not made of cookies!\lYou only get one.
boxset 6
release
end
现在我们在记事本当中,选择另存为,存为*.rbc格式即可.
接下来我们将脚本写入ROM.
1.3 写入ROM
现在在"我的电脑"中找到刚才保存好的脚本,右键可以看到"合并脚本到ROM"的相关字样(英文:complie the script),点击.这时程序会弹出两个窗口,一个类似于工作日志,我们关闭它;而另一个则是Pokescript合并器的主窗口.(如果这个窗口未能弹出,那么双击同目录生成的文件即可)
紧接着我们有两个方法来完成剩余的工作.
①比较直接的方法
单击那个好像书本一样的按钮,然后载入你想合并的ROM.
注意,如果此时底下的列表中有多项内容你希望添加,那么使用shift可以复选,否则选中一个就好.
现在就会弹出一个小窗口─此窗口会告诉你,即将写入的信息有多少以及ROM有多少剩余空间、从什么地方开始写起.如果是第一次使用,那么我们大可按照默认的地址0x800000开始写入,因为在原来的ROM中,这个地方是空的.按下你需要写入的地址,然后点"assign".
瞧,又回到主窗口了.点击"file"菜单中的"Burn",程序就开始工作了.
工作完毕后千万不要直接关闭,记下程序回显中紧跟着起始地址的一行数字,我们一会有用的哦.
②推荐的方法
回到刚才,弹出小窗口的时候.大家应该注意到"assign"按钮上有一个复选框,钩选之后按钮就会显示"Reserve",如此你所写入ROM的信息就不会覆盖到任何其它数据了(如果这不是个Clean ROM的话).
1.4 真正显示于游戏
经过刚才的步骤,脚本已经被输入到ROM当中了,但是我们并没有让脚本的内容进入游戏.
打开经典的工具Advanced Map,调至你所想要修改对话的NPC(在event view页面选中),在地图右边找到"Script Offset"一项(也就是地址了),还记得刚才我要大家记下的数字吗?粘贴替换掉现在那个,保存,测试!
那么,现在一个最基本的步骤就算结束了,后面,我们就来完成一开始的那个小剧本吧.
注意了,如果您在ROM当中发现修改后的对话成为了乱码,那么您必须参见这里解决:
http://poketb.com/bbs/viewthread.php?tid=4258&extra=page%3D1
2. 关于物品赠送
学习完以上的内容,大家应该对脚本制作有一个大概的了解了.如何开始一个脚本、如何结束一个脚本以及如何使脚本在游戏中实现,都必须牢记.
现在让我们来看看关于物品赠送的部分.
以下的例子和上文中的很相似,不过这次我们给变量一个新名字:$GotCookie(上文名为$ShowText).
2.1 只给一次的情形处理(使用标识)
当然,就和前面一样,我们的脚本仍然这么开头:
#org $Startscript
Lock
Faceplayer
为了能使得游戏知道每一个事件,我们通常要用到一个命令:setflag,中文即是设立标识.这就好比公交车站牌一样,告诉公交车何时该停下.
大概有6000个标识可以使用。但是,在0x300 - 0x400 和 0x800 - 0x900 有许多游戏本身使用的,所以要避开这些去进行HACK.
标识通常写作16进制,不过我们这会还不用亲自设立标识,而只需要让游戏检查标识.
说到这大家可能晕了,什么是检查标识?我们并没有设立任何标识啊.是这样的,检查标识是一个预备性的命令,而关于设立标识,则是以后几节的重点,现在只要认得这个:
checkflag 0x200
if B_TRUE goto $GotCookie
你可能看不懂以上的脚本,没关系,我现在来讲解一下.
checkflag这个命令在检查标识0x200.
而这里,B_TRUE也可以写作1或者0x1,它们都表示"正确".
$GotCookie是我们事先写好的脚本.
也就是这么个意思:检查标识0x200,如果该标识存在,则进入脚本$GotCookie
为了能更好的理解上面所说的,我们来进入下一节.当一切联系起来的时候,你就会明了了.
2.2 是或不是的问题处理
是或不是的问题在对话时显得相当简洁,同时在结构上和之前显示对话的样式也很相似,因为它们都由对话引起.
message $AskMe
$AskMe 1 = Would you like a Lava Cookie?
boxset 5
以上的脚本和之前的很相似,唯一的区别就是命令boxset后的数字了.我们前面学过,6表示普通的文本对话框,那么5呢?5则表示一个"是或否"的选择框.游戏中我们经常见到这样的选择框,不是吗?比如在捕捉到新精灵时,系统会自动问你,要起昵称吗,此时用到的就是这个了.
与checkflag型的语法不同,语句块是不可以直接跟在if之后的,我们需要这样做:
compare LASTRESUILT B_TRUE
if B_False goto $DontGet
compare命令是在做对比,即如果以上的YES OR NO的问题中你选则了和YES不同的答案,那么将跳转到$DontGet部分的脚本.
当然,compare命令不只可以用在YES OR NO的问题判断中,它还可以处理其它多值问题当中,这一点我们将在增加精灵一节展示出来,你会发现那是多么的事半功倍.
而现在,我们得看看如何接收物品了.
2.3 接收物品
在上例中,我们最终会得到一块饼干,饼干的值是0x26.你可以从附件中的items.txt获得(L:文章的最后我会提供下载的).
在获得饼干的过程中不必担心背包已满而发生数据溢出的问题,系统会自动处理这一切:回绝别人的赠送.
紧跟着上面的代码,我们还要加一句:
setflag 0x200
很眼熟吧?这就是上节中我们检查的那个标识,有了setflag这个命令,标识0x200就被建立起来了,而当checkflag再次检查时,得到的结果就是B_TRUE了.
现在我们来结束这个脚本,写上:
Release
end
完整的脚本就是:
#org $Startscript
Lock
Faceplayer
checkflag 0x200
if B_TRUE goto $GotCookie
message $AskMe
$AskMe 1 = Would you like a Lava Cookie?
boxset 5
compare LASTRESUILT B_TRUE
if B_False goto $DontGet
giveitem 0x26 1
setflag 0x200
Release
end
#ORG $GotCookie
Lock
Faceplayer
message $NoCookie
$NoCookie 1 = I'm not made of cookies!\lYou only get one.
boxset 6
release
end
#ORG $DontGet
Lock
Faceplayer
message $AllMine
$AllMine 1 = All the more for me!
boxset 6
release
end
如果你还不能理解整个脚本,那么请让我来注释一番:
脚本$Startscript部分
锁定人物
面向主角
如果标识0x200存在,则跳转至$GotCookie部分
否则显示$AskMe部分的信息
$AskMe表示Would you like a Lava Cookie?
弹出YES OR NO选择框
对比选择框结果和 B_TRUE
如果不匹配则跳转至$DontGet部分
否则将饼干给予1块
设立标识0x200
恢复人物状态
脚本结束
脚本$GotCookie部分
锁定人物
面向主角
显示信息$NoCookie
信息$NoCookie表示I'm not made of cookies!换行You only get one.
弹出标准文本框
恢复人物状态
脚本结束
脚本$DontGet部分
锁定人物
面向主角
显示信息$AllMine
信息$AllMine表示All the more for me!
弹出标准文本框
恢复人物状态
脚本结束
2.4 检查物品
我们有时会考虑这样一种情形:
1. 首先我们激活一个NPC.
2. 如果你有一块饼干,那么她会用一个超级球作为交换.
3. 如果你在上文的脚本中没有获得饼干她会说她想要饼干.
4. 如果你给过她饼干了,再次对话时她会说十分感谢.
这个构思把我们之前所写的脚本紧紧的联系到了一起,这正体现出RPG游戏一贯严谨的剧情风格.
因为上例中我们已经使用了标识0x200,所以本次的例子我们将使用标识0x201,同时再启用一些新的地址变量,比如$GotBall.
现在来接触一下新的命令:
Checkitem 0x26
Checkitem是一个检查物品数量的命令,它返回的值是一个数字.而且这个返回值是可以被命令compare所使用的,比如:
Compare LASTRESULT 1
表示比较结果和1是否相同,结果就是上面Checkitem返回的值,那么我们就可以这么理解:
Compare Checkitem 0x26 1
当然,这只是我们所想象的过程,真正脚本在处理时必须写作:
Compare LASTRESULT 1
但是这个脚本在我们的剧本中只能用来判断有或是没有饼干,也就是比较0和1,尽管正常情况下饼干只能得到一块,但如果发生意外了呢?──难道有两块饼干就不能换超级球了么?
我们必须考虑一个范围的问题,也就是说,当背包中只要有饼干就换球,而不仅仅是1块饼干.我们用如下的命令格式来完成它:
B_<< 小于 (0)
B_== 等于 (1)
B_>> 大于 (2)
B_<= 小于等于 (3)
B_>= 大于等于 (4)
B_!= 不等于 (5)
括号内的数字表示的是另一种表达方式,我们暂且不管.
用上面的语句格式,就可以拓展我们的IF判断命令了:
#Org $StartScript
checkflag 0x201
if B_True goto $GotBall
checkitem 0x26
compare LASTRESULT 1
if B_<< goto $NoCookie
2.5 删除物品
我们来瞧瞧已经完成的脚本:
$WantBall 1 = Oh, You have a lavacookie.\pIf you give it to me I'll\lgive
you this UltraBall...\pWhat do you say?
message 5
boxset 5
compare LASTRESULT 1
if B_FALSE goto $DontGet
在这之后NPC便会给主角一个超级球,但是问题也来了:饼干仍旧在主角的背包当中,于是我们得加上这样一个命令使得交易公平起来:
removeitem 0x26 1
参数格式和giveitem命令完全一样,连在一起就是:
giveitem 0x2 1
removeitem 0x26 1
而如果我们希望5个饼干才能换取一个超级球,那么则可以这样:
compare LASTRESULT 5
if B_<< goto $NoCookie
giveitem 0x2 1
removeitem 0x26 5
最后别忘了再加上:
Release
end
现在来看看完善后的脚本:
#Org $StartScript
checkflag 0x201
if B_True goto $GotBall
checkitem 0x26
compare LASTRESULT 1
if B_<< goto $NoCookie
message $WantBall
$WantBall 1 = Oh, You have a lavacookie.\pIf you give it to me I'll\lgive you this UltraBall...\pWhat do you say?
boxset 5
compare LASTRESULT 1
if B_FALSE goto $DontGet
giveitem 0x2 1
removeitem 0x26 1
Release
end
#ORG $GotBall
Lock
Faceplayer
message $LikeCookie
$LikeCookie 1 = Thanks for the cookie!
boxset 6
release
end
#ORG $NoCookie
Lock
Faceplayer
message $LoveCookie
$LoveCookie 1 = I Absolutely LOVE Lava Cookies!\lThey're Just so Spicy!
boxset 6
release
end
#ORG $DontGet
Lock
Faceplayer
message $AAAW
$AAAW 1 = Aaw C'Mon. It's a fair trade!!\nI Love those things.
boxset 6
release
end
这次我不再翻译了,看不懂的人得再阅读上文.
以上就是第二部分的全部了.