【长文多图】使用LuaEngine制作一个趣味派生mod的教程

今天给大家带来一个使用LuaEngine制作一个简单的派生mod的教程

如果有不明白的地方可以在评论中发问


Mod要达成的效果

首先要想好外面这个mod要达到什么效果,然后再思考要怎么去做,这里我想要一个连续拔刀斩的效果

思考实现方法

这里我们先思考一下,太刀有收刀和把刀的动作,如果像达到我们要的效果,我们需要在拔刀时,让刀再收回去,这样循环即可既

特殊收刀->居合拔刀斩->特殊收刀

这样的循环,如果使用fsm文件进行修改,我们可以在居合拔刀斩上添加特殊收刀的派生,大家可以试一下,这样的效果并不是很好,我们特殊收刀会有一个后退收刀的动作,拔刀斩会二连斩,动作时间都很长,显然不是我们要的效果

那么我们现在使用LuaEngine来制作这样的派生模拟,是否能达到目标效果呐

首先我们看一下lua(即LuaEngine)能做到什么,我们打开引擎文件Engine_player.lua,这个是对玩家的各项数据进行读取和操作的引擎,先找一找对派生动作进行控制的项目

在文件头部的注释中可以看到,Action中描述了玩家动作相关的数据,数据中包含了lmtID和fsm的相关数据,新接触lua和fsm、lmt的朋友可能看不太懂这些代表了什么,不过没关系,我们只需要知道,当玩家进行派生时,这些数据会随着改变,我们可以根据这些进行判断就可以了

接下来我们看引擎底部,有关数据监听修改的地方

我们可以看到这里lmtID和fsm结构都被设置了数据监听功能,当我们修改这些数据时,对应的修改将会直接体现在游戏当中

现在我们已经知道了,lua可以对我们当前的动作进行读取和修改,那么,实现方法我们改成下面这样

特殊收刀->居合拔刀斩->当第一刀斩下后打断居合拔刀斩并派生特殊收刀->取消特殊收刀前几十帧动作并完成收刀

现在有朋友要问了,怎么打断动作啊,怎么取消前几十帧啊,这里我们就要理解一下lua在进行动作修改时是机制了,相对于游戏中使用条件文件进行判断不同,lua在执行动作修改时会立马将新的动作予以执行,并不会对现有动作的状态进行判断,至于取消前几十帧的操作,可以参考前面我们观察引擎中动作的结构一样,动作帧frame也在引擎中有相应的声明

至此,我们已经完成了这个mod设计思路,接下来就是用代码将思路实现了

将思路转换成代码

相较于其他编程语音,lua相当简单,只需要懂得基本的语法就可以按照自己的思路进行编写

首先我们新建一个test.lua文件,文件可以随意起名,这里我们用test,不过重载功能只支持英文名的脚本,这里要注意一下

打开我们的脚本文件,这里你可以使用自己喜欢的编辑软件,记事本都行,我这里用的vscode,创建一个on_time()的函数,这个函数会在游戏运行过程中,随时间的变化进行运作

接下来我们要先进行引擎的初始化,写法是固定的照着抄就行,然后我们要确认一下玩家是否使用的是太刀这把武器,如果不是,接下来的脚本就不用运行了,当前玩家的武器类型同样跟我们查看动作信息一样,在引擎中可以找到

接下来,按照我们的思路,要实现的是当居合拔刀斩第一刀斩下后打断居合拔刀斩并派生特殊收刀,这里我们首先需要知道,居合拔刀斩和特殊收刀的lmtID或fsmID,这里我们可以动用lua的示例文件中包含的数据窗口快速找到这些数据

首先我们打开数据窗口的玩家数据,找到动作一栏,这里我们可以看到,当前动作(lmtID)、动作帧大小和当前动作帧(frame结构)、派生id和派生目标(fsm结构)


我们首先进行特殊收刀的动作,然后看这里的变化,特殊收刀过程中,当前动作始终是49458,派生id在收刀前是98,收刀后是99,动作帧目前这个动作我们还用不上,后面再说

