v0.14.4 - Sort buff loop by cost (cheapest-first when no channeling)
- Regular buff loop in all 3 tiers now collects candidates then sorts by MP cost ascending (cheapest first) when no channeling, or descending (most expensive first) when channeling is active - Previously just iterated BUFF_PRIORITY declaration order (Haste → Spark → Heartseeker → Regen → Absorb → Shadow Veil) which wasn't cost-ordered - _reason now shows 'buff' (cheapest first) or 'chBuff' (most expensive)
This commit is contained in:
parent
48e5103655
commit
0a41f9d7c5
5 changed files with 84 additions and 18 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.14.3
|
||||
// @version 0.14.4
|
||||
// @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.14.3';
|
||||
const VERSION = '0.14.4';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
@ -1155,12 +1155,19 @@ function strategyNovice() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -1291,17 +1298,24 @@ function strategyAdept() {
|
|||
}
|
||||
// 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 channeling is active, prioritize most expensive buff for best value
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Adept)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -1447,12 +1461,20 @@ function strategyVeteran() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
// No channeling → cheapest first (proc chance), channeling → most expensive (MP value)
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true, _reason: 'buff' };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.14.3
|
||||
// @version 0.14.4
|
||||
// @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.14.3';
|
||||
const VERSION = '0.14.4';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
@ -1155,12 +1155,19 @@ function strategyNovice() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -1291,17 +1298,24 @@ function strategyAdept() {
|
|||
}
|
||||
// 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 channeling is active, prioritize most expensive buff for best value
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Adept)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -1447,12 +1461,20 @@ function strategyVeteran() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
// No channeling → cheapest first (proc chance), channeling → most expensive (MP value)
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true, _reason: 'buff' };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// CONFIG — default settings
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
const VERSION = '0.14.3';
|
||||
const VERSION = '0.14.4';
|
||||
|
||||
const CFG = {
|
||||
// — Battle automation
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name HV Unified
|
||||
// @namespace hvunified
|
||||
// @version 0.14.3
|
||||
// @version 0.14.4
|
||||
// @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse
|
||||
// @author GaboGG + Hermes
|
||||
// @match *://*.hentaiverse.org/*
|
||||
|
|
|
|||
|
|
@ -430,12 +430,19 @@ function strategyNovice() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -566,17 +573,24 @@ function strategyAdept() {
|
|||
}
|
||||
// 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 channeling is active, prioritize most expensive buff for best value
|
||||
if (STATE.channeling && STATE.mp > 0.10) {
|
||||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Adept)
|
||||
if (STATE.mp < CFG.manaGemMP) {
|
||||
|
|
@ -722,12 +736,20 @@ function strategyVeteran() {
|
|||
const ch = findBestChannelingTarget();
|
||||
if (ch) return ch;
|
||||
}
|
||||
// Collect available buff candidates and sort by cost
|
||||
// No channeling → cheapest first (proc chance), channeling → most expensive (MP value)
|
||||
const buffCandidates = [];
|
||||
for (const b of BUFF_PRIORITY) {
|
||||
if (shouldBuff(b.icon, b.minTurns) && STATE.mp > 0.10 && hasReadySpell(b.spell)) {
|
||||
if (b.icon === 'regen' && STATE.hp >= CFG.cureRegenHP) continue;
|
||||
return { type: 'spell', name: b.spell, selfTarget: true, _reason: 'buff' };
|
||||
const sp = findSpell(b.spell);
|
||||
buffCandidates.push({ ...b, mpCost: sp ? sp.mp : 0 });
|
||||
}
|
||||
}
|
||||
if (buffCandidates.length > 0) {
|
||||
buffCandidates.sort((a, b) => STATE.channeling ? b.mpCost - a.mpCost : a.mpCost - b.mpCost);
|
||||
return { type: 'spell', name: buffCandidates[0].spell, selfTarget: true, _reason: STATE.channeling ? 'chBuff' : 'buff' };
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Mana/spirit items — AFTER buffs (Novice)
|
||||
|
|
|
|||
Loading…
Reference in a new issue