diff --git a/atlas.html b/atlas.html index dd41f3e..b33f36d 100644 --- a/atlas.html +++ b/atlas.html @@ -36,6 +36,11 @@
WynnCustom
+ + + +
WynnGPS
+
diff --git a/build.js b/build.js index 65685e2..7aab5eb 100644 --- a/build.js +++ b/build.js @@ -96,16 +96,17 @@ class Build{ * @description Construct a build. * @param {Number} level : Level of the player. * @param {String[]} equipment : List of equipment names that make up the build. - * In order: Helmet, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon. + * In order: boots, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon. * @param {Number[]} powders : Powder application. List of lists of integers (powder IDs). - * In order: Helmet, Chestplate, Leggings, Boots, Weapon. + * In order: boots, Chestplate, Leggings, Boots, Weapon. * @param {Object[]} inputerrors : List of instances of error-like classes. */ constructor(level,equipment, powders, externalStats, inputerrors=[]){ let errors = inputerrors; - //this contains the Craft objects, if there are any crafted items. this.helmet, etc. will contain the statMap of the Craft (which is built to be an expandedItem). + //this contains the Craft objects, if there are any crafted items. this.boots, etc. will contain the statMap of the Craft (which is built to be an expandedItem). this.craftedItems = []; + this.customItems = []; // NOTE: powders is just an array of arrays of powder IDs. Not powder objects. this.powders = powders; if(itemMap.get(equipment[0]) && itemMap.get(equipment[0]).type === "helmet") { @@ -114,7 +115,8 @@ class Build{ this.helmet = expandItem(helmet, this.powders[0]); } else { try { - let helmet = getCraftFromHash(equipment[0]); + //let boots = getCraftFromHash(equipment[0]) ? getCraftFromHash(equipment[0]) : (getCustomFromHash(equipment[0])? getCustomFromHash(equipment[0]) : undefined); + let helmet = getCustomFromHash(equipment[0]) ? getCustomFromHash(equipment[0]) : (getCraftFromHash(equipment[0]) ? getCraftFromHash(equipment[0]) : undefined); if (helmet.statMap.get("type") !== "helmet") { throw new Error("Not a helmet"); } @@ -122,7 +124,12 @@ class Build{ helmet.statMap.set("powders",this.powders[0].slice()); helmet.applyPowders(); this.helmet = helmet.statMap; - this.craftedItems.push(helmet); + if (this.helmet.get("custom")) { + this.customItems.push(helmet); + } else if (this.helmet.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(helmet); + } + } catch (Error) { //console.log(Error); //fix const helmet = itemMap.get("No Helmet"); @@ -137,7 +144,7 @@ class Build{ this.chestplate = expandItem(chestplate, this.powders[1]); } else { try { - let chestplate = getCraftFromHash(equipment[1]); + let chestplate = getCustomFromHash(equipment[1]) ? getCustomFromHash(equipment[1]) : (getCraftFromHash(equipment[1]) ? getCraftFromHash(equipment[1]) : undefined); if (chestplate.statMap.get("type") !== "chestplate") { throw new Error("Not a chestplate"); } @@ -145,7 +152,11 @@ class Build{ chestplate.statMap.set("powders",this.powders[1].slice()); chestplate.applyPowders(); this.chestplate = chestplate.statMap; - this.craftedItems.push(chestplate); + if (this.chestplate.get("custom")) { + this.customItems.push(chestplate); + } else if (this.chestplate.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(chestplate); + } } catch (Error) { const chestplate = itemMap.get("No Chestplate"); this.powders[1] = this.powders[1].slice(0,chestplate.slots); @@ -159,7 +170,7 @@ class Build{ this.leggings = expandItem(leggings, this.powders[2]); } else { try { - let leggings = getCraftFromHash(equipment[2]); + let leggings = getCustomFromHash(equipment[2]) ? getCustomFromHash(equipment[2]) : (getCraftFromHash(equipment[2]) ? getCraftFromHash(equipment[2]) : undefined); if (leggings.statMap.get("type") !== "leggings") { throw new Error("Not a leggings"); } @@ -167,7 +178,11 @@ class Build{ leggings.statMap.set("powders",this.powders[2].slice()); leggings.applyPowders(); this.leggings = leggings.statMap; - this.craftedItems.push(leggings); + if (this.leggings.get("custom")) { + this.customItems.push(leggings); + } else if (this.leggings.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(leggings); + } } catch (Error) { const leggings = itemMap.get("No Leggings"); this.powders[2] = this.powders[2].slice(0,leggings.slots); @@ -181,7 +196,7 @@ class Build{ this.boots = expandItem(boots, this.powders[3]); } else { try { - let boots = getCraftFromHash(equipment[3]); + let boots = getCustomFromHash(equipment[3]) ? getCustomFromHash(equipment[3]) : (getCraftFromHash(equipment[3]) ? getCraftFromHash(equipment[3]) : undefined); if (boots.statMap.get("type") !== "boots") { throw new Error("Not a boots"); } @@ -190,7 +205,11 @@ class Build{ boots.applyPowders(); this.boots = boots.statMap; console.log(boots); - this.craftedItems.push(boots); + if (this.boots.get("custom")) { + this.customItems.push(boots); + } else if (this.boots.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(boots); + } } catch (Error) { const boots = itemMap.get("No Boots"); this.powders[3] = this.powders[3].slice(0,boots.slots); @@ -203,12 +222,16 @@ class Build{ this.ring1 = expandItem(ring, []); }else{ try { - let ring = getCraftFromHash(equipment[4]); + let ring = getCustomFromHash(equipment[4]) ? getCustomFromHash(equipment[4]) : (getCraftFromHash(equipment[4]) ? getCraftFromHash(equipment[4]) : undefined); if (ring.statMap.get("type") !== "ring") { throw new Error("Not a ring"); } this.ring1 = ring.statMap; - this.craftedItems.push(ring); + if (this.ring1.get("custom")) { + this.customItems.push(ring); + } else if (this.ring1.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(ring); + } } catch (Error) { const ring = itemMap.get("No Ring 1"); this.ring1 = expandItem(ring, []); @@ -220,12 +243,16 @@ class Build{ this.ring2 = expandItem(ring, []); }else{ try { - let ring = getCraftFromHash(equipment[5]); + let ring = getCustomFromHash(equipment[5]) ? getCustomFromHash(equipment[5]) : (getCraftFromHash(equipment[5]) ? getCraftFromHash(equipment[5]) : undefined); if (ring.statMap.get("type") !== "ring") { throw new Error("Not a ring"); } this.ring2 = ring.statMap; - this.craftedItems.push(ring); + if (this.ring2.get("custom")) { + this.customItems.push(ring); + } else if (this.ring2.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(ring); + } } catch (Error) { const ring = itemMap.get("No Ring 2"); this.ring2 = expandItem(ring, []); @@ -237,12 +264,16 @@ class Build{ this.bracelet = expandItem(bracelet, []); }else{ try { - let bracelet = getCraftFromHash(equipment[6]); + let bracelet = getCustomFromHash(equipment[6]) ? getCustomFromHash(equipment[6]) : (getCraftFromHash(equipment[6]) ? getCraftFromHash(equipment[6]) : undefined); if (bracelet.statMap.get("type") !== "bracelet") { throw new Error("Not a bracelet"); } this.bracelet = bracelet.statMap; - this.craftedItems.push(bracelet); + if (this.bracelet.get("custom")) { + this.customItems.push(bracelet); + } else if (this.bracelet.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(bracelet); + } } catch (Error) { const bracelet = itemMap.get("No Bracelet"); this.bracelet = expandItem(bracelet, []); @@ -254,12 +285,16 @@ class Build{ this.necklace = expandItem(necklace, []); }else{ try { - let necklace = getCraftFromHash(equipment[7]); + let necklace = getCustomFromHash(equipment[7]) ? getCustomFromHash(equipment[7]) : (getCraftFromHash(equipment[7]) ? getCraftFromHash(equipment[7]) : undefined); if (necklace.statMap.get("type") !== "necklace") { throw new Error("Not a necklace"); } this.necklace = necklace.statMap; - this.craftedItems.push(necklace); + if (this.necklace.get("custom")) { + this.customItems.push(necklace); + } else if (this.necklace.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(necklace); + } } catch (Error) { const necklace = itemMap.get("No Necklace"); this.necklace = expandItem(necklace, []); @@ -277,12 +312,16 @@ class Build{ } }else{ try { - let weapon = getCraftFromHash(equipment[8]); + let weapon = getCustomFromHash(equipment[8]) ? getCustomFromHash(equipment[8]) : (getCraftFromHash(equipment[8]) ? getCraftFromHash(equipment[8]) : undefined); if (weapon.statMap.get("category") !== "weapon") { throw new Error("Not a weapon"); } this.weapon = weapon.statMap; - this.craftedItems.push(weapon); + if (this.weapon.get("custom")) { + this.customItems.push(weapon); + } else if (this.weapon.get("crafted")) { //customs can also be crafted, but custom takes priority. + this.craftedItems.push(weapon); + } this.powders[4] = this.powders[4].slice(0,this.weapon.slots); this.weapon.set("powders",this.powders[4].slice()); document.getElementsByClassName("powder-specials")[0].style.display = "grid"; @@ -294,7 +333,7 @@ class Build{ errors.push(new ItemNotFound(equipment[8], "weapon", true)); } } - console.log(this.craftedItems) + //console.log(this.craftedItems) if (level < 1) { //Should these be constants? this.level = 1; @@ -362,6 +401,9 @@ class Build{ */ getMeleeStats(){ const stats = this.statMap; + if (this.weapon.get("tier") === "Crafted") { + stats.set("damageBases", [this.weapon.get("nDamBaseHigh"),this.weapon.get("eDamBaseHigh"),this.weapon.get("tDamBaseHigh"),this.weapon.get("wDamBaseHigh"),this.weapon.get("fDamBaseHigh"),this.weapon.get("aDamBaseHigh")]); + } let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier"); if(adjAtkSpd > 6){ adjAtkSpd = 6; diff --git a/builder.js b/builder.js index ccc3694..ee151af 100644 --- a/builder.js +++ b/builder.js @@ -2,7 +2,7 @@ const url_tag = location.hash.slice(1); console.log(url_base); console.log(url_tag); -const BUILD_VERSION = "6.9.42"; +const BUILD_VERSION = "6.9.42.0"; function setTitle() { let text; @@ -82,15 +82,7 @@ let powderInputs = [ "weapon-powder", ]; -let itemTypes = armorTypes.concat(accessoryTypes).concat(weaponTypes); -let itemLists = new Map(); -for (const it of itemTypes) { - itemLists.set(it, []); -} -let itemMap = new Map(); -/* Mapping from item names to set names. */ -let idMap = new Map(); -let redirectMap = new Map(); + /* * Function that takes an item list and populates its corresponding dropdown. @@ -109,58 +101,7 @@ function populateItemList(type) { * Populate dropdowns, add listeners, etc. */ function init() { - let noneItems = [ - ["armor", "helmet", "No Helmet"], - ["armor", "chestplate", "No Chestplate"], - ["armor", "leggings", "No Leggings"], - ["armor", "boots", "No Boots"], - ["accessory", "ring", "No Ring 1"], - ["accessory", "ring", "No Ring 2"], - ["accessory", "bracelet", "No Bracelet"], - ["accessory", "necklace", "No Necklace"], - ["weapon", "dagger", "No Weapon"], - ]; - for (let i = 0; i < 9; i++) { - let item = Object(); - item.slots = 0; - item.category = noneItems[i][0]; - item.type = noneItems[i][1]; - item.name = noneItems[i][2]; - item.displayName = item.name; - item.set = null; - item.quest = null; - item.skillpoints = [0, 0, 0, 0, 0]; - item.has_negstat = false; - item.reqs = [0, 0, 0, 0, 0]; - item.fixID = true; - item.tier = " ";//do not get rid of this @hpp - item.id = 10000 + i; - item.nDam = "0-0"; - item.eDam = "0-0"; - item.tDam = "0-0"; - item.wDam = "0-0"; - item.fDam = "0-0"; - item.aDam = "0-0"; - - noneItems[i] = item; - } - items = items.concat(noneItems); - console.log(items); - for (const item of items) { - if (item.remapID === undefined) { - itemLists.get(item.type).push(item.displayName); - itemMap.set(item.displayName, item); - if (noneItems.includes(item)) { - idMap.set(item.id, ""); - } - else { - idMap.set(item.id, item.displayName); - } - } - else { - redirectMap.set(item.id, item.remapID); - } - } + for (const armorType of armorTypes) { populateItemList(armorType); @@ -171,13 +112,13 @@ function init() { if (itemMap.has(item_name)) { let item = itemMap.get(item_name); nSlots = item["slots"]; - console.log(item); + //console.log(item); } else { - let crafted_item = getCraftFromHash(item_name); - if (crafted_item != undefined) { - nSlots = crafted_item.statMap.get("slots"); - } + 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"; @@ -213,9 +154,10 @@ function init() { // Add change listener to update weapon slots. document.getElementById("weapon-choice").addEventListener("change", (event) => { - let item = itemMap.has(event.target.value) ? itemMap.get(event.target.value) : (getCraftFromHash(event.target.value) != undefined ? getCraftFromHash(event.target.value).statMap : undefined); + 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.get ? item.get("slots") : 0))+ " slots"; + 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"; } @@ -274,7 +216,7 @@ function decodeBuild(url_tag) { } info[1] = equipments.slice(27); } - if (version === "4") { + if (version === "4") { let info_str = info[1]; let start_idx = 0; for (let i = 0; i < 9; ++i ) { @@ -290,7 +232,25 @@ function decodeBuild(url_tag) { } info[1] = info_str.slice(start_idx); } - + if (version === "5") { + let info_str = info[1]; + let start_idx = 0; + for (let i = 0; i < 9; ++i ) { + if (info_str.slice(start_idx,start_idx+3) === "CR-") { + equipment[i] = info_str.slice(start_idx, start_idx+20); + start_idx += 20; + } else if (info_str.slice(start_idx+3,start_idx+6) === "CI-") { + let len = Base64.toInt(info_str.slice(start_idx,start_idx+3)); + equipment[i] = info_str.slice(start_idx+3,start_idx+3+len); + start_idx += (3+len); + } else { + let equipment_str = info_str.slice(start_idx, start_idx+3); + equipment[i] = getItemNameFromID(Base64.toInt(equipment_str)); + start_idx += 3; + } + } + info[1] = info_str.slice(start_idx); + } if (version === "1") { let powder_info = info[1]; powdering = parsePowdering(powder_info); @@ -303,7 +263,7 @@ function decodeBuild(url_tag) { let powder_info = info[1].slice(10); powdering = parsePowdering(powder_info); - } else if (version === "3" || version === "4"){ + } else if (version === "3" || version === "4" || version === "5"){ level = Base64.toInt(info[1].slice(10,12)); setValue("level-choice",level); save_skp = true; @@ -331,15 +291,19 @@ function decodeBuild(url_tag) { */ function encodeBuild() { if (player_build) { - //@hpp update for 4_ - let build_string = "4_"; + let build_string = "5_"; let crafted_idx = 0; + let custom_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 { + + 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); } } @@ -439,7 +403,7 @@ function calculateBuild(save_skp, skp){ else errors.push(new IncorrectInput(errorederrors[0], "t6 or e3", powderInputs[i])); } - console.log("POWDERING: " + powdering); + //console.log("POWDERING: " + powdering); powderings.push(powdering); } @@ -794,7 +758,8 @@ function calculateBuildStats() { for (const item of player_build.items) { let item_lvl; if (item.get("crafted")) { - item_lvl = parseInt(item.get("lvl").split("-")[0]); + //item_lvl = item.get("lvlLow") + "-" + item.get("lvl"); + item_lvl = item.get("lvlLow"); } else { item_lvl = item.get("lvl"); diff --git a/craft.js b/craft.js index 84cfcb8..1f65c59 100644 --- a/craft.js +++ b/craft.js @@ -3,28 +3,35 @@ //constructs a craft from a hash 'CR-qwoefsabaoe' or 'qwoefsaboe' function getCraftFromHash(hash) { let name = hash.slice(); - if (name.slice(0,3) === "CR-") { - name = name.substring(3); - } - version = name.substring(0,1); - name = name.substring(1); - if (version === "1") { - let ingreds = []; - for (let i = 0; i < 6; i ++ ) { - ingreds.push( expandIngredient(ingMap.get(ingIDMap.get(Base64.toInt(name.substring(2*i,2*i+2))))) ); + try { + if (name.slice(0,3) === "CR-") { + name = name.substring(3); + } else { + throw new Error("Not a crafted item!"); } - let recipe = expandRecipe(recipeMap.get(recipeIDMap.get(Base64.toInt(name.substring(12,14))))); - - tierNum = Base64.toInt(name.substring(14,15)); - let mat_tiers = []; - mat_tiers.push(tierNum % 3 == 0 ? 3 : tierNum % 3); - mat_tiers.push(Math.floor((tierNum-0.5) / 3)+1); //Trying to prevent round-off error, don't yell at me - let atkSpd = Base64.toInt(name.substring(15)); - let atkSpds = ["SLOW","NORMAL","FAST"]; - let attackSpeed = atkSpds[atkSpd]; - return new Craft(recipe,mat_tiers,ingreds,attackSpeed,"1"+name); + version = name.substring(0,1); + name = name.substring(1); + if (version === "1") { + let ingreds = []; + for (let i = 0; i < 6; i ++ ) { + ingreds.push( expandIngredient(ingMap.get(ingIDMap.get(Base64.toInt(name.substring(2*i,2*i+2))))) ); + } + let recipe = expandRecipe(recipeMap.get(recipeIDMap.get(Base64.toInt(name.substring(12,14))))); + + tierNum = Base64.toInt(name.substring(14,15)); + let mat_tiers = []; + mat_tiers.push(tierNum % 3 == 0 ? 3 : tierNum % 3); + mat_tiers.push(Math.floor((tierNum-0.5) / 3)+1); //Trying to prevent round-off error, don't yell at me + let atkSpd = Base64.toInt(name.substring(15)); + let atkSpds = ["SLOW","NORMAL","FAST"]; + let attackSpeed = atkSpds[atkSpd]; + return new Craft(recipe,mat_tiers,ingreds,attackSpeed,"1"+name); + } + } catch (error) { + return undefined; } + } @@ -42,7 +49,7 @@ class Craft{ this.ingreds = ingreds; this.statMap = new Map(); //can use the statMap as an expanded Item this.atkSpd = attackSpeed; - this.hash = hash; + this.hash = "CR-" + hash; this.initCraftStats(); this.statMap.set("hash", this.hash); } @@ -64,9 +71,9 @@ class Craft{ } setHash(hash) { - this.hash = hash; - this.statMap.set("name", "CR-" + this.hash); - this.statMap.set("displayName", "CR-" + this.hash); + this.hash = "CR-" + hash; + this.statMap.set("name", this.hash); + this.statMap.set("displayName", this.hash); this.statMap.set("hash", this.hash); } /* Get all stats for this build. Stores in this.statMap. @@ -77,13 +84,14 @@ class Craft{ let statMap = new Map(); statMap.set("minRolls", new Map()); statMap.set("maxRolls", new Map()); - statMap.set("name", "CR-" + this.hash); - statMap.set("displayName", "CR-" + this.hash); + statMap.set("name", this.hash); + statMap.set("displayName", this.hash); statMap.set("tier", "Crafted"); statMap.set("type", this.recipe.get("type").toLowerCase()); statMap.set("duration", [this.recipe.get("duration")[0], this.recipe.get("duration")[1]]); //[low, high] statMap.set("durability", [this.recipe.get("durability")[0], this.recipe.get("durability")[1]]); - statMap.set("lvl", (this.recipe.get("lvl")[0] + "-" + this.recipe.get("lvl")[1]) ); + statMap.set("lvl", this.recipe.get("lvl")[1]); + statMap.set("lvlLow", this.recipe.get("lvl")[0]); statMap.set("nDam", 0); statMap.set("hp",0); statMap.set("hpLow",0); @@ -223,9 +231,13 @@ class Craft{ let low2 = Math.floor(nDamBaseLow * 1.1); let high1 = Math.floor(nDamBaseHigh * 0.9); let high2 = Math.floor(nDamBaseHigh * 1.1); + statMap.set("nDamBaseLow", nDamBaseLow); + statMap.set("nDamBaseHigh", nDamBaseHigh); statMap.set("nDamLow", low1+"-"+low2); statMap.set("nDam", high1+"-"+high2); for (const e in skp_elements) { + statMap.set(skp_elements[e]+"DamBaseLow", elemDamBaseLow[e]); + statMap.set(skp_elements[e]+"DamBaseHigh", elemDamBaseHigh[e]); low1 = Math.floor(elemDamBaseLow[e] * 0.9); low2 = Math.floor(elemDamBaseLow[e] * 1.1); high1 = Math.floor(elemDamBaseHigh[e] * 0.9); diff --git a/crafter.html b/crafter.html index 7213001..17ce149 100644 --- a/crafter.html +++ b/crafter.html @@ -36,6 +36,11 @@
WynnCustom
+ + + +
WynnGPS
+
@@ -225,7 +230,7 @@