Commit graph

95 commits

Author SHA1 Message Date
GaboGG
b2e96c6191 v0.14.37 - Fix gear panel: buttons were submitting the armory form
Root cause: both buttons were inserted inside the armory <form>.
HTML <button> defaults to type=submit — clicking submitted the form,
the page reloaded, and the panel (which renders 300ms later) was
destroyed. The split-second flash was the panel before the reload.

Fix: type='button' on both buttons. Panel now stays up.
2026-07-31 09:02:16 -04:00
GaboGG
f3561bb435 v0.14.36 - Add diagnostic logs to gear panel (click, build, render) 2026-07-31 08:57:28 -04:00
GaboGG
217e0cd162 v0.14.35 - Fix gear panel not showing + remove Daily Activities
- Gear panel: wrapped autoScrapeGear() and buildGearPanel() in try/catch.
  An exception during scrape (new store-scan loop) killed the onclick
  handler before the panel was scheduled — panel never appeared.
- Removed renderProgressPanel() call (Daily Activities window) per user
  request — not used.
2026-07-31 07:14:52 -04:00
GaboGG
03cbccf703 v0.14.34 - Fix difficulty comparison case bug
Bug: difficulties.indexOf(difficulty.toUpperCase()) — the array has
'Nintendo' (mixed case) but toUpperCase() gives 'NINTENDO' which
doesn't match, so currentIdx = -1 and -1 < suggestedIdx always true.
The suggestion kept firing even when already on Nintendo.
(IWBTH worked by luck since uppercase == itself.)

Fix: case-insensitive findIndex comparison on both sides.
2026-07-31 07:09:30 -04:00
GaboGG
166539e845 v0.14.33 - In-game gear analysis module
New src/gear-analysis.js — ports analyze_gear.py scoring to JS:
- gearScoreArmor() / gearScoreWeapon() — same weights as Python
- gearDetectSlot() / gearIsTwoHandWeapon() / gearUsable()
- analyzeGear() — scores equipped vs armory vs buy per slot

UI on Armory pages (above equiplist):
- 🔍 Analyze Gear — rescrapes current page, shows per-slot panel
  with top 4 candidates, scores, prices, and upgrade highlights
- 🔄 Clear Buy + Rescan — wipes stale buy data, rescrapes, analyzes

scrapeBuyPage() now also scavenges the full dynjs_eqstore for items
not visible in the current filter tab — one Purchase visit captures
the entire store (429+ items), no need to click through tabs.

Console API: HV.analyzeGear(), HV.gearPanel(), HV.clearBuy()
2026-07-31 07:07:38 -04:00
GaboGG
6ac31faa1f v0.14.32 - Veteran suggestion: IWBTH → Nintendo
- guidance.js now suggests Nintendo (4x) instead of IWBTH (5x) for
  the Veteran tier (150-300). You're dropping down to clear arenas
  while the current gear catches up.
- Updated the reason text to '10x EXP. Better drops than Hell, while
  still comfortable.'
2026-07-29 12:41:15 -04:00
GaboGG
3ec8932b86 v0.14.31 - Skip debuffs during spirit burst (flag >= 1) to prevent toggle loops
Bug: spirit toggle ON → Imperil intercepts → toggle OFF → never fires skill.
The 3-state flag for spirit burst worked, but debuffs (Imperil at step 6)
came before weapon skills (step 11) in the priority chain. Each time the
flag advanced past 1, Imperil fired instead of Rending Blow, consuming
the turn and causing spirit to toggle off without ever using the skill.

Fix: debuffs now check _spiritForSkill === 0 before firing. When spirit
burst is pending (flag >= 1), skip Imperil/Weaken so the weapon skills
section fires uninterrupted.
2026-07-29 12:35:50 -04:00
GaboGG
2d6042df64 v0.14.30 - Ignore high threat when 2 or fewer enemies
- Step 0e (emergency weapon skills): requires STATE.monsters.length >= 3.
  With 1-2 enemies, basic attack and tank the hits — better to farm OC.
- Step 11 (normal weapon skills): isHighThreat trigger also requires >= 3.
  If OC >= 60 naturally, skills still fire regardless of enemy count.
- Great Cleave on rares still works at lower OC since rares are worth
  killing fast regardless of group size.
2026-07-28 10:43:07 -04:00
GaboGG
782a094691 v0.14.29 - Fix Rending Blow positioning + remove hp guard on OC build
- Rending Blow now uses findOptimalDominoTarget() which scores monsters
  by how many alive neighbors are within 2 slots left/right. This
  ensures RB hits max targets instead of wasting half the AoE on
  edge monsters (previously used findDangerousMonster which ignores
  positioning).
- Removed STATE.hp > 0.40 guard from step 2c OC-building check. When
  Spark of Life procs, hp=0 in the DOM but the player is still alive.
  The old guard blocked OC building in this state, causing Imperil
  to fire instead of basic attacking to build OC.
2026-07-28 10:40:16 -04:00
GaboGG
e48ef78121 v0.14.28 - OC-building priority: skip debuffs/buffs when AoE ready but OC low
New step 2c: when 5+ monsters, Rending Blow is ready, and OC < 60,
skip Imperil/Absorb/buff loops and basic attack to build OC.

In your log, RB was ready (sk:RRGR) from turn 1 at OC=20, but the
script spent 20 turns on Imperil x3 + Absorb (999!) + Curx3 +
items before finally firing RB at turn 21 when monsters were at
100+ SP. Now it basic-attacks aggressively to hit OC=60 faster,
then fires RB as soon as threshold is reached.
2026-07-28 10:36:34 -04:00
GaboGG
206c682d9e v0.14.27 - Enhanced logging: alive/dead markers, skill readiness, item counts
Log line now shows:
- spBars: 0:29A 1:28A 2:59A 3:52A 4:34A 5:43A 6:29A
  (A=alive onclick, D=dead/no onclick — so you know which SP bars
   are actionable vs leftover from dead mobs)
- sk: RC CC RC (R=Rending Blow Ready/C=Cooldown, S=Shatter, G=Great Cleave)
  — first char of skill name + R/C for ready/cooldown
- h5 s3 m4 (heal=5, spirit=3, mana=4 — item counts per type)
  — so you can see consumable status at a glance
2026-07-28 10:16:31 -04:00
GaboGG
ff728fe68f v0.14.26 - Fix threat threshold (70%->80%) + stalling on single enemy
- Threat threshold raised from 70% (84px) to 80% (96px) — stops
  wasting OC on Rending Blow when enemies are at 89 SP (31 points
  from actually specialing). In the log, RB fired at OC=50 on 89SP
  mobs which wasn't an emergency.
- Single-monster stalling now triggers regardless of enemy SP level.
  Previously blocked by !hasHighThreat — if the last enemy had high
  SP, stalling was skipped and the script killed immediately, wasting
  the stall opportunity for skill cooldown recovery.
2026-07-28 10:14:08 -04:00
GaboGG
3618198081 v0.14.25 - Stalling: refresh buffs when 1 enemy remains (gives skill CDs time)
- New stalling logic: when exactly 1 normal enemy remains (not rare,
  not high threat), refresh any buff below 15 turns instead of attacking
- This naturally delays the killing blow by 1 turn, letting Rending Blow
  and Shatter Strike cooldowns tick down before the round ends
- Result: next round starts with skills ready + higher buff uptime
- Edge case: one-tapping the last enemy would end the round with skills
  still on cooldown — now avoided
2026-07-28 09:36:58 -04:00
GaboGG
7c714eb589 v0.14.24 - Fix spirit burst toggle-off (was stuck ON after Rending Blow killed <7 mobs)
- The toggle-off (state 2 -> OFF) was inside the monsters.length >= 7 check
- If Rending Blow killed enough enemies to drop below 7, the else block
  reset _spiritForSkill = 0 without toggling spirit off, leaving it ON
