This commit is contained in:
reschan 2022-05-14 13:02:46 +07:00
commit 1a9443e079
9 changed files with 130 additions and 62 deletions

View file

@ -507,7 +507,8 @@
Rage (Passive) Rage (Passive)
</div> </div>
<div class="col"> <div class="col">
<input type = "range" class = "e_slider" id = "str_boost_armor" name = "str-boost-armor" min = '0' max = '396' value = '0' step = '1' onchange = "updateArmorPowderSpecials('str_boost_armor')"> <input type = "range" class = "e_slider" id = "str_boost_armor" name = "str-boost-armor" autocomplete = "off" min = '0' max = '400' value = '0' step = '1' onchange = "updateArmorPowderSpecials('str_boost_armor', true)">
<input type="text" id="str_boost_armor_prev" autocomplete = "off" value="0" style = "display:none;">
<label id = "str_boost_armor_label" for="str-boost-armor">% Earth Dmg Boost: 0</label> <label id = "str_boost_armor_label" for="str-boost-armor">% Earth Dmg Boost: 0</label>
</div> </div>
</div> </div>
@ -550,7 +551,8 @@
Kill Streak (Passive) Kill Streak (Passive)
</div> </div>
<div class="col"> <div class="col">
<input type = "range" class = "t_slider" id = "dex_boost_armor" name = "dex-boost-armor" min = '0' max = '200' value = '0' step = '1' onchange = "updateArmorPowderSpecials('dex_boost_armor')"> <input type = "range" class = "t_slider" id = "dex_boost_armor" name = "dex-boost-armor" autocomplete = "off" min = '0' max = '200' value = '0' step = '1' onchange = "updateArmorPowderSpecials('dex_boost_armor', true)">
<input type="text" id="dex_boost_armor_prev" autocomplete = "off" value="0" style = "display:none;">
<label id = "dex_boost_armor_label" for="dex-boost-armor">% Thunder Dmg Boost: 0</label> <label id = "dex_boost_armor_label" for="dex-boost-armor">% Thunder Dmg Boost: 0</label>
</div> </div>
</div> </div>
@ -593,7 +595,8 @@
Concentration (Passive) Concentration (Passive)
</div> </div>
<div class="col"> <div class="col">
<input type = "range" class = "w_slider" id = "int_boost_armor" name = "dex-boost-armor" min = '0' max = '150' value = '0' step = '1' onchange = "updateArmorPowderSpecials('int_boost_armor')"> <input type = "range" class = "w_slider" id = "int_boost_armor" name = "dex-boost-armor" autocomplete = "off" min = '0' max = '150' value = '0' step = '1' onchange = "updateArmorPowderSpecials('int_boost_armor', true)">
<input type="text" id="int_boost_armor_prev" autocomplete = "off" value="0" style = "display:none;">
<label id = "int_boost_armor_label" for="dex-boost-armor">% Water Dmg Boost: 0</label> <label id = "int_boost_armor_label" for="dex-boost-armor">% Water Dmg Boost: 0</label>
</div> </div>
</div> </div>
@ -636,7 +639,8 @@
Endurance (Passive) Endurance (Passive)
</div> </div>
<div class="col"> <div class="col">
<input type = "range" class = "f_slider" id = "def_boost_armor" name = "def-boost-armor" min = '0' max = '200' value = '0' step = '1' onchange = "updateArmorPowderSpecials('def_boost_armor')"> <input type = "range" class = "f_slider" id = "def_boost_armor" name = "def-boost-armor" autocomplete = "off" min = '0' max = '200' value = '0' step = '1' onchange = "updateArmorPowderSpecials('def_boost_armor', true)">
<input type="text" id="def_boost_armor_prev" autocomplete = "off" value="0" style = "display:none;">
<label id = "def_boost_armor_label" for="def-boost-armor">% Fire Dmg Boost: 0</label> <label id = "def_boost_armor_label" for="def-boost-armor">% Fire Dmg Boost: 0</label>
</div> </div>
</div> </div>
@ -679,7 +683,8 @@
Dodge (Passive) Dodge (Passive)
</div> </div>
<div class="col"> <div class="col">
<input type = "range" class = "a_slider" id = "agi_boost_armor" name = "agi-boost-armor" min = '0' max = '150' value = '0' step = '1' onchange = "updateArmorPowderSpecials('agi_boost_armor')"> <input type = "range" class = "a_slider" id = "agi_boost_armor" name = "agi-boost-armor" autocomplete = "off" min = '0' max = '150' value = '0' step = '1' onchange = "updateArmorPowderSpecials('agi_boost_armor', true)">
<input type="text" id="agi_boost_armor_prev" autocomplete = "off" value="0" style = "display:none;">
<label id = "agi_boost_armor_label" for="agi-boost-armor">% Air Dmg Boost: 0</label> <label id = "agi_boost_armor_label" for="agi-boost-armor">% Air Dmg Boost: 0</label>
</div> </div>
</div> </div>

