pulling latest
This commit is contained in:
Restia Ashdoll 2021-01-19 11:49:00 -07:00
commit 88c1a95d02
21 changed files with 40604 additions and 198 deletions

View file

@ -3,47 +3,6 @@ const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ];
const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];
const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.20] ]);
/*Turns the input amount of skill points into a float precision percentage.
* @param skp - the integer skillpoint count to be converted
*/
function skillPointsToPercentage(skp){
if (skp<=0){
return 0.0;
}else if(skp>=150){
return 0.808;
}else{
return (-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771);
//return(-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771).toFixed(3);
}
}
/*Turns the input amount of levels into skillpoints available.
*
* @param level - the integer level count te be converted
*/
function levelToSkillPoints(level){
if(level < 1){
return 0;
}else if(level >= 101){
return 200;
}else{
return (level - 1) * 2;
}
}
/*Turns the input amount of levels in to base HP.
* @param level - the integer level count to be converted
*/
function levelToHPBase(level){
if(level < 1){ //bad level
return this.levelToHPBase(1);
}else if (level > 106){ //also bad level
return this.levelToHPBase(106);
}else{ //good level
return 5*level + 5;
}
}
/**
* @description Error to catch items that don't exist.
* @module ItemNotFound
@ -284,7 +243,7 @@ class Build{
/*Returns build in string format
*/
toString(){
return this.helmet.get("name") + ", " + this.chestplate.get("name") + ", " + this.leggings.get("name") + ", " + this.boots.get("name") + ", " + this.ring1.get("name") + ", " + this.ring2.get("name") + ", " + this.bracelet.get("name") + ", " + this.necklace.get("name") + ", " + this.weapon.get("name");
return [this.equipment,this.weapon].flat();
}
/* Getters */

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

