From a093a65e765ad530ab07529f7419ceee9ad64ab8 Mon Sep 17 00:00:00 2001 From: ferricles Date: Tue, 30 Mar 2021 23:44:56 -0700 Subject: [PATCH] functional tooltips for spell costs, spell damages, melee damage, and defense stats --- build.js | 8 +-- customizer.html | 4 +- damage_calc.js | 39 ++++++++++--- display.js | 152 ++++++++++++++++++++++++++++++++---------------- styles.css | 23 +++++++- utils.js | 33 +++++++++++ 6 files changed, 194 insertions(+), 65 deletions(-) diff --git a/build.js b/build.js index 06c7049..291bdc1 100644 --- a/build.js +++ b/build.js @@ -1,6 +1,5 @@ -const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ]; -//0.51, 0.82, 1.50, 2.05, 2.50, 3.11, 4.27 + const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.20] ]); /** @@ -414,8 +413,9 @@ class Build{ let damage_mult = 1; if (this.weapon.get("type") === "relik") { - console.log("ASDFASDFASDFA"); damage_mult = 0.99; // CURSE YOU WYNNCRAFT + //One day we will create WynnWynn and no longer have shaman 99% melee injustice. + //In all seriousness 99% is because wynn uses 0.33 to estimate dividing the damage by 3 to split damage between 3 beams. } // 0spellmult for melee damage. let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], stats.get("mdRaw"), stats.get("mdPct") + this.externalStats.get("mdPct"), 0, this.weapon, this.total_skillpoints, damage_mult * this.damageMultiplier, this.externalStats); @@ -436,7 +436,7 @@ class Build{ let critDPS = (totalDamCrit[0]+totalDamCrit[1])/2 * baseDamageMultiplier[adjAtkSpd]; let avgDPS = (normDPS * (1 - skillPointsToPercentage(dex))) + (critDPS * (skillPointsToPercentage(dex))); //[[n n n n] [e e e e] [t t t t] [w w w w] [f f f f] [a a a a] [lowtotal hightotal normalChance] [critlowtotal crithightotal critChance] normalDPS critCPS averageDPS adjAttackSpeed, singleHit] - return damages_results.concat([totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS,adjAtkSpd, singleHitTotal]); + return damages_results.concat([totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS,adjAtkSpd, singleHitTotal]).concat(results[3]); } /* diff --git a/customizer.html b/customizer.html index 5310445..39e325e 100644 --- a/customizer.html +++ b/customizer.html @@ -992,12 +992,12 @@
-
+
diff --git a/damage_calc.js b/damage_calc.js index c701529..9c2ecca 100644 --- a/damage_calc.js +++ b/damage_calc.js @@ -5,6 +5,8 @@ const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["va function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier, externalStats) { let buildStats = new Map(stats); let tooltipinfo = new Map(); + //6x for damages, normal min normal max crit min crit max + let damageformulas = [["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "]]; if(externalStats) { //if nothing is passed in, then this hopefully won't trigger for (const entry of externalStats) { @@ -87,10 +89,11 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, - tooltipinfo.set("damagebase",[neutralRemainingRaw,damages[1],damages[2],damages[3],damages[4],damages[5]]); - console.log(tooltipinfo); + + //console.log(tooltipinfo); damages[0] = neutralRemainingRaw; + tooltipinfo.set("damageBases", damages); let damageMult = damageMultiplier; let melee = false; @@ -101,17 +104,21 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, melee = true; } else { + tooltipinfo.set("dmgMult", `(${tooltipinfo.get("dmgMult")} * ${spellMultiplier} * ${baseDamageMultiplier[attackSpeeds.indexOf(buildStats.get("atkSpd"))]})`) damageMult *= spellMultiplier * baseDamageMultiplier[attackSpeeds.indexOf(buildStats.get("atkSpd"))]; } //console.log(damages); //console.log(damageMult); - + tooltipinfo.set("rawModifier", `(${rawModifier} * ${spellMultiplier} * ${damageMultiplier})`); rawModifier *= spellMultiplier * damageMultiplier; let totalDamNorm = [0, 0]; let totalDamCrit = [0, 0]; if(!melee){ totalDamNorm = [rawModifier, rawModifier]; totalDamCrit = [rawModifier, rawModifier]; + for (let arr of damageformulas) { + arr = arr.map(x => x + " + " +tooltipinfo.get("rawModifier")); + } } let damages_results = []; // 0th skillpoint is strength, 1st is dex. @@ -119,23 +126,35 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, let strBoost = 1 + skillPointsToPercentage(str); //let staticBoost = (pctModifier / 100.); let staticBoost = (pctModifier / 100.) + skillPointsToPercentage(str); + tooltipinfo.set("staticBoost", `${(pctModifier/ 100.).toFixed(2)} + ${skillPointsToPercentage(str).toFixed(2)}`); + tooltipinfo.set("skillBoost",["","","","","",""]); let skillBoost = [0]; for (let i in total_skillpoints) { skillBoost.push(skillPointsToPercentage(total_skillpoints[i]) + buildStats.get("damageBonus")[i] / 100.); + tooltipinfo.get("skillBoost")[i] = `(${skillPointsToPercentage(total_skillpoints[i]).toFixed(2)} + ${(buildStats.get("damageBonus")[i]/100.).toFixed(2)})` } for (let i in damages) { let damageBoost = 1 + skillBoost[i] + staticBoost; + tooltipinfo.set("damageBoost", `(1 + ${tooltipinfo.get("skillBoost")[i]} + ${tooltipinfo.get("staticBoost")})`) damages_results.push([ //Math.max(damages[i][0] * strBoost * Math.max(damageBoost,0) * damageMult, 0), // Normal min //Math.max(damages[i][1] * strBoost * Math.max(damageBoost,0) * damageMult, 0), // Normal max //Math.max(damages[i][0] * strBoost * 2 * Math.max(damageBoost,0) * damageMult, 0), // Crit min //Math.max(damages[i][1] * strBoost * 2 * Math.max(damageBoost,0) * damageMult, 0), // Crit max - Math.max(damages[i][0] * Math.max(damageBoost,0) * damageMult, 0), // Normal min - Math.max(damages[i][1] * Math.max(damageBoost,0) * damageMult, 0), // Normal max - Math.max(damages[i][0] * Math.max(1 + damageBoost, 0) * damageMult, 0), // Crit min - Math.max(damages[i][1] * Math.max(1 + damageBoost, 0) * damageMult, 0), // Crit max + // Math.max(damages[i][0] * Math.max(damageBoost,0) * damageMult, 0), // Normal min + // Math.max(damages[i][1] * Math.max(damageBoost,0) * damageMult, 0), // Normal max + // Math.max(damages[i][0] * Math.max(1 + damageBoost, 0) * damageMult, 0), // Crit min + // Math.max(damages[i][1] * Math.max(1 + damageBoost, 0) * damageMult, 0), // Crit max + damages[i][0] * Math.max(damageBoost,0) * damageMult, // Normal min + damages[i][1] * Math.max(damageBoost,0) * damageMult, // Normal max + damages[i][0] * Math.max(1 + damageBoost, 0) * damageMult, // Crit min + damages[i][1] * Math.max(1 + damageBoost, 0) * damageMult, // Crit max ]); + damageformulas[i][0] += `(max((${tooltipinfo.get("damageBases")[i][0]} * max(${tooltipinfo.get("damageBoost")}, 0) * ${tooltipinfo.get("dmgMult")}), 0))` + damageformulas[i][1] += `(max((${tooltipinfo.get("damageBases")[i][1]} * max(${tooltipinfo.get("damageBoost")}, 0) * ${tooltipinfo.get("dmgMult")}), 0))` + damageformulas[i][2] += `(max((${tooltipinfo.get("damageBases")[i][0]} * max(1 + ${tooltipinfo.get("damageBoost")}, 0) * ${tooltipinfo.get("dmgMult")}), 0))` + damageformulas[i][3] += `(max((${tooltipinfo.get("damageBases")[i][1]} * max(1 + ${tooltipinfo.get("damageBoost")}, 0) * ${tooltipinfo.get("dmgMult")}), 0))` totalDamNorm[0] += damages_results[i][0]; totalDamNorm[1] += damages_results[i][1]; totalDamCrit[0] += damages_results[i][2]; @@ -159,13 +178,17 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, damages_results[0][1] += rawModifier; damages_results[0][2] += rawModifier; damages_results[0][3] += rawModifier; + for (let i in damageformulas[0]) { + damageformulas[0][i] += ` + ${tooltipinfo.get("rawModifier")}` + } + if (totalDamNorm[0] < 0) totalDamNorm[0] = 0; if (totalDamNorm[1] < 0) totalDamNorm[1] = 0; if (totalDamCrit[0] < 0) totalDamCrit[0] = 0; if (totalDamCrit[1] < 0) totalDamCrit[1] = 0; - + tooltipinfo.set("damageformulas", damageformulas); return [totalDamNorm, totalDamCrit, damages_results, tooltipinfo]; } diff --git a/display.js b/display.js index fa939d4..c2c821d 100644 --- a/display.js +++ b/display.js @@ -1412,6 +1412,9 @@ function displayPoisonDamage(overallparent_elem, build) { } function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ + console.log("Melee Stats"); + console.log(meleeStats); + let tooltipinfo = meleeStats[13]; let attackSpeeds = ["Super Slow", "Very Slow", "Slow", "Normal", "Fast", "Very Fast", "Super Fast"]; //let damagePrefixes = ["Neutral Damage: ","Earth Damage: ","Thunder Damage: ","Water Damage: ","Fire Damage: ","Air Damage: "]; parent_elem.textContent = ""; @@ -1431,6 +1434,8 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ for (let i = 8; i < 11; ++i){ stats[i] = stats[i].toFixed(2); } + //tooltipelem, tooltiptext + let tooltip; let tooltiptext; //title let title_elem = document.createElement("p"); @@ -1452,7 +1457,11 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ let averageDamage = document.createElement("p"); averageDamage.classList.add("left"); averageDamage.classList.add("itemp"); + averageDamage.classList.add("tooltip"); averageDamage.textContent = "Average DPS: " + stats[10]; + tooltiptext = `= ((${stats[8]} * ${(stats[6][2]).toFixed(2)}) + (${stats[9]} * ${(stats[7][2]).toFixed(2)}))` + tooltip = createTooltip(tooltip, "p", tooltiptext, averageDamage, ["melee-tooltip"]); + averageDamage.appendChild(tooltip); parent_elem.append(averageDamage); //overall average DPS @@ -1464,6 +1473,7 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ let overallaverageDamageSecond = document.createElement("b"); overallaverageDamageSecond.classList.add("Damage"); overallaverageDamageSecond.textContent = stats[10]; + tooltip = createTooltip(tooltip, "p", tooltiptext, overallaverageDamage, ["melee-tooltip", "summary-tooltip"]); overallaverageDamage.appendChild(overallaverageDamageFirst); overallaverageDamage.appendChild(overallaverageDamageSecond); @@ -1490,7 +1500,6 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ overallatkSpd.appendChild(overallatkSpdFirst); overallatkSpd.appendChild(overallatkSpdSecond); overallparent_elem.append(overallatkSpd); - //overallparent_elem.append(document.createElement("br")); //Non-Crit: n->elem, total dmg, DPS let nonCritStats = document.createElement("p"); @@ -1499,23 +1508,38 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ nonCritStats.textContent = "Non-Crit Stats: "; nonCritStats.append(document.createElement("br")); for (let i = 0; i < 6; i++){ - if(stats[i][1] > 0){ + if(stats[i][1] != 0){ let dmg = document.createElement("p"); - dmg.textContent = stats[i][0] + "-" + stats[i][1]; + dmg.textContent = stats[i][0] + " \u2013 " + stats[i][1]; dmg.classList.add(damageClasses[i]); dmg.classList.add("itemp"); + tooltiptext = tooltipinfo.get("damageformulas")[i].slice(0,2).join("\n"); + tooltip = createTooltip(tooltip, "p", tooltiptext, dmg, ["melee-tooltip"]); nonCritStats.append(dmg); } } let normalDamage = document.createElement("p"); - normalDamage.textContent = "Total: " + stats[6][0] + "-" + stats[6][1]; + normalDamage.textContent = "Total: " + stats[6][0] + " \u2013 " + stats[6][1]; normalDamage.classList.add("itemp"); + let tooltiparr = ["Min: = ", "Max: = "] + let arr = []; let arr2 = []; + for (let i = 0; i < 6; i++) { + if (stats[i][0] != 0) { + arr.push(stats[i][0]); + arr2.push(stats[i][1]); + } + } + tooltiptext = tooltiparr[0] + arr.join(" + ") + "\n" + tooltiparr[1] + arr2.join(" + "); + tooltip = createTooltip(tooltip, "p", tooltiptext, normalDamage, ["melee-tooltip"]); nonCritStats.append(normalDamage); let normalDPS = document.createElement("p"); normalDPS.textContent = "Normal DPS: " + stats[8]; normalDPS.classList.add("itemp"); + normalDPS.classList.add("tooltip"); + tooltiptext = ` = ((${stats[6][0]} + ${stats[6][1]}) / 2) * ${baseDamageMultiplier[stats[11]]}`; + tooltip = createTooltip(tooltip, "p", tooltiptext, normalDPS, ["melee-tooltip"]); nonCritStats.append(normalDPS); //overall average DPS @@ -1526,6 +1550,8 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ let singleHitDamageSecond = document.createElement("b"); singleHitDamageSecond.classList.add("Damage"); singleHitDamageSecond.textContent = stats[12].toFixed(2); + tooltiptext = ` = ((${stats[6][0]} + ${stats[6][1]}) / 2) * ${stats[6][2].toFixed(2)} + ((${stats[7][0]} + ${stats[7][1]}) / 2) * ${stats[7][2].toFixed(2)}`; + tooltip = createTooltip(tooltip, "p", tooltiptext, singleHitDamage, ["melee-tooltip", "summary-tooltip"]); singleHitDamage.appendChild(singleHitDamageFirst); singleHitDamage.appendChild(singleHitDamageSecond); @@ -1549,22 +1575,37 @@ function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){ critStats.textContent = "Crit Stats: "; critStats.append(document.createElement("br")); for (let i = 0; i < 6; i++){ - if(stats[i][3] > 0){ + if(stats[i][3] != 0) { dmg = document.createElement("p"); - dmg.textContent = stats[i][2] + "-" + stats[i][3]; + dmg.textContent = stats[i][2] + " \u2013 " + stats[i][3]; dmg.classList.add(damageClasses[i]); dmg.classList.add("itemp"); + tooltiptext = tooltipinfo.get("damageformulas")[i].slice(2,4).join("\n"); + tooltip = createTooltip(tooltip, "p", tooltiptext, dmg, ["melee-tooltip"]); critStats.append(dmg); } } let critDamage = document.createElement("p"); - critDamage.textContent = "Total: " + stats[7][0] + "-" + stats[7][1]; + critDamage.textContent = "Total: " + stats[7][0] + " \u2013 " + stats[7][1]; critDamage.classList.add("itemp"); + tooltiparr = ["Min: = ", "Max: = "] + arr = []; arr2 = []; + for (let i = 0; i < 6; i++) { + if (stats[i][0] != 0) { + arr.push(stats[i][2]); + arr2.push(stats[i][3]); + } + } + tooltiptext = tooltiparr[0] + arr.join(" + ") + "\n" + tooltiparr[1] + arr2.join(" + "); + tooltip = createTooltip(tooltip, "p", tooltiptext, critDamage, ["melee-tooltip"]); + critStats.append(critDamage); let critDPS = document.createElement("p"); critDPS.textContent = "Crit DPS: " + stats[9]; critDPS.classList.add("itemp"); + tooltiptext = ` = ((${stats[7][0]} + ${stats[7][1]}) / 2) * ${baseDamageMultiplier[stats[11]]}`; + tooltip = createTooltip(tooltip, "p", tooltiptext, critDPS, ["melee-tooltip"]); critStats.append(critDPS); let critChance = document.createElement("p"); @@ -1645,7 +1686,7 @@ function displayDefenseStats(parent_elem, build, insertSummary){ hpRow.append(boost); statsTable.appendChild(hpRow); - let tooltip_elem; + let tooltip; let tooltiptext; let defMult = build.statMap.get("defMult"); if (!defMult) {defMult = 1} @@ -1659,12 +1700,8 @@ function displayDefenseStats(parent_elem, build, insertSummary){ boost = document.createElement("td"); boost.textContent = stats[1][0]; boost.classList.add("right"); - boost.classList.add("tooltip"); - tooltip_elem = document.createElement("p"); - tooltip_elem.classList.add("tooltiptext"); - tooltip_elem.classList.add("def-tooltip"); - tooltip_elem.textContent = `= ${stats[0]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (1 - ${skillPointsToPercentage(build.total_skillpoints[4]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` - boost.appendChild(tooltip_elem); + tooltiptext = `= ${stats[0]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (1 - ${skillPointsToPercentage(build.total_skillpoints[4]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` + tooltip = createTooltip(tooltip, "p", tooltiptext, boost, ["def-tooltip"]); ehpRow.appendChild(ehp); ehpRow.append(boost); @@ -1678,12 +1715,8 @@ function displayDefenseStats(parent_elem, build, insertSummary){ boost = document.createElement("td"); boost.textContent = stats[1][1]; boost.classList.add("right"); - boost.classList.add("tooltip"); - tooltip_elem = document.createElement("p"); - tooltip_elem.classList.add("tooltiptext"); - tooltip_elem.classList.add("def-tooltip"); - tooltip_elem.textContent = `= ${stats[0]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` - boost.appendChild(tooltip_elem); + tooltiptext = `= ${stats[0]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` + tooltip = createTooltip(tooltip, "p", tooltiptext, boost, ["def-tooltip"]); ehpRow.appendChild(ehp); ehpRow.append(boost); @@ -1711,12 +1744,8 @@ function displayDefenseStats(parent_elem, build, insertSummary){ boost = document.createElement("td"); boost.textContent = stats[3][0]; boost.classList.add("right"); - boost.classList.add("tooltip"); - tooltip_elem = document.createElement("p"); - tooltip_elem.classList.add("tooltiptext"); - tooltip_elem.classList.add("def-tooltip"); - tooltip_elem.textContent = `= ${stats[2]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (1 - ${skillPointsToPercentage(build.total_skillpoints[4]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` - boost.appendChild(tooltip_elem); + tooltiptext = `= ${stats[2]} / ((1 - ${skillPointsToPercentage(build.total_skillpoints[3]).toFixed(3)}) * (1 - ${skillPointsToPercentage(build.total_skillpoints[4]).toFixed(3)}) * (2 - ${defMult}) * (2 - ${build.defenseMultiplier}))` + tooltip = createTooltip(tooltip, "p", tooltiptext, boost, ["def-tooltip"]); ehprRow.appendChild(ehpr); ehprRow.append(boost); @@ -1757,21 +1786,17 @@ function displayDefenseStats(parent_elem, build, insertSummary){ boost.textContent = eledefs[i]; boost.classList.add(eledefs[i] >= 0 ? "positive" : "negative"); boost.classList.add("right"); - boost.classList.add("tooltip"); - tooltip_elem = document.createElement("p"); - tooltip_elem.classList.add("tooltiptext"); - tooltip_elem.classList.add("def-tooltip"); let defRaw = build.statMap.get("defRaw")[i]; let defPct = build.statMap.get("defBonus")[i]/100; if (defRaw < 0) { defPct >= 0 ? defPct = "- " + defPct: defPct = "+ " + defPct; - tooltip_elem.textContent = `= min(0, ${defRaw} * (1 ${defPct}))` + tooltiptext = `= min(0, ${defRaw} * (1 ${defPct}))` } else { defPct >= 0 ? defPct = "+ " + defPct: defPct = "- " + defPct; - tooltip_elem.textContent = `= ${defRaw} * (1 ${defPct})` + tooltiptext = `= ${defRaw} * (1 ${defPct})` } - boost.appendChild(tooltip_elem); + tooltip = createTooltip(tooltip, "p", tooltiptext, boost, ["def-tooltip"]); eledefElemRow.appendChild(boost); @@ -1933,6 +1958,8 @@ function displayPowderSpecials(parent_elem, powderSpecials, build) { function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx) { parent_elem.textContent = ""; + + let tooltip; let tooltiptext; const stats = build.statMap; let title_elem = document.createElement("p"); title_elem.classList.add("smalltitle"); @@ -1953,16 +1980,6 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell second.textContent = build.getSpellCost(spellIdx, spell.cost); second.classList.add("Mana"); second.classList.add("tooltip"); - - let mana_cost_tooltip = document.createElement("p"); - mana_cost_tooltip.classList.add("tooltiptext"); - mana_cost_tooltip.classList.add("spellcostcalc") - mana_cost_tooltip.classList.add("itemp"); - - let tooltip_text = document.createElement("div"); - tooltip_text.width = "100%"; - tooltip_text.style.wordBreak = "break-all"; - tooltip_text.style.overflowWrap = "break-word"; let int_redux = skillPointsToPercentage(build.total_skillpoints[2]).toFixed(2); let spPct_redux = (build.statMap.get("spPct" + spellIdx)/100).toFixed(2); @@ -1970,9 +1987,9 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell spPct_redux >= 0 ? spPct_redux = "+ " + spPct_redux : spPct_redux = "- " + Math.abs(spPct_redux); spRaw_redux >= 0 ? spRaw_redux = "+ " + spRaw_redux : spRaw_redux = "- " + Math.abs(spRaw_redux); - tooltip_text.textContent = `= max(1, floor((ceil(${spell.cost} * (1 - ${int_redux})) ${spRaw_redux}) * (1 ${spPct_redux})))`; - mana_cost_tooltip.appendChild(tooltip_text); - second.appendChild(mana_cost_tooltip); + tooltiptext = `= max(1, floor((ceil(${spell.cost} * (1 - ${int_redux})) ${spRaw_redux}) * (1 ${spPct_redux})))`; + tooltip = createTooltip(tooltip, "p", tooltiptext, second, ["spellcostcalc"]); + second.appendChild(tooltip); title_elem.appendChild(second.cloneNode(true)); title_elemavg.appendChild(second); @@ -2032,6 +2049,8 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell let totalDamNormal = _results[0]; let totalDamCrit = _results[1]; let results = _results[2]; + let tooltipinfo = _results[3]; + for (let i = 0; i < 6; ++i) { for (let j in results[i]) { results[i][j] = results[i][j].toFixed(2); @@ -2043,7 +2062,9 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell let averageLabel = document.createElement("p"); averageLabel.textContent = "Average: "+averageDamage.toFixed(2); + tooltiptext = ` = ((1 - ${critChance}) * ${nonCritAverage.toFixed(2)}) + (${critChance} * ${critAverage.toFixed(2)})` averageLabel.classList.add("damageSubtitle"); + tooltip = createTooltip(tooltip, "p", tooltiptext, averageLabel, ["spell-tooltip"]); part_div.append(averageLabel); @@ -2055,6 +2076,7 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell second.textContent = averageDamage.toFixed(2); overallaverageLabel.appendChild(first); overallaverageLabel.appendChild(second); + tooltip = createTooltip(tooltip, "p", tooltiptext, overallaverageLabel, ["spell-tooltip", "summary-tooltip"]); second.classList.add("Damage"); overallaverageLabel.classList.add("overallp"); part_divavg.append(overallaverageLabel); @@ -2065,36 +2087,56 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell nonCritLabel.classList.add("damageSubtitle"); part_div.append(nonCritLabel); + let noncritarrmin = []; + let noncritarrmax = []; for (let i = 0; i < 6; i++){ - if (results[i][1] > 0){ + if (results[i][1] != 0){ let p = document.createElement("p"); p.classList.add("damagep"); p.classList.add(damageClasses[i]); - p.textContent = results[i][0]+"-"+results[i][1]; + p.textContent = results[i][0] + " \u2013 " + results[i][1]; + tooltiptext = tooltipinfo.get("damageformulas")[i].slice(0,2).join("\n"); + tooltip = createTooltip(tooltip, "p", tooltiptext, p, ["spell-tooltip"]); + noncritarrmin.push(results[i][0]); + noncritarrmax.push(results[i][1]); part_div.append(p); } } + tooltiptext = ` = ((${noncritarrmin.join(" + ")}) + (${noncritarrmax.join(" + ")})) / 2`; + tooltip = createTooltip(tooltip, "p", tooltiptext, nonCritLabel, ["spell-tooltip"]); + //part_div.append(document.createElement("br")); let critLabel = document.createElement("p"); critLabel.textContent = "Crit Average: "+critAverage.toFixed(2); critLabel.classList.add("damageSubtitle"); part_div.append(critLabel); + let critarrmin = []; + let critarrmax = []; for (let i = 0; i < 6; i++){ - if (results[i][1] > 0){ + if (results[i][1] != 0){ let p = document.createElement("p"); p.classList.add("damagep"); p.classList.add(damageClasses[i]); - p.textContent = results[i][2]+"-"+results[i][3]; + p.textContent = results[i][2]+" \u2013 "+results[i][3]; + tooltiptext = tooltipinfo.get("damageformulas")[i].slice(2,4).join("\n"); + tooltip = createTooltip(tooltip, "p", tooltiptext, p, ["spell-tooltip"]); + critarrmin.push(results[i][2]); + critarrmax.push(results[i][3]); part_div.append(p); } } + tooltiptext = ` = ((${critarrmin.join(" + ")}) + (${critarrmax.join(" + ")})) / 2`; + tooltip = createTooltip(tooltip, "p", tooltiptext, critLabel, ["spell-tooltip"]); + save_damages.push(averageDamage); } else if (part.type === "heal") { let heal_amount = (part.strength * build.getDefenseStats()[0] * Math.max(0.5,Math.min(1.75, 1 + 0.5 * stats.get("wDamPct")/100))).toFixed(2); + tooltiptext = ` = ${part.strength} * ${build.getDefenseStats()[0]} * max(0.5, min(1.75, 1 + 0.5 * ${stats.get("wDamPct")/100}))`; let healLabel = document.createElement("p"); healLabel.textContent = heal_amount; healLabel.classList.add("damagep"); + tooltip = createTooltip(tooltip, "p", tooltiptext, healLabel, ["spell-tooltip"]); part_div.append(healLabel); if (part.summary == true) { let overallhealLabel = document.createElement("p"); @@ -2106,16 +2148,25 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell second.classList.add("Set"); overallhealLabel.appendChild(second); overallhealLabel.classList.add("overallp"); + tooltip = createTooltip(tooltip, "p", tooltiptext, second, ["spell-tooltip"]); part_divavg.append(overallhealLabel); } } else if (part.type === "total") { let total_damage = 0; + tooltiptext = ""; for (let i in part.factors) { total_damage += save_damages[i] * part.factors[i]; } + + let dmgarr = part.factors.slice(); + dmgarr = dmgarr.map(x => "(" + x + " * " + save_damages[dmgarr.indexOf(x)].toFixed(2) + ")"); + tooltiptext = " = " + dmgarr.join(" + "); + + let averageLabel = document.createElement("p"); averageLabel.textContent = "Average: "+total_damage.toFixed(2); averageLabel.classList.add("damageSubtitle"); + tooltip = createTooltip(tooltip, "p", tooltiptext, averageLabel, ["spell-tooltip"]); part_div.append(averageLabel); let overallaverageLabel = document.createElement("p"); @@ -2125,6 +2176,7 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell overallaverageLabelFirst.textContent = "Average: "; overallaverageLabelSecond.textContent = total_damage.toFixed(2); overallaverageLabelSecond.classList.add("Damage"); + tooltip = createTooltip(tooltip, "p", tooltiptext, overallaverageLabel, ["spell-tooltip", "summary-tooltip"]); overallaverageLabel.appendChild(overallaverageLabelFirst); diff --git a/styles.css b/styles.css index fd21fdf..b09fa0a 100644 --- a/styles.css +++ b/styles.css @@ -491,7 +491,7 @@ button.toggleOn:hover { top: 100%; } .spellcostcalc { - width: max(70%, 130px) !important; + width: max(70%, 120px) !important; font-size: 12px; /*overflow-wrap: break-word !important;*/ border: 1.5px dotted #BCBCBC !important; @@ -510,6 +510,27 @@ button.toggleOn:hover { margin-top: 20px; left: -30%; } +.melee-tooltip { + width: max(80%, 150px) !important; + font-size: 12px; + border: 1.5px dotted #BCBCBC !important; + border-radius: 1px !important; + /*JANK*/ + margin-top: 20px; + left: -10%; +} +.spell-tooltip { + width: max(80%, 150px) !important; + font-size: 12px; + border: 1.5px dotted #BCBCBC !important; + border-radius: 1px !important; + /*JANK*/ + margin-top: 20px; + left: -10%; +} +.summary-tooltip { + left: 10% !important; +} .recipe { z-index: 1; diff --git a/utils.js b/utils.js index 0cf3b5d..f1c100e 100644 --- a/utils.js +++ b/utils.js @@ -11,6 +11,8 @@ let accessoryTypes = [ "ring", "bracelet", "necklace" ]; let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ]; let consumableTypes = [ "potion", "scroll", "food"]; const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"]; +const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ]; +//0.51, 0.82, 1.50, 2.05, 2.50, 3.11, 4.27 const classes = ["Warrior", "Assassin", "Mage", "Archer", "Shaman"]; const tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"] //I'm not sure why you would make a custom crafted but if you do you should be able to use it w/ the correct powder formula const types = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(consumableTypes).map(x => x.substring(0,1).toUpperCase() + x.substring(1)); @@ -310,4 +312,35 @@ function randomColorHSL(h,s,l) { } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +} + +/** Creates a tooltip. + * + * @param {DOM Element} elem - the element to make a tooltip + * @param {String} element_type - the HTML element type that the tooltiptext should be. + * @param {String} tooltiptext - the text to display in the tooltip. + * @param {DOM Element} parent - the parent elem. optional. + * @param {String[]} classList - a list of classes to add to the element. + */ +function createTooltip(elem, element_type, tooltiptext, parent, classList) { + elem = document.createElement(element_type); + elem.classList.add("tooltiptext"); + if (tooltiptext.includes("\n")) { + let texts = tooltiptext.split("\n"); + for (const t of texts) { + let child = document.createElement(element_type); + child.textContent = t; + elem.appendChild(child); + } + } else { + elem.textContent = tooltiptext; + } + for (const c of classList) { + elem.classList.add(c); + } + if (parent) { + parent.classList.add("tooltip"); + parent.appendChild(elem); + } + return elem; } \ No newline at end of file