部落与弯刀 Mod制作教程 Lua篇
本帖最后由 魔剑圣尊 于 2021-7-3 16:42 编辑导言其实部落与弯刀在2020年的4月更新里就加入了Lua,但是那时候的官方接口还很少,加上我也没太玩明白Lua接入后如何使用,所以一直没动笔。现在终于有空了,所以就来填个坑。
一、让Lua运行在弯刀的世界准备1.此教程默认观看者会写部落与弯刀的剧情指令,有过mod构建的经验。如果没有经验,可以参考我教程的基础篇
2.此教程不包括Lua的基础语法教学如果没学过Lua,推荐观看菜鸟教程Lua
3.请准备一个可以编写lua的编辑器此处推荐使用vscode或jetbrain的IDE,配合Emmylua插件
4.为IDE配置.lua.txt的后缀为lua,此处可参考官方WIKI的设置方法。http://blywd.hanjiasongshu.com/index.php?title=%E6%B8%B8%E6%88%8F%E4%B8%AD%E8%B0%83%E7%94%A8LUA%E8%84%9A%E6%9C%AC%E7%9A%84%E5%BC%80%E5%8F%91%E5%8F%8A%E8%B0%83%E8%AF%95
1.新建一个工程简易工程即可,我取名为LuaExample1对设置没有太多要求,随便写写就行
2.添加Lua导入在mod工程的Res目录,新建文件夹,命名LuaScripts打开mod工程的interface/overrides.txt输入以下内容:RES\LuaScripts\* >:\BuildSource\LuaScripts\*文件
3.添加剧情Excel与触发器Excel从游戏的目录:DesertLegend\ModSamples\Example_ExcelReference\excel\Main下复制C触发器_Triggers_Common.xlsx与 J剧情事件_StoryEvents_Common.xlsx到mod工程的Excel文件夹下
打开valuebundle/INDEX_Source.xml 在文档中加入以下两行
<convert reg="event_trigger_pojo_new.xml"from="C触发器_Triggers_Common.xlsx"need_translate="false" /><convert reg="storyevent_pojo_new.xml"from="J剧情事件_StoryEvents_Common.xlsx"need_translate="false" />
注:在多语言更新后,弯刀的Excel分为了两种,老版本的中文Excel,新版本的双语Excel。新老版本使用的Pojo文件的区别是新版本在老版本的Pojo后加了_new后缀注2:XML里的need_translate为是否为游戏开启翻译功能,不写多语言mod的话推荐关闭,该选项对于部分Excel会有破坏性修改(加入语言标记等)
随后删除valuebundle文件夹下的default.xml。注3:在某次版本更新后,这个文件会对游戏里的Excel文件引用产生影响,但是该文件可以由Index文件自动生成,因此推荐在Index修改后删除该文件,由mod构建时自动生成。
4.第一个Lua文件新建一个文本文件,命名为example1.lua.txt注:由于弯刀资源框架的加载限制,所有lua文件需要以.lua.txt结尾
在写lua文件之前,我们先来熟悉一下弯刀调用lua的指令以上的指令里,RUN_SCRIPT有明显的局限性,而且在使用时会留下很多奇怪的bug,因此被列为不推荐使用。而我们主要要使用的lua调用指令为:RUN_SCRIPT_FUNC*脚本相对路径文件名标准方法名称(脚本中的方法名,参数为传入的环境变量)这句指令的意思是调用脚本中的一个函数,同时该函数有一个环境变量参数那么打开Lua文件,先定义我们的第一个函数:
function HelloWorld(args) print("HelloWorld")end
将该函数写入lua文件,保存。打开部落与弯刀,先打开调试日志工具,然后构建mod,调试时启用mod后进入游戏。 进入游戏后,打开游戏内控制台,输入:RUN_SCRIPT_FUNC*example1#HelloWorld点击执行。 在调试日志窗口,我们可以看到这样一条输出:那么到此,我们的第一个lua文件就成功被加载进部落与弯刀并运行了。
二、弯刀的脚本环境变量与函数封装接上一篇的工程文件1.环境变量是什么细心的小伙伴应该能发现,在上一个文件里,我在函数里定义里一个args变量,那这个变量的作用是什么呢? 在弯刀里,每个事件实际上都有一个环境变量,比如在进入城镇的事件里,就储存里当前城镇是什么;在路上遇到其他队伍时,环境变量里储存里对方是哪个角色。因为有环境变量,才能在各个事件里区分目标人物与目标地点。 2.环境变量参考打开游戏目录 DesertLegend\ModSamples\ScriptInterfaces在这个文件夹下,存储着弯刀对lua开放的各种参考脚本文件,以下是各文件的注解:GameCoreHelper.cs --弯刀对Lua开放的游戏工具类GUIHelperInterface.cs --弯刀对Lua开放的GUI工具类IGameContainer.cs --游戏里的储存容器的接口IGameRole.cs --游戏里的角色的接口IResourceOwner.cs --游戏里资源持有者(如角色)的接口ITeamInMap.cs --游戏里大地图队伍的接口RuntimeArgVals.cs --游戏里的环境变量类 我们现在的目标是RuntimeArgVals.cs这个文件,打开他打开之后,里面的内容是C#的类定义,没学过C#的小伙伴可能看着有些迷糊,不过此处只需要清楚,类里定义的所有成员变量都是传入脚本的args变量可以使用的即可。3.使用环境变量修改lua文件里的HelloWorld函数,改成如下形式:function HelloWorld(args) print("角色ID:"..args.CurTagRoleID)end 构建后进入游戏,从控制台调用以下脚本(注,复制后一起粘贴进控制台,不要分开调用):SET_TAGROLE*主角RUN_SCRIPT_FUNC*example1#HelloWorld 恩,很好,控制台输出了……主角! 别急,这并不是一个没用的举动,这里我们是手动传入了TarRole的ID,但是在实际的事件调用过程中,TagRole是由游戏自动填写的,因此我们可以再做一丢丢(指尖宇宙)的修改。 4.把Lua脚本封装成指令接下来,我们打开GameCoreHelper.cs 文件,找到以下方法:该方法的作用是返回一个角色的数据,在Lua里的调用方法为:CS.GameCoreHelper.GetRole(roleName)CS是xlua调用C#的通用协定前缀,GameCoreHelper是这个工具类的类名。可以看出C#的方法在lua里调用,基本大差不差。 我们用一个变量接收返回的Role数据local role = CS.GameCoreHelper.GetRole(args.CurTagRoleID) 对于这个数据,该如何使用?打开IGameRole.cs从这里可以看到,RoleRuntimeData继承了IGameRole接口,不理解继承和接口也没关系,只需要知道下面的属性都可以在lua里使用即可。我们本次翻到下面两个方法定义:这次我们就用这两个接口,封装一个给目标角色升一级的方法。在Lua里定义以下函数:function AddRoleLevel(args) local role = CS.GameCoreHelper.GetRole(args.CurTagRoleID) role:AddExp(role:GetRoleLevelUpExp())end该函数的功能一目了然,获取一个角色升级所需要的经验值,为该角色添加升级所需的经验。注:冒号与点号的区别在Lua里,点号用于获取表(table)里的一个任意物体,而冒号,则是在表里获取函数后调用时,将自己作为函数的第一个参数。 如:a:b()等价于a.b(a) 而xlua在调用C#的函数时,如果是非静态函数,则需要将自身作为第一个参数,传入到函数当中。 接下来打开触发器Excel,加入以下一行内容(注:从官方文件复制的Excel记得要清空一下):
Lua函数测试1SELECTanyany10000 [%tagrole%][<>][$null$]SUB_EVENT.Lua函数测试1[]
打开剧情事件Excel,加入以下一行内容:
Lua函数测试1 RUN_SCRIPT_FUNC*example1#AddRoleLevel1[=]1:SUB_EVENT_RETURN*
保存,构建,进入游戏找到一个未满级的角色,对话点击升级后,离开对话,重新打开队伍面板后,可以看到角色已经升了一级
本帖最后由 魔剑圣尊 于 2021-7-3 18:34 编辑
三、断点调试与数据查看
1.断点调试的功能与作用断点,指让程序中断在某个点上。是常见的程序调试的方式之一。断点调试可以用于查看在当前断点处,程序的上下文变量的值,可以较为清晰直观的分析程序的运行情况。
而在弯刀的lua运行过程中,断点调试的作用不仅在于查看程序的运行情况,还能通过xlua反射出来的数据查找更多官方没用公开的函数方法与成员变量。2.准备工作1.断点工具在官方的教程中,他们推荐使用luaPanda插件进行lua断点调试但是在本篇教程里,我们将使用EmmyLua插件进行断点调试请按需选择调试方法。官方使用的luaPanda断点调试教程地址:http://blywd.hanjiasongshu.com/index.php?title=%E6%B8%B8%E6%88%8F%E4%B8%AD%E8%B0%83%E7%94%A8LUA%E8%84%9A%E6%9C%AC%E7%9A%84%E5%BC%80%E5%8F%91%E5%8F%8A%E8%B0%83%E8%AF%95
2.插件介绍EmmyLua插件是一个拥有代码提示、语法检查、引用查找、类型标注、格式化代码等多功能的Lua插件,目前拥有VsCode版本与IntelliJ版本。仓库地址:https://github.com/EmmyLua/VSCode-EmmyLuahttps://github.com/EmmyLua/IntelliJ-EmmyLua
本篇教程,我们将以VsCode为编辑器使用该插件。
3.插件安装打开VsCode,在侧边栏里选择扩展,搜索Emmylua,安装即可。
4.工作区设置如果想要调试功能能正常运行,则VsCode必须以工作区的方式打开。从VsCode顶部 文件-将文件夹添加到工作区或 在工程目录空白处右键,选择通过VsCode打开 来将整个工程文件夹或包含LuaScripts的目录在VSCode中打开。
打开后,我们需要保存工作区,从VsCode顶部 文件-将工作区另存为 把工作区设置储存为一个文件。此时VsCode顶部应当显示:这说明工作区已经正确保存了。
3.开始断点在LuaScripts文件夹下新建一个Lua文件,命名为example2.lua.txt在文件里输入以下函数:function GetPlayer(args) local player = CS.GameCoreHelper.GetRole("主角") print(player.Name)end随后,我们在print函数一行的左侧,点击行号边上的小红点,即为该脚本添加了一个断点。光添加断点是无法生效的,我们需要用调试器附加到弯刀上,才能成功断点。打开调试器步骤:1.按F5 或 从VsCode顶部点击 运行-启动调试2.在如下窗口中选择EmmyLuaAttach Debug3.选择附加到弯刀的游戏进程 DesertLegend.exe上
附加成功后,VsCode左侧会切换到调试栏,而底部也会变为橙色,表明此时已经进入了Debug模式。构建Mod,进入游戏,在控制台内输入如下内容:RUN_SCRIPT_FUNC*example2#GetPlayer如果一切顺利的话,输入完后,游戏会卡住,代表此时已经断点成功了。
我们切换到VsCode界面,此时窗口呈现如下状态:我们来按顺序说明各个窗口的作用:1.变量窗口变量窗口展现了当前函数环境内的环境变量值,包括Lua的_Env环境,以及函数里定义的local变量。可以通过折叠展开来查看table或userdata类型变量下的具体内容2.监视窗口监视窗口与变量窗口略有不同,默认监视窗口是一片空白的。将鼠标挪到监视窗口上后,会出现一些新的按钮:此处可以通过+号键,来手动键入需要查看的变量值,如:输入player.Name监视窗口立即返回了获取到的变量数值3.调用堆栈此处显示了Lua里的函数调用堆栈关系,我们目前只使用了一个函数,如果Lua里有多个函数相互调用后进入断点时,便可以使用此窗口来切换当前的堆栈信息。堆栈切换后,变量与监视窗口皆会受到影响,展示的信息会有所变化。4.代码窗口代码窗口与之前有所不同,表现在于:1.当前断点的行的背景变为了黄色2.变量的后面出现了变量说明当断点成功后,将鼠标放到变量上即可查看当前变量的数据,如图所示:通过这种方式,可以快速查看变量的内容,方便找到bug所在。5.断点工具条该工具条内的功能也可在VsCode顶部 运行 栏找到通过该工具栏,可以从断点处继续运行等等。4.从断点获取信息这一章节,断点并不单纯为了寻找程序bug,而是同时为寻找Mod所需要的函数。例如,如果我想获取一个角色当前的位置,则在断点数据里,我们可以寻找对应的内容:通过查阅弯刀Wiki,我们能很快找到对应的解释通过分析后可以知道whereType 对应 位置代码whereBindID 对应 地点ID或队伍IDwhereBindSubID对应 设施ID这样,当需要判断一个角色的位置时,我们便能使用这些从断点数据里挖掘的变量
这只是断点的用处之一,更多的用法还有待你们的挖掘。
路过,支持一下LZ{:3_118:}~
页:
[1]