菜鸟的只狼Talk详细教程(二)

大家好,我是Last孤影众后面还有一个点,今天专门列个专栏写一下只狼中的talk教程。

注意:阅读本文需要读者拥有魂系列参数编辑能力和最基础的事件编辑能力,想学习的可以移步琐帝BNU的参数编辑教程和我的事件编辑教程。

一、Talk的组成结构
我们先点开剑圣的talk:112240

这里我推荐大家使用visual studio code打开py文件,这样无论是查看还是编辑都非常方便,也是我很喜欢用的文本编辑器。
浏览整个talk文件,有很多我们都是不懂的,不过问题不大,因为我们并不需要看懂所有东西。首先我们可以发现,定义分两种形式:
一种是t112240_+一个数字:

一种是t112240_x+数字:

我们将前者称为触发对话,后者成为执行对话(没错我自己命名的)
触发对话指的是我们需要他来满足一些条件,来进行对话的触发,是对话必不可少的部分;
而执行对话则是在触发对话后执行命令的对话,一般情况触发对话都会链接一些执行对话,这样我们可以在触发后直接跳转到执行对话执行命令。
很关键的一点:一个对话必须至少拥有一个触发对话,不然它将无法触发条件运行执行对话
触发对话就像人体的头部起到一个接收信息指挥作用,执行语句就是躯干,没有头部一切都是空谈。
而对于执行对话,也不是毫无规律的,FS社最喜欢套模板,所以在每个talk的相同编号的执行对话的内容一般都大同小异,简单来说可以总结为以下东西:

我希望大家在新建talk编辑的时候也能遵循这个规则,不同功能的触发对话选择相应的编号,这样才不至于乱套,比较关键的是我认为esdtool解包并不完全,特别是触发对话里面肯定有很多东西没有被解包出来,所以大家照着fs社的标准来做准没错。
同样我们需要注意的是,因为解包触发对话的不完全,所以新建触发对话是个风险很大的操作,我的建议是当我们需要某种触发对话时,我们应当找到原版中有类似触发对话的敌人,将该敌人的talk文件复制并且修改编号变成我们所需要的talk文件,然后在这个复制过来的talk文件内做一些修改,而不是新建一个空白文本自行编辑。
执行对话的意义在于将庞大的内容单独放到一个对话中,并且我们可以在talk中随时随地引用,这个就类似于c语言中的子函数,我们不建立子函数也能完成一些操作,但这样一会显得代码臃肿,例如你也可以把执行对话的内容全放在触发对话中,但是这样触发对话就很庞大,不利于修改;

二来当我们需要多次进行同一操作时,多次引用执行对话是明显会方便很多的;最后一点则在于执行对话可以设置未知数,让触发对话提供未知数的具体数值带入进行计算,看起来很像事件中的通用事件,带入数值计算的类型。


二、单个对话结构
前面我们谈了整个talk的组成,一般来说是由触发对话和执行对话构成,而触发对话是必须的,执行对话则不是必要,只是为了方便表达和使用而建立。
下面我们来谈论单个对话,也就是一个触发/执行对话由哪些组成:
我们下面这个例子:

如果大家也是用vscode打开的话,可以发现这个执行对话有很多种颜色的部分构成:
首先是红色的内容,包括while(循环函数),if(条件判断函数),break(c语言里没怎么见过,大概意思就是跳出循环),pass(空操作,保证结构完整性,没有什么实际意义)等等,这些如果我们有一些c语言基础都是很好理解的。而其中的assert是很重要的部分,他能直接调用其他的执行对话。
接下来是深蓝色部分,一般都是些逻辑运算符,and not or之类的,代表一种逻辑,这个我相信有事件基础的一看就懂。
然后是淡蓝色的部分,这些一般都是对话的未知待定参数,需要我们将具体数值带入进行运算,其中这个call比较有趣,他的作用和前面的assert差不多,但是他着重于执行完对话后的结果,根据返回的结果进行一些操作。
游戏中,很多时候call会和continue配合使用,来达到一种循环检测直到成立的效果,目的就是为了让同一对话中敌人在满足条件的情况下依旧无法执行对应代码,因为检测途中,系统只会一直在call中循环,就算其他部分满足判定条件,也不会去触发。

这里的两个call+continue如果各位能看懂,就离搞懂talk不远了:首先第一个call+continue,剑圣在说完上吧只狼之后,就会处于循环检测,直到满足
f120() - f121() == 1 and not GetEventStatus(71120205):
大概意思就是一心掉了一个红点,并且还未说出热血沸腾那句话,直到这个时候才会跳出call,检测对话中的其他判定条件是否成立
第二个也是同理的,当一心被我们致命忍杀后(拥有30008特效),会跪在那里,此时call+continue锁住对话一直循环检测,直到我们不死斩将其处决,也就是他拥有特效30009之后,他会说出:动手。
但如果我们直接让一心拥有30009特效的话,他说的则不是"动手",而是"热血沸腾起来了"

