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

相关推荐
小努蛋3 天前
linux编译openresty异常问题,lua_cjson.c:706:5: 错误: ‘for‘ 循环初始化声明只在 C99 或 C++ 模式下允许
开发语言·lua·openresty
rockey6275 天前
基于AScript的Lua脚本语言发布啦
c#·.net·lua·script·动态脚本
MC皮蛋侠客7 天前
Redis 系列(七):事务、Pipeline 与 Lua 脚本——从原子性到 Functions
数据库·redis·lua
l1t9 天前
用李红艳先生的DuckDB luajit插件批量计算数独
数据库·sql·lua·duckdb
智购科技自动售卖机厂家13 天前
从STM32到RK3588——自动售货机嵌入式主控方案的架构演进~YH
stm32·嵌入式硬件·物联网·架构·lua·零售·symfony
qq_3707730915 天前
Unity游戏xLua逆向实战:从SO版本识别到Lua脚本热替换全链路
游戏·unity·lua
k4m7v2pz17 天前
黄色警戒 Mod 移植 Chrono Divide 踩坑记录实战日志分析 + 完整移植检查清单
移植·mod·红色警戒2·chrono divide·网页红警
星空露珠18 天前
迷你世界3.0API,事件监听
开发语言·数据结构·数据库·游戏·lua
ellis197019 天前
u3d插件xLua[二]例2:U3DScripting,例3:UIEvent分析
unity·lua
寒水馨21 天前
Windows下载、安装neovim-v0.12.4(附安装包nvim-win64.msi)
windows·编辑器·vim·lua·终端·lsp·neovim