《哈迪斯》自带的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😂 好吧,这不重要了。我在整个过程中学到了很多。而且,我所做的工作在未来是可复用的✌

相关推荐
unix2linux1 天前
YOLO v5 Series - Image & Video Storage ( Openresty + Lua)
yolo·lua·openresty
最后一个bug1 天前
如何理解Lua 使用虚拟堆栈
linux·c语言·开发语言·嵌入式硬件·lua
半夏知半秋3 天前
lua-lru缓存算法解析
笔记·学习·算法·缓存·lua
最后一个bug3 天前
C语言执行Lua进行错误处理
linux·服务器·c语言·开发语言·嵌入式硬件·lua
袁庭新3 天前
Lua如何连接MySQL数据库?
redis·mysql·lua·lua5.4·袁庭新
红黑色的圣西罗3 天前
Lua 实现继承的一种方式
开发语言·lua
weixin_428498495 天前
Lua资料
开发语言·lua
Clown955 天前
go-zero(四) 错误处理(统一响应信息)
开发语言·golang·lua
半夏知半秋6 天前
lua实现雪花算法
开发语言·笔记·算法·lua
最后一个bug6 天前
lua调用C语言函数,在函数中进行类型检查
linux·c语言·开发语言·lua