然后我们进行居合拔刀斩的动作,这里可以看到,派生id只有101一个,当动作帧执行到了22帧时拔刀到了第一刀的最高点

接下来我们就可以让动作在101时且动作帧大于22时,执行派生动作,但是这样我们就会陷入一个派生循环,每当进行居合拔刀斩时都会返回特殊收刀,这里我们还需要一个条件,当满足条件时才能返回到收刀状态,我们先上代码

现在来讲解一下代码,首先第一个if

Data_Player.Action.fsm.fsmID == 101

这里判断了当前的动作是否是居合拔刀斩,还记得上面我们找到的居合拔刀斩的派生id吗,就是101,然后我们进行了动作帧的判断

Data_Player.Frame.frame > 22 and Data_Player.Frame.frame < 35

上面我们说。22开始是第一刀到了最高点时,如果往下看,35左右是第一刀斩下第二刀还没开始的时候,所以我们取这之间进行触发,至于第一个条件engine.keypad('LMouse'),我们可以查看引擎主文件Engine.lua中对于这个函数的描述


可以看到,这是一个用于检测玩家是否按下了某个按键的函数,这里我们检测了玩家是否按下了鼠标左键

当满足条件时,我们执行派生动作,让玩家的动作返回到特殊收刀上

Data_Player.Action.fsm = { fsmTarget = 3, fsmID = 98 }

这里可以看到,我们是将整个结构给了fsm ,监听结构时,我们必须将整个结构给与监听目标才能生效,结构可以直接从引擎中复制出来,根据我们找到的特殊收刀的派生信息,派生目标(fsmTarget )是3,派生id(fsmID )开始是98,所以我们将这个数据传给Data_Player.Action.fsm,这样就可以派生到我们要的动作上了

接下来,我们可以看到动作返回了特殊收刀,并从头开始执行(动作帧从0开始),这时我们可以将动作帧直接跳到即将收刀前的动作帧,这里可以多次尝试最佳时机,截取动作帧的数值,我们这里取60帧

这里可以看到,我们判断特殊收刀时,使用了lmtID,还记得我们之前找特殊收刀动作时,他的fsmid有98和99两个,而lmtid只有49458一个吗,显然我们用lmtid做判断即可覆盖整个收刀周期

如果现在我们运行这段代码,会发现收刀时卡住了,想想这是什么原因?这是因为我们在做特殊收刀判断时,仅仅参考了动作id的因素,只有是执行这个操作,就肯定会卡在60帧上,这时我们要做判断,只有当第一个操作执行的特殊收刀时,我们才进行动作帧的设置,这里我们用一个全局变量记录下动作的阶段,然后进行判断即可,代码如下


这里我们可以看到,我创建了一个全局变量actionStage,当然,这里的全局是相对于这个脚本而言,真正的全局是不用加local的,首先当没进入阶段是,我们让变量值为0,让第一个条件触发时,我们设定阶段为1,这是再进行判断,只有阶段为1时,才进行动作帧的修改,这样就能满足我们的要求了,此时我们还需要还原动作阶段为0,让其他动作打断了这套动作时,我们也应当还原动作阶段为0

后续

到现在为止,我们已经达到了我们想要的效果,不过以目前的效果而言,其实并不算满意,我们可以看到一些明显的缺点,比如每次斩击都会向前移动,动作运行起来过于平淡,速度仍然过慢等等,这些就需要接下来不断的优化脚本,添砖加瓦了

我这里给出一个完成优化的脚本,供大家参考,希望大家能做出符合自己期待的mod来

作业

都看到这里了,我也该留个随堂作业了,那么这样,做一个大锤连续锤击的mod,看大家自己发挥,1月27日前交作业还可以参赛哦。

by Alcedo 发布于 2023-01-23
打赏后可直接下载附件 赠人玫瑰 手留余香
默认
最新
1