diff --git a/build.js b/build.js index af00975..67e240c 100644 --- a/build.js +++ b/build.js @@ -3,44 +3,89 @@ const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ]; const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"]; const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.20] ]); -/*Turns the input amount of skill points into a float precision percentage. -* @param skp - the integer skillpoint count to be converted -*/ -function skillPointsToPercentage(skp){ - if (skp<=0){ - return 0.0; - }else if(skp>=150){ - return 0.808; - }else{ - return (-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771); - //return(-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771).toFixed(3); - } -} - -/*Turns the input amount of levels into skillpoints available. -* -* @param level - the integer level count te be converted -*/ -function levelToSkillPoints(level){ - if(level < 1){ - return 0; - }else if(level >= 101){ - return 200; - }else{ - return (level - 1) * 2; +/** + * @description Error to catch items that don't exist. + * @module ItemNotFound + */ +class ItemNotFound { + /** + * @class + * @param {String} item the item name entered + * @param {String} type the type of item + * @param {Boolean} genElement whether to generate an element from inputs + * @param {String} override override for item type + */ + constructor(item, type, genElement, override) { + /** + * @public + * @type {String} + */ + this.message = `Cannot find ${override||type} named ${item}`; + if (genElement) + /** + * @public + * @type {Element} + */ + this.element = document.getElementById(`${type}-choice`).parentElement.querySelectorAll("p.error")[0]; + else + this.element = document.createElement("div"); } } -/*Turns the input amount of levels in to base HP. -* @param level - the integer level count to be converted -*/ -function levelToHPBase(level){ - if(level < 1){ //bad level - return this.levelToHPBase(1); - }else if (level > 106){ //also bad level - return this.levelToHPBase(106); - }else{ //good level - return 5*level + 5; +/** + * @description Error to catch incorrect input. + * @module IncorrectInput + */ +class IncorrectInput { + /** + * @class + * @param {String} input the inputted text + * @param {String} format the correct format + * @param {String} sibling the id of the error node's sibling + */ + constructor(input, format, sibling) { + /** + * @public + * @type {String} + */ + this.message = `${input} is incorrect. Example: ${format}`; + /** + * @public + * @type {String} + */ + this.id = sibling; + } +} + +/** + * @description Error that inputs an array of items to generate errors of. + * @module ListError + * @extends Error + */ +class ListError extends Error { + /** + * @class + * @param {Array} errors array of errors + */ + constructor(errors) { + let ret = []; + if (typeof errors[0] == "string") { + super(errors[0]); + } else { + super(errors[0].message); + } + for (let i of errors) { + if (typeof i == "string") { + ret.push(new Error(i)); + } else { + ret.push(i); + } + } + /** + * @public + * @type {Object[]} + */ + this.errors = ret; } } @@ -48,15 +93,19 @@ function levelToHPBase(level){ */ class Build{ - /* - * Construct a build. - * @param level : Level of the player. - * @param equipment : List of equipment names that make up the 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. - * @param powders : Powder application. List of lists of integers (powder IDs). + * @param {Number[]} powders : Powder application. List of lists of integers (powder IDs). * In order: Helmet, Chestplate, Leggings, Boots, Weapon. + * @param {Object[]} inputerrors : List of instances of error-like classes. */ - constructor(level,equipment, powders, externalStats){ + constructor(level,equipment, powders, externalStats, inputerrors=[]){ + + let errors = inputerrors; + // 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") { @@ -64,67 +113,99 @@ class Build{ this.powders[0] = this.powders[0].slice(0,helmet.slots); this.helmet = expandItem(helmet, this.powders[0]); }else{ - throw new TypeError("No such helmet named "+ equipment[0]); + 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{ - throw new TypeError("No such chestplate named "+ equipment[1]); + 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{ - throw new TypeError("No such leggings named "+ equipment[2]); + const chestplate = itemMap.get("No Leggings"); + this.powders[1] = this.powders[1].slice(0,chestplate.slots); + this.chestplate = expandItem(chestplate, this.powders[1]); + 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{ - throw new TypeError("No such boots named "+ equipment[3]); + 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{ - throw new TypeError("No such ring named "+ equipment[4]); + 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{ - throw new TypeError("No such ring named "+ equipment[5]); + 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{ - throw new TypeError("No such bracelet named "+ equipment[6]); + 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{ - throw new TypeError("No such necklace named "+ equipment[7]); + 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]); this.powders[4] = this.powders[4].slice(0,weapon.slots); this.weapon = expandItem(weapon, this.powders[4]); }else{ - throw new TypeError("No such weapon named "+ equipment[8]); + const weapon = itemMap.get("No Weapon"); + this.powders[4] = this.powders[4].slice(0,weapon.slots); + this.weapon = expandItem(weapon, this.powders[4]); + errors.push(new ItemNotFound(equipment[8], "weapon", true)); } - if(level < 1){ //Should these be constants? + + if (level < 1) { //Should these be constants? this.level = 1; - }else if (level > 106){ + } else if (level > 106) { this.level = 106; - }else{ + } else if (level <= 106 && level >= 1) { this.level = level; + } else if (typeof level === "string") { + this.level = level; + errors.push(new IncorrectInput(level, "a number", "level-choice")); + } else { + errors.push("Level is not a string or number."); } + document.getElementById("level-choice").value = this.level; + this.level = 106; + this.availableSkillpoints = levelToSkillPoints(this.level); this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ]; this.items = this.equipment.concat([this.weapon]); @@ -144,12 +225,19 @@ class Build{ this.externalStats = externalStats; this.initBuildStats(); + + // Remove every error before adding specific ones + for (let i of document.getElementsByClassName("error")) { + i.textContent = ""; + } + this.errors = errors; + if (errors.length > 0) this.errored = true; } /*Returns build in string format */ toString(){ - return this.helmet.get("name") + ", " + this.chestplate.get("name") + ", " + this.leggings.get("name") + ", " + this.boots.get("name") + ", " + this.ring1.get("name") + ", " + this.ring2.get("name") + ", " + this.bracelet.get("name") + ", " + this.necklace.get("name") + ", " + this.weapon.get("name"); + return [this.equipment,this.weapon].flat(); } /* Getters */ @@ -274,14 +362,10 @@ class Build{ } } } + statMap.set("poisonPct", 100); // The stuff relevant for damage calculation!!! @ferricles statMap.set("atkSpd", this.weapon.get("atkSpd")); - statMap.set("damageRaw", [this.weapon.get("nDam"), this.weapon.get("eDam"), this.weapon.get("tDam"), this.weapon.get("wDam"), this.weapon.get("fDam"), this.weapon.get("aDam")]); - statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]); - statMap.set("defRaw", [statMap.get("eDam"), statMap.get("tDef"), statMap.get("wDef"), statMap.get("fDef"), statMap.get("aDef")]); - statMap.set("defBonus", [statMap.get("eDamPct"), statMap.get("tDefPct"), statMap.get("wDefPct"), statMap.get("fDefPct"), statMap.get("aDefPct")]); - statMap.set("poisonPct", 100); for (const x of skp_elements) { this.externalStats.set(x + "DamPct", 0); @@ -292,6 +376,15 @@ class Build{ this.externalStats.set("defBonus",[0, 0, 0, 0, 0]); this.externalStats.set("poisonPct", 0); this.statMap = statMap; + + this.aggregateStats(); } + aggregateStats() { + let statMap = this.statMap; + statMap.set("damageRaw", [this.weapon.get("nDam"), this.weapon.get("eDam"), this.weapon.get("tDam"), this.weapon.get("wDam"), this.weapon.get("fDam"), this.weapon.get("aDam")]); + statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]); + statMap.set("defRaw", [statMap.get("eDef"), statMap.get("tDef"), statMap.get("wDef"), statMap.get("fDef"), statMap.get("aDef")]); + statMap.set("defBonus", [statMap.get("eDefPct"), statMap.get("tDefPct"), statMap.get("wDefPct"), statMap.get("fDefPct"), statMap.get("aDefPct")]); + } } diff --git a/build_utils.js b/build_utils.js new file mode 100644 index 0000000..f9d071a --- /dev/null +++ b/build_utils.js @@ -0,0 +1,40 @@ +/*Turns the input amount of skill points into a float precision percentage. +* @param skp - the integer skillpoint count to be converted +*/ +function skillPointsToPercentage(skp){ + if (skp<=0){ + return 0.0; + }else if(skp>=150){ + return 0.808; + }else{ + return (-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771); + //return(-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771).toFixed(3); + } +} + +/*Turns the input amount of levels into skillpoints available. +* +* @param level - the integer level count te be converted +*/ +function levelToSkillPoints(level){ + if(level < 1){ + return 0; + }else if(level >= 101){ + return 200; + }else{ + return (level - 1) * 2; + } +} + +/*Turns the input amount of levels in to base HP. +* @param level - the integer level count to be converted +*/ +function levelToHPBase(level){ + if(level < 1){ //bad level + return this.levelToHPBase(1); + }else if (level > 106){ //also bad level + return this.levelToHPBase(106); + }else{ //good level + return 5*level + 5; + } +} \ No newline at end of file diff --git a/builder.js b/builder.js index f374c0e..19d293a 100644 --- a/builder.js +++ b/builder.js @@ -1,16 +1,9 @@ -/* - * TESTING SECTION - */ - const url_base = location.href.split("#")[0]; const url_tag = location.hash.slice(1); console.log(url_base); console.log(url_tag); -/* - * END testing section - */ - +const BUILD_VERSION = "6.9.4"; function setTitle() { document.getElementById("header").textContent = "WynnBuilder version "+BUILD_VERSION+" (db version "+DB_VERSION+")"; @@ -26,6 +19,7 @@ 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" ]; @@ -424,29 +418,36 @@ function calculateBuild(save_skp, skp){ equipment[i] = equip; } let powderings = []; + let errors = []; for (const i in powderInputs) { // read in two characters at a time. // TODO: make this more robust. let input = getValue(powderInputs[i]); let powdering = []; + let errorederrors = []; while (input) { let first = input.slice(0, 2); let powder = powderIDs.get(first); console.log(powder); if (powder === undefined) { - throw new TypeError("Invalid powder " + powder + " in slot " + i); + errorederrors.push(first); + } else { + powdering.push(powder); } - powdering.push(powder); input = input.slice(2); } + if (errorederrors.length > 0) { + if (errorederrors.length > 1) + errors.push(new IncorrectInput(errorederrors.join(""), "t6w6", powderInputs[i])); + else + errors.push(new IncorrectInput(errorederrors[0], "t6 or e3", powderInputs[i])); + } + console.log("POWDERING" + powdering); powderings.push(powdering); } - //level setting - let level = document.getElementById("level-choice").value; - if(level === ""){ - level = 106; - } - document.getElementById("level-choice").value = level; + + console.log(equipment); + player_build = new Build(document.getElementById("level-choice").value, equipment, powderings, new Map(), errors); for (let i of document.getElementsByClassName("hide-container-block")) { i.style.display = "block"; @@ -454,9 +455,9 @@ function calculateBuild(save_skp, skp){ for (let i of document.getElementsByClassName("hide-container-grid")) { i.style.display = "grid"; } + document.getElementById("int-info-div").style.display = "none"; - player_build = new Build(level, equipment, powderings, new Map()); - //console.log(player_build.toString()); + console.log(player_build.toString()); displayEquipOrder(document.getElementById("build-order"),player_build.equip_order); @@ -466,6 +467,11 @@ function calculateBuild(save_skp, skp){ for (let i in skp_order){ //big bren setText(skp_order[i] + "-skp-base", "Original Value: " + skillpoints[i]); } + + for (let id of editable_item_fields) { + setValue(id, player_build.statMap.get(id)); + setText(id+"-base", "Original Value: " + player_build.statMap.get(id)); + } if (save_skp) { // TODO: reduce duplicated code, @updateStats @@ -483,21 +489,50 @@ function calculateBuild(save_skp, skp){ calculateBuildStats(); setTitle(); + if (player_build.errored) + throw new ListError(player_build.errors); + } catch (error) { - let msg = error.stack; - let lines = msg.split("\n"); - let header = document.getElementById("header"); - header.textContent = ""; - for (const line of lines) { - let p = document.createElement("p"); - p.classList.add("itemp"); - p.textContent = line; - header.appendChild(p); + if (error instanceof ListError) { + for (let i of error.errors) { + if (i instanceof ItemNotFound) { + i.element.textContent = i.message; + } else if (i instanceof IncorrectInput) { + if (document.getElementById(i.id) !== null) { + document.getElementById(i.id).parentElement.querySelectorAll("p.error")[0].textContent = i.message; + } + } else { + let msg = i.stack; + let lines = msg.split("\n"); + let header = document.getElementById("header"); + header.textContent = ""; + for (const line of lines) { + let p = document.createElement("p"); + p.classList.add("itemp"); + p.textContent = line; + header.appendChild(p); + } + let p2 = document.createElement("p"); + p2.textContent = "If you believe this is an error, contact hppeng on forums or discord."; + header.appendChild(p2); + } + } + } else { + let msg = error.stack; + let lines = msg.split("\n"); + let header = document.getElementById("header"); + header.textContent = ""; + for (const line of lines) { + let p = document.createElement("p"); + p.classList.add("itemp"); + p.textContent = line; + header.appendChild(p); + } + let p2 = document.createElement("p"); + p2.textContent = "If you believe this is an error, contact hppeng on forums or discord."; + header.appendChild(p2); } - let p2 = document.createElement("p"); - p2.textContent = "If you believe this is an error, contact hppeng on forums or discord."; - header.appendChild(p2); } } @@ -550,28 +585,33 @@ function updateStats() { delta_total += delta; } player_build.assigned_skillpoints += delta_total; - calculateBuildStats(); if(player_build){ - updatePowderSpecials("skip"); - updateBoosts("skip"); + updatePowderSpecials("skip", false); + updateBoosts("skip", false); } + for (let id of editable_item_fields) { + player_build.statMap.set(id, parseInt(getValue(id))); + } + player_build.aggregateStats(); + console.log(player_build.statMap); + calculateBuildStats(); } /* Updates all spell boosts */ -function updateBoosts(buttonId) { +function updateBoosts(buttonId, recalcStats) { let elem = document.getElementById(buttonId); let name = buttonId.split("-")[0]; if(buttonId !== "skip") { if (elem.classList.contains("toggleOn")) { player_build.damageMultiplier -= damageMultipliers.get(name); if (name === "warscream") { - player_build.defenseMultiplier -= .10; + player_build.defenseMultiplier -= .20; } elem.classList.remove("toggleOn"); }else{ player_build.damageMultiplier += damageMultipliers.get(name); if (name === "warscream") { - player_build.defenseMultiplier += .10; + player_build.defenseMultiplier += .20; } elem.classList.add("toggleOn"); } @@ -582,16 +622,18 @@ function updateBoosts(buttonId) { if (elem.classList.contains("toggleOn")) { elem.classList.remove("toggleOn"); player_build.damageMultiplier -= value; - if (key === "warscream") { player_build.defenseMultiplier -= .10 } + if (key === "warscream") { player_build.defenseMultiplier -= .20 } } } } - calculateBuildStats(); + if (recalcStats) { + calculateBuildStats(); + } } /* Updates all powder special boosts */ -function updatePowderSpecials(buttonId){ +function updatePowderSpecials(buttonId, recalcStats) { //console.log(player_build.statMap); let name = (buttonId).split("-")[0]; @@ -671,8 +713,10 @@ function updatePowderSpecials(buttonId){ } } + if (recalcStats) { + calculateBuildStats(); + } displayPowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build); - calculateBuildStats(); //also make damage boosts apply ;-; } /* Calculates all build statistics and updates the entire display. */ @@ -836,5 +880,18 @@ function resetFields(){ calculateBuild(); } +function toggleID() { + let button = document.getElementById("show-id-button"); + let targetDiv = document.getElementById("id-edit"); + if (button.classList.contains("toggleOn")) { //toggle the pressed button off + targetDiv.style.display = "none"; + button.classList.remove("toggleOn"); + } + else { + targetDiv.style.display = "block"; + button.classList.add("toggleOn"); + } +} + load_init(init); diff --git a/clean.json b/clean.json index 68bd2e4..0bc0b5a 100644 --- a/clean.json +++ b/clean.json @@ -270652,7 +270652,7 @@ "restrict": "1.20 item", "fixID": false, "strReq": 0, - "dexReq": 105, + "dexReq": 120, "intReq": 0, "defReq": 0, "agiReq": 0, diff --git a/craft.js b/craft.js new file mode 100644 index 0000000..3fbfff6 --- /dev/null +++ b/craft.js @@ -0,0 +1,181 @@ +let armorTypes = [ "helmet", "chestplate", "leggings", "boots" ]; +let accessoryTypes = [ "ring", "bracelet", "necklace" ]; +let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ]; +let consumableTypes = [ "potion", "scroll", "food"] +/* Creates a crafted item object. +*/ +class Craft{ + /* Constructs a craft. + @param recipe: Helmet-1-3 (id), etc. A recipe object. + @param mat_tiers: [1->3, 1->3]. An array with 2 numbers. + @param ingreds: []. An array with 6 entries, each with an ingredient Map. + */ + constructor(recipe, mat_tiers, ingreds) { + this.recipe = recipe; + this.mat_tiers = mat_tiers; + this.ingreds = ingreds; + this.statMap = new Map(); //can use the statMap as an expanded Item + + this.initCraftStats(); + } + + + /* Get all stats for this build. Stores in this.statMap. + @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()); + statMap.set("displayName", "Crafted Item"); //TODO: DISPLAY THE 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("nDam", 0); + + if (armorTypes.includes(statMap.get("type")) || weaponTypes.includes(statMap.get("type"))) { + if(this.recipe.get("lvl")[0] < 30) { + statMap.set("slots", 1); + } else if (this.recipe.get("lvl") < 70) { + statMap.set("slots", 2); + } else{ + statMap.set("slots", 3); + } + } else { + statMap.set("slots", 0); + } + if (consumableTypes.includes(statMap.get("type"))) { + if(this.recipe.get("lvl")[0] < 30) { + statMap.set("charges", 1); + } else if (this.recipe.get("lvl") < 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; + break; + } + } + if (allNone) { + statMap.set("charges", 3); + statMap.set("hp", this.recipe.get("healthOrDamage").join("-")); + } + statMap.set("category","consumable"); + } else { + statMap.set("slots", 0); + } + + if (armorTypes.includes(statMap.get("type"))) { + statMap.set("hp", this.recipe.get("healthOrDamage").join("-")); + statMap.set("category","armor"); + } else if (weaponTypes.includes(statMap.get("type"))) { + statMap.set("nDam", this.recipe.get("healthOrDamage").join("-")); + for (const e of skp_elements) { + statMap.set(e + "Dam", "0-0"); + } + //statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]); + statMap.set("category","weapon"); + } + statMap.set("powders",""); + /* Change certain IDs based on material tier. + healthOrDamage changes. + duration and durability change. (but not basicDuration) + + */ + + //calc ingredient effectivenesses -> see https://wynndata.tk/cr/585765168 + let eff = [[100,100],[100,100],[100,100]]; + for (let n in this.ingreds) { + let ingred = this.ingreds[n]; + //i and j will refer to the eff matrix. + let i = Math.floor(n / 2); + let j = n % 2; + for (const [key,value] of ingred.get("posMods")) { + if(value == 0) { + continue; + } else { + if (key === "above") { + for (let k = i-1; k > -1; k--) { + eff[k][j] += value; + } + } else if (key === "under") { + for (let k = i+1; k < 3; k++) { + eff[k][j] += value; + } + } else if (key === "left") { + if (j == 1) { + eff[i][j-1] += value; + } + } else if (key === "right") { + if (j == 0) { + eff[i][j+1] += value; + } + } else if (key === "touching") { + for (let k in eff) { + for (let l in eff[k]) { + if ( (Math.abs(k-i) == 1 && Math.abs (l-j) == 0) || (Math.abs(k-i) == 0 && Math.abs (l-j) == 1) ) { + eff[k][l] += value; + } + } + } + } else if (key === "notTouching") { + for (let k in eff) { + for (let l in eff[k]) { + if ( (Math.abs(k-i) > 1) || (Math.abs(k-i) == 1 && Math.abs(l-j) == 1) ) { + eff[k][l] += value; + } + } + } + } else { + console.log("Something went wrong. Please contact hppeng."); + //wtf happened + } + } + } + } + //apply ingredient effectivness - on ids, and reqs (itemIDs). NOT on durability, duration, or charges. + let eff_flat = eff.flat(); + //console.log(eff_flat); + //apply ingredient ids + for (const n in this.ingreds) { + 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") { + statMap.set(key, statMap.get(key) + Math.floor(value*eff_mult)); //CHECK IF THIS IS CORRECT + } else { //durability, NOT affected by effectiveness + statMap.set("durability", statMap.get("durability").map(x => x + value)); + } + } + for (const [key,value] of ingred.get("consumableIDs")) { + //neither duration nor charges are affected by effectiveness + if(key === "dura") { + statMap.set("duration", statMap.get("duration").map(x => x + value)); + } else{ + statMap.set(key, statMap.get("charges") + value); + } + } + for (const [key,value] of ingred.get("ids").get("minRolls")) { + if (value && value != 0) { + let rolls = [value,ingred.get("ids").get("maxRolls").get(key)]; + rolls = rolls.map(x => Math.floor(x * eff_mult)).sort(); + console.log(rolls); + statMap.get("minRolls").set(key, (statMap.get("minRolls").get(key)) ? statMap.get("minRolls").get(key) + rolls[0] : rolls[0]); + statMap.get("maxRolls").set(key, (statMap.get("maxRolls").get(key)) ? statMap.get("maxRolls").get(key) + rolls[1] : rolls[1]); + } + } + } + for(const e of skp_order) { + statMap.set(e,statMap.get("maxRolls").get(e)); + } + + this.statMap = statMap; + } +} \ No newline at end of file diff --git a/crafter.html b/crafter.html new file mode 100644 index 0000000..7544d4e --- /dev/null +++ b/crafter.html @@ -0,0 +1,183 @@ + + + + + + + + + + + + + WynnCrafter + + + +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + + + + + + +
+ + + + + + + +
+
+ + + + +

+

+

+

+ +
+ +
+

Made by hppeng and ferricles with Atlas Inc (JavaScript required to function, nothing works without js)

+

Hard refresh the page (Ctrl+Shift+R on windows/chrome) if it isn't updating correctly.

+
+
+ Additional credits +
+ + + + + + + + + + + diff --git a/crafter.js b/crafter.js new file mode 100644 index 0000000..a39d09d --- /dev/null +++ b/crafter.js @@ -0,0 +1,229 @@ +/* + * 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 BUILD_VERSION = "6.9.4"; +/* + * END testing section + */ + + + /* TODO: + Make it craft + Make material tier do something + Double powders + Integrate to normal builder + */ +let recipeTypes = ["HELMET","CHESTPLATE","LEGGINGS","BOOTS","RELIK","WAND","SPEAR","DAGGER","BOW","RING","NECKLACE","BRACELET","SCROLL","FOOD","POTION"]; +let levelTypes = ["1-3","3-5","5-7","7-9","10-13","13-15","15-17","17-19","20-23","23-25","25-27","27-29","30-33","33-35","35-37","37-39","40-43","43-45","45-47","47-49","50-53","53-55","55-57","57-59","60-63","63-65","65-67","67-69","70-73","73-75","75-77","77-79","80-83","83-85","85-87","87-89","90-93","93-95","95-97","97-99","100-103","103-105",] +let ingFields = ["fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "lq", "ref", "str", "dex", "int", "agi", "def", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "jh", "sprint", "sprintReg", "gXp", "gSpd"]; +let player_craft; + +function setTitle() { + document.getElementById("header").textContent = "WynnBuilder version "+BUILD_VERSION+" (ingredient db version "+ING_DB_VERSION+")"; + document.getElementById("header").classList.add("funnynumber"); +} +setTitle(); + +let ingMap = new Map(); +let ingList = []; + +let recipeMap = new Map(); +function init() { + //no ing + let ing = Object(); + ing.name = "No Ingredient"; + ing.tier = 0; + ing.lvl = 0; + ing.skills = ["ARMOURING", "TAILORING", "WEAPONSMITHING", "WOODWORKING", "JEWELING", "COOKING", "ALCHEMISM", "SCRIBING"]; + ing.ids= {}; + ing.itemIDs = {"dura": 0, "strReq": 0, "dexReq": 0,"intReq": 0,"defReq": 0,"agiReq": 0,}; + ing.consumableIDs = {"dura": 0, "charges": 0}; + ing.posMods = {"left": 0, "right": 0, "above": 0, "under": 0, "touching": 0, "notTouching": 0} + ingMap.set(ing["name"], ing); + for (const ing of ings) { + ingMap.set(ing["name"], ing); + ingList.push(ing["name"]); + } + for (const recipe of recipes) { + recipeMap.set(recipe["id"], recipe); + } + console.log("all ingredients"); + console.log(ings); + console.log("all recipes"); + console.log(recipes); + + document.getElementById("recipe-choice").addEventListener("change", (event) => { + updateMaterials(); + }); + document.getElementById("level-choice").addEventListener("change", (event) => { + updateMaterials(); + }); + + populateFields(); +} +function updateMaterials() { + let recipeName = getValue("recipe-choice") ? getValue("recipe-choice") : "Potion"; + let levelRange = getValue("level-choice") ? getValue("level-choice") : "103-105"; + let recipe = expandRecipe(recipeMap.get(recipeName + "-" + levelRange)); + if (recipe !== undefined) { + try{ + document.getElementById("mat-1").textContent = recipe.get("materials")[0].get("item").split(" ").slice(1).join(" ") + " Tier:"; + document.getElementById("mat-2").textContent = recipe.get("materials")[1].get("item").split(" ").slice(1).join(" ") + " Tier:"; + } catch (error){ + //eee + } + } + else { + document.getElementById("mat-1").textContent = "Material 1 Tier:"; + document.getElementById("mat-2").textContent = "Material 2 Tier:"; + } +} + +function calculateCraft() { + //Make things display. + for (let i of document.getElementsByClassName("hide-container-block")) { + i.style.display = "block"; + } + for (let i of document.getElementsByClassName("hide-container-grid")) { + i.style.display = "grid"; + } + //define the fields that will go into crafting the craft. + let recipe = getValue("recipe-choice") === "" ? "Potion" : getValue("recipe-choice"); + let levelrange = getValue("level-choice") === "" ? "103-105" : getValue("level-choice"); + recipe = expandRecipe(recipeMap.get(recipe+"-"+levelrange)); + let mat_tiers = []; + for (i = 1; i < 3; i++) { + for(j = 1; j < 4; j++) { + let elem = document.getElementById("mat-" + i + "-" + j); + if(elem.classList.contains("toggleOn")) { + mat_tiers.push(j); //Tier is 1, 2, or 3. + break; + } + } + if (mat_tiers.length < i) { //defualt to t3 + mat_tiers.push(3); + document.getElementById("mat-"+i+"-3").classList.add("toggleOn"); + } + } + let ingreds = []; + for (i = 1; i < 7; i++) { + getValue("ing-choice-" + i) === "" ? ingreds.push(expandIngredient(ingMap.get("No Ingredient"))) : ingreds.push(expandIngredient(ingMap.get(getValue("ing-choice-" + i)))); + } + + //create the craft + player_craft = new Craft(recipe,mat_tiers,ingreds); + console.log(player_craft); + /*console.log(recipe) + console.log(levelrange) + console.log(mat_tiers) + console.log(ingreds)*/ + document.getElementById("mat-1").textContent = recipe.get("materials")[0].get("item").split(" ").slice(1).join(" ") + " Tier:"; + document.getElementById("mat-2").textContent = recipe.get("materials")[1].get("item").split(" ").slice(1).join(" ") + " Tier:"; + + + //Display Craft Stats + displayCraftStats(player_craft, "craft-stats"); + //Display Ingredients' Stats + for (let i = 1; i < 7; i++) { + displayExpandedIngredient(player_craft.ingreds[i-1] , "ing-"+i+"-stats"); + } + //set the location hash. TODO + /*let hash = ""; + location.hash = hash;*/ +} +function populateFields() { + let recipe_list = document.getElementById("recipe-choices"); + for (const recipe of recipeTypes) { + let el = document.createElement("option"); + el.value = recipe.charAt(0) + recipe.substring(1).toLowerCase(); + recipe_list.appendChild(el); + } + let level_list = document.getElementById("level-choices"); + for (const range of levelTypes) { + let el = document.createElement("option"); + el.value = range; + level_list.appendChild(el); + } + for (i = 1; i < 7; i++) { + let ing_list = document.getElementById("ing-choices-"+i); + for (const ing of ingList) { + let el = document.createElement("option"); + el.value = ing; + ing_list.appendChild(el); + } + } + + +} + +/* Toggles ONE button +*/ +function toggleButton(buttonId) { + let elem = document.getElementById(buttonId); + if (elem.classList.contains("toggleOn")) { + elem.classList.remove("toggleOn"); + } else{ + elem.classList.add("toggleOn"); + } +} + +/* Copy the link +*/ +function copyRecipe(){ + if (player_craft) { + copyTextToClipboard(url_base+location.hash); + document.getElementById("copy-button").textContent = "Copied!"; + } +} + +/* Copy the link AND a display of all ingredients +*/ +function shareRecipe(){ + if (player_craft) { + copyTextToClipboard(url_base+location.hash); + document.getElementById("share-button").textContent = "Copied!"; + } +} +/* Toggles the entire material's buttons +*/ +function toggleMaterial(buttonId) { + let elem = document.getElementById(buttonId); + let mat = buttonId.split("-")[1] + if (!elem.classList.contains("toggleOn")) { //we turned on that button, now toggle the others off + toggleButton(buttonId); + for (i = 1; i < 4; i++) { + if ("mat-" + mat + "-" + i !== buttonId) { + document.getElementById("mat-" + mat + "-" + i).classList.remove("toggleOn"); + } + } + } else { //we turned off a button: do nothing + toggleButton(buttonId); + } +} + +/* Reset all fields +*/ +function resetFields() { + for (let i = 1; i < 3; i ++) { + for (let j = 1; j < 4; j++) { + document.getElementById("mat-"+i+"-"+j).classList.remove("toggleOn"); + } + } + for (let i = 1; i < 7; i++) { + setValue("ing-choice-"+i, ""); + } + setValue("recipe-choice", ""); + setValue("level-choice", ""); + location.hash = ""; + calculateCraft(); +} + +load_ing_init(init); \ No newline at end of file diff --git a/credits.txt b/credits.txt index 6145cc2..29ba52c 100644 --- a/credits.txt +++ b/credits.txt @@ -6,5 +6,5 @@ The game, of course Additional Contributors: - QuantumNep (Layout code/layout ideas) - - dr_carlos (Hiding UI elements, misc. fixes) + - dr_carlos (Hiding UI elements properly, fade animations, proper error handling) - Atlas Inc discord (feedback, ideas, etc) diff --git a/display.js b/display.js index 5f0737c..af316c1 100644 --- a/display.js +++ b/display.js @@ -139,7 +139,7 @@ let consumableIDPrefixes = { } let consumableIDSuffixes = { "charges": "", - "dura": " Sec." + "dura": " sec." } //Used for ingredient itemIDs let itemIDPrefixes = { @@ -163,7 +163,7 @@ let posModPrefixes = { "left":"Effectiveness Left: ", "right":"EFfectiveness Right: ", "above":"Effectiveness Above: ", - "below":"Effectivness Below: ", + "under":"Effectiveness Under: ", "touching":"EFfectiveness Touching: ", "notTouching":"Effectiveness Not Touching: " } @@ -171,7 +171,7 @@ let posModSuffixes = { "left":"%", "right":"%", "above":"%", - "below":"%", + "under":"%", "touching":"%", "notTouching":"%" } @@ -407,6 +407,7 @@ function displayExpandedItem(item, parent_id){ "#ldiv", "str", "dex", "int", "def", "agi", "#table", + "str", "dex", "int", "def", "agi", //jank lmao "hpBonus", "hprRaw", "hprPct", "sdRaw", "sdPct", @@ -469,7 +470,7 @@ function displayExpandedItem(item, parent_id){ } else { let id = command; - if(nonRolledIDs.includes(id) && item.get(id)){//nonRolledID & non-0/non-null/non-und ID + if(( nonRolledIDs.includes(id) && item.get(id))){//nonRolledID & non-0/non-null/non-und ID if (id === "slots") { let p_elem = document.createElement("p"); // PROPER POWDER DISPLAYING EZ CLAP @@ -498,14 +499,23 @@ function displayExpandedItem(item, parent_id){ powderSuffix.textContent = "]"; p_elem.appendChild(powderSuffix); active_elem.appendChild(p_elem); - } - else { - let p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format); + } else { + let p_elem; + if (!(skp_order.includes(id) && item.get("tier") === "Crafted")) { + p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format); + } if (id === "displayName") { p_elem.classList.add("title"); if (item.get("tier") !== " ") { p_elem.classList.add(item.get("tier")); } + if (["potion", "scroll", "food"].includes(item.get("type"))){ //must have access to craft.js + let b = document.createElement("b"); + b.textContent = "[" + item.get("charges") + "/" + item.get("charges") + "]"; + b.classList.add("spaceleft"); + p_elem.appendChild(b); + } + /*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"); @@ -519,28 +529,52 @@ function displayExpandedItem(item, parent_id){ p_elem.append(p); }*/ } else if (skp_order.includes(id)) { //id = str, dex, int, def, or agi - p_elem.textContent = ""; - p_elem.classList.add("itemtable"); - let row = document.createElement("tr"); - let title = document.createElement("td"); - title.textContent = idPrefixes[id] + " "; - let boost = document.createElement("td"); - if (item.get(id) < 0) { - boost.classList.add("negative"); - } else { //boost = 0 SHOULD not come up - boost.classList.add("positive"); + if ( item.get("tier") !== "Crafted" && active_elem.nodeName === "DIV") { + p_elem.textContent = ""; + p_elem.classList.add("itemp"); + row = document.createElement("p"); + row.classList.add("left"); + + 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); + p_elem.appendChild(row); + } else if ( item.get("tier") === "Crafted" && active_elem.nodeName === "TABLE") { + let row = document.createElement('tr'); + let min_elem = document.createElement('td'); + + min_elem.classList.add('left'); + min_elem.classList.add( item.get("minRolls").get(id) < 0 ? "negative" : "positive"); + min_elem.textContent = item.get("minRolls").get(id) + idSuffixes[id]; + row.appendChild(min_elem); + + let desc_elem = document.createElement('td'); + desc_elem.classList.add('center'); + //TODO elemental format jank + desc_elem.textContent = idPrefixes[id]; + row.appendChild(desc_elem); + + let max_elem = document.createElement('td'); + max_elem.classList.add('right'); + max_elem.classList.add( item.get("maxRolls").get(id) < 0 ? "negative" : "positive"); + max_elem.textContent = item.get("maxRolls").get(id) + idSuffixes[id]; + row.appendChild(max_elem); + active_elem.appendChild(row); } - boost.classList.add("spaceLeft"); - boost.textContent = item.get(id); - row.appendChild(title); - row.appendChild(boost); - p_elem.appendChild(row); - } else if (id === "restrict") { + } else if (id === "restrict") { p_elem.classList.add("restrict"); } } } - else if (rolledIDs.includes(id) && item.get("minRolls").get(id)){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID + else if ( (rolledIDs.includes(id) && item.get("minRolls").get(id)) ){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID let style = "positive"; if (item.get("minRolls").get(id) < 0) { style = "negative"; @@ -579,74 +613,95 @@ function displayExpandedItem(item, parent_id){ row.appendChild(max_elem); active_elem.appendChild(row); } - }//Just don't do anything if else + }else{ + // :/ + } } } //Show powder specials ;-; - let powder_special = document.createElement("p"); - powder_special.classList.add("left"); - 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; + 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("p"); + powder_special.classList.add("left"); + 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("p"); - let specialEffects = document.createElement("p"); - specialTitle.classList.add("left"); - specialTitle.classList.add("itemp"); - specialTitle.classList.add(damageClasses[skp_elements.indexOf(element) + 1]); - specialEffects.classList.add("left"); - specialEffects.classList.add("itemp"); - specialEffects.classList.add("nocolor"); - 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) { - if (key !== "Description") { - let effect = document.createElement("p"); - effect.classList.add("itemp"); - effect.textContent += key + ": " + value[power] + specialSuffixes.get(key); - if(key === "Damage"){ - effect.textContent += elementIcons[skp_elements.indexOf(element)]; - } - if (element === "w") { - effect.textContent += " / Mana Used"; - } - specialEffects.appendChild(effect); - }else{ - specialTitle.textContent += "[ " + effects.get("Description") + " ]"; + 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("p"); + let specialEffects = document.createElement("p"); + specialTitle.classList.add("left"); + specialTitle.classList.add("itemp"); + specialTitle.classList.add(damageClasses[skp_elements.indexOf(element) + 1]); + specialEffects.classList.add("left"); + specialEffects.classList.add("itemp"); + specialEffects.classList.add("nocolor"); + 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) { + if (key !== "Description") { + let effect = document.createElement("p"); + effect.classList.add("itemp"); + effect.textContent += key + ": " + value[power] + specialSuffixes.get(key); + if(key === "Damage"){ + effect.textContent += elementIcons[skp_elements.indexOf(element)]; + } + if (element === "w") { + effect.textContent += " / Mana Used"; + } + specialEffects.appendChild(effect); + }else{ + specialTitle.textContent += "[ " + effects.get("Description") + " ]"; + } + } + specialTitle.append(specialEffects); + powder_special.appendChild(specialTitle); + + + parent_div.append(powder_special); } - specialTitle.append(specialEffects); - powder_special.appendChild(specialTitle); - - - parent_div.append(powder_special); } - + + if(item.get("tier") && item.get("tier") === "Crafted") { + let dura_elem = document.createElement("p"); + dura_elem.classList.add("left"); + 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." + } + 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('p'); + let item_desc_elem = document.createElement("p"); item_desc_elem.classList.add('left'); item_desc_elem.classList.add(item.get("tier")); item_desc_elem.textContent = item.get("tier")+" "+item.get("type"); @@ -654,11 +709,8 @@ function displayExpandedItem(item, parent_id){ } } function displayCraftStats(craft, parent_id) { - -} - -function displayExpandedRecipe(recipe, parent_id) { - + let mock_item = craft.statMap; + displayExpandedItem(mock_item,parent_id); } @@ -693,7 +745,7 @@ function displayExpandedIngredient(ingred, parent_id) { ] let posMods_order = [ "above", - "below", + "under", "left", "right", "touching", @@ -803,6 +855,8 @@ function displayExpandedIngredient(ingred, parent_id) { p_elem.textContent = "Crafting Lvl Min: " + ingred.get("lvl"); }else if (command === "posMods") { for (const [key,value] of ingred.get("posMods")) { + let p = document.createElement("p"); + p.classList.add("nomarginp"); if (value != 0) { let title = document.createElement("b"); title.textContent = posModPrefixes[key]; @@ -813,8 +867,9 @@ function displayExpandedIngredient(ingred, parent_id) { } else { val.classList.add("negative"); } - p_elem.appendChild(title); - p_elem.appendChild(val); + p.appendChild(title); + p.appendChild(val); + p_elem.appendChild(p); } } } else if (command === "itemIDs") { //dura, reqs diff --git a/index.html b/index.html index 0257cdc..4ccd08b 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,9 @@ +
+ Forum thread (instructions/help) +
@@ -34,10 +37,12 @@ +

+

@@ -46,10 +51,12 @@ +

+

@@ -58,10 +65,12 @@ +

+

@@ -70,10 +79,12 @@ +

+

@@ -83,11 +94,13 @@ +


+

@@ -105,6 +118,7 @@ +

@@ -113,6 +127,7 @@ +

@@ -121,6 +136,7 @@ +

@@ -129,6 +145,7 @@ +

@@ -136,6 +153,7 @@
+

@@ -424,7 +442,7 @@

- +
Manually Assigned: 0 @@ -438,7 +456,7 @@

- +
Manually Assigned: 0 @@ -452,7 +470,7 @@

- +
Manually Assigned: 0 @@ -466,7 +484,7 @@

- +
Manually Assigned: 0 @@ -480,7 +498,7 @@

- +
Manually Assigned: 0 @@ -492,10 +510,317 @@
+ +
+