跳转到内容
输入关键词开始搜索。

游戏中调用LUA脚本的开发及调试

开发者可以使用任何趁手的工具来编写LUA脚本。目前推荐使用 VSCode + EmmyLua 插件来编辑 LUA 脚本,并能实现断点调试、变量监控等功能

Emmylua.png

  • 由于xlua的lua文件格式是.lua.txt的,所以VSCode默认情况下并不能将其识别为lua文件,需要我们通过settings来完成

Imgpic 2.png

  • 打开自定义设置的JSON文件,并添加如下内容:
{
"files.associations": {
"*.lua.txt":"lua"
},
"luaide.apiType": "xlua",
}

注意:在选择配置文件时一定要选择工作区设置,而不是用户设置。选择之后会在工程根目录下生成一个 .vscode 文件夹,里面有一个 settings.json;如果 .lua.txt 文件中出现了 Lua 语法高亮,则为配置成功。

Imgpic 3.png

Imgpic 4.png

游戏中的 Lua 脚本代码最终必须映射到资源目录 Asset\BuildSource\LuaScripts\ 下运行。运行时可以使用 RUN_SCRIPT 或者 RUN_SCRIPT_FUNC 来调用脚本或者脚本中的函数。

例如:

RUN_SCRIPT_FUNC*test_script#TestFunc1
  • 如果想要调试功能能正常运行,则VSCode必须以工作区的方式打开。

从 VSCode 顶部选择“文件 -> 将文件夹添加到工作区”,或在工程目录空白处右键选择通过 VSCode 打开,将整个工程文件夹或包含 LuaScripts 的目录在 VSCode 中打开。

打开后,需要保存工作区。从 VSCode 顶部选择“文件 -> 将工作区另存为”,把工作区设置储存为一个文件。此时 VSCode 顶部应当显示:

338*42像素

  • 开始断点
  1. 按 F5,或从 VSCode 顶部点击“运行 -> 启动调试”。
  2. 在如下窗口中选择 EmmyLua Attach Debug

Lua Img 3.png

  1. 选择附加到弯刀的游戏进程 DesertLegend.exe 上。

Lua Img 2.png

附加成功后,VSCode左侧会切换到调试栏,而底部也会变为橙色,表明此时已经进入了Debug模式。

Lua Img 4.png

当需要将自定义的Lua逻辑挂载到游戏中时,可以通过插件设置表来实现。通过指定要挂载的逻辑,并绑定挂载的函数后,游戏会在对应逻辑执行时,自动执行挂载逻辑。

推荐使用该方式新增Lua逻辑,以避免Lua脚本的冲突

在插件设置表中可配置的Lua挂载逻辑如下

类型目标字段目标值函数范例说明
ADDon_game_start脚本名#函数名function onGameStart()
— 进入游戏时进行的操作
end
进入游戏或载入游戏后运行
ADDget_lua_intAD脚本名#函数名function GetLuaIntVal(valKey, contextArgVal)
if string.find(valKey,‘test=’) ~= nil then
local key = string.sub(valKey, 6)
return tonumber(key)
elseif valKey == “rand100” then
return math.random(1, 100)
end
return 0
end
通过lua实现自定义的整形变量查询,对应查询指令[$lua_int:KEY$]
valKey: 类型string,用指令传入进来的KEY
contextArgVal: 类型RuntimeArgVals,当前脚本的环境参数
返回0代表查询没有结果,因此将会继续调用其他的lua查询挂载函数,直到获得有效结果为止。
返回非0数值会立即结束查询,并将该值返回到查询指令的结果当中。
ADDget_lua_str脚本名#函数名function GetLuaStringVal(valKey, contextArgVal)
if valKey == “test” then
return “ok”
end
return ""
end
通过lua实现自定义的字符串变量查询,对应查询指令[$lua_str:KEY$]
valKey: 类型string,用指令传入进来的KEY
contextArgVal: 类型RuntimeArgVals,当前脚本的环境参数
返回nil或空字符串代表查询没有结果,因此将会继续调用其他的lua查询挂载函数,直到获得有效结果为止。
返回非空字符串会立即结束查询,并将该值返回到查询指令的结果当中。
ADDgame_hour_logics脚本名#函数名function OnGameHourLogic(curDay, curH)
if curH == 7 then
—每天固定时间检测队伍成员好感度
PlayerPartyMemberLeaveCheck(curDay);
elseif curH == 9 then
—阵营势力自定义逻辑遍历
CampDailyUpdateLogic();
end
end
游戏中游戏时间每过1个单位执行的逻辑(每天12个单位)
curDay: 类型int,游戏当前天数
curHour: 类型int,游戏当前天单位数,游戏内一天12个单位
在该接口中尽量不要集中进行逻辑判断,或者尽量将逻辑部分分散到各个单位之中,以避免游戏卡顿
ADDcamp_daily_logics脚本名#函数名function OnCampDailyLogic(tagCamp, curDay)
— 进行阵营逻辑判断
end
游戏内阵营每日执行逻辑
tagCamp: 类型HanFramework.GameCampRtData,当前进行逻辑判断的阵营
curDay: 类型int,游戏当前天数
只有参与游戏斗争的已激活阵营才会执行阵营逻辑