- Now toggle-off guard runs independently of monster count
- Also resets flag if spirit gets toggled externally
2026-07-28 09:19:22 -04:00
GaboGG
f42e44db34 v0.14.23 - OC conservation: save weapon skills for 3+ mob groups
- Raised heal threshold from 60%@7+ to 65%@5+ (earlier healing in big groups)
- Cure threshold also dynamic: 65% when 5+ mobs, normal otherwise
- Secondary weapon skill dump restricted to 3+ enemies (no OC waste on cleanup)
- Great Cleave already limited to rares — kept as-is
- Simulation confirmed +7 rounds deeper (R30->R37 avg) from OC conservation
- Source: agy_oc_output.txt
2026-07-28 09:12:01 -04:00
GaboGG
93c0f85acd v0.14.22 - Survival-first priority chain (simulation-backed, 10/10 survival)
AGY built a full 60-round arena simulator (hv-battle-sim.py) using
the user's actual gear/stats and ran 10 iterations:

  Original: 0/10 survived (0%)
  Improved: 10/10 survived (100%)

Critical changes from simulation findings:
  - Health items + Cure moved to TOP of priority chain (before skills)
  - Dynamic HP threshold: 60% when 7+ mobs, normal threshold otherwise
  - SP threshold raised from 55% to 60% for Spark safety buffer
  - Mana maintenance raised to prevent spell lockout
  - AoE crowd control prioritized for 4+ mobs

Full report in agy_sim_output.txt
2026-07-28 06:19:02 -04:00
GaboGG
229d81b86c v0.14.21 - Show purchasable (buy) items in gearSummary
- logGearSummary() now shows 3 sources: 🟢 equipped, 📦 stored, 🛒 purchasable
- Highlights buy items NOT already in armory inventory
- Summary: Gear DB: 746 total (7 🟢 equipped, 305 📦 stored, 434 🛒 purchasable)
- Works with manual HV.scrapeGear() call on Purchase page
2026-07-27 20:54:16 -04:00
GaboGG
5286f66b3e v0.14.20 - Fix Purchase page scraper: const dynjs_eqstore + screen=purchase
- Bug 1: Purchase tab URL is 'screen=purchase', not 'screen=buy'
- Bug 2: dynjs_eqstore is declared with 'const', not 'var', so it doesn't
  create a window property. getHVEquipStore() now also checks bare names
  which works with @grant none and the IIFE scope chain
- Fixed price parsing: purchase table has 2 td cells (label + price),
  previously required >3 cells so prices were always empty
- Names with 🔺 prefix are cleaned before storage
2026-07-27 20:48:27 -04:00
GaboGG
f2e8ce536a v0.14.19 - Add Bazaar Buy page scraper + 3-source analysis
- scrapeBuyPage() scrapes equipment for sale from Bazaar Buy tab
  (URL: ss=am&screen=buy or ss=bi), marks as source='buy'
- Stores merge with existing: buy items don't overwrite equipped/armory
- Auto-detect routing handles buy page URL patterns
- analyze_gear.py updated with 3-source output:
  🟢 Equipped = currently worn
  📦 Stored = in armory inventory
  🛒 For Sale = purchasable from Bazaar
- Shows level limits (Lv155 + 15 = Lv170 cap), prices where available
- Re-scrape after visiting Buy tab to include market items
2026-07-27 20:38:09 -04:00
GaboGG
94ab29a82c v0.14.18 - Spirit Stance burst toggle for 7+ mob Rending Blow
- When 7+ enemies and OC >= 60: toggles Spirit Stance ON before casting
  Rending Blow, then toggles OFF after one skill
- Uses 3-state flag: press1=toggleON, press2=castSkill, press3=toggleOFF
- Only triggers on normal (non-panic) Rending Blow — step 0e emergency
  skill still fires without spirit to avoid delay
- Resets on battle init and when conditions change
2026-07-27 20:14:21 -04:00
GaboGG
f2f296274c v0.14.17 - Faster weapon skills: lower skillOC to 60, threat to 70%, single-monster emergency
- skillOC default lowered from 75 to 60 — with 300ms Q debounce, it took
  ~6 presses to go from 50 to 70 OC (too slow against IWBTH enemies)
- Threat threshold lowered from 85% (102px) to 70% (84px) — triggers
  earlier when monsters have high SP bars
- Added single-monster emergency: if ANY enemy >90% SP, fire skills
  even without 2+ monsters (catches the lone special attacker)
