From 589ed7e34cd1e3d71f9aebc313a0919a0058ce46 Mon Sep 17 00:00:00 2001 From: GaboGG Date: Mon, 3 Aug 2026 16:04:37 -0400 Subject: [PATCH] v0.15.4 - Elemental Strikes parsed + scored per wiki (Void Strike, etc.) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From EHWiki Detailed_Equip_Characteristics + Equipment_Basics: - Elemental strikes are 'X Strike (Y%)' lines (Void/Fire/Cold/Elec/ Wind/Holy/Dark), separate hit for ~50% of physical damage, max 2 strikes + Void Strike - Ethereal weapons deal Void damage (+523 Void Damage), prefixes: Ethereal→Void, Fiery→Fire, Arctic→Cold, Shocking→Elec, Tempestuous→Wind, Hallowed→Holy, Demonic→Dark - Weapon procs by type: Piercing→Penetrated Armor (Estoc/Rapier), Crushing→Stun (Mace/Club), Slashing→Bleeding Wound (Longsword/ Katana/Shortsword/Axe/Wakizashi) Parser now captures: - stats['Strike '] = chance% (e.g. 'Strike Void': 50) - stats['Weapon Damage'] for Void too (+523 Void Damage) Scorer adds expected strike damage (chance/100 × 0.5 × weapon dmg) weighted same as base damage. Type bonuses updated to match real procs (Stun 1.15x > Bleeding 1.10x, Rapier 1.20x like Estoc 1.25x). So your lottery Peerless Ethereal Rapier (+523 Void, Void Strike 50%) now scores properly. Note: re-scrape after update for Strike fields. --- analyze_gear.py | 32 +++++++++++++++-------------- scripts/hv-unified.user.js | 41 ++++++++++++++++++++++++++------------ scripts/latest.user.js | 41 ++++++++++++++++++++++++++------------ src/config.js | 2 +- src/gear-analysis.js | 26 ++++++++++++++---------- src/gear-scraper.js | 11 +++++++++- src/header.user.js | 2 +- 7 files changed, 101 insertions(+), 54 deletions(-) diff --git a/analyze_gear.py b/analyze_gear.py index c358406..c674fbe 100644 --- a/analyze_gear.py +++ b/analyze_gear.py @@ -67,10 +67,14 @@ def score_weapon(item): s += get_num(stats.get('Block',0)) * 0.5 s += get_num(stats.get('Agility',0)) * 0.5 s -= get_num(stats.get('burden',0)) * 0.5 - # Base weapon damage + elemental damage - s += get_num(stats.get('Weapon Damage',0)) * 0.30 - for el in ['Fire','Cold','Elec','Wind','Holy','Dark','Ethereal','Elemental']: - s += get_num(stats.get('Elemental ' + el,0)) * 0.25 + # Base weapon damage + elemental strikes + wd = get_num(stats.get('Weapon Damage',0)) + s += wd * 0.30 + for el in ['Fire','Cold','Elec','Wind','Holy','Dark','Void','Ethereal']: + chance = get_num(stats.get('Strike ' + el,0)) + if chance > 0: + expected = (chance / 100) * 0.5 * wd + s += expected * 0.30 if expected > 0 else chance * 0.15 # Proc lines for k, v in stats.items(): if k.startswith('Proc '): @@ -87,18 +91,16 @@ def score_weapon(item): quality_mult = 0.8 + (quality * 0.12) # q4=1.28x, q5=1.40x, q6=1.52x s *= quality_mult - # Weapon type bonus: Estoc has Penetrated Armor proc (armor break) - # Longsword has Weaken proc (damage debuff on enemies) + # Weapon type bonus (wiki procs: Piercing→Penetrated Armor, Crushing→Stun, + # Slashing→Bleeding Wound; Estoc=2H Penetrated Armor is the 2H physical build's core) if 'estoc' in name_lower: - s *= 1.25 # Estoc's Penetrated Armor is the defining proc for 2H physical builds - elif 'longsword' in name_lower: - s *= 1.10 # Weaken proc is decent but not as impactful - elif 'great mace' in name_lower: - s *= 0.90 # No armor pen, lower utility - elif 'club' in name_lower: - s *= 0.85 - elif 'axe' in name_lower: - s *= 0.90 + s *= 1.25 + elif 'rapier' in name_lower: + s *= 1.20 # 1H Penetrated Armor + elif any(k in name_lower for k in ['longsword','katana','shortsword','axe','wakizashi']): + s *= 1.10 # Bleeding Wound + elif any(k in name_lower for k in ['great mace','club','mace']): + s *= 1.15 # Stun return s diff --git a/scripts/hv-unified.user.js b/scripts/hv-unified.user.js index a9a43b8..b3db691 100644 --- a/scripts/hv-unified.user.js +++ b/scripts/hv-unified.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.15.3 +// @version 0.15.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.15.3'; +const VERSION = '0.15.4'; const CFG = { // — Battle automation @@ -3528,7 +3528,16 @@ function parseEquipHTML(htmlStr) { return; } - // Weapon damage line: "+708 Piercing Damage" + // Elemental Strike line (wiki: "X Strike (Y%)" — e.g. "Void Strike (50%)") + // Additional ~50%-of-physical-damage hit; max 2 strikes + Void Strike. + const strikeM = text.match(/^([A-Za-z]+)\s+Strike\s*\(\s*(\d+)%\s*\)$/); + if (strikeM) { + stats['Strike ' + strikeM[1]] = parseInt(strikeM[2]); + return; + } + + // Weapon damage line: "+523 Void Damage" / "+708 Piercing Damage" + // Base type can be Slashing/Crushing/Piercing, or Void for Ethereal. const dmgM = text.match(/^\+([\d,]+)\s*([A-Za-z]+)\s*Damage$/); if (dmgM) { stats['Weapon Damage'] = parseInt(dmgM[1].replace(/,/g, '')); @@ -3864,11 +3873,17 @@ function gearScoreWeapon(item) { s += _num(st['Block']) * 0.5; s += _num(st['Agility']) * 0.5; s -= _num(st['burden']) * 0.5; - // Base weapon damage (e.g. "+708 Piercing Damage") — scales with quality - s += _num(st['Weapon Damage']) * 0.30; - // Elemental damage lines (e.g. "+25 Fire Damage", "+30 Elec Strike") - ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Ethereal', 'Elemental'].forEach(el => { - s += _num(st['Elemental ' + el]) * 0.25; + // Base weapon damage (e.g. "+708 Piercing Damage", "+523 Void Damage") — scales with quality + const wd = _num(st['Weapon Damage']); + s += wd * 0.30; + // Elemental Strikes (wiki: "X Strike (Y%)" — separate hit for ~50% of physical damage) + // Expected damage = chance% × 0.5 × weapon damage. Weight same as base damage (0.30). + ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Void', 'Ethereal'].forEach(el => { + const chance = _num(st['Strike ' + el]); + if (chance > 0) { + const expected = (chance / 100) * 0.5 * wd; + s += expected > 0 ? expected * 0.30 : chance * 0.15; + } }); // Proc lines: elemental/status procs add value (e.g. "Proc Penetrated Armor: 21.7%") let procBonus = 0; @@ -3885,12 +3900,12 @@ function gearScoreWeapon(item) { s += procBonus; // Quality multiplier (q6=Magnificent, q5=Exquisite, q4=Superior) s *= 0.8 + (quality * 0.12); - // Weapon type bonus + // Weapon type bonus (wiki procs: Piercing→Penetrated Armor, Crushing→Stun, + // Slashing→Bleeding Wound; Estoc=2H Penetrated Armor is the 2H physical build's core) if (name.includes('estoc')) s *= 1.25; - else if (name.includes('longsword')) s *= 1.10; - else if (name.includes('great mace')) s *= 0.90; - else if (name.includes('club')) s *= 0.85; - else if (name.includes('axe')) s *= 0.90; + else if (name.includes('rapier')) s *= 1.20; // 1H Penetrated Armor + else if (name.includes('longsword') || name.includes('katana') || name.includes('shortsword') || name.includes('axe') || name.includes('wakizashi')) s *= 1.10; // Bleeding Wound + else if (name.includes('great mace') || name.includes('club') || name.includes('mace')) s *= 1.15; // Stun return s; } diff --git a/scripts/latest.user.js b/scripts/latest.user.js index a9a43b8..b3db691 100644 --- a/scripts/latest.user.js +++ b/scripts/latest.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.15.3 +// @version 0.15.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.15.3'; +const VERSION = '0.15.4'; const CFG = { // — Battle automation @@ -3528,7 +3528,16 @@ function parseEquipHTML(htmlStr) { return; } - // Weapon damage line: "+708 Piercing Damage" + // Elemental Strike line (wiki: "X Strike (Y%)" — e.g. "Void Strike (50%)") + // Additional ~50%-of-physical-damage hit; max 2 strikes + Void Strike. + const strikeM = text.match(/^([A-Za-z]+)\s+Strike\s*\(\s*(\d+)%\s*\)$/); + if (strikeM) { + stats['Strike ' + strikeM[1]] = parseInt(strikeM[2]); + return; + } + + // Weapon damage line: "+523 Void Damage" / "+708 Piercing Damage" + // Base type can be Slashing/Crushing/Piercing, or Void for Ethereal. const dmgM = text.match(/^\+([\d,]+)\s*([A-Za-z]+)\s*Damage$/); if (dmgM) { stats['Weapon Damage'] = parseInt(dmgM[1].replace(/,/g, '')); @@ -3864,11 +3873,17 @@ function gearScoreWeapon(item) { s += _num(st['Block']) * 0.5; s += _num(st['Agility']) * 0.5; s -= _num(st['burden']) * 0.5; - // Base weapon damage (e.g. "+708 Piercing Damage") — scales with quality - s += _num(st['Weapon Damage']) * 0.30; - // Elemental damage lines (e.g. "+25 Fire Damage", "+30 Elec Strike") - ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Ethereal', 'Elemental'].forEach(el => { - s += _num(st['Elemental ' + el]) * 0.25; + // Base weapon damage (e.g. "+708 Piercing Damage", "+523 Void Damage") — scales with quality + const wd = _num(st['Weapon Damage']); + s += wd * 0.30; + // Elemental Strikes (wiki: "X Strike (Y%)" — separate hit for ~50% of physical damage) + // Expected damage = chance% × 0.5 × weapon damage. Weight same as base damage (0.30). + ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Void', 'Ethereal'].forEach(el => { + const chance = _num(st['Strike ' + el]); + if (chance > 0) { + const expected = (chance / 100) * 0.5 * wd; + s += expected > 0 ? expected * 0.30 : chance * 0.15; + } }); // Proc lines: elemental/status procs add value (e.g. "Proc Penetrated Armor: 21.7%") let procBonus = 0; @@ -3885,12 +3900,12 @@ function gearScoreWeapon(item) { s += procBonus; // Quality multiplier (q6=Magnificent, q5=Exquisite, q4=Superior) s *= 0.8 + (quality * 0.12); - // Weapon type bonus + // Weapon type bonus (wiki procs: Piercing→Penetrated Armor, Crushing→Stun, + // Slashing→Bleeding Wound; Estoc=2H Penetrated Armor is the 2H physical build's core) if (name.includes('estoc')) s *= 1.25; - else if (name.includes('longsword')) s *= 1.10; - else if (name.includes('great mace')) s *= 0.90; - else if (name.includes('club')) s *= 0.85; - else if (name.includes('axe')) s *= 0.90; + else if (name.includes('rapier')) s *= 1.20; // 1H Penetrated Armor + else if (name.includes('longsword') || name.includes('katana') || name.includes('shortsword') || name.includes('axe') || name.includes('wakizashi')) s *= 1.10; // Bleeding Wound + else if (name.includes('great mace') || name.includes('club') || name.includes('mace')) s *= 1.15; // Stun return s; } diff --git a/src/config.js b/src/config.js index f985738..f6cb234 100644 --- a/src/config.js +++ b/src/config.js @@ -2,7 +2,7 @@ // CONFIG — default settings // ═══════════════════════════════════════════════════════════════════════ -const VERSION = '0.15.3'; +const VERSION = '0.15.4'; const CFG = { // — Battle automation diff --git a/src/gear-analysis.js b/src/gear-analysis.js index 70fbd1e..fa78e4c 100644 --- a/src/gear-analysis.js +++ b/src/gear-analysis.js @@ -45,11 +45,17 @@ function gearScoreWeapon(item) { s += _num(st['Block']) * 0.5; s += _num(st['Agility']) * 0.5; s -= _num(st['burden']) * 0.5; - // Base weapon damage (e.g. "+708 Piercing Damage") — scales with quality - s += _num(st['Weapon Damage']) * 0.30; - // Elemental damage lines (e.g. "+25 Fire Damage", "+30 Elec Strike") - ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Ethereal', 'Elemental'].forEach(el => { - s += _num(st['Elemental ' + el]) * 0.25; + // Base weapon damage (e.g. "+708 Piercing Damage", "+523 Void Damage") — scales with quality + const wd = _num(st['Weapon Damage']); + s += wd * 0.30; + // Elemental Strikes (wiki: "X Strike (Y%)" — separate hit for ~50% of physical damage) + // Expected damage = chance% × 0.5 × weapon damage. Weight same as base damage (0.30). + ['Fire', 'Cold', 'Elec', 'Wind', 'Holy', 'Dark', 'Void', 'Ethereal'].forEach(el => { + const chance = _num(st['Strike ' + el]); + if (chance > 0) { + const expected = (chance / 100) * 0.5 * wd; + s += expected > 0 ? expected * 0.30 : chance * 0.15; + } }); // Proc lines: elemental/status procs add value (e.g. "Proc Penetrated Armor: 21.7%") let procBonus = 0; @@ -66,12 +72,12 @@ function gearScoreWeapon(item) { s += procBonus; // Quality multiplier (q6=Magnificent, q5=Exquisite, q4=Superior) s *= 0.8 + (quality * 0.12); - // Weapon type bonus + // Weapon type bonus (wiki procs: Piercing→Penetrated Armor, Crushing→Stun, + // Slashing→Bleeding Wound; Estoc=2H Penetrated Armor is the 2H physical build's core) if (name.includes('estoc')) s *= 1.25; - else if (name.includes('longsword')) s *= 1.10; - else if (name.includes('great mace')) s *= 0.90; - else if (name.includes('club')) s *= 0.85; - else if (name.includes('axe')) s *= 0.90; + else if (name.includes('rapier')) s *= 1.20; // 1H Penetrated Armor + else if (name.includes('longsword') || name.includes('katana') || name.includes('shortsword') || name.includes('axe') || name.includes('wakizashi')) s *= 1.10; // Bleeding Wound + else if (name.includes('great mace') || name.includes('club') || name.includes('mace')) s *= 1.15; // Stun return s; } diff --git a/src/gear-scraper.js b/src/gear-scraper.js index fbf82cc..fa8e72e 100644 --- a/src/gear-scraper.js +++ b/src/gear-scraper.js @@ -133,7 +133,16 @@ function parseEquipHTML(htmlStr) { return; } - // Weapon damage line: "+708 Piercing Damage" + // Elemental Strike line (wiki: "X Strike (Y%)" — e.g. "Void Strike (50%)") + // Additional ~50%-of-physical-damage hit; max 2 strikes + Void Strike. + const strikeM = text.match(/^([A-Za-z]+)\s+Strike\s*\(\s*(\d+)%\s*\)$/); + if (strikeM) { + stats['Strike ' + strikeM[1]] = parseInt(strikeM[2]); + return; + } + + // Weapon damage line: "+523 Void Damage" / "+708 Piercing Damage" + // Base type can be Slashing/Crushing/Piercing, or Void for Ethereal. const dmgM = text.match(/^\+([\d,]+)\s*([A-Za-z]+)\s*Damage$/); if (dmgM) { stats['Weapon Damage'] = parseInt(dmgM[1].replace(/,/g, '')); diff --git a/src/header.user.js b/src/header.user.js index 21e8bce..c31d9b5 100644 --- a/src/header.user.js +++ b/src/header.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name HV Unified // @namespace hvunified -// @version 0.15.3 +// @version 0.15.4 // @description HV Unified — battle automation, guidance, and UI enhancements for HentaiVerse // @author GaboGG + Hermes // @match *://*.hentaiverse.org/*