游戏的一些核心逻辑放在 LUA 脚本中,MOD 制作者可以通过覆盖对应脚本来调整外交、内政、好感度等逻辑。

目前游戏内置的主要逻辑接口代码写在映射路径 Asset\BuildSource\LuaScripts\GameLogics.lua.txt 对应的 LUA 脚本中。该文件可以在游戏根目录下的 ModSamples\LuaScripts 文件夹中找到。通过 MOD 设置中的 override 功能映射该路径,就可以替换指定的 LUA 脚本。

GameLogics.lua.txt脚本中的主要代码接口有:

接口方法用途参数说明
OnGameStart()每次进入游戏(或是载入游戏后)会调用此接口无参数
GetLuaStringVal(valKey, contextArgVal)[$lua_str:KEY$]查询指令对应的接口valKey:查询字段的KEY
contextArgVal:查询指令调用时的环境变量参数
返回值:查询结果字符串
GetLuaIntVal(valKey, contextArgVal)[$lua_int:KEY$]查询指令对应的接口valKey:查询字段的KEY
contextArgVal:查询指令调用时的环境变量参数
返回值:查询结果整形数字
SetRoleRep(opRole, targetType, tagID, opVal, isAdd, isNotify, isChainedMode)游戏内为角色改变对应声望的接口opRole:执行操作的角色对象
targetType:操作对象类型 0:阵营 1:角色 2:地点
tagID:操作对象的ID
opVal:操作值
isAdd:是否改变模式,当为true时在原值上加减,否则为直接设置到目标值
isNotify:当涉及主角时是否进行信息播报
isChainedMode:是否进行链式操作(关联好感度的对象进行改变)
返回值:查询结果整形数字
GivePresentLogic(contextArgVal)给NPC送礼物涨好感度的逻辑接口contextArgVal:调用此逻辑时的环境变量参数
返回值:无
OnCampDailyLogic(tagCamp, curDay)阵营每日逻辑(游戏中每天都会对所有阵营执行此逻辑接口)无参数和返回值
OnAIDecideDipEvent(execCamp, dipInfo)AI势力决定外交行为的判断(玩家处理外交行为逻辑通过处理 dip_event 触发器事件来决定)execCamp:当前执行此外交事件的阵营对象
dipInfo:当前执行外交事件的详细信息,类型为DiplomaticEventInfo,其数据结构如下:
- public GameCampRtData fromCamp;
- public GameCampRtData execCamp;
- public int dipType;
- public string tagRoleID;
- public string argsVal;
- public float resultRatio;
- public bool isDecided;
返回值:无
OnDipEventCallback(dipResult, dipInfo)游戏中所有阵营执行外交事件处理结果接口dipResult:外交事件结果 true 同意 false 拒绝
dipInfo:同上
返回值:无
SetCampRl(campID1, campID2, rlState, fvOpMode, fvOpVal, isNotify)游戏中所有操作阵营外交关系时执行的接口campID1:外交关系对象A
campID2:外交关系对象B
rlState:欲改变至的外交状态 -1:不改变 0:中立 1:敌对 2:结盟
fvOpMode:外交好感度的操作方式:0:不改变 1:增加 2:设置到目标值
fvOpVal:外交好感度操作值
isNotify:当涉及玩家时是否进行信息播报
返回值:查询结果整形数字