- Step 0d high-threat check now fires for solitary imminent threats too
2026-07-27 20:05:47 -04:00
GaboGG
4aff813f01 v0.14.16 - Armory scraper now scavenges full store for all items
- Previously only scraped items visible in the current filter tab
  (had to visit each tab: New, Two-Handed, Light, Heavy, etc.)
- Now also scans the full dynjs_equip store for ALL items in your
  account (305 total) — every filter tab's worth of data at once
- Category guessed from tooltip type (Cloth, Light, Heavy, Weapon, etc.)
- One visit to the Armory page + HV.scrapeGear() = complete inventory
2026-07-27 15:58:02 -04:00
GaboGG
d95409026f v0.14.15 - Retry gear scrape until dynjs_equip store loads
- equip-UID.js loads asynchonously after document-end, so dynjs_equip
  might not exist when init() first runs
- Now retries up to 10 times (500ms apart, 5 seconds total) waiting for
  the store to populate before scraping
- Added HV.gearStore() to check whether the store is loaded
- If store never loads, falls back to name/ID scrape without stats
2026-07-27 15:51:22 -04:00
GaboGG
329e9403b4 v0.14.14 - V2 gear scraper: reads from HV in-memory JS store (no hovers)
- Previously: tried equips.set() + 300ms delays + popup_box polling
  which was fragile, async, and often saved stats to wrong slots
- Now: reads window.dynjs_equip / dynjs_eqstore which contains ALL
  item data pre-loaded on page load (name, quality, full tooltip HTML)
- Uses DOMParser to parse the embedded .eq HTML into structured stats
  (type, level, condition, burden, ADB, mit, attributes, etc.)
- Zero hover, zero delays, zero popup_box interaction — instant stats
- Works on Character Equipment page AND Armory pages simultaneously
- Removed triggerAllTooltips() and captureAllTooltips() — obsolete
2026-07-27 15:46:36 -04:00
GaboGG
28457202ba v0.14.13 - Clean scrape flow: basic data on page load, stats via captureAllTooltips
- scrapeCharacterEquip() now only reads names/IDs from DOM slots (no tooltip
  popup reading — that was attaching wrong stats to wrong slots)
- captureAllTooltips() now calls logGearSummary() instead of autoScrapeGear()
  so the tooltip stats aren't wiped by a re-scrape
- Workflow: visit Character Equipment page, then run HV.captureTooltips()
  to populate full stats with 300ms hover delay per item
2026-07-27 15:35:30 -04:00
GaboGG
ce09755fa8 v0.14.12 - Add captureAllTooltips() with async hover-to-popup delay
- captureAllTooltips() iterates each equipment slot, calls equips.set()
  to trigger the tooltip popup, waits 300ms for the DOM to update,
  then reads and saves the full stat block from #popup_box
- Catches 'Popup Box' default text vs real tooltip
- Saves stats directly to localStorage gear DB
- Exposed as HV.captureTooltips() for console use
- For best results: visit Character Equipment page, run HV.captureTooltips()
2026-07-27 15:31:06 -04:00
GaboGG
c632c13818 v0.14.11 - Fix DOM selector: onmouseover is on inner div, not .eqb parent
- .eqb parent has onclick and structure, but the onmouseover with
  equips.set() and the item name text are on a CHILD div within .eqb
- Fixed scrapeCharacterEquip() and triggerAllTooltips() to query
  :scope > div[onmouseover] inside each .eqb slot
- Fixed debugScrapeGear() diagnostic to show inner div content
2026-07-27 15:28:58 -04:00
GaboGG
992c6acc38 v0.14.10 - Add debugScrapeGear() diagnostic + HV.gearDebug()
- New debugScrapeGear() function checks DOM structure:
  - Whether #eqsb exists and its slot count
  - Whether #equiplist exists
  - Whether #popup_box exists and its content
  - Whether equips global is available
- Exposed as HV.gearDebug() for console use
2026-07-27 15:16:03 -04:00
GaboGG
a7a304f5d4 v0.14.9 - Rewrite gear scraper with correct DOM selectors
- Character Equipment page (?s=Character&ss=eq): reads #eqsb > .eqb
  divs with onmouseover='equips.set(ID,...)' for item names and IDs
