# HentaiVerse Scripts — Source Code Analysis & Architecture Patterns ## Based on Monsterbation 1.4.1.2 (163KB, 2402 lines) + Wiki formulas ============================================================================= ## 1. SOURCE CODE STATUS | Script | Version | Status | Source | |--------|---------|--------|--------| | **Monsterbation** | 1.4.1.2 | Downloaded (163KB) | Forum attachment 157304 | | **CrunkJuice** | 1.3.0 | Available (same thread) | Forum attachment (companion) | | **jpx** | v2026.07.06 | Forum thread 290507 | GitHub-hosted? (Cloudflare blocked) | | **HV Utils** | 4.2.3 | Forum thread 211883 | Forum attachment 188793 (Cloudflare blocked) | | **HV Toolbox** | 1.0.14 | Forum thread 209070 | Forum attachment 165038 (Cloudflare blocked) | | **HVSTAT** | 5.7.1 | Forum thread 79552 | Forum attachment 15604 (Cloudflare blocked) | **Blockers**: E-hentai forums are behind Cloudflare protection. Direct downloads from the VPS are blocked by JS challenge. None are on GreasyFork/GitHub (community convention is forum-only distribution). User needs to download these from their browser and upload to VPS. ============================================================================= ## 2. MONSTERBATION — ARCHITECTURE DEEP DIVE ### 2.1 High-Level Architecture ``` Monsterbation = Tampermonkey userscript injected into hentaiverse.org DETECTION: Check for DOM elements #textlog or #riddlemaster → battle page NO HTTP requests for game state. ALL state parsed from DOM. PATTERN: Page interactions = clicking existing DOM elements. NEVER constructs raw HTTP POSTs. ``` ### 2.2 Core Loop ``` Page loads (battle round start) → Enhance() called → Parse DOM: monsters[], vitals (HP/MP/SP bars), buffs, cooldowns → Set up event listeners on monsters (mouseover, mousedown, wheel, contextmenu) → If hover enabled: auto-fire hover attack on target monster → Wait for human interaction (keyboard/mouse) Human moves mouse over monster → SetTarget(i) called → If hover enabled: Hover() fires → Hover(): run cfg.hoverAction() → then monsters[target].click() → The click triggers the page's built-in onclick handler → Server processes turn → new HTML page loads → loop repeats ``` ### 2.3 DOM-Based State Parsing **Monster detection:** ```javascript monsters = document.querySelectorAll('.btm') // Battle table monsters // Each monster has onclick attribute when alive monsters[i].hasAttribute('onclick') // true = alive, false = dead ``` **Vitals (HP/MP/SP):** ```javascript // Parse from bar image widths (2 possible formats - isekai vs persistent) mp = parseInt(image.width) / 414 // MP bar fill ratio sp = parseInt(image.width) / 414 // SP bar fill ratio hp_left = parseInt(image.width) / 414 // HP bar fill ratio // Overcharge: bar_orange.png width // Isekai uses /207 instead of /414 (different base widths) ``` **Buffs/Debuffs:** ```javascript // Parse from onmouseover text on effect icons var effects = document.getElementById('pane_effects').getElementsByTagName('img') effects[n].getAttribute('onmouseover') // Contains duration + stack count // Regex: /regexp.duration/ extracts turns remaining and stacks ``` **Cooldowns:** ```javascript // Quickbar icons have cooldown info in their style/attributes // Timer shows turns until available ``` **Battle log (post-combat):** ```javascript // Parses textLog for damage numbers, proficiency gains, drops var log = document.getElementById('textlog') // Regex extracts: monsters present, damage dealt, items dropped ``` ### 2.4 Action System (how it submits turns) **Design principle: NEVER construct URLs or form POSTs. ALWAYS click page elements.** ```javascript // SPELLS: Find the spell icon by its onmouseover text containing spell name function Cast(name) { return function() { var spell; if ((spell = document.querySelector( '.bts > div[onclick][onmouseover*="\'' + name + '\'"]'))) { // Use a dummy element to trigger the spell's mouseover+click dummy.setAttribute('onclick', spell.getAttribute('onmouseover')); dummy.click(); spell.click(); } }; } // ITEMS: Find by element ID function Use(id) { return function() { var item; if ((item = document.getElementById('ikey_' + id))) { dummy.setAttribute('onclick', item.getAttribute('onmouseover')); dummy.click(); item.click(); } }; } // ATTACK: Click the monster div directly function TargetMonster(num) { return function() { if (monsters[num] && monsters[num].hasAttribute('onclick')) monsters[num].click(); }; } // TOGGLE: Click checkbox elements by ID function Toggle(name) { return function() { if ((state = document.getElementById('ckey_' + name.toLowerCase()))) state.click(); }; } ``` **Key insight:** The game's page has HTML elements with onclick/onmouseover handlers. Monsterbation finds these elements and triggers their events. The server processes the resulting HTTP request normally. This is why it's considered "single action" — each click = one server round-trip = one turn. ### 2.5 Hover System (the killer feature) ``` hoverArea: 6 = which .btmX div within monster triggers hover Hover flow: 1. Mouse enters monster area → SetTarget(i) called 2. If hover enabled → Hover() fires 3. Hover() → runs the configured action chain 4. Action chain clicks spell/item/attack elements on the page 5. The last action clicks the monster → server resolves turn 6. Next page loads → Enhance() → parse new state → loop Modifier keys: - No modifier: cfg.hoverAction - Shift: cfg.hoverShiftAction (e.g. dark spells) - Ctrl: cfg.hoverCtrlAction (e.g. holy spells) - Alt: cfg.hoverAltAction (e.g. fire spells) Hover interrupts: - stopOnSpark (spark of life triggered) - stopOnUsable (consumable becomes available) - stopOnLowHP/MP/SP - stopOnBuffsExpiring (custom regex) - stopOnMiss - Impulse system: inject one-time spell into rotation ``` ### 2.6 Spell Rotation System ```javascript // Strongest: tries actions in order, first one that is available fires Strongest([Cast('Ragnarok'), Cast('Disintegrate'), Cast('Corruption')]) // This tries Ragnarok first. If the element doesn't exist (cooldown/spell unavailable), // it falls through to Disintegrate, then Corruption. // The action fires by finding the spell icon in the DOM and clicking it. // Impulse: injects a one-time action into the rotation // e.g. press I while hovering to cast Imperil once, then resume normal rotation Bind(KEY_I, Impulse(Cast('Imperil'))) ``` ### 2.7 Keybinding System ```javascript // Format: Bind(KEY, ON_KEYDOWN, ON_KEYUP) // KEY: string like 'F', 'Digit1', 'Numpad1', 'ShiftLeft', etc. // Examples: Bind('KeyR', Strongest([Cast('Ragnarok'), Cast('Disintegrate')])); // Press R → cast strongest dark spell at mouse target Bind('KeyH', Any, ToggleHover); // Release H → toggle hover play Bind('KeyV', HoverAction(Nothing)); // Hold V → attack monster at mouse cursor Bind('Digit2', Strongest([ToggleHover, HoverAction(Cast('Imperil'))])); // Press 2 → cast Imperil (even if hovering is stopped) ``` ### 2.8 Profile System ``` cfg.name → cfg.persona[0].name → cfg.persona[0].set[0].name ├── settings ├── settings ├── hoverAction ├── hoverAction ├── bind ├── bind └── ... └── ... Profiles auto-switch when: - Persona changes (cfg.profileAutoswitch) - Equipment set changes - Isekai mode detected (cfg.isekaiInherit) Storage: localStorage['HVmbcfg'] for config, localStorage['HVtrackdrops'] for tracking ``` ### 2.9 Out-of-Battle Features (CrunkJuice, the companion script) CrunkJuice handles non-combat automation: - ED confirm (auto-confirm that annoying dialog) - Faster "sell all" button - Monster morale/hunger display - Feed pills/crystals to all monsters - Monster database search - RE timer/counter - Quality filter in bazaar - Arena page auto-open ============================================================================= ## 3. CORE ARCHITECTURAL PATTERNS (applicable to any new tool) ### Pattern 1: DOM Detection, Not HTTP ```javascript // Detect battle page: if (document.getElementById('textlog') || document.getElementById('riddlemaster')) { // We're in battle } // Detect bazaar/character page: if (document.getElementById('mainpane')) { // We're in the main game area } ``` ### Pattern 2: Click Elements, Don't POST ```javascript // WRONG (bot-like, detectable): fetch('?s=BATTLE', {method:'POST', body:'action=attack&target=2'}); // RIGHT (same as human clicking): document.querySelector('.btm[onclick]').click(); document.querySelector('.bts > div[onclick]').click(); ``` ### Pattern 3: Element Selection by Content ```javascript // Find the Imperil spell icon: document.querySelector('.bts > div[onclick][onmouseover*="Imperil"]') // Find a specific item by its game-internal ID: document.getElementById('ikey_3') // Item slot 3 // Find Spirit Stance toggle: document.getElementById('ckey_spirit') ``` ### Pattern 4: State from Style Widths ```javascript // HP percentage from green bar: var hp_pct = parseInt( document.querySelector('img[src$="green.png"]').style.width ) / 414; // MP from blue bar: var mp_pct = parseInt( document.querySelector('img[src$="blue.png"]').style.width ) / 414; // Overcharge from orange bar: var oc_full = parseInt( document.querySelector('img[src$="bar_orange.png"]').style.width ) >= 414; ``` ### Pattern 5: localStorage for Persistence ```javascript // Config storage: localStorage['HVmbcfg'] = JSON.stringify(config); // Monster HP database (to show HP numbers): localStorage['HVmonsterData'] = JSON.stringify(monsterData); // Drop tracking: localStorage['HVtrackdrops'] = JSON.stringify(droplog); // Combat stats: localStorage['HVcombatlog'] = JSON.stringify(combatlog); ``` ### Pattern 6: Dummy Element Trick ```javascript // The game often requires a specific click sequence: // 1. Click spell icon → triggers mouseover → shows targeting mode // 2. Click monster → actually casts spell // Monsterbation handles this with a dummy element: var dummy = document.createElement('div'); dummy.setAttribute('onclick', spell.getAttribute('onmouseover')); dummy.click(); // Sets up targeting spell.click(); // Actually selects spell monster.click(); // Fires the spell at target ``` ============================================================================= ## 4. EXISTING TOOL GAPS — WHERE TO IMPROVE ### Gap 1: No automated Battle Mode Selection Current tools require manually picking Arena/Grindfest/Item World. A tool could: - Parse available arenas, check which ones are uncleared that day - Sort by credit/minute efficiency based on player's clear speed - One-click "do today's best arena" ### Gap 2: No Smart Mana/SP Management Current hover systems use threshold-based interrupts (stop at X% mana). A smarter approach: - Calculate exact mana cost of next spell (including interference, spirit stance, etc.) - Predict regeneration rate over time - Decide: cast now vs wait 1 tick vs use mana potion - Pre-cast buffs when MP is high, conserve when MP is low ### Gap 3: No Per-Monster Adaptive Targeting Current tools target whoever the mouse is over, or use "Strongest spell rotation" blindly. A fully informed targeting system would: - Scan all monsters for resistances (from Monster Lab database) - Match elemental weakness to available spells - Prioritize: debuff needs → lowest HP (sweep) → highest threat - Account for monster status effects (don't waste Imperil on already-imperiled target) ### Gap 4: No Auto-Equipment Optimizer for Battle Current tools don't read equipment loadouts and suggest optimal gear. Could: - Parse equipment stats for current fighting style - Auto-equip best set for the battle mode (Arena vs GF vs IW) - Warn about broken equipment before battle ### Gap 5: Fragmented Tool Ecosystem Monsterbation (battle) + CrunkJuice (out-of-battle) + HV Utils (shop/shrine) + HV Toolbox (MoogleMail) + jpx (auto-battler rules) = 5+ separate scripts. A unified tool with modular architecture would: - Share state between modules (drops in battle → auto-sell in shop) - Single config/profile system - Consistent keybindings and UI ### Gap 6: No VPS-Ready Remote Monitoring None of the tools offer headless monitoring. Could: - WebSocket bridge: browser extension sends state to VPS - VPS logs: daily earnings, Hath balance, stamina status - Push notifications: "Your stamina is full" or "Arena reset is ready" ### Gap 7: Training Queue Current tools handle training manually. Could: - Queue training purchases with credit thresholds - Auto-buy Scavenger/Quartermaster/Archaeologist when credits exceed threshold - Prioritize Ability Boost when leveling ### Gap 8: Monster Lab Auto-Management CrunkJuice has basic feeding. Could extend to: - Optimal crystal allocation (which monster gets which crystal type) - Morale management (pill when below threshold) - Auto-name/auto-level tracking ============================================================================= ## 5. BUILD PLAN — UNIFIED BATTLE ASSISTANT (Tampermonkey) ### Architecture ``` hv-unified.user.js ├── engine/ │ ├── detector.js ← Detect which page we're on (battle/bazaar/monsterlab/etc.) │ ├── parser.js ← DOM→gameState (shared parser for all modules) │ ├── submitter.js ← Action submitter (click elements, dummy trick) │ ├── storage.js ← localStorage wrapper (config, tracking, monster DB) │ └── config.js ← Profile system, keybinding parser ├── battle/ │ ├── vitals.js ← HP/MP/SP/OC monitoring │ ├── buffs.js ← Buff duration tracking, alert conditions │ ├── cooldowns.js ← Spell/skill/item cooldown display │ ├── monsters.js ← Monster state (HP, status, resistances) │ ├── hover.js ← Hover system (target selection, action execution) │ ├── strategy.js ← Action decision logic (spell rotation, target priority) │ ├── spells.js ← Spell selection (find icons by name, check mana cost) │ ├── skills.js ← Skill selection (overcharge management) │ └── items.js ← Item usage (potions, scrolls, infusions) ├── bazaar/ │ ├── arena.js ← Arena detection, completion tracking │ ├── shrine.js ← Bulk shrine artifacts │ ├── shop.js ← Auto-sell/salvage low-quality gear │ ├── training.js ← Training queue management │ └── monsterlab.js ← Auto-feeding, crystal allocation ├── tracking/ │ ├── drops.js ← Drop logging and statistics │ ├── damage.js ← Damage dealt/taken tracking │ ├── proficiency.js ← Proficiency gain tracking │ └── credits.js ← Credit earning rate calculation └── ui/ ├── quickbar.js ← Extended quickbar with cooldowns ├── overlay.js ← Settings panel, profile switcher ├── alerts.js ← Visual/audio alerts (low HP, spark, buffs expiring) └── keybind.js ← Keybinding system ``` ### Strategy Engine — The Core Innovation Rather than Monsterbation's simple "cast all spells in rotation at whatever target", build a **conditional rule engine**: ```javascript const strategy = { // Priority-ordered rules. First matching rule fires. rules: [ { name: 'Emergency heal', condition: () => state.hp < 0.25, action: () => Use('health_potion') || Cast('Full-Cure') || Cast('Cure'), }, { name: 'Maintain Imperil', condition: () => !monsterHasEffect(currentTarget, 'imperil'), action: () => Cast('Imperil'), }, { name: 'Maintain Weaken', condition: () => !monsterHasEffect(currentTarget, 'weaken') && state.mp > 0.3, action: () => Cast('Weaken'), }, { name: 'Maintain buffs', condition: () => !hasBuff('haste') || !hasBuff('shadow_veil'), action: () => castMissingBuffs(), }, { name: 'Use Spirit Stance', condition: () => state.oc >= 100 && !spiritStanceActive && state.sp > 0.25, action: () => Toggle('spirit'), }, { name: 'Use skill at full OC', condition: () => state.oc >= 200 && !skillOnCooldown('frenzied_blows'), action: () => Skill('Frenzied Blows'), }, { name: 'AOE spell', condition: () => aliveMonsters > 1 && canCast('Inferno'), action: () => Cast('Inferno'), }, { name: 'Single target: match weakness', condition: () => true, // fallback action: () => castBestSpellAgainst(currentTarget), }, ], }; ``` ### Elemental Weakness Matching Build a monster database: ```javascript const monsterDB = { // key: monster name pattern 'Giant': { weak: 'Cold', resist: 'Fire', hp_scaling: 1.2 }, 'Dragon': { weak: 'Elec', resist: 'Fire', hp_scaling: 1.5 }, // ... populated from Monster Lab scans + community data }; function castBestSpellAgainst(monster) { const info = findMonsterInDB(monster.name); if (info && info.weak) { return Cast(getHighestTierSpell(info.weak)); } // Fallback: use neutral/highest damage spell return Cast('Ragnarok'); } ``` ============================================================================= ## 6. RULES COMPLIANCE CHECKLIST The script MUST: - [x] Require human input per combat round (hotkey press or mouse hover) - [x] NOT auto-advance between rounds without input - [x] NOT auto-start new battles - [x] NOT auto-feed monsters - [x] NOT auto-solve RiddleMaster - [x] NOT combine multiple actions into one user input - [x] Stop on RiddleMaster detection and alert user - [x] Parse game state only for recommendations, not for triggering actions For out-of-battle features: - [ ] Auto-sell/salvage: ALLOWED if user initiates (HV Utils pattern) - [ ] Auto-training queue: GREY AREA — training is manual, queuing probably OK - [ ] Auto-shrine: ALLOWED if user clicks the button (bulk shrine OK) - [ ] Monster feeding: NOT ALLOWED if automatic (must require button press) - [ ] Auto-arena selection: GREY AREA — suggesting which arena is OK, auto-entering is NOT ============================================================================= ## 7. NEXT STEPS 1. **User downloads remaining scripts** from forums (browser → upload to VPS): - jpx from https://forums.e-hentai.org/index.php?showtopic=290507 - HV Utils from https://forums.e-hentai.org/index.php?showtopic=211883 - HV Toolbox from https://forums.e-hentai.org/index.php?showtopic=209070 2. **Analyze jpx's ruleset system** — it has the most advanced conditional logic for auto-battle, and understanding its rule format would inform our strategy engine design 3. **Extract Monster Lab data** — build a JSON database of monster weaknesses from the existing script databases (decondelite's server at nibl.co.uk) 4. **Build MVP**: start with battle parser + strategy engine + hover system, integrating the best patterns from all existing tools 5. **Test in a low-level account** before running on your main to verify rules compliance