View file

@ -147,6 +147,6 @@
<script type="text/javascript" src="../js/expr_parser.js"></script> <script type="text/javascript" src="../js/expr_parser.js"></script>
<script type="text/javascript" src="../js/load.js"></script> <script type="text/javascript" src="../js/load.js"></script>
<script type="text/javascript" src="../js/items.js"></script> <script type="text/javascript" src="../js/items.js"></script>
<script type="text/javascript" src="../js/sq2Items.js"></script> <script type="text/javascript" src="../js/sq2items.js"></script>
</body> </body>
</html> </html>

27
js/computation_graph.js Normal file
View file

@ -0,0 +1,27 @@
class ComputeNode() {
constructor(name) {
this.inputs = [];
this.children = [];
this.value = 0;
this.compute_func = null;
this.callback_func = null;
this.name = name;
}
update() {
let value_map = Map();
for (const input of this.inputs) {
value_map.set(input.name, input.get_value());
}
this.value = this.compute_func(this.value_map);
for (const child of this.children) {
child.update();
}
this.callback_func(this.value);
}
get_value() {
return this.value
}
}

View file

@ -4,7 +4,7 @@ const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["va
// externalStats should be a map // externalStats should be a map
function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier, externalStats) { function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier, externalStats) {
let buildStats = new Map(stats); let buildStats = new Map(stats);
let tooltipinfo = new Map(); let tooltipinfo = new Map();
//6x for damages, normal min normal max crit min crit max //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: = "]]; 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: = "]];

View file

@ -24,6 +24,8 @@ document.addEventListener('DOMContentLoaded', function() {
} }
document.querySelector("#level-choice").setAttribute("oninput", "calcBuildSchedule()") document.querySelector("#level-choice").setAttribute("oninput", "calcBuildSchedule()")
document.querySelector("#weapon-choice").setAttribute("oninput", document.querySelector("#weapon-choice").getAttribute("oninput") + "resetArmorPowderSpecials();");
let skp_fields = document.getElementsByClassName("skp-update"); let skp_fields = document.getElementsByClassName("skp-update");
@ -41,7 +43,7 @@ document.addEventListener('DOMContentLoaded', function() {
margin: { margin: {
x: 20, x: 20,
y: 20, y: 20,
} }
}); });
@ -180,10 +182,6 @@ function update_field(field) {
if (category == 'weapon') { if (category == 'weapon') {
document.querySelector("#weapon-img").setAttribute('src', '../media/items/new/generic-'+type+'.png'); document.querySelector("#weapon-img").setAttribute('src', '../media/items/new/generic-'+type+'.png');
} }
// call calc build
} }
/* tabulars | man i hate this code but too lazy to fix /shrug */ /* tabulars | man i hate this code but too lazy to fix /shrug */

View file

