/** * File containing utility functions relevant to the builder page, as well as the setup code (at the very bottom). */ function populateBuildList() { const buildList = document.getElementById("build-choice"); const savedBuilds = window.localStorage.getItem("builds") === null ? {} : JSON.parse(window.localStorage.getItem("builds")); for (const buildName of Object.keys(savedBuilds).sort()) { const buildOption = document.createElement("option"); buildOption.setAttribute("value", buildName); buildList.appendChild(buildOption); } } function saveBuild() { if (player_build) { const savedBuilds = window.localStorage.getItem("builds") === null ? {} : JSON.parse(window.localStorage.getItem("builds")); const saveName = document.getElementById("build-name").value; const encodedBuild = encodeBuild(player_build); if ((!Object.keys(savedBuilds).includes(saveName) || document.getElementById("saved-error").textContent !== "") && encodedBuild !== "") { savedBuilds[saveName] = encodedBuild.replace("#", ""); window.localStorage.setItem("builds", JSON.stringify(savedBuilds)); document.getElementById("saved-error").textContent = ""; document.getElementById("saved-build").textContent = "Build saved locally"; const buildList = document.getElementById("build-choice"); const buildOption = document.createElement("option"); buildOption.setAttribute("value", saveName); buildList.appendChild(buildOption); } else { document.getElementById("saved-build").textContent = ""; if (encodedBuild === "") { document.getElementById("saved-error").textContent = "Empty build"; } else { document.getElementById("saved-error").textContent = "Exists. Overwrite?"; } } } } function loadBuild() { let savedBuilds = window.localStorage.getItem("builds") === null ? {} : JSON.parse(window.localStorage.getItem("builds")); let saveName = document.getElementById("build-name").value; if (Object.keys(savedBuilds).includes(saveName)) { decodeBuild(savedBuilds[saveName]) document.getElementById("loaded-error").textContent = ""; document.getElementById("loaded-build").textContent = "Build loaded"; } else { document.getElementById("loaded-build").textContent = ""; document.getElementById("loaded-error").textContent = "Build doesn't exist"; } } function resetFields(){ for (const i of powder_inputs) { setValue(i, ""); } for (const i of equipment_inputs) { setValue(i, ""); } for (const i of tomeInputs) { setValue(i, ""); } setValue("str-skp", "0"); setValue("dex-skp", "0"); setValue("int-skp", "0"); setValue("def-skp", "0"); setValue("agi-skp", "0"); for (const special_name of specialNames) { for (let i = 1; i < 6; i++) { //toggle all pressed buttons of the same powder special off //name is same, power is i let elem = document.getElementById(special_name.replace(" ", "_")+'-'+i); if (elem.classList.contains("toggleOn")) { elem.classList.remove("toggleOn"); } } } for (const [key, value] of damageMultipliers) { let elem = document.getElementById(key + "-boost") if (elem.classList.contains("toggleOn")) { elem.classList.remove("toggleOn"); } } for (const elem of skp_order) { console.log(document.getElementById(elem + "_boost_armor").value); document.getElementById(elem + "_boost_armor").value = 0; document.getElementById(elem + "_boost_armor").style.background = `linear-gradient(to right, #AAAAAA, #AAAAAA 0%, #AAAAAA 100%)`; document.getElementById(elem + "_boost_armor_label").textContent = `% ${damageClasses[skp_order.indexOf(elem)+1]} Damage Boost: 0`; } const nodes_to_reset = item_nodes.concat(powder_nodes).concat(edit_input_nodes).concat([powder_special_input, boosts_node, armor_powder_node]); for (const node of nodes_to_reset) { node.mark_dirty(); } for (const node of nodes_to_reset) { node.update(); } setValue("level-choice", "106"); location.hash = ""; } function toggleID() { let button = document.getElementById("show-id-button"); let targetDiv = document.getElementById("id-edit"); if (button.classList.contains("toggleOn")) { //toggle the pressed button off targetDiv.style.display = "none"; button.classList.remove("toggleOn"); } else { targetDiv.style.display = "block"; button.classList.add("toggleOn"); } } 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"); } } } // Toggles display of a certain element, given the ID. function toggle_tab(tab) { if (document.querySelector("#"+tab).style.display == "none") { document.querySelector("#"+tab).style.display = ""; } else { document.querySelector("#"+tab).style.display = "none"; } } // Toggle display of a certain tab, in a group of tabs, given the target tab ID, and a list of associated tabs. // Also sets visual display of an element with ID of target + "-btn" to selected. function show_tab(target, tabs) { //hide all tabs, then show the tab of the div clicked and highlight the correct button for (const i in tabs) { document.querySelector("#" + tabs[i]).style.display = "none"; document.getElementById(tabs[i] + "-btn").classList.remove("selected-btn"); } document.querySelector("#" + target).style.display = ""; document.getElementById(target + "-btn").classList.add("selected-btn"); } // autocomplete initialize function init_autocomplete() { let dropdowns = new Map(); for (const eq of equipment_keys) { if (tome_keys.includes(eq)) { continue; } // build dropdown let item_arr = []; if (eq == 'weapon') { for (const weaponType of weapon_keys) { for (const weapon of itemLists.get(weaponType)) { let item_obj = itemMap.get(weapon); if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") { continue; } if (item_obj["name"] == 'No '+ eq.charAt(0).toUpperCase() + eq.slice(1)) { continue; } item_arr.push(weapon); } } } else { for (const item of itemLists.get(eq.replace(/[0-9]/g, ''))) { let item_obj = itemMap.get(item); if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") { continue; } if (item_obj["name"] == 'No '+ eq.charAt(0).toUpperCase() + eq.slice(1)) { continue; } item_arr.push(item) } } // create dropdown dropdowns.set(eq, new autoComplete({ data: { src: item_arr }, selector: "#"+ eq +"-choice", wrapper: false, resultsList: { maxResults: 1000, tabSelect: true, noResults: true, class: "search-box dark-7 rounded-bottom px-2 fw-bold dark-shadow-sm", element: (list, data) => { // dynamic result loc let position = document.getElementById(eq+'-dropdown').getBoundingClientRect(); list.style.top = position.bottom + window.scrollY +"px"; list.style.left = position.x+"px"; list.style.width = position.width+"px"; list.style.maxHeight = position.height * 2 +"px"; if (!data.results.length) { message = document.createElement('li'); message.classList.add('scaled-font'); message.textContent = "No results found!"; list.prepend(message); } }, }, resultItem: { class: "scaled-font search-item", selected: "dark-5", element: (item, data) => { item.classList.add(itemMap.get(data.value).tier); }, }, events: { input: { selection: (event) => { if (event.detail.selection.value) { event.target.value = event.detail.selection.value; } event.target.dispatchEvent(new Event('change')); }, }, } })); } for (const eq of tome_keys) { // build dropdown let tome_arr = []; let tome_aliases = new Map(); for (const tome_name of tomeLists.get(eq.replace(/[0-9]/g, ''))) { let tome_obj = tomeMap.get(tome_name); if (tome_obj["restrict"] && tome_obj["restrict"] === "DEPRECATED") { continue; } //this should suffice for tomes - jank if (tome_obj["name"].includes('No ' + eq.charAt(0).toUpperCase())) { continue; } let tome_alias = tome_obj['alias']; tome_arr.push(tome_name); tome_arr.push(tome_alias); tome_aliases.set(tome_alias, tome_name); } // create dropdown dropdowns.set(eq, new autoComplete({ data: { src: tome_arr }, selector: "#"+ eq +"-choice", wrapper: false, resultsList: { maxResults: 1000, tabSelect: true, noResults: false, class: "search-box dark-7 rounded-bottom px-2 fw-bold dark-shadow-sm", element: (list, data) => { // dynamic result loc let position = document.getElementById(eq+'-dropdown').getBoundingClientRect(); list.style.top = position.bottom + window.scrollY +"px"; list.style.left = position.x+"px"; list.style.width = position.width+"px"; list.style.maxHeight = position.height * 2 +"px"; if (!data.results.length) { message = document.createElement('li'); message.classList.add('scaled-font'); message.textContent = "No results found!"; list.prepend(message); } }, }, resultItem: { class: "scaled-font search-item", selected: "dark-5", element: (tome, data) => { let val = data.value; if (tome_aliases.has(val)) { val = tome_aliases.get(val); } tome.classList.add(tomeMap.get(val).tier); }, }, events: { input: { selection: (event) => { if (event.detail.selection.value) { let val = event.detail.selection.value; if (tome_aliases.has(val)) { val = tome_aliases.get(val); } event.target.value = val; } event.target.dispatchEvent(new Event('change')); }, }, } })); } } function collapse_element(elmnt) { elem_list = document.querySelector(elmnt).children; if (elem_list) { for (elem of elem_list) { if (elem.classList.contains("no-collapse")) { continue; } if (elem.style.display == "none") { elem.style.display = ""; } else { elem.style.display = "none"; } } } // macy quirk window.dispatchEvent(new Event('resize')); // weird bug where display: none overrides?? document.querySelector(elmnt).style.removeProperty('display'); } function init() { console.log("builder.js init"); init_autocomplete(); // Other "main" stuff // Spell dropdowns for (const eq of equipment_keys) { document.querySelector("#"+eq+"-tooltip").addEventListener("click", () => collapse_element('#'+eq+'-tooltip')); } // Armor Specials for (let i = 0; i < 5; ++i) { const powder_special = powderSpecialStats[i]; const elem_name = damageClasses[i+1]; // skip neutral const elem_char = skp_elements[i]; // TODO: merge? const skp_name = skp_order[i]; // TODO: merge? const boost_parent = document.getElementById(skp_name+'-boost'); const slider_id = skp_name+'_boost_armor'; const label_name = "% " + elem_name + " Dmg Boost"; const slider_container = gen_slider_labeled({label_name: label_name, max: powder_special.cap, id: slider_id, color: elem_colors[i]}); boost_parent.appendChild(slider_container); document.getElementById(slider_id).addEventListener("change", (_) => armor_powder_node.mark_dirty().update() ); } // Masonry setup let masonry = Macy({ container: "#masonry-container", columns: 1, mobileFirst: true, breakAt: { 1200: 4, }, margin: { x: 20, y: 20, } }); let search_masonry = Macy({ container: "#search-results", columns: 1, mobileFirst: true, breakAt: { 1200: 4, }, margin: { x: 20, y: 20, } }); decodeBuild(url_tag); builder_graph_init(); for (const item_node of item_nodes) { if (item_node.get_value() === null) { // likely DB load failure... if (confirm('One or more items failed to load correctly. This could be due to a corrupted build link, or (more likely) a database load failure. Would you like to reload?')) { hardReload(); } break; } } } window.onerror = function(message, source, lineno, colno, error) { document.getElementById('err-box').textContent = message; document.getElementById('stack-box').textContent = error.stack; }; (async function() { let load_promises = [ load_init(), load_ing_init(), load_tome_init() ]; await Promise.all(load_promises); init(); })();