所以说call+continue的使用,能让我们的对话具有顺序性,强制在某句话说在某句话之后,中途不会收到其他影响。当然我们也可以手动控制特效的添加顺序,不用call也行,这里介绍给大伙主要是方便之后在原基础上修改时不会出错。
4.回到正题,我们可以发现有很多画了黄色波浪线的语句,这些代码就是今天的重点,也是大家最想知道的:命令语句和功能语句。
功能语句一般用在条件判断if之后,设立各种各样的判断条件:

例如这里就是判断talk链接的人物是否拥有30009特效。
那么功能语句这么多到底都有代表了什么呢?这里我整理了一些,历代魂系列和只狼都包含在内:

命令语句一般用来执行命令的,例如打开菜单,给特效之类的操作,一般是在满足功能语句的条件后,进行命令语句的操作。同上,这里我整理了一些命令语句:

在talk中,所有命令语句的表达格式为:c1_xxx,这里c代表command,即命令;1代表block代表分区(意义不大,因为只有一个分区)。xxx代表的就是我上面表中语句前的编号,例如OpenBonfireSubmenu这个命令语句我们可以表示为c1_127,实际上我们看到的OpenBonfireSubmenu都是c1_127的注释,当然这个注释是作者给我们加的,不然我们打开talk啥都看不懂了,但这就代表了我们可以在对应文件中修改注释,例如这样:

这个是我自己注释的空缺功能语句,本来显示成f1_xxx的(f代表function),不过我还是建议大家使用英文,如果一个对话中半英文半中文看起来就很怪。
多的我也不说了,大家自己对照图片理解对话含义,我都整理这么完整了。
三、talk中的“talk”
上个部分我们谈到了命令语句和功能语句,其中一个我要着重介绍,那就是命令语句中的TalkToPlayer:

首先可以看到这个命令语句里有四个参数,第二个第四个不太清楚,第一个代表的是我们talkparam的编号,也就是参数编辑器中的talkparam。

打开talkparam,右边菜单栏可以看到很多项目:

也就是说talk中的对话是使用了talktoplayer,然后这个命令语句调用对应编号的talkparam,talkparam链接对应的文本和语音,最后将文本显示,语音播放在游戏中。
这里我们需要注意的点是,talkparam的编号和文本编号,语音编号并不一定是相同的(当然大部分情况下相同),如下图

文本id我相信大家都知道,目录如下:


打开就可以看到文本对应的编号:

而音频则是在sound中,对话语音被放在地图语音中,文件名格式为:vm+地图编号+_jaj.fsb
比较麻烦的事我们想看就必须要将音频解密,具体的我这里就不说了,大家自己去b站找教程学一下,很简单的东西,解密完了就可以用DSSI v2.1.exe打开音频,然后在软件中试听语音。

而TalkToPlayer的第三个参数代表的是对话出现的类型,对话可以分为战斗对话和非战斗对话,战斗对话就是一心那种,在战斗中说一些话,不会影响到玩家;非战斗对话一般是玩家主动互动触发,然后玩家会站在原地,一句一句听完对话,也可以按下互动键跳过对话。
但其实战斗对话和非战斗对话的根本区别就在于是否能跳过对话,能否移动之类的是其他命令语句的效果,如果第三个参数,也就是图中的flag14=1,那么对话不可以被跳过;反之对话可以被跳过。
四、在talk基础上修改
那么一开始修改talk,我是不建议大家直接新建对话的,我们可以先去尝试修改一些有talk的敌人,例如弦一郎,苇名一心,义父等等。
例如我们想给苇名一心进入三阶段(最后一个红点)时加个台词“还没完啊,只狼”,那么我们首先需要使用事件编辑器,检测一心红点只有1时,给予一心一个30004特效,这个特效30002到30009都能用,这个是游戏专门用来触发对话的空检测特效,但是最好不要和对话中的特效重合,避免出错。

然后模仿下下面的热血沸腾对话,仿造一个对话的触发:


最终结果如下:

接着打包文件,然后我们进入游戏中检测一下看看有没有正常触发就行了。
这里有一个要提的点,t112240_x3有四个参数,其中第二个参数代表开启的事件标志,我们可以改成-1,这样就不会改动任何eventflag。
那其实这种在原本基础上加对话是非常简单的,可以看到我就用了短短几行代码就加了一句对话,大家也可以去试试修改。
五、后话
今天先讲到这里,下一篇文章我将教大家如何新建不同类型的对话,可能就是talk教学的最终篇了,点赞100更下一篇。
