《哈迪斯》自带的Lua解释器是哪个版本?

玩过《哈迪斯》(英文名:Hades)吗?最近在研究怎么给这款游戏做MOD,想把它的振动体验升级到更高品质的RichTapN站下载了一些别人做的MOD,发现很多都基于相同的格式,均是对游戏.sjon文件或.lua文件的修改。我们也可以在游戏的安装目录 {installation_path}\Content下看到,Game子目录里有很多.sjon文件,Scripts子目录里有很多.lua文件。很显然,这款游戏支持Lua脚本。如果我要给游戏扩展功能,势必也要写Lua脚本代码。Lua有很多历史版本,需要考虑新写代码的兼容性。那么,《哈迪斯》自带的Lua解释器到底是哪个版本呢?这便是本文标题的由来。

于是,我到Lua.org官网查看了它的版本历史,发现Lua 最近几个版本的发布时间分别是:

  1. Lua 5.4:2020年6月。最新版5.4.6发布于2023年5月。
  2. Lua 5.3:2015年1月。
  3. Lua 5.2:2011年12月。
  4. Lua 5.1:2006年2月。
  5. Lua 5.0:2003年4月。

而《哈迪斯》最早是在2018年12月发布的。猜测它用的Lua不是5.3就是5.2吧。我需要再去验证一下。

我在N站下载了一个叫"Multiplier Config"的MOD,它能在战斗场景下动态调整给主角或敌人带来的伤害数值。按照网站上的指示安装好MOD。然后,我需要修改其中的MultiplierConfig.lua。我本想加一行print(_VERSION)来打印Lua的版本号。问题是,我到哪里能看到这个打印信息呢?

我有个想法。因为RichTap Windows SDK是以DLL的形式提供的,我在Lua代码里识别游戏场景后是需要调用这个DLL来触发高品质振动的。我何不在这个DLL里实现一个ShowMsg函数,让它把收到的内容以Windows MessageBox的方式弹出来呢。经过一番研究,发现能被Lua代码调用的DLL是需要特殊定制的 ,那我就重新开发一个最简单的"转发器"DLL吧,这篇文章介绍了关键点,美中不足的是作者没有提供拿来即用的源代码工程。于是我在GitHub找了一个,是一个叫swerg的俄罗斯哥们开发的。swerg维护了QUIK工具包,他的simple-lua-c-dll工程也依赖那个工具环境,具体来说是他自己编译的Lua解释器qlua.dll。通过Dependency Walker也能确认这一点:

我想尽可能减少依赖!看来我还不得不自己编译Lua源代码呀! 感谢faybull的这篇文章:"Windows下lua的编译与环境搭建",写得很清晰,看完一遍就懂了!不过我下载的是Lua 5.2.4的源代码,代码工程上传到GitHub了,我编译出了自己的lua.exe、lua52.dll和lua52.lib!然后我从swerg的simple-lua-c-dll fork了一个版本出来,再把我编出来的库文件以及相应的头文件用到我fork出来的simple-lua-c-dll工程,稍作修改后便顺利编译通过了。写了最简单的测试脚本test1.lua:

Lua 复制代码
print(_VERSION)
print("Hello World")

然后在控制台运行:lua.exe {path}\test1.lua,顺利通过!

接下来,我就要给simple-lua-c-dll实现ShowMsg函数了:

cpp 复制代码
static int forLua_ShowMsg(lua_State* L) {
	const int n = lua_gettop(L);
	if (n > 0) {
		int type = lua_type(L, 1); // 只处理第一个输入参数

		if (type == LUA_TNUMBER) {
			char strMsg[100] = { 0 };
			sprintf(strMsg, "The number is %.2f", lua_tonumber(L, 1));
			MessageBox(NULL, strMsg, _T("QM"), MB_OK);
		}
		else if (type == LUA_TSTRING) {
			const char* pStr = lua_tostring(L, 1);
			if (pStr) {
				MessageBox(NULL, pStr, _T("QM"), MB_OK);
			}
		}
	}

	return(1);
}

将编译出来的luacdll.dll拷贝到游戏安装目录的{installation_path}\x86下,也即把它跟主程序Hades.exe放在一起。修改MOD的MultiplierConfig.lua脚本如下:

Lua 复制代码
ModUtil.WrapBaseFunction("Damage",
  function(baseFunc, victim, triggerArgs)
    local multiplier = MultiplierConfig.Config.Multiplier

    -- My codes begin
    luacdll = require("luacdll")
    if luacdll ~= nil then
      luacdll.ShowMsg(_VERSION)
    end
    -- My codes end

    if victim ~= nil then

      if victim == CurrentRun.Hero then
        triggerArgs.DamageAmount = triggerArgs.DamageAmount * multiplier.DamageTaken
      else
        triggerArgs.DamageAmount = triggerArgs.DamageAmount * multiplier.Damage
      end

    end

    return baseFunc(victim, triggerArgs)

  end
)

见证奇迹的时刻到了!运行游戏。在进入战斗场景后,很快就会看到弹出这样的消息框:

完美!!!然后......然后......我在游戏主程序所在的目录下看到了lua52.dll😂 好吧,这不重要了。我在整个过程中学到了很多。而且,我所做的工作在未来是可复用的✌

相关推荐
旷世奇才李先生1 天前
Lua 安装使用教程
开发语言·lua
Accpdaiyekun1 天前
C# 操作mongodb 多次查询快还是使用管道查询速度快
mongodb·c#·lua
快下雨了L2 天前
Lua现学现卖
开发语言·lua
WIN赢11 天前
PostMan使用
测试工具·lua·postman
多多*11 天前
计算机网络期末 网络基础概述
运维·服务器·网络·数据库·计算机网络·oracle·lua
12 天前
Lua复习之何为闭包
开发语言·unity·游戏引擎·lua·交互
码上库利南12 天前
详解Redis的LUA脚本、管道 (Pipelining)、事务事务 (Transactions)
数据库·redis·lua
RPGMZ12 天前
RPGMZ 游戏引擎如何与lua进行互相调用 初探
开发语言·javascript·游戏引擎·lua·rpgmz
Hello.Reader13 天前
Lua 事务双写、RedisGears 异步双写、零停机索引迁移与容量预估
开发语言·lua
虾球xz13 天前
CppCon 2017 学习:Howling at the Moon: Lua for C++ Programmers
开发语言·c++·学习·lua