- triggerAllTooltips() calls equips.set() for each item to populate
  the #popup_box tooltip, then parses full stat blocks (ADB, damage,
  mitigation, attributes, burden, interference, condition)
- Armory Organize page: reads #equiplist table rows with
  onmouseover='hover_equip(ID)' and checkbox values
- Reads right-side #equipinfo preview for condition and stats
- Modify detail page: reads full stat tables
2026-07-27 15:12:28 -04:00
GaboGG
6167df57b4 v0.14.8 - Expose gear API via HV.gear() / HV.gearSummary()
- Added to window.HV public API: gear(), gearSummary(), scrapeGear()
- Now accessible from console as HV.gear(), HV.gearSummary()
- Also keep getGearDB() and logGearSummary() directly available
2026-07-27 15:05:52 -04:00
GaboGG
d60233d205 v0.14.7 - Gear scraper: captures full equipment stats to localStorage
- New module: gear-scraper.js (10K, 200+ lines)
- Auto-scrapes Character page (?ss=ch) for equipped gear with full stat
  blocks: ADB, damage, crit, parry, evade, burden, mitigation, stats
- Auto-scrapes Armory inventory page for all items with IDs, names,
  categories, potency, durability
- Scrapes Modify detail page for one item's complete stat table
- Stores everything in localStorage['hvunified_geardb']
- ParseHV.advice() now includes gear info
- Public API: getGearDB() returns full gear database
2026-07-27 14:55:48 -04:00
GaboGG
91d53e0f1c v0.14.6 - High-threat weapon skills step 0d (before buffs/items)
- Added step 0d in Veteran: if 2+ monsters have SP >85%, fire weapon
  skills BEFORE buffs, items, debuffs, or anything else
- Only needs OC >= 20 (one skill's worth, builds fast from basic attacks)
- Rending Blow > Shatter Strike > Great Cleave, targeting most dangerous monster
- Formerly: weapon skills were at step 11, after all buffs and items.
  Enemies got multiple turns to special attack during the buff-up phase.
  Now dangerous monsters get shut down immediately.
2026-07-27 14:49:50 -04:00
GaboGG
9af0237754 v0.14.5 - Conservative debuffs: Imperil only on bosses/rares or 5+ mobs
- Imperil no longer casts on every 2-mob wave (Estoc's native Penetrated
  Armor handles armor-breaking for <5 targets)
- Imperil threshold raised from MP>20% to MP>35%
- Imperil now only fires on bosses/rares OR 5+ monster waves (Grindfest)
- Weaken now only on high-threat (SP>85%) or bosses, not every 3-mob wave
- Formerly: Imperil on 2+ mobs, Weaken on 3+ mobs — drained MP fast
2026-07-27 14:46:39 -04:00
GaboGG
0a41f9d7c5 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)
2026-07-27 14:45:00 -04:00
GaboGG
48e5103655 v0.14.3 - Add reason tags to castInitialBuffs (init/initCh)
- castInitialBuffs now tags actions with _reason='init' (cheapest-first
  sort, no channeling) or _reason='initCh' (most-expensive-first,
  channeling already charged)
- Makes the log clearly show which buff path fired
2026-07-27 14:43:40 -04:00
GaboGG
205f1cd631 v0.14.2 - Double-check cooldown via img opacity:0.5 in hasReadySpell
- Some quickbar/deprecated elements retain onclick even when on cooldown
  if the cooldown indicator is only visual (img opacity:0.5) not structural
- Now also checks img.btqi / img style.opacity !== '0.5'
- This catches cases where the parent div has onclick but the inner image
  is visually dimmed (game cooldown)
2026-07-27 14:08:48 -04:00
GaboGG
7ae6e4855f v0.14.1 - Fix cooldown checks: spells on cooldown no longer selected
- Added hasReadySpell() that checks DOM for onclick attribute (off cooldown)
- Buff loop (all tiers) now uses hasReadySpell instead of hasSpell
- Cure/Full-Cure now checks cooldown before casting
- Channeling target selection checks cooldown
- castInitialBuffs checks cooldown
- Imperil/Weaken debuffs check cooldown
- hasSpell() kept for knowledge checks (do we know this spell at all)
- Prevents silent failures where on-cooldown spells are selected but
  can't actually be cast (btsd[onclick] fails to find them)
