《哈迪斯》自带的Lua解释器是哪个版本?
玩过《哈迪斯》(英文名:Hades)吗?最近在研究怎么给这款游戏做MOD,想把它的振动体验升级到更高品质的RichTap。N站下载了一些别人做的MOD,发现很多都基于相同的格式,均是对游戏.sjon文件或.lua文件的修改。我们也可以在游戏的安装目录 {installation_path}\Content下看到,Game子目录里有很多.sjon文件,Scripts子目录里有很多.lua文件。很显然,这款游戏支持Lua脚本。如果我要给游戏扩展功能,势必也要写Lua脚本代码。Lua有很多历史版本,需要考虑新写代码的兼容性。那么,《哈迪斯》自带的Lua解释器到底是哪个版本呢?这便是本文标题的由来。
于是,我到Lua.org官网查看了它的版本历史,发现Lua 最近几个版本的发布时间分别是:
- Lua 5.4:2020年6月。最新版5.4.6发布于2023年5月。
- Lua 5.3:2015年1月。
- Lua 5.2:2011年12月。
- Lua 5.1:2006年2月。
- 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:
print(_VERSION)
print("Hello World")
然后在控制台运行:lua.exe {path}\test1.lua,顺利通过!
接下来,我就要给simple-lua-c-dll实现ShowMsg函数了:
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脚本如下:
ModUtil.WrapBaseFunction("Damage",function(baseFunc, victim, triggerArgs)local multiplier = MultiplierConfig.Config.Multiplier-- My codes beginluacdll = require("luacdll")if luacdll ~= nil thenluacdll.ShowMsg(_VERSION)end-- My codes endif victim ~= nil thenif victim == CurrentRun.Hero thentriggerArgs.DamageAmount = triggerArgs.DamageAmount * multiplier.DamageTakenelsetriggerArgs.DamageAmount = triggerArgs.DamageAmount * multiplier.Damageendendreturn baseFunc(victim, triggerArgs)end
)
见证奇迹的时刻到了!运行游戏。在进入战斗场景后,很快就会看到弹出这样的消息框:
完美!!!然后……然后……我在游戏主程序所在的目录下看到了lua52.dll😂 好吧,这不重要了。我在整个过程中学到了很多。而且,我所做的工作在未来是可复用的✌
相关文章:

《哈迪斯》自带的Lua解释器是哪个版本?
玩过《哈迪斯》(英文名:Hades)吗?最近在研究怎么给这款游戏做MOD,想把它的振动体验升级到更高品质的RichTap。N站下载了一些别人做的MOD,发现很多都基于相同的格式,均是对游戏.sjon文件或.lua文…...

Java内存泄漏内存溢出
1.定义 OOM内存溢出是指应用程序尝试使用更多内存资源,而系统无足够的内存,导致程序崩溃。 内存泄漏是指应用程序中分配的内存未能被正确释放,导致系统中的可用内存逐渐减少。 2.内存泄漏的原因 可能包括对象引用未被释放、缓存未被清理等。 …...

【springboot】项目启动时打印全部接口方法
方法:在你springboot项目的基础上,创建下面的类: package com.llq.wahaha.listener;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework…...

单例19c RMAN数据迁移方案
一、环境说明 源库 目标库 IP 192.168.37.200 192.168.37.202 系统版本 RedHat 7.9 RedHat 7.9 数据库版本 19.3.0.0.0 19.3.0.0.0 SID beg beg hostname beg rman 数据量 1353M 说明:源库已经创建数据库实例,并且存在用户kk和他创建的表空间…...

05—面向对象(上)
一、面向对象编程 1、类和对象 (1)什么是类 类是一类具有相同特性的事物的抽象描述,是一组相关属性和行为的集合。 属性:就是该事物的状态信息。行为:就是在你这个程序中,该状态信息要做什么操作&#x…...

【LeetCode热题100】【链表】两数相加
题目链接:2. 两数相加 - 力扣(LeetCode) 基本思路同:【leetcode】大数相加-CSDN博客 数值的位置已经倒过来了,用一个进位记录进位,用一个数记录和,链表到空了就当成0 class Solution { publi…...

Linux命令学习—linux 的硬件管理
1.1、linux 的硬件管理 1.1.1、计算机的硬件管理 在 linux 下,计算机所有设备是以文件的形势存在的。 在 linux 下查看硬件信息 ①、lspci 列出所有的 PCI 设备 ②、fdisk -l 查看存储设备信息 ③、查看/proc 目录下相应的文件来查看一些设备信息 cat /proc/cp…...

通讯录项目(用c语言实现)
一.什么是通讯录 通讯录是一种用于存储联系人信息的工具或应用程序。它是一种电子化的地址簿,用于记录和管理个人、机构或组织的联系方式,如姓名、电话号码、电子邮件地址和邮寄地址等。通讯录的目的是方便用户在需要时查找和联系他人。 通讯录通常以列…...

让大模型落地有“技”可循
“2018年,随着Transformer预训练模型的兴起,自然语言处理(NLP)学术圈中形成了一个主流观点——NLP领域的不同技术方向,如文本分类、文本匹配、序列标注等,最终都会被归结到文本生成这一核心任务之下。”这是…...

java:字符集和字符流
字符集 规定了字符和二进制之间对应关系的一张表 字节是计算机最基本的存储单位 字符则是通过字符组成和编码而成的文本 常见字符集 1,ASCII字符集 基础字符编码标准,包含128个字符,只包括英文字母,数字和一些常见的符号 一个字节表示一个字符 所有的字符集均兼容ASCII…...

Java常见的设计模式
Java常见的设计模式 工厂模式(Factory Pattern)单例模式(Singleton Pattern)代理模式模式(Proxy Pattern)适配器模式(Adapter Pattern)观察者模式(Observer Pattern&…...

Oracle 19c RAC集群相关日志
1.DB日志(数据库日志) Redo Log(重做日志): 在Oracle数据库中,重做日志记录了数据库发生的所有修改操作,包括数据的插入,更新和删除。在RAC的环境中,每个实例都有自己的重…...

TR4 - Transformer中的多头注意力机制
目录 前言自注意力机制Self-Attention层的具体机制Self-Attention 矩阵计算 多头注意力机制例子解析 代码实现总结与心得体会 前言 多头注意力机制可以说是Transformer中最主要的模块,没有之一。这次我们来仔细分析一下注意力机制与多头注意力机制。 自注意力机制…...

three.js跟着教程实现VR效果(四)
参照教程:https://juejin.cn/post/6973865268426571784(作者:大帅老猿) 1.WebGD3D引擎 用three.js (1)使用立方体6面图 camera放到 立方体的中间 like “回” 让贴图向内翻转 (2)使…...

AI预测体彩排3第1弹【2024年4月12日预测--第1套算法开始计算第1次测试】
前面经过多个模型几十次对福彩3D的预测,积累了一定的经验,摸索了一些稳定的规律,有很多彩友让我也出一下排列3的预测结果,我认为目前时机已成熟,且由于福彩3D和体彩排列3的玩法完全一样,我认为3D的规律和模…...

spring 中的控制反转
在Spring框架中,控制反转(IoC,Inversion of Control)是指将对象的创建和管理交给了容器,而不是在应用程序代码中直接创建对象。在传统的编程模式中,应用程序代码通常负责创建对象并管理它们的生命周期&…...

GO并发总是更快吗?
许多开发人员的一个误解是,并发解决方案总是比串行更快,大错特错。解决方案的整体性能取决于许多因素,例如,结构的效率(并发)、可以并行处理的部分以及计算单元的竞争程度。 1. GO调度 线程是操作系统可以执行的最小单元。如果一个进程想要同时执行多个动作,它可以启动…...

echarts折线图自定义打点标记小工具
由于没研究明白echarts怎么用label和lableLine实现自定义打点标记,索性用markPoint把长方形压扁成线模拟了一番自定义打点标记,记录下来备用。(markLine同理也能实现) 实现代码如下: <!DOCTYPE html> <html…...

【图论】Leetcode 200. 岛屿数量【中等】
岛屿数量 给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以…...

酒店大厅装水离子雾化壁炉前和装后对比
在酒店大厅装水离子雾化壁炉之前和之后,大厅的氛围和体验会有显著的对比: 装水离子雾化壁炉之前: 传统感:在壁炉安装之前,大厅可能会有传统的装饰或者简单的暖气设备,缺乏现代化的元素。这种传统感可能会…...

城市内涝与海绵城市规划设计中的水文水动力模拟
原文链接:城市内涝与海绵城市规划设计中的水文水动力模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601198&idx5&sn35b9e5e3961ea2f190f9742236a7217f&chksmfa820dc9cdf584df97633f64d19bdc3e5f7d1a5a85000c8f040e1953c51b9b39c87b5…...

C++项目实战与经验分享
在编程世界中,C++ 是一种功能强大且灵活的编程语言,广泛应用于系统级编程、游戏开发、嵌入式系统以及高性能计算等领域。本文将分享一个基于C++的图像处理系统项目实战经验,并深入探讨在开发过程中遇到的问题及解决方案。 一、项目概述 本次项目实战的目标是开发一个基于C…...

Day17_学点JavaEE_转发、重定向、Get、POST、乱码问题总结
1 转发 转发:一般查询了数据之后,转发到一个jsp页面进行展示 req.setAttribute("list", list); req.getRequestDispatcher("student_list.jsp").forward(req, resp);2 重定向 重定向:一般添加、删除、修改之后重定向到…...

Mouse IFN-α ELISA kit (Quick Test)
干扰素α(IFN-α)是一类由免疫细胞分泌的内源性调节因子,也被称为白细胞干扰素,主要参与响应病毒感染的先天性免疫。 基于结构特征、受体、细胞来源和生物活性的不同,干扰素可被分为Ⅰ、Ⅱ、Ⅲ三种类型,其中…...

AMD Tensile 简介与示例
按照知其然,再知其所以然的认知次序进行 1,下载代码 git clone --recursive https://github.com/ROCm/Tensile.git 2,安装 Tensile cd Tensile mkdir build cd build ../Tensile/bin/Tensile ../Tensile/Configs/rocblas_dgemm_nn_asm_full…...

Rust语言
文章目录 Rust语言一,Rust语言是什么二,Rust语言能做什么?Rust语言的设计使其适用于许多不同的领域,包括但不限于以下几个方面:1. 传统命令行程序:2. Web 应用:3. 网络服务器:4. 嵌入…...

排序算法之冒泡排序
目录 一、简介二、代码实现三、应用场景 一、简介 算法平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度排序方式稳定性冒泡排序O(n^2 )O(n)O(n^2)O(1)In-place稳定 稳定:如果A原本在B前面,而AB,排序之后A仍然在B的前面; 不…...

js打印页面源码 ,打印选取的容器里的内容,打印指定内容
js打印页面源码 ,打印选取的容器里的内容,打印指定内容 效果 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge&…...

算法练习第五十天|123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV
123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV 123.买卖股票的最佳时机III class Solution {public int maxProfit(int[] prices) {//dp[i][j] 第i天买卖股票获得的最大利润/**j0不操作j1第一次持有j2第一次不持有j3第二次持有j4第二次不持有dp[i][0] dp[i-1][0]d…...

细胞世界:4.细胞分化(划区域)与细胞衰老(设施磨损)
(1)细胞凋亡 1. 概念:细胞凋亡可以比作城市的规划者主动拆除某些建筑来更新城市或防止危险建筑对市民的潜在伤害。这是一个有序的过程,由城市(细胞内部)的特定规划(基因)所决定。 2. 特征:细…...