From 06f745c158b8da65c0201bba1f85b3a6cbad47b5 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 22 May 2022 00:57:47 -0700 Subject: [PATCH] Consolidate constants/utils files, start working on new builder file --- builder/index.html | 4 +- js/build_constants.js | 106 +++++++ js/build_utils.js | 3 +- js/builder.js | 607 +++++++++++++++++++--------------------- js/computation_graph.js | 13 +- js/display_constants.js | 1 - js/sq2bs.js | 14 +- js/sq2builder.js | 21 +- 8 files changed, 405 insertions(+), 364 deletions(-) create mode 100644 js/build_constants.js diff --git a/builder/index.html b/builder/index.html index c49ccb4..7a89a26 100644 --- a/builder/index.html +++ b/builder/index.html @@ -1379,6 +1379,7 @@ + @@ -1399,7 +1400,8 @@ - + + diff --git a/js/build_constants.js b/js/build_constants.js new file mode 100644 index 0000000..fbcbb3f --- /dev/null +++ b/js/build_constants.js @@ -0,0 +1,106 @@ +/** + * I kinda lied. Theres some listener stuff in here + * but its mostly constants for builder page specifically. + */ + +const url_tag = location.hash.slice(1); + +const BUILD_VERSION = "7.0.19"; + +let player_build; + + +// THIS IS SUPER DANGEROUS, WE SHOULD NOT BE KEEPING THIS IN SO MANY PLACES +let editable_item_fields = [ "sdPct", "sdRaw", "mdPct", "mdRaw", "poison", + "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", + "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", + "hprRaw", "hprPct", "hpBonus", "atkTier", + "spPct1", "spRaw1", "spPct2", "spRaw2", + "spPct3", "spRaw3", "spPct4", "spRaw4" ]; + +let editable_elems = []; + +for (let i of editable_item_fields) { + let elem = document.getElementById(i); + elem.addEventListener("change", (event) => { + elem.classList.add("highlight"); + }); + editable_elems.push(elem); +} + +for (let i of skp_order) { + let elem = document.getElementById(i+"-skp"); + elem.addEventListener("change", (event) => { + elem.classList.add("highlight"); + }); + editable_elems.push(elem); +} + +function clear_highlights() { + for (let i of editable_elems) { + i.classList.remove("highlight"); + } +} + + +let equipment_fields = [ + "helmet", + "chestplate", + "leggings", + "boots", + "ring1", + "ring2", + "bracelet", + "necklace", + "weapon" +]; +let tome_fields = [ + "weaponTome1", + "weaponTome2", + "armorTome1", + "armorTome2", + "armorTome3", + "armorTome4", + "guildTome1", +] +let equipment_names = [ + "Helmet", + "Chestplate", + "Leggings", + "Boots", + "Ring 1", + "Ring 2", + "Bracelet", + "Necklace", + "Weapon" +]; + +let tome_names = [ + "Weapon Tome", + "Weapon Tome", + "Armor Tome", + "Armor Tome", + "Armor Tome", + "Armor Tome", + "Guild Tome", +] +let equipmentInputs = equipment_fields.map(x => x + "-choice"); +let buildFields = equipment_fields.map(x => x+"-tooltip").concat(tome_fields.map(x => x + "-tooltip")); +let tomeInputs = tome_fields.map(x => x + "-choice"); + +let powderInputs = [ + "helmet-powder", + "chestplate-powder", + "leggings-powder", + "boots-powder", + "weapon-powder", +]; + +let weapon_keys = ['dagger', 'wand', 'bow', 'relik', 'spear']; +let armor_keys = ['helmet', 'chestplate', 'leggings', 'boots']; +let accessory_keys= ['ring1', 'ring2', 'bracelet', 'necklace']; +let powderable_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'weapon']; +let equipment_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace', 'weapon'].concat(tome_keys); + +let spell_disp = ['spell0-info', 'spell1-info', 'spell2-info', 'spell3-info']; +let other_disp = ['build-order', 'set-info', 'int-info']; diff --git a/js/build_utils.js b/js/build_utils.js index e60474b..9381035 100644 --- a/js/build_utils.js +++ b/js/build_utils.js @@ -138,6 +138,7 @@ let rolledIDs = [ "gXp", "gSpd" ]; +let reversedIDs = [ "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; /** * Take an item with id list and turn it into a set of minrolls and maxrolls. @@ -186,7 +187,7 @@ function expandItem(item) { } expandedItem.set("minRolls",minRolls); expandedItem.set("maxRolls",maxRolls); - expandedItem.set("powders", powders); + expandedItem.set("powders", []); return expandedItem; } diff --git a/js/builder.js b/js/builder.js index a91ef19..3455ee2 100644 --- a/js/builder.js +++ b/js/builder.js @@ -1,182 +1,3 @@ -const url_tag = location.hash.slice(1); -// console.log(url_base); -// console.log(url_tag); - - -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 editable_item_fields = [ "sdPct", "sdRaw", "mdPct", "mdRaw", "poison", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "hprRaw", "hprPct", "hpBonus", "atkTier", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; -let editable_elems = []; - -for (let i of editable_item_fields) { - let elem = document.getElementById(i); - elem.addEventListener("change", (event) => { - elem.classList.add("highlight"); - }); - editable_elems.push(elem); -} - -for (let i of skp_order) { - let elem = document.getElementById(i+"-skp"); - elem.addEventListener("change", (event) => { - elem.classList.add("highlight"); - }); - editable_elems.push(elem); -} - -function clear_highlights() { - for (let i of editable_elems) { - i.classList.remove("highlight"); - } -} - - -let equipment_fields = [ - "helmet", - "chestplate", - "leggings", - "boots", - "ring1", - "ring2", - "bracelet", - "necklace", - "weapon" -]; -let equipment_names = [ - "Helmet", - "Chestplate", - "Leggings", - "Boots", - "Ring 1", - "Ring 2", - "Bracelet", - "Necklace", - "Weapon" -]; -let equipmentInputs = equipment_fields.map(x => x + "-choice"); -let buildFields = equipment_fields.map(x => "build-"+x); - -let powderInputs = [ - "helmet-powder", - "chestplate-powder", - "leggings-powder", - "boots-powder", - "weapon-powder", -]; - - - -/* - * Function that takes an item list and populates its corresponding dropdown. - * Used for armors and bracelet/necklace. - */ -function populateItemList(type) { - let item_list = document.getElementById(type+"-items"); - for (const item of itemLists.get(type)) { - let item_obj = itemMap.get(item); - if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") { - continue; - } - let el = document.createElement("option"); - el.value = item; - item_list.appendChild(el); - } -} - -/* - * Populate dropdowns, add listeners, etc. - */ -function init() { - console.log("builder.js init"); - - for (const armorType of armorTypes) { - populateItemList(armorType); - // Add change listener to update armor slots. - document.getElementById(armorType+"-choice").addEventListener("change", (event) => { - let item_name = event.target.value; - let nSlots = undefined; - if (itemMap.has(item_name)) { - let item = itemMap.get(item_name); - nSlots = item["slots"]; - //console.log(item); - } - else { - let crafted_custom_item = getCraftFromHash(item_name) !== undefined ? getCraftFromHash(item_name) : (getCustomFromHash(item_name) !== undefined ? getCustomFromHash(item_name) : undefined); - if (crafted_custom_item !== undefined) { - nSlots = crafted_custom_item.statMap.get("slots"); - } - } - if (nSlots !== undefined) { - document.getElementById(armorType+"-slots").textContent = nSlots + " slots"; - } - else { - document.getElementById(armorType+"-slots").textContent = "X slots"; - } - }); - } - - let ring1_list = document.getElementById("ring1-items"); - let ring2_list = document.getElementById("ring2-items"); - for (const ring of itemLists.get("ring")) { - let item_obj = itemMap.get(ring); - if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") { - continue; - } - let el1 = document.createElement("option"); - let el2 = document.createElement("option"); - el1.value = ring; - el2.value = ring; - ring1_list.appendChild(el1); - ring2_list.appendChild(el2); - } - - populateItemList("bracelet"); - populateItemList("necklace"); - - let weapon_list = document.getElementById("weapon-items"); - for (const weaponType of weaponTypes) { - for (const weapon of itemLists.get(weaponType)) { - let item_obj = itemMap.get(weapon); - if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") { - continue; - } - let el = document.createElement("option"); - el.value = weapon; - weapon_list.appendChild(el); - } - } - - // Add change listener to update weapon slots. - document.getElementById("weapon-choice").addEventListener("change", (event) => { - let item_name = event.target.value; - let item = itemMap.has(item_name) ? itemMap.get(item_name) : (getCraftFromHash(item_name) ? getCraftFromHash(item_name) : (getCustomFromHash(item_name) ? getCustomFromHash(item_name) : undefined)); - if (item !== undefined && event.target.value !== "") { - document.getElementById("weapon-slots").textContent = (item["slots"] ? item["slots"] : (item.statMap !== undefined ? ( item.statMap.has("slots") ? item.statMap.get("slots") : 0): 0) )+ " slots"; - } else { - document.getElementById("weapon-slots").textContent = "X slots"; - } - }); - - decodeBuild(url_tag); - - populateBuildList(); -} function getItemNameFromID(id) { if (redirectMap.has(id)) { @@ -185,13 +6,20 @@ function getItemNameFromID(id) { return idMap.get(id); } +function getTomeNameFromID(id) { + if (tomeRedirectMap.has(id)) { + return getTomeNameFromID(tomeRedirectMap.get(id)); + } + return tomeIDMap.get(id); +} + function parsePowdering(powder_info) { // TODO: Make this run in linear instead of quadratic time... ew let powdering = []; for (let i = 0; i < 5; ++i) { let powders = ""; let n_blocks = Base64.toInt(powder_info.charAt(0)); - console.log(n_blocks + " blocks"); + // console.log(n_blocks + " blocks"); powder_info = powder_info.slice(1); for (let j = 0; j < n_blocks; ++j) { let block = powder_info.slice(0,5); @@ -205,7 +33,7 @@ function parsePowdering(powder_info) { } powdering[i] = powders; } - return powdering; + return [powdering, powder_info]; } /* @@ -213,14 +41,20 @@ function parsePowdering(powder_info) { */ function decodeBuild(url_tag) { if (url_tag) { + //default values let equipment = [null, null, null, null, null, null, null, null, null]; + let tomes = [null, null, null, null, null, null, null]; let powdering = ["", "", "", "", ""]; let info = url_tag.split("_"); let version = info[0]; let save_skp = false; let skillpoints = [0, 0, 0, 0, 0]; let level = 106; - if (version === "0" || version === "1" || version === "2" || version === "3") { + + version_number = parseInt(version) + //equipment (items) + // TODO: use filters + if (version_number < 4) { let equipments = info[1]; for (let i = 0; i < 9; ++i ) { let equipment_str = equipments.slice(i*3,i*3+3); @@ -228,7 +62,7 @@ function decodeBuild(url_tag) { } info[1] = equipments.slice(27); } - if (version === "4") { + else if (version_number == 4) { let info_str = info[1]; let start_idx = 0; for (let i = 0; i < 9; ++i ) { @@ -244,7 +78,7 @@ function decodeBuild(url_tag) { } info[1] = info_str.slice(start_idx); } - if (version === "5") { + else if (version_number <= 6) { let info_str = info[1]; let start_idx = 0; for (let i = 0; i < 9; ++i ) { @@ -263,10 +97,17 @@ function decodeBuild(url_tag) { } info[1] = info_str.slice(start_idx); } - if (version === "1") { + //constant in all versions + for (let i in equipment) { + setValue(equipmentInputs[i], equipment[i]); + } + + //level, skill point assignments, and powdering + if (version_number == 1) { let powder_info = info[1]; - powdering = parsePowdering(powder_info); - } else if (version === "2") { + let res = parsePowdering(powder_info); + powdering = res[0]; + } else if (version_number == 2) { save_skp = true; let skillpoint_info = info[1].slice(0, 10); for (let i = 0; i < 5; ++i ) { @@ -274,8 +115,9 @@ function decodeBuild(url_tag) { } let powder_info = info[1].slice(10); - powdering = parsePowdering(powder_info); - } else if (version === "3" || version === "4" || version === "5"){ + let res = parsePowdering(powder_info); + powdering = res[0]; + } else if (version_number <= 6){ level = Base64.toInt(info[1].slice(10,12)); setValue("level-choice",level); save_skp = true; @@ -286,126 +128,101 @@ function decodeBuild(url_tag) { let powder_info = info[1].slice(12); - powdering = parsePowdering(powder_info); + let res = parsePowdering(powder_info); + powdering = res[0]; + info[1] = res[1]; + } + // Tomes. + if (version == 6) { + //tome values do not appear in anything before v6. + for (let i = 0; i < 7; ++i) { + let tome_str = info[1].charAt(i); + for (let i in tomes) { + setValue(tomeInputs[i], getTomeNameFromID(Base64.toInt(tome_str))); + } + } + info[1] = info[1].slice(7); } for (let i in powderInputs) { setValue(powderInputs[i], powdering[i]); } - for (let i in equipment) { - setValue(equipmentInputs[i], equipment[i]); - } + calculateBuild(save_skp, skillpoints); } } -/* Stores the entire build in a string using B64 encryption and adds it to the URL. +/* Stores the entire build in a string using B64 encoding and adds it to the URL. */ function encodeBuild() { if (player_build) { let build_string; - if (player_build.customItems.length > 0) { //v5 encoding - build_string = "5_"; - let crafted_idx = 0; - let custom_idx = 0; - for (const item of player_build.items) { - - if (item.get("custom")) { - let custom = "CI-"+encodeCustom(player_build.customItems[custom_idx],true); - build_string += Base64.fromIntN(custom.length, 3) + custom; - custom_idx += 1; - } else if (item.get("crafted")) { - build_string += "CR-"+encodeCraft(player_build.craftedItems[crafted_idx]); - crafted_idx += 1; - } else { - build_string += Base64.fromIntN(item.get("id"), 3); - } - } - - for (const skp of skp_order) { - build_string += Base64.fromIntN(getValue(skp + "-skp"), 2); // Maximum skillpoints: 2048 - } - build_string += Base64.fromIntN(player_build.level, 2); - for (const _powderset of player_build.powders) { - let n_bits = Math.ceil(_powderset.length / 6); - build_string += Base64.fromIntN(n_bits, 1); // Hard cap of 378 powders. - // Slice copy. - let powderset = _powderset.slice(); - while (powderset.length != 0) { - let firstSix = powderset.slice(0,6).reverse(); - let powder_hash = 0; - for (const powder of firstSix) { - powder_hash = (powder_hash << 5) + 1 + powder; // LSB will be extracted first. - } - build_string += Base64.fromIntN(powder_hash, 5); - powderset = powderset.slice(6); - } - } - } else { //v4 encoding - build_string = "4_"; - let crafted_idx = 0; - for (const item of player_build.items) { - if (item.get("crafted")) { - build_string += "-"+encodeCraft(player_build.craftedItems[crafted_idx]); - crafted_idx += 1; - } else { - build_string += Base64.fromIntN(item.get("id"), 3); - } - } - - for (const skp of skp_order) { - build_string += Base64.fromIntN(getValue(skp + "-skp"), 2); // Maximum skillpoints: 2048 - } - build_string += Base64.fromIntN(player_build.level, 2); - for (const _powderset of player_build.powders) { - let n_bits = Math.ceil(_powderset.length / 6); - build_string += Base64.fromIntN(n_bits, 1); // Hard cap of 378 powders. - // Slice copy. - let powderset = _powderset.slice(); - while (powderset.length != 0) { - let firstSix = powderset.slice(0,6).reverse(); - let powder_hash = 0; - for (const powder of firstSix) { - powder_hash = (powder_hash << 5) + 1 + powder; // LSB will be extracted first. - } - build_string += Base64.fromIntN(powder_hash, 5); - powderset = powderset.slice(6); + + //V6 encoding - Tomes + build_version = 4; + build_string = ""; + tome_string = ""; + + let crafted_idx = 0; + let custom_idx = 0; + for (const item of player_build.items) { + + if (item.get("custom")) { + let custom = "CI-"+encodeCustom(player_build.customItems[custom_idx],true); + build_string += Base64.fromIntN(custom.length, 3) + custom; + custom_idx += 1; + build_version = Math.max(build_version, 5); + } else if (item.get("crafted")) { + build_string += "CR-"+encodeCraft(player_build.craftedItems[crafted_idx]); + crafted_idx += 1; + } else if (item.get("category") === "tome") { + let tome_id = item.get("id"); + if (tome_id <= 60) { + // valid normal tome. ID 61-63 is for NONE tomes. + build_version = Math.max(build_version, 6); } + tome_string += Base64.fromIntN(tome_id, 1); + } else { + build_string += Base64.fromIntN(item.get("id"), 3); } } - return build_string; + + for (const skp of skp_order) { + build_string += Base64.fromIntN(getValue(skp + "-skp"), 2); // Maximum skillpoints: 2048 + } + build_string += Base64.fromIntN(player_build.level, 2); + for (const _powderset of player_build.powders) { + let n_bits = Math.ceil(_powderset.length / 6); + build_string += Base64.fromIntN(n_bits, 1); // Hard cap of 378 powders. + // Slice copy. + let powderset = _powderset.slice(); + while (powderset.length != 0) { + let firstSix = powderset.slice(0,6).reverse(); + let powder_hash = 0; + for (const powder of firstSix) { + powder_hash = (powder_hash << 5) + 1 + powder; // LSB will be extracted first. + } + build_string += Base64.fromIntN(powder_hash, 5); + powderset = powderset.slice(6); + } + } + build_string += tome_string; + + return build_version.toString() + "_" + build_string; } - // this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ]; - // let build_string = "3_" + Base64.fromIntN(player_build.helmet.get("id"), 3) + - // Base64.fromIntN(player_build.chestplate.get("id"), 3) + - // Base64.fromIntN(player_build.leggings.get("id"), 3) + - // Base64.fromIntN(player_build.boots.get("id"), 3) + - // Base64.fromIntN(player_build.ring1.get("id"), 3) + - // Base64.fromIntN(player_build.ring2.get("id"), 3) + - // Base64.fromIntN(player_build.bracelet.get("id"), 3) + - // Base64.fromIntN(player_build.necklace.get("id"), 3) + - // Base64.fromIntN(player_build.weapon.get("id"), 3); - return ""; } function calculateBuild(save_skp, skp){ 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){ + resetEditableIDs(); + if (player_build) { + reset_powder_specials(); updateBoosts("skip", false); updatePowderSpecials("skip", false); } let weaponName = getValue(equipmentInputs[8]); + //bruh @hpp if (weaponName.startsWith("Morph-")) { let equipment = [ "Morph-Stardust", "Morph-Steel", "Morph-Iron", "Morph-Gold", "Morph-Topaz", "Morph-Emerald", "Morph-Amethyst", "Morph-Ruby", weaponName.substring(6) ]; for (let i in equipment) { @@ -440,7 +257,6 @@ function calculateBuild(save_skp, skp){ while (input) { let first = input.slice(0, 2); let powder = powderIDs.get(first); - console.log(powder); if (powder === undefined) { errorederrors.push(first); } else { @@ -457,11 +273,24 @@ function calculateBuild(save_skp, skp){ //console.log("POWDERING: " + powdering); powderings.push(powdering); } + let tomes = [ null, null, null, null, null, null, null]; + for (let i in tomes) { + let equip = getValue(tomeInputs[i]).trim(); + if (equip === "") { + equip = "No " + tome_names[i] + } + else { + setValue(tomeInputs[i], equip); + } + tomes[i] = equip; + } let level = document.getElementById("level-choice").value; - player_build = new Build(level, equipment, powderings, new Map(), errors); + player_build = new Build(level, equipment, powderings, new Map(), errors, tomes); console.log(player_build); + + //isn't this deprecated? for (let i of document.getElementsByClassName("hide-container-block")) { i.style.display = "block"; } @@ -470,21 +299,14 @@ function calculateBuild(save_skp, skp){ } console.log(player_build.toString()); - displayEquipOrder(document.getElementById("build-order"),player_build.equip_order); - - + displaysq2EquipOrder(document.getElementById("build-order"),player_build.equip_order); const assigned = player_build.base_skillpoints; const skillpoints = player_build.total_skillpoints; for (let i in skp_order){ //big bren - setText(skp_order[i] + "-skp-base", "Original Value: " + skillpoints[i]); + setText(skp_order[i] + "-skp-base", "Original: " + skillpoints[i]); } - for (let id of editable_item_fields) { - setValue(id, player_build.statMap.get(id)); - setText(id+"-base", "Original Value: " + player_build.statMap.get(id)); - } - if (save_skp) { // TODO: reduce duplicated code, @updateStats let skillpoints = player_build.total_skillpoints; @@ -499,14 +321,13 @@ function calculateBuild(save_skp, skp){ player_build.assigned_skillpoints += delta_total; } + updateEditableIDs(); calculateBuildStats(); - setTitle(); if (player_build.errored) throw new ListError(player_build.errors); - } catch (error) { - handleBuilderError(error); + console.log(error); } } @@ -586,7 +407,7 @@ function updateStats() { let delta_total = 0; for (let i in skp_order) { let value = document.getElementById(skp_order[i] + "-skp").value; - if (value === ""){value = "0"; setValue(skp_order[i] + "-skp", value)} + if (value === ""){value = 0; setValue(skp_order[i] + "-skp", value)} let manual_assigned = 0; if (value.includes("+")) { let skp = value.split("+"); @@ -604,15 +425,58 @@ function updateStats() { player_build.assigned_skillpoints += delta_total; if(player_build){ updatePowderSpecials("skip", false); + updateArmorPowderSpecials("skip", false); updateBoosts("skip", false); - } - for (let id of editable_item_fields) { - player_build.statMap.set(id, parseInt(getValue(id))); + for (let id of editable_item_fields) { + player_build.statMap.set(id, parseInt(getValue(id))); + } } player_build.aggregateStats(); console.log(player_build.statMap); calculateBuildStats(); } + + +/* Updates all IDs in the edit IDs section. Resets each input and original value text to the correct text according to the current build. +*/ +function updateEditableIDs() { + if (player_build) { + for (const id of editable_item_fields) { + let edit_input = document.getElementById(id); + let val = player_build.statMap.get(id); + edit_input.value = val; + edit_input.placeholder = val; + + let value_label = document.getElementById(id + "-base"); + value_label.textContent = "Original Value: " + val; + //a hack to make resetting easier + value_label.value = val; + } + } +} + +/* Resets all IDs in the edit IDs section to their "original" values. +*/ +function resetEditableIDs() { + if (player_build) { + for (const id of editable_item_fields) { + let edit_input = document.getElementById(id); + let value_label = document.getElementById(id + "-base"); + + edit_input.value = value_label.value; + edit_input.placeholder = value_label.value; + } + } else { + //no player build, reset to 0 + for (const id of editable_item_fields) { + let edit_input = document.getElementById(id); + + edit_input.value = 0; + edit_input.placeholder = 0; + } + } +} + /* Updates all spell boosts */ function updateBoosts(buttonId, recalcStats) { @@ -655,7 +519,7 @@ function updateBoosts(buttonId, recalcStats) { } } -/* Updates all powder special boosts +/* Updates ACTIVE powder special boosts (weapons) */ function updatePowderSpecials(buttonId, recalcStats) { //console.log(player_build.statMap); @@ -740,8 +604,76 @@ function updatePowderSpecials(buttonId, recalcStats) { if (recalcStats) { calculateBuildStats(); } - displayPowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build); + displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true); } + + +/* Updates PASSIVE powder special boosts (armors) +*/ +function updateArmorPowderSpecials(elem_id, recalc_stats) { + //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 + let elem = document.getElementById(elem_id); + let label = document.getElementById(elem_id + "_label"); + let prev_label = document.getElementById(elem_id + "_prev"); + + let value = elem.value; + + //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 + calculateBuildStats(); + // displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true); + } + +} + +function resetArmorPowderSpecials() { + 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[skp_names.indexOf(skp)])} Damage Boost: 0` + } +} + /* Calculates all build statistics and updates the entire display. */ function calculateBuildStats() { @@ -749,27 +681,29 @@ function calculateBuildStats() { const skillpoints = player_build.total_skillpoints; let skp_effects = ["% more damage dealt.","% chance to crit.","% spell cost reduction.","% less damage taken.","% chance to dodge."]; for (let i in skp_order){ //big bren - setText(skp_order[i] + "-skp-assign", "Manually Assigned: " + assigned[i]); + setText(skp_order[i] + "-skp-assign", "Assign: " + assigned[i]); setValue(skp_order[i] + "-skp", skillpoints[i]); let linebreak = document.createElement("br"); linebreak.classList.add("itemp"); document.getElementById(skp_order[i] + "-skp-label"); setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100).toFixed(1).concat(skp_effects[i])); + document.getElementById(skp_order[i]+"-warnings").textContent = '' if (assigned[i] > 100) { let skp_warning = document.createElement("p"); skp_warning.classList.add("warning"); - skp_warning.textContent += "WARNING: Cannot assign " + assigned[i] + " skillpoints in " + ["Strength","Dexterity","Intelligence","Defense","Agility"][i] + " manually."; - document.getElementById(skp_order[i]+"-skp-pct").appendChild(skp_warning); + skp_warning.classList.add("small-text") + skp_warning.textContent += "Cannot assign " + assigned[i] + " skillpoints in " + ["Strength","Dexterity","Intelligence","Defense","Agility"][i] + " manually."; + document.getElementById(skp_order[i]+"-warnings").textContent = '' + document.getElementById(skp_order[i]+"-warnings").appendChild(skp_warning); } } let summarybox = document.getElementById("summary-box"); summarybox.textContent = ""; let skpRow = document.createElement("p"); - let td = document.createElement("p"); let remainingSkp = document.createElement("p"); - remainingSkp.classList.add("center"); + remainingSkp.classList.add("scaled-font"); let remainingSkpTitle = document.createElement("b"); remainingSkpTitle.textContent = "Assigned " + player_build.assigned_skillpoints + " skillpoints. Remaining skillpoints: "; let remainingSkpContent = document.createElement("b"); @@ -783,13 +717,12 @@ function calculateBuildStats() { summarybox.append(skpRow); summarybox.append(remainingSkp); if(player_build.assigned_skillpoints > levelToSkillPoints(player_build.level)){ - let skpWarning = document.createElement("p"); + let skpWarning = document.createElement("span"); //skpWarning.classList.add("itemp"); skpWarning.classList.add("warning"); - skpWarning.classList.add("itemp"); skpWarning.textContent = "WARNING: Too many skillpoints need to be assigned!"; let skpCount = document.createElement("p"); - skpCount.classList.add("itemp"); + skpCount.classList.add("warning"); 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(skpCount); @@ -826,7 +759,6 @@ function calculateBuildStats() { const bonus = sets[setName].bonuses[count-1]; // console.log(setName); if (bonus["illegal"]) { - console.log("mmmm"); let setWarning = document.createElement("p"); setWarning.classList.add("itemp"); setWarning.classList.add("warning"); @@ -836,30 +768,32 @@ function calculateBuildStats() { } for (let i in player_build.items) { - displayExpandedItem(player_build.items[i], buildFields[i]); + displaysq2ExpandedItem(player_build.items[i], buildFields[i]); + collapse_element("#"+equipment_keys[i]+"-tooltip"); } - displayBuildStats("build-overall-stats",player_build); - displaySetBonuses("set-info",player_build); - displayNextCosts("int-info",player_build); + displaysq2ArmorStats(player_build); + displaysq2BuildStats('overall-stats', player_build, build_all_display_commands); + displaysq2BuildStats("offensive-stats",player_build, build_offensive_display_commands); + displaysq2SetBonuses("set-info",player_build); + displaysq2WeaponStats(player_build); let meleeStats = player_build.getMeleeStats(); - displayMeleeDamage(document.getElementById("build-melee-stats"), document.getElementById("build-melee-statsAvg"), meleeStats); + displaysq2MeleeDamage(document.getElementById("build-melee-stats"), document.getElementById("build-melee-statsAvg"), meleeStats); - displayDefenseStats(document.getElementById("build-defense-stats"),player_build); + displaysq2DefenseStats(document.getElementById("defensive-stats"),player_build); - displayPoisonDamage(document.getElementById("build-poison-stats"),player_build); + displaysq2PoisonDamage(document.getElementById("build-poison-stats"),player_build); let spells = spell_table[player_build.weapon.get("type")]; for (let i = 0; i < 4; ++i) { let parent_elem = document.getElementById("spell"+i+"-info"); let overallparent_elem = document.getElementById("spell"+i+"-infoAvg"); - displaySpellDamage(parent_elem, overallparent_elem, player_build, spells[i], i+1); + displaysq2SpellDamage(parent_elem, overallparent_elem, player_build, spells[i], i+1); } location.hash = encodeBuild(); clear_highlights(); - updateOGP(); } function copyBuild() { @@ -971,7 +905,21 @@ function toggleID() { } } +function toggleButton(button_id) { + let button = document.getElementById(button_id); + if (button) { + if (button.classList.contains("toggleOn")) { + button.classList.remove("toggleOn"); + } else { + button.classList.add("toggleOn"); + } + } +} + function optimizeStrDex() { + if (!player_build) { + return; + } const remaining = levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints; const base_skillpoints = player_build.base_skillpoints; const max_str_boost = 100 - base_skillpoints[0]; @@ -1061,7 +1009,6 @@ function optimizeStrDex() { try { calculateBuildStats(); - setTitle(); if (player_build.errored) throw new ListError(player_build.errors); } @@ -1071,8 +1018,20 @@ function optimizeStrDex() { } // TODO: Learn and use await +function init() { + console.log("builder.js init"); + init_autocomplete(); + decodeBuild(url_tag); + for (const i of equipment_keys) { + update_field(i); + } +} function init2() { load_ing_init(init); } -load_init(init2); -updateOGP(); \ No newline at end of file +function init3() { + load_tome_init(init2) +} + + +load_init(init3); diff --git a/js/computation_graph.js b/js/computation_graph.js index cdd1212..9039685 100644 --- a/js/computation_graph.js +++ b/js/computation_graph.js @@ -1,5 +1,3 @@ -let _ALL_NODES = new Map(); - class ComputeNode { /** * Make a generic compute node. @@ -8,10 +6,6 @@ class ComputeNode { * @param name : Name of the node (string). Must be unique. Must "fit in" a JS string (terminated by single quotes). */ constructor(name) { - if (_ALL_NODES.has(name)) { - throw 'Duplicate node name: ' + name; - } - _ALL_NODES.set(name, this) this.inputs = []; this.children = []; this.value = 0; @@ -65,10 +59,9 @@ class ComputeNode { /** * Schedule a ComputeNode to be updated. * - * @param node_name : ComputeNode name to schedule an update for. + * @param node : ComputeNode to schedule an update for. */ -function calcSchedule(node_name) { - node = _ALL_NODES.get(node_name); +function calcSchedule(node) { if (node.update_task !== null) { clearTimeout(node.update_task); } @@ -92,7 +85,7 @@ class ItemInputNode extends ComputeNode { */ constructor(name, item_input_field, none_item) { super(name); - this.input_field.setAttribute("onInput", "calcSchedule('"+name+"');"); + this.input_field.setAttribute("input", () => calcSchedule(this)); this.input_field = item_input_field; this.none_item = expandItem(none_item); } diff --git a/js/display_constants.js b/js/display_constants.js index d8c26dd..93f77e6 100644 --- a/js/display_constants.js +++ b/js/display_constants.js @@ -1,4 +1,3 @@ -let reversedIDs = [ "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; let colorMap = new Map( [ ["Normal", "#fff"], diff --git a/js/sq2bs.js b/js/sq2bs.js index 25ac2d2..94f1c22 100644 --- a/js/sq2bs.js +++ b/js/sq2bs.js @@ -1,13 +1,3 @@ -let weapon_keys = ['dagger', 'wand', 'bow', 'relik', 'spear']; -let armor_keys = ['helmet', 'chestplate', 'leggings', 'boots']; -let skp_keys = ['str', 'dex', 'int', 'def', 'agi']; -let accessory_keys= ['ring1', 'ring2', 'bracelet', 'necklace']; -let powderable_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'weapon']; -let equipment_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace', 'weapon'].concat(tome_keys); -let powder_keys = ['e', 't', 'w', 'f', 'a']; - -let spell_disp = ['spell0-info', 'spell1-info', 'spell2-info', 'spell3-info']; -let other_disp = ['build-order', 'set-info', 'int-info']; document.addEventListener('DOMContentLoaded', function() { @@ -202,7 +192,7 @@ function update_field(field) { document.querySelector("#"+field+"-powder").classList.add("is-invalid"); } else { for (i = 0; i < powder_string.length / 2; i++) { - if (powder_keys.includes(powder_string.substring(i*2, i*2+2).split("")[0]) == false || isNaN(powder_string.substring(i*2, i*2+2).split("")[1]) || parseInt(powder_string.substring(i*2, i*2+2).split("")[1]) < 1 || parseInt(powder_string.substring(i*2, i*2+2).split("")[1]) > 6) { + if (skp_elements.includes(powder_string.substring(i*2, i*2+2).split("")[0]) == false || isNaN(powder_string.substring(i*2, i*2+2).split("")[1]) || parseInt(powder_string.substring(i*2, i*2+2).split("")[1]) < 1 || parseInt(powder_string.substring(i*2, i*2+2).split("")[1]) > 6) { document.querySelector("#"+field+"-powder").classList.add("is-invalid"); } } @@ -239,7 +229,7 @@ function toggle_spell_tab(tab) { } function toggle_boost_tab(tab) { - for (const i of skp_keys) { + for (const i of skp_order) { document.querySelector("#"+i+"-boost").style.display = "none"; document.getElementById(i + "-boost-tab").classList.remove("selected-btn"); } diff --git a/js/sq2builder.js b/js/sq2builder.js index fc42f6d..e63cdb0 100644 --- a/js/sq2builder.js +++ b/js/sq2builder.js @@ -5,25 +5,16 @@ const url_tag = location.hash.slice(1); 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; // THIS IS SUPER DANGEROUS, WE SHOULD NOT BE KEEPING THIS IN SO MANY PLACES -let editable_item_fields = [ "sdPct", "sdRaw", "mdPct", "mdRaw", "poison", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "hprRaw", "hprPct", "hpBonus", "atkTier", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; +let editable_item_fields = [ "sdPct", "sdRaw", "mdPct", "mdRaw", "poison", + "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", + "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", + "hprRaw", "hprPct", "hpBonus", "atkTier", + "spPct1", "spRaw1", "spPct2", "spRaw2", + "spPct3", "spRaw3", "spPct4", "spRaw4" ]; let editable_elems = [];