@ -31,7 +31,6 @@ for (let i of editable_item_fields) {
editable_elems.push(elem);
}
let skp_order = ["str","dex","int","def","agi"];
for (let i of skp_order) {
let elem = document.getElementById(i+"-skp");
elem.addEventListener("change", (event) => {
@ -46,9 +45,6 @@ function clear_highlights() {
}
}
let skp_elements = ["e","t","w","f","a"];
let elementIcons = ["\u2724","\u2726", "\u2749", "\u2739", "\u274b" ];
let skpReqs = skp_order.map(x => x + "Req");
let equipment_fields = [
"helmet",
@ -430,8 +426,8 @@ function calculateBuild(save_skp, skp){
}
}
if(player_build){
updateBoosts("skip");
updatePowderSpecials("skip");
updateBoosts("skip", false);
updatePowderSpecials("skip", false);
}
//updatePowderSpecials("skip"); //jank pt 1
save_skp = (typeof save_skp !== 'undefined') ? save_skp : false;

182
craft.js Normal file
View file

@ -0,0 +1,182 @@
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("duration", this.recipe.get("basicDuration"));
}
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

@ -85,8 +85,8 @@ function expandIngredient(ing) {
idMap.set("maxRolls", new Map());
for (const field of ingFields) {
let val = (ing['ids'][field] || 0);
idMap.get("minRolls").set(field, val);
idMap.get("maxRolls").set(field, val);
idMap.get("minRolls").set(field, val['minimum']);
idMap.get("maxRolls").set(field, val['maximum']);
}
expandedIng.set("ids",idMap);
//console.log(expandedIng);
@ -105,6 +105,8 @@ function expandRecipe(recipe) {
for (const id of rangeIDs) {
if(recipe[id]){
expandedRecipe.set(id, [recipe[id]['minimum'], recipe[id]['maximum']]);
} else {
expandedRecipe.set(id, [0,0]);
}
}
expandedRecipe.set("materials", [ new Map([ ["item", recipe['materials'][0]['item']], ["amount", recipe['materials'][0]['amount']] ]) , new Map([ ["item", recipe['materials'][1]['item']], ["amount",recipe['materials'][0]['amount'] ] ]) ]);
@ -124,8 +126,55 @@ function idRound(id){
}
}
//Used for item IDs and ingredient id field IDs
let idPrefixes = {"displayName": "", "lvl":"Combat Level Min: ", "classReq":"Class Req: ","strReq":"Strength Min: ","dexReq":"Dexterity Min: ","intReq":"Intelligence Min: ","defReq":"Defense Min: ","agiReq":"Agility Min: ", "nDam_":"Neutral Damage: ", "eDam_":"Earth Damage: ", "tDam_":"Thunder Damage: ", "wDam_":"Water Damage: ", "fDam_":"Fire Damage: ", "aDam_":"Air Damage: ", "atkSpd":"Attack Speed: ", "hp":"Health : ", "eDef":"Earth Defense: ", "tDef":"Thunder Defense: ", "wDef":"Water Defense: ", "fDef":"Fire Defense: ", "aDef":"Air Defense: ", "str":"Strength: ", "dex":"Dexterity: ", "int":"Intelligence: ", "def":"Defense: ","agi":"Agility: ", "hpBonus":"Health Bonus: ", "hprRaw":"Health Regen Raw: ", "hprPct":"Health Regen %: ", "sdRaw":"Raw Spell Damage: ", "sdPct":"Spell Damage %: ", "mdRaw":"Raw Melee Damage: ", "mdPct":"Melee Damage %: ", "mr":"Mana Regen: ", "ms":"Mana Steal: ", "ref":"Reflection: ", "ls":"Life Steal: ", "poison":"Poison: ", "thorns":"Thorns: ", "expd":"Exploding: ", "spd":"Walk Speed Bonus: ", "atkTier":"Attack Speed Bonus: ", "eDamPct":"Earth Damage %: ", "tDamPct":"Thunder Damage %: ", "wDamPct":"Water Damage %: ", "fDamPct":"Fire Damage %: ", "aDamPct":"Air Damage %: ", "eDefPct":"Earth Defense %: ", "tDefPct":"Thunder Defense %: ", "wDefPct":"Water Defense %: ", "fDefPct":"Fire Defense %: ", "aDefPct":"Air Defense %: ", "spPct1":"1st Spell Cost %: ", "spRaw1":"1st Spell Cost Raw: ", "spPct2":"2nd Spell Cost %: ", "spRaw2":"2nd Spell Cost Raw: ", "spPct3":"3rd Spell Cost %: ", "spRaw3":"3rd Spell Cost Raw: ", "spPct4":"4th Spell Cost %: ", "spRaw4":"4th Spell Cost Raw: ", "rainbowRaw":"Rainbow Spell Damage Raw: ", "sprint":"Sprint Bonus: ", "sprintReg":"Sprint Regen Bonus: ", "jh":"Jump Height: ", "xpb":"Combat XP Bonus: ", "lb":"Loot Bonus: ", "lq":"Loot Quality: ", "spRegen":"Soul Point Regen: ", "eSteal":"Stealing: ", "gXp":"Gathering XP Bonus: ", "gSpd":"Gathering Speed Bonus: ", "slots":"Powder Slots: ", "set":"Set: ", "quest":"Quest Req: ", "restrict":""};
let idSuffixes = {"displayName": "", "lvl":"", "classReq":"","strReq":"","dexReq":"","intReq":"","defReq":"","agiReq":"", "nDam_":"", "eDam_":"", "tDam_":"", "wDam_":"", "fDam_":"", "aDam_":"", "atkSpd":"", "hp":"", "eDef":"", "tDef":"", "wDef":"", "fDef":"", "aDef":"", "str":"", "dex":"", "int":"", "def":"","agi":"", "hpBonus":"", "hprRaw":"", "hprPct":"%", "sdRaw":"", "sdPct":"%", "mdRaw":"", "mdPct":"%", "mr":"/4s", "ms":"/4s", "ref":"%", "ls":"/4s", "poison":"/3s", "thorns":"%", "expd":"%", "spd":"%", "atkTier":" tier", "eDamPct":"%", "tDamPct":"%", "wDamPct":"%", "fDamPct":"%", "aDamPct":"%", "eDefPct":"%", "tDefPct":"%", "wDefPct":"%", "fDefPct":"%", "aDefPct":"%", "spPct1":"%", "spRaw1":"", "spPct2":"%", "spRaw2":"", "spPct3":"%", "spRaw3":"", "spPct4":"%", "spRaw4":"", "rainbowRaw":"", "sprint":"%", "sprintReg":"%", "jh":"", "xpb":"%", "lb":"%", "lq":"%", "spRegen":"%", "eSteal":"%", "gXp":"%", "gSpd":"%", "slots":"", "set":" set.", "quest":"", "restrict":""};
//Used for ingredient IDs - name, lvl, tier. As of now, not used.
/*let ingPrefixes = {"name": "", "lvl": "", "tier": ""};
let ingSuffixes = {"name": "", "lvl": "", "tier": ""}*/
//Used for ingredient consumableIDs
let consumableIDPrefixes = {
"charges": "Charges: ",
"dura": "Duration: "
}
let consumableIDSuffixes = {
"charges": "",
"dura": " sec."
}
//Used for ingredient itemIDs
let itemIDPrefixes = {
"dura": "Durability: ",
"strReq": "Strength Min: ",
"dexReq": "Dexterity Min: ",
"intReq": "Intelligence Min: ",
"defReq": "Defense Min: ",
"agiReq": "Agility Min: "
}
/*let itemIDSuffixes = {
"dura": "",
"strReq": "",
"dexReq": "",
"intReq": "",
"defReq": "",
"agiReq": ""
}*/
//Used for ingredient posMods IDs
let posModPrefixes = {
"left":"Effectiveness Left: ",
"right":"EFfectiveness Right: ",
"above":"Effectiveness Above: ",
"under":"Effectiveness Under: ",
"touching":"EFfectiveness Touching: ",
"notTouching":"Effectiveness Not Touching: "
}
let posModSuffixes = {
"left":"%",
"right":"%",
"above":"%",
"under":"%",
"touching":"%",
"notTouching":"%"
}
function apply_elemental_format(p_elem, id, suffix) {
suffix = (typeof suffix !== 'undefined') ? suffix : "";
@ -358,6 +407,7 @@ function displayExpandedItem(item, parent_id){
"#ldiv",
"str", "dex", "int", "def", "agi",
"#table",
"str", "dex", "int", "def", "agi", //jank lmao
"hpBonus",
"hprRaw", "hprPct",
"sdRaw", "sdPct",
@ -420,7 +470,7 @@ function displayExpandedItem(item, parent_id){
}
else {
let id = command;
if(nonRolledIDs.includes(id) && item.get(id)){//nonRolledID & non-0/non-null/non-und ID
if(( nonRolledIDs.includes(id) && item.get(id))){//nonRolledID & non-0/non-null/non-und ID
if (id === "slots") {
let p_elem = document.createElement("p");
// PROPER POWDER DISPLAYING EZ CLAP
@ -449,14 +499,23 @@ function displayExpandedItem(item, parent_id){
powderSuffix.textContent = "]";
p_elem.appendChild(powderSuffix);
active_elem.appendChild(p_elem);
}
else {
let p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
} else {
let p_elem;
if (!(skp_order.includes(id) && item.get("tier") === "Crafted")) {
p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
}
if (id === "displayName") {
p_elem.classList.add("title");
if (item.get("tier") !== " ") {
p_elem.classList.add(item.get("tier"));
}
if (["potion", "scroll", "food"].includes(item.get("type"))){ //must have access to craft.js
let b = document.createElement("b");
b.textContent = "[" + item.get("charges") + "/" + item.get("charges") + "]";
b.classList.add("spaceleft");
p_elem.appendChild(b);
}
/*let validTypes = ["helmet", "chestplate", "leggings", "boots", "relik", "wand", "bow", "spear", "dagger", "ring", "bracelet", "necklace"];
if (item.has("type") && validTypes.includes(item.get("type"))) {
p = document.createElement("p");
@ -470,28 +529,52 @@ function displayExpandedItem(item, parent_id){
p_elem.append(p);
}*/
} else if (skp_order.includes(id)) { //id = str, dex, int, def, or agi
p_elem.textContent = "";
p_elem.classList.add("itemtable");
let row = document.createElement("tr");
let title = document.createElement("td");
title.textContent = idPrefixes[id] + " ";
let boost = document.createElement("td");
if (item.get(id) < 0) {
boost.classList.add("negative");
} else { //boost = 0 SHOULD not come up
boost.classList.add("positive");
if ( item.get("tier") !== "Crafted" && active_elem.nodeName === "DIV") {
p_elem.textContent = "";
p_elem.classList.add("itemp");
row = document.createElement("p");
row.classList.add("left");
let title = document.createElement("b");
title.textContent = idPrefixes[id] + " ";
let boost = document.createElement("b");
if (item.get(id) < 0) {
boost.classList.add("negative");
} else { //boost = 0 SHOULD not come up
boost.classList.add("positive");
}
boost.textContent = item.get(id);
row.appendChild(title);
row.appendChild(boost);
p_elem.appendChild(row);
} else if ( item.get("tier") === "Crafted" && active_elem.nodeName === "TABLE") {
let row = document.createElement('tr');
let min_elem = document.createElement('td');
min_elem.classList.add('left');
min_elem.classList.add( item.get("minRolls").get(id) < 0 ? "negative" : "positive");
min_elem.textContent = item.get("minRolls").get(id) + idSuffixes[id];
row.appendChild(min_elem);
let desc_elem = document.createElement('td');
desc_elem.classList.add('center');
//TODO elemental format jank
desc_elem.textContent = idPrefixes[id];
row.appendChild(desc_elem);
let max_elem = document.createElement('td');
max_elem.classList.add('right');
max_elem.classList.add( item.get("maxRolls").get(id) < 0 ? "negative" : "positive");
max_elem.textContent = item.get("maxRolls").get(id) + idSuffixes[id];
row.appendChild(max_elem);
active_elem.appendChild(row);
}
boost.classList.add("spaceLeft");
boost.textContent = item.get(id);
row.appendChild(title);
row.appendChild(boost);
p_elem.appendChild(row);
} else if (id === "restrict") {
} else if (id === "restrict") {
p_elem.classList.add("restrict");
}
}
}
else if (rolledIDs.includes(id) && item.get("minRolls").get(id)){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID
else if ( (rolledIDs.includes(id) && item.get("minRolls").get(id)) ){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID
let style = "positive";
if (item.get("minRolls").get(id) < 0) {
style = "negative";
@ -530,74 +613,95 @@ function displayExpandedItem(item, parent_id){
row.appendChild(max_elem);
active_elem.appendChild(row);
}
}//Just don't do anything if else
}else{
// :/
}
}
}
//Show powder specials ;-;
let powder_special = document.createElement("p");
powder_special.classList.add("left");
let powders = item.get("powders");
let element = "";
let power = 0;
for (let i = 0; i < powders.length; i++) {
let firstPowderType = skp_elements[Math.floor(powders[i]/6)];
if (element !== "") break;
else if (powders[i]%6 > 2) { //t4+
for (let j = i+1; j < powders.length; j++) {
let currentPowderType = skp_elements[Math.floor(powders[j]/6)]
if (powders[j] % 6 > 2 && firstPowderType === currentPowderType) {
element = currentPowderType;
power = Math.round(((powders[i] % 6 + powders[j] % 6 + 2) / 2 - 4) * 2);
break;
let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots", "ring", "bracelet", "necklace"];
if(nonConsumables.includes(item.get("type"))) {
let powder_special = document.createElement("p");
powder_special.classList.add("left");
let powders = item.get("powders");
let element = "";
let power = 0;
for (let i = 0; i < powders.length; i++) {
let firstPowderType = skp_elements[Math.floor(powders[i]/6)];
if (element !== "") break;
else if (powders[i]%6 > 2) { //t4+
for (let j = i+1; j < powders.length; j++) {
let currentPowderType = skp_elements[Math.floor(powders[j]/6)]
if (powders[j] % 6 > 2 && firstPowderType === currentPowderType) {
element = currentPowderType;
power = Math.round(((powders[i] % 6 + powders[j] % 6 + 2) / 2 - 4) * 2);
break;
}
}
}
}
}
if (element !== "") {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
let powderSpecial = powderSpecialStats[ skp_elements.indexOf(element)];
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
let specialTitle = document.createElement("p");
let specialEffects = document.createElement("p");
specialTitle.classList.add("left");
specialTitle.classList.add("itemp");
specialTitle.classList.add(damageClasses[skp_elements.indexOf(element) + 1]);
specialEffects.classList.add("left");
specialEffects.classList.add("itemp");
specialEffects.classList.add("nocolor");
let effects;
if (item.get("category") === "weapon") {//weapon
effects = powderSpecial["weaponSpecialEffects"];
specialTitle.textContent = powderSpecial["weaponSpecialName"];
}else if (item.get("category") === "armor") {//armor
effects = powderSpecial["armorSpecialEffects"];
specialTitle.textContent += powderSpecial["armorSpecialName"] + ": ";
}
for (const [key,value] of effects) {
if (key !== "Description") {
let effect = document.createElement("p");
effect.classList.add("itemp");
effect.textContent += key + ": " + value[power] + specialSuffixes.get(key);
if(key === "Damage"){
effect.textContent += elementIcons[skp_elements.indexOf(element)];
}
if (element === "w") {
effect.textContent += " / Mana Used";
}
specialEffects.appendChild(effect);
}else{
specialTitle.textContent += "[ " + effects.get("Description") + " ]";
if (element !== "") {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
let powderSpecial = powderSpecialStats[ skp_elements.indexOf(element)];
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
let specialTitle = document.createElement("p");
let specialEffects = document.createElement("p");
specialTitle.classList.add("left");
specialTitle.classList.add("itemp");
specialTitle.classList.add(damageClasses[skp_elements.indexOf(element) + 1]);
specialEffects.classList.add("left");
specialEffects.classList.add("itemp");
specialEffects.classList.add("nocolor");
let effects;
if (item.get("category") === "weapon") {//weapon
effects = powderSpecial["weaponSpecialEffects"];
specialTitle.textContent = powderSpecial["weaponSpecialName"];
}else if (item.get("category") === "armor") {//armor
effects = powderSpecial["armorSpecialEffects"];
specialTitle.textContent += powderSpecial["armorSpecialName"] + ": ";
}
for (const [key,value] of effects) {
if (key !== "Description") {
let effect = document.createElement("p");
effect.classList.add("itemp");
effect.textContent += key + ": " + value[power] + specialSuffixes.get(key);
if(key === "Damage"){
effect.textContent += elementIcons[skp_elements.indexOf(element)];
}
if (element === "w") {
effect.textContent += " / Mana Used";
}
specialEffects.appendChild(effect);
}else{
specialTitle.textContent += "[ " + effects.get("Description") + " ]";
}
}
specialTitle.append(specialEffects);
powder_special.appendChild(specialTitle);
parent_div.append(powder_special);
}
specialTitle.append(specialEffects);
powder_special.appendChild(specialTitle);
parent_div.append(powder_special);
}
if(item.get("tier") && item.get("tier") === "Crafted") {
let dura_elem = document.createElement("p");
dura_elem.classList.add("left");
let dura = [];
let suffix = "";
if(nonConsumables.includes(item.get("type"))) {
dura = item.get("durability");
dura_elem.textContent = "Durability: "
} else {
dura = item.get("duration");
dura_elem.textContent = "Duration: "
suffix = " sec."
}
dura_elem.textContent += dura[0]+"-"+dura[1] + suffix;
parent_div.append(dura_elem);
}
//Show item tier
if (item.get("tier") && item.get("tier") !== " ") {
let item_desc_elem = document.createElement('p');
let item_desc_elem = document.createElement("p");
item_desc_elem.classList.add('left');
item_desc_elem.classList.add(item.get("tier"));
item_desc_elem.textContent = item.get("tier")+" "+item.get("type");
@ -605,16 +709,15 @@ function displayExpandedItem(item, parent_id){
}
}
function displayCraftStats(craft, parent_id) {
}
function displayExpandedRecipe(recipe, parent_id) {
let mock_item = craft.statMap;
displayExpandedItem(mock_item,parent_id);
}
function displayExpandedIngredient(ingred, parent_id) {
let elem = document.getElementById(parent_id);
console.log(ingred);
let parent_elem = document.getElementById(parent_id);
parent_elem.textContent = "";
let display_order = [
"#cdiv",
"name", //tier will be displayed w/ name
@ -628,7 +731,27 @@ function displayExpandedIngredient(ingred, parent_id) {
"lvl",
"skills",
]
let id_display_commands = [ //all center div!
let item_order = [
"dura",
"strReq",
"dexReq",
"intReq",
"defReq",
"agiReq"
]
let consumable_order = [
"dura",
"charges"
]
let posMods_order = [
"above",
"under",
"left",
"right",
"touching",
"notTouching"
];
let id_display_order = [
"eDefPct",
"tDefPct",
"wDefPct",
@ -679,22 +802,184 @@ function displayExpandedIngredient(ingred, parent_id) {
"gXp",
"gSpd",
];
if (command.charAt(0) === "#") {
if (command === "#cdiv") {
active_elem = document.createElement('div');
active_elem.classList.add('itemcenter');
}
else if (command === "#ldiv") {
active_elem = document.createElement('div');
active_elem.classList.add('itemleft');
}
else if (command === "#table") {
active_elem = document.createElement('table');
active_elem.classList.add('itemtable');
}
parent_div.appendChild(active_elem);
}
let active_elem;
let elemental_format = false;
let style;
for (const command of display_order) {
if (command.charAt(0) === "#") {
if (command === "#cdiv") {
active_elem = document.createElement('div');
active_elem.classList.add('itemcenter');
}
else if (command === "#ldiv") {
active_elem = document.createElement('div');
active_elem.classList.add('itemleft');
}
else if (command === "#table") {
active_elem = document.createElement('table');
active_elem.classList.add('itemtable');
}
parent_elem.appendChild(active_elem);
}else {
let p_elem = document.createElement("p");
p_elem.classList.add("left");
if (command === "name") {
p_elem.classList.add("title");
p_elem.classList.remove("left");
let title_elem = document.createElement("b");
title_elem.textContent = ingred.get("name");
p_elem.appendChild(title_elem);
let space = document.createElement("b");
space.classList.add("space");
p_elem.appendChild(space);
let tier = ingred.get("tier"); //tier in [0,3]
let begin = document.createElement("b");
begin.classList.add("T"+tier+"-bracket");
begin.textContent = "[";
p_elem.appendChild(begin);
for (let i = 0; i < 3; i++) {
let tier_elem = document.createElement("b");
if(i < tier) {tier_elem.classList.add("T"+tier)}
else {tier_elem.classList.add("T0")}
tier_elem.textContent = "\u272B";
p_elem.appendChild(tier_elem);
}
let end = document.createElement("b");
end.classList.add("T"+tier+"-bracket");
end.textContent = "]";
p_elem.appendChild(end);
}else if (command === "lvl") {
p_elem.textContent = "Crafting Lvl Min: " + ingred.get("lvl");
}else if (command === "posMods") {
for (const [key,value] of ingred.get("posMods")) {
let p = document.createElement("p");
p.classList.add("nomarginp");
if (value != 0) {
let title = document.createElement("b");
title.textContent = posModPrefixes[key];
let val = document.createElement("b");
val.textContent = value + posModSuffixes[key];
if(value > 0) {
val.classList.add("positive");
} else {
val.classList.add("negative");
}
p.appendChild(title);
p.appendChild(val);
p_elem.appendChild(p);
}
}
} else if (command === "itemIDs") { //dura, reqs
for (const [key,value] of ingred.get("itemIDs")) {
let p = document.createElement("p");
p.classList.add("nomarginp");
if (value != 0) {
let title = document.createElement("b");
title.textContent = itemIDPrefixes[key];
p.appendChild(title);
}
let desc = document.createElement("b");
if(value > 0) {
if(key !== "dura") {
desc.classList.add("negative");
} else{
desc.classList.add("positive");
}
desc.textContent = "+"+value;
} else if (value < 0){
if(key !== "dura") {
desc.classList.add("positive");
} else{
desc.classList.add("negative");
}
desc.textContent = value;
}
if(value != 0){
p.appendChild(desc);
}
p_elem.append(p);
}
} else if (command === "consumableIDs") { //dura, charges
for (const [key,value] of ingred.get("consumableIDs")) {
let p = document.createElement("p");
p.classList.add("nomarginp");
if (value != 0) {
let title = document.createElement("b");
title.textContent = consumableIDPrefixes[key];
p.appendChild(title);
}
let desc = document.createElement("b");
if(value > 0) {
desc.classList.add("positive");
desc.textContent = "+"+value;
} else if (value < 0){
desc.classList.add("negative");
desc.textContent = value;
}
if(value != 0){
p.appendChild(desc);
let suffix = document.createElement("b");
suffix.textContent = consumableIDSuffixes[key];
p.appendChild(suffix);
}
p_elem.append(p);
}
}else if (command === "skills") {
p_elem.textContent = "Used in:";
for(const skill of ingred.get("skills")) {
let p = document.createElement("p");
p.textContent = skill.charAt(0) + skill.substring(1).toLowerCase();
p.classList.add("left");
p_elem.append(p);
}
} else if (command === "ids") { //warp
for (const [key,value] of ingred.get("ids").get("minRolls")) {
if (ingred.get("ids").get("minRolls").get(key) && value != 0 && ingred.get("ids").get("maxRolls").get(key) != 0){
if(value > 0) {
style = "positive";
} else if (value < 0) {
style = "negative";
}
if(reversedIDs.filter(e => e !== "atkTier").includes(key)){
style === "positive" ? style = "negative" : style = "positive";
}
let row = document.createElement('tr');
row.classList.add("center");
let min_elem = document.createElement('td');
min_elem.classList.add('left');
min_elem.classList.add(style);
min_elem.textContent = value + idSuffixes[key];
row.appendChild(min_elem);
let desc_elem = document.createElement('td');
desc_elem.classList.add('center');
//TODO elemental format jank
if (elemental_format) {
apply_elemental_format(desc_elem, key);
}
else {
desc_elem.textContent = idPrefixes[key];
}
row.appendChild(desc_elem);
let max_elem = document.createElement('td');
max_elem.classList.add('right');
max_elem.classList.add(style);
max_elem.textContent = ingred.get("ids").get("maxRolls").get(key) + idSuffixes[key];
row.appendChild(max_elem);
active_elem.appendChild(row);
}
}
} else {//this shouldn't be happening
}
active_elem.appendChild(p_elem);
}
}
}
function displayNextCosts(parent_id, build) {
@ -716,7 +1001,7 @@ function displayNextCosts(parent_id, build) {
p_elem.append(title);
p_elem.append(int_title);
for (const spell of spells) { //warp
for (const spell of spells) {
let spellp = document.createElement("p");
let spelltitle = document.createElement("p");
spelltitle.classList.add("itemp");

View file

@ -262,7 +262,7 @@
</tr>
<tr>
<td>
<button class = "button-narrow" id = "vanish-boost" onclick = "updateBoosts('vanish-boost'), true">
<button class = "button-narrow" id = "vanish-boost" onclick = "updateBoosts('vanish-boost', true)">
Vanish (+80%)
</button>
</td>
@ -976,6 +976,7 @@
</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>

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

View file

@ -29,6 +29,7 @@ async function ing_load_local(init_func) {
request4.onsuccess = function(event) {
console.log("Successfully read local recipe db.");
recipes = request4.result;
init_func();
}
await get_tx.complete;
db.close();
@ -53,15 +54,15 @@ async function load_ings(init_func) {
recipes = result.recipes;
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/clear
let clear_tx2 = db.transaction(['ing_db'], 'readwrite');
/*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;
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) {
@ -82,7 +83,7 @@ async function load_ings(init_func) {
function load_ing_init(init_func) {
let request = window.indexedDB.open("ing_db", DB_VERSION)
let request = window.indexedDB.open("ing_db", ING_DB_VERSION)
request.onerror = function() {
console.log("DB failed to open...");
}
@ -91,11 +92,11 @@ function load_ing_init(init_func) {
db = request.result;
if (!reload) {
console.log("Using stored data...")
load_local(init_func);
ing_load_local(init_func);
}
else {
console.log("Using new data...")
load(init_func);
load_ings(init_func);
}
}

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

View file

@ -6,7 +6,6 @@
.all {
font-family: 'Nunito',sans-serif;
font-weight: 700;
text-size-adjust: none;
}
th, td {
@ -15,9 +14,11 @@ th, td {
.nomargin {
padding: 0px;
margin: 0px;
}
.nomarginp {
margin: 0px;
padding: 0px;
}
div {
padding: 0%;
}
@ -30,11 +31,7 @@ div {
grid-template-rows: min-content min-content auto;
}
.id-edit1 {
}
.skillpoints {
.skillpoints, .id-edit1 {
padding: 0% 4% 2%;
display: grid;
grid-template-columns: repeat(5, 1fr);
@ -42,6 +39,14 @@ div {
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{
padding: 0% 4% 2%;
display: grid;
@ -63,6 +68,14 @@ div {
a.link{
color: #A5FDFF;
}
.title{
text-align: center;
font-size: 150%;
}
.smalltitle{
text-align: center;
font-size: 125%;
}
.center {
text-align: center;
position: relative;
@ -82,13 +95,19 @@ table.center{
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, .crafter, .recipe-stats, .craft-stats, .ing-stats, .id-box {
.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;
background: #121516;
border: 3px solid #BCBCBC;
border-radius: 3px;
width: 96%;
}
.crafter, .recipe-stats, .craft-stats, .ing-stats {
color: #aaa;
background: #121516;
border: 3px solid #BCBCBC;
border-radius: 3px;
}
.spell-info {
margin-bottom: 10px;
@ -108,23 +127,19 @@ table.center{
margin: 2px 2%;
width: 94%;
margin-bottom: 16px;
margin-left: auto;
margin-right: auto;
}
.itemp, .damagep {
margin: 2px 2%;
padding: 0;
}
.powderLeft {
margin: 2px 0% 2px 2%;
padding: 0;
}
.powderRight {
margin: 2px 2% 2px 0%;
padding: 0;
}
.space {
margin-right: 5px;
}
.spaceleft{
margin-left: 5px;
}
.damageSubtitle {
text-align: center;
@ -189,8 +204,8 @@ table.center{
margin: auto;
}
.idLeft {
text-align: left;
.idCenter {
text-align: center;
padding: 1em 0px 0px 0px;
position: relative;
display: flex;
@ -222,7 +237,40 @@ table.center{
::-webkit-scrollbar-corner{
background: #110110;
}
.button-narrow {
background-color: #666;
border: 2px solid #444;
border-radius: 5px;
color: #ddd;
text-align: center;
text-decoration: none;
font-family: 'Nunito',sans-serif;
font-weight: 700;
font-size: 90%;
display: inline-block;
}
button {
background-color: #666;
border: 2px solid #444;
border-radius: 5px;
color: #ddd;
text-align: center;
text-decoration: none;
font-family: 'Nunito',sans-serif;
font-weight: 700;
font-size: 120%;
display: inline-block;
}
button:hover {
background-color: #556;
}
button:active {
background-color: #558;
box-shadow: 0 3px #666;
transform: translateY(1px);
}
input {
background-color: #666;
border: 2px solid #444;
@ -256,6 +304,12 @@ input {
.Mythic{
color:#a0a;
}
.Crafted {
color: #0aa;
}
.Custom {
color: #0aa;
}
.Set{
color:#5f5;
}
@ -267,17 +321,6 @@ button.toggleOn{
background-color:#0a0;
border: 3 px solid rgb(0, 70, 0);
}
.toggleOn:hover {
background-color: #585;
}
button:hover {
background-color: #556;
}
button:active {
background-color: #558;
box-shadow: 0 3px #666;
transform: translateY(1px);
}
.funnynumber {
background-image: linear-gradient(to left, #f5f, #a0a, #5ff, #5f5, #ff5, #fa0, #a00); -webkit-background-clip: text;
@ -297,7 +340,31 @@ button:active {
width: 100%;
}
.hide-container-block, .hide-container-grid, .set-info-div, .fade-in, .misc {
.T0 {
color: #555;
}
.T1 {
color: #ff5;
}
.T2 {
color: #f5f;
}
.T3 {
color: #5ff;
}
.T0-bracket {
color: #555;
}
.T1-bracket {
color: #fa0;
}
.T2-bracket {
color: #a0a;
}
.T3-bracket {
color: #0aa;
}
.hide-container-block, .hide-container-grid, .set-info-div, .fade-in {
animation-duration: 0.5s;
animation-name: fadeInFromNone;
animation-fill-mode: forwards;
@ -316,8 +383,3 @@ button:active {
opacity: 1;
}
}
.highlight {
color: #ff5;
background-color: #775;
}

0
temp.json Normal file
View file

View file

@ -1,3 +1,9 @@
let skp_order = ["str","dex","int","def","agi"];
let skill = ["Strength", "Dexterity", "Intelligence", "Defense", "Agility"];
let skp_elements = ["e","t","w","f","a"];
let elementIcons = ["\u2724","\u2726", "\u2749", "\u2739", "\u274b" ];
let skpReqs = skp_order.map(x => x + "Req");
// Permutations in js reference (also cool algorithm):
// https://stackoverflow.com/a/41068709
function perm(a){

View file

@ -19,13 +19,12 @@
.container {
padding: 2% 4% 4%;
display: grid;
grid-template-columns: 1fr 0.7fr 0.7fr;
grid-template-columns: 1fr 0.4fr 0.6fr;
grid-auto-columns: minmax(200px, auto);
gap: 5px;
grid-auto-rows: minmax(60px, auto);
}
.ingredients {
padding: 2% 4% 4%;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-columns: minmax(200px, auto);