From 25ea8b4543ce3a45012166621468536e85c60dd0 Mon Sep 17 00:00:00 2001 From: GaboGG Date: Sun, 26 Jul 2026 14:01:48 -0400 Subject: [PATCH] v0.13.15 - Fix stale Mystic Gem state, add debug logging to Q press MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mystic Gem usage now tracked with STATE._mysticUsed flag Prevents re-triggering the gem check after it's been consumed (stale STATE.itemsKnown was causing infinite 'item → p' loops) - Flag resets on new battle initialization - Added buff durations + channeling status to Q-key console output Shows: ch=true/false mp=X% oc=X buffs: heartseeker=47 haste=24 ... --- scripts/hv-unified.user.js | 26 ++++++++++++++++++-------- scripts/latest.user.js | 26 ++++++++++++++++++-------- src/action-executor.js | 2 ++ src/config.js | 2 +- src/header.user.js | 2 +- src/init.js | 1 + src/keybindings.js | 5 +++++ src/state.js | 2 ++ src/strategy-engine.js | 12 ++++++------ 9 files changed, 54 insertions(+), 24 deletions(-) diff --git a/scripts/hv-unified.user.js b/scripts/hv-unified.user.js index 36e2425..f374ee3 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.13.14 +// @version 0.13.15 // @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* @@ -17,7 +17,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.13.14'; +const VERSION = '0.13.15'; const CFG = { // — Battle automation @@ -77,6 +77,8 @@ const STATE = { inBattle: false, battleInitialized: false, + _mysticUsed: false, // Track if Mystic Gem has been used this battle + maxBuffDur: {}, // Tracks highest duration seen per buff icon hoverTarget: -1, @@ -967,10 +969,10 @@ function getSmartAction() { // ── Novice (1-50): survival first ── function strategyNovice() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle // (channeling status is tracked from the battle log) const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1088,9 +1090,9 @@ function strategyNovice() { // ── Adept (50-150): building power ── function strategyAdept() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1220,9 +1222,9 @@ function strategyAdept() { // ── Veteran (150-300) / Master (300+): full rotation ── function strategyVeteran() { - // 0. Mystic Gem for channeling + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1410,6 +1412,8 @@ function castTargetSpell(n, i) { function useItem(id) { const it = document.getElementById('ikey_' + id); if (!it) return false; + // Track that we used the P-slot gem so we don't retry stale state + if (id === 'p') STATE._mysticUsed = true; dummy.setAttribute('onclick', it.getAttribute('onmouseover')); dummy.click(); it.click(); @@ -1516,6 +1520,11 @@ function setupKeybindings() { if (!isInputFocused() && isBattlePage()) { console.log('%c[HV] Q pressed — checking action...', 'color:#888'); parseBattleState(); + // Debug: show active buffs and channeling status + const activeBuffs = Object.entries(STATE.buffs) + .filter(([k, v]) => v > 0 && k !== 'regen' || v > 0) + .map(([k, v]) => `${k}=${v}`).join(' '); + console.log(`%c[HV] ch=${STATE.channeling} mp=${(STATE.mp*100).toFixed(0)}% oc=${STATE.oc.toFixed(0)} buffs: ${activeBuffs}`, 'color:#888'); const a = getRecommendedAction(); if (a) { e.preventDefault(); @@ -3270,6 +3279,7 @@ function initializeBattle() { if (STATE.battleInitialized && STATE.page === 'battle') return; STATE.page = 'battle'; STATE.inBattle = true; + STATE._mysticUsed = false; // Reset Mystic Gem tracking on new battle parseBattleState(); // Force tier update from cached level (battle page may not have level_readout) diff --git a/scripts/latest.user.js b/scripts/latest.user.js index 36e2425..f374ee3 100644 --- a/scripts/latest.user.js +++ b/scripts/latest.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.13.14 +// @version 0.13.15 // @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* @@ -17,7 +17,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.13.14'; +const VERSION = '0.13.15'; const CFG = { // — Battle automation @@ -77,6 +77,8 @@ const STATE = { inBattle: false, battleInitialized: false, + _mysticUsed: false, // Track if Mystic Gem has been used this battle + maxBuffDur: {}, // Tracks highest duration seen per buff icon hoverTarget: -1, @@ -967,10 +969,10 @@ function getSmartAction() { // ── Novice (1-50): survival first ── function strategyNovice() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle // (channeling status is tracked from the battle log) const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1088,9 +1090,9 @@ function strategyNovice() { // ── Adept (50-150): building power ── function strategyAdept() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1220,9 +1222,9 @@ function strategyAdept() { // ── Veteran (150-300) / Master (300+): full rotation ── function strategyVeteran() { - // 0. Mystic Gem for channeling + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -1410,6 +1412,8 @@ function castTargetSpell(n, i) { function useItem(id) { const it = document.getElementById('ikey_' + id); if (!it) return false; + // Track that we used the P-slot gem so we don't retry stale state + if (id === 'p') STATE._mysticUsed = true; dummy.setAttribute('onclick', it.getAttribute('onmouseover')); dummy.click(); it.click(); @@ -1516,6 +1520,11 @@ function setupKeybindings() { if (!isInputFocused() && isBattlePage()) { console.log('%c[HV] Q pressed — checking action...', 'color:#888'); parseBattleState(); + // Debug: show active buffs and channeling status + const activeBuffs = Object.entries(STATE.buffs) + .filter(([k, v]) => v > 0 && k !== 'regen' || v > 0) + .map(([k, v]) => `${k}=${v}`).join(' '); + console.log(`%c[HV] ch=${STATE.channeling} mp=${(STATE.mp*100).toFixed(0)}% oc=${STATE.oc.toFixed(0)} buffs: ${activeBuffs}`, 'color:#888'); const a = getRecommendedAction(); if (a) { e.preventDefault(); @@ -3270,6 +3279,7 @@ function initializeBattle() { if (STATE.battleInitialized && STATE.page === 'battle') return; STATE.page = 'battle'; STATE.inBattle = true; + STATE._mysticUsed = false; // Reset Mystic Gem tracking on new battle parseBattleState(); // Force tier update from cached level (battle page may not have level_readout) diff --git a/src/action-executor.js b/src/action-executor.js index 0cf3644..2628b5f 100644 --- a/src/action-executor.js +++ b/src/action-executor.js @@ -47,6 +47,8 @@ function castTargetSpell(n, i) { function useItem(id) { const it = document.getElementById('ikey_' + id); if (!it) return false; + // Track that we used the P-slot gem so we don't retry stale state + if (id === 'p') STATE._mysticUsed = true; dummy.setAttribute('onclick', it.getAttribute('onmouseover')); dummy.click(); it.click(); diff --git a/src/config.js b/src/config.js index a7b6369..9a98df4 100644 --- a/src/config.js +++ b/src/config.js @@ -2,7 +2,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.13.14'; +const VERSION = '0.13.15'; const CFG = { // — Battle automation diff --git a/src/header.user.js b/src/header.user.js index 7016a4e..df83265 100644 --- a/src/header.user.js +++ b/src/header.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.13.14 +// @version 0.13.15 // @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* diff --git a/src/init.js b/src/init.js index ecb0de6..d86382b 100644 --- a/src/init.js +++ b/src/init.js @@ -49,6 +49,7 @@ function initializeBattle() { if (STATE.battleInitialized && STATE.page === 'battle') return; STATE.page = 'battle'; STATE.inBattle = true; + STATE._mysticUsed = false; // Reset Mystic Gem tracking on new battle parseBattleState(); // Force tier update from cached level (battle page may not have level_readout) diff --git a/src/keybindings.js b/src/keybindings.js index bb4d0d6..6024979 100644 --- a/src/keybindings.js +++ b/src/keybindings.js @@ -23,6 +23,11 @@ function setupKeybindings() { if (!isInputFocused() && isBattlePage()) { console.log('%c[HV] Q pressed — checking action...', 'color:#888'); parseBattleState(); + // Debug: show active buffs and channeling status + const activeBuffs = Object.entries(STATE.buffs) + .filter(([k, v]) => v > 0 && k !== 'regen' || v > 0) + .map(([k, v]) => `${k}=${v}`).join(' '); + console.log(`%c[HV] ch=${STATE.channeling} mp=${(STATE.mp*100).toFixed(0)}% oc=${STATE.oc.toFixed(0)} buffs: ${activeBuffs}`, 'color:#888'); const a = getRecommendedAction(); if (a) { e.preventDefault(); diff --git a/src/state.js b/src/state.js index db45b01..c60dafb 100644 --- a/src/state.js +++ b/src/state.js @@ -13,6 +13,8 @@ const STATE = { inBattle: false, battleInitialized: false, + _mysticUsed: false, // Track if Mystic Gem has been used this battle + maxBuffDur: {}, // Tracks highest duration seen per buff icon hoverTarget: -1, diff --git a/src/strategy-engine.js b/src/strategy-engine.js index c5b6f1e..c5fbbb4 100644 --- a/src/strategy-engine.js +++ b/src/strategy-engine.js @@ -308,10 +308,10 @@ function getSmartAction() { // ── Novice (1-50): survival first ── function strategyNovice() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle // (channeling status is tracked from the battle log) const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -429,9 +429,9 @@ function strategyNovice() { // ── Adept (50-150): building power ── function strategyAdept() { - // 0. Mystic Gem for channeling — free OC + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early @@ -561,9 +561,9 @@ function strategyAdept() { // ── Veteran (150-300) / Master (300+): full rotation ── function strategyVeteran() { - // 0. Mystic Gem for channeling + // 0. Mystic Gem for channeling — only use once per battle const gem = hasUsableGem('channel'); - if (gem && !STATE.channeling) + if (gem && !STATE.channeling && !STATE._mysticUsed) return { type: 'item', id: gem.id, selfTarget: true }; // 1. Health items — safe to use early