古塔是曙光狩猎体验最优秀的地图,但有个很烦人的问题:无论打什么怪都只会放古塔的BGM而非怪物的BGM. 我断断续续试图用怪物BGM覆盖掉地图BGM但一直没成功。在隔壁 MH Modding Discord 请教了好半天但并没问出什么结果,大佬说直觉上不太好实现。不过我大致把 REF 里任务音乐的机制搞明白了,请问有没有比较了解MHR音乐机制(pck/bnk修改)或者 REFramework 中 wwise 组件的大佬能给些思路吗?如果回复或者站内信不好写的话也可以加我 discord: 孟孟#8283
只要解决以下两个问题中的任何一个就可以实现古塔BGM覆盖,希望大家能给出解决这俩问题的建议:
- 在斗技场 pck/bnk 文件里复制一份所有怪物的音乐信息,注意是增加而非替换;
- 进任务前让游戏加载普通任务音乐资源包,而非斗技场类专用资源包。
下面是我搞明白的内容:
snow.wwise.WwiseMusicManager 是控制音乐播放的管理器,在普通任务中会每帧调用 updateQuestMusic() 这个方法,, 在斗技场/狱泉乡/古塔这样的单怪地图则会使用 updateOneAreaQuestMusic() 这个方法。
这些 update 方法非常复杂,我没太搞明白,似乎主要干的事是更新 _XXXMusicState,所以手动修改 music state 也会使得音乐发生变化。 而 updateOneAreaQuestMusic 基本上保证了无论打什么怪,都只会播放当前地图的 BGM 而非怪物的音乐;
狱泉乡焰狐龙任务和最新加的古塔傀异天迴是例外,焰狐二阶段会强制切歌成泡狐BGM,而天迴会全程播放它自己的音乐。根据反编译出来的代码,这个的实现方法非常偷懒,泡狐是通过 WwiseMusicManager._OneAreaPriorityChange 这个 bool 实现的。勾选这个 bool 之后 update 方法会用 WwiseMusicManager._SettingsData._OneAreaEmPriorityState 来更新 music state 从而切歌。只要在斗技场类地图,在任何任务中把这个改成 true 就会强制播放泡狐BGM。而天迴则是又加了一个新的 bool 为 _OneAreaPriorityChangeOver 来切歌成天迴BGM。对应的 state 为 _OneAreaOverEmPriorityState.
反编译代码中关于 _OneAreaEmPriorityState 的部分。反编译代码是岚龙版本更新之前的,所以没有关于天迴的代码。
WwiseMusicManager 中实现切歌的两个 bool:
WwiseMusicManager._SettingsData 中关于泡狐和天迴BGM的两个 music states:
Music state 的结构分为四个部分,group ID name, group ID, name 和 ID. 音乐相关的 group ID name / group ID 都是固定的可以不管。name 格式为 em_XXX, XXX 是怪物编号,可以在 https://github.com/mhvuze/MonsterHunterRiseModding/wiki/Monster-IDs 查询。ID 则是 name 的哈希,我有一张表,里面有所有关键字的哈希。name 本身是无功能的,只修改 ID 就会让音乐发生变化。
ID 哈希表,em_072 是天迴一家,em_082 是泡狐一家,可以看到第二列里的哈希和 REF 里 StateID 的 unsigned 值是对应的:
经测试,修改 state 的 ID 就可以更改播放的音乐。比如我们进一个古塔傀异天迴的任务,_OneAreaPriorityChangeOver 会被自动勾选,音乐也会播放天迴 BGM. 但如果我们把天迴对应的 _OneAreaOverEmPriorityState 里面 ID 改为泡狐的 2925254856,那么音乐就会立刻切为泡狐音乐。
类似的,在普通任务里也有同样的 state ID 结构。下图为在一个砂原的傀异天慧(em_086)任务中用 cheat engine 找到的天慧BGM state ID, 可以看到 stateGroupID 是和之前一样的值, stateName 和 stateID 是一样的结构。如果把 0xBF6C4FE8 这个 ID 改成别的哈希,比如炎王 em_027 的 2757478667,那打天慧的时候听到的音乐也会变成炎王的。
不过根据地址范围和几次测试的结果来看,这些 state ID 好像是动态加载的,我还没太搞明白在 REF 里对应的变量在哪(不过应该和古塔BGM覆盖不相关,这个实验只是验证通过修改 state ID 来切歌是可行的)。
但很遗憾的是把这个 state ID 改成其他怪的哈希并不会起作用,音乐会变回地图BGM,原理见下。
无法播泡狐和天迴之外的音乐的原因是在斗技场类地图中游戏并不会加载大部分音乐资源,只会加载一个特殊的斗技场地图专用的资源包,所以即使修改了 ID 游戏也找不到对应的音乐。
下图为普通任务的音乐资源包的崛起本体部分,可以看到包括了普通地图音乐(比如 0, 1 号分别是砂原和废神社,6号是水没林)和怪物音乐(比如3号是泡狐、4号是雷狼):
下图为斗技场类地图音乐资源包的本体部分,可以看到包括了单区地图的音乐(5号是斗技场、8号是狱泉乡)。泡狐音乐也专门被添加到了这个资源包里,为0号,应该就是为焰狐切歌专门弄的。这个表应该是岚龙更新前的,所以没有天迴:
在古塔任务中通过 MusicManager 的那几个 bool 和 state 来修改音乐是可行的。但问题在与游戏只加载了古塔地图BGM、泡狐BGM和天迴BGM,所以我们可以在这三首里切来切去,但并不能改成别的比如说雷狼BGM。
为了实现这个功能我现在有两个思路:
- 类似于泡狐和天迴,我们把其他怪的音乐也添加到斗技场专用资源包里;
- 进斗技场类任务时,让游戏加载普通任务音乐包。
对于方法1,现在已有不少替换音乐的教程,也就是 pck/bnk 修改,但并没有如何添加音乐的教程。我在 modding discord 里问了的结果好像是没人知道怎么做。请问有没有熟悉 bnk 结构的大佬?
对于方法2,关于音乐加载,我找到了一个 WwiseMediaLoadManager. 我发现每次进任务的时候都会调用 loadMedia(type), 任务结束回村的时候会 unloadMedia(type),其中 type = 2 为普通任务,type = 3 为斗技场类任务。我尝试了一下如果检测到游戏试图 loadMedia(3), 则替换为 loadMedia(2),但似乎并没有什么效果。游戏会照样播放古塔 BGM,也无法播放泡狐天迴以外的怪物音乐,也就是说实际被加载的还是斗技场音乐包。请问有没有人知道这个东西到底是干啥用的,或者实际管理音乐加载的是哪个类?
load/unload media 的参数 type 的定义,可以看到 2 代表 quest(普通任务),3 代表 one area quest(单区任务):
反编译出来的 loadMedia 的代码,完全搞不明白在干啥:
欢迎任何任何形式的建议和提示!有偿也可以!我真的很希望能在崛起/曙光完结之前搞定这个功能