2026-07-27 14:05:25 -04:00
GaboGG
c9ad92e28d v0.14.0 - Major strategy overhaul from agy research report
BUG FIXES (P0):
- Spark of Life SP safety: consume spirit items when SP < 55% BEFORE
  buffs, Cure, or any other action (both Adept and Veteran)
- Spirit Stance safety auto-disable: auto-toggle OFF if SP drops below 60%
- useItem() fallback: auto_ slot IDs now lookup by onmouseover attribute
  (on-cooldown items without DOM id were silently failing)
- setTimeout targeting race: removed 50ms delay in castTargetSpell/useSkill
  (was causing targeting failures with fast Q-repeat)
- maxBuffDur pre-seeded with L150+ baseline values (haste=80, heartseeker=120,
  sparklife=50, etc.) so fill-level scoring works from first turn

STRATEGY (P1):
- Channeling waste eliminated for 2H physical builds: no more Fiery Blast
  fallback — let channeling expire on a basic attack (Domino Strike +
  Penetrated Armor do more damage)
- Weapon skill thresholds lowered from 5+ to 3+ enemies (IWBTH survivability)
- Expanded debuffs: Imperil on any 2+ mobs, Weaken on high-threat targets
  (not just bosses anymore)
- Domino Strike optimal targeting: findOptimalDominoTarget() picks center
  monsters to max splash coverage (up to 2 targets each side)

NEW FEATURES:
- Domino Strike splash positioning algorithm added to all tiers
- Full _reason tags on every action return for decision tracing
- agy research report saved at hermes_report.md (554 lines)
2026-07-27 14:01:05 -04:00
GaboGG
467e844aae v0.13.34 - Explicit action names in log + _reason tags per decision
- Log now shows spell names/skill names/item names explicitly:
  '[HV] ▶ spell → Haste (self)' instead of '▶ spell → monster 0'
  '[HV] ▶ spell → Fiery Blast → monster 1 (ch fallback)'
  '[HV] ▶ item → Spirit Draught (self) (sp55)'
- Added _reason tag to every action return: 'hp60', 'sp55', 'buff',
  'ch score 81', 'threat', 'oc', 'boss', 'stun', 'mana', 'gem',
  'mystic', 'fallback', 'dmg'
- Now you can see exactly WHY each action was chosen on every turn
2026-07-27 13:35:45 -04:00
GaboGG
949aab915f v0.13.33 - Persist maxBuffDur to localStorage (no more warm-up)
- maxBuffDur now saved to localStorage['hvunified_maxBuffDur'] on every
  new high observation and loaded on STATE init
- Survives page reloads: Heartseeker's 180-turn max stays learned
- Removed the unreliable-max fallback hack — no longer needed
- First Q press of a fresh session has accurate fill-level scores
  for all buffs that were observed in previous sessions
2026-07-27 13:26:51 -04:00
GaboGG
b8e2e945ec v0.13.32 - Fix channeling waste when maxBuffDur hasn't learned true cap
- When maxBuffDur gap (max - current) is < 10, the cap is unreliable
  (first observation mid-battle, not at full duration)
- In that case, skip the fill-level formula entirely
- Only suggest a buff for channeling if it actually needs refresh
  (dur <= minTurns from BUFF_PRIORITY)
- Once maxBuffDur learns the true cap (after a fresh cast), the
  normal fill-level scoring takes over correctly
2026-07-27 13:22:15 -04:00
GaboGG
533fad252a v0.13.31 - Enhanced battle logging for deep diagnostics
- Q-key log now shows: HP, current MP, MP%, SP%, OC, monster count,
  buff durations, and per-monster SP bar levels (spBars: 0:120 1:95 ...)
- High-threat detection logs a red '⚠ HIGH THREAT' warning
- Emergency skill usage at low OC logs an orange '⚠ emergency' warning
- Now you can paste me the console log and I'll see exact threat levels,
  why skills did/didn't fire, and what the state was before each action
2026-07-27 13:13:59 -04:00
GaboGG
b5a5c3df54 v0.13.30 - Fix spirit item detection, add threat-based targeting
- Fix: items on cooldown (no id attr) were invisible to parser
  Spirit Draught/Potion on cooldown couldn't be auto-consumed
- Fix: spiritPotionSP raised from 30% to 60%
- New: parse monster SP bar widths into STATE.monsterSp[]
- New: findDangerousMonster() — targets highest SP bar monster
- New: hasHighThreat() — true if 2+ monsters >85% SP (about to special)
- Weapon skills now fire on high-threat even without full OC
- Basic attacks prefer dangerous monsters in all tiers
2026-07-27 13:07:39 -04:00
GaboGG
b6d78067ce v0.13.29 - Aggressive SP management for Spark of Life survival
- Raised spiritPotionSP threshold from 30% to 60%
- Added Spirit item check at step 2b in Adept and Veteran tiers:
  if SP < 55%, consume Spirit Draught/Potion immediately
- Spark of Life costs 50% max SP when triggered. If SP is too low,
  Spark fails and you die. Keeping SP above 55% ensures Spark always
  has enough fuel to save you from a killing blow on IWBTH
2026-07-27 11:08:16 -04:00
GaboGG
e1269cd3fe v0.13.28 - Fix difficulty advice: recommend IWBTH for Veteran, not PFUDOR
- Changed Veteran suggestion from PFUDOR (20x) to IWBTH (15x)
- PFUDOR is now only suggested at Master tier (L300+)
- Since you're already on IWBTH, the banner won't show anymore
  (current == suggested, so no nag)
2026-07-27 10:04:02 -04:00
GaboGG
ad2ff4b482 v0.13.27 - Remove auto Spirit Stance toggle from all tiers
- Removed toggle_spirit calls from Novice, Adept, and Veteran
  strategy functions (was auto-toggling stance at OC 60+)
- Spirit Stance is now fully manual (press spirit button yourself)
- Spirit Gem auto-consumption remains (fills SP when dropped)
- Kept the config guards (CFG.autoSpirit) for future opt-in
2026-07-26 15:26:51 -04:00
GaboGG
1a4f9a80a3 v0.13.26 - Stricter Q debounce: reset timer after each successful action
- executeAction now sets STATE._lastActionTime after dispatching
- Q handler checks this instead of a local var
- When an action executes, the Q debounce resets so the next Q press
  waits the full 300ms before attempting again
- Prevents stale-state queueing when game hasn't processed the
  previous action yet (was sending 12+ 'skill' commands to the
  game, though only 1 actually ran)
2026-07-26 15:23:04 -04:00
GaboGG
8c21920d4b v0.13.25 - Debounce Q key to prevent spam on held-key repeat
- Added _lastQTime debounce (300ms) to the Q key handler
- Holding Q now fires at most ~3 actions per second instead
  of ~20, preventing duplicate actions from stale state reads
- The previous issue: 6 identical Haste casts, then 8 identical
  Spark casts, then 12 identical Heartseeker casts — all from
  state not yet updated by the game
2026-07-26 15:17:27 -04:00
GaboGG
86968f531c v0.13.24 - Fix castInitialBuffs sorting (was most-expensive-first, not cheapest-first)
- castInitialBuffs was sorting by mpCost descending (b.mpCost - a.mpCost)
- So it picked Spark of Life (70) before Haste (41), defeating the
  whole purpose of casting cheapest-first to proc channeling
- Changed to ascending sort (a.mpCost - b.mpCost): Haste first, then
  Spark, etc.
2026-07-26 15:16:07 -04:00
GaboGG
0aa268b3f9 v0.13.23 - Fix affordable MP check using actual current MP from DOM
- Was using vrhd (HP element) instead of vrm (current MP)
- Now reads #vrm textContent for current MP value
- Simply compares mpCost > curMp to skip unaffordable spells
- This prevents the infinite Heartseeker loop when you
  don't have enough MP even though the buff is a good target
2026-07-26 15:09:38 -04:00