crafteds v0

This commit is contained in:
ferricles 2021-01-19 09:32:27 -08:00
commit b809c279c3
28 changed files with 41377 additions and 535 deletions

205
build.js
View file

@ -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 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] ]); 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 * @description Error to catch items that don't exist.
*/ * @module ItemNotFound
function skillPointsToPercentage(skp){ */
if (skp<=0){ class ItemNotFound {
return 0.0; /**
}else if(skp>=150){ * @class
return 0.808; * @param {String} item the item name entered
}else{ * @param {String} type the type of item
return (-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771); * @param {Boolean} genElement whether to generate an element from inputs
//return(-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771).toFixed(3); * @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 into skillpoints available. /**
* * @description Error to catch incorrect input.
* @param level - the integer level count te be converted * @module IncorrectInput
*/ */
function levelToSkillPoints(level){ class IncorrectInput {
if(level < 1){ /**
return 0; * @class
}else if(level >= 101){ * @param {String} input the inputted text
return 200; * @param {String} format the correct format
}else{ * @param {String} sibling the id of the error node's sibling
return (level - 1) * 2; */
constructor(input, format, sibling) {
/**
* @public
* @type {String}
*/
this.message = `${input} is incorrect. Example: ${format}`;
/**
* @public
* @type {String}
*/
this.id = sibling;
} }
} }
/*Turns the input amount of levels in to base HP. /**
* @param level - the integer level count to be converted * @description Error that inputs an array of items to generate errors of.
*/ * @module ListError
function levelToHPBase(level){ * @extends Error
if(level < 1){ //bad level */
return this.levelToHPBase(1); class ListError extends Error {
}else if (level > 106){ //also bad level /**
return this.levelToHPBase(106); * @class
}else{ //good level * @param {Array} errors array of errors
return 5*level + 5; */
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{ class Build{
/* /**
* Construct a build. * @description Construct a build.
* @param level : Level of the player. * @param {Number} level : Level of the player.
* @param equipment : List of equipment names that make up the build. * @param {String[]} equipment : List of equipment names that make up the build.
* In order: Helmet, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon. * In order: 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. * 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. // NOTE: powders is just an array of arrays of powder IDs. Not powder objects.
this.powders = powders; this.powders = powders;
if(itemMap.get(equipment[0]) && itemMap.get(equipment[0]).type === "helmet") { 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.powders[0] = this.powders[0].slice(0,helmet.slots);
this.helmet = expandItem(helmet, this.powders[0]); this.helmet = expandItem(helmet, this.powders[0]);
}else{ }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") { if(itemMap.get(equipment[1]) && itemMap.get(equipment[1]).type === "chestplate") {
const chestplate = itemMap.get(equipment[1]); const chestplate = itemMap.get(equipment[1]);
this.powders[1] = this.powders[1].slice(0,chestplate.slots); this.powders[1] = this.powders[1].slice(0,chestplate.slots);
this.chestplate = expandItem(chestplate, this.powders[1]); this.chestplate = expandItem(chestplate, this.powders[1]);
}else{ }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") { if(itemMap.get(equipment[2]) && itemMap.get(equipment[2]).type === "leggings") {
const leggings = itemMap.get(equipment[2]); const leggings = itemMap.get(equipment[2]);
this.powders[2] = this.powders[2].slice(0,leggings.slots); this.powders[2] = this.powders[2].slice(0,leggings.slots);
this.leggings = expandItem(leggings, this.powders[2]); this.leggings = expandItem(leggings, this.powders[2]);
}else{ }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") { if(itemMap.get(equipment[3]) && itemMap.get(equipment[3]).type === "boots") {
const boots = itemMap.get(equipment[3]); const boots = itemMap.get(equipment[3]);
this.powders[3] = this.powders[3].slice(0,boots.slots); this.powders[3] = this.powders[3].slice(0,boots.slots);
this.boots = expandItem(boots, this.powders[3]); this.boots = expandItem(boots, this.powders[3]);
}else{ }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") { if(itemMap.get(equipment[4]) && itemMap.get(equipment[4]).type === "ring") {
const ring = itemMap.get(equipment[4]); const ring = itemMap.get(equipment[4]);
this.ring1 = expandItem(ring, []); this.ring1 = expandItem(ring, []);
}else{ }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") { if(itemMap.get(equipment[5]) && itemMap.get(equipment[5]).type === "ring") {
const ring = itemMap.get(equipment[5]); const ring = itemMap.get(equipment[5]);
this.ring2 = expandItem(ring, []); this.ring2 = expandItem(ring, []);
}else{ }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") { if(itemMap.get(equipment[6]) && itemMap.get(equipment[6]).type === "bracelet") {
const bracelet = itemMap.get(equipment[6]); const bracelet = itemMap.get(equipment[6]);
this.bracelet = expandItem(bracelet, []); this.bracelet = expandItem(bracelet, []);
}else{ }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") { if(itemMap.get(equipment[7]) && itemMap.get(equipment[7]).type === "necklace") {
const necklace = itemMap.get(equipment[7]); const necklace = itemMap.get(equipment[7]);
this.necklace = expandItem(necklace, []); this.necklace = expandItem(necklace, []);
}else{ }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") { if(itemMap.get(equipment[8]) && itemMap.get(equipment[8]).category === "weapon") {
const weapon = itemMap.get(equipment[8]); const weapon = itemMap.get(equipment[8]);
this.powders[4] = this.powders[4].slice(0,weapon.slots); this.powders[4] = this.powders[4].slice(0,weapon.slots);
this.weapon = expandItem(weapon, this.powders[4]); this.weapon = expandItem(weapon, this.powders[4]);
}else{ }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; this.level = 1;
}else if (level > 106){ } else if (level > 106) {
this.level = 106; this.level = 106;
}else{ } else if (level <= 106 && level >= 1) {
this.level = level; 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.availableSkillpoints = levelToSkillPoints(this.level);
this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ]; 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]); this.items = this.equipment.concat([this.weapon]);
@ -144,12 +225,19 @@ class Build{
this.externalStats = externalStats; this.externalStats = externalStats;
this.initBuildStats(); 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 /*Returns build in string format
*/ */
toString(){ 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 */ /* Getters */
@ -274,14 +362,10 @@ class Build{
} }
} }
} }
statMap.set("poisonPct", 100);
// The stuff relevant for damage calculation!!! @ferricles // The stuff relevant for damage calculation!!! @ferricles
statMap.set("atkSpd", this.weapon.get("atkSpd")); 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) { for (const x of skp_elements) {
this.externalStats.set(x + "DamPct", 0); this.externalStats.set(x + "DamPct", 0);
@ -292,6 +376,15 @@ class Build{
this.externalStats.set("defBonus",[0, 0, 0, 0, 0]); this.externalStats.set("defBonus",[0, 0, 0, 0, 0]);
this.externalStats.set("poisonPct", 0); this.externalStats.set("poisonPct", 0);
this.statMap = statMap; 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")]);
}
} }

40
build_utils.js Normal file
View file

@ -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;
}
}

View file

@ -1,16 +1,9 @@
/*
* TESTING SECTION
*/
const url_base = location.href.split("#")[0]; const url_base = location.href.split("#")[0];
const url_tag = location.hash.slice(1); const url_tag = location.hash.slice(1);
console.log(url_base); console.log(url_base);
console.log(url_tag); console.log(url_tag);
/* const BUILD_VERSION = "6.9.4";
* END testing section
*/
function setTitle() { function setTitle() {
document.getElementById("header").textContent = "WynnBuilder version "+BUILD_VERSION+" (db version "+DB_VERSION+")"; 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" ]; let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ];
// THIS IS SUPER DANGEROUS, WE SHOULD NOT BE KEEPING THIS IN SO MANY PLACES // 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 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; equipment[i] = equip;
} }
let powderings = []; let powderings = [];
let errors = [];
for (const i in powderInputs) { for (const i in powderInputs) {
// read in two characters at a time. // read in two characters at a time.
// TODO: make this more robust. // TODO: make this more robust.
let input = getValue(powderInputs[i]); let input = getValue(powderInputs[i]);
let powdering = []; let powdering = [];
let errorederrors = [];
while (input) { while (input) {
let first = input.slice(0, 2); let first = input.slice(0, 2);
let powder = powderIDs.get(first); let powder = powderIDs.get(first);
console.log(powder); console.log(powder);
if (powder === undefined) { 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); 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); powderings.push(powdering);
} }
//level setting
let level = document.getElementById("level-choice").value; console.log(equipment);
if(level === ""){ player_build = new Build(document.getElementById("level-choice").value, equipment, powderings, new Map(), errors);
level = 106;
}
document.getElementById("level-choice").value = level;
for (let i of document.getElementsByClassName("hide-container-block")) { for (let i of document.getElementsByClassName("hide-container-block")) {
i.style.display = "block"; i.style.display = "block";
@ -454,9 +455,9 @@ function calculateBuild(save_skp, skp){
for (let i of document.getElementsByClassName("hide-container-grid")) { for (let i of document.getElementsByClassName("hide-container-grid")) {
i.style.display = "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); displayEquipOrder(document.getElementById("build-order"),player_build.equip_order);
@ -467,6 +468,11 @@ function calculateBuild(save_skp, skp){
setText(skp_order[i] + "-skp-base", "Original Value: " + skillpoints[i]); 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) { if (save_skp) {
// TODO: reduce duplicated code, @updateStats // TODO: reduce duplicated code, @updateStats
let skillpoints = player_build.total_skillpoints; let skillpoints = player_build.total_skillpoints;
@ -483,8 +489,36 @@ function calculateBuild(save_skp, skp){
calculateBuildStats(); calculateBuildStats();
setTitle(); setTitle();
if (player_build.errored)
throw new ListError(player_build.errors);
} }
catch (error) { catch (error) {
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 msg = error.stack;
let lines = msg.split("\n"); let lines = msg.split("\n");
let header = document.getElementById("header"); let header = document.getElementById("header");
@ -499,6 +533,7 @@ function calculateBuild(save_skp, skp){
p2.textContent = "If you believe this is an error, contact hppeng on forums or discord."; p2.textContent = "If you believe this is an error, contact hppeng on forums or discord.";
header.appendChild(p2); header.appendChild(p2);
} }
}
} }
/* Updates all build statistics based on (for now) the skillpoint input fields and then calculates build stats. /* Updates all build statistics based on (for now) the skillpoint input fields and then calculates build stats.
@ -550,28 +585,33 @@ function updateStats() {
delta_total += delta; delta_total += delta;
} }
player_build.assigned_skillpoints += delta_total; player_build.assigned_skillpoints += delta_total;
calculateBuildStats();
if(player_build){ if(player_build){
updatePowderSpecials("skip"); updatePowderSpecials("skip", false);
updateBoosts("skip"); 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 /* Updates all spell boosts
*/ */
function updateBoosts(buttonId) { function updateBoosts(buttonId, recalcStats) {
let elem = document.getElementById(buttonId); let elem = document.getElementById(buttonId);
let name = buttonId.split("-")[0]; let name = buttonId.split("-")[0];
if(buttonId !== "skip") { if(buttonId !== "skip") {
if (elem.classList.contains("toggleOn")) { if (elem.classList.contains("toggleOn")) {
player_build.damageMultiplier -= damageMultipliers.get(name); player_build.damageMultiplier -= damageMultipliers.get(name);
if (name === "warscream") { if (name === "warscream") {
player_build.defenseMultiplier -= .10; player_build.defenseMultiplier -= .20;
} }
elem.classList.remove("toggleOn"); elem.classList.remove("toggleOn");
}else{ }else{
player_build.damageMultiplier += damageMultipliers.get(name); player_build.damageMultiplier += damageMultipliers.get(name);
if (name === "warscream") { if (name === "warscream") {
player_build.defenseMultiplier += .10; player_build.defenseMultiplier += .20;
} }
elem.classList.add("toggleOn"); elem.classList.add("toggleOn");
} }
@ -582,16 +622,18 @@ function updateBoosts(buttonId) {
if (elem.classList.contains("toggleOn")) { if (elem.classList.contains("toggleOn")) {
elem.classList.remove("toggleOn"); elem.classList.remove("toggleOn");
player_build.damageMultiplier -= value; player_build.damageMultiplier -= value;
if (key === "warscream") { player_build.defenseMultiplier -= .10 } if (key === "warscream") { player_build.defenseMultiplier -= .20 }
} }
} }
} }
if (recalcStats) {
calculateBuildStats(); calculateBuildStats();
}
} }
/* Updates all powder special boosts /* Updates all powder special boosts
*/ */
function updatePowderSpecials(buttonId){ function updatePowderSpecials(buttonId, recalcStats) {
//console.log(player_build.statMap); //console.log(player_build.statMap);
let name = (buttonId).split("-")[0]; let name = (buttonId).split("-")[0];
@ -671,8 +713,10 @@ function updatePowderSpecials(buttonId){
} }
} }
if (recalcStats) {
calculateBuildStats();
}
displayPowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build); displayPowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build);
calculateBuildStats(); //also make damage boosts apply ;-;
} }
/* Calculates all build statistics and updates the entire display. /* Calculates all build statistics and updates the entire display.
*/ */
@ -836,5 +880,18 @@ function resetFields(){
calculateBuild(); 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); load_init(init);

