function displaysq2BuildStats(parent_id,build,command_group){ // Commands to "script" the creation of nice formatting. // #commands create a new element. // !elemental is some janky hack for elemental damage. // normals just display a thing. let display_commands = command_group; //console.log(display_commands); let parent_div = document.getElementById(parent_id); // Clear the parent div. if (parent_div != null) { setHTML(parent_id, ""); } let stats = build.statMap; //console.log(build.statMap); let active_elem; let elemental_format = false; //TODO this is put here for readability, consolidate with definition in build.js let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef"]; for (const command of display_commands) { // style instructions if (command.charAt(0) === "#") { if (command === "#defense-stats") { displaysq2DefenseStats(parent_div, build, true); } } if (command.charAt(0) === "!") { // TODO: This is sooo incredibly janky..... if (command === "!elemental") { elemental_format = !elemental_format; } } // id instruction else { let id = command; if (stats.get(id) || build.externalStats.get(id)) { let style = null; // TODO: add pos and neg style if (!staticIDs.includes(id)) { style = "positive"; if (stats.get(id) < 0) { style = "negative"; } } // ignore let id_val = stats.get(id); if (build.externalStats.has(id)) { id_val += build.externalStats.get(id); } if (reversedIDs.includes(id)) { style === "positive" ? style = "negative" : style = "positive"; } if (id === "poison" && id_val > 0) { id_val = Math.ceil(id_val*build.statMap.get("poisonPct")/100); } displaysq2FixedID(parent_div, id, id_val, elemental_format, style); if (id === "poison" && id_val > 0) { let row = document.createElement('div'); row.classList.add("row") let value_elem = document.createElement('div'); value_elem.classList.add('col'); value_elem.classList.add('text-end'); let prefix_elem = document.createElement('b'); prefix_elem.textContent = "\u279C With Strength: "; let number_elem = document.createElement('b'); number_elem.classList.add(style); number_elem.textContent = (id_val * (1+skillPointsToPercentage(build.total_skillpoints[0])) ).toFixed(0) + idSuffixes[id]; value_elem.append(prefix_elem); value_elem.append(number_elem); row.appendChild(value_elem); parent_div.appendChild(row); } // sp thingy } else if (skp_order.includes(id)) { let total_assigned = build.total_skillpoints[skp_order.indexOf(id)]; let base_assigned = build.base_skillpoints[skp_order.indexOf(id)]; let diff = total_assigned - base_assigned; let style; if (diff > 0) { style = "positive"; } else if (diff < 0) { style = "negative"; } if (diff != 0) { displaysq2FixedID(parent_div, id, diff, false, style); } } } } } function displaysq2ExpandedItem(item, parent_id){ // Commands to "script" the creation of nice formatting. // #commands create a new element. // !elemental is some janky hack for elemental damage. // normals just display a thing. if (item.get("category") === "weapon") { let stats = new Map(); stats.set("atkSpd", item.get("atkSpd")); stats.set("damageBonus", [0, 0, 0, 0, 0]); //SUPER JANK @HPP PLS FIX let damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; if (item.get("tier") !== "Crafted") { stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]); let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); let damages = results[2]; let total_damage = 0; for (const i in damage_keys) { total_damage += damages[i][0] + damages[i][1]; item.set(damage_keys[i], damages[i][0]+"-"+damages[i][1]); } total_damage = total_damage / 2; item.set("basedps", total_damage); } else { stats.set("damageRaw", [item.get("nDamLow"), item.get("eDamLow"), item.get("tDamLow"), item.get("wDamLow"), item.get("fDamLow"), item.get("aDamLow")]); stats.set("damageBases", [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]); let resultsLow = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); let damagesLow = resultsLow[2]; stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]); stats.set("damageBases", [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]); let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); let damages = results[2]; console.log(damages); let total_damage_min = 0; let total_damage_max = 0; for (const i in damage_keys) { total_damage_min += damagesLow[i][0] + damagesLow[i][1]; total_damage_max += damages[i][0] + damages[i][1]; item.set(damage_keys[i], damagesLow[i][0]+"-"+damagesLow[i][1]+"\u279c"+damages[i][0]+"-"+damages[i][1]); } total_damage_min = total_damage_min / 2; total_damage_max = total_damage_max / 2; item.set("basedps", [total_damage_min, total_damage_max]); } } else if (item.get("category") === "armor") { } let display_commands = sq2_item_display_commands; // Clear the parent div. setHTML(parent_id, ""); let parent_div = document.getElementById(parent_id); parent_div.classList.add("border", "border-2", "border-dark"); let fix_id = item.has("fixID") && item.get("fixID"); let elemental_format = false; for (let i = 0; i < display_commands.length; i++) { const command = display_commands[i]; if (command.charAt(0) === "!") { // TODO: This is sooo incredibly janky..... if (command === "!elemental") { elemental_format = !elemental_format; } else if (command === "!spacer") { let spacer = document.createElement('div'); spacer.classList.add("row", "my-2"); parent_div.appendChild(spacer); continue; } } else { let id = command; if(nonRolledIDs.includes(id)){//nonRolledID & non-0/non-null/non-und ID if (!item.get(id)) { if (! (item.get("crafted") && skp_order.includes(id) && (item.get("maxRolls").get(id) || item.get("minRolls").get(id)))) { continue; } } if (id === "slots") { let p_elem = document.createElement("div"); p_elem.classList.add("col"); // PROPER POWDER DISPLAYING let numerals = new Map([[1, "I"], [2, "II"], [3, "III"], [4, "IV"], [5, "V"], [6, "VI"]]); let powderPrefix = document.createElement("b"); powderPrefix.textContent = "Powder Slots: " + item.get(id) + " ["; p_elem.appendChild(powderPrefix); let powders = item.get("powders"); for (let i = 0; i < powders.length; i++) { let powder = document.createElement("b"); powder.textContent = numerals.get((powders[i]%6)+1)+" "; powder.classList.add(damageClasses[Math.floor(powders[i]/6)+1]+"_powder"); p_elem.appendChild(powder); } let powderSuffix = document.createElement("b"); powderSuffix.textContent = "]"; p_elem.appendChild(powderSuffix); parent_div.appendChild(p_elem); } else if (id === "set") { if (item.get("hideSet")) { continue; } let p_elem = document.createElement("div"); p_elem.classList.add("col"); p_elem.textContent = "Set: " + item.get(id).toString(); parent_div.appendChild(p_elem); } else if (id === "majorIds") { //console.log(item.get(id)); for (let majorID of item.get(id)) { let p_elem = document.createElement("div"); p_elem.classList.add("col"); let title_elem = document.createElement("b"); let b_elem = document.createElement("b"); if (majorID.includes(":")) { let name = majorID.substring(0, majorID.indexOf(":")+1); let mid = majorID.substring(majorID.indexOf(":")+1); if (name.charAt(0) !== "+") {name = "+" + name} title_elem.classList.add("Legendary"); title_elem.textContent = name; b_elem.classList.add("Crafted"); b_elem.textContent = mid; p_elem.appendChild(title_elem); p_elem.appendChild(b_elem); } else { let name = item.get(id).toString() if (name.charAt(0) !== "+") {name = "+" + name} b_elem.classList.add("Legendary"); b_elem.textContent = name; p_elem.appendChild(b_elem); } parent_div.appendChild(p_elem); } } else if (id === "lvl" && item.get("tier") === "Crafted") { let p_elem = document.createElement("div"); p_elem.classList.add("col"); p_elem.textContent = "Combat Level Min: " + item.get("lvlLow") + "-" + item.get(id); parent_div.appendChild(p_elem); } else if (id === "displayName") { let row = document.createElement("div"); let a_elem = document.createElement("a"); row.classList.add("row", "justify-content-center"); a_elem.classList.add("col-auto", "text-center", "item-title", "p-0"); a_elem.classList.add(item.has("tier") ? item.get("tier").replace(" ","") : "Normal"); // a_elem.style.textGrow = 1; row.appendChild(a_elem); /* FUNCTIONALITY FOR THIS FEATURE HAS SINCE BEEN REMOVED (WITH SQ2). IF WE WANT TO USE IT IN THE FUTURE, I'VE LEFT THE CODE TO ADD IT IN HERE */ //allow the plus minus element to toggle upon click: ➕➖ // let plusminus = document.createElement("div"); // plusminus.id = parent_div.id.split("-")[0] + "-pm"; // plusminus.classList.add("col", "plus_minus", "text_end"); // plusminus.style.flexGrow = 0; // plusminus.textContent = "\u2795"; // row.appendChild(plusminus); if (item.get("custom")) { a_elem.href = "../custom/#" + item.get("hash"); a_elem.textContent = item.get("displayName"); } else if (item.get("crafted")) { a_elem.href = "../crafter/#" + item.get("hash"); a_elem.textContent = item.get(id); } else { a_elem.href = "../item/#" + item.get("displayName"); a_elem.textContent = item.get("displayName"); } parent_div.appendChild(row); let nolink_row = document.createElement("div"); let p_elem = document.createElement("p"); nolink_row.classList.add("row", "justify-content-center"); nolink_row.style.display = "none"; p_elem.classList.add("col-auto", "text-center", "item-title", "p-0"); p_elem.classList.add(item.has("tier") ? item.get("tier").replace(" ","") : "Normal"); if (item.get("custom")) { p_elem.textContent = item.get("displayName"); } else if (item.get("crafted")) { p_elem.textContent = item.get(id); } else { p_elem.textContent = item.get("displayName"); } nolink_row.appendChild(p_elem); parent_div.appendChild(nolink_row); let img = document.createElement("img"); if (item && item.has("type")) { img.src = "../media/items/" + (newIcons ? "new/":"old/") + "generic-" + item.get("type") + ".png"; img.alt = item.get("type"); img.style = " z=index: 1; position: relative;"; let container = document.createElement("div"); let bckgrd = document.createElement("div"); bckgrd.classList.add("col", "px-0", "d-flex", "align-items-center", "justify-content-center");// , "no-collapse"); bckgrd.style = "border-radius: 50%;background-image: radial-gradient(closest-side, " + colorMap.get(item.get("tier")) + " 20%," + "hsl(0, 0%, 16%) 80%); margin-left: auto; margin-right: auto;" bckgrd.classList.add("scaled-bckgrd"); parent_div.appendChild(container); container.appendChild(bckgrd); bckgrd.appendChild(img); } } else { let p_elem; if ( !(item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") && (!skp_order.includes(id)) || (skp_order.includes(id) && item.get("tier") !== "Crafted" && parent_div.nodeName === "table") ) { //skp warp p_elem = displaysq2FixedID(parent_div, id, item.get(id), elemental_format); } else if (item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") { p_elem = displaysq2FixedID(parent_div, id, item.get(id+"Low")+"-"+item.get(id), elemental_format); } if (id === "lore") { p_elem.style = "font-style: italic"; } else if (skp_order.includes(id)) { //id = str, dex, int, def, or agi if ( item.get("tier") !== "Crafted") { row = document.createElement("div"); row.classList.add("col"); let title = document.createElement("b"); title.textContent = idPrefixes[id] + " "; let boost = document.createElement("b"); if (item.get(id) < 0) { boost.classList.add("negative"); } else { //boost = 0 SHOULD not come up boost.classList.add("positive"); } boost.textContent = item.get(id); row.appendChild(title); row.appendChild(boost); parent_div.appendChild(row); } else if ( item.get("tier") === "Crafted") { let row = displaysq2RolledID(item, id, elemental_format); parent_div.appendChild(row); } } else if (id === "restrict") { p_elem.classList.add("restrict"); } } } else if ( rolledIDs.includes(id) && ((item.get("maxRolls") && item.get("maxRolls").get(id)) || (item.get("minRolls") && item.get("minRolls").get(id)))) { let style = "positive"; if (item.get("minRolls").get(id) < 0) { style = "negative"; } if(reversedIDs.includes(id)){ style === "positive" ? style = "negative" : style = "positive"; } if (fix_id) { p_elem = document.createElement("div"); p_elem.classList.add("col", "text-nowrap"); if (id == "dex") { console.log("dex activated at fix_id") } displaysq2FixedID(p_elem, id, item.get("minRolls").get(id), elemental_format, style); parent_div.appendChild(p_elem); } else { let row = displaysq2RolledID(item, id, elemental_format); parent_div.appendChild(row); } }else{ // :/ } } } //Show powder specials ;-; let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots", "ring", "bracelet", "necklace"]; if(nonConsumables.includes(item.get("type"))) { let powder_special = document.createElement("div"); powder_special.classList.add("col"); let powders = item.get("powders"); let element = ""; let power = 0; for (let i = 0; i < powders.length; i++) { let firstPowderType = skp_elements[Math.floor(powders[i]/6)]; if (element !== "") break; else if (powders[i]%6 > 2) { //t4+ for (let j = i+1; j < powders.length; j++) { let currentPowderType = skp_elements[Math.floor(powders[j]/6)] if (powders[j] % 6 > 2 && firstPowderType === currentPowderType) { element = currentPowderType; power = Math.round(((powders[i] % 6 + powders[j] % 6 + 2) / 2 - 4) * 2); break; } } } } if (element !== "") {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]" let powderSpecial = powderSpecialStats[ skp_elements.indexOf(element)]; let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]); let specialTitle = document.createElement("span"); let specialEffects = document.createElement("span"); addClasses(specialTitle, [damageClasses[skp_elements.indexOf(element) + 1]]); let effects; if (item.get("category") === "weapon") {//weapon effects = powderSpecial["weaponSpecialEffects"]; specialTitle.textContent = powderSpecial["weaponSpecialName"]; }else if (item.get("category") === "armor") {//armor effects = powderSpecial["armorSpecialEffects"]; specialTitle.textContent += powderSpecial["armorSpecialName"] + ": "; } for (const [key,value] of effects.entries()) { if (key !== "Description") { let effect = document.createElement("p"); effect.classList.add("m-0"); effect.textContent = key + ": " + value[power] + specialSuffixes.get(key); if(key === "Damage"){ effect.textContent += elementIcons[skp_elements.indexOf(element)]; } if (element === "w" && item.get("category") === "armor") { effect.textContent += " / Mana Used"; } specialEffects.appendChild(effect); }else{ specialTitle.textContent += "[ " + effects.get("Description") + " ]"; } } powder_special.appendChild(specialTitle); powder_special.appendChild(specialEffects); parent_div.appendChild(powder_special); } } if(item.get("tier") && item.get("tier") === "Crafted") { let dura_elem = document.createElement("div"); dura_elem.classList.add("col"); let dura = []; let suffix = ""; if(nonConsumables.includes(item.get("type"))) { dura = item.get("durability"); dura_elem.textContent = "Durability: " } else { dura = item.get("duration"); dura_elem.textContent = "Duration: " suffix = " sec." let charges = document.createElement("b"); charges.textContent = "Charges: " + item.get("charges"); parent_div.appendChild(charges); } if (typeof(dura) === "string") { dura_elem.textContent += dura + suffix; } else { dura_elem.textContent += dura[0]+"-"+dura[1] + suffix; } parent_div.append(dura_elem); } //Show item tier if (item.get("tier") && item.get("tier") !== " ") { let item_desc_elem = document.createElement("div"); item_desc_elem.classList.add("col"); item_desc_elem.classList.add(item.get("tier")); if (tome_types.includes(item.get("type"))) { tome_type_map = new Map([["weaponTome", "Weapon Tome"],["armorTome", "Armor Tome"],["guildTome", "Guild Tome"]]); item_desc_elem.textContent = item.get("tier")+" "+tome_type_map.get(item.get("type")); } else { item_desc_elem.textContent = item.get("tier")+" "+item.get("type"); } parent_div.append(item_desc_elem); } //Show item hash if applicable if (item.get("crafted") || item.get("custom")) { let item_desc_elem = document.createElement("p"); item_desc_elem.classList.add('itemp'); item_desc_elem.style.maxWidth = "100%"; item_desc_elem.style.wordWrap = "break-word"; item_desc_elem.style.wordBreak = "break-word"; item_desc_elem.textContent = item.get("hash"); parent_div.append(item_desc_elem); } if (item.get("category") === "weapon") { let damage_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; let total_damages = item.get("basedps"); let base_dps_elem = document.createElement("p"); base_dps_elem.classList.add("left"); base_dps_elem.classList.add("itemp"); if (item.get("tier") === "Crafted") { let base_dps_min = total_damages[0] * damage_mult; let base_dps_max = total_damages[1] * damage_mult; base_dps_elem.textContent = "Base DPS: "+base_dps_min.toFixed(3)+"\u279c"+base_dps_max.toFixed(3); } else { base_dps_elem.textContent = "Base DPS: "+(total_damages * damage_mult); } parent_div.appendChild(document.createElement("p")); parent_div.appendChild(base_dps_elem); } } function displaysq2RolledID(item, id, elemental_format) { let row = document.createElement('div'); row.classList.add('col'); let item_div = document.createElement('div'); item_div.classList.add('row'); let min_elem = document.createElement('div'); min_elem.classList.add('col', 'text-start'); min_elem.style.cssText += "flex-grow: 0"; let id_min = item.get("minRolls").get(id) let style = id_min < 0 ? "negative" : "positive"; if(reversedIDs.includes(id)){ style === "positive" ? style = "negative" : style = "positive"; } min_elem.classList.add(style); min_elem.textContent = id_min + idSuffixes[id]; item_div.appendChild(min_elem); let desc_elem = document.createElement('div'); desc_elem.classList.add('col', 'text-center');//, 'text-nowrap'); desc_elem.style.cssText += "flex-grow: 1"; //TODO elemental format jank if (elemental_format) { apply_sq2_elemental_format(desc_elem, id); } else { desc_elem.textContent = idPrefixes[id]; } item_div.appendChild(desc_elem); let max_elem = document.createElement('div'); let id_max = item.get("maxRolls").get(id) max_elem.classList.add('col', 'text-end'); max_elem.style.cssText += "flex-grow: 0"; style = id_max < 0 ? "negative" : "positive"; if (reversedIDs.includes(id)) { style === "positive" ? style = "negative" : style = "positive"; } max_elem.classList.add(style); max_elem.textContent = id_max + idSuffixes[id]; item_div.appendChild(max_elem); row.appendChild(item_div); return row; } function displaysq2WeaponStats(build) { // let base_damage = build.get('damageRaw'); let damage_keys = [ "nDam", "eDam", "tDam", "wDam", "fDam", "aDam" ]; // pP base calc (why do i still use pP) let item = build.weapon; let stats = new Map(); stats.set("atkSpd", item.get("atkSpd")); stats.set("damageBonus", [0, 0, 0, 0, 0]); stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]); let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, build.weapon, [0, 0, 0, 0, 0], 1, undefined); let powdered_base = results[2]; const powdered_map = new Map(); powdered_map.set('nDam', powdered_base[0][0]+'-'+powdered_base[0][1]); powdered_map.set('eDam', powdered_base[1][0]+'-'+powdered_base[1][1]); powdered_map.set('tDam', powdered_base[2][0]+'-'+powdered_base[2][1]); powdered_map.set('wDam', powdered_base[3][0]+'-'+powdered_base[3][1]); powdered_map.set('fDam', powdered_base[4][0]+'-'+powdered_base[4][1]); powdered_map.set('aDam', powdered_base[5][0]+'-'+powdered_base[5][1]); // display //I think this is res's code? in any case it doesn't work - ferri /* for (const i in damage_keys) { document.getElementById(damage_keys[i]+"-base").textContent = powdered_map.get(damage_keys[i]); } */ let tot = 0; //sum up elemental damages to get sum of base dps's for (let i = 0; i < 6; i++) { tot += powdered_base[i][0] + powdered_base[i][1]; } tot /= 2; let dps = Math.max(0, Math.round(tot * baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))] )); //atkspeeds document.getElementById("weapon-dps").textContent = "base dps: " + dps; document.getElementById("weapon-lv").textContent = item.get("lvl"); if (item.get("type")) { document.getElementById("weapon-img").src = "../media/items/" + (newIcons ? "new/":"old/") + "generic-" + item.get("type") + ".png"; } } function displaysq2FixedID(active, id, value, elemental_format, style) { if (style) { let row = document.createElement('div'); row.classList.add("row"); let desc_elem = document.createElement('div'); desc_elem.classList.add('col'); desc_elem.classList.add('text-start'); if (elemental_format) { apply_sq2_elemental_format(desc_elem, id); } else { desc_elem.textContent = idPrefixes[id]; } row.appendChild(desc_elem); let value_elem = document.createElement('div'); value_elem.classList.add('col'); value_elem.classList.add('text-end'); value_elem.classList.add(style); value_elem.textContent = value + idSuffixes[id]; row.appendChild(value_elem); active.appendChild(row); return row; } else { // HACK TO AVOID DISPLAYING ZERO DAMAGE! TODO if (value === "0-0" || value === "0-0\u279c0-0") { return; } let p_elem = document.createElement('div'); p_elem.classList.add('col'); if (elemental_format) { apply_sq2_elemental_format(p_elem, id, value); } else { p_elem.textContent = idPrefixes[id].concat(value, idSuffixes[id]); } active.appendChild(p_elem); return p_elem; } } function displaysq2PoisonDamage(overallparent_elem, build) { overallparent_elem.textContent = ""; //Title let title_elemavg = document.createElement("b"); title_elemavg.textContent = "Poison Stats"; overallparent_elem.append(title_elemavg); let overallpoisonDamage = document.createElement("p"); let overallpoisonDamageFirst = document.createElement("span"); let overallpoisonDamageSecond = document.createElement("span"); let poison_tick = Math.ceil(build.statMap.get("poison") * (1+skillPointsToPercentage(build.total_skillpoints[0])) * (build.statMap.get("poisonPct") + build.externalStats.get("poisonPct"))/100 /3); overallpoisonDamageFirst.textContent = "Poison Tick: "; overallpoisonDamageSecond.textContent = Math.max(poison_tick,0); overallpoisonDamageSecond.classList.add("Damage"); overallpoisonDamage.appendChild(overallpoisonDamageFirst); overallpoisonDamage.appendChild(overallpoisonDamageSecond); overallparent_elem.append(overallpoisonDamage); } function displaysq2MeleeDamage(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 = ""; overallparent_elem.textContent = ""; const stats = meleeStats.slice(); for (let i = 0; i < 6; ++i) { for (let j in stats[i]) { stats[i][j] = stats[i][j].toFixed(2); } } for (let i = 6; i < 8; ++i) { for (let j = 0; j < 2; j++) { stats[i][j] = stats[i][j].toFixed(2); } } 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"); title_elem.classList.add("title"); title_elem.textContent = "Melee Stats"; parent_elem.append(title_elem); parent_elem.append(document.createElement("br")); //overall title let title_elemavg = document.createElement("b"); title_elemavg.textContent = "Melee Stats"; overallparent_elem.append(title_elemavg); //average DPS let averageDamage = document.createElement("p"); averageDamage.classList.add("left"); 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 let overallaverageDamage = document.createElement("p"); let overallaverageDamageFirst = document.createElement("span"); overallaverageDamageFirst.textContent = "Average DPS: " let overallaverageDamageSecond = document.createElement("span"); overallaverageDamageSecond.classList.add("Damage"); overallaverageDamageSecond.textContent = stats[10]; overallaverageDamage.appendChild(overallaverageDamageFirst); overallaverageDamage.appendChild(overallaverageDamageSecond); overallparent_elem.append(overallaverageDamage); //overallparent_elem.append(document.createElement("br")); //attack speed let atkSpd = document.createElement("p"); atkSpd.classList.add("left"); atkSpd.textContent = "Attack Speed: " + attackSpeeds[stats[11]]; parent_elem.append(atkSpd); parent_elem.append(document.createElement("br")); //overall attack speed let overallatkSpd = document.createElement("p"); let overallatkSpdFirst = document.createElement("span"); overallatkSpdFirst.textContent = "Attack Speed: "; let overallatkSpdSecond = document.createElement("span"); overallatkSpdSecond.classList.add("Damage"); overallatkSpdSecond.textContent = attackSpeeds[stats[11]]; overallatkSpd.appendChild(overallatkSpdFirst); overallatkSpd.appendChild(overallatkSpdSecond); overallparent_elem.append(overallatkSpd); //Non-Crit: n->elem, total dmg, DPS let nonCritStats = document.createElement("p"); nonCritStats.classList.add("left"); nonCritStats.textContent = "Non-Crit Stats: "; nonCritStats.append(document.createElement("br")); for (let i = 0; i < 6; i++){ if(stats[i][1] != 0){ let dmg = document.createElement("p"); 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] + " \u2013 " + stats[6][1]; 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("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 let singleHitDamage = document.createElement("p"); let singleHitDamageFirst = document.createElement("span"); singleHitDamageFirst.textContent = "Single Hit Average: "; let singleHitDamageSecond = document.createElement("span"); 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); overallparent_elem.append(singleHitDamage); let normalChance = document.createElement("p"); normalChance.textContent = "Non-Crit Chance: " + (stats[6][2]*100).toFixed(2) + "%"; normalChance.append(document.createElement("br")); normalChance.append(document.createElement("br")); nonCritStats.append(normalChance); parent_elem.append(nonCritStats); parent_elem.append(document.createElement("br")); //Crit: n->elem, total dmg, DPS let critStats = document.createElement("p"); critStats.classList.add("left"); critStats.textContent = "Crit Stats: "; critStats.append(document.createElement("br")); for (let i = 0; i < 6; i++){ if(stats[i][3] != 0) { dmg = document.createElement("p"); 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] + " \u2013 " + stats[7][1]; 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]; 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"); critChance.textContent = "Crit Chance: " + (stats[7][2]*100).toFixed(2) + "%"; critChance.append(document.createElement("br")); critChance.append(document.createElement("br")); critStats.append(critChance); parent_elem.append(critStats); } function displaysq2ArmorStats(build) { let armor_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace']; for (const i in armor_keys) { document.getElementById(armor_keys[i]+'-health').textContent = build[armor_keys[i]].get('hp'); document.getElementById(armor_keys[i]+'-lv').textContent = build[armor_keys[i]].get('lvl'); } } function displaysq2DefenseStats(parent_elem, build, insertSummary){ let defenseStats = build.getDefenseStats(); insertSummary = (typeof insertSummary !== 'undefined') ? insertSummary : false; if (!insertSummary) { parent_elem.textContent = ""; } const stats = defenseStats.slice(); // parent_elem.append(document.createElement("br")); let statsTable = document.createElement("div"); //[total hp, ehp, total hpr, ehpr, [def%, agi%], [edef,tdef,wdef,fdef,adef]] for(const i in stats){ if(typeof stats[i] === "number"){ stats[i] = stats[i].toFixed(2); }else{ for(const j in stats[i]){ stats[i][j] = stats[i][j].toFixed(2); } } } //total HP let hpRow = document.createElement("div"); hpRow.classList.add('row'); let hp = document.createElement("div"); hp.classList.add('col'); hp.classList.add("Health"); hp.classList.add("text-start"); hp.textContent = "Total HP:"; let boost = document.createElement("div"); boost.classList.add('col'); boost.textContent = stats[0]; boost.classList.add("text-end"); hpRow.appendChild(hp); hpRow.append(boost); if (insertSummary) { parent_elem.appendChild(hpRow); } else { statsTable.appendChild(hpRow); } let tooltip; let tooltiptext; let defMult = build.statMap.get("defMult"); if (!defMult) {defMult = 1} //EHP let ehpRow = document.createElement("div"); ehpRow.classList.add("row"); let ehp = document.createElement("div"); ehp.classList.add("col"); ehp.classList.add("text-start"); ehp.textContent = "Effective HP:"; boost = document.createElement("div"); boost.textContent = stats[1][0]; boost.classList.add("col"); boost.classList.add("text-end"); 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); if (insertSummary) { parent_elem.appendChild(ehpRow) } else { statsTable.append(ehpRow); } ehpRow = document.createElement("div"); ehpRow.classList.add("row"); ehp = document.createElement("div"); ehp.classList.add("col"); ehp.classList.add("text-start"); ehp.textContent = "Effective HP (no agi):"; boost = document.createElement("div"); boost.textContent = stats[1][1]; boost.classList.add("col"); boost.classList.add("text-end"); 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); statsTable.append(ehpRow); //total HPR let hprRow = document.createElement("div"); hprRow.classList.add("row") let hpr = document.createElement("div"); hpr.classList.add("Health"); hpr.classList.add("col"); hpr.classList.add("text-start"); hpr.textContent = "HP Regen (Total):"; boost = document.createElement("div"); boost.textContent = stats[2]; boost.classList.add("col"); boost.classList.add("text-end"); hprRow.appendChild(hpr); hprRow.appendChild(boost); if (insertSummary) { parent_elem.appendChild(hprRow); } else { statsTable.appendChild(hprRow); } //EHPR let ehprRow = document.createElement("div"); ehprRow.classList.add("row") let ehpr = document.createElement("div"); ehpr.classList.add("col"); ehpr.classList.add("text-start"); ehpr.textContent = "Effective HP Regen:"; boost = document.createElement("div"); boost.textContent = stats[3][0]; boost.classList.add("col"); boost.classList.add("text-end"); 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); statsTable.append(ehprRow); /* ehprRow = document.createElement("tr"); ehpr = document.createElement("td"); ehpr.classList.add("left"); ehpr.textContent = "Effective HP Regen (no agi):"; boost = document.createElement("td"); boost.textContent = stats[3][1]; boost.classList.add("right"); ehprRow.appendChild(ehpr); ehprRow.append(boost); statsTable.append(ehprRow); */ //eledefs let eledefs = stats[5]; for (let i = 0; i < eledefs.length; i++){ let eledefElemRow = document.createElement("div"); eledefElemRow.classList.add("row") let eledef = document.createElement("div"); eledef.classList.add("col"); eledef.classList.add("text-start"); let eledefTitle = document.createElement("span"); eledefTitle.textContent = damageClasses[i+1]; eledefTitle.classList.add(damageClasses[i+1]); let defense = document.createElement("span"); defense.textContent = " Def (Total): "; eledef.appendChild(eledefTitle); eledef.appendChild(defense); eledefElemRow.appendChild(eledef); let boost = document.createElement("div"); boost.textContent = eledefs[i]; boost.classList.add(eledefs[i] >= 0 ? "positive" : "negative"); boost.classList.add("col"); boost.classList.add("text-end"); let defRaw = build.statMap.get("defRaw")[i]; let defPct = build.statMap.get("defBonus")[i]/100; if (defRaw < 0) { defPct >= 0 ? defPct = "- " + defPct: defPct = "+ " + defPct; tooltiptext = `= min(0, ${defRaw} * (1 ${defPct}))` } else { defPct >= 0 ? defPct = "+ " + defPct: defPct = "- " + defPct; tooltiptext = `= ${defRaw} * (1 ${defPct})` } // tooltip = createTooltip(tooltip, "p", tooltiptext, boost, ["def-tooltip"]); eledefElemRow.appendChild(boost); if (insertSummary) { parent_elem.appendChild(eledefElemRow); } else { statsTable.appendChild(eledefElemRow); } } if (!insertSummary) { //skp let defRow = document.createElement("div"); defRow.classList.add("row"); let defElem = document.createElement("div"); defElem.classList.add("col"); defElem.classList.add("text-start"); defElem.textContent = "Damage Absorbed %:"; boost = document.createElement("div"); boost.classList.add("col"); boost.classList.add("text-end"); boost.textContent = stats[4][0] + "%"; defRow.appendChild(defElem); defRow.appendChild(boost); statsTable.append(defRow); let agiRow = document.createElement("div"); agiRow.classList.add("row"); let agiElem = document.createElement("div"); agiElem.classList.add("col"); agiElem.classList.add("text-start"); agiElem.textContent = "Dodge Chance %:"; boost = document.createElement("div"); boost.classList.add("col"); boost.classList.add("text-end"); boost.textContent = stats[4][1] + "%"; agiRow.appendChild(agiElem); agiRow.appendChild(boost); statsTable.append(agiRow); } if (!insertSummary) { parent_elem.append(statsTable); } } function displaysq2PowderSpecials(parent_elem, powderSpecials, build, overall=false) { parent_elem.textContent = "" let title = document.createElement("b"); title.textContent = "Powder Specials"; parent_elem.appendChild(title); let specials = powderSpecials.slice(); let stats = build.statMap; let expandedStats = new Map(); //each entry of powderSpecials is [ps, power] for (special of specials) { //iterate through the special and display its effects. let powder_special = document.createElement("p"); let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]); let specialTitle = document.createElement("p"); let specialEffects = document.createElement("p"); specialTitle.classList.add(damageClasses[powderSpecialStats.indexOf(special[0]) + 1]); let effects = special[0]["weaponSpecialEffects"]; let power = special[1]; specialTitle.textContent = special[0]["weaponSpecialName"] + " " + Math.floor((power-1)*0.5 + 4) + (power % 2 == 0 ? ".5" : ""); if (!overall || powderSpecialStats.indexOf(special[0]) == 2 || powderSpecialStats.indexOf(special[0]) == 3 || powderSpecialStats.indexOf(special[0]) == 4) { for (const [key,value] of effects) { let effect = document.createElement("p"); effect.textContent += key + ": " + value[power-1] + specialSuffixes.get(key); if(key === "Damage"){ effect.textContent += elementIcons[powderSpecialStats.indexOf(special[0])]; } if(special[0]["weaponSpecialName"] === "Wind Prison" && key === "Damage Boost") { effect.textContent += " (only 1st hit)"; } specialEffects.appendChild(effect); } } powder_special.appendChild(specialTitle); powder_special.appendChild(specialEffects); //if this special is an instant-damage special (Quake, Chain Lightning, Courage Burst), display the damage. let specialDamage = document.createElement("p"); // specialDamage.classList.add("item-margin"); let spells = spell_table["powder"]; if (powderSpecialStats.indexOf(special[0]) == 0 || powderSpecialStats.indexOf(special[0]) == 1 || powderSpecialStats.indexOf(special[0]) == 3) { //Quake, Chain Lightning, or Courage let spell = (powderSpecialStats.indexOf(special[0]) == 3 ? spells[2] : spells[powderSpecialStats.indexOf(special[0])]); let part = spell["parts"][0]; let _results = calculateSpellDamage(stats, part.conversion, stats.get("mdRaw"), stats.get("mdPct") + build.externalStats.get("mdPct"), 0, build.weapon, build.total_skillpoints, build.damageMultiplier * ((part.multiplier[power-1] / 100)), build.externalStats);//part.multiplier[power] / 100 let critChance = skillPointsToPercentage(build.total_skillpoints[1]); let save_damages = []; let totalDamNormal = _results[0]; let totalDamCrit = _results[1]; let results = _results[2]; for (let i = 0; i < 6; ++i) { for (let j in results[i]) { results[i][j] = results[i][j].toFixed(2); } } let nonCritAverage = (totalDamNormal[0]+totalDamNormal[1])/2 || 0; let critAverage = (totalDamCrit[0]+totalDamCrit[1])/2 || 0; let averageDamage = (1-critChance)*nonCritAverage+critChance*critAverage || 0; let averageWrap = document.createElement("p"); let averageLabel = document.createElement("span"); averageLabel.textContent = "Average: "; let averageLabelDmg = document.createElement("span"); averageLabelDmg.classList.add("Damage"); averageLabelDmg.textContent = averageDamage.toFixed(2); averageWrap.appendChild(averageLabel); averageWrap.appendChild(averageLabelDmg); specialDamage.appendChild(averageWrap); if (!overall) { let nonCritLabel = document.createElement("p"); nonCritLabel.textContent = "Non-Crit Average: "+nonCritAverage.toFixed(2); nonCritLabel.classList.add("damageSubtitle"); nonCritLabel.classList.add("item-margin"); specialDamage.append(nonCritLabel); for (let i = 0; i < 6; i++){ 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]; specialDamage.append(p); } } let normalDamage = document.createElement("p"); normalDamage.textContent = "Total: " + totalDamNormal[0].toFixed(2) + "-" + totalDamNormal[1].toFixed(2); normalDamage.classList.add("itemp"); specialDamage.append(normalDamage); let nonCritChanceLabel = document.createElement("p"); nonCritChanceLabel.textContent = "Non-Crit Chance: " + ((1-critChance)*100).toFixed(2) + "%"; specialDamage.append(nonCritChanceLabel); let critLabel = document.createElement("p"); critLabel.textContent = "Crit Average: "+critAverage.toFixed(2); critLabel.classList.add("damageSubtitle"); critLabel.classList.add("item-margin"); specialDamage.append(critLabel); for (let i = 0; i < 6; i++){ 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]; specialDamage.append(p); } } let critDamage = document.createElement("p"); critDamage.textContent = "Total: " + totalDamCrit[0].toFixed(2) + "-" + totalDamCrit[1].toFixed(2); critDamage.classList.add("itemp"); specialDamage.append(critDamage); let critChanceLabel = document.createElement("p"); critChanceLabel.textContent = "Crit Chance: " + (critChance*100).toFixed(2) + "%"; specialDamage.append(critChanceLabel); save_damages.push(averageDamage); } powder_special.append(specialDamage); } parent_elem.appendChild(powder_special); } } function displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx) { parent_elem.textContent = ""; let tooltip; let tooltiptext; const stats = build.statMap; let title_elem = document.createElement("p"); overallparent_elem.textContent = ""; let title_elemavg = document.createElement("b"); if (spellIdx != 0) { let first = document.createElement("span"); first.textContent = spell.title + " ("; title_elem.appendChild(first.cloneNode(true)); //cloneNode is needed here. title_elemavg.appendChild(first); let second = document.createElement("span"); second.textContent = build.getSpellCost(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); // 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); let third = document.createElement("span"); third.textContent = ") [Base: " + build.getBaseSpellCost(spellIdx, spell.cost) + " ]"; title_elem.appendChild(third); let third_summary = document.createElement("span"); third_summary.textContent = ")"; title_elemavg.appendChild(third_summary); } else { title_elem.textContent = spell.title; title_elemavg.textContent = spell.title; } parent_elem.append(title_elem); overallparent_elem.append(title_elemavg); overallparent_elem.append(displaysq2NextCosts(spell, build)); let critChance = skillPointsToPercentage(build.total_skillpoints[1]); let save_damages = []; let part_divavg = document.createElement("p"); overallparent_elem.append(part_divavg); let spell_parts; if (spell.parts) { spell_parts = spell.parts; } else { spell_parts = spell.variants.DEFAULT; for (const majorID of stats.get("activeMajorIDs")) { if (majorID in spell.variants) { spell_parts = spell.variants[majorID]; break; } } } //console.log(spell_parts); for (const part of spell_parts) { let part_div = document.createElement("p"); parent_elem.append(part_div); let subtitle_elem = document.createElement("p"); subtitle_elem.textContent = part.subtitle; part_div.append(subtitle_elem); if (part.type === "damage") { //console.log(build.expandedStats); let _results = calculateSpellDamage(stats, part.conversion, stats.get("sdRaw") + stats.get("rainbowRaw"), stats.get("sdPct") + build.externalStats.get("sdPct"), part.multiplier / 100, build.weapon, build.total_skillpoints, build.damageMultiplier, build.externalStats); 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); } } let nonCritAverage = (totalDamNormal[0]+totalDamNormal[1])/2 || 0; let critAverage = (totalDamCrit[0]+totalDamCrit[1])/2 || 0; let averageDamage = (1-critChance)*nonCritAverage+critChance*critAverage || 0; 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); if (part.summary == true) { let overallaverageLabel = document.createElement("p"); let first = document.createElement("span"); let second = document.createElement("span"); first.textContent = part.subtitle + " Average: "; 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"); part_divavg.append(overallaverageLabel); } function _damage_display(label_text, average, result_idx) { let label = document.createElement("p"); label.textContent = label_text+average.toFixed(2); part_div.append(label); let arrmin = []; let arrmax = []; for (let i = 0; i < 6; i++){ if (results[i][1] != 0){ let p = document.createElement("p"); p.classList.add(damageClasses[i]); p.textContent = results[i][result_idx] + " \u2013 " + results[i][result_idx + 1]; arrmin.push(results[i][result_idx]); arrmax.push(results[i][result_idx + 1]); part_div.append(p); } } tooltiptext = ` = ((${arrmin.join(" + ")}) + (${arrmax.join(" + ")})) / 2`; // tooltip = createTooltip(tooltip, "p", tooltiptext, label, ["spell-tooltip"]); } _damage_display("Non-Crit Average: ", nonCritAverage, 0); _damage_display("Crit Average: ", critAverage, 2); 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"); let first = document.createElement("span"); let second = document.createElement("span"); first.textContent = part.subtitle + ": "; second.textContent = heal_amount; overallhealLabel.appendChild(first); second.classList.add("Set"); overallhealLabel.appendChild(second); 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"); let overallaverageLabelFirst = document.createElement("span"); let overallaverageLabelSecond = document.createElement("span"); overallaverageLabelFirst.textContent = "Average: "; overallaverageLabelSecond.textContent = total_damage.toFixed(2); overallaverageLabelSecond.classList.add("Damage"); overallaverageLabel.appendChild(overallaverageLabelFirst); overallaverageLabel.appendChild(overallaverageLabelSecond); part_divavg.append(overallaverageLabel); } } } function displaysq2EquipOrder(parent_elem, buildOrder){ parent_elem.textContent = ""; const order = buildOrder.slice(); let title_elem = document.createElement("b"); title_elem.textContent = "Equip order "; title_elem.classList.add("Normal", "text-center"); parent_elem.append(title_elem); for (const item of order) { let p_elem = document.createElement("b"); p_elem.textContent = item.get("displayName"); parent_elem.append(p_elem); } } function displaysq2NextCosts(spell, build) { let int = build.total_skillpoints[2]; let spells = spell_table[build.weapon.get("type")]; 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.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.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 noUpdate = false; //forgive me... I couldn't inverse ceil, floor, and max. while (build.getSpellCost(spells.indexOf(spell) + 1, spell.cost) > target) { if(needed > 150) { noUpdate = true; break; } needed++; build.total_skillpoints[2] = needed; } let missing = needed - int; //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); }else { next_cost.textContent = (init_cost.textContent === "1" ? 1 : build.getSpellCost(spells.indexOf(spell) + 1, spell.cost)); } build.total_skillpoints[2] = int;//forgive me pt 2 int_needed.textContent = ": " + (needed > 150 ? ">150" : needed) + " int (+" + (needed > 150 ? "n/a" : missing) + ")"; } // row.appendChild(init_cost); row.appendChild(arrow); row.appendChild(next_cost); row.appendChild(int_needed); return row; } function apply_sq2_elemental_format(p_elem, id, suffix) { suffix = (typeof suffix !== 'undefined') ? suffix : ""; // THIS IS SO JANK BUT IM TOO LAZY TO FIX IT TODO let parts = idPrefixes[id].split(/ (.*)/); let element_prefix = parts[0]; let desc = parts[1]; let i_elem = document.createElement('span'); i_elem.classList.add(element_prefix); i_elem.textContent = element_prefix; p_elem.appendChild(i_elem); let i_elem2 = document.createElement('span'); i_elem2.textContent = " " + desc + suffix; p_elem.appendChild(i_elem2); } function displaysq2SetBonuses(parent_id,build) { setHTML(parent_id, ""); let parent_div = document.getElementById(parent_id); let set_summary_elem = document.createElement('p'); set_summary_elem.classList.add('text-center'); set_summary_elem.textContent = "Set Bonuses"; parent_div.append(set_summary_elem); for (const [setName, count] of build.activeSetCounts) { const active_set = sets[setName]; if (active_set["hidden"]) { continue; } let set_elem = document.createElement('p'); set_elem.id = "set-"+setName; set_summary_elem.append(set_elem); const bonus = active_set.bonuses[count-1]; let mock_item = new Map(); mock_item.set("fixID", true); mock_item.set("displayName", setName+" Set: "+count+"/"+sets[setName].items.length); let mock_minRolls = new Map(); let mock_maxRolls = new Map(); mock_item.set("minRolls", mock_minRolls); mock_item.set("maxRolls", mock_maxRolls); for (const id in bonus) { if (rolledIDs.includes(id)) { mock_minRolls.set(id, bonus[id]); mock_maxRolls.set(id, bonus[id]); } else { mock_item.set(id, bonus[id]); } } mock_item.set("powders", []); displaysq2ExpandedItem(mock_item, set_elem.id); console.log(mock_item); } } function toggle_plus_minus(elem_id) { let elem = document.getElementById(elem_id); if (elem.classList.contains("plus_minus")) { if (elem.textContent == "\u2795") { elem.textContent = "\u2796"; } else if (elem.textContent == "\u2796"){ elem.textContent = "\u2795"; } else { // ???? } } } // updates the powders within this element. function updatePowders(elem_id) { // let elem = document.getElementById(elem_id); // for (let i = 0; i < elem.value.length - 1; i++) { // if ('etwfa'.includes(elem.value.charAt(i)) && elem.value.charAt(i + 1) >= '1' && elem.value.charAt(i + 1) <= '6') { // elem.value = elem.value.substring(0, i) + powder_chars['etwfa'.indexOf(elem.value.charAt(i))] + elem.value.substring(i + 2); // } // } } /* * Displays stats about a recipe that are NOT displayed in the craft stats. * Includes: mat name and amounts, ingred names in an "array" with ingred effectiveness */ function displaysq2RecipeStats(craft, parent_id) { let elem = document.getElementById(parent_id); if (!elem.classList.contains("col")) { elem.classList.add("col"); } //local vars elem.textContent = ""; recipe = craft["recipe"]; mat_tiers = craft["mat_tiers"]; ingreds = []; for (const n of craft["ingreds"]) { ingreds.push(n.get("name")); } let effectiveness = craft["statMap"].get("ingredEffectiveness"); let title = document.createElement("div"); title.classList.add("row", "box-title", "fw-bold", "justify-content-center"); title.textContent = "Recipe Stats"; elem.appendChild(title); let mats = document.createElement("div"); mats.classList.add("row"); mats.textContent = "Crafting Materials: "; elem.appendChild(mats); for (let i = 0; i < 2; i++) { let tier = mat_tiers[i]; let row = document.createElement("div"); row.classList.add("row", "px-0", "mx-0"); let b = document.createElement("div"); let mat = recipe.get("materials")[i]; b.textContent = "- " + mat.get("amount") + "x " + mat.get("item").split(" ").slice(1).join(" "); b.classList.add("col"); row.appendChild(b); let starsB = document.createElement("div"); starsB.classList.add("T1-bracket", "col-auto", "px-0"); starsB.textContent = "["; row.appendChild(starsB); for(let j = 0; j < 3; j ++) { let star = document.createElement("div"); star.classList.add("col-auto", "px-0"); star.textContent = "\u272B"; if(j < tier) { star.classList.add("T1"); } else { star.classList.add("T0"); } row.append(star); } let starsE = document.createElement("div"); starsE.classList.add("T1-bracket", "col-auto", "px-0"); starsE.textContent = "]"; row.appendChild(starsE); elem.appendChild(row); } let ingredTable = document.createElement("div"); ingredTable.classList.add("row"); for (let i = 0; i < 3; i++) { let row = document.createElement("div"); row.classList.add("row", "g-1", "justify-content-center"); for (let j = 0; j < 2; j++) { if (j == 1) { let spacer = document.createElement("div"); spacer.classList.add("col-1"); row.appendChild(spacer); } let ingredName = ingreds[2 * i + j]; let col = document.createElement("div"); col.classList.add("col-5", "rounded", "dark-6", "border", "border-3", "dark-shadow"); let temp_row = document.createElement("div"); temp_row.classList.add("row"); col.appendChild(temp_row); let ingred_div = document.createElement("div"); ingred_div.classList.add("col"); ingred_div.textContent = ingredName; temp_row.appendChild(ingred_div); let eff_div = document.createElement("div"); eff_div.classList.add("col-auto"); let e = effectiveness[2 * i + j]; if (e > 0) { eff_div.classList.add("positive"); } else if (e < 0) { eff_div.classList.add("negative"); } eff_div.textContent = "[" + e + "%]"; temp_row.appendChild(eff_div); row.appendChild(col); } ingredTable.appendChild(row); } elem.appendChild(ingredTable); } /* * Displays an ingredient in item format. * However, an ingredient is too far from a normal item to display as one. */ function displaysq2ExpandedIngredient(ingred, parent_id) { let parent_elem = document.getElementById(parent_id); parent_elem.textContent = ""; let item_order = [ "dura", "strReq", "dexReq", "intReq", "defReq", "agiReq" ] let consumable_order = [ "dura", "charges" ] let posMods_order = [ "above", "under", "left", "right", "touching", "notTouching" ]; let id_display_order = [ "eDefPct", "tDefPct", "wDefPct", "fDefPct", "aDefPct", "eDamPct", "tDamPct", "wDamPct", "fDamPct", "aDamPct", "str", "dex", "int", "agi", "def", "hpBonus", "mr", "ms", "ls", "hprRaw", "hprPct", "sdRaw", "sdPct", "mdRaw", "mdPct", "xpb", "lb", "lq", "ref", "thorns", "expd", "spd", "atkTier", "poison", "spRegen", "eSteal", "spRaw1", "spRaw2", "spRaw3", "spRaw4", "spPct1", "spPct2", "spPct3", "spPct4", "jh", "sprint", "sprintReg", "gXp", "gSpd", ]; let active_elem; let elemental_format = false; let style; for (const command of sq2_ing_display_order) { if (command.charAt(0) === "!") { // TODO: This is sooo incredibly janky..... if (command === "!elemental") { elemental_format = !elemental_format; } else if (command === "!spacer") { let spacer = document.createElement('div'); spacer.classList.add("row", "my-2"); parent_elem.appendChild(spacer); continue; } } else { let div = document.createElement("div"); div.classList.add("row"); if (command === "displayName") { div.classList.add("box-title"); let title_elem = document.createElement("div"); title_elem.classList.add("col-auto", "justify-content-center", "pr-1"); title_elem.textContent = ingred.get("displayName"); div.appendChild(title_elem); let tier = ingred.get("tier"); //tier in [0,3] let begin = document.createElement("b"); begin.classList.add("T"+tier+"-bracket", "col-auto", "px-0"); begin.textContent = "["; div.appendChild(begin); for (let i = 0; i < 3; i++) { let tier_elem = document.createElement("b"); if (i < tier) { tier_elem.classList.add("T"+tier); } else { tier_elem.classList.add("T0"); } tier_elem.classList.add("px-0", "col-auto"); tier_elem.textContent = "\u272B"; div.appendChild(tier_elem); } let end = document.createElement("b"); end.classList.add("T"+tier+"-bracket", "px-0", "col-auto"); end.textContent = "]"; div.appendChild(end); }else if (command === "lvl") { div.textContent = "Crafting Lvl Min: " + ingred.get("lvl"); }else if (command === "posMods") { for (const [key,value] of ingred.get("posMods")) { let posModRow = document.createElement("div"); posModRow.classList.add("row"); if (value != 0) { let posMod = document.createElement("div"); posMod.classList.add("col-auto"); posMod.textContent = posModPrefixes[key]; posModRow.appendChild(posMod); let val = document.createElement("div"); val.classList.add("col-auto", "px-0"); val.textContent = value + posModSuffixes[key]; if(value > 0) { val.classList.add("positive"); } else { val.classList.add("negative"); } posModRow.appendChild(val); div.appendChild(posModRow); } } } else if (command === "itemIDs") { //dura, reqs for (const [key,value] of ingred.get("itemIDs")) { let idRow = document.createElement("div"); idRow.classList.add("row"); if (value != 0) { let title = document.createElement("div"); title.classList.add("col-auto"); title.textContent = itemIDPrefixes[key]; idRow.appendChild(title); } let desc = document.createElement("div"); desc.classList.add("col-auto"); if(value > 0) { if(key !== "dura") { desc.classList.add("negative"); } else{ desc.classList.add("positive"); } desc.textContent = "+"+value; } else if (value < 0){ if(key !== "dura") { desc.classList.add("positive"); } else{ desc.classList.add("negative"); } desc.textContent = value; } if(value != 0){ idRow.appendChild(desc); } div.appendChild(idRow); } } else if (command === "consumableIDs") { //dura, charges for (const [key,value] of ingred.get("consumableIDs")) { let idRow = document.createElement("div"); idRow.classList.add("row"); if (value != 0) { let title = document.createElement("div"); title.classList.add("col-auto"); title.textContent = consumableIDPrefixes[key]; idRow.appendChild(title); } let desc = document.createElement("div"); desc.classList.add("col-auto"); if(value > 0) { desc.classList.add("positive"); desc.textContent = "+"+value; } else if (value < 0){ desc.classList.add("negative"); desc.textContent = value; } if(value != 0){ idRow.appendChild(desc); let suffix = document.createElement("div"); suffix.classList.add("col-auto"); suffix.textContent = consumableIDSuffixes[key]; idRow.appendChild(suffix); } div.appendChild(idRow); } }else if (command === "skills") { let row = document.createElement("div"); row.classList.add("row"); let title = document.createElement("div"); title.classList.add("row"); title.textContent = "Used in:"; row.appendChild(title); for(const skill of ingred.get("skills")) { let skill_div = document.createElement("div"); skill_div.classList.add("row"); skill_div.textContent = skill.charAt(0) + skill.substring(1).toLowerCase(); row.appendChild(skill_div); } div.appendChild(row); } else if (command === "ids") { //warp for (let [key,value] of ingred.get("ids").get("maxRolls")) { if (value !== undefined && value != 0) { let row = displaysq2RolledID(ingred.get("ids"), key, elemental_format); row.classList.remove("col"); row.classList.remove("col-12"); div.appendChild(row); } } } else {//this shouldn't be happening } parent_elem.appendChild(div); } } } //TODO: translate the below to BS /** Displays Additional Info for * * @param {String} elemID - the parent element's id * @param {Map} item - the statMap of the item * @returns */ function displaysq2AdditionalInfo(elemID, item) { let parent_elem = document.getElementById(elemID); let title = document.createElement("div"); title.classList.add("big-title", "justify-content-center"); title.textContent = "Additional Info"; parent_elem.appendChild(title); let droptype_elem = document.createElement("div"); droptype_elem.classList.add("row"); droptype_elem.textContent = "Drop type: " + (item.has("drop") ? item.get("drop"): "NEVER"); parent_elem.appendChild(droptype_elem); let warning_elem = document.createElement("div"); warning_elem.classList.add("row"); warning_elem.textContent = "This page is incomplete. Will work on it later."; parent_elem.appendChild(warning_elem); return; } /** Displays the ID costs of an item * * @param {String} elemID - the id of the parent element. * @param {Map} item - the statMap of an item. */ function displaysq2IDCosts(elemID, item) { let parent_elem = document.getElementById(elemID); let tier = item.get("tier"); if ( (item.has("fixID") && item.get("fixID")) || ["Normal","Crafted","Custom","none", " ",].includes(item.get("tier"))) { return; } else { /** Returns the number of inventory slots minimum an amount of emeralds would take up + the configuration of doing so. * Returns an array of [invSpace, E, EB, LE, Stx LE] * * @param {number} ems - the total numerical value of emeralds to compact. */ function emsToInvSpace(ems) { let stx = Math.floor(ems/262144); ems -= stx*4096*64; let LE = Math.floor(ems/4096); ems -= LE*4096; let EB = Math.floor(ems/64); ems -= EB*64; let e = ems; return [ stx + Math.ceil(LE/64) + Math.ceil(EB/64) + Math.ceil(e/64) , e, EB, LE, stx]; } /** * * @param {String} tier - item tier * @param {Number} lvl - item level */ function getIDCost(tier, lvl) { switch (tier) { case "Unique": return Math.round(0.5*lvl + 3); case "Rare": return Math.round(1.2*lvl + 8); case "Legendary": return Math.round(4.5*lvl + 12); case "Fabled": return Math.round(12*lvl + 26); case "Mythic": return Math.round(18*lvl + 90); case "Set": return Math.round(1.5*lvl + 8) default: return -1; } } parent_elem.style = "display: visible"; let lvl = item.get("lvl"); if (typeof(lvl) === "string") { lvl = parseFloat(lvl); } let title_elem = document.createElement("div"); title_elem.classList.add("big-title", "justify-content-center", "Set"); title_elem.textContent = "Identification Costs"; parent_elem.appendChild(title_elem); let grid_item = document.createElement("div"); grid_item.classList.add("row", "g-3"); parent_elem.appendChild(grid_item); let IDcost = getIDCost(tier, lvl); let initIDcost = IDcost; let invSpace = emsToInvSpace(IDcost); let rerolls = 0; while(invSpace[0] <= 28 && IDcost > 0) { let container_container = document.createElement("div"); container_container.classList.add("col-lg-3", "col-sm-12"); let container = document.createElement("div"); container.classList.add("col", "rounded", "border", "border-dark", "border-2"); container_container.appendChild(container); let container_title = document.createElement("div"); container_title.classList.add("row", "box-title", "justify-content-center"); if (rerolls == 0) { container_title.textContent = "Initial ID Cost: "; } else { container_title.textContent = "Reroll to [" + (rerolls+1) + "] Cost:"; } container.appendChild(container_title); let total_cost_container = document.createElement("div"); total_cost_container.classList.add("row"); let total_cost_number = document.createElement("b"); total_cost_number.classList.add("Set", "fw-bold", "col-6", "text-end"); total_cost_number.textContent = IDcost + " "; let total_cost_suffix = document.createElement("div"); total_cost_suffix.classList.add("col-6", "text-start"); total_cost_suffix.textContent = "emeralds." total_cost_container.appendChild(total_cost_number); total_cost_container.appendChild(total_cost_suffix); container.appendChild(total_cost_container); let OR = document.createElement("div"); OR.classList.add("row"); container.appendChild(OR); let OR_text = document.createElement("div"); OR_text.classList.add("col", "text-center"); OR_text.textContent = "OR"; OR.appendChild(OR_text); let esuffixes = ["", "emeralds.", "EB.", "LE.", "stacks of LE."]; for (let i = 4; i > 0; i--) { let n_container = document.createElement("div"); n_container.classList.add("row"); let n_number = document.createElement("b"); n_number.classList.add("Set", "fw-bold", "col-6", "text-end"); n_number.textContent = invSpace[i] + " "; let n_suffix = document.createElement("div"); n_suffix.classList.add("col-6", "text-start"); n_suffix.textContent = esuffixes[i]; n_container.appendChild(n_number); n_container.appendChild(n_suffix); container.appendChild(n_container); } grid_item.appendChild(container_container); rerolls += 1; IDcost = Math.round(initIDcost * (5 ** rerolls)); invSpace = emsToInvSpace(IDcost); } } } /** Displays all set bonuses (0/n, 1/n, ... n/n) for a given set * * @param {String} parent_id - id of the parent element * @param {String} setName - the name of the set */ function displaysq2AllSetBonuses(parent_id, setName) { let parent_elem = document.getElementById(parent_id); parent_elem.style.display = ""; let set = sets[setName]; let title_elem = document.createElement("div"); title_elem.textContent = setName + " Set Bonuses"; title_elem.classList.add("Set", "big-title", "justify-content-center"); parent_elem.appendChild(title_elem); let grid_elem = document.createElement("div"); grid_elem.classList.add("row"); parent_elem.appendChild(grid_elem); for (let i = 0; i < set.items.length; i++) { let set_elem = document.createElement('div'); set_elem.classList.add("col-lg-3", "col-sm-12", "py-2", "my-1"); grid_elem.appendChild(set_elem); const bonus = set.bonuses[i]; let set_elem_display = document.createElement("div"); set_elem_display.classList.add("rounded", "col", "g-0", "scaled-font", "border", "border-3", "border-dark", "dark-shadow", "dark-7", "p-3"); set_elem_display.id = "set-"+setName+"-"+i; set_elem.appendChild(set_elem_display); let mock_item = new Map(); mock_item.set("fixID", true); mock_item.set("tier", "Set"); mock_item.set("displayName", setName+" Set: " + (i+1) + "/"+sets[setName].items.length); // set_elem.textContent = mock_item.get("displayName"); let mock_minRolls = new Map(); let mock_maxRolls = new Map(); mock_item.set("minRolls", mock_minRolls); mock_item.set("maxRolls", mock_maxRolls); for (const id in bonus) { if (rolledIDs.includes(id)) { mock_minRolls.set(id, bonus[id]); mock_maxRolls.set(id, bonus[id]); } else { mock_item.set(id, bonus[id]); } } mock_item.set("powders", []); displaysq2ExpandedItem(mock_item, set_elem_display.id); } } /** Displays the individual probabilities of each possible value of each rollable ID for this item. * * @param {String} parent_id the document id of the parent element * @param {String} item expandedItem object * @param {String} amp the level of corkian amplifier used. 0 means no amp, 1 means Corkian Amplifier I, etc. [0,3] */ function displaysq2IDProbabilities(parent_id, item, amp) { if (item.has("fixID") && item.get("fixID")) {return} let parent_elem = document.getElementById(parent_id); parent_elem.style.display = ""; parent_elem.innerHTML = ""; let title_elem = document.createElement("div"); title_elem.textContent = "Identification Probabilities"; title_elem.classList.add("row", "Legendary", "big-title", "justify-content-center"); parent_elem.appendChild(title_elem); let disclaimer_elem = document.createElement("div"); disclaimer_elem.classList.add("row", "justify-content-center"); disclaimer_elem.textContent = "IDs are rolled on a uniform distribution. A chance of 0% means that either the minimum or maximum possible multiplier must be rolled to get this value." parent_elem.appendChild(disclaimer_elem); let amp_row = document.createElement("div"); amp_row.classList.add("row", "justify-content-center"); amp_row.id = "amp_row"; let amp_text = document.createElement("div"); amp_text.classList.add("col-lg-2", "col-sm-3"); amp_text.textContent = "Corkian Amplifier Used: " amp_row.appendChild(amp_text); let amp_1 = document.createElement("button"); amp_1.classList.add("col-lg-1", "col-sm-3", "border-dark", "text-light", "dark-5", "rounded", "scaled-font"); amp_1.id = "cork_amp_1"; amp_1.textContent = "I"; amp_row.appendChild(amp_1); let amp_2 = document.createElement("button"); amp_2.classList.add("col-lg-1", "col-sm-3", "border-dark", "text-light", "dark-5", "rounded", "scaled-font"); amp_2.id = "cork_amp_2"; amp_2.textContent = "II"; amp_row.appendChild(amp_2); let amp_3 = document.createElement("button"); amp_3.classList.add("col-lg-1", "col-sm-3", "border-dark", "text-light", "dark-5", "rounded", "scaled-font"); amp_3.id = "cork_amp_3"; amp_3.textContent = "III"; amp_row.appendChild(amp_3); amp_1.addEventListener("click", (event) => {toggleAmps(1)}); amp_2.addEventListener("click", (event) => {toggleAmps(2)}); amp_3.addEventListener("click", (event) => {toggleAmps(3)}); parent_elem.appendChild(amp_row); if (amp != 0) {toggleButton("cork_amp_" + amp)} item_name = item.get("displayName"); for (const [id,val] of Object.entries(itemMap.get(item_name))) { if (rolledIDs.includes(id)) { let min = item.get("minRolls").get(id); let max = item.get("maxRolls").get(id); if (min != 0 || max != 0) { //Apply corkian amps if (val > 0) { let base = itemMap.get(item_name)[id]; if (reversedIDs.includes(id)) {max = Math.max( Math.round((0.3 + 0.05*amp) * base), 1)} else {min = Math.max( Math.round((0.3 + 0.05*amp) * base), 1)} } let row_elem = document.createElement("div"); row_elem.classList.add("row"); parent_elem.appendChild(row_elem); let base_and_range = document.createElement("div"); base_and_range.classList.add("col-lg-4", "col-sm-12"); let base_elem = document.createElement("div"); let base_val = document.createElement("div"); base_elem.classList.add("row"); base_prefix = document.createElement("div"); base_prefix.classList.add("col-auto"); base_val.classList.add("col-auto"); base_prefix.textContent = idPrefixes[id] + "Base "; base_val.textContent = val + idSuffixes[id]; if (val > 0 == !reversedIDs.includes(id)) { base_val.classList.add("positive"); } else if (val > 0 == reversedIDs.includes(id)) { base_val.classList.add("negative"); } base_elem.appendChild(base_prefix); base_elem.appendChild(base_val); let range_elem = document.createElement("div"); range_elem.classList.add("row", "justify-content-center"); range_elem.textContent = "[ " + min + idSuffixes[id] + ", " + max + idSuffixes[id] + " ]"; if ( (min > 0 && max > 0 && !reversedIDs.includes(id)) || (min < 0 && max < 0 && reversedIDs.includes(id)) ) { range_elem.classList.add("positive"); } else if ( (min < 0 && max < 0 && !reversedIDs.includes(id)) || (min > 0 && max > 0 && reversedIDs.includes(id)) ) { range_elem.classList.add("negative"); } base_and_range.appendChild(base_elem); base_and_range.appendChild(range_elem); row_elem.appendChild(base_and_range); let pdf_and_cdf = document.createElement("div"); pdf_and_cdf.classList.add("col-lg-4", "col-sm-12"); let pdf_elem = document.createElement("div"); pdf_elem.id = id + "-pdf"; let cdf_elem = document.createElement("div"); cdf_elem.id = id + "-cdf"; pdf_elem.classList.add("row"); cdf_elem.classList.add("row"); pdf_and_cdf.appendChild(pdf_elem); pdf_and_cdf.appendChild(cdf_elem); row_elem.appendChild(pdf_and_cdf); let input_sec = document.createElement("div"); input_sec.classList.add("col-lg-4", "col-sm-12"); let title_input_slider = document.createElement("input"); title_input_slider.classList.add("row"); title_input_slider.type = "range"; title_input_slider.id = id+"-slider"; if (!reversedIDs.includes(id)) { title_input_slider.step = 1; title_input_slider.min = `${min}`; title_input_slider.max = `${max}`; title_input_slider.value = `${max}`; } else { title_input_slider.step = 1; title_input_slider.min = `${-1*min}`; title_input_slider.max = `${-1*max}`; title_input_slider.value = `${-1*max}`; } let title_input_textbox = document.createElement("input"); title_input_textbox.classList.add("row"); title_input_textbox.type = "text"; title_input_textbox.value = `${max}`; title_input_textbox.id = id+"-textbox"; title_input_textbox.classList.add("rounded", "border", "border-dark", "border-2", "dark-5", "text-light"); input_sec.appendChild(title_input_slider); input_sec.appendChild(title_input_textbox); row_elem.appendChild(input_sec); sq2StringPDF(id, max, val, amp); //val is base roll sq2StringCDF(id, max, val, amp); //val is base roll title_input_slider.addEventListener("change", (event) => { let id_name = event.target.id.split("-")[0]; let textbox_elem = document.getElementById(id_name+"-textbox"); if (reversedIDs.includes(id_name)) { if (event.target.value < -1*min) { event.target.value = -1*min} if (event.target.value > -1*max) { event.target.value = -1*max} sq2StringPDF(id_name, -1*event.target.value, val, amp); //val is base roll sq2StringCDF(id_name, -1*event.target.value, val, amp); //val is base roll } else { if (event.target.value < min) { event.target.value = min} if (event.target.value > max) { event.target.value = max} sq2StringPDF(id_name, 1*event.target.value, val, amp); //val is base roll sq2StringCDF(id_name, 1*event.target.value, val, amp); //val is base roll } if (textbox_elem && textbox_elem.value !== event.target.value) { if (reversedIDs.includes(id_name)) { textbox_elem.value = -event.target.value; } else { textbox_elem.value = event.target.value; } } }); title_input_textbox.addEventListener("change", (event) => { let id_name = event.target.id.split("-")[0]; if (reversedIDs.includes(id_name)) { if (event.target.value > min) { event.target.value = min} if (event.target.value < max) { event.target.value = max} } else { if (event.target.value < min) { event.target.value = min} if (event.target.value > max) { event.target.value = max} } let slider_elem = document.getElementById(id_name+"-slider"); if (slider_elem.value !== event.target.value) { slider_elem.value = -event.target.value; } sq2StringPDF(id_name, 1*event.target.value, val, amp); sq2StringCDF(id_name, 1*event.target.value, val, amp); }); } } } } //helper functions. id - the string of the id's name, val - the value of the id, base - the base value of the item for this id function sq2StringPDF(id,val,base,amp) { /** [0.3b,1.3b] positive normal * [1.3b,0.3b] positive reversed * [1.3b,0.7b] negative normal * [0.7b,1.3b] negative reversed * * [0.3, 1.3] minr, maxr [0.3b, 1.3b] min, max * the minr/maxr decimal roll that corresponds to val -> minround, maxround */ let p; let min; let max; let minr; let maxr; let minround; let maxround; if (base > 0) { minr = 0.3 + 0.05*amp; maxr = 1.3; min = Math.max(1, Math.round(minr*base)); max = Math.max(1, Math.round(maxr*base)); minround = (min == max) ? (minr) : ( Math.max(minr, (val-0.5) / base) ); maxround = (min == max) ? (maxr) : ( Math.min(maxr, (val+0.5) / base) ); } else { minr = 1.3; maxr = 0.7; min = Math.min(-1, Math.round(minr*base)); max = Math.min(-1, Math.round(maxr*base)); minround = (min == max) ? (minr) : ( Math.min(minr, (val-0.5) / base) ); maxround = (min == max) ? (maxr) : ( Math.max(maxr, (val+0.5) / base) ); } p = Math.abs(maxround-minround)/Math.abs(maxr-minr)*100; p = p.toFixed(3); let div1 = document.createElement("div"); div1.textContent = "Roll exactly "; div1.classList.add("col-auto", "px-0"); let div2 = document.createElement("div"); div2.textContent = val + idSuffixes[id]; div2.classList.add("col-auto", "px-1"); if (val > 0 == !reversedIDs.includes(id)) {div2.classList.add("positive")} if (val > 0 == reversedIDs.includes(id)) {div2.classList.add("negative")} let div3 = document.createElement("div"); div3.textContent = ": " + p + "%"; div3.classList.add("col-auto", "px-0"); document.getElementById(id + "-pdf").innerHTML = ""; document.getElementById(id + "-pdf").appendChild(div1); document.getElementById(id + "-pdf").appendChild(div2); document.getElementById(id + "-pdf").appendChild(div3); } function sq2StringCDF(id,val,base,amp) { let p; let min; let max; let minr; let maxr; let minround; let maxround; if (base > 0) { minr = 0.3 + 0.05*amp; maxr = 1.3; min = Math.max(1, Math.round(minr*base)); max = Math.max(1, Math.round(maxr*base)); minround = (min == max) ? (minr) : ( Math.max(minr, (val-0.5) / base) ); maxround = (min == max) ? (maxr) : ( Math.min(maxr, (val+0.5) / base) ); } else { minr = 1.3; maxr = 0.7; min = Math.min(-1, Math.round(minr*base)); max = Math.min(-1, Math.round(maxr*base)); minround = (min == max) ? (minr) : ( Math.min(minr, (val-0.5) / base) ); maxround = (min == max) ? (maxr) : ( Math.max(maxr, (val+0.5) / base) ); } if (reversedIDs.includes(id)) { p = Math.abs(minr-maxround)/Math.abs(maxr-minr)*100; } else { p = Math.abs(maxr-minround)/Math.abs(maxr-minr)*100; } p = p.toFixed(3); let div1 = document.createElement("div"); div1.textContent = "Roll "; div1.classList.add("col-auto", "px-0"); let div2 = document.createElement("div"); div2.textContent = val + idSuffixes[id]; div2.classList.add("col-auto", "px-1"); if (val > 0 == !reversedIDs.includes(id)) {div2.classList.add("positive")} if (val > 0 == reversedIDs.includes(id)) {div2.classList.add("negative")} let div3 = document.createElement("div"); div3.textContent= " or better: " + p + "%"; div3.classList.add("col-auto", "px-0"); document.getElementById(id + "-cdf").innerHTML = ""; document.getElementById(id + "-cdf").appendChild(div1); document.getElementById(id + "-cdf").appendChild(div2); document.getElementById(id + "-cdf").appendChild(div3); }