From 751d001ba3b9183f5b138c1da0142c2b8f25aaf7 Mon Sep 17 00:00:00 2001 From: GaboGG Date: Tue, 4 Aug 2026 17:15:42 -0400 Subject: [PATCH] v0.17.6 - jpx chain: never press M while jpx is active (toggle-off guard) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the race where our synthetic M landed while jpx was mid-round (active=true) and disabled the chain. Now jpxTriggerAuto skips if jpxLastActive===true, and the initial press waits for jpx's first state event. NOTE: ajaxRound must stay OFF for chaining to work — jpx's AJAX round advance dispatches a synthetic DOMContentLoaded that resets its own isActiveBattle flag. --- scripts/hv-unified.user.js | 31 ++++++++++++++++++++++--------- scripts/latest.user.js | 31 ++++++++++++++++++++++--------- src/config.js | 2 +- src/header.user.js | 2 +- src/jpx-bridge.js | 27 ++++++++++++++++++++------- 5 files changed, 66 insertions(+), 27 deletions(-) diff --git a/scripts/hv-unified.user.js b/scripts/hv-unified.user.js index 81f955b..a55d15d 100644 --- a/scripts/hv-unified.user.js +++ b/scripts/hv-unified.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.17.5 +// @version 0.17.6 // @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils) // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* @@ -18,7 +18,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.17.5'; +const VERSION = '0.17.6'; const CFG = { // — Battle strategy advisory @@ -1587,16 +1587,30 @@ function jpxChainStart() { jpxChainEnabled = true; jpxChainRounds = 0; jpxChainCooldown = Date.now(); - // Start the first auto round (equivalent to pressing M once) - setTimeout(jpxTriggerAuto, 800); + // Start the first auto round — but only AFTER we know jpx's real state + // (wait up to 1.5s for its first jpx_ctrlWidget_update event). If the + // user already pressed M manually, jpxLastActive=true and we skip. + let waited = 0; + const sync = setInterval(() => { + waited += 300; + if (jpxLastActive !== null || waited > 1500) { + clearInterval(sync); + setTimeout(jpxTriggerAuto, 200); + } + }, 300); console.log('%c[HV] ⛓ jpx auto-chain engaged (re-triggering M each round)', 'color:#0f0'); } -// Trigger jpx's auto-battle toggle (equivalent to pressing M). -// jpx listens for keydown on document (capture phase) and maps key 'm' to -// toggleActive via userKeybinds. A synthetic KeyboardEvent works because -// jpx reads e.key, not e.isTrusted. +// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is +// currently INACTIVE. Pressing M while jpx is already active toggles it OFF, +// which is the bug we hit: our M landed while jpx was mid-round (active=true) +// and disabled the chain. function jpxTriggerAuto() { + // If we know jpx is already active, pressing M would DISABLE it — skip. + if (jpxLastActive === true) { + console.log('%c[HV] ⛓ jpx already active — skipping M (would toggle off)', 'color:#f80'); + return false; + } try { const evt = new KeyboardEvent('keydown', { key: 'm', @@ -1607,7 +1621,6 @@ function jpxTriggerAuto() { cancelable: true, }); // Give jpx a moment to process, then verify via its own state event. - // If it didn't toggle, the keybind didn't reach jpx. const before = jpxLastActive; document.dispatchEvent(evt); setTimeout(() => { diff --git a/scripts/latest.user.js b/scripts/latest.user.js index 81f955b..a55d15d 100644 --- a/scripts/latest.user.js +++ b/scripts/latest.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.17.5 +// @version 0.17.6 // @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils) // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* @@ -18,7 +18,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.17.5'; +const VERSION = '0.17.6'; const CFG = { // — Battle strategy advisory @@ -1587,16 +1587,30 @@ function jpxChainStart() { jpxChainEnabled = true; jpxChainRounds = 0; jpxChainCooldown = Date.now(); - // Start the first auto round (equivalent to pressing M once) - setTimeout(jpxTriggerAuto, 800); + // Start the first auto round — but only AFTER we know jpx's real state + // (wait up to 1.5s for its first jpx_ctrlWidget_update event). If the + // user already pressed M manually, jpxLastActive=true and we skip. + let waited = 0; + const sync = setInterval(() => { + waited += 300; + if (jpxLastActive !== null || waited > 1500) { + clearInterval(sync); + setTimeout(jpxTriggerAuto, 200); + } + }, 300); console.log('%c[HV] ⛓ jpx auto-chain engaged (re-triggering M each round)', 'color:#0f0'); } -// Trigger jpx's auto-battle toggle (equivalent to pressing M). -// jpx listens for keydown on document (capture phase) and maps key 'm' to -// toggleActive via userKeybinds. A synthetic KeyboardEvent works because -// jpx reads e.key, not e.isTrusted. +// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is +// currently INACTIVE. Pressing M while jpx is already active toggles it OFF, +// which is the bug we hit: our M landed while jpx was mid-round (active=true) +// and disabled the chain. function jpxTriggerAuto() { + // If we know jpx is already active, pressing M would DISABLE it — skip. + if (jpxLastActive === true) { + console.log('%c[HV] ⛓ jpx already active — skipping M (would toggle off)', 'color:#f80'); + return false; + } try { const evt = new KeyboardEvent('keydown', { key: 'm', @@ -1607,7 +1621,6 @@ function jpxTriggerAuto() { cancelable: true, }); // Give jpx a moment to process, then verify via its own state event. - // If it didn't toggle, the keybind didn't reach jpx. const before = jpxLastActive; document.dispatchEvent(evt); setTimeout(() => { diff --git a/src/config.js b/src/config.js index ca3f603..26ca02e 100644 --- a/src/config.js +++ b/src/config.js @@ -2,7 +2,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.17.5'; +const VERSION = '0.17.6'; const CFG = { // — Battle strategy advisory diff --git a/src/header.user.js b/src/header.user.js index 2d7e78f..b509a22 100644 --- a/src/header.user.js +++ b/src/header.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.17.5 +// @version 0.17.6 // @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils) // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* diff --git a/src/jpx-bridge.js b/src/jpx-bridge.js index 528a88b..d74e951 100644 --- a/src/jpx-bridge.js +++ b/src/jpx-bridge.js @@ -40,16 +40,30 @@ function jpxChainStart() { jpxChainEnabled = true; jpxChainRounds = 0; jpxChainCooldown = Date.now(); - // Start the first auto round (equivalent to pressing M once) - setTimeout(jpxTriggerAuto, 800); + // Start the first auto round — but only AFTER we know jpx's real state + // (wait up to 1.5s for its first jpx_ctrlWidget_update event). If the + // user already pressed M manually, jpxLastActive=true and we skip. + let waited = 0; + const sync = setInterval(() => { + waited += 300; + if (jpxLastActive !== null || waited > 1500) { + clearInterval(sync); + setTimeout(jpxTriggerAuto, 200); + } + }, 300); console.log('%c[HV] ⛓ jpx auto-chain engaged (re-triggering M each round)', 'color:#0f0'); } -// Trigger jpx's auto-battle toggle (equivalent to pressing M). -// jpx listens for keydown on document (capture phase) and maps key 'm' to -// toggleActive via userKeybinds. A synthetic KeyboardEvent works because -// jpx reads e.key, not e.isTrusted. +// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is +// currently INACTIVE. Pressing M while jpx is already active toggles it OFF, +// which is the bug we hit: our M landed while jpx was mid-round (active=true) +// and disabled the chain. function jpxTriggerAuto() { + // If we know jpx is already active, pressing M would DISABLE it — skip. + if (jpxLastActive === true) { + console.log('%c[HV] ⛓ jpx already active — skipping M (would toggle off)', 'color:#f80'); + return false; + } try { const evt = new KeyboardEvent('keydown', { key: 'm', @@ -60,7 +74,6 @@ function jpxTriggerAuto() { cancelable: true, }); // Give jpx a moment to process, then verify via its own state event. - // If it didn't toggle, the keybind didn't reach jpx. const before = jpxLastActive; document.dispatchEvent(evt); setTimeout(() => {