View file

@ -270652,7 +270652,7 @@
"restrict": "1.20 item", "restrict": "1.20 item",
"fixID": false, "fixID": false,
"strReq": 0, "strReq": 0,
"dexReq": 105, "dexReq": 120,
"intReq": 0, "intReq": 0,
"defReq": 0, "defReq": 0,
"agiReq": 0, "agiReq": 0,

181
craft.js Normal file
View file

@ -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;
}
}

183
crafter.html Normal file
View file

@ -0,0 +1,183 @@
<!DOCTYPE html>
<html scroll-behavior="smooth">
<head>
<!-- nunito font, copying wynndata -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" media="screen and (min-width: 1100px)" href="wide.css"/>
<link rel="stylesheet" media="screen and (max-width: 1099px)" href="narrow.css"/>
<link rel="icon" href="favicon.png">
<link rel="manifest" href="manifest.json">
<title>WynnCrafter</title>
</head>
<body class="all">
<div class="header" id="header">
WynnBuilder Crafter
</div>
<div class = "container" display = "grid">
<div class = "crafter center" style = "grid-column:1;grid-row:1" >
<table class = "center">
<tr>
<td>
<label for="recipe-choice">Recipe Type:</label>
<br/>
<input class="recipeinput" list="recipe-choices" id="recipe-choice" name="recipe-choice" placeholder="Potion"/>
<datalist id="recipe-choices">
</datalist>
</td>
<td >
<label for="level-choice">Recipe Level:</label>
<br/>
<input class="levelinput" list="level-choices" id="level-choice" name="level-choice" placeholder="103-105" />
<datalist id="level-choices">
</datalist>
</td>
</tr>
<tr>
<td class="center">
<label id = "mat-1" for="mat-1-tier-choice">Material 1 Tier:</label>
<br/>
<button class = "button Star" id = "mat-1-1" onclick = "toggleMaterial('mat-1-1')">1</button>
<button class = "button Star" id = "mat-1-2" onclick = "toggleMaterial('mat-1-2')">2</button>
<button class = "button Star" id = "mat-1-3" onclick = "toggleMaterial('mat-1-3')">3</button>
</td>
<td class="center">
<label id = "mat-2" for="mat-2-tier-choice">Material 2 Tier:</label>
<br/>
<button class = "button Star" id = "mat-2-1" onclick = "toggleMaterial('mat-2-1')">1</button>
<button class = "button Star" id = "mat-2-2" onclick = "toggleMaterial('mat-2-2')">2</button>
<button class = "button Star" id = "mat-2-3" onclick = "toggleMaterial('mat-2-3')">3</button>
</td>
</tr>
<tr>
<td class="center">
<label for="ing-choice-1">Ingredient 1:</label>
<br/>
<input class="inginput" list="ing-choices-1" id="ing-choice-1" name="ing-choice-1" placeholder="No Ingredient" />
<datalist id="ing-choices-1">
</datalist>
</td>
<td class="center">
<label for="ing-choice-2">Ingredient 2:</label>
<br/>
<input class="inginput" list="ing-choices-2" id="ing-choice-2" name="ing-choice-2" placeholder="No Ingredient" />
<datalist id="ing-choices-2">
</datalist>
</td>
</tr>
<tr>
<td class="center">
<label for="ing-choice-3">Ingredient 3:</label>
<br/>
<input class="inginput" list="ing-choices-3" id="ing-choice-3" name="ing-choice-3" placeholder="No Ingredient" />
<datalist id="ing-choices-3">
</datalist>
</td>
<td class="center">
<label for="ing-choice-4">Ingredient 4:</label>
<br/>
<input class="inginput" list="ing-choices-4" id="ing-choice-4" name="ing-choice-4" placeholder="No Ingredient" />
<datalist id="ing-choices-4">
</datalist>
</td>
</tr>
<tr>
<td class="center">
<label for="ing-choice-5">Ingredient 5:</label>
<br/>
<input class="inginput" list="ing-choices-5" id="ing-choice-5" name="ing-choice-5" placeholder="No Ingredient" />
<datalist id="ing-choices-5">
</datalist>
</td>
<td class="center">
<label for="ing-choice-6">Ingredient 6:</label>
<br/>
<input class="inginput" list="ing-choices-6" id="ing-choice-6" name="ing-choice-6" placeholder="No Ingredient" />
<datalist id="ing-choices-6">
</datalist>
</td>
</tr>
</table>
<table class = "center">
<tr>
<td class = "center">
<button class = "button" id = "craft-button" onclick = "calculateCraft()">
Craft Item
</button>
</td>
<td class = "center">
<button class = "button" id = "reset-button" onclick = "resetFields()">
Reset
</button>
</td>
<td class = "center">
<button class = "button" id = "copy-button" onclick = "copyRecipe()">
Copy Short
</button>
</td>
<td class = "center">
<button class = "button" id = "share-button" onclick = "shareRecipe()">
Copy Long
</button>
</td>
</tr>
</table>
</div>
<div class = "recipe hide-container-block" style = "display:none">
<!--This is incredibly janky-->
</div>
<div class = "crafted hide-container-block" style = "display:none">
<div class = "craft-stats">
<div class = "center" id = "craft-stats"></div>
</div>
</div>
<p class = "center title hide-container-block" style = "display:none">
Ingredients
</p>
<!--This is also incredibly janky.-->
<p>
</p>
<p>
</p>
<div class="ingredients hide-container-grid" id = "ingreds" style = "display:none">
<div class="ing-stats" id = "ing-1" style = "grid-item-1">
<div class = "center" id = "ing-1-stats"></div>
</div>
<div class="ing-stats" id = "ing-2" style = "grid-item-2">
<div class = "center" id = "ing-2-stats"></div>
</div>
<div class="ing-stats" id = "ing-3" style = "grid-item-3">
<div class = "center" id = "ing-3-stats"></div>
</div>
<div class="ing-stats" id = "ing-4" style = "grid-item-4">
<div class = "center" id = "ing-4-stats"></div>
</div>
<div class="ing-stats" id = "ing-5" style = "grid-item-5">
<div class = "center" id = "ing-5-stats"></div>
</div>
<div class="ing-stats" id = "ing-6" style = "grid-item-6">
<div class = "center" id = "ing-6-stats"></div>
</div>
</div>
</div>
<div class="center" id="header2">
<p>Made by <b class = "hppeng">hppeng</b> and <b class = "ferricles">ferricles</b> with Atlas Inc (JavaScript required to function, nothing works without js)</p>
<p>Hard refresh the page (Ctrl+Shift+R on windows/chrome) if it isn't updating correctly.</p>
</div>
<div class="center" id="credits">
<a href="credits.txt" class="link">Additional credits</a>
</div>
<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript" src="build_utils.js"></script>
<script type="text/javascript" src="skillpoints.js"></script>
<script type="text/javascript" src="damage_calc.js"></script>
<script type="text/javascript" src="display.js"></script>
<script type="text/javascript" src="load_ing.js"></script>
<script type="text/javascript" src="craft.js"></script>
<script type="text/javascript" src="crafter.js"></script>
</body>
</html>

