diff --git a/crafter.js b/crafter.js index 5d3e323..771cc8d 100644 --- a/crafter.js +++ b/crafter.js @@ -9,7 +9,7 @@ console.log(ing_url_tag); -const ING_BUILD_VERSION = "6.9.40"; +const ING_BUILD_VERSION = "6.9.41"; /* * END testing section */ @@ -262,6 +262,7 @@ function encodeCraft(craft) { } return ""; } + function decodeCraft(ing_url_tag) { if (ing_url_tag) { console.log(ing_url_tag); diff --git a/custom.js b/custom.js index 7b32cad..227b597 100644 --- a/custom.js +++ b/custom.js @@ -1,14 +1,15 @@ -tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"] //I'm not sure why you would make a custom crafted but if you do you should be able to use it w/ the correct powder formula -types = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(consumableTypes).map(x => x.substring(0,1).toUpperCase() + x.substring(1)); +const tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"] //I'm not sure why you would make a custom crafted but if you do you should be able to use it w/ the correct powder formula +const types = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(consumableTypes).map(x => x.substring(0,1).toUpperCase() + x.substring(1)); +const atkSpds = ["SUPER_SLOW","VERY_SLOW","SLOW","NORMAL","FAST","VERY_FAST","SUPER_FAST"]; +const ci_save_order = ["name", "lore", "tier", "set", "slots", "type", "material", "drop", "quest", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq","str", "dex", "int", "agi", "def", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd"]; +//omitted restrict - it's always "Custom Item" +//omitted displayName - either it's the same as name (repetitive) or it's "Custom Item" +//omitted category - can always get this from type +//omitted fixId - we will denote this early in the string. -//constructs a CI from a hash 'CI-qwoefsabaoe' or 'qwoefsaboe' -function getCustomFromHash(hash) { - -} - /** An object representing a Custom Item. Mostly for vanity purposes. * @dep Requires the use of nonRolledIDs and rolledIDs from display.js. @@ -40,21 +41,15 @@ class Custom{ } } - //Sets the "Hash" of the CI. YOU SHOULD NEVER BE CHANGING THE HASH. + setHash(hash) { this.hash = hash; - //this.statMap.set("displayName", "CI-" + this.hash); - this.statMap.set("hash", this.hash); - } - - //TODO - setHash() { - this.statMap.set("hash", "Custom Item"); + this.statMap.set("hash",hash); } updateName(name) { this.name = name; - this.displayName = name; //name overrides hash + this.displayName = name; } /* Get all stats for this CI. @@ -63,8 +58,11 @@ class Custom{ * TODO: Check if this is even useful */ initCustomStats(){ + //this.setHashVerbose(); //do NOT move sethash from here please + + this.statMap.set("custom", true); if (this.statMap.get("tier") === "Crafted") { - this.statMap.set("Crafted", true); + this.statMap.set("crafted", true); for (const e of skp_elements) { this.statMap.set(e+"DamLow", this.statMap.get(e+"Dam")); } @@ -87,11 +85,11 @@ class Custom{ this.statMap.set("atkSpd", ""); } - this.setHash(); + if (this.statMap.get("name") && this.statMap.get("name") !== "") { this.statMap.set("displayName", this.statMap.get("name")); } else { - this.statMap.set("displayName", this.statMap.get("hash")); + this.statMap.set("displayName", "Custom Item"); } this.statMap.set("reqs",[this.statMap.get("strReq"),this.statMap.get("dexReq"),this.statMap.get("intReq"),this.statMap.get("defReq"),this.statMap.get("agiReq")]); diff --git a/customizer.html b/customizer.html index 0776dd2..3062d3a 100644 --- a/customizer.html +++ b/customizer.html @@ -105,13 +105,7 @@

- - - - -

- - + @@ -1842,25 +1836,36 @@ Create +
+ +
+
+
Fixed IDs:
+
-
- +
+
-
+
+ +

+
+
Base Item:
-
+
-
+
diff --git a/customizer.js b/customizer.js index 2d12a23..5f449fd 100644 --- a/customizer.js +++ b/customizer.js @@ -8,7 +8,7 @@ const custom_url_tag = location.hash.slice(1); console.log(custom_url_base); console.log(custom_url_tag); -const BUILD_VERSION = "6.9.40"; +const BUILD_VERSION = "6.9.41"; function setTitle() { let text = "WynnCustom version "+BUILD_VERSION; @@ -32,6 +32,7 @@ let pos_range = [0.3,1.3]; let neg_range = [1.3,0.7]; + let itemMap = new Map(); /* Mapping from item names to set names. */ let idMap = new Map(); @@ -120,10 +121,10 @@ function calculateCustom() { if (input.classList.contains("number-input")) { if (parseFloat(input.value)) { if(rolledIDs.includes(id)) { - statMap.get("minRolls").set(id,parseFloat(input.value)); - statMap.get("maxRolls").set(id,parseFloat(input.value)); + statMap.get("minRolls").set(id,Math.round(parseFloat(input.value))); + statMap.get("maxRolls").set(id,Math.round(parseFloat(input.value))); } else { - statMap.set(id, parseFloat(input.value)); + statMap.set(id, Math.round(parseFloat(input.value))); } } } else if (input.classList.contains("string-input")) { @@ -134,16 +135,16 @@ function calculateCustom() { statMap.set(id, input.value); } } else if (input.classList.contains("array-input")) { - statMap.set(id, input.value.split("-").map(x=>parseFloat(x))); + statMap.set(id, input.value.split("-").map(x=>Math.round(parseFloat(x)))); } if(input.value === "" && input.placeholder && input.placeholder !== "") { if (input.classList.contains("number-input") && parseFloat(input.placeholder)) { - statMap.set(id, parseFloat(input.placeholder)); + statMap.set(id, Math.round(parseFloat(input.placeholder))); } else if (input.classList.contains("string-input")) { statMap.set(id, input.placeholder); } else if (input.classList.contains("array-input")) { - statMap.set(id, input.placeholder.split("-").map(x=>parseFloat(x))); + statMap.set(id, input.placeholder.split("-").map(x=>Math.round(parseFloat(x)))); } } } @@ -174,9 +175,9 @@ function calculateCustom() { if (input.classList.contains("number-input")) { if (parseFloat(input.value)) { if (rolledIDs.includes(id)) { - statMap.get(rollMap).set(id, parseFloat(input.value)); + statMap.get(rollMap).set(id, Math.round(parseFloat(input.value))); } else { - statMap.set(id, parseFloat(input.value)); + statMap.set(id, Math.round(parseFloat(input.value))); } } } else if (input.classList.contains("string-input")) { @@ -186,15 +187,15 @@ function calculateCustom() { statMap.set(id, input.value); } } else if (input.classList.contains("array-input")) { - statMap.set(id, input.value.split("-").map(x=>parseFloat(x))); + statMap.set(id, input.value.split("-").map(x=>Math.round(parseFloat(x)))); } if(input.value === "" && input.placeholder && input.placeholder !== "") { if (input.classList.contains("number-input")) { if (rolledIDs.includes(id)) { - statMap.get(rollMap).set(id, parseFloat(input.placeholder)); + statMap.get(rollMap).set(id, Math.round(parseFloat(input.placeholder))); } else { - statMap.set(id, parseFloat(input.placeholder)); + statMap.set(id, Math.round(parseFloat(input.placeholder))); } } else if (input.classList.contains("string-input")){ if (rolledIDs.includes(id)) { @@ -203,7 +204,7 @@ function calculateCustom() { statMap.set(id, input.placeholder); } } else if (input.classList.contains("array-input")) { - statMap.set(id, input.placeholder.split("-").map(x=>parseFloat(x))); + statMap.set(id, input.placeholder.split("-").map(x=>Math.round(parseFloat(x)))); } } } @@ -212,8 +213,16 @@ function calculateCustom() { player_custom_item = new Custom(statMap); + + let custom_str = encodeCustom(player_custom_item.statMap, false); + location.hash = custom_str; + player_custom_item.setHash(custom_str); + console.log(player_custom_item.statMap.get("hash")); + + displayExpandedItem(player_custom_item.statMap, "custom-stats"); - console.log(player_custom_item.statMap); + + //console.log(player_custom_item.statMap); }catch (error) { //USE THE ERROR

S! @@ -235,20 +244,123 @@ function calculateCustom() { } -function encodeCustom(custom) { - +/** + * @param {Map} custom - the statMap of the CI + * @param {boolean} verbose - if we want lore and majorIds to display + */ +function encodeCustom(custom, verbose) { + if (custom) { + let hash = "1"; + //version 1 + if (custom.has("fixID") && custom.get("fixID")) { + hash += "1"; + } else { + hash += "0"; + } + for (const i in ci_save_order) { + let id = ci_save_order[i]; + if (rolledIDs.includes(id)) { + let val_min = custom.get("minRolls").has(id) ? custom.get("minRolls").get(id) : 0; + let val_max = custom.get("maxRolls").has(id) ? custom.get("maxRolls").get(id) : 0; + let min_len = Math.max(1,Math.ceil(log(64,Math.abs(val_min)))); + let max_len = Math.max(1,Math.ceil(log(64,Math.abs(val_max)))); + let len = Math.max(min_len,max_len); + + if ( val_min != 0 || val_max != 0 ) { + //hash += Base64.fromIntN(i,2) + Base64.fromIntN(val_min,Math.max(1,Math.ceil(log(64,Math.abs(val_min))))) + ":" + Base64.fromIntN(val_max,Math.max(1,Math.ceil(log(64,Math.abs(val_min))))) + "_"; + if (custom.get("fixID")) { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(len,2) + Base64.fromIntN(val_min, len); + } else { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(len,2) + Base64.fromIntN(val_min, len) + Base64.fromIntN(val_max,len); + } + } + } else { + let damages = ["nDam", "eDam", "tDam", "wDam", "fDam", "aDam","nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_"]; + let val = custom.get(id); + if (typeof(val) === "string" && val !== "") { + if ((damages.includes(id) && val === "0-0") || (!verbose && (id === "lore" || id === "majorIds"))) { continue; } + if (id === "type") { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(types.indexOf(val.substring(0,1).toUpperCase()+val.slice(1)),1); + } else if (id === "tier") { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(tiers.indexOf(val),1); + } else if (id === "atkSpd") { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(atkSpds.indexOf(val),1); + } else { + hash += Base64.fromIntN(i,2) + Base64.fromIntN(val.replace(" ", "%20").length,2) + val.replace(" ", "%20"); //values cannot go above 4096 chars!!!! Is this ok? + } + } else if (typeof(val) === "number" && val != 0) { + let len = Math.max(1,Math.ceil(log(64,Math.abs(val)))); + //hash += Base64.fromIntN(i,2) + Base64.fromIntN(val,Math.max(1,Math.ceil(log(64,Math.abs(val))))) + "_"; + hash += Base64.fromIntN(i,2) + Base64.fromIntN(len,2) + Base64.fromIntN(val,len); + } + } + } + + return hash; + } return ""; } function decodeCustom(custom_url_tag) { if (custom_url_tag) { - console.log(custom_url_tag); let version = custom_url_tag.charAt(0); - let tag = custom_url_tag.substring(1); + let fixID = Boolean(parseInt(custom_url_tag.charAt(1),10)); + let tag = custom_url_tag.substring(2); + let statMap = new Map(); + statMap.set("minRolls", new Map()); + statMap.set("maxRolls", new Map()); + if (version === "1") { //do the things - + if (fixID) {statMap.set("fixId", "true");} + while (tag !== "") { + let id = ci_save_order[Base64.toInt(tag.slice(0,2))]; + let len = Base64.toInt(tag.slice(2,4)); + if (rolledIDs.includes(id)) { + let minRoll = Base64.toInt(tag.slice(4,4+len)); + if (!fixID) { + let maxRoll = Base64.toInt(tag.slice(4+len,4+2*len)); + setValue(id+"-choice-min", minRoll); + setValue(id+"-choice-max", maxRoll); + statMap.get("minRolls").set(id,minRoll); + statMap.get("maxRolls").set(id,maxRoll); + tag = tag.slice(4+2*len); + } else { + setValue(id+"-choice-fixed", minRoll); + statMap.get("minRolls").set(id,minRoll); + statMap.get("maxRolls").set(id,minRoll); + tag = tag.slice(4+len); + } + } else { + let val; + let elem = document.getElementById(id+"-choice"); + if (elem.classList.contains("number-input")) { + val = Base64.toInt(tag.slice(4,4+len)); + } else if (elem.classList.contains("string-input") || classList.contains("array-input")) { + if (id === "tier") { + val = tiers[Base64.toInt(tag.charAt(2))]; + len = -1; + } else if (id === "type") { + val = types[Base64.toInt(tag.charAt(2))]; + len = -1; + } + else if (id === "atkSpd") { + val = atkSpds[Base64.toInt(tag.charAt(2))]; + len = -1; + } else { //general case + val = tag.slice(4,4+len).replace("%20"," "); + } + } else { + val = ""; + } + statMap.set(id, val); + setValue(id+"-choice", val); + tag = tag.slice(4+len); + } + } + statMap.set("hash",custom_url_tag); calculateCustom(); + player_custom_item.setHash(custom_url_tag); } } } @@ -406,13 +518,22 @@ function useBaseItem(elem) { /* Copy the link */ -function copyCustom(){ +function copyCustom() { if (player_custom_item) { copyTextToClipboard(custom_url_base+location.hash); document.getElementById("copy-button").textContent = "Copied!"; } } +function copyCustomLong() { + if (player_custom_item) { + let hash = encodeCustom(player_custom_item.statMap,true); + console.log(hash); + location.hash = hash; + copyTextToClipboard(custom_url_base+location.hash); + document.getElementById("copy-button-long").textContent = "Copied!"; + } +} /* Reset all fields diff --git a/display.js b/display.js index e780e71..c2e9fb5 100644 --- a/display.js +++ b/display.js @@ -597,10 +597,22 @@ function displayExpandedItem(item, parent_id){ p_elem.classList.add('itemp'); p_elem.classList.add("smalltitle"); p_elem.classList.add(item.get("tier")); - p_elem.href = url_base + "crafter.html#" + item.get("hash"); + p_elem.href = url_base.replace("crafter.html","").replace("customizer.html","") + "crafter.html#" + item.get("hash"); + p_elem.target = "_blank"; p_elem.textContent = item.get(id); active_elem.appendChild(p_elem); } + if(item.get("custom")) { + p_elem.remove(); + p_elem = document.createElement("a"); + p_elem.classList.add('itemp'); + p_elem.classList.add("smalltitle"); + p_elem.classList.add(item.get("tier")); + p_elem.href = url_base.replace("crafter.html","").replace("customizer.html","") + "customizer.html#" + item.get("hash"); + p_elem.target = "_blank"; + p_elem.textContent = item.get("displayName"); + active_elem.appendChild(p_elem); + } let img = document.createElement("img"); img.src = "/media/items/generic-" + item.get("type") + ".png"; img.alt = item.get("type"); diff --git a/utils.js b/utils.js index 5c07484..c9a2cfa 100644 --- a/utils.js +++ b/utils.js @@ -70,6 +70,10 @@ function getValue(id) { return document.getElementById(id).value; } +function log(b, n) { + return Math.log(n) / Math.log(b); +} + // Base 64 encoding tools // https://stackoverflow.com/a/27696695 // Modified for fixed precision