v0.17.4 - jpx chain: wait for next-round monsters before pressing M
The chain was pressing M at round-END (continue button up, no monsters), so jpx read it as 'advance' and never started auto-play on the next round. Now: on jpx inactive, poll up to 8s until the next round's monsters spawn, THEN trigger M. Manual M worked because user pressed it after round load.
This commit is contained in:
parent
6a7d5a435b
commit
4d29215e71
6 changed files with 81 additions and 30 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name HV Unified
|
// @name HV Unified
|
||||||
// @namespace hvunified
|
// @namespace hvunified
|
||||||
// @version 0.17.3
|
// @version 0.17.4
|
||||||
// @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.3';
|
const VERSION = '0.17.4';
|
||||||
|
|
||||||
const CFG = {
|
const CFG = {
|
||||||
// — Battle strategy advisory
|
// — Battle strategy advisory
|
||||||
|
|
@ -1563,6 +1563,7 @@ let jpxChainTimer = null;
|
||||||
let jpxLastActive = null; // last known isActiveBattle from jpx
|
let jpxLastActive = null; // last known isActiveBattle from jpx
|
||||||
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
||||||
let jpxChainRetryCount = 0; // lazy-start retry counter
|
let jpxChainRetryCount = 0; // lazy-start retry counter
|
||||||
|
let jpxChainWaiting = false; // waiting for next-round monsters to spawn
|
||||||
|
|
||||||
function jpxPresent() {
|
function jpxPresent() {
|
||||||
return !!(document.getElementById('ctrl-widget') ||
|
return !!(document.getElementById('ctrl-widget') ||
|
||||||
|
|
@ -1651,15 +1652,30 @@ function jpxChainOnState(detail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-trigger for the next round — with a small delay so jpx finishes
|
// Don't press M yet — jpx would read it as "advance" (round already
|
||||||
// its re-init (reDoBattle resets state) before we press M again.
|
// ended, no monsters). Wait until the NEXT round's monsters spawn,
|
||||||
// Guard against double-firing within 2.5s.
|
// then trigger auto. Poll up to ~8s.
|
||||||
|
jpxChainWaiting = true;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - jpxChainCooldown < 2500) return;
|
if (now - jpxChainCooldown < 2500) return;
|
||||||
jpxChainCooldown = now;
|
jpxChainCooldown = now;
|
||||||
jpxChainRounds++;
|
jpxChainRounds++;
|
||||||
setTimeout(jpxTriggerAuto, 600);
|
let waited = 0;
|
||||||
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
const timer = setInterval(() => {
|
||||||
|
waited += 400;
|
||||||
|
if (jpxMonstersPresent()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
setTimeout(jpxTriggerAuto, 200);
|
||||||
|
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
||||||
|
} else if (waited > 8000 || jpxBattleOver()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
if (!jpxBattleOver()) {
|
||||||
|
console.log('%c[HV] ⛓ timeout waiting for next round', 'color:#f80');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3921,9 +3937,10 @@ function initializeBattle() {
|
||||||
jpxChainStart(); // start first auto round
|
jpxChainStart(); // start first auto round
|
||||||
if (!jpxChainTimer) {
|
if (!jpxChainTimer) {
|
||||||
jpxChainTimer = setInterval(() => {
|
jpxChainTimer = setInterval(() => {
|
||||||
// Fallback poll: if jpx reports inactive but we missed the event
|
// Fallback: if jpx went inactive but we missed the event
|
||||||
// (page reload etc.), check monsters + continue button
|
// (page reload etc.), re-run the state handler to re-arm the
|
||||||
if (jpxChainEnabled && jpxLastActive === false && jpxMonstersPresent() && !jpxBattleOver()) {
|
// wait-for-monsters chain (guarded by the cooldown inside).
|
||||||
|
if (jpxChainEnabled && jpxLastActive === false && !jpxChainWaiting && jpxMonstersPresent() && !jpxBattleOver()) {
|
||||||
jpxChainOnState({ active: false });
|
jpxChainOnState({ active: false });
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name HV Unified
|
// @name HV Unified
|
||||||
// @namespace hvunified
|
// @namespace hvunified
|
||||||
// @version 0.17.3
|
// @version 0.17.4
|
||||||
// @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.3';
|
const VERSION = '0.17.4';
|
||||||
|
|
||||||
const CFG = {
|
const CFG = {
|
||||||
// — Battle strategy advisory
|
// — Battle strategy advisory
|
||||||
|
|
@ -1563,6 +1563,7 @@ let jpxChainTimer = null;
|
||||||
let jpxLastActive = null; // last known isActiveBattle from jpx
|
let jpxLastActive = null; // last known isActiveBattle from jpx
|
||||||
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
||||||
let jpxChainRetryCount = 0; // lazy-start retry counter
|
let jpxChainRetryCount = 0; // lazy-start retry counter
|
||||||
|
let jpxChainWaiting = false; // waiting for next-round monsters to spawn
|
||||||
|
|
||||||
function jpxPresent() {
|
function jpxPresent() {
|
||||||
return !!(document.getElementById('ctrl-widget') ||
|
return !!(document.getElementById('ctrl-widget') ||
|
||||||
|
|
@ -1651,15 +1652,30 @@ function jpxChainOnState(detail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-trigger for the next round — with a small delay so jpx finishes
|
// Don't press M yet — jpx would read it as "advance" (round already
|
||||||
// its re-init (reDoBattle resets state) before we press M again.
|
// ended, no monsters). Wait until the NEXT round's monsters spawn,
|
||||||
// Guard against double-firing within 2.5s.
|
// then trigger auto. Poll up to ~8s.
|
||||||
|
jpxChainWaiting = true;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - jpxChainCooldown < 2500) return;
|
if (now - jpxChainCooldown < 2500) return;
|
||||||
jpxChainCooldown = now;
|
jpxChainCooldown = now;
|
||||||
jpxChainRounds++;
|
jpxChainRounds++;
|
||||||
setTimeout(jpxTriggerAuto, 600);
|
let waited = 0;
|
||||||
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
const timer = setInterval(() => {
|
||||||
|
waited += 400;
|
||||||
|
if (jpxMonstersPresent()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
setTimeout(jpxTriggerAuto, 200);
|
||||||
|
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
||||||
|
} else if (waited > 8000 || jpxBattleOver()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
if (!jpxBattleOver()) {
|
||||||
|
console.log('%c[HV] ⛓ timeout waiting for next round', 'color:#f80');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3921,9 +3937,10 @@ function initializeBattle() {
|
||||||
jpxChainStart(); // start first auto round
|
jpxChainStart(); // start first auto round
|
||||||
if (!jpxChainTimer) {
|
if (!jpxChainTimer) {
|
||||||
jpxChainTimer = setInterval(() => {
|
jpxChainTimer = setInterval(() => {
|
||||||
// Fallback poll: if jpx reports inactive but we missed the event
|
// Fallback: if jpx went inactive but we missed the event
|
||||||
// (page reload etc.), check monsters + continue button
|
// (page reload etc.), re-run the state handler to re-arm the
|
||||||
if (jpxChainEnabled && jpxLastActive === false && jpxMonstersPresent() && !jpxBattleOver()) {
|
// wait-for-monsters chain (guarded by the cooldown inside).
|
||||||
|
if (jpxChainEnabled && jpxLastActive === false && !jpxChainWaiting && jpxMonstersPresent() && !jpxBattleOver()) {
|
||||||
jpxChainOnState({ active: false });
|
jpxChainOnState({ active: false });
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// CONFIG — default settings
|
// CONFIG — default settings
|
||||||
// ═══════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
const VERSION = '0.17.3';
|
const VERSION = '0.17.4';
|
||||||
|
|
||||||
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.3
|
// @version 0.17.4
|
||||||
// @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/*
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,10 @@ function initializeBattle() {
|
||||||
jpxChainStart(); // start first auto round
|
jpxChainStart(); // start first auto round
|
||||||
if (!jpxChainTimer) {
|
if (!jpxChainTimer) {
|
||||||
jpxChainTimer = setInterval(() => {
|
jpxChainTimer = setInterval(() => {
|
||||||
// Fallback poll: if jpx reports inactive but we missed the event
|
// Fallback: if jpx went inactive but we missed the event
|
||||||
// (page reload etc.), check monsters + continue button
|
// (page reload etc.), re-run the state handler to re-arm the
|
||||||
if (jpxChainEnabled && jpxLastActive === false && jpxMonstersPresent() && !jpxBattleOver()) {
|
// wait-for-monsters chain (guarded by the cooldown inside).
|
||||||
|
if (jpxChainEnabled && jpxLastActive === false && !jpxChainWaiting && jpxMonstersPresent() && !jpxBattleOver()) {
|
||||||
jpxChainOnState({ active: false });
|
jpxChainOnState({ active: false });
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ let jpxChainTimer = null;
|
||||||
let jpxLastActive = null; // last known isActiveBattle from jpx
|
let jpxLastActive = null; // last known isActiveBattle from jpx
|
||||||
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
let jpxChainCooldown = 0; // timestamp guard to avoid double-trigger
|
||||||
let jpxChainRetryCount = 0; // lazy-start retry counter
|
let jpxChainRetryCount = 0; // lazy-start retry counter
|
||||||
|
let jpxChainWaiting = false; // waiting for next-round monsters to spawn
|
||||||
|
|
||||||
function jpxPresent() {
|
function jpxPresent() {
|
||||||
return !!(document.getElementById('ctrl-widget') ||
|
return !!(document.getElementById('ctrl-widget') ||
|
||||||
|
|
@ -104,15 +105,30 @@ function jpxChainOnState(detail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-trigger for the next round — with a small delay so jpx finishes
|
// Don't press M yet — jpx would read it as "advance" (round already
|
||||||
// its re-init (reDoBattle resets state) before we press M again.
|
// ended, no monsters). Wait until the NEXT round's monsters spawn,
|
||||||
// Guard against double-firing within 2.5s.
|
// then trigger auto. Poll up to ~8s.
|
||||||
|
jpxChainWaiting = true;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - jpxChainCooldown < 2500) return;
|
if (now - jpxChainCooldown < 2500) return;
|
||||||
jpxChainCooldown = now;
|
jpxChainCooldown = now;
|
||||||
jpxChainRounds++;
|
jpxChainRounds++;
|
||||||
setTimeout(jpxTriggerAuto, 600);
|
let waited = 0;
|
||||||
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
const timer = setInterval(() => {
|
||||||
|
waited += 400;
|
||||||
|
if (jpxMonstersPresent()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
setTimeout(jpxTriggerAuto, 200);
|
||||||
|
console.log(`%c[HV] ⛓ chaining round ${jpxChainRounds}${CFG.chainMaxRounds ? '/' + CFG.chainMaxRounds : ''}`, 'color:#0f0');
|
||||||
|
} else if (waited > 8000 || jpxBattleOver()) {
|
||||||
|
clearInterval(timer);
|
||||||
|
jpxChainWaiting = false;
|
||||||
|
if (!jpxBattleOver()) {
|
||||||
|
console.log('%c[HV] ⛓ timeout waiting for next round', 'color:#f80');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue