v0.17.6 - jpx chain: never press M while jpx is active (toggle-off guard)
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.
This commit is contained in:
parent
5012d5f74f
commit
751d001ba3
5 changed files with 66 additions and 27 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name HV Unified
|
// @name HV Unified
|
||||||
// @namespace hvunified
|
// @namespace hvunified
|
||||||
// @version 0.17.5
|
// @version 0.17.6
|
||||||
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
||||||
// @author GaboGG + Hermes
|
// @author GaboGG + Hermes
|
||||||
// @match *://*.hentaiverse.org/*
|
// @match *://*.hentaiverse.org/*
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// CONFIG — default settings
|
// CONFIG — default settings
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
const VERSION = '0.17.5';
|
const VERSION = '0.17.6';
|
||||||
|
|
||||||
const CFG = {
|
const CFG = {
|
||||||
// — Battle strategy advisory
|
// — Battle strategy advisory
|
||||||
|
|
@ -1587,16 +1587,30 @@ function jpxChainStart() {
|
||||||
jpxChainEnabled = true;
|
jpxChainEnabled = true;
|
||||||
jpxChainRounds = 0;
|
jpxChainRounds = 0;
|
||||||
jpxChainCooldown = Date.now();
|
jpxChainCooldown = Date.now();
|
||||||
// Start the first auto round (equivalent to pressing M once)
|
// Start the first auto round — but only AFTER we know jpx's real state
|
||||||
setTimeout(jpxTriggerAuto, 800);
|
// (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');
|
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).
|
// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is
|
||||||
// jpx listens for keydown on document (capture phase) and maps key 'm' to
|
// currently INACTIVE. Pressing M while jpx is already active toggles it OFF,
|
||||||
// toggleActive via userKeybinds. A synthetic KeyboardEvent works because
|
// which is the bug we hit: our M landed while jpx was mid-round (active=true)
|
||||||
// jpx reads e.key, not e.isTrusted.
|
// and disabled the chain.
|
||||||
function jpxTriggerAuto() {
|
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 {
|
try {
|
||||||
const evt = new KeyboardEvent('keydown', {
|
const evt = new KeyboardEvent('keydown', {
|
||||||
key: 'm',
|
key: 'm',
|
||||||
|
|
@ -1607,7 +1621,6 @@ function jpxTriggerAuto() {
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
});
|
});
|
||||||
// Give jpx a moment to process, then verify via its own state event.
|
// 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;
|
const before = jpxLastActive;
|
||||||
document.dispatchEvent(evt);
|
document.dispatchEvent(evt);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name HV Unified
|
// @name HV Unified
|
||||||
// @namespace hvunified
|
// @namespace hvunified
|
||||||
// @version 0.17.5
|
// @version 0.17.6
|
||||||
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
||||||
// @author GaboGG + Hermes
|
// @author GaboGG + Hermes
|
||||||
// @match *://*.hentaiverse.org/*
|
// @match *://*.hentaiverse.org/*
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// CONFIG — default settings
|
// CONFIG — default settings
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
const VERSION = '0.17.5';
|
const VERSION = '0.17.6';
|
||||||
|
|
||||||
const CFG = {
|
const CFG = {
|
||||||
// — Battle strategy advisory
|
// — Battle strategy advisory
|
||||||
|
|
@ -1587,16 +1587,30 @@ function jpxChainStart() {
|
||||||
jpxChainEnabled = true;
|
jpxChainEnabled = true;
|
||||||
jpxChainRounds = 0;
|
jpxChainRounds = 0;
|
||||||
jpxChainCooldown = Date.now();
|
jpxChainCooldown = Date.now();
|
||||||
// Start the first auto round (equivalent to pressing M once)
|
// Start the first auto round — but only AFTER we know jpx's real state
|
||||||
setTimeout(jpxTriggerAuto, 800);
|
// (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');
|
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).
|
// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is
|
||||||
// jpx listens for keydown on document (capture phase) and maps key 'm' to
|
// currently INACTIVE. Pressing M while jpx is already active toggles it OFF,
|
||||||
// toggleActive via userKeybinds. A synthetic KeyboardEvent works because
|
// which is the bug we hit: our M landed while jpx was mid-round (active=true)
|
||||||
// jpx reads e.key, not e.isTrusted.
|
// and disabled the chain.
|
||||||
function jpxTriggerAuto() {
|
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 {
|
try {
|
||||||
const evt = new KeyboardEvent('keydown', {
|
const evt = new KeyboardEvent('keydown', {
|
||||||
key: 'm',
|
key: 'm',
|
||||||
|
|
@ -1607,7 +1621,6 @@ function jpxTriggerAuto() {
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
});
|
});
|
||||||
// Give jpx a moment to process, then verify via its own state event.
|
// 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;
|
const before = jpxLastActive;
|
||||||
document.dispatchEvent(evt);
|
document.dispatchEvent(evt);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// CONFIG — default settings
|
// CONFIG — default settings
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
const VERSION = '0.17.5';
|
const VERSION = '0.17.6';
|
||||||
|
|
||||||
const CFG = {
|
const CFG = {
|
||||||
// — Battle strategy advisory
|
// — Battle strategy advisory
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name HV Unified
|
// @name HV Unified
|
||||||
// @namespace hvunified
|
// @namespace hvunified
|
||||||
// @version 0.17.5
|
// @version 0.17.6
|
||||||
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
// @description HV Unified — Bridge & Strategy/Gear Advisor for HentaiVerse (complements Monsterbation & HVUtils)
|
||||||
// @author GaboGG + Hermes
|
// @author GaboGG + Hermes
|
||||||
// @match *://*.hentaiverse.org/*
|
// @match *://*.hentaiverse.org/*
|
||||||
|
|
|
||||||
|
|
@ -40,16 +40,30 @@ function jpxChainStart() {
|
||||||
jpxChainEnabled = true;
|
jpxChainEnabled = true;
|
||||||
jpxChainRounds = 0;
|
jpxChainRounds = 0;
|
||||||
jpxChainCooldown = Date.now();
|
jpxChainCooldown = Date.now();
|
||||||
// Start the first auto round (equivalent to pressing M once)
|
// Start the first auto round — but only AFTER we know jpx's real state
|
||||||
setTimeout(jpxTriggerAuto, 800);
|
// (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');
|
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).
|
// Trigger jpx's auto-battle (equivalent to pressing M) — ONLY when jpx is
|
||||||
// jpx listens for keydown on document (capture phase) and maps key 'm' to
|
// currently INACTIVE. Pressing M while jpx is already active toggles it OFF,
|
||||||
// toggleActive via userKeybinds. A synthetic KeyboardEvent works because
|
// which is the bug we hit: our M landed while jpx was mid-round (active=true)
|
||||||
// jpx reads e.key, not e.isTrusted.
|
// and disabled the chain.
|
||||||
function jpxTriggerAuto() {
|
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 {
|
try {
|
||||||
const evt = new KeyboardEvent('keydown', {
|
const evt = new KeyboardEvent('keydown', {
|
||||||
key: 'm',
|
key: 'm',
|
||||||
|
|
@ -60,7 +74,6 @@ function jpxTriggerAuto() {
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
});
|
});
|
||||||
// Give jpx a moment to process, then verify via its own state event.
|
// 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;
|
const before = jpxLastActive;
|
||||||
document.dispatchEvent(evt);
|
document.dispatchEvent(evt);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue