diff --git a/builder/index.html b/builder/index.html
index 283d301..2084f43 100644
--- a/builder/index.html
+++ b/builder/index.html
@@ -619,7 +619,7 @@
Spell Damage %:
-
+
Original Value: 0
@@ -630,7 +630,7 @@
Spell Damage Raw:
-
+
Original Value: 0
@@ -641,7 +641,7 @@
Melee Damage %:
-
+
Original Value: 0
@@ -652,7 +652,7 @@
Melee Damage Raw:
-
+
Original Value: 0
@@ -665,7 +665,7 @@
Poison:
-
+
Original Value: 0
@@ -676,7 +676,7 @@
Damage %:
-
+
Original Value: 0
@@ -687,7 +687,7 @@
Damage %:
-
+
Original Value: 0
@@ -698,7 +698,7 @@
Damage %:
-
+
Original Value: 0
@@ -711,7 +711,7 @@
Damage %:
-
+
Original Value: 0
@@ -722,7 +722,7 @@
Damage %:
-
+
Original Value: 0
@@ -733,7 +733,7 @@
+ Tier:
-
+
Original Value: 0
@@ -752,7 +752,7 @@
Defense %:
-
+
Original Value: 0
@@ -763,7 +763,7 @@
Defense %:
-
+
Original Value: 0
@@ -774,7 +774,7 @@
Defense %:
-
+
Original Value: 0
@@ -785,7 +785,7 @@
Defense %:
-
+
Original Value: 0
@@ -798,7 +798,7 @@
Defense %:
-
+
Original Value: 0
@@ -809,7 +809,7 @@
Health Regen Raw:
-
+
Original Value: 0
@@ -820,7 +820,7 @@
Health Regen %:
-
+
Original Value: 0
@@ -831,7 +831,7 @@
Health Bonus:
-
+
Original Value: 0
@@ -847,7 +847,7 @@
1st Spell Cost %:
-
+
Original Value: 0
@@ -858,7 +858,7 @@
2nd Spell Cost %:
-
+
Original Value: 0
@@ -869,7 +869,7 @@
3rd Spell Cost %:
-
+
Original Value: 0
@@ -880,7 +880,7 @@
4th Spell Cost %:
-
+
Original Value: 0
@@ -893,7 +893,7 @@
1st Spell Cost Raw:
-
+
Original Value: 0
@@ -904,7 +904,7 @@
2nd Spell Cost Raw:
-
+
Original Value: 0
@@ -915,7 +915,7 @@
3rd Spell Cost Raw:
-
+
Original Value: 0
@@ -926,7 +926,7 @@
4th Spell Cost Raw:
-
+
Original Value: 0
diff --git a/js/build.js b/js/build.js
index a655290..78cf2ac 100644
--- a/js/build.js
+++ b/js/build.js
@@ -149,64 +149,6 @@ class Build{
return [this.equipment,this.weapon,this.tomes].flat();
}
- /* Getters */
-
- getSpellCost(spellIdx, cost) {
- return Math.max(1, this.getBaseSpellCost(spellIdx, cost));
- }
-
- getBaseSpellCost(spellIdx, cost) {
- // old intelligence:
- cost = Math.ceil(cost * (1 - skillPointsToPercentage(this.total_skillpoints[2])));
- cost += this.statMap.get("spRaw"+spellIdx);
- return Math.floor(cost * (1 + this.statMap.get("spPct"+spellIdx) / 100));
- }
-
-
- /* Get melee stats for build.
- Returns an array in the order:
- */
- getMeleeStats(){
- const stats = this.statMap;
- const weapon_stats = this.weapon.statMap;
- if (weapon_stats.get("tier") === "Crafted") {
- stats.set("damageBases", [weapon_stats.get("nDamBaseHigh"),weapon_stats.get("eDamBaseHigh"),weapon_stats.get("tDamBaseHigh"),weapon_stats.get("wDamBaseHigh"),weapon_stats.get("fDamBaseHigh"),weapon_stats.get("aDamBaseHigh")]);
- }
- let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier");
- if(adjAtkSpd > 6){
- adjAtkSpd = 6;
- }else if(adjAtkSpd < 0){
- adjAtkSpd = 0;
- }
-
- let damage_mult = 1;
- if (weapon_stats.get("type") === "relik") {
- 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"), 0, this.weapon.statMap, this.total_skillpoints, damage_mult * this.damageMultiplier);
-
- let dex = this.total_skillpoints[1];
-
- let totalDamNorm = results[0];
- let totalDamCrit = results[1];
- totalDamNorm.push(1-skillPointsToPercentage(dex));
- totalDamCrit.push(skillPointsToPercentage(dex));
- let damages_results = results[2];
-
- let singleHitTotal = ((totalDamNorm[0]+totalDamNorm[1])*(totalDamNorm[2])
- +(totalDamCrit[0]+totalDamCrit[1])*(totalDamCrit[2]))/2;
-
- //Now do math
- let normDPS = (totalDamNorm[0]+totalDamNorm[1])/2 * baseDamageMultiplier[adjAtkSpd];
- 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]).concat(results[3]);
- }
-
/* Get all stats for this build. Stores in this.statMap.
@pre The build itself should be valid. No checking of validity of pieces is done here.
diff --git a/js/builder_graph.js b/js/builder_graph.js
index d1b7292..29ec4d6 100644
--- a/js/builder_graph.js
+++ b/js/builder_graph.js
@@ -260,7 +260,6 @@ class PowderInputNode extends InputNode {
}
input = input.slice(2);
}
- //console.log("POWDERING: " + powdering);
return powdering;
}
}
@@ -407,7 +406,7 @@ class SpellDisplayNode extends ComputeNode {
}
compute_func(input_map) {
- const build = input_map.get('build');
+ const stats = input_map.get('stats');
const spell_info = input_map.get('spell-info');
const damages = input_map.get('spell-damage');
const spell = spell_info[0];
@@ -416,10 +415,60 @@ class SpellDisplayNode extends ComputeNode {
const i = this.spell_idx;
let parent_elem = document.getElementById("spell"+i+"-info");
let overallparent_elem = document.getElementById("spell"+i+"-infoAvg");
- displaySpellDamage(parent_elem, overallparent_elem, build, spell, i+1, spell_parts, damages);
+ displaySpellDamage(parent_elem, overallparent_elem, stats, spell, i+1, spell_parts, damages);
}
}
+/* Get melee stats for build.
+ Returns an array in the order:
+*/
+function getMeleeStats(stats, weapon) {
+ const weapon_stats = weapon.statMap;
+ const skillpoints = [
+ stats.get('str'),
+ stats.get('dex'),
+ stats.get('int'),
+ stats.get('def'),
+ stats.get('agi')
+ ];
+ if (weapon_stats.get("tier") === "Crafted") {
+ stats.set("damageBases", [weapon_stats.get("nDamBaseHigh"),weapon_stats.get("eDamBaseHigh"),weapon_stats.get("tDamBaseHigh"),weapon_stats.get("wDamBaseHigh"),weapon_stats.get("fDamBaseHigh"),weapon_stats.get("aDamBaseHigh")]);
+ }
+ let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier");
+ if(adjAtkSpd > 6){
+ adjAtkSpd = 6;
+ }else if(adjAtkSpd < 0){
+ adjAtkSpd = 0;
+ }
+
+ let damage_mult = 1;
+ if (weapon_stats.get("type") === "relik") {
+ 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"), 0, weapon_stats, skillpoints, damage_mult);
+
+ let dex = skillpoints[1];
+
+ let totalDamNorm = results[0];
+ let totalDamCrit = results[1];
+ totalDamNorm.push(1-skillPointsToPercentage(dex));
+ totalDamCrit.push(skillPointsToPercentage(dex));
+ let damages_results = results[2];
+
+ let singleHitTotal = ((totalDamNorm[0]+totalDamNorm[1])*(totalDamNorm[2])
+ +(totalDamCrit[0]+totalDamCrit[1])*(totalDamCrit[2]))/2;
+
+ //Now do math
+ let normDPS = (totalDamNorm[0]+totalDamNorm[1])/2 * baseDamageMultiplier[adjAtkSpd];
+ 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]).concat(results[3]);
+}
+
/**
* Display build stats.
*
@@ -434,7 +483,9 @@ class BuildDisplayNode extends ComputeNode {
displayBuildStats('overall-stats', build, build_all_display_commands, stats);
displayBuildStats("offensive-stats", build, build_offensive_display_commands, stats);
displaySetBonuses("set-info", build);
- let meleeStats = build.getMeleeStats();
+ let meleeStats = getMeleeStats(stats, build.weapon);
+ // TODO: move weapon out?
+ console.log(meleeStats);
displayMeleeDamage(document.getElementById("build-melee-stats"), document.getElementById("build-melee-statsAvg"), meleeStats);
displayDefenseStats(document.getElementById("defensive-stats"), stats);
@@ -541,7 +592,6 @@ class DisplayBuildWarningsNode extends ComputeNode {
}
for (const [setName, count] of build.activeSetCounts) {
const bonus = sets.get(setName).bonuses[count-1];
- // console.log(setName);
if (bonus["illegal"]) {
let setWarning = document.createElement("p");
setWarning.classList.add("itemp");
@@ -606,7 +656,6 @@ class SkillPointSetterNode extends ComputeNode {
}
compute_func(input_map) {
- console.log("mmm");
if (input_map.size !== 1) { throw "SkillPointSetterNode accepts exactly one input (build)"; }
const [build] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element
for (const [idx, elem] of skp_order.entries()) {
@@ -656,6 +705,7 @@ class SumNumberInputNode extends InputNode {
let item_nodes = [];
let powder_nodes = [];
let spelldmg_nodes = [];
+let edit_input_nodes = [];
function builder_graph_init() {
// Phase 1/2: Set up item input, propagate updates, etc.
@@ -714,7 +764,6 @@ function builder_graph_init() {
// Create one node that will be the "aggregator node" (listen to all the editable id nodes, as well as the build_node (for non editable stats) and collect them into one statmap)
let stat_agg_node = new AggregateStatsNode();
stat_agg_node.link_to(build_node, 'build').link_to(item_nodes[8], 'weapon');
- let edit_input_nodes = [];
for (const field of editable_item_fields) {
// Create nodes that listens to each editable id input, the node name should match the "id"
const elem = document.getElementById(field);
@@ -753,7 +802,7 @@ function builder_graph_init() {
spelldmg_nodes.push(calc_node);
let display_node = new SpellDisplayNode(i);
- display_node.link_to(build_node, 'build'); // TODO: same here..
+ display_node.link_to(stat_agg_node, 'stats'); // TODO: same here..
display_node.link_to(spell_node, 'spell-info');
display_node.link_to(calc_node, 'spell-damage');
}
diff --git a/js/damage_calc.js b/js/damage_calc.js
index 9149a13..eef3825 100644
--- a/js/damage_calc.js
+++ b/js/damage_calc.js
@@ -105,7 +105,7 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier,
let staticBoost = (pctModifier / 100.);
let skillBoost = [0];
for (let i in total_skillpoints) {
- skillBoost.push(skillPointsToPercentage(total_skillpoints[i]) + buildStats.get("damageBonus")[i] / 100.);
+ skillBoost.push(skillPointsToPercentage(total_skillpoints[i]) + buildStats.get(skp_elements[i]+"DamPct") / 100.);
}
for (let i in damages) {
diff --git a/js/display.js b/js/display.js
index 30175c8..c87f689 100644
--- a/js/display.js
+++ b/js/display.js
@@ -941,46 +941,45 @@ function displayExpandedIngredient(ingred, parent_id) {
}
}
-function displayNextCosts(spell, build, weapon) {
- let int = build.total_skillpoints[2];
- let spells = spell_table[weapon.get("type")];
+function displayNextCosts(_stats, spell, spellIdx) {
+ let stats = new Map(_stats);
+ let intel = stats.get('int');
let row = document.createElement("div");
row.classList.add("spellcost-tooltip");
let init_cost = document.createElement("b");
- init_cost.textContent = build.getSpellCost(spells.indexOf(spell) + 1, spell.cost);
+ init_cost.textContent = getSpellCost(stats, spellIdx, spell.cost);
init_cost.classList.add("Mana");
let arrow = document.createElement("b");
arrow.textContent = "\u279C";
let next_cost = document.createElement("b");
- next_cost.textContent = (init_cost.textContent === "1" ? 1 : build.getSpellCost(spells.indexOf(spell) + 1, spell.cost) - 1);
+ next_cost.textContent = (init_cost.textContent === "1" ? 1 : getSpellCost(stats, spellIdx, spell.cost) - 1);
next_cost.classList.add("Mana");
let int_needed = document.createElement("b");
if (init_cost.textContent === "1") {
int_needed.textContent = ": n/a (+0)";
}else { //do math
- let target = build.getSpellCost(spells.indexOf(spell) + 1, spell.cost) - 1;
- let needed = int;
+ let target = getSpellCost(stats, spellIdx, spell.cost) - 1;
+ let needed = intel;
let noUpdate = false;
//forgive me... I couldn't inverse ceil, floor, and max.
- while (build.getSpellCost(spells.indexOf(spell) + 1, spell.cost) > target) {
+ while (getSpellCost(stats, spellIdx, spell.cost) > target) {
if(needed > 150) {
noUpdate = true;
break;
}
needed++;
- build.total_skillpoints[2] = needed;
+ stats.set('int', stats.get('int') + 1);
}
- let missing = needed - int;
+ let missing = needed - intel;
//in rare circumstances, the next spell cost can jump.
if (noUpdate) {
- next_cost.textContent = (init_cost.textContent === "1" ? 1 : build.getSpellCost(spells.indexOf(spell) + 1, spell.cost)-1);
+ next_cost.textContent = (init_cost.textContent === "1" ? 1 : getSpellCost(stats, spellIdx, spell.cost)-1);
}else {
- next_cost.textContent = (init_cost.textContent === "1" ? 1 : build.getSpellCost(spells.indexOf(spell) + 1, spell.cost));
+ next_cost.textContent = (init_cost.textContent === "1" ? 1 : getSpellCost(stats, spellIdx, spell.cost));
}
- build.total_skillpoints[2] = int;//forgive me pt 2
int_needed.textContent = ": " + (needed > 150 ? ">150" : needed) + " int (+" + (needed > 150 ? "n/a" : missing) + ")";
}
@@ -1583,12 +1582,23 @@ function displayPowderSpecials(parent_elem, powderSpecials, build) {
}
}
-function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx, spell_parts, damages) {
+function getSpellCost(stats, spellIdx, cost) {
+ return Math.max(1, getBaseSpellCost(stats, spellIdx, cost));
+}
+
+function getBaseSpellCost(stats, spellIdx, cost) {
+ // old intelligence:
+ cost = Math.ceil(cost * (1 - skillPointsToPercentage(stats.get('int'))));
+ cost += stats.get("spRaw"+spellIdx);
+ return Math.floor(cost * (1 + stats.get("spPct"+spellIdx) / 100));
+}
+
+
+function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spellIdx, spell_parts, damages) {
// TODO: remove spellIdx (just used to flag melee and cost)
// TODO: move cost calc out
parent_elem.textContent = "";
- const stats = build.statMap;
let title_elem = document.createElement("p");
overallparent_elem.textContent = "";
@@ -1601,21 +1611,15 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell
title_elemavg.appendChild(first);
let second = document.createElement("span");
- second.textContent = build.getSpellCost(spellIdx, spell.cost);
+ second.textContent = getSpellCost(stats, spellIdx, spell.cost);
second.classList.add("Mana");
- let int_redux = skillPointsToPercentage(build.total_skillpoints[2]).toFixed(2);
- let spPct_redux = (build.statMap.get("spPct" + spellIdx)/100).toFixed(2);
- let spRaw_redux = (build.statMap.get("spRaw" + spellIdx)).toFixed(2);
- 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);
-
title_elem.appendChild(second.cloneNode(true));
title_elemavg.appendChild(second);
let third = document.createElement("span");
- third.textContent = ") [Base: " + build.getBaseSpellCost(spellIdx, spell.cost) + " ]";
+ third.textContent = ") [Base: " + getBaseSpellCost(stats, spellIdx, spell.cost) + " ]";
title_elem.appendChild(third);
let third_summary = document.createElement("span");
third_summary.textContent = ")";
@@ -1629,9 +1633,9 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell
parent_elem.append(title_elem);
overallparent_elem.append(title_elemavg);
- overallparent_elem.append(displayNextCosts(spell, build, build.weapon.statMap));
+ overallparent_elem.append(displayNextCosts(stats, spell, spellIdx));
- let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
+ let critChance = skillPointsToPercentage(stats.get('dex'));
let save_damages = [];
@@ -1650,7 +1654,6 @@ function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spell
part_div.append(subtitle_elem);
if (part.type === "damage") {
- //console.log(build.expandedStats);
let _results = damage;
let totalDamNormal = _results[0];
let totalDamCrit = _results[1];
diff --git a/js/optimize.js b/js/optimize.js
index 6185edd..fdce392 100644
--- a/js/optimize.js
+++ b/js/optimize.js
@@ -40,7 +40,7 @@ function optimizeStrDex() {
for (const part of spell_parts) {
if (part.type === "damage") {
let _results = calculateSpellDamage(stats, part.conversion,
- stats.get("sdRaw"), stats.get("sdPct") + player_build.externalStats.get("sdPct"),
+ stats.get("sdRaw"), stats.get("sdPct"),
part.multiplier / 100, player_build.weapon, total_skillpoints,
player_build.damageMultiplier, player_build.externalStats);
let totalDamNormal = _results[0];