v0.13.21 - Dynamic base cost read + affordable MP check for channeling
- Removed hardcoded SPELL_COSTS table (was brittle) - Now reads base MP cost directly from the magic pane's onmouseover tooltip (always shows true base cost, unaffected by channeling's 1-MP display or Mana Conservation) - Added affordable check: skip spells where base cost exceeds current MP, even though channeling would make it cost 1 - The game's native MP check (shown by "You do not have enough") checks against base cost, not channeling-reduced cost
This commit is contained in:
parent
e20fe0495c
commit
80fc77600a
5 changed files with 60 additions and 30 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.13.20
|
||||
// @version 0.13.21
|
||||
// @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.20';
|
||||
const VERSION = '0.13.21';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
@ -915,15 +915,23 @@ function findBestChannelingTarget() {
|
|||
const dur = buffDuration(b.icon);
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
const sp = findSpell(b.spell);
|
||||
// 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;
|
||||
// Read base MP cost from the magic pane tooltip (always the full base cost,
|
||||
// unaffected by channeling's 1-MP display or Mana Conservation)
|
||||
let baseCost = 0;
|
||||
const paneEl = $$('.btsd[onmouseover*="' + b.spell.replace(/'/g, "\\'") + '"]',
|
||||
document.getElementById('pane_magic'))[0];
|
||||
if (paneEl) {
|
||||
const costM = (paneEl.getAttribute('onmouseover') || '')
|
||||
.match(/set_infopane_spell\('[^']+',\s*'[^']*',\s*'[^']*',\s*(\d+)/);
|
||||
if (costM) baseCost = parseInt(costM[1]);
|
||||
}
|
||||
let mpCost = sp ? sp.mp : 0;
|
||||
// Use base cost from DOM instead of Mana Conservation-reduced cost
|
||||
if (baseCost > 0) mpCost = baseCost;
|
||||
// Skip if we can't afford the base cost — game pre-checks even when
|
||||
// channeling makes the effective cost 1 MP
|
||||
const maxMp = parseInt((document.getElementById('vrhd') || {}).textContent) || 414;
|
||||
if (mpCost > 0 && (mpCost / maxMp) > STATE.mp) continue;
|
||||
// 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
|
||||
|
|
@ -1141,6 +1149,8 @@ function strategyAdept() {
|
|||
if (ib) return ib;
|
||||
}
|
||||
// If channeling is active, prioritize most expensive buff for best value
|
||||
// Note: channeling reduces cost to ~1, but the game pre-checks base MP,
|
||||
// so we skip spells we can't afford at base cost
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.13.20
|
||||
// @version 0.13.21
|
||||
// @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.20';
|
||||
const VERSION = '0.13.21';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
@ -915,15 +915,23 @@ function findBestChannelingTarget() {
|
|||
const dur = buffDuration(b.icon);
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
const sp = findSpell(b.spell);
|
||||
// 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;
|
||||
// Read base MP cost from the magic pane tooltip (always the full base cost,
|
||||
// unaffected by channeling's 1-MP display or Mana Conservation)
|
||||
let baseCost = 0;
|
||||
const paneEl = $$('.btsd[onmouseover*="' + b.spell.replace(/'/g, "\\'") + '"]',
|
||||
document.getElementById('pane_magic'))[0];
|
||||
if (paneEl) {
|
||||
const costM = (paneEl.getAttribute('onmouseover') || '')
|
||||
.match(/set_infopane_spell\('[^']+',\s*'[^']*',\s*'[^']*',\s*(\d+)/);
|
||||
if (costM) baseCost = parseInt(costM[1]);
|
||||
}
|
||||
let mpCost = sp ? sp.mp : 0;
|
||||
// Use base cost from DOM instead of Mana Conservation-reduced cost
|
||||
if (baseCost > 0) mpCost = baseCost;
|
||||
// Skip if we can't afford the base cost — game pre-checks even when
|
||||
// channeling makes the effective cost 1 MP
|
||||
const maxMp = parseInt((document.getElementById('vrhd') || {}).textContent) || 414;
|
||||
if (mpCost > 0 && (mpCost / maxMp) > STATE.mp) continue;
|
||||
// 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
|
||||
|
|
@ -1141,6 +1149,8 @@ function strategyAdept() {
|
|||
if (ib) return ib;
|
||||
}
|
||||
// If channeling is active, prioritize most expensive buff for best value
|
||||
// Note: channeling reduces cost to ~1, but the game pre-checks base MP,
|
||||
// so we skip spells we can't afford at base cost
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// CONFIG — default settings
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
const VERSION = '0.13.20';
|
||||
const VERSION = '0.13.21';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.13.20
|
||||
// @version 0.13.21
|
||||
// @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse
|
||||
// @author GaboGG + Hermes
|
||||
// @match *://*.hentaiverse.org/*
|
||||
|
|
|
|||
|
|
@ -238,15 +238,23 @@ function findBestChannelingTarget() {
|
|||
const dur = buffDuration(b.icon);
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
const sp = findSpell(b.spell);
|
||||
// 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;
|
||||
// Read base MP cost from the magic pane tooltip (always the full base cost,
|
||||
// unaffected by channeling's 1-MP display or Mana Conservation)
|
||||
let baseCost = 0;
|
||||
const paneEl = $$('.btsd[onmouseover*="' + b.spell.replace(/'/g, "\\'") + '"]',
|
||||
document.getElementById('pane_magic'))[0];
|
||||
if (paneEl) {
|
||||
const costM = (paneEl.getAttribute('onmouseover') || '')
|
||||
.match(/set_infopane_spell\('[^']+',\s*'[^']*',\s*'[^']*',\s*(\d+)/);
|
||||
if (costM) baseCost = parseInt(costM[1]);
|
||||
}
|
||||
let mpCost = sp ? sp.mp : 0;
|
||||
// Use base cost from DOM instead of Mana Conservation-reduced cost
|
||||
if (baseCost > 0) mpCost = baseCost;
|
||||
// Skip if we can't afford the base cost — game pre-checks even when
|
||||
// channeling makes the effective cost 1 MP
|
||||
const maxMp = parseInt((document.getElementById('vrhd') || {}).textContent) || 414;
|
||||
if (mpCost > 0 && (mpCost / maxMp) > STATE.mp) continue;
|
||||
// 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
|
||||
|
|
@ -464,6 +472,8 @@ function strategyAdept() {
|
|||
if (ib) return ib;
|
||||
}
|
||||
// If channeling is active, prioritize most expensive buff for best value
|
||||
// Note: channeling reduces cost to ~1, but the game pre-checks base MP,
|
||||
// so we skip spells we can't afford at base cost
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
|
|
|
|||
Loading…
Reference in a new issue