@ -5,6 +5,20 @@ const url_tag = location.hash.slice(1);
const BUILD_VERSION = "7.0.19"; const BUILD_VERSION = "7.0.19";
function setTitle() {
let text;
if (url_base.includes("hppeng-wynn")) {
text = "WynnBuilder UNSTABLE version "+BUILD_VERSION+" (db version "+DB_VERSION+")";
}
else {
text = "WynnBuilder version "+BUILD_VERSION+" (db version "+DB_VERSION+")";
document.getElementById("header").classList.add("funnynumber");
}
document.getElementById("header").textContent = text;
}
setTitle();
let player_build; let player_build;
@ -70,9 +84,6 @@ let powderInputs = [
"weapon-powder", "weapon-powder",
]; ];
//keeps track of the armor powder special sliders. Needed for math. Assumes everything starts at 0.
armor_powder_boosts = [0, 0, 0, 0, 0];
function init() { function init() {
console.log("builder.js init"); console.log("builder.js init");
init_autocomplete(); init_autocomplete();
@ -295,18 +306,6 @@ function encodeBuild() {
function calculateBuild(save_skp, skp){ function calculateBuild(save_skp, skp){
try { try {
/*
let specialNames = ["Quake", "Chain_Lightning", "Curse", "Courage", "Wind_Prison"];
for (const sName of specialNames) {
for (let i = 1; i < 6; i++) {
let elem = document.getElementById(sName + "-" + i);
let name = sName.replace("_", " ");
if (elem.classList.contains("toggleOn")) { //toggle the pressed button off
elem.classList.remove("toggleOn");
}
}
}
*/
if(player_build){ if(player_build){
reset_powder_specials(); reset_powder_specials();
updateBoosts("skip", false); updateBoosts("skip", false);
@ -399,7 +398,6 @@ function calculateBuild(save_skp, skp){
} }
calculateBuildStats(); calculateBuildStats();
// setTitle();
if (player_build.errored) if (player_build.errored)
throw new ListError(player_build.errors); throw new ListError(player_build.errors);
@ -492,7 +490,7 @@ function updateStats() {
for (const s of skp) { for (const s of skp) {
manual_assigned += parseInt(s,10); manual_assigned += parseInt(s,10);
} }
} else { } else {
manual_assigned = parseInt(value,10); manual_assigned = parseInt(value,10);
} }
let delta = manual_assigned - skillpoints[i]; let delta = manual_assigned - skillpoints[i];
@ -503,14 +501,9 @@ function updateStats() {
player_build.assigned_skillpoints += delta_total; player_build.assigned_skillpoints += delta_total;
if(player_build){ if(player_build){
updatePowderSpecials("skip", false); updatePowderSpecials("skip", false);
updateArmorPowderSpecials("skip", false);
updateBoosts("skip", false); updateBoosts("skip", false);
} }
/*
for (let id of editable_item_fields) {
player_build.statMap.set(id, parseInt(getValue(id)));
console.log(player_build.statMap.get(id));
}
}*/
player_build.aggregateStats(); player_build.aggregateStats();
console.log(player_build.statMap); console.log(player_build.statMap);
calculateBuildStats(); calculateBuildStats();
@ -648,33 +641,68 @@ function updatePowderSpecials(buttonId, recalcStats) {
/* Updates PASSIVE powder special boosts (armors) /* Updates PASSIVE powder special boosts (armors)
*/ */
function updateArmorPowderSpecials(elem_id) { function updateArmorPowderSpecials(elem_id, recalc_stats) {
let wynn_elem = elem_id.split("_")[0]; //str, dex, int, def, agi //we only update the powder special + external stats if the player has a build
if (elem_id !== "skip") {
if (player_build !== undefined && player_build.weapon !== undefined && player_build.weapon.get("name") !== "No Weapon") {
let wynn_elem = elem_id.split("_")[0]; //str, dex, int, def, agi
//update the label associated w/ the slider //update the label associated w/ the slider
let elem = document.getElementById(elem_id); let elem = document.getElementById(elem_id);
let value = elem.value; let label = document.getElementById(elem_id + "_label");
let prev_label = document.getElementById(elem_id + "_prev");
let label = document.getElementById(elem_id + "_label");
label.textContent = label.textContent.split(":")[0] + ": " + value;
if (player_build) { let value = elem.value;
let dmg_id = elem_chars[skp_names.indexOf(wynn_elem)] + "DamPct";
let new_dmgboost = player_build.externalStats.get(dmg_id) + (value - armor_powder_boosts[skp_names.indexOf(wynn_elem)]);
armor_powder_boosts[skp_names.indexOf(wynn_elem)] = value;
//update build stats
player_build.externalStats.set(dmg_id, new_dmgboost);
//for use in editing build stats
let prev_value = prev_label.value;
let value_diff = value - prev_value;
//update the "previous" label
prev_label.value = value;
label.textContent = label.textContent.split(":")[0] + ": " + value;
let dmg_id = elem_chars[skp_names.indexOf(wynn_elem)] + "DamPct";
let new_dmgboost = player_build.externalStats.get(dmg_id) + value_diff;
//update build external stats - the second one is the relevant one for damage calc purposes
player_build.externalStats.set(dmg_id, new_dmgboost);
player_build.externalStats.get("damageBonus")[skp_names.indexOf(wynn_elem)] = new_dmgboost;
//update the slider's graphics
let bg_color = elem_colors[skp_names.indexOf(wynn_elem)];
let pct = Math.round(100 * value / powderSpecialStats[skp_names.indexOf(wynn_elem)].cap);
elem.style.background = `linear-gradient(to right, ${bg_color}, ${bg_color} ${pct}%, #AAAAAA ${pct}%, #AAAAAA 100%)`;
}
} else {
if (player_build !== undefined) {
for (let i = 0; i < skp_names.length; ++i) {
skp_name = skp_names[i];
skp_char = elem_chars[i];
player_build.externalStats.set(skp_char + "DamPct", player_build.externalStats.get(skp_char + "DamPct") - document.getElementById(skp_name+"_boost_armor").value);
player_build.externalStats.get("damageBonus")[i] -= document.getElementById(skp_name+"_boost_armor").value;
}
}
}
if (recalc_stats && player_build) {
//calc build stats and display powder special //calc build stats and display powder special
calculateBuildStats(); calculateBuildStats();
// displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true); // displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true);
} }
//update the slider's graphics }
let bg_color = elem_colors[skp_names.indexOf(wynn_elem)];
let pct = Math.round(100 * value / powderSpecialStats[skp_names.indexOf(wynn_elem)].cap); function resetArmorPowderSpecials() {
elem.style.background = `linear-gradient(to right, ${bg_color}, ${bg_color} ${pct}%, #AAAAAA ${pct}%, #AAAAAA 100%)`; for (const skp of skp_names) {
document.getElementById(skp + "_boost_armor").value = 0;
document.getElementById(skp + "_boost_armor_prev").value = 0;
document.getElementById(skp + "_boost_armor").style.background = `linear-gradient(to right, #AAAAAA, #AAAAAA 0%, #AAAAAA 100%)`;
document.getElementById(skp + "_boost_armor_label").textContent = `% ${capitalizeFirst(elem_names[skpnames.indexOf(skp)])} Damage Boost: 0`
}
} }
/* Calculates all build statistics and updates the entire display. /* Calculates all build statistics and updates the entire display.
@ -704,7 +732,6 @@ function calculateBuildStats() {
let summarybox = document.getElementById("summary-box"); let summarybox = document.getElementById("summary-box");
summarybox.textContent = ""; summarybox.textContent = "";
let skpRow = document.createElement("p"); let skpRow = document.createElement("p");
// let td = document.createElement("p");
let remainingSkp = document.createElement("p"); let remainingSkp = document.createElement("p");
remainingSkp.classList.add("scaled-font"); remainingSkp.classList.add("scaled-font");
@ -724,11 +751,9 @@ function calculateBuildStats() {
let skpWarning = document.createElement("span"); let skpWarning = document.createElement("span");
//skpWarning.classList.add("itemp"); //skpWarning.classList.add("itemp");
skpWarning.classList.add("warning"); skpWarning.classList.add("warning");
// skpWarning.classList.add("skp-tooltip");
skpWarning.textContent = "WARNING: Too many skillpoints need to be assigned!"; skpWarning.textContent = "WARNING: Too many skillpoints need to be assigned!";
let skpCount = document.createElement("p"); let skpCount = document.createElement("p");
skpCount.classList.add("warning"); skpCount.classList.add("warning");
// skpCount.classList.add("skp-tooltip");
skpCount.textContent = "For level " + (player_build.level>101 ? "101+" : player_build.level) + ", there are only " + levelToSkillPoints(player_build.level) + " skill points available."; skpCount.textContent = "For level " + (player_build.level>101 ? "101+" : player_build.level) + ", there are only " + levelToSkillPoints(player_build.level) + " skill points available.";
summarybox.append(skpWarning); summarybox.append(skpWarning);
summarybox.append(skpCount); summarybox.append(skpCount);
@ -774,9 +799,6 @@ function calculateBuildStats() {
} }
for (let i in player_build.items) { for (let i in player_build.items) {
// if (player_build.items[i].get("id") > 9999) {
// continue;
// }
displaysq2ExpandedItem(player_build.items[i], buildFields[i]); displaysq2ExpandedItem(player_build.items[i], buildFields[i]);
collapse_element("#"+equipment_keys[i]+"-tooltip"); collapse_element("#"+equipment_keys[i]+"-tooltip");
} }
@ -1017,4 +1039,4 @@ function optimizeStrDex() {
function init2() { function init2() {
load_ing_init(init); load_ing_init(init);
} }
load_init(init2); load_init(init2);

View file

@ -41,7 +41,7 @@ function displaysq2BuildStats(parent_id,build,command_group){
// id instruction // id instruction
else { else {
let id = command; let id = command;
if (stats.get(id)) { if (stats.get(id) || build.externalStats.get(id)) {
let style = null; let style = null;
// TODO: add pos and neg style // TODO: add pos and neg style
@ -54,6 +54,10 @@ function displaysq2BuildStats(parent_id,build,command_group){
// ignore // ignore
let id_val = stats.get(id); let id_val = stats.get(id);
if (build.externalStats.has(id)) {
id_val += build.externalStats.get(id);
}
if (reversedIDs.includes(id)) { if (reversedIDs.includes(id)) {
style === "positive" ? style = "negative" : style = "positive"; style === "positive" ? style = "negative" : style = "positive";
} }

View file

@ -30,6 +30,14 @@ let elem_chars = [
'a' 'a'
] ]
let elem_names = [
'earth',
'thunder',
'water',
'fire',
'air'
]
let elem_colors = [ let elem_colors = [
"#00AA00", "#00AA00",
"#FFFF55", "#FFFF55",

View file

@ -409,3 +409,7 @@ async function hardReload() {
location.reload(true); location.reload(true);
} }
function capitalizeFirst(str) {
return str.charAt(0).toUpperCase + str.slice(1);
}