3DMGAME 3DM首页 新闻中心 前瞻 | 评测 游戏库 热门 | 最新 攻略中心 攻略 | 秘籍 下载中心 游戏 | 汉化 购买正版 论坛

注册 登录

QQ登录

只需一步,快速开始

查看: 6498|回复: 3
打印 上一主题 下一主题

[原创] 部落与弯刀 Mod制作教程 Lua篇

[复制链接]

16

主题

190

帖子

1万

积分

Mod站 原创组

Rank: 12Rank: 12Rank: 12

贡献度
1300
金元
117759
积分
17026
精华
5
注册时间
2015-6-22

3DM MOD站(黄金)

跳转到指定楼层
主题
发表于 2021-7-1 13:34 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 魔剑圣尊 于 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

查看全部评分

回复

使用道具 举报

16

主题

190

帖子

1万

积分

Mod站 原创组

Rank: 12Rank: 12Rank: 12

贡献度
1300
金元
117759
积分
17026
精华
5
注册时间
2015-6-22

3DM MOD站(黄金)

舒服的沙发
 楼主| 发表于 2021-7-3 16:46 | 只看该作者
二、弯刀的脚本环境变量与函数封装
接上一篇的工程文件
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函数测试1
  
SELECT
any
any
100
0
0
 
[%tagrole%][<>][$null$]
SUB_EVENT.Lua函数测试1
[[yellow:升级]]
打开剧情事件Excel,加入以下一行内容:
  
Lua函数测试1
  
 
RUN_SCRIPT_FUNC*example1#AddRoleLevel
1[=]1:SUB_EVENT_RETURN*
保存,构建,进入游戏
找到一个未满级的角色,对话
点击升级后,离开对话,重新打开队伍面板后,可以看到角色已经升了一级

回复 支持 反对

使用道具 举报

16

主题

190

帖子

1万

积分

Mod站 原创组

Rank: 12Rank: 12Rank: 12

贡献度
1300
金元
117759
积分
17026
精华
5
注册时间
2015-6-22

3DM MOD站(黄金)

硬硬的板凳
 楼主| 发表于 2021-7-3 18:30 | 只看该作者
本帖最后由 魔剑圣尊 于 2021-7-3 18:34 编辑

三、断点调试与数据查看
1.断点调试的功能与作用
断点,指让程序中断在某个点上。是常见的程序调试的方式之一。
断点调试可以用于查看在当前断点处,程序的上下文变量的值,可以较为清晰直观的分析程序的运行情况。

而在弯刀的lua运行过程中,断点调试的作用不仅在于查看程序的运行情况,还能通过xlua反射出来的数据查找更多官方没用公开的函数方法与成员变量。
2.准备工作1.断点工具
在官方的教程中,他们推荐使用luaPanda插件进行lua断点调试
但是在本篇教程里,我们将使用EmmyLua插件进行断点调试
请按需选择调试方法。
官方使用的luaPanda断点调试教程地址:

2.插件介绍
EmmyLua插件是一个拥有代码提示、语法检查、引用查找、类型标注、格式化代码等多功能的Lua插件,目前拥有VsCode版本与IntelliJ版本。
仓库地址:

本篇教程,我们将以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 Debug
3.选择附加到弯刀的游戏进程 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或队伍ID
whereBindSubID对应 设施ID
这样,当需要判断一个角色的位置时,我们便能使用这些从断点数据里挖掘的变量

这只是断点的用处之一,更多的用法还有待你们的挖掘。



回复 支持 反对

使用道具 举报

18

主题

1万

帖子

5万

积分

游戏圣者

Trainer Tester

Rank: 12Rank: 12Rank: 12

贡献度
355
金元
514248
积分
52865
精华
2
注册时间
2009-7-6

玛丽·萝丝~端午节专属勋章3DMer(永久)3DM MOD站(白银)

冰凉的地板
发表于 2021-7-28 00:26 | 只看该作者
路过,支持一下LZ~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|3DMGAME ( 京ICP备14006952号-1  沪公网安备 31011202006753号

GMT+8, 2026-3-31 19:18 , Processed in 0.033118 second(s), 19 queries , Memcached On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表