From e74c97f87a0c8cfc445b0a02b012486c3c9665ae Mon Sep 17 00:00:00 2001 From: GaboGG Date: Sun, 26 Jul 2026 14:08:50 -0400 Subject: [PATCH] v0.13.17 - Fix fill-level scoring when maxBuffDur hasn't been learned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - When maxBuffDur for a buff equals its current duration (first observation in a battle), the emptiness was 0 — making the script think all buffs are full and skipping them - Now: if maxDur <= current dur, assume a minimum of 30 turns as the max - This ensures buffs like Shadow Veil at 8/8 are treated as 8/30 (73% empty) instead of 8/8 (0% empty) --- scripts/hv-unified.user.js | 8 +++++--- scripts/latest.user.js | 8 +++++--- src/config.js | 2 +- src/header.user.js | 2 +- src/strategy-engine.js | 4 +++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/scripts/hv-unified.user.js b/scripts/hv-unified.user.js index 9d89d1e..ec45c86 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.16 +// @version 0.13.17 // @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.16'; +const VERSION = '0.13.17'; const CFG = { // — Battle automation @@ -903,7 +903,9 @@ function findBestChannelingTarget() { const sp = findSpell(b.spell); const mpCost = sp ? sp.mp : 0; // Fill level: how empty is this buff relative to its max observed duration - const maxDur = STATE.maxBuffDur[b.icon] || (dur + 10); // fallback if unknown + let maxDur = STATE.maxBuffDur[b.icon] || 0; + // If max matches current (first observation, no learning yet), assume min 30 turns + if (maxDur <= dur) maxDur = Math.max(dur + 1, 30); const emptiness = maxDur > 0 ? Math.min(1, (maxDur - dur) / maxDur) : 1; // Score: emptiness × mp_cost — an empty expensive buff is best const score = emptiness * mpCost; diff --git a/scripts/latest.user.js b/scripts/latest.user.js index 9d89d1e..ec45c86 100644 --- a/scripts/latest.user.js +++ b/scripts/latest.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.13.16 +// @version 0.13.17 // @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.16'; +const VERSION = '0.13.17'; const CFG = { // — Battle automation @@ -903,7 +903,9 @@ function findBestChannelingTarget() { const sp = findSpell(b.spell); const mpCost = sp ? sp.mp : 0; // Fill level: how empty is this buff relative to its max observed duration - const maxDur = STATE.maxBuffDur[b.icon] || (dur + 10); // fallback if unknown + let maxDur = STATE.maxBuffDur[b.icon] || 0; + // If max matches current (first observation, no learning yet), assume min 30 turns + if (maxDur <= dur) maxDur = Math.max(dur + 1, 30); const emptiness = maxDur > 0 ? Math.min(1, (maxDur - dur) / maxDur) : 1; // Score: emptiness × mp_cost — an empty expensive buff is best const score = emptiness * mpCost; diff --git a/src/config.js b/src/config.js index dc586d9..c3e785d 100644 --- a/src/config.js +++ b/src/config.js @@ -2,7 +2,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.13.16'; +const VERSION = '0.13.17'; const CFG = { // — Battle automation diff --git a/src/header.user.js b/src/header.user.js index 61f5e99..9e955d6 100644 --- a/src/header.user.js +++ b/src/header.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.13.16 +// @version 0.13.17 // @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse // @author GaboGG + Hermes // @match *://*.hentaiverse.org/* diff --git a/src/strategy-engine.js b/src/strategy-engine.js index c5fbbb4..cc20624 100644 --- a/src/strategy-engine.js +++ b/src/strategy-engine.js @@ -240,7 +240,9 @@ function findBestChannelingTarget() { const sp = findSpell(b.spell); const mpCost = sp ? sp.mp : 0; // Fill level: how empty is this buff relative to its max observed duration - const maxDur = STATE.maxBuffDur[b.icon] || (dur + 10); // fallback if unknown + let maxDur = STATE.maxBuffDur[b.icon] || 0; + // If max matches current (first observation, no learning yet), assume min 30 turns + if (maxDur <= dur) maxDur = Math.max(dur + 1, 30); const emptiness = maxDur > 0 ? Math.min(1, (maxDur - dur) / maxDur) : 1; // Score: emptiness × mp_cost — an empty expensive buff is best const score = emptiness * mpCost;