From be52f1bfff79f3704a8d8bd4cef20c38f7a2e138 Mon Sep 17 00:00:00 2001 From: Mansive <33560917+Mansive@users.noreply.github.com> Date: Sun, 9 Mar 2025 00:33:42 -0600 Subject: [PATCH 1/5] Add Monster Hunter Wilds --- PC_Steam_Monster_Hunter_Wilds.js | 178 +++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 PC_Steam_Monster_Hunter_Wilds.js diff --git a/PC_Steam_Monster_Hunter_Wilds.js b/PC_Steam_Monster_Hunter_Wilds.js new file mode 100644 index 00000000..0701cfd0 --- /dev/null +++ b/PC_Steam_Monster_Hunter_Wilds.js @@ -0,0 +1,178 @@ +// ==UserScript== +// @name Monster Hunter Wilds +// @version 1.000.04.00 +// @author Mansive +// @description Steam +// * CAPCOM Co., Ltd. +// +// https://store.steampowered.com/app/2246340/Monster_Hunter_Wilds/ +// ==/UserScript== + +const ui = require("./libUI.js"); +const __e = Process.enumerateModules()[0]; + +// using original size leads to access violation +__e.size = 0x10000000; + +const texts = new Set(); +let timer = null; +let open = false; + +//#region Hooks + +const hooks = [ + { + name: "DialogueEnable", + pattern: + // "E8 46 11 B1 02 41 83 BE C0 02 00 00 03 41 0F 94 C0 48 89 F1 48 89 FA E8", + "e8 ?? ?? ?? ?? 4? 83 b? ?? ?? ?? ?? ?? 4? 0f 94", + register: null, + handler: dialogueEnableHandler, + }, // E8 4611B102 + { + name: "Dialogue", + pattern: + // "FF 15 37 D1 44 04", + "ff 15 ?? ?? ?? ?? 89 c2 4? 89 f9 4? 89 e0 4? 31 c9 e8 ?? ?? ?? ?? 4? 85 c0 75", + register: "rax", + handler: dialogueHandler, + }, +]; + +//#endregion + +//#region Attach + +/** + * Scans a pattern in memory and returns a NativePointer for first match. + * @param {string} name + * @param {string} pattern + * @returns {NativePointer} + */ +function getPatternAddress(name, pattern) { + let results = null; + + try { + results = Memory.scanSync(__e.base, __e.size, pattern); + } catch (err) { + throw new Error(`Error ocurred with [${name}]: ${err.message}`, { + cause: err, + }); + } + + if (results.length === 0) { + throw new Error(`[${name}] Hook not found!`); + } else if (results.length >= 2) { + console.warn(`${name} has ${results.length} results`); + } + + const address = results[0].address; + + console.log(`\x1b[32m[${name}] Found hook ${address}\x1b[0m`); + + return address; +} + +function attachHooks() { + for (const hook of hooks) { + const { name, pattern, register, handler } = hook; + const address = getPatternAddress(name, pattern); + + Interceptor.attach(address, function () { + handler.call(this, name, this.context[register]); + }); + } +} + +//#endregion + +//#region Handlers + +function genericHandler(text) { + texts.add(text); + + clearTimeout(timer); + timer = setTimeout(() => { + trans.send([...texts].join("\r\n")); + texts.clear(); + }, 200); +} + +/** Temporarily enable {@link dialogueHandler}. */ +function dialogueEnableHandler(name, address) { + console.log(`onEnter: ${name}`); + + open = true; + + clearTimeout(timer); + timer = setTimeout(() => { + open = false; + texts.clear(); + }, 1000); +} + +function dialogueHandler(name, address) { + if (open === false) { + console.log(`\x1b[2mskipped: ${name}\x1b[0m`); + return null; + } + + console.log(`onEnter: ${name}`); + + const text = address.readUtf16String(); + genericHandler(text); +} + +//#endregion + +//#region Start + +/** + * Installing REFramework involves placing a customized dinput8.dll into the + * game's folder. + * + * Because REFramework uses ImGui, we can detect if REFramework is installed + * by checking if the game's dinput8.dll contains an export from ImGui. + */ +function checkForREFramework() { + let found = false; + + // there can be multiple dinput8.dll, need to check each one + for (const module of Process.enumerateModules()) { + if ( + module.name.toLowerCase() === "dinput8.dll" && + module.findExportByName("igText") !== null + ) { + found = true; + break; + } + } + + if (found === true) { + console.log(`\x1b[32mREFramework found.\n\x1b[0m`); + return true; + } else if (found === false) { + console.warn(` + \rREFramework not found! + \rThe game might crash horrifically. + `); + return false; + } +} + +function start() { + console.warn(` + \rThis script requires Capcom's anti-tamper to be disabled, + \ror else attaching will cause the game to crash. + + \rOne way to disable it is by installing REFramework. + \rLink: https://github.com/praydog/REFramework + + \rUse this script (and REFramework) at your own risk! + `); + + checkForREFramework(); + attachHooks(); +} + +start(); From 1f9c5aeef2af46664e06ef6d06944c9917fb1efb Mon Sep 17 00:00:00 2001 From: Mansive <33560917+Mansive@users.noreply.github.com> Date: Sun, 9 Mar 2025 00:45:20 -0600 Subject: [PATCH 2/5] Fix hook by separating timers --- PC_Steam_Monster_Hunter_Wilds.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PC_Steam_Monster_Hunter_Wilds.js b/PC_Steam_Monster_Hunter_Wilds.js index 0701cfd0..ad02d203 100644 --- a/PC_Steam_Monster_Hunter_Wilds.js +++ b/PC_Steam_Monster_Hunter_Wilds.js @@ -16,6 +16,7 @@ __e.size = 0x10000000; const texts = new Set(); let timer = null; +let timerDialogueEnable = null; let open = false; //#region Hooks @@ -99,16 +100,16 @@ function genericHandler(text) { } /** Temporarily enable {@link dialogueHandler}. */ -function dialogueEnableHandler(name, address) { +function dialogueEnableHandler(name) { console.log(`onEnter: ${name}`); open = true; - clearTimeout(timer); - timer = setTimeout(() => { + clearTimeout(timerDialogueEnable); + timerDialogueEnable = setTimeout(() => { open = false; texts.clear(); - }, 1000); + }, 500); } function dialogueHandler(name, address) { @@ -176,3 +177,5 @@ function start() { } start(); + +//#endregion From 81c023494b553d825b4641f666cc85d871832e05 Mon Sep 17 00:00:00 2001 From: Mansive <33560917+Mansive@users.noreply.github.com> Date: Mon, 10 Mar 2025 22:21:24 -0500 Subject: [PATCH 3/5] Improve detection of REFramework --- PC_Steam_Monster_Hunter_Wilds.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/PC_Steam_Monster_Hunter_Wilds.js b/PC_Steam_Monster_Hunter_Wilds.js index ad02d203..3b239f6c 100644 --- a/PC_Steam_Monster_Hunter_Wilds.js +++ b/PC_Steam_Monster_Hunter_Wilds.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Monster Hunter Wilds -// @version 1.000.04.00 +// @version 1.000.05.00 // @author Mansive // @description Steam // * CAPCOM Co., Ltd. @@ -8,7 +8,6 @@ // https://store.steampowered.com/app/2246340/Monster_Hunter_Wilds/ // ==/UserScript== -const ui = require("./libUI.js"); const __e = Process.enumerateModules()[0]; // using original size leads to access violation @@ -108,7 +107,6 @@ function dialogueEnableHandler(name) { clearTimeout(timerDialogueEnable); timerDialogueEnable = setTimeout(() => { open = false; - texts.clear(); }, 500); } @@ -132,20 +130,23 @@ function dialogueHandler(name, address) { * Installing REFramework involves placing a customized dinput8.dll into the * game's folder. * - * Because REFramework uses ImGui, we can detect if REFramework is installed - * by checking if the game's dinput8.dll contains an export from ImGui. + * The function returns true if the string "REFramework" is found in the game's + * dinput8.dll. */ function checkForREFramework() { let found = false; // there can be multiple dinput8.dll, need to check each one for (const module of Process.enumerateModules()) { - if ( - module.name.toLowerCase() === "dinput8.dll" && - module.findExportByName("igText") !== null - ) { - found = true; - break; + if (module.name.toLowerCase() === "dinput8.dll") { + // bytes of the string "REFramework" + const pattern = "52 45 46 72 61 6d 65 77 6f 72 6b"; + const results = Memory.scanSync(module.base, module.size, pattern); + + if (results.length !== 0) { + found = true; + break; + } } } From 8ba060fde45daf0b3e85efe97bbbfb64d3a1cad1 Mon Sep 17 00:00:00 2001 From: Mansive <33560917+Mansive@users.noreply.github.com> Date: Tue, 11 Mar 2025 21:39:02 -0500 Subject: [PATCH 4/5] Disable spammable console log, remove italic tags --- PC_Steam_Monster_Hunter_Wilds.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PC_Steam_Monster_Hunter_Wilds.js b/PC_Steam_Monster_Hunter_Wilds.js index 3b239f6c..134ee699 100644 --- a/PC_Steam_Monster_Hunter_Wilds.js +++ b/PC_Steam_Monster_Hunter_Wilds.js @@ -112,13 +112,13 @@ function dialogueEnableHandler(name) { function dialogueHandler(name, address) { if (open === false) { - console.log(`\x1b[2mskipped: ${name}\x1b[0m`); + // console.log(`\x1b[2mskipped: ${name}\x1b[0m`); return null; } console.log(`onEnter: ${name}`); - const text = address.readUtf16String(); + const text = address.readUtf16String().replace(/<\/?ITALIC>/g, ""); genericHandler(text); } From e131675c04906734314d8f0bb209d001bb5a6e6d Mon Sep 17 00:00:00 2001 From: Mansive <33560917+Mansive@users.noreply.github.com> Date: Tue, 11 Mar 2025 21:55:03 -0500 Subject: [PATCH 5/5] Remove all tags --- PC_Steam_Monster_Hunter_Wilds.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PC_Steam_Monster_Hunter_Wilds.js b/PC_Steam_Monster_Hunter_Wilds.js index 134ee699..615fad0b 100644 --- a/PC_Steam_Monster_Hunter_Wilds.js +++ b/PC_Steam_Monster_Hunter_Wilds.js @@ -118,7 +118,10 @@ function dialogueHandler(name, address) { console.log(`onEnter: ${name}`); - const text = address.readUtf16String().replace(/<\/?ITALIC>/g, ""); + const text = address + .readUtf16String() + .replace(/<\/?ITALIC>/g, "") + .replace(/<.+>/g, ""); genericHandler(text); }