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

相关推荐
2401_8788204714 小时前
Redis+Lua脚本实现全局令牌桶限流
数据库·redis·lua
上海合宙LuatOS3 天前
Air8000多网通信- RNDIS/ECM
物联网·lua·嵌入式开发·多网通信
Linux运维技术栈3 天前
一次暴力枚举攻击的防御实践:从 IP 封禁到 WAF,再到 Nginx+Lua 业务层防御
tcp/ip·nginx·安全·lua·云服务器
诙_4 天前
由C++速通Lua
开发语言·lua
yeshan7 天前
【Draft】基于 cluacov 的 Lua 代码分支覆盖率统计:从行级近似到指令级精确
单元测试·lua
zz0723207 天前
Redis + Lua 实现高性能分布式限流
redis·lua·aop·限流算法·分布式限流
衣舞晨风7 天前
运行时行为盲区:API7 AI 网关CPU打满故障的AI辅助事后复盘
lua·openresty·apisix·coroutine·cpu-saturation·socket-buffer
笨鸟先飞的橘猫10 天前
基于Skynet的分布式游戏场景题:大型MMO的跨服战场系统设计
分布式·学习·游戏·面试·lua
Huanzhi_Lin12 天前
skynet笔记
笔记·lua·skynet·actor·actor模型
笨鸟先飞的橘猫12 天前
MMO游戏中的“跨服团队副本”匹配与状态同步系统
分布式·学习·游戏·lua·skynet