1d6b302f38
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354753 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354749 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354744 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354739 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354735 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354730 -0700 parent3e725eded8
author hppeng <hppeng> 1699417872 -0800 committer hppeng <hppeng> 1720354688 -0700 Update recipes.json (#265) Change ratio of gems to oil as it has been updated in 2.0.4 > Updated the Jeweling Recipe Changes (Bracelet- 2:1 gems:oil, Necklaces- 3:1 gems:oil) https://forums.wynncraft.com/threads/2-0-4-full-changelog-new-bank-lootruns-more.310535/ Finish updating recipes.json why are there 4 versions of this file active at any given time Fix damage calculation for rainbow raw wow this bug has been here for a LONG time also bump version for ing db Bunch of bugfixes - new major ID - divine honor: reduce earth damage - radiance: don't boost tomes, xp/loot bonuses atree: - parry: minor typo - death magnet: marked dep - nightcloak knife: 15s desc Api v3 (#267) * Tweak ordering to be consistent internally * v3 items (#266) * item_wrapper script for updating item data with v3 endpoint * metadata from v3 * v3 item format For the purpose of wynnbuilder, additional mapping might be needed. * v3 item format additional mapping might be needed for wb * v3 compressed item json * clean item json v3 format * Update translate map to api v3 partially... we will need to redo scripts to flatmap all the items * Fix items for 2.0.4.3 finally * New ingredients (and parse script update) just realized I forgot to commit the parse script this whole time * Forgot to commit data files, and bump ing db version * Sketchily reverse translate major ids internalname and separate lookup table lol * Forgot to update data files todo: script should update all files at once * Bump wynn version number already outdated... * Forgot to update 2.0.4.3 major ids --------- Co-authored-by: hppeng <hppeng> Co-authored-by: RawFish69 <108964215+RawFish69@users.noreply.github.com> Add missing fields to ingreds missing ids and consumableIDs tags in some ingreds Fix missing properties in item search setup these should be unified maybe to avoid duplicated code Fix sacshrine dependency on fluid healing also: fix ": " in item searcher I managed to mess up all major ids note: major ids min file is generated along with atree. it uses numeric ids, not just json compress 2.0.4.4 update (#269) * 2.0.4.4 update Fix v3 item api debug script Implement hellfire (discombob disallow not happening yet) * Fix boiling blood implementation slightly more intuitive also, janky first pass implementation for hellfire * Atree default update Allow sliders to specify a default value, for puppet and boiling blood for now * Fix rainbow def display on items and build stats Calculate into raw def correctly * Atree backend improvements Allow major ids to have dependencies Implement cherry bomb new ver. (wooo replace_spell just works out of the box!) Add comments to atree.js * Fix name of normal items don't you love it when wynn api makes breaking changes for no reason * Misc bugfix Reckless abandon req Tempest new damage ID in search * Fix major id search and temblor desc * Fix blockers on mage * Fix flaming uppercut implementation * Force base dps display to display less digits * Tomes finally pulling from the API but still with alias feature enabled! * Lootrun tomes (finally?) cool? maybe? * Fix beachside set set bonus --------- Co-authored-by: hppeng <hppeng> Fix rainbow def display on items and build stats Calculate into raw def correctly Fix major id search and temblor desc Force base dps display to display less digits Fix beachside set set bonus Fix build decode error reading only 7 tome fields no matter what Give NONE tomes correct ids in load_tome i hate this system so much Allow searching for max/min of ranges Fix crafted item damage display in the process, also update powder calculation logic! Should be fully correct now... TL;DR: Weapon damage is floating point; item display is wrong; ingame displays (damage floaters and compass) are floored. Fluid healing now multiplicative with heal efficiency ID NOTE: this breaks backwards compatibility with older atree jsons. Do we care about this? Realizing how much of a nightmare it will be (and already is) to keep atree fully backwards compatible. Maybe that will be something left to `git clone` instead. fix (#274)
402 lines
19 KiB
JavaScript
402 lines
19 KiB
JavaScript
let recipeTypes = ["HELMET","CHESTPLATE","LEGGINGS","BOOTS","RELIK","WAND","SPEAR","DAGGER","BOW","RING","NECKLACE","BRACELET","POTION", "SCROLL","FOOD"];
|
|
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",]
|
|
|
|
function encodeCraft(craft) {
|
|
if (craft) {
|
|
let atkSpds = ["SLOW","NORMAL","FAST"];
|
|
let craft_string = "1" +
|
|
Base64.fromIntN(craft.ingreds[0].get("id"), 2) +
|
|
Base64.fromIntN(craft.ingreds[1].get("id"), 2) +
|
|
Base64.fromIntN(craft.ingreds[2].get("id"), 2) +
|
|
Base64.fromIntN(craft.ingreds[3].get("id"), 2) +
|
|
Base64.fromIntN(craft.ingreds[4].get("id"), 2) +
|
|
Base64.fromIntN(craft.ingreds[5].get("id"), 2) +
|
|
Base64.fromIntN(craft.recipe.get("id"),2) +
|
|
Base64.fromIntN(craft.mat_tiers[0] + (craft.mat_tiers[1]-1)*3, 1) + //this maps tiers [a,b] to a+3b.
|
|
Base64.fromIntN(atkSpds.indexOf(craft["atkSpd"]),1);
|
|
return craft_string;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
//constructs a craft from a hash 'CR-qwoefsabaoe' or 'qwoefsaboe'
|
|
function getCraftFromHash(hash) {
|
|
let name = hash.slice();
|
|
try {
|
|
if (name.slice(0,3) === "CR-") {
|
|
name = name.substring(3);
|
|
} else {
|
|
throw new Error("Not a crafted item!");
|
|
}
|
|
version = name.substring(0,1);
|
|
name = name.substring(1);
|
|
if (version === "1") {
|
|
let ingreds = [];
|
|
for (let i = 0; i < 6; i ++ ) {
|
|
ingreds.push( expandIngredient(ingMap.get(ingIDMap.get(Base64.toInt(name.substring(2*i,2*i+2))))) );
|
|
}
|
|
let recipe = expandRecipe(recipeMap.get(recipeIDMap.get(Base64.toInt(name.substring(12,14)))));
|
|
|
|
tierNum = Base64.toInt(name.substring(14,15));
|
|
let mat_tiers = [];
|
|
mat_tiers.push(tierNum % 3 == 0 ? 3 : tierNum % 3);
|
|
mat_tiers.push(Math.floor((tierNum-0.5) / 3)+1); //Trying to prevent round-off error, don't yell at me
|
|
let atkSpd = Base64.toInt(name.substring(15));
|
|
let atkSpds = ["SLOW","NORMAL","FAST"];
|
|
let attackSpeed = atkSpds[atkSpd];
|
|
return new Craft(recipe,mat_tiers,ingreds,attackSpeed,"1"+name);
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
return undefined;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 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, attackSpeed, hash) {
|
|
this.recipe = recipe;
|
|
this.mat_tiers = mat_tiers;
|
|
this.ingreds = ingreds;
|
|
this.statMap = new Map(); //can use the statMap as an expanded Item
|
|
this.atkSpd = attackSpeed;
|
|
this.hash = "CR-" + hash;
|
|
this.initCraftStats();
|
|
this.statMap.set("hash", this.hash);
|
|
}
|
|
|
|
applyPowders() {
|
|
if (this.statMap.get("category") === "armor" || this.statMap.get("category" === "accessory")) {
|
|
//double apply armor powders
|
|
for(const id of this.statMap.get("powders")){
|
|
let powder = powderStats[id];
|
|
let name = powderNames.get(id);
|
|
this.statMap.set(name.charAt(0) + "Def", (this.statMap.get(name.charAt(0)+"Def") || 0) + 2 * powder["defPlus"]);
|
|
this.statMap.set(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5] + "Def", (this.statMap.get(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5]+"Def") || 0) - 2 * powder["defMinus"]);
|
|
}
|
|
}else if (this.statMap.get("category") === "weapon") {
|
|
//do nothing - weapon powders are handled in displayExpandedItem
|
|
}
|
|
}
|
|
setHash(hash) {
|
|
this.hash = "CR-" + hash;
|
|
this.statMap.set("name", this.hash);
|
|
this.statMap.set("displayName", this.hash);
|
|
this.statMap.set("hash", this.hash);
|
|
}
|
|
/* 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 statMap = new Map();
|
|
statMap.set("minRolls", new Map());
|
|
statMap.set("maxRolls", new Map());
|
|
statMap.set("name", this.hash);
|
|
statMap.set("displayName", this.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")[1]);
|
|
statMap.set("lvlLow", this.recipe.get("lvl")[0]);
|
|
statMap.set("nDam", 0);
|
|
statMap.set("hp",0);
|
|
statMap.set("hpLow",0);
|
|
for (const e of skp_elements) {
|
|
statMap.set(e + "Dam", "0-0");
|
|
statMap.set(e + "Def", 0);
|
|
}
|
|
for (const e of skp_order) {
|
|
statMap.set(e + "Req", 0)
|
|
statMap.set(e, 0);
|
|
}
|
|
let allNone = true;
|
|
if (armorTypes.includes(statMap.get("type")) || weaponTypes.includes(statMap.get("type"))) {
|
|
statMap.set("category","weapon");
|
|
if(this.recipe.get("lvl")[0] < 30) {
|
|
statMap.set("slots", 1);
|
|
} else if (this.recipe.get("lvl")[0] < 70) {
|
|
statMap.set("slots", 2);
|
|
} else{
|
|
statMap.set("slots", 3);
|
|
}
|
|
} else {
|
|
statMap.set("slots", 0);
|
|
}
|
|
if (consumableTypes.includes(statMap.get("type"))) {
|
|
statMap.set("category","consumable");
|
|
if(this.recipe.get("lvl")[0] < 30) {
|
|
statMap.set("charges", 1);
|
|
} else if (this.recipe.get("lvl")[0] < 70) {
|
|
statMap.set("charges", 2);
|
|
} else{
|
|
statMap.set("charges", 3);
|
|
}
|
|
//no ingredient consumables ALWAYS have 3 charges.
|
|
|
|
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("charges", 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(e + "DamLow", "0-0");
|
|
}
|
|
statMap.set("category","weapon");
|
|
statMap.set("atkSpd",this.atkSpd);
|
|
}
|
|
if (accessoryTypes.includes(statMap.get("type"))) {
|
|
statMap.set("category", "accessory");
|
|
}
|
|
statMap.set("powders",[]);
|
|
|
|
/* Change certain IDs based on material tier.
|
|
healthOrDamage changes.
|
|
duration and durability change. (but not basicDuration)
|
|
*/
|
|
let matmult = 1;
|
|
let tierToMult = [0,1,1.25,1.4];
|
|
let tiers = this.mat_tiers.slice();
|
|
let amounts = this.recipe.get("materials").map(x=> x.get("amount"));
|
|
//Mat Multipliers - should work!
|
|
matmult = (tierToMult[tiers[0]]*amounts[0] + tierToMult[tiers[1]]*amounts[1]) / (amounts[0]+amounts[1]);
|
|
|
|
let low = this.recipe.get("healthOrDamage")[0];
|
|
let high = this.recipe.get("healthOrDamage")[1];
|
|
if (statMap.get("category") === "consumable") {
|
|
if(allNone) {
|
|
statMap.set("hp", Math.floor( low * matmult )+ "-" + Math.floor( high * matmult ));
|
|
}
|
|
statMap.set("duration", [Math.round( statMap.get("duration")[0] * matmult ), Math.round( statMap.get("duration")[1] * matmult )]);
|
|
} else {
|
|
//durability modifier
|
|
statMap.set("durability", [Math.round( statMap.get("durability")[0] * matmult ), Math.round( statMap.get("durability")[1] * matmult )]);
|
|
}
|
|
if (statMap.get("category") === "weapon") {
|
|
//attack damages oh boy
|
|
let ratio = 2.05;
|
|
if (this['atkSpd'] === "SLOW") {
|
|
ratio /= 1.5;
|
|
} else if (this['atkSpd'] === "NORMAL") {
|
|
ratio = 1;
|
|
} else if (this['atkSpd'] === "FAST") {
|
|
ratio /= 2.5;
|
|
}
|
|
let nDamBaseLow = Math.floor(low * matmult);
|
|
let nDamBaseHigh = Math.floor(high * matmult);
|
|
nDamBaseLow = Math.floor(nDamBaseLow * ratio);
|
|
nDamBaseHigh = Math.floor(nDamBaseHigh * ratio);
|
|
let elemDamBaseLow = [0,0,0,0,0];
|
|
let elemDamBaseHigh = [0,0,0,0,0];
|
|
/*
|
|
* APPLY POWDERS - MAY NOT BE CORRECT
|
|
*/
|
|
let powders = [];
|
|
for (let n in this.ingreds) {
|
|
let ingred = this.ingreds[n];
|
|
if (ingred.get("isPowder")) {
|
|
powders.push(ingred.get("pid"));
|
|
}
|
|
}
|
|
// for (const p of powders) {
|
|
// /* Powders as ingredients in crafted weapons are different than powders applied to non-crafted weapons. Thanks to nbcss for showing me the math.
|
|
// */
|
|
// let powder = powderStats[p]; //use min, max, and convert
|
|
// let element = Math.floor((p+0.01)/6); //[0,4], the +0.01 attempts to prevent division error
|
|
// let diffLow = Math.floor(nDamBaseLow * powder.convert/100);
|
|
// nDamBaseLow -= diffLow;
|
|
// elemDamBaseLow[element] += diffLow + Math.floor( (powder.min + powder.max) / 2 );
|
|
// let diffHigh = Math.floor(nDamBaseHigh * powder.convert/100);
|
|
// nDamBaseHigh -= diffHigh;
|
|
// elemDamBaseHigh[element] += diffHigh + Math.floor( (powder.min + powder.max) / 2 );
|
|
// }
|
|
statMap.set("ingredPowders", powders);
|
|
|
|
/* I create a separate variable for each low damage range because we need one damage range to calculate damage with, and it's custom to use the maximum range of the range range.
|
|
*/
|
|
let low1 = Math.floor(nDamBaseLow * 0.9);
|
|
let low2 = Math.floor(nDamBaseLow * 1.1);
|
|
let high1 = Math.floor(nDamBaseHigh * 0.9);
|
|
let high2 = Math.floor(nDamBaseHigh * 1.1);
|
|
statMap.set("nDamBaseLow", nDamBaseLow);
|
|
statMap.set("nDamBaseHigh", nDamBaseHigh);
|
|
statMap.set("nDamLow", low1+"-"+low2);
|
|
statMap.set("nDam", high1+"-"+high2);
|
|
for (const e in skp_elements) {
|
|
statMap.set(skp_elements[e]+"DamBaseLow", elemDamBaseLow[e]);
|
|
statMap.set(skp_elements[e]+"DamBaseHigh", elemDamBaseHigh[e]);
|
|
low1 = Math.floor(elemDamBaseLow[e] * 0.9);
|
|
low2 = Math.floor(elemDamBaseLow[e] * 1.1);
|
|
high1 = Math.floor(elemDamBaseHigh[e] * 0.9);
|
|
high2 = Math.floor(elemDamBaseHigh[e] * 1.1);
|
|
statMap.set(skp_elements[e]+"DamLow", low1+"-"+low2);
|
|
statMap.set(skp_elements[e]+"Dam",high1+"-"+high2);
|
|
}
|
|
} else if (statMap.get("category") === "armor") {
|
|
low = Math.floor(low * matmult);
|
|
high = Math.floor(high * matmult);
|
|
statMap.set("hp",high);
|
|
statMap.set("hpLow",low);
|
|
}
|
|
if (statMap.get("category") === "armor" || statMap.get("category") == "accessory") {
|
|
for (let n in this.ingreds) {
|
|
let ingred = this.ingreds[n];
|
|
if (ingred.get("isPowder")) {
|
|
let powder = powderStats[ingred.get("pid")];
|
|
let name = powderNames.get(ingred.get("pid"));
|
|
statMap.set(name.charAt(0) + "Def", (statMap.get(name.charAt(0)+"Def") || 0) + powder["defPlus"]);
|
|
statMap.set(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5] + "Def", (statMap.get(skp_elements[(skp_elements.indexOf(name.charAt(0)) + 4 )% 5]+"Def") || 0) - powder["defMinus"]);
|
|
}
|
|
}
|
|
}
|
|
/* END SECTION */
|
|
|
|
|
|
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();
|
|
statMap.set("ingredEffectiveness", 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" && !consumableTypes.includes(statMap.get("type"))) { //consumables NEVER get reqs
|
|
if (!ingred.get("isPowder")) {
|
|
statMap.set(key, Math.round(statMap.get(key) + value*eff_mult));
|
|
} else {
|
|
statMap.set(key, Math.round(statMap.get(key) + value));
|
|
}
|
|
} else { //durability, NOT affected by effectiveness
|
|
statMap.set("durability", statMap.get("durability").map(x => x + value));
|
|
}
|
|
}
|
|
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("maxRolls")) {
|
|
if (value && value != 0) {
|
|
let rolls = [ingred.get("ids").get("minRolls").get(key), value];
|
|
rolls = rolls.map(x => Math.floor(x * eff_mult)).sort(function(a, b){return a - b});
|
|
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 d in statMap.get("durability")) {
|
|
if(statMap.get("durability")[d] < 1) { statMap.get("durability")[d] = 1;}
|
|
else {
|
|
statMap.get("durability")[d] = Math.floor(statMap.get("durability")[d]);
|
|
}
|
|
}
|
|
for (const d in statMap.get("duration")) {
|
|
if(!allNone && statMap.get("duration")[d] < 10) { statMap.get("duration")[d] = 10;}
|
|
}
|
|
if(statMap.has("charges") && statMap.get("charges") < 1 ) { statMap.set("charges",1)}
|
|
|
|
statMap.set("reqs",[0,0,0,0,0]);
|
|
statMap.set("skillpoints", [0,0,0,0,0]);
|
|
for (const e in skp_order) {
|
|
statMap.set(skp_order[e], statMap.get("maxRolls").has(skp_order[e]) ? statMap.get("maxRolls").get(skp_order[e]) : 0);
|
|
statMap.get("skillpoints")[e] = statMap.get("maxRolls").has(skp_order[e]) ? statMap.get("maxRolls").get(skp_order[e]) : 0;
|
|
statMap.get("reqs")[e] = statMap.has(skp_order[e]+"Req") && !consumableTypes.includes(statMap.get("type"))? statMap.get(skp_order[e]+"Req") : 0;
|
|
}
|
|
for (const id of rolledIDs) {
|
|
if (statMap.get("minRolls").has(id)) {
|
|
continue;
|
|
} else {
|
|
statMap.get("minRolls").set(id,0);
|
|
statMap.get("maxRolls").set(id,0);
|
|
}
|
|
}
|
|
|
|
statMap.set("crafted", true);
|
|
this.statMap = statMap;
|
|
}
|
|
|
|
copy() {
|
|
return new Craft(this.recipe, this.mat_tiers, this.ingreds, this.atkSpd, this.hash.slice(3));
|
|
}
|
|
}
|