v0.13.20 - Add SPELL_COSTS fallback for Mana Conservation-reduced MP costs

- Some spells show mp=1 in the DOM due to high Mana Conservation
  proficiency, making fill-level scoring produce near-zero values
- Now: if mpCost < 5, look up the base cost from SPELL_COSTS table
- This ensures Heartseeker (141 MP) scores correctly even when the
  DOM shows it costing 1 MP
This commit is contained in:
GaboGG 2026-07-26 15:01:49 -04:00
parent e914c08475
commit e20fe0495c
6 changed files with 69 additions and 9 deletions

View file

@ -1,7 +1,7 @@
// ==UserScript==
// @name HV Unified
// @namespace hvunified
// @version 0.13.19
// @version 0.13.20
// @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.19';
const VERSION = '0.13.20';
const CFG = {
// — Battle automation
@ -580,6 +580,18 @@ function hasUsableGem(type) {
// KNOWLEDGE BASE — game data, spell unlocks, milestones, stat advice
// ═══════════════════════════════════════════════════════════════════════
// Base MP costs for buff spells (used for channeling value calculation when
// the DOM shows Mana Conservation-reduced costs like 1 MP)
const SPELL_COSTS = {
'Absorb': 40,
'Haste': 51,
'Heartseeker': 141,
'Protection': 32,
'Regen': 71,
'Shadow Veil': 52,
'Spark of Life': 70,
};
const KB = {
qualities: ['Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary', 'Peerless'],
@ -903,7 +915,15 @@ function findBestChannelingTarget() {
const dur = buffDuration(b.icon);
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
const sp = findSpell(b.spell);
const mpCost = sp ? sp.mp : 0;
// Use a reasonable MP cost: ignore Mana Conservation-reduced values
// (the DOM may show 1 MP at high proficiency, but the real base cost
// determines the savings from a free channeling cast)
let mpCost = sp ? sp.mp : 0;
if (mpCost > 0 && mpCost < 5 && sp) {
// Try to get base cost from knowledge-base
const kb = SPELL_COSTS[b.spell];
if (kb) mpCost = kb;
}
// Fill level: how empty is this buff relative to its max observed duration
let maxDur = STATE.maxBuffDur[b.icon] || 0;
// If max matches current (first observation, no learning yet), assume min 30 turns

View file

@ -1,7 +1,7 @@
// ==UserScript==
// @name HV Unified
// @namespace hvunified
// @version 0.13.19
// @version 0.13.20
// @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.19';
const VERSION = '0.13.20';
const CFG = {
// — Battle automation
@ -580,6 +580,18 @@ function hasUsableGem(type) {
// KNOWLEDGE BASE — game data, spell unlocks, milestones, stat advice
// ═══════════════════════════════════════════════════════════════════════
// Base MP costs for buff spells (used for channeling value calculation when
// the DOM shows Mana Conservation-reduced costs like 1 MP)
const SPELL_COSTS = {
'Absorb': 40,
'Haste': 51,
'Heartseeker': 141,
'Protection': 32,
'Regen': 71,
'Shadow Veil': 52,
'Spark of Life': 70,
};
const KB = {
qualities: ['Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary', 'Peerless'],
@ -903,7 +915,15 @@ function findBestChannelingTarget() {
const dur = buffDuration(b.icon);
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
const sp = findSpell(b.spell);
const mpCost = sp ? sp.mp : 0;
// Use a reasonable MP cost: ignore Mana Conservation-reduced values
// (the DOM may show 1 MP at high proficiency, but the real base cost
// determines the savings from a free channeling cast)
let mpCost = sp ? sp.mp : 0;
if (mpCost > 0 && mpCost < 5 && sp) {
// Try to get base cost from knowledge-base
const kb = SPELL_COSTS[b.spell];
if (kb) mpCost = kb;
}
// Fill level: how empty is this buff relative to its max observed duration
let maxDur = STATE.maxBuffDur[b.icon] || 0;
// If max matches current (first observation, no learning yet), assume min 30 turns

View file

@ -2,7 +2,7 @@
// CONFIG — default settings
// ═══════════════════════════════════════════════════════════════════════
const VERSION = '0.13.19';
const VERSION = '0.13.20';
const CFG = {
// — Battle automation

View file

@ -1,7 +1,7 @@
// ==UserScript==
// @name HV Unified
// @namespace hvunified
// @version 0.13.19
// @version 0.13.20
// @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse
// @author GaboGG + Hermes
// @match *://*.hentaiverse.org/*

View file

@ -2,6 +2,18 @@
// KNOWLEDGE BASE — game data, spell unlocks, milestones, stat advice
// ═══════════════════════════════════════════════════════════════════════
// Base MP costs for buff spells (used for channeling value calculation when
// the DOM shows Mana Conservation-reduced costs like 1 MP)
const SPELL_COSTS = {
'Absorb': 40,
'Haste': 51,
'Heartseeker': 141,
'Protection': 32,
'Regen': 71,
'Shadow Veil': 52,
'Spark of Life': 70,
};
const KB = {
qualities: ['Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary', 'Peerless'],

View file

@ -238,7 +238,15 @@ function findBestChannelingTarget() {
const dur = buffDuration(b.icon);
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
const sp = findSpell(b.spell);
const mpCost = sp ? sp.mp : 0;
// Use a reasonable MP cost: ignore Mana Conservation-reduced values
// (the DOM may show 1 MP at high proficiency, but the real base cost
// determines the savings from a free channeling cast)
let mpCost = sp ? sp.mp : 0;
if (mpCost > 0 && mpCost < 5 && sp) {
// Try to get base cost from knowledge-base
const kb = SPELL_COSTS[b.spell];
if (kb) mpCost = kb;
}
// Fill level: how empty is this buff relative to its max observed duration
let maxDur = STATE.maxBuffDur[b.icon] || 0;
// If max matches current (first observation, no learning yet), assume min 30 turns