229
crafter.js Normal file
View file

@ -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);

View file

@ -6,5 +6,5 @@ The game, of course
Additional Contributors: Additional Contributors:
- QuantumNep (Layout code/layout ideas) - 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) - Atlas Inc discord (feedback, ideas, etc)

View file

@ -139,7 +139,7 @@ let consumableIDPrefixes = {
} }
let consumableIDSuffixes = { let consumableIDSuffixes = {
"charges": "", "charges": "",
"dura": " Sec." "dura": " sec."
} }
//Used for ingredient itemIDs //Used for ingredient itemIDs
let itemIDPrefixes = { let itemIDPrefixes = {
@ -163,7 +163,7 @@ let posModPrefixes = {
"left":"Effectiveness Left: ", "left":"Effectiveness Left: ",
"right":"EFfectiveness Right: ", "right":"EFfectiveness Right: ",
"above":"Effectiveness Above: ", "above":"Effectiveness Above: ",
"below":"Effectivness Below: ", "under":"Effectiveness Under: ",
"touching":"EFfectiveness Touching: ", "touching":"EFfectiveness Touching: ",
"notTouching":"Effectiveness Not Touching: " "notTouching":"Effectiveness Not Touching: "
} }
@ -171,7 +171,7 @@ let posModSuffixes = {
"left":"%", "left":"%",
"right":"%", "right":"%",
"above":"%", "above":"%",
"below":"%", "under":"%",
"touching":"%", "touching":"%",
"notTouching":"%" "notTouching":"%"
} }
@ -407,6 +407,7 @@ function displayExpandedItem(item, parent_id){
"#ldiv", "#ldiv",
"str", "dex", "int", "def", "agi", "str", "dex", "int", "def", "agi",
"#table", "#table",
"str", "dex", "int", "def", "agi", //jank lmao
"hpBonus", "hpBonus",
"hprRaw", "hprPct", "hprRaw", "hprPct",
"sdRaw", "sdPct", "sdRaw", "sdPct",
@ -469,7 +470,7 @@ function displayExpandedItem(item, parent_id){
} }
else { else {
let id = command; 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") { if (id === "slots") {
let p_elem = document.createElement("p"); let p_elem = document.createElement("p");
// PROPER POWDER DISPLAYING EZ CLAP // PROPER POWDER DISPLAYING EZ CLAP
@ -498,14 +499,23 @@ function displayExpandedItem(item, parent_id){
powderSuffix.textContent = "]"; powderSuffix.textContent = "]";
p_elem.appendChild(powderSuffix); p_elem.appendChild(powderSuffix);
active_elem.appendChild(p_elem); active_elem.appendChild(p_elem);
} else {
let p_elem;
if (!(skp_order.includes(id) && item.get("tier") === "Crafted")) {
p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
} }
else {
let p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
if (id === "displayName") { if (id === "displayName") {
p_elem.classList.add("title"); p_elem.classList.add("title");
if (item.get("tier") !== " ") { if (item.get("tier") !== " ") {
p_elem.classList.add(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"]; /*let validTypes = ["helmet", "chestplate", "leggings", "boots", "relik", "wand", "bow", "spear", "dagger", "ring", "bracelet", "necklace"];
if (item.has("type") && validTypes.includes(item.get("type"))) { if (item.has("type") && validTypes.includes(item.get("type"))) {
p = document.createElement("p"); p = document.createElement("p");
@ -519,28 +529,52 @@ function displayExpandedItem(item, parent_id){
p_elem.append(p); p_elem.append(p);
}*/ }*/
} else if (skp_order.includes(id)) { //id = str, dex, int, def, or agi } 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 = ""; p_elem.textContent = "";
p_elem.classList.add("itemtable"); p_elem.classList.add("itemp");
let row = document.createElement("tr"); row = document.createElement("p");
let title = document.createElement("td"); row.classList.add("left");
let title = document.createElement("b");
title.textContent = idPrefixes[id] + " "; title.textContent = idPrefixes[id] + " ";
let boost = document.createElement("td"); let boost = document.createElement("b");
if (item.get(id) < 0) { if (item.get(id) < 0) {
boost.classList.add("negative"); boost.classList.add("negative");
} else { //boost = 0 SHOULD not come up } else { //boost = 0 SHOULD not come up
boost.classList.add("positive"); boost.classList.add("positive");
} }
boost.classList.add("spaceLeft");
boost.textContent = item.get(id); boost.textContent = item.get(id);
row.appendChild(title); row.appendChild(title);
row.appendChild(boost); row.appendChild(boost);
p_elem.appendChild(row); 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);
}
} else if (id === "restrict") { } else if (id === "restrict") {
p_elem.classList.add("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"; let style = "positive";
if (item.get("minRolls").get(id) < 0) { if (item.get("minRolls").get(id) < 0) {
style = "negative"; style = "negative";
@ -579,10 +613,14 @@ function displayExpandedItem(item, parent_id){
row.appendChild(max_elem); row.appendChild(max_elem);
active_elem.appendChild(row); active_elem.appendChild(row);
} }
}//Just don't do anything if else }else{
// :/
}
} }
} }
//Show powder specials ;-; //Show powder specials ;-;
let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots", "ring", "bracelet", "necklace"];
if(nonConsumables.includes(item.get("type"))) {
let powder_special = document.createElement("p"); let powder_special = document.createElement("p");
powder_special.classList.add("left"); powder_special.classList.add("left");
let powders = item.get("powders"); let powders = item.get("powders");
@ -643,10 +681,27 @@ function displayExpandedItem(item, parent_id){
parent_div.append(powder_special); 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 //Show item tier
if (item.get("tier") && item.get("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('left');
item_desc_elem.classList.add(item.get("tier")); item_desc_elem.classList.add(item.get("tier"));
item_desc_elem.textContent = item.get("tier")+" "+item.get("type"); 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 displayCraftStats(craft, parent_id) {
let mock_item = craft.statMap;
} displayExpandedItem(mock_item,parent_id);
function displayExpandedRecipe(recipe, parent_id) {
} }
@ -693,7 +745,7 @@ function displayExpandedIngredient(ingred, parent_id) {
] ]
let posMods_order = [ let posMods_order = [
"above", "above",
"below", "under",
"left", "left",
"right", "right",
"touching", "touching",
@ -803,6 +855,8 @@ function displayExpandedIngredient(ingred, parent_id) {
p_elem.textContent = "Crafting Lvl Min: " + ingred.get("lvl"); p_elem.textContent = "Crafting Lvl Min: " + ingred.get("lvl");
}else if (command === "posMods") { }else if (command === "posMods") {
for (const [key,value] of ingred.get("posMods")) { for (const [key,value] of ingred.get("posMods")) {
let p = document.createElement("p");
p.classList.add("nomarginp");
if (value != 0) { if (value != 0) {
let title = document.createElement("b"); let title = document.createElement("b");
title.textContent = posModPrefixes[key]; title.textContent = posModPrefixes[key];
@ -813,8 +867,9 @@ function displayExpandedIngredient(ingred, parent_id) {
} else { } else {
val.classList.add("negative"); val.classList.add("negative");
} }
p_elem.appendChild(title); p.appendChild(title);
p_elem.appendChild(val); p.appendChild(val);
p_elem.appendChild(p);
} }
} }
} else if (command === "itemIDs") { //dura, reqs } else if (command === "itemIDs") { //dura, reqs

View file

@ -16,6 +16,9 @@
<div class="header" id="header"> <div class="header" id="header">
Wynn build calculator Wynn build calculator
</div> </div>
<div class="center" id="help">
<a href="https://forums.wynncraft.com/threads/wynnbuilder-release-thread-and-some-damage-calculation-updates.281438">Forum thread (instructions/help)</a>
</div>
<div class="summary"> <div class="summary">
<div class="equipment" style="grid-column:1/span 2;grid-row:1"> <div class="equipment" style="grid-column:1/span 2;grid-row:1">
<div style="grid-column:1/span 2;grid-row:1"> <div style="grid-column:1/span 2;grid-row:1">
@ -34,10 +37,12 @@
<input class="iteminput" list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/> <input class="iteminput" list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/>
<datalist id="helmet-items"> <datalist id="helmet-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
<td class="left"> <td class="left">
<label id="helmet-slots" for="helmet-powder">X slots</label> <label id="helmet-slots" for="helmet-powder">X slots</label>
<input class="iteminput" type="text" id="helmet-powder" name="helmet-powder" placeholder="Example: t6t6"/> <input class="iteminput" type="text" id="helmet-powder" name="helmet-powder" placeholder="Example: t6t6"/>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -46,10 +51,12 @@
<input class="iteminput" list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate" /> <input class="iteminput" list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate" />
<datalist id="chestplate-items"> <datalist id="chestplate-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
<td class="left"> <td class="left">
<label id="chestplate-slots" for="chestplate-powder">X slots</label> <label id="chestplate-slots" for="chestplate-powder">X slots</label>
<input class="iteminput" type="text" id="chestplate-powder" name="chestplate-powder" /> <input class="iteminput" type="text" id="chestplate-powder" name="chestplate-powder" />
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -58,10 +65,12 @@
<input class="iteminput" list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings" /> <input class="iteminput" list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings" />
<datalist id="leggings-items"> <datalist id="leggings-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
<td class="left"> <td class="left">
<label id="leggings-slots" for="leggings-powder">X slots</label> <label id="leggings-slots" for="leggings-powder">X slots</label>
<input class="iteminput" type="text" id="leggings-powder" name="leggings-powder" /> <input class="iteminput" type="text" id="leggings-powder" name="leggings-powder" />
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -70,10 +79,12 @@
<input class="iteminput" list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots" /> <input class="iteminput" list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots" />
<datalist id="boots-items"> <datalist id="boots-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
<td class="left"> <td class="left">
<label id="boots-slots" for="boots-powder">X slots</label> <label id="boots-slots" for="boots-powder">X slots</label>
<input class="iteminput" type="text" id="boots-powder" name="boots-powder" /> <input class="iteminput" type="text" id="boots-powder" name="boots-powder" />
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -83,11 +94,13 @@
<input class="iteminput" list="weapon-items" id="weapon-choice" name="weapon-choice" placeholder="No Weapon" value=""/> <input class="iteminput" list="weapon-items" id="weapon-choice" name="weapon-choice" placeholder="No Weapon" value=""/>
<datalist id="weapon-items"> <datalist id="weapon-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
<td class="left"> <td class="left">
<br> <br>
<label id="weapon-slots" for="weapon-powder">X slots</label> <label id="weapon-slots" for="weapon-powder">X slots</label>
<input class="iteminput" type="text" id="weapon-powder" name="weapon-powder" /> <input class="iteminput" type="text" id="weapon-powder" name="weapon-powder" />
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
</table> </table>
@ -105,6 +118,7 @@
<input class="iteminput" list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/> <input class="iteminput" list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/>
<datalist id="ring1-items"> <datalist id="ring1-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -113,6 +127,7 @@
<input class="iteminput" list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2" /> <input class="iteminput" list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2" />
<datalist id="ring2-items"> <datalist id="ring2-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -121,6 +136,7 @@
<input class="iteminput" list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet" /> <input class="iteminput" list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet" />
<datalist id="bracelet-items"> <datalist id="bracelet-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -129,6 +145,7 @@
<input class="iteminput" list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/> <input class="iteminput" list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/>
<datalist id="necklace-items"> <datalist id="necklace-items">
</datalist> </datalist>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif; white-space: nowrap;"></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -136,6 +153,7 @@
<br/> <br/>
<label for="level-choice">Level:</label> <label for="level-choice">Level:</label>
<input class="iteminput" id="level-choice" name="level-choice" placeholder="106" value=""/> <input class="iteminput" id="level-choice" name="level-choice" placeholder="106" value=""/>
<p class="error" style="color: red; top: 30px; font-size: 10px; padding: 0; margin: 0; height: 5px; font-family: 'Nunito', sans-serif;"></p>
</td> </td>
</tr> </tr>
</table> </table>
@ -424,7 +442,7 @@
<div class="center" style="grid-column:1;grid-row:1"> <div class="center" style="grid-column:1;grid-row:1">
<div> <div>
<label for="str-skp" class="skpLabel" id="str-skp-label">Strength:</label><br> <label for="str-skp" class="skpLabel" id="str-skp-label">Strength:</label><br>
<input class="skp-input" type="string" id="str-skp" name="str-skp" value="0" class="skpInput"/> <input type="string" id="str-skp" name="str-skp" value="0" class="skpInput"/>
</div> </div>
<div id="str-skp-assign"> <div id="str-skp-assign">
Manually Assigned: 0 Manually Assigned: 0
@ -438,7 +456,7 @@
<div class="center" style="grid-column:2;grid-row:1"> <div class="center" style="grid-column:2;grid-row:1">
<div> <div>
<label for="dex-skp" class="skpLabel" id="dex-skp-label">Dexterity:</label><br> <label for="dex-skp" class="skpLabel" id="dex-skp-label">Dexterity:</label><br>
<input class="skp-input" type="string" id="dex-skp" name="dex-skp" value="0" class="skpInput"/> <input type="string" id="dex-skp" name="dex-skp" value="0" class="skpInput"/>
</div> </div>
<div id="dex-skp-assign"> <div id="dex-skp-assign">
Manually Assigned: 0 Manually Assigned: 0
@ -452,7 +470,7 @@
<div class="center" style="grid-column:3;grid-row:1"> <div class="center" style="grid-column:3;grid-row:1">
<div> <div>
<label for="int-skp" class="skpLabel" id="int-skp-label">Intelligence:</label><br> <label for="int-skp" class="skpLabel" id="int-skp-label">Intelligence:</label><br>
<input class="skp-input" type="string" id="int-skp" name="int-skp" value="0" class="skpInput"/> <input type="string" id="int-skp" name="int-skp" value="0" class="skpInput"/>
</div> </div>
<div id="int-skp-assign"> <div id="int-skp-assign">
Manually Assigned: 0 Manually Assigned: 0
@ -466,7 +484,7 @@
<div class="center" style="grid-column:4;grid-row:1"> <div class="center" style="grid-column:4;grid-row:1">
<div> <div>
<label for="def-skp" class="skpLabel" id="def-skp-label">Defense:</label><br> <label for="def-skp" class="skpLabel" id="def-skp-label">Defense:</label><br>
<input class="skp-input" type="string" id="def-skp" name="def-skp" value="0" class="skpInput"/> <input type="string" id="def-skp" name="def-skp" value="0" class="skpInput"/>
</div> </div>
<div id="def-skp-assign"> <div id="def-skp-assign">
Manually Assigned: 0 Manually Assigned: 0
@ -480,7 +498,7 @@
<div class="center" style="grid-column:5;grid-row:1"> <div class="center" style="grid-column:5;grid-row:1">
<div> <div>
<label for="agi-skp" class="skpLabel" id="agi-skp-label">Agility:</label><br> <label for="agi-skp" class="skpLabel" id="agi-skp-label">Agility:</label><br>
<input class="skp-input" type="string" id="agi-skp" name="agi-skp" value="0" class="skpInput"/> <input type="string" id="agi-skp" name="agi-skp" value="0" class="skpInput"/>
</div> </div>
<div id="agi-skp-assign"> <div id="agi-skp-assign">
Manually Assigned: 0 Manually Assigned: 0
@ -492,10 +510,317 @@
</div> </div>
</div> </div>
</div> </div>
<div class="id-box fade-in" id="id-edit" style="display: none">
<div class="id-edit1">
<div class="idCenter">
<div class="idWrap">
<div>
<label for="sdPct" class="idLabel" id="sdPct-label">Spell Damage %:</label><br>
<input type="number" id="sdPct" name="sdPct" value="0" class="idInput"/>
</div>
<div id="sdPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="sdRaw" class="idLabel" id="sdRaw-label">Spell Damage Raw:</label><br>
<input type="number" id="sdRaw" name="sdRaw" value="0" class="idInput"/>
</div>
<div id="sdRaw-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="mdPct" class="idLabel" id="mdPct-label">Melee Damage %:</label><br>
<input type="number" id="mdPct" name="mdPct" value="0" class="idInput"/>
</div>
<div id="mdPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="mdRaw" class="idLabel" id="mdRaw-label">Melee Damage Raw:</label><br>
<input type="number" id="mdRaw" name="mdRaw" value="0" class="idInput"/>
</div>
<div id="mdRaw-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="poison" class="idLabel" id="poison-label">Poison:</label><br>
<input type="number" id="poison" name="poison" value="0" class="idInput"/>
</div>
<div id="poison-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="eDamPct" class="idLabel" id="eDamPct-label">Earth Damage %:</label><br>
<input type="number" id="eDamPct" name="eDamPct" value="0" class="idInput"/>
</div>
<div id="eDamPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="tDamPct" class="idLabel" id="tDamPct-label">Thunder Damage %:</label><br>
<input type="number" id="tDamPct" name="tDamPct" value="0" class="idInput"/>
</div>
<div id="tDamPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="wDamPct" class="idLabel" id="wDamPct-label">Water Damage %:</label><br>
<input type="number" id="wDamPct" name="wDamPct" value="0" class="idInput"/>
</div>
<div id="wDamPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="fDamPct" class="idLabel" id="fDamPct-label">Fire Damage %:</label><br>
<input type="number" id="fDamPct" name="fDamPct" value="0" class="idInput"/>
</div>
<div id="fDamPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="aDamPct" class="idLabel" id="aDamPct-label">Air Damage %:</label><br>
<input type="number" id="aDamPct" name="aDamPct" value="0" class="idInput"/>
</div>
<div id="aDamPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="eDefPct" class="idLabel" id="eDefPct-label">Earth Defense %:</label><br>
<input type="number" id="eDefPct" name="eDefPct" value="0" class="idInput"/>
</div>
<div id="eDefPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="tDefPct" class="idLabel" id="tDefPct-label">Thunder Defense %:</label><br>
<input type="number" id="tDefPct" name="tDefPct" value="0" class="idInput"/>
</div>
<div id="tDefPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="wDefPct" class="idLabel" id="wDefPct-label">Water Defense %:</label><br>
<input type="number" id="wDefPct" name="wDefPct" value="0" class="idInput"/>
</div>
<div id="wDefPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="fDefPct" class="idLabel" id="fDefPct-label">Fire Defense %:</label><br>
<input type="number" id="fDefPct" name="fDefPct" value="0" class="idInput"/>
</div>
<div id="fDefPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="aDefPct" class="idLabel" id="aDefPct-label">Air Defense %:</label><br>
<input type="number" id="aDefPct" name="aDefPct" value="0" class="idInput"/>
</div>
<div id="aDefPct-base">
Original Value: 0
</div>
</div>
</div>
</div>
<div class="id-edit2">
<div class="idCenter">
<div class="idWrap">
<div>
<label for="hprRaw" class="idLabel" id="hprRaw-label">Health Regen Raw:</label><br>
<input type="number" id="hprRaw" name="hprRaw" value="0" class="idInput"/>
</div>
<div id="hprRaw-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="hprPct" class="idLabel" id="hprPct-label">Health Regen %:</label><br>
<input type="number" id="hprPct" name="hprPct" value="0" class="idInput"/>
</div>
<div id="hprPct-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="hpBonus" class="idLabel" id="hpBonus-label">Health Bonus:</label><br>
<input type="number" id="hpBonus" name="hpBonus" value="0" class="idInput"/>
</div>
<div id="hpBonus-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="atkTier" class="idLabel" id="atkTier-label">Attack Speed Bonus:</label><br>
<input type="number" id="atkTier" name="atkTier" value="0" class="idInput"/>
</div>
<div id="atkTier-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spPct1" class="idLabel" id="spPct1-label">1st Spell Cost %:</label><br>
<input type="number" id="spPct1" name="spPct1" value="0" class="idInput"/>
</div>
<div id="spPct1-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spPct2" class="idLabel" id="spPct2-label">2nd Spell Cost %:</label><br>
<input type="number" id="spPct2" name="spPct2" value="0" class="idInput"/>
</div>
<div id="spPct2-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spPct3" class="idLabel" id="spPct3-label">3rd Spell Cost %:</label><br>
<input type="number" id="spPct3" name="spPct3" value="0" class="idInput"/>
</div>
<div id="spPct3-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spPct4" class="idLabel" id="spPct4-label">4th Spell Cost %:</label><br>
<input type="number" id="spPct4" name="spPct4" value="0" class="idInput"/>
</div>
<div id="spPct4-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spRaw1" class="idLabel" id="spRaw1-label">1st Spell Cost Raw:</label><br>
<input type="number" id="spRaw1" name="spRaw1" value="0" class="idInput"/>
</div>
<div id="spRaw1-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spRaw2" class="idLabel" id="spRaw2-label">2nd Spell Cost Raw:</label><br>
<input type="number" id="spRaw2" name="spRaw2" value="0" class="idInput"/>
</div>
<div id="spRaw2-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spRaw3" class="idLabel" id="spRaw3-label">3rd Spell Cost Raw:</label><br>
<input type="number" id="spRaw3" name="spRaw3" value="0" class="idInput"/>
</div>
<div id="spRaw3-base">
Original Value: 0
</div>
</div>
</div>
<div class="idCenter">
<div class="idWrap">
<div>
<label for="spRaw4" class="idLabel" id="spRaw4-label">4th Spell Cost Raw:</label><br>
<input type="number" id="spRaw4" name="spRaw4" value="0" class="idInput"/>
</div>
<div id="spRaw4-base">
Original Value: 0
</div>
</div>
</div>
</div>
</div>
<br>
<div class="center"> <div class="center">
<button class = "button" id = "update-button" onclick = "updateStats()"> <button class = "button" id = "update-button" onclick = "updateStats()">
Update Stats Update Stats
</button> </button>
<button class = "button" id = "show-id-button" onclick = "toggleID()">
Edit IDs
</button>
</div> </div>
<div class = "build hide-container-grid" style="display: none;"> <div class = "build hide-container-grid" style="display: none;">
<div class = "center build-helmet" id = "build-helmet" style = "grid-item-1"> <div class = "center build-helmet" id = "build-helmet" style = "grid-item-1">
@ -554,24 +879,23 @@
<div class = "center set-info" id = "set-info-div" style = "grid-column:1;grid-row:1; display: none;"> <div class = "center set-info" id = "set-info-div" style = "grid-column:1;grid-row:1; display: none;">
<div class = "center" id = "set-info">Set info</div> <div class = "center" id = "set-info">Set info</div>
</div> </div>
<div class = "center int-info" id = "int-info-div" style = "grid-column:4;grid-row:1;visibility:visible;"> <div class = "center int-info" id = "int-info-div" style = "grid-column:4;grid-row:1; display: none;">
<div class = "center" id = "int-info">Next Spell Costs</div> <div class = "center" id = "int-info">Next Spell Costs</div>
</div> </div>
</div> </div>
<div class="center" id="header2"> <div class="center" id="header2">
<p>Made by <b class = "hppeng">hppeng</b> and <b class = "ferricles">ferricles</b> with Atlas Inc (JavaScript required to function, nothing works without js)</p> <p>Made by <b class = "hppeng">hppeng</b> and <b class = "ferricles">ferricles</b> with Atlas Inc (JavaScript required to function, nothing works without js)</p>
<p>Hard refresh the page (Ctrl+Shift+R on windows/chrome) if it isn't updating correctly.</p>
</div> </div>
<div class="center" id="credits"> <div class="center" id="credits">
<a href="credits.txt" class="link">Additional credits</a> <a href="credits.txt" class="link">Additional credits</a>
</div> </div>
<script type="text/javascript" src="utils.js"></script> <script type="text/javascript" src="utils.js"></script>
<script type="text/javascript" src="build_utils.js"></script>
<script type="text/javascript" src="skillpoints.js"></script> <script type="text/javascript" src="skillpoints.js"></script>
<script type="text/javascript" src="damage_calc.js"></script> <script type="text/javascript" src="damage_calc.js"></script>
<script type="text/javascript" src="display.js"></script> <script type="text/javascript" src="display.js"></script>
<script type="text/javascript" src="build.js"></script> <script type="text/javascript" src="build.js"></script>
<script type="text/javascript" src="craft.js"></script>
<script type="text/javascript" src="load.js"></script> <script type="text/javascript" src="load.js"></script>
<script type="text/javascript" src="builder.js"></script> <script type="text/javascript" src="builder.js"></script>
</body> </body>

359
ing_transform_combine.py Normal file
View file

@ -0,0 +1,359 @@
"""
NOTE!!!!!!!
DEMON TIDE 1.20 IS HARD CODED!
AMBIVALENCE IS REMOVED!
"""
import json
with open("dump.json", "r") as infile:
data = json.loads(infile.read())
items = data["items"]
del data["request"]
with open("recipes_compress.json", "r") as infile:
recipe_data = json.loads(infile.read())
recipes = recipe_data["recipes"]
#this data does not have request :)
with open("ingreds_compress.json", "r") as infile:
ing_data = json.loads(infile.read())
ings = ing_data["ingredients"]
#this data does not have request :)
import os
sets = dict()
item_set_map = dict()
for filename in os.listdir('sets'):
if "json" not in filename:
continue
set_name = filename[1:].split(".")[0].replace("+", " ").replace("%27", "'")
with open("sets/"+filename) as set_info:
set_obj = json.load(set_info)
for item in set_obj["items"]:
item_set_map[item] = set_name
sets[set_name] = set_obj
data["sets"] = sets
translate_mappings = { #this is used for items.
#"name": "name",
#"displayName": "displayName",
#"tier": "tier",
#"set": "set",
"sockets": "slots",
#"type": "type",
#"armorType": "armorType", (deleted)
#"armorColor": "color", (deleted)
#"addedLore": "lore", (deleted)
#"material": "material", (deleted)
"dropType": "drop",
#"quest": "quest",
"restrictions": "restrict",
"damage": "nDam",
"fireDamage": "fDam",
"waterDamage": "wDam",
"airDamage": "aDam",
"thunderDamage": "tDam",
"earthDamage": "eDam",
"attackSpeed": "atkSpd",
"health": "hp",
"fireDefense": "fDef",
"waterDefense": "wDef",
"airDefense": "aDef",
"thunderDefense": "tDef",
"earthDefense": "eDef",
"level": "lvl",
"classRequirement": "classReq",
"strength": "strReq",
"dexterity": "dexReq",
"intelligence": "intReq",
"agility": "agiReq",
"defense": "defReq",
"healthRegen": "hprPct",
"manaRegen": "mr",
"spellDamage": "sdPct",
"damageBonus": "mdPct",
"lifeSteal": "ls",
"manaSteal": "ms",
"xpBonus": "xpb",
"lootBonus": "lb",
"reflection": "ref",
"strengthPoints": "str",
"dexterityPoints": "dex",
"intelligencePoints": "int",
"agilityPoints": "agi",
"defensePoints": "def",
#"thorns": "thorns",
"exploding": "expd",
"speed": "spd",
"attackSpeedBonus": "atkTier",
#"poison": "poison",
"healthBonus": "hpBonus",
"soulPoints": "spRegen",
"emeraldStealing": "eSteal",
"healthRegenRaw": "hprRaw",
"spellDamageRaw": "sdRaw",
"damageBonusRaw": "mdRaw",
"bonusFireDamage": "fDamPct",
"bonusWaterDamage": "wDamPct",
"bonusAirDamage": "aDamPct",
"bonusThunderDamage": "tDamPct",
"bonusEarthDamage": "eDamPct",
"bonusFireDefense": "fDefPct",
"bonusWaterDefense": "wDefPct",
"bonusAirDefense": "aDefPct",
"bonusThunderDefense": "tDefPct",
"bonusEarthDefense": "eDefPct",
"accessoryType": "type",
"identified": "fixID",
#"skin": "skin",
#"category": "category",
"spellCostPct1": "spPct1",
"spellCostRaw1": "spRaw1",
"spellCostPct2": "spPct2",
"spellCostRaw2": "spRaw2",
"spellCostPct3": "spPct3",
"spellCostRaw3": "spRaw3",
"spellCostPct4": "spPct4",
"spellCostRaw4": "spRaw4",
"rainbowSpellDamageRaw": "rainbowRaw",
#"sprint": "sprint",
"sprintRegen": "sprintReg",
"jumpHeight": "jh",
"lootQuality": "lq",
"gatherXpBonus": "gXp",
"gatherSpeed": "gSpd",
}
delete_keys = [
"addedLore",
#"skin",
"armorType",
"armorColor",
"material"
]
ing_translate_mappings = {
#"name" : "name",
#"tier" :"tier",
"level" : "lvl",
#"skills" : "skills",
"identifications" : "ids",
"itemOnlyIDs" : "itemIDs",
"consumableOnlyIDs" : "consumableIDs",
"ingredientPositionModifiers" : "posMods",
}
ing_metaID_mappings = {
#item only IDs
"durabilityModifier": "dura",
"strengthRequirement": "strReq",
"dexterityRequirement": "dexReq",
"intelligenceRequirement": "intReq",
"defenceRequirement": "defReq",
"agilityRequirement": "agiReq",
"attackSpeedModifier": "atkTier",
"powderSlotModifier": "slotMod",
#consumable only IDs
"duration": "dura",
#"charges": "charges",
#position modifiers
#"left": "left",
#"right": "right",
#"above": "above",
#"under": "under",
#"touching": "touching",
#"notTouching": "notTouching",
}
ing_id_mappings = { #specifically for the id field of an ingredient.
#"name": "name",
#"displayName": "displayName",
#"tier": "tier",
#"set": "set",
#"sockets": "slots",
#"type": "type",
#"armorType": "armorType", (deleted)
#"armorColor": "color", (deleted)
#"addedLore": "lore", (deleted)
#"material": "material", (deleted)
#"dropType": "drop",
#"quest": "quest",
#"restrictions": "restrict",
#"damage": "nDam",
#"fireDamage": "fDam",
#"waterDamage": "wDam",
#"airDamage": "aDam",
#"thunderDamage": "tDam",
#"earthDamage": "eDam",
#"ATTACKSPEED": "atkSpd",
#"health": "hp",
"FIREDEFENSE": "fDefPct",
"WATERDEFENSE": "wDefPct",
"AIRDEFENSE": "aDefPct",
"THUNDERDEFENSE": "tDefPct",
"EARTHDEFENSE": "eDefPct",
#"level": "lvl",
#"classRequirement": "classReq",
#"strength": "strReq",
#"dexterity": "dexReq",
#"intelligence": "intReq",
#"agility": "agiReq",
#"defense": "defReq",
"HEALTHREGEN": "hprPct",
"MANAREGEN": "mr",
"SPELLDAMAGE": "sdPct",
"DAMAGEBONUS": "mdPct",
"LIFESTEAL": "ls",
"MANASTEAL": "ms",
"XPBONUS": "xpb",
"LOOTBONUS": "lb",
"LOOT_QUALITY": "lq",
"REFLECTION": "ref",
"STRENGTHPOINTS": "str",
"DEXTERITYPOINTS": "dex",
"INTELLIGENCEPOINTS": "int",
"AGILITYPOINTS": "agi",
"DEFENSEPOINTS": "def",
"THORNS": "thorns",
"EXPLODING": "expd",
"SPEED": "spd",
"ATTACKSPEED": "atkTier",
"POISON": "poison",
"HEALTHBONUS": "hpBonus",
"SOULPOINTS": "spRegen",
"EMERALDSTEALING": "eSteal",
"HEALTHREGENRAW": "hprRaw",
"SPELLDAMAGERAW": "sdRaw",
"DAMAGEBONUSRAW": "mdRaw",
"FIREDAMAGEBONUS": "fDamPct",
"WATERDAMAGEBONUS": "wDamPct",
"AIRDAMAGEBONUS": "aDamPct",
"THUNDERDAMAGEBONUS": "tDamPct",
"EARTHDAMAGEBONUS": "eDamPct",
#"accessoryType": "type",
#"identified": "fixID",
#"skin": "skin",
#"category": "category",
#THESE ARE NOT IN ANY INGREDIENT YET. THEY MAY NOT HAVE THE CORRECT ID NAME
"SPELLCOSTPCT1": "spPct1",
"SPELLCOSTRAW1": "spRaw1",
"SPELLCOSTPCT2": "spPct2",
"SPELLCOSTRAW2": "spRaw2",
"SPELLCOSTPCT3": "spPct3",
"SPELLCOSTRAW3": "spRaw3",
"SPELLCOSTPCT4": "spPct4",
"SPELLCOSTRAW4": "spRaw4",
"JUMPHEIGHT": "jh",
#"rainbowSpellDamageRaw": "rainbowRaw",
"SPRINT": "sprint",
"SPRINGREGEN": "sprintReg",
"GATHERXPBONUS": "gXp",
"GATHERSPEED": "gSpd",
#"lootQuality": "lq",
}
ing_delete_keys = [
"sprite",
]
recipe_translate_mappings = {
"level" : "lvl",
}
recipe_delete_keys = [ #lol
]
import os
if os.path.exists("id_map.json"):
with open("id_map.json","r") as id_mapfile:
id_map = json.load(id_mapfile)
else:
id_map = {item["name"]: i for i, item in enumerate(items)}
# wtf is this hpp
texture_names = []
import base64
for item in items:
for key in delete_keys:
if key in item:
del item[key]
for k, v in translate_mappings.items():
if k in item:
item[v] = item[k]
del item[k]
if not (item["name"] in id_map):
id_map[item["name"]] = len(id_map)
print(f'New item: {item["name"]}')
item["id"] = id_map[item["name"]]
item["type"] = item["type"].lower()
if item["name"] in item_set_map:
item["set"] = item_set_map[item["name"]]
print(ings[0])
for ing in ings:
for key in ing_delete_keys:
if key in ing:
del ing[key]
for k, v in ing_translate_mappings.items():
if k in ing:
ing[v] = ing[k]
del ing[k]
for k, v in ing_metaID_mappings.items():
if k in ing['itemIDs']:
print(ing['itemIDs'])
ing['itemIDs'][v] = ing['itemIDs'][k]
del ing['itemIDs'][k]
elif k in ing['consumableIDs']:
ing['consumableIDs'][v] = ing['consumableIDs'][k]
del ing['consumableIDs'][k]
'''elif k in ing.posMods: #Not subbing, if we do sub uncomment this.
ing.posMods[v] = ing.posMods[k]
del ing.posMods[k] '''
for k, v in ing_id_mappings.items():
if k in ing['ids']: #yes this is dumb
ing['ids'][v] = ing['ids'][k]
del ing['ids'][k]
for recipe in recipes:
for key in recipe_delete_keys:
if key in recipe:
del recipe[key]
for k, v in recipe_translate_mappings.items():
if k in recipe:
recipe[v] = recipe[k]
del recipe[k]
with open("1_20_ci.json", "r") as ci_file:
ci_items = json.load(ci_file)
items.extend(ci_items)
'''with open("id_map.json","w") as id_mapfile:
json.dump(id_map, id_mapfile, indent=2)
with open("clean.json", "w") as outfile:
json.dump(data, outfile, indent=2)
with open("compress.json", "w") as outfile:
json.dump(data, outfile)'''
with open("ingreds_clean.json", "w") as outfile:
json.dump(ing_data, outfile, indent = 2)
with open("ingreds_compress2.json", "w") as outfile:
json.dump(ing_data, outfile)
with open("recipes_clean.json", "w") as outfile:
json.dump(recipe_data, outfile, indent = 2)
with open("recipes_compress2.json", "w") as outfile:
json.dump(recipe_data, outfile)

1
ingreds.json Normal file

File diff suppressed because one or more lines are too long

20
ingreds.py Normal file
View file

@ -0,0 +1,20 @@
import json
import requests
#Nothing to ingreds.json
'''arr = []
for i in range(4):
response = requests.get("https://api.wynncraft.com/v2/ingredient/search/tier/" + str(i))
arr.append(response.json())
with open("ingreds.json", "w") as outfile:
outfile.write(json.dumps(arr))'''
with open("ingreds_compress.json", "w") as infile:
data = json.loads(infile.read())
with open("ingreds_clean.json", "w") as outfile:
json.dump(data, outfile,indent = 2) #needs further cleaning

21888
ingreds_clean.json Normal file

File diff suppressed because it is too large Load diff

1
ingreds_compress.json Normal file

File diff suppressed because one or more lines are too long

1
ingreds_compress2.json Normal file

File diff suppressed because one or more lines are too long

82
load.js
View file

@ -1,24 +1,18 @@
const DB_VERSION = 20; const DB_VERSION = 21;
const BUILD_VERSION = "6.9.2";
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js // @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
let db; let db;
let reload = false; let reload = false;
let items; let items;
let sets; let sets;
let ings;
let recipes;
/* /*
* Load item set from local DB. Calls init() on success. * Load item set from local DB. Calls init() on success.
*/ */
async function load_local(init_func) { async function load_local(init_func) {
let get_tx = db.transaction(['item_db', 'set_db', 'ing_db', 'recipe_db'], 'readonly'); let get_tx = db.transaction(['item_db', 'set_db'], 'readonly');
let sets_store = get_tx.objectStore('set_db'); let sets_store = get_tx.objectStore('set_db');
let get_store = get_tx.objectStore('item_db'); let get_store = get_tx.objectStore('item_db');
let ings_store = get_tx.objectStore('ing_db');
let recipes_store = get_tx.objectStore('recipe_db');
let request = get_store.getAll(); let request = get_store.getAll();
request.onerror = function(event) { request.onerror = function(event) {
console.log("Could not read local item db..."); console.log("Could not read local item db...");
@ -44,25 +38,8 @@ async function load_local(init_func) {
console.log(sets); console.log(sets);
init_func(); init_func();
} }
} }
} }
let request3 = ings_store.getAll();
request3.onerror = function(event) {
console.log("Could not read local ingredient db...");
}
request3.onsuccess = function(event) {
console.log("Successfully read local ingredient db.");
ings = request3.result;
}
let request4 = recipes_store.getAll();
request4.onerror = function(event) {
console.log("Could not read local recipe db...");
}
request4.onsuccess = function(event) {
console.log("Successfully read local recipe db.");
recipes = request4.result;
}
await get_tx.complete; await get_tx.complete;
db.close(); db.close();
} }
@ -87,32 +64,9 @@ async function load(init_func) {
let getUrl = window.location; let getUrl = window.location;
let baseUrl = getUrl.protocol + "//" + getUrl.host + "/" + getUrl.pathname.split('/')[1]; let baseUrl = getUrl.protocol + "//" + getUrl.host + "/" + getUrl.pathname.split('/')[1];
let url = baseUrl + "/compress.json"; let url = baseUrl + "/compress.json";
url = url.replace("/crafter.html", ""); //JANK
let result = await (await fetch(url)).json(); let result = await (await fetch(url)).json();
items = result.items; items = result.items;
sets = result.sets; sets = result.sets;
url = url.replace("/compress.json", "/ingreds_compress.json");
result = await (await fetch(url)).json();
ings = result.ingredients;
url = url.replace("/ingreds_compress.json", "/recipes_compress.json");
result = await (await fetch(url)).json();
recipes = result.recipes;
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/clear
let clear_tx = db.transaction(['item_db', 'set_db'], 'readwrite');
let clear_items = clear_tx.objectStore('item_db');
let clear_sets = clear_tx.objectStore('item_db');
let clear_tx2 = db.transaction(['ing_db'], 'readwrite');
let clear_ings = clear_tx2.objectStore('ing_db');
let clear_tx3 = db.transaction(['recipe_db'], 'readwrite');
let clear_recipes = clear_tx3.objectStore('recipe_db');
await clear_items.clear();
await clear_sets.clear();
await clear_ings.clear();
await clear_recipes.clear();
await clear_tx.complete;
await clear_tx2.complete;
await clear_tx3.complete;
let add_tx = db.transaction(['item_db', 'set_db'], 'readwrite'); let add_tx = db.transaction(['item_db', 'set_db'], 'readwrite');
let items_store = add_tx.objectStore('item_db'); let items_store = add_tx.objectStore('item_db');
@ -125,20 +79,7 @@ async function load(init_func) {
for (const set in sets) { for (const set in sets) {
add_promises.push(sets_store.add(sets[set], set)); add_promises.push(sets_store.add(sets[set], set));
} }
let add_tx2 = db.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 recipes_store = add_tx3.objectStore('recipe_db');
for (const recipe in recipes) {
add_promises.push(recipes_store.add(recipes[recipe], recipe));
}
add_promises.push(add_tx.complete); add_promises.push(add_tx.complete);
add_promises.push(add_tx2.complete);
add_promises.push(add_tx3.complete);
Promise.all(add_promises).then((values) => { Promise.all(add_promises).then((values) => {
db.close(); db.close();
init_func(); init_func();
@ -146,11 +87,11 @@ async function load(init_func) {
} }
function load_init(init_func) { function load_init(init_func) {
let request = window.indexedDB.open('item_db', DB_VERSION);
let request = window.indexedDB.open("ing_db", DB_VERSION)
request.onerror = function() { request.onerror = function() {
console.log("DB failed to open..."); console.log("DB failed to open...");
} };
request.onsuccess = function() { request.onsuccess = function() {
db = request.result; db = request.result;
@ -181,22 +122,9 @@ function load_init(init_func) {
catch (error) { catch (error) {
console.log("Could not delete set DB. This is probably fine"); console.log("Could not delete set DB. This is probably fine");
} }
try {
db.deleteObjectStore('ing_db');
}
catch (error) {
console.log("Could not delete ingredient DB. This is probably fine");
}
try {
db.deleteObjectStore('recipe_db');
}
catch (error) {
console.log("Could not delete recipe DB. This is probably fine");
}
db.createObjectStore('item_db'); db.createObjectStore('item_db');
db.createObjectStore('set_db'); db.createObjectStore('set_db');
db.createObjectStore('ing_db');
db.createObjectStore('recipe_db');
console.log("DB setup complete..."); console.log("DB setup complete...");
} }

125
load_ing.js Normal file
View file

@ -0,0 +1,125 @@
const ING_DB_VERSION = 1;
// @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 ings;
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 ings_store = get_tx.objectStore('ing_db');
let recipes_store = get_tx.objectStore('recipe_db');
let request3 = ings_store.getAll();
request3.onerror = function(event) {
console.log("Could not read local ingredient db...");
}
request3.onsuccess = function(event) {
console.log("Successfully read local ingredient db.");
ings = request3.result;
}
let request4 = recipes_store.getAll();
request4.onerror = function(event) {
console.log("Could not read local recipe db...");
}
request4.onsuccess = function(event) {
console.log("Successfully read local recipe db.");
recipes = request4.result;
init_func();
}
await get_tx.complete;
db.close();
}
/*
* Load item set from remote DB (aka a big json file). Calls init() on success.
*/
async function load_ings(init_func) {
let getUrl = window.location;
let baseUrl = getUrl.protocol + "//" + getUrl.host + "/" + getUrl.pathname.split('/')[1];
let url = baseUrl + "/ingreds_compress.json";
url = url.replace("/crafter.html", ""); //JANK
let result = await (await fetch(url)).json();
result = await (await fetch(url)).json();
ings = result.ingredients;
url = url.replace("/ingreds_compress.json", "/recipes_compress.json");
result = await (await fetch(url)).json();
recipes = result.recipes;
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/clear
/*let clear_tx2 = db.transaction(['ing_db'], 'readwrite');
let clear_ings = clear_tx2.objectStore('ing_db');
let clear_tx3 = db.transaction(['recipe_db'], 'readwrite');
let clear_recipes = clear_tx3.objectStore('recipe_db');
await clear_ings.clear();
await clear_recipes.clear();
await clear_tx2.complete;
await clear_tx3.complete;*/
let add_promises = [];
let add_tx2 = db.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 recipes_store = add_tx3.objectStore('recipe_db');
for (const recipe in recipes) {
add_promises.push(recipes_store.add(recipes[recipe], recipe));
}
add_promises.push(add_tx2.complete);
add_promises.push(add_tx3.complete);
Promise.all(add_promises).then((values) => {
db.close();
init_func();
});
}
function load_ing_init(init_func) {
let request = window.indexedDB.open("ing_db", ING_DB_VERSION)
request.onerror = function() {
console.log("DB failed to open...");
}
request.onsuccess = function() {
db = request.result;
if (!reload) {
console.log("Using stored data...")
ing_load_local(init_func);
}
else {
console.log("Using new data...")
load_ings(init_func);
}
}
request.onupgradeneeded = function(e) {
reload = true;
let db = e.target.result;
try {
db.deleteObjectStore('ing_db');
}
catch (error) {
console.log("Could not delete ingredient DB. This is probably fine");
}
try {
db.deleteObjectStore('recipe_db');
}
catch (error) {
console.log("Could not delete recipe DB. This is probably fine");
}
db.createObjectStore('ing_db');
db.createObjectStore('recipe_db');
console.log("DB setup complete...");
}
}

View file

@ -33,40 +33,9 @@
max-height: 50px; max-height: 50px;
} }
.skp-input { .skpInput, .idInput {
width: 15vw; width: 90%;
height: 7vw; height: 7vw;
max-height: 30px; max-height: 30px;
} }
.hide-container-block {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
.hide-container-grid {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
.set-info-div {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
@keyframes fadeInFromNone {
0% {
opacity: 0;
}
1% {
opacity: 0;
}
100% {
opacity: 1;
}
}

1
recipes.json Normal file

File diff suppressed because one or more lines are too long

33
recipes.py Normal file

File diff suppressed because one or more lines are too long

17518
recipes_clean.json Normal file

File diff suppressed because it is too large Load diff

1
recipes_compress.json Normal file

File diff suppressed because one or more lines are too long

1
recipes_compress2.json Normal file

File diff suppressed because one or more lines are too long

View file

@ -31,7 +31,7 @@ div {
grid-template-rows: min-content min-content auto; grid-template-rows: min-content min-content auto;
} }
.skillpoints { .skillpoints, .id-edit1 {
padding: 0% 4% 2%; padding: 0% 4% 2%;
display: grid; display: grid;
grid-template-columns: repeat(5, 1fr); grid-template-columns: repeat(5, 1fr);
@ -39,6 +39,14 @@ div {
grid-auto-rows: minmax(60px, auto); grid-auto-rows: minmax(60px, auto);
} }
.id-edit2 {
padding: 0% 4% 2%;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
grid-auto-rows: minmax(60px, auto);
}
.powder-specials{ .powder-specials{
padding: 0% 4% 2%; padding: 0% 4% 2%;
display: grid; display: grid;
@ -70,6 +78,7 @@ a.link{
} }
.center { .center {
text-align: center; text-align: center;
position: relative;
} }
table.center{ table.center{
margin: 10px; margin: 10px;
@ -86,7 +95,7 @@ table.center{
text-align: left; text-align: left;
} }
.build-helmet, .build-chestplate, .build-leggings, .build-boots, .build-ring1, .build-ring2, .build-bracelet, .build-necklace, .build-weapon, .build-order, .build-overall, .build-melee-stats, .build-defense-stats, .spell-info, .set-info, .powder-special, .powder-special-stats, .int-info { .build-helmet, .build-chestplate, .build-leggings, .build-boots, .build-ring1, .build-ring2, .build-bracelet, .build-necklace, .build-weapon, .build-order, .build-overall, .build-melee-stats, .build-defense-stats, .spell-info, .set-info, .powder-special, .powder-special-stats, .int-info, .id-box {
color: #aaa; color: #aaa;
background: #121516; background: #121516;
border: 3px solid #BCBCBC; border: 3px solid #BCBCBC;
@ -128,6 +137,9 @@ table.center{
.space { .space {
margin-right: 5px; margin-right: 5px;
} }
.spaceleft{
margin-left: 5px;
}
.damageSubtitle { .damageSubtitle {
text-align: center; text-align: center;
@ -187,11 +199,21 @@ table.center{
content: "\2764" ' '; content: "\2764" ' ';
} }
.skpInput, .skplabel { .skplabel {
display: block; display: block;
margin: auto; margin: auto;
} }
.idCenter {
text-align: center;
padding: 1em 0px 0px 0px;
position: relative;
display: flex;
}
.idWrap {
align-self: flex-end;
}
/*Scrollbar*/ /*Scrollbar*/
/* width */ /* width */
::-webkit-scrollbar { ::-webkit-scrollbar {
@ -282,6 +304,12 @@ input {
.Mythic{ .Mythic{
color:#a0a; color:#a0a;
} }
.Crafted {
color: #0aa;
}
.Custom {
color: #0aa;
}
.Set{ .Set{
color:#5f5; color:#5f5;
} }
@ -312,6 +340,7 @@ button.toggleOn{
width: 100%; width: 100%;
} }
<<<<<<< HEAD
.T0 { .T0 {
color: #555; color: #555;
} }
@ -336,3 +365,24 @@ button.toggleOn{
.T3-bracket { .T3-bracket {
color: #0aa; color: #0aa;
} }
=======
.hide-container-block, .hide-container-grid, .set-info-div, .fade-in {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
@keyframes fadeInFromNone {
0% {
opacity: 0;
}
1% {
opacity: 0;
}
100% {
opacity: 1;
}
}
>>>>>>> ca179c7c401539ebf0a5c647f2cf962de7dfe494

0
temp.json Normal file
View file

View file

@ -16,14 +16,6 @@ with open("dump.json", "r") as infile:
items = data["items"] items = data["items"]
del data["request"] del data["request"]
with open("recipes_compress.json", "r") as infile:
recipe_data = json.loads(infile.read())
recipes = recipe_data["recipes"]
#this data does not have request :)
with open("ingreds_compress.json", "r") as infile:
ing_data = json.loads(infile.read())
ings = ing_data["ingredients"]
#this data does not have request :)
import os import os
sets = dict() sets = dict()
item_set_map = dict() item_set_map = dict()
@ -39,7 +31,7 @@ for filename in os.listdir('sets'):
data["sets"] = sets data["sets"] = sets
translate_mappings = { #this is used for items. translate_mappings = {
#"name": "name", #"name": "name",
#"displayName": "displayName", #"displayName": "displayName",
#"tier": "tier", #"tier": "tier",
@ -140,142 +132,13 @@ delete_keys = [
"material" "material"
] ]
ing_translate_mappings = {
#"name" : "name",
#"tier" :"tier",
"level" : "lvl",
#"skills" : "skills",
"identifications" : "ids",
"itemOnlyIDs" : "itemIDs",
"consumableOnlyIDs" : "consumableIDs",
"ingredientPositionModifiers" : "posMods",
}
ing_metaID_mappings = {
#item only IDs
"durabilityModifier": "dura",
"strengthRequirement": "strReq",
"dexterityRequirement": "dexReq",
"intelligenceRequirement": "intReq",
"defenceRequirement": "defReq",
"agilityRequirement": "agiReq",
"attackSpeedModifier": "atkTier",
"powderSlotModifier": "slotMod",
#consumable only IDs
"duration": "dura",
#"charges": "charges",
#position modifiers
#"left": "left",
#"right": "right",
#"above": "above",
#"under": "under",
#"touching": "touching",
#"notTouching": "notTouching",
}
ing_id_mappings = { #specifically for the id field of an ingredient.
#"name": "name",
#"displayName": "displayName",
#"tier": "tier",
#"set": "set",
#"sockets": "slots",
#"type": "type",
#"armorType": "armorType", (deleted)
#"armorColor": "color", (deleted)
#"addedLore": "lore", (deleted)
#"material": "material", (deleted)
#"dropType": "drop",
#"quest": "quest",
#"restrictions": "restrict",
#"damage": "nDam",
#"fireDamage": "fDam",
#"waterDamage": "wDam",
#"airDamage": "aDam",
#"thunderDamage": "tDam",
#"earthDamage": "eDam",
#"ATTACKSPEED": "atkSpd",
#"health": "hp",
"FIREDEFENSE": "fDefPct",
"WATERDEFENSE": "wDefPct",
"AIRDEFENSE": "aDefPct",
"THUNDERDEFENSE": "tDefPct",
"EARTHDEFENSE": "eDefPct",
#"level": "lvl",
#"classRequirement": "classReq",
#"strength": "strReq",
#"dexterity": "dexReq",
#"intelligence": "intReq",
#"agility": "agiReq",
#"defense": "defReq",
"HEALTHREGEN": "hprPct",
"MANAREGEN": "mr",
"SPELLDAMAGE": "sdPct",
"DAMAGEBONUS": "mdPct",
"LIFESTEAL": "ls",
"MANASTEAL": "ms",
"XPBONUS": "xpb",
"LOOTBONUS": "lb",
"LOOT_QUALITY": "lq",
"REFLECTION": "ref",
"STRENGTHPOINTS": "str",
"DEXTERITYPOINTS": "dex",
"INTELLIGENCEPOINTS": "int",
"AGILITYPOINTS": "agi",
"DEFENSEPOINTS": "def",
"THORNS": "thorns",
"EXPLODING": "expd",
"SPEED": "spd",
"ATTACKSPEED": "atkTier",
"POISON": "poison",
"HEALTHBONUS": "hpBonus",
"SOULPOINTS": "spRegen",
"EMERALDSTEALING": "eSteal",
"HEALTHREGENRAW": "hprRaw",
"SPELLDAMAGERAW": "sdRaw",
"DAMAGEBONUSRAW": "mdRaw",
"FIREDAMAGEBONUS": "fDamPct",
"WATERDAMAGEBONUS": "wDamPct",
"AIRDAMAGEBONUS": "aDamPct",
"THUNDERDAMAGEBONUS": "tDamPct",
"EARTHDAMAGEBONUS": "eDamPct",
#"accessoryType": "type",
#"identified": "fixID",
#"skin": "skin",
#"category": "category",
#THESE ARE NOT IN ANY INGREDIENT YET. THEY MAY NOT HAVE THE CORRECT ID NAME
"SPELLCOSTPCT1": "spPct1",
"SPELLCOSTRAW1": "spRaw1",
"SPELLCOSTPCT2": "spPct2",
"SPELLCOSTRAW2": "spRaw2",
"SPELLCOSTPCT3": "spPct3",
"SPELLCOSTRAW3": "spRaw3",
"SPELLCOSTPCT4": "spPct4",
"SPELLCOSTRAW4": "spRaw4",
"JUMPHEIGHT": "jh",
#"rainbowSpellDamageRaw": "rainbowRaw",
"SPRINT": "sprint",
"SPRINGREGEN": "sprintReg",
"GATHERXPBONUS": "gXp",
"GATHERSPEED": "gSpd",
#"lootQuality": "lq",
}
ing_delete_keys = [
"sprite",
]
recipe_translate_mappings = {
"level" : "lvl",
}
recipe_delete_keys = [ #lol
]
import os import os
if os.path.exists("id_map.json"): if os.path.exists("id_map.json"):
with open("id_map.json","r") as id_mapfile: with open("id_map.json","r") as id_mapfile:
id_map = json.load(id_mapfile) id_map = json.load(id_mapfile)
else: else:
id_map = {item["name"]: i for i, item in enumerate(items)} id_map = {item["name"]: i for i, item in enumerate(items)}
# wtf is this hpp
texture_names = [] texture_names = []
@ -299,61 +162,13 @@ for item in items:
if item["name"] in item_set_map: if item["name"] in item_set_map:
item["set"] = item_set_map[item["name"]] item["set"] = item_set_map[item["name"]]
print(ings[0])
for ing in ings:
for key in ing_delete_keys:
if key in ing:
del ing[key]
for k, v in ing_translate_mappings.items():
if k in ing:
ing[v] = ing[k]
del ing[k]
for k, v in ing_metaID_mappings.items():
if k in ing['itemIDs']:
print(ing['itemIDs'])
ing['itemIDs'][v] = ing['itemIDs'][k]
del ing['itemIDs'][k]
elif k in ing['consumableIDs']:
ing['consumableIDs'][v] = ing['consumableIDs'][k]
del ing['consumableIDs'][k]
'''elif k in ing.posMods: #Not subbing, if we do sub uncomment this.
ing.posMods[v] = ing.posMods[k]
del ing.posMods[k] '''
for k, v in ing_id_mappings.items():
if k in ing['ids']: #yes this is dumb
ing['ids'][v] = ing['ids'][k]
del ing['ids'][k]
for recipe in recipes:
for key in recipe_delete_keys:
if key in recipe:
del recipe[key]
for k, v in recipe_translate_mappings.items():
if k in recipe:
recipe[v] = recipe[k]
del recipe[k]
with open("1_20_ci.json", "r") as ci_file: with open("1_20_ci.json", "r") as ci_file:
ci_items = json.load(ci_file) ci_items = json.load(ci_file)
items.extend(ci_items) items.extend(ci_items)
'''with open("id_map.json","w") as id_mapfile: with open("id_map.json","w") as id_mapfile:
json.dump(id_map, id_mapfile, indent=2) json.dump(id_map, id_mapfile, indent=2)
with open("clean.json", "w") as outfile: with open("clean.json", "w") as outfile:
json.dump(data, outfile, indent=2) json.dump(data, outfile, indent=2)
with open("compress.json", "w") as outfile: with open("compress.json", "w") as outfile:
json.dump(data, outfile)''' json.dump(data, outfile)
with open("ingreds_clean.json", "w") as outfile:
json.dump(ing_data, outfile, indent = 2)
with open("ingreds_compress2.json", "w") as outfile:
json.dump(ing_data, outfile)
with open("recipes_clean.json", "w") as outfile:
json.dump(recipe_data, outfile, indent = 2)
with open("recipes_compress2.json", "w") as outfile:
json.dump(recipe_data, outfile)

View file

@ -15,7 +15,7 @@
.container { .container {
padding: 2% 4% 4%; padding: 2% 4% 4%;
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 0.4fr 0.6fr;
grid-auto-columns: minmax(200px, auto); grid-auto-columns: minmax(200px, auto);
gap: 5px; gap: 5px;
grid-auto-rows: minmax(60px, auto); grid-auto-rows: minmax(60px, auto);
@ -42,38 +42,7 @@
} }
.skp-input { .skpInput, .idInput {
} }
.hide-container-block {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
.hide-container-grid {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
.set-info-div {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
}
@keyframes fadeInFromNone {
0% {
opacity: 0;
}
1% {
opacity: 0;
}
100% {
opacity: 1;
}
}