From 07cafe0c0a15f246c946daabb1471865ca3d1658 Mon Sep 17 00:00:00 2001 From: ferricles Date: Sat, 30 Jan 2021 00:50:25 -0800 Subject: [PATCH] many crafted item fixes, crafted item saving implemented, crafted items in builds implemented, build saving with crafted items not implemented. --- build.js | 142 ++++++++++++++++++++++++++++++++++++------------- builder.js | 44 +++++++-------- craft.js | 115 ++++++++++++++++++++++++++------------- crafter.js | 65 +++++++++++----------- damage_calc.js | 9 +++- display.js | 29 +++------- index.html | 4 +- load_ing.js | 30 +++++------ utils.js | 6 +++ 9 files changed, 276 insertions(+), 168 deletions(-) diff --git a/build.js b/build.js index d002c06..29c9c63 100644 --- a/build.js +++ b/build.js @@ -105,7 +105,8 @@ class Build{ 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.craftedItems = []; // 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") { @@ -113,72 +114,133 @@ class Build{ this.powders[0] = this.powders[0].slice(0,helmet.slots); this.helmet = expandItem(helmet, this.powders[0]); }else{ - const helmet = itemMap.get("No Helmet"); - this.powders[0] = this.powders[0].slice(0,helmet.slots); - this.helmet = expandItem(helmet, this.powders[0]); - errors.push(new ItemNotFound(equipment[0], "helmet", true)); + try { + let helmet = getCraftFromHash(equipment[0]); + this.powders[0] = this.powders[0].slice(0,helmet.statMap.slots); + helmet.statMap.set("powders",this.powders[0].slice()); + helmet.applyPowders(); + this.helmet = helmet.statMap; + this.craftedItems.push(helmet); + } catch (Error) { + //console.log(Error); //fix + const helmet = itemMap.get("No Helmet"); + this.powders[0] = this.powders[0].slice(0,helmet.slots); + this.helmet = expandItem(helmet, this.powders[0]); + errors.push(new ItemNotFound(equipment[0], "helmet", true)); + } } if(itemMap.get(equipment[1]) && itemMap.get(equipment[1]).type === "chestplate") { const chestplate = itemMap.get(equipment[1]); this.powders[1] = this.powders[1].slice(0,chestplate.slots); this.chestplate = expandItem(chestplate, this.powders[1]); }else{ - const chestplate = itemMap.get("No Chestplate"); - this.powders[1] = this.powders[1].slice(0,chestplate.slots); - this.chestplate = expandItem(chestplate, this.powders[1]); - errors.push(new ItemNotFound(equipment[1], "chestplate", true)); + try { + let chestplate = getCraftFromHash(equipment[1]); + this.powders[1] = this.powders[1].slice(0,chestplate.statMap.slots); + chestplate.statMap.set("powders",this.powders[1].slice()); + chestplate.applyPowders(); + this.chestplate = chestplate.statMap; + this.craftedItems.push(chestplate); + } catch (Error) { + const chestplate = itemMap.get("No Chestplate"); + this.powders[1] = this.powders[1].slice(0,chestplate.slots); + this.chestplate = expandItem(chestplate, this.powders[1]); + errors.push(new ItemNotFound(equipment[1], "chestplate", true)); + } } if(itemMap.get(equipment[2]) && itemMap.get(equipment[2]).type === "leggings") { const leggings = itemMap.get(equipment[2]); this.powders[2] = this.powders[2].slice(0,leggings.slots); this.leggings = expandItem(leggings, this.powders[2]); }else{ - const leggings = itemMap.get("No Leggings"); - this.powders[2] = this.powders[2].slice(0,leggings.slots); - this.leggings = expandItem(leggings, this.powders[2]); - errors.push(new ItemNotFound(equipment[2], "leggings", true)); + try { + let leggings = getCraftFromHash(equipment[2]); + this.powders[2] = this.powders[2].slice(0,leggings.statMap.slots); + leggings.statMap.set("powders",this.powders[2].slice()); + leggings.applyPowders(); + this.leggings = leggings.statMap; + this.craftedItems.push(leggings); + } catch (Error) { + const leggings = itemMap.get("No Leggings"); + this.powders[2] = this.powders[2].slice(0,leggings.slots); + this.leggings = expandItem(leggings, this.powders[2]); + errors.push(new ItemNotFound(equipment[2], "leggings", true)); + } } if(itemMap.get(equipment[3]) && itemMap.get(equipment[3]).type === "boots") { const boots = itemMap.get(equipment[3]); this.powders[3] = this.powders[3].slice(0,boots.slots); this.boots = expandItem(boots, this.powders[3]); }else{ - const boots = itemMap.get("No Boots"); - this.powders[3] = this.powders[3].slice(0,boots.slots); - this.boots = expandItem(boots, this.powders[3]); - errors.push(new ItemNotFound(equipment[3], "boots", true)); + try { + let boots = getCraftFromHash(equipment[3]); + this.powders[3] = this.powders[3].slice(0,boots.statMap.slots); + boots.statMap.set("powders",this.powders[3].slice()); + boots.applyPowders(); + this.boots = boots.statMap; + this.craftedItems.push(boots); + } catch (Error) { + const boots = itemMap.get("No Boots"); + this.powders[3] = this.powders[3].slice(0,boots.slots); + this.boots = expandItem(boots, this.powders[3]); + errors.push(new ItemNotFound(equipment[3], "boots", true)); + } } if(itemMap.get(equipment[4]) && itemMap.get(equipment[4]).type === "ring") { const ring = itemMap.get(equipment[4]); this.ring1 = expandItem(ring, []); }else{ - const ring = itemMap.get("No Ring 1"); - this.ring1 = expandItem(ring, []); - errors.push(new ItemNotFound(equipment[4], "ring1", true, "ring")); + try { + let ring = getCraftFromHash(equipment[4]); + this.ring1 = ring.statMap; + this.craftedItems.push(ring); + } catch (Error) { + const ring = itemMap.get("No Ring 1"); + this.ring1 = expandItem(ring, []); + errors.push(new ItemNotFound(equipment[4], "ring1", true, "ring")); + } } if(itemMap.get(equipment[5]) && itemMap.get(equipment[5]).type === "ring") { const ring = itemMap.get(equipment[5]); this.ring2 = expandItem(ring, []); }else{ - const ring = itemMap.get("No Ring 2"); - this.ring2 = expandItem(ring, []); - errors.push(new ItemNotFound(equipment[5], "ring2", true, "ring")); + try { + let ring = getCraftFromHash(equipment[5]); + this.ring2 = ring.statMap; + this.craftedItems.push(ring); + } catch (Error) { + const ring = itemMap.get("No Ring 2"); + this.ring2 = expandItem(ring, []); + errors.push(new ItemNotFound(equipment[5], "ring2", true, "ring")); + } } if(itemMap.get(equipment[6]) && itemMap.get(equipment[6]).type === "bracelet") { const bracelet = itemMap.get(equipment[6]); this.bracelet = expandItem(bracelet, []); }else{ - const bracelet = itemMap.get("No Bracelet"); - this.bracelet = expandItem(bracelet, []); - errors.push(new ItemNotFound(equipment[6], "bracelet", true)); + try { + let bracelet = getCraftFromHash(equipment[6]); + this.bracelet = bracelet.statMap; + this.craftedItems.push(bracelet); + } catch (Error) { + const bracelet = itemMap.get("No Bracelet"); + this.bracelet = expandItem(bracelet, []); + errors.push(new ItemNotFound(equipment[6], "bracelet", true)); + } } if(itemMap.get(equipment[7]) && itemMap.get(equipment[7]).type === "necklace") { const necklace = itemMap.get(equipment[7]); this.necklace = expandItem(necklace, []); }else{ - const necklace = itemMap.get("No Necklace"); - this.necklace = expandItem(necklace, []); - errors.push(new ItemNotFound(equipment[7], "necklace", true)); + try { + let necklace = getCraftFromHash(equipment[7]); + this.necklace = necklace.statMap; + this.craftedItems.push(necklace); + } catch (Error) { + const necklace = itemMap.get("No Necklace"); + this.necklace = expandItem(necklace, []); + errors.push(new ItemNotFound(equipment[7], "necklace", true)); + } } if(itemMap.get(equipment[8]) && itemMap.get(equipment[8]).category === "weapon") { const weapon = itemMap.get(equipment[8]); @@ -190,11 +252,20 @@ class Build{ document.getElementsByClassName("powder-specials")[0].style.display = "none"; } }else{ - const weapon = itemMap.get("No Weapon"); - this.powders[4] = this.powders[4].slice(0,weapon.slots); - this.weapon = expandItem(weapon, this.powders[4]); - document.getElementsByClassName("powder-specials")[0].style.display = "none"; - errors.push(new ItemNotFound(equipment[8], "weapon", true)); + try { + let weapon = getCraftFromHash(equipment[8]); + this.weapon = weapon.statMap; + 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"; + } catch (Error) { + const weapon = itemMap.get("No Weapon"); + this.powders[4] = this.powders[4].slice(0,weapon.slots); + this.weapon = expandItem(weapon, this.powders[4]); + document.getElementsByClassName("powder-specials")[0].style.display = "none"; + errors.push(new ItemNotFound(equipment[8], "weapon", true)); + } } if (level < 1) { //Should these be constants? @@ -339,13 +410,12 @@ class Build{ let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef"]; //Create a map of this build's stats - //This is universal for every possible build, so it's possible to move this elsewhere. let statMap = new Map(); for (const staticID of staticIDs) { statMap.set(staticID, 0); } - statMap.set("hp", levelToHPBase(this.level)); //TODO: Add player base health + statMap.set("hp", levelToHPBase(this.level)); for (const item of this.items){ for (let [id, value] of item.get("maxRolls")) { diff --git a/builder.js b/builder.js index 8e001c9..36df985 100644 --- a/builder.js +++ b/builder.js @@ -3,7 +3,7 @@ const url_tag = location.hash.slice(1); console.log(url_base); console.log(url_tag); -const BUILD_VERSION = "6.9.11"; +const BUILD_VERSION = "6.9.20"; function setTitle() { let text; @@ -20,10 +20,7 @@ function setTitle() { setTitle(); let player_build; -// Set up item lists for quick access later. -let armorTypes = [ "helmet", "chestplate", "leggings", "boots" ]; -let accessoryTypes = [ "ring", "bracelet", "necklace" ]; -let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ]; + // THIS IS SUPER DANGEROUS, WE SHOULD NOT BE KEEPING THIS IN SO MANY PLACES let item_fields = [ "name", "displayName", "tier", "set", "slots", "type", "material", "drop", "quest", "restrict", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "str", "dex", "int", "agi", "def", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "fixID", "category", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd", "id" ]; let editable_item_fields = [ "sdPct", "sdRaw", "mdPct", "mdRaw", "poison", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "hprRaw", "hprPct", "hpBonus", "atkTier", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; @@ -170,9 +167,9 @@ function init() { populateItemList(armorType); // Add change listener to update armor slots. document.getElementById(armorType+"-choice").addEventListener("change", (event) => { - let item = itemMap.get(event.target.value); - if (item !== undefined) { - document.getElementById(armorType+"-slots").textContent = item.slots + " slots"; + let item = itemMap.has(event.target.value) ? itemMap.get(event.target.value) : (getCraftFromHash(event.target.value) != undefined ? getCraftFromHash(event.target.value).statMap : undefined); + if (item !== undefined && event.target.value !== "") { + document.getElementById(armorType+"-slots").textContent = (item["slots"] ? item["slots"] : item.get("slots"))+ " slots"; } else { document.getElementById(armorType+"-slots").textContent = "X slots"; @@ -205,11 +202,10 @@ function init() { // Add change listener to update weapon slots. document.getElementById("weapon-choice").addEventListener("change", (event) => { - let item = itemMap.get(event.target.value); - if (item !== undefined) { - document.getElementById("weapon-slots").textContent = item.slots + " slots"; - } - else { + let item = itemMap.has(event.target.value) ? itemMap.get(event.target.value) : (getCraftFromHash(event.target.value) != undefined ? getCraftFromHash(event.target.value).statMap : undefined); + if (item !== undefined && event.target.value !== "") { + document.getElementById("weapon-slots").textContent = (item["slots"] ? item["slots"] : item.get("slots"))+ " slots"; + } else { document.getElementById("weapon-slots").textContent = "X slots"; } }); @@ -241,8 +237,7 @@ function decodeBuild(url_tag) { for (let i = 0; i < 9; ++i ) { equipment[i] = getItemNameFromID(Base64.toInt(equipments.slice(i*3,i*3+3))); } - } - if (version === "1") { + } else if (version === "1") { let powder_info = info[1].slice(27); console.log(powder_info); // TODO: Make this run in linear instead of quadratic time... ew @@ -263,8 +258,7 @@ function decodeBuild(url_tag) { } powdering[i] = powders; } - } - if (version === "2") { + } else if (version === "2") { save_skp = true; let skillpoint_info = info[1].slice(27, 37); for (let i = 0; i < 5; ++i ) { @@ -291,8 +285,7 @@ function decodeBuild(url_tag) { } powdering[i] = powders; } - } - if(version === "3"){ + } else if (version === "3"){ level = Base64.toInt(info[1].slice(37,39)); setValue("level-choice",level); save_skp = true; @@ -319,6 +312,8 @@ function decodeBuild(url_tag) { } powdering[i] = powders; } + } else if (version === "4") { //crafted support + //@hpp } for (let i in powderInputs) { setValue(powderInputs[i], powdering[i]); @@ -334,6 +329,7 @@ function decodeBuild(url_tag) { */ function encodeBuild() { if (player_build) { + //@hpp update for 4_ let build_string = "3_" + Base64.fromIntN(player_build.helmet.get("id"), 3) + Base64.fromIntN(player_build.chestplate.get("id"), 3) + Base64.fromIntN(player_build.leggings.get("id"), 3) + @@ -406,7 +402,7 @@ function calculateBuild(save_skp, skp){ let equipment = [ null, null, null, null, null, null, null, null, null ]; for (let i in equipment) { let equip = getValue(equipmentInputs[i]); - if (equip === "") equip = "No " + equipment_names[i]; + if (equip === "") { equip = "No " + equipment_names[i] } equipment[i] = equip; } let powderings = []; @@ -434,14 +430,14 @@ 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); } - console.log(equipment); - console.log(document.getElementById("level-choice").value); - player_build = new Build(document.getElementById("level-choice").value, equipment, powderings, new Map(), errors); + let level = document.getElementById("level-choice").value; + player_build = new Build(level, equipment, powderings, new Map(), errors); + console.log(player_build); for (let i of document.getElementsByClassName("hide-container-block")) { i.style.display = "block"; } diff --git a/craft.js b/craft.js index f1b1e52..1c6bcab 100644 --- a/craft.js +++ b/craft.js @@ -1,31 +1,30 @@ -let armorTypes = [ "helmet", "chestplate", "leggings", "boots" ]; -let accessoryTypes = [ "ring", "bracelet", "necklace" ]; -let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ]; -let consumableTypes = [ "potion", "scroll", "food"] + //constructs a craft from a hash 'CR-qwoefsabaoe' or 'qwoefsaboe' -function createCraft(hash) { - let name = hash; +function getCraftFromHash(hash) { + let name = hash.slice(); if (name.slice(0,3) === "CR-") { name = name.substring(3); } - this.hash = name; - ingreds = []; - /*for (let i = 0; i < 6; i ++ ) { - ingreds.push( ingIDMap.get(Base64.toInt(name.substring(2*i,2*i+2))) ); + 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); } - let recipe = recipeIDMap.get(Base64.toInt(tag.substring(12,14))); - recipesName = recipe.split("-"); - setValue("recipe-choice",recipesName[0]); - setValue("level-choice",recipesName[1]+"-"+recipesName[2]); - tierNum = Base64.toInt(tag.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(tag.substring(15)); - let atkSpds = ["SLOW,NORMAL,FAST"]; - let attackSpeed atkSpds[atkSpd]; - */ + } @@ -48,7 +47,21 @@ class Craft{ } + applyPowders() { + if (this.statMap.get("category") === "armor") { + //double apply armor powders + for(const id of this.statMap.get("powders")){ + let powder = powderStats[id]; + let name = powderNames.get(id); + this.statMap.set(name.charAt(0) + "Def", (this.statMap.get(name.charAt(0)+"Def") || 0) + 2 * powder["defPlus"]); + this.statMap.set(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5] + "Def", (this.statMap.get(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5]+"Def") || 0) - 2 * powder["defMinus"]); + } + }else if (this.statMap.get("category") === "weapon") { + //do nothing - weapon powders are handled in displayExpandedItem + } + + } setHash(hash) { this.hash = hash; this.statMap.set("displayName", "CR-" + this.hash); @@ -57,7 +70,7 @@ class Craft{ @pre The craft itself should be valid. No checking of validity of pieces is done here. */ initCraftStats(){ - let consumables = ["POTION", "SCROLL", "FOOD"]; + let statMap = new Map(); statMap.set("minRolls", new Map()); statMap.set("maxRolls", new Map()); @@ -68,18 +81,22 @@ class Craft{ 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("nDam", 0); + statMap.set("hp",0); + statMap.set("hpLow",0); for (const e of skp_elements) { statMap.set(e + "Dam", "0-0"); statMap.set(e + "Def", 0); } for (const e of skp_order) { statMap.set(e + "Req", 0) + statMap.set(e, 0); } - + let allNone = true; if (armorTypes.includes(statMap.get("type")) || weaponTypes.includes(statMap.get("type"))) { + statMap.set("category","weapon"); if(this.recipe.get("lvl")[0] < 30) { statMap.set("slots", 1); - } else if (this.recipe.get("lvl") < 70) { + } else if (this.recipe.get("lvl")[0] < 70) { statMap.set("slots", 2); } else{ statMap.set("slots", 3); @@ -88,15 +105,16 @@ class Craft{ statMap.set("slots", 0); } if (consumableTypes.includes(statMap.get("type"))) { + statMap.set("category","consumable"); if(this.recipe.get("lvl")[0] < 30) { statMap.set("charges", 1); - } else if (this.recipe.get("lvl") < 70) { + } else if (this.recipe.get("lvl")[0] < 70) { statMap.set("charges", 2); } else{ statMap.set("charges", 3); } //no ingredient consumables ALWAYS have 3 charges. - let allNone = true; + for(const ingred of this.ingreds) { if(ingred.get("name") !== "No Ingredient") { allNone = false; @@ -126,6 +144,9 @@ class Craft{ statMap.set("category","weapon"); statMap.set("atkSpd",this.atkSpd); } + if (accessoryTypes.includes(statMap.get("type"))) { + statMap.set("category", "accessory"); + } statMap.set("powders",[]); /* Change certain IDs based on material tier. @@ -152,8 +173,7 @@ class Craft{ let low = this.recipe.get("healthOrDamage")[0]; let high = this.recipe.get("healthOrDamage")[1]; if (statMap.get("category") === "consumable") { - //duration modifier - if(statMap.has("hp")) { //hack + if(allNone) { statMap.set("hp", Math.floor( low * matmult )+ "-" + Math.floor( high * matmult )); } else { statMap.set("duration", [Math.floor( statMap.get("duration")[0] * matmult ), Math.floor( statMap.get("duration")[1] * matmult )]); @@ -229,7 +249,8 @@ class Craft{ } low = Math.floor(low * matmult); high = Math.floor(high * matmult); - statMap.set("hp",low+"-"+high); + statMap.set("hp",high); + statMap.set("hpLow",low); } /* END SECTION */ @@ -293,11 +314,11 @@ class Craft{ let ingred = this.ingreds[n]; let eff_mult = (eff_flat[n] / 100).toFixed(2); for (const [key, value] of ingred.get("itemIDs")) { - if(key !== "dura") { + if(key !== "dura" && !consumableTypes.includes(statMap.get("type"))) { //consumables NEVER get reqs if (!ingred.get("isPowder")) { - statMap.set(key, Math.floor(statMap.get(key) + value*eff_mult)); //CHECK IF THIS IS CORRECT + statMap.set(key, Math.round(statMap.get(key) + value*eff_mult)); } else { - statMap.set(key, Math.floor(statMap.get(key) + value)); + statMap.set(key, Math.round(statMap.get(key) + value)); } } else { //durability, NOT affected by effectiveness statMap.set("durability", statMap.get("durability").map(x => x + value)); @@ -320,16 +341,34 @@ class Craft{ } } } - for (const e of skp_order) { - statMap.set(e,statMap.get("maxRolls").get(e)); - } for (const d in statMap.get("durability")) { - if(statMap.get("durability")[d] < 1) { statMap.get("durability")[d] = 1;} + if(statMap.get("durability")[d] < 1) { statMap.get("durability")[d] = 1;} + else { + statMap.get("durability")[d] = Math.floor(statMap.get("durability")[d]); + } } for (const d in statMap.get("duration")) { - if(statMap.get("duration")[d] < 1) { statMap.get("duration")[d] = 1;} + if(statMap.get("duration")[d] < 10) { statMap.get("duration")[d] = 10;} } if(statMap.has("charges") && statMap.get("charges") < 1 ) { statMap.set("charges",1)} + + statMap.set("reqs",[0,0,0,0,0]); + statMap.set("skillpoints", [0,0,0,0,0]); + statMap.set("damageBonus",[0,0,0,0,0]); + for (const e in skp_order) { + statMap.set(skp_order[e], statMap.get("maxRolls").has(skp_order[e]) ? statMap.get("maxRolls").get(skp_order[e]) : 0); + statMap.get("skillpoints")[e] = statMap.get("maxRolls").has(skp_order[e]) ? statMap.get("maxRolls").get(skp_order[e]) : 0; + statMap.get("reqs")[e] = statMap.has(skp_order[e]+"Req") && !consumableTypes.includes(statMap.get("type"))? statMap.get(skp_order[e]+"Req") : 0; + statMap.get("damageBonus")[e] = statMap.has(skp_order[e]+"DamPct") ? statMap.get(skp_order[e]+"DamPct") : 0; + } + for (const id of rolledIDs) { + if (statMap.get("minRolls").has(id)) { + continue; + } else { + statMap.get("minRolls").set(id,0); + statMap.get("maxRolls").set(id,0); + } + } this.statMap = statMap; } } \ No newline at end of file diff --git a/crafter.js b/crafter.js index d7b275e..6856d5d 100644 --- a/crafter.js +++ b/crafter.js @@ -2,14 +2,14 @@ * TESTING SECTION */ -const url_base = location.href.split("#")[0]; -const url_tag = location.hash.slice(1); -console.log(url_base); -console.log(url_tag); +const ing_url_base = location.href.split("#")[0]; +const ing_url_tag = location.hash.slice(1); +console.log(ing_url_base); +console.log(ing_url_tag); -const BUILD_VERSION = "6.9.11"; +const ING_BUILD_VERSION = "6.9.20"; /* * END testing section */ @@ -26,13 +26,13 @@ let ingFields = ["fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "hprPct" let player_craft; function setTitle() { - document.getElementById("header").textContent = "WynnCrafter version "+BUILD_VERSION+" (ingredient db version "+ING_DB_VERSION+")"; + document.getElementById("header").textContent = "WynnCrafter version "+ING_BUILD_VERSION+" (ingredient db version "+ING_DB_VERSION+")"; document.getElementById("header").classList.add("funnynumber"); let disclaimer = document.createElement("p"); disclaimer.textContent = "THIS CRAFTER IS NEARLY COMPLETE. The effect of material tiers on crafted items is not 100% tested and accurate. If you know how the math behind it works OR if you have a crafted item whose stats contradict this crafter, please contact ferricles on forums, discord, or ingame."; document.getElementById("header").append(disclaimer); } -setTitle(); + let ingMap = new Map(); let ingList = []; @@ -111,20 +111,25 @@ function init() { console.log(ings); console.log("all recipes"); console.log(recipes); - console.log(ingList); + /*console.log(ingList); console.log(recipeList); console.log(ingIDMap); - console.log(recipeIDMap); - - document.getElementById("recipe-choice").addEventListener("change", (event) => { - updateMaterials(); - }); - document.getElementById("level-choice").addEventListener("change", (event) => { - updateMaterials(); - }); - - populateFields(); - decodeCraft(url_tag); + console.log(recipeIDMap);*/ + try { + document.getElementById("recipe-choice").addEventListener("change", (event) => { + updateMaterials(); + }); + document.getElementById("level-choice").addEventListener("change", (event) => { + updateMaterials(); + }); + + populateFields(); + decodeCraft(ing_url_tag); + setTitle(); + } catch (Error) { + console.log("If you are seeing this while building, do not worry. Oherwise, panic! (jk contact ferricles)"); + } + } function updateMaterials() { @@ -198,7 +203,7 @@ function calculateCraft() { player_craft = new Craft(recipe,mat_tiers,ingreds,atkSpd,""); location.hash = encodeCraft(); - player_craft.setHash(encodeCraft().split("_")[1]); + player_craft.setHash(encodeCraft()); console.log(player_craft); /*console.log(recipe) console.log(levelrange) @@ -237,7 +242,7 @@ function calculateCraft() { function encodeCraft() { if (player_craft) { let atkSpds = ["SLOW","NORMAL","FAST"]; - let craft_string = "1_" + + let craft_string = "1" + Base64.fromIntN(player_craft.ingreds[0].get("id"), 2) + Base64.fromIntN(player_craft.ingreds[1].get("id"), 2) + Base64.fromIntN(player_craft.ingreds[2].get("id"), 2) + @@ -251,19 +256,19 @@ function encodeCraft() { } return ""; } -function decodeCraft(url_tag) { - if (url_tag) { - let info = url_tag.split("_"); - let version = info[0]; - let tag = info[1]; +function decodeCraft(ing_url_tag) { + if (ing_url_tag) { + console.log(ing_url_tag); + let version = ing_url_tag.charAt(0); + let tag = ing_url_tag.substring(1); if (version === "1") { ingreds = []; for (let i = 0; i < 6; i ++ ) { setValue("ing-choice-"+(i+1), ingIDMap.get(Base64.toInt(tag.substring(2*i,2*i+2)))); - console.log(Base64.toInt(tag.substring(2*i,2*i+2))); + //console.log(Base64.toInt(tag.substring(2*i,2*i+2))); } recipe = recipeIDMap.get(Base64.toInt(tag.substring(12,14))); - console.log(Base64.toInt(tag.substring(12,14))); + //console.log(Base64.toInt(tag.substring(12,14))); recipesName = recipe.split("-"); setValue("recipe-choice",recipesName[0]); setValue("level-choice",recipesName[1]+"-"+recipesName[2]); @@ -322,7 +327,7 @@ function toggleButton(buttonId) { */ function copyRecipe(){ if (player_craft) { - copyTextToClipboard(url_base+location.hash); + copyTextToClipboard(ing_url_base+location.hash); document.getElementById("copy-button").textContent = "Copied!"; } } @@ -331,7 +336,7 @@ function copyRecipe(){ */ function shareRecipe(){ if (player_craft) { - let copyString = url_base+location.hash + "\n"; + let copyString = ing_url_base+location.hash + "\n"; let name = player_craft.recipe.get("name").split("-"); copyString += " > " + name[0] + " " + "Lv. " + name[1] + "-" + name[2] + " (" + player_craft.mat_tiers[0] + "\u272B, " + player_craft.mat_tiers[1] + "\u272B)\n"; let names = [ diff --git a/damage_calc.js b/damage_calc.js index 9454c6c..c131ef7 100644 --- a/damage_calc.js +++ b/damage_calc.js @@ -40,7 +40,14 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, } //console.log(damages); let rawBoosts = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]; - for (const powderID of weapon.get("powders")) { + //Double powder apply for weapons + let powders = weapon.get("powders").slice(); + if (weapon.get("tier") === "Crafted") { + powders = powders.flatMap(x => [x,x]); + } + + //apply powders to weapon + for (const powderID of powders) { const powder = powderStats[powderID]; // Bitwise to force conversion to integer (integer division). const element = (powderID/6) | 0; diff --git a/display.js b/display.js index 588aa70..ac8f547 100644 --- a/display.js +++ b/display.js @@ -60,17 +60,14 @@ function expandItem(item, powders){ expandedItem.set("minRolls",minRolls); expandedItem.set("maxRolls",maxRolls); expandedItem.set("powders", powders); - - if(expandedItem.get("category") == "armor"){ //item is armor + if(item.category === "armor") { for(const id of powders){ - //console.log(powderStats[id]); let powder = powderStats[id]; let name = powderNames.get(id); expandedItem.set(name.charAt(0) + "Def", (expandedItem.get(name.charAt(0)+"Def") || 0) + powder["defPlus"]); expandedItem.set(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5] + "Def", (expandedItem.get(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5]+"Def") || 0) - powder["defMinus"]); } } - //console.log(expandedItem); return expandedItem; } @@ -453,7 +450,7 @@ function displayExpandedItem(item, parent_id){ item.set(damage_keys[i], damagesLow[i][0]+"-"+damagesLow[i][1]+"\u279c"+damages[i][0]+"-"+damages[i][1]); } } - + } else if (item.get("category") === "armor") { } let display_commands = [ @@ -543,8 +540,6 @@ function displayExpandedItem(item, parent_id){ let p_elem = document.createElement("p"); // PROPER POWDER DISPLAYING let numerals = new Map([[1, "I"], [2, "II"], [3, "III"], [4, "IV"], [5, "V"], [6, "VI"]]); - /*p_elem.textContent = idPrefixes[id].concat(item.get(id), idSuffixes[id]) + - " [ " + item.get("powders").map(x => powderNames.get(x)) + " ]";*/ let powderPrefix = document.createElement("b"); powderPrefix.classList.add("powderLeft"); @@ -553,7 +548,6 @@ function displayExpandedItem(item, parent_id){ p_elem.appendChild(powderPrefix); let powders = item.get("powders"); - //console.log(powders); for (let i = 0; i < powders.length; i++) { let powder = document.createElement("b"); powder.textContent = numerals.get((powders[i]%6)+1)+" "; @@ -569,9 +563,11 @@ function displayExpandedItem(item, parent_id){ active_elem.appendChild(p_elem); } else { let p_elem; - if( (!skp_order.includes(id)) || (skp_order.includes(id) && item.get("tier") !== "Crafted" && active_elem.nodeName === "DIV") ) { //skp + if ( !(item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") && (!skp_order.includes(id)) || (skp_order.includes(id) && item.get("tier") !== "Crafted" && active_elem.nodeName === "DIV") ) { //skp warp p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format); - } + } else if (item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") { + p_elem = displayFixedID(active_elem, id, item.get(id+"Low")+"-"+item.get(id), elemental_format); + } if (id === "displayName") { p_elem.classList.add("title"); if (item.get("tier") !== " ") { @@ -592,18 +588,7 @@ function displayExpandedItem(item, parent_id){ bckgrd.classList.add("itemp"); active_elem.appendChild(bckgrd); bckgrd.appendChild(img); - /*let validTypes = ["helmet", "chestplate", "leggings", "boots", "relik", "wand", "bow", "spear", "dagger", "ring", "bracelet", "necklace"]; - if (item.has("type") && validTypes.includes(item.get("type"))) { - p = document.createElement("p"); - img = document.createElement("img"); - img.src = "./media/items/generic-"+item.get("type")+".png"; - img.alt = "image no display :("; - img.classList.add("center"); - p.append(img); - p.classList.add("itemp"); - - p_elem.append(p); - }*/ + } else if (skp_order.includes(id)) { //id = str, dex, int, def, or agi if ( item.get("tier") !== "Crafted" && active_elem.nodeName === "DIV") { p_elem.textContent = ""; diff --git a/index.html b/index.html index 0de9786..a7cb832 100644 --- a/index.html +++ b/index.html @@ -1005,9 +1005,9 @@ - + diff --git a/load_ing.js b/load_ing.js index 4ac1e32..4866896 100644 --- a/load_ing.js +++ b/load_ing.js @@ -2,8 +2,8 @@ const ING_DB_VERSION = 4; // @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js -let db; -let reload = false; +let idb; +let ireload = false; let ings; let recipes; @@ -11,7 +11,7 @@ let recipes; * Load item set from local DB. Calls init() on success. */ async function ing_load_local(init_func) { - let get_tx = db.transaction(['ing_db', 'recipe_db'], 'readonly'); + let get_tx = idb.transaction(['ing_db', 'recipe_db'], 'readonly'); let ings_store = get_tx.objectStore('ing_db'); let recipes_store = get_tx.objectStore('recipe_db'); let request3 = ings_store.getAll(); @@ -32,7 +32,7 @@ async function ing_load_local(init_func) { init_func(); } await get_tx.complete; - db.close(); + idb.close(); } /* @@ -63,12 +63,12 @@ async function load_ings(init_func) { await clear_tx2.complete; await clear_tx3.complete;*/ let add_promises = []; - let add_tx2 = db.transaction(['ing_db'], 'readwrite'); + let add_tx2 = idb.transaction(['ing_db'], 'readwrite'); let ings_store = add_tx2.objectStore('ing_db'); for (const ing in ings) { add_promises.push(ings_store.add(ings[ing], ing)); } - let add_tx3 = db.transaction(['recipe_db'], 'readwrite'); + let add_tx3 = idb.transaction(['recipe_db'], 'readwrite'); let recipes_store = add_tx3.objectStore('recipe_db'); for (const recipe in recipes) { add_promises.push(recipes_store.add(recipes[recipe], recipe)); @@ -76,7 +76,7 @@ async function load_ings(init_func) { add_promises.push(add_tx2.complete); add_promises.push(add_tx3.complete); Promise.all(add_promises).then((values) => { - db.close(); + idb.close(); init_func(); }); } @@ -89,8 +89,8 @@ function load_ing_init(init_func) { } request.onsuccess = function() { - db = request.result; - if (!reload) { + idb = request.result; + if (!ireload) { console.log("Using stored data...") ing_load_local(init_func); } @@ -101,24 +101,24 @@ function load_ing_init(init_func) { } request.onupgradeneeded = function(e) { - reload = true; + ireload = true; - let db = e.target.result; + let idb = e.target.result; try { - db.deleteObjectStore('ing_db'); + idb.deleteObjectStore('ing_db'); } catch (error) { console.log("Could not delete ingredient DB. This is probably fine"); } try { - db.deleteObjectStore('recipe_db'); + idb.deleteObjectStore('recipe_db'); } catch (error) { console.log("Could not delete recipe DB. This is probably fine"); } - db.createObjectStore('ing_db'); - db.createObjectStore('recipe_db'); + idb.createObjectStore('ing_db'); + idb.createObjectStore('recipe_db'); console.log("DB setup complete..."); } diff --git a/utils.js b/utils.js index df1185d..8b61e93 100644 --- a/utils.js +++ b/utils.js @@ -2,6 +2,12 @@ let skp_order = ["str","dex","int","def","agi"]; let skill = ["Strength", "Dexterity", "Intelligence", "Defense", "Agility"]; let skp_elements = ["e","t","w","f","a"]; let damageClasses = ["Neutral","Earth","Thunder","Water","Fire","Air"]; +// Set up item lists for quick access later. +let armorTypes = [ "helmet", "chestplate", "leggings", "boots" ]; +let accessoryTypes = [ "ring", "bracelet", "necklace" ]; +let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ]; +let consumableTypes = [ "potion", "scroll", "food"]; + let elementIcons = ["\u2724","\u2726", "\u2749", "\u2739", "\u274b" ]; let skpReqs = skp_order.map(x => x + "Req");