2021-01-10 10:02:23 +00:00
2021-03-31 06:44:56 +00:00
2021-01-12 22:49:57 +00:00
const classDefenseMultipliers = new Map ( [ [ "relik" , 0.50 ] , [ "bow" , 0.60 ] , [ "wand" , 0.80 ] , [ "dagger" , 1.0 ] , [ "spear" , 1.20 ] ] ) ;
2021-01-10 10:02:23 +00:00
2021-01-17 21:01:20 +00:00
/ * *
* @ description Error to catch items that don ' t exist .
* @ module ItemNotFound
* /
class ItemNotFound {
/ * *
* @ class
* @ param { String } item the item name entered
* @ param { String } type the type of item
* @ param { Boolean } genElement whether to generate an element from inputs
* @ param { String } override override for item type
* /
constructor ( item , type , genElement , override ) {
/ * *
* @ public
* @ type { String }
* /
this . message = ` Cannot find ${ override || type } named ${ item } ` ;
if ( genElement )
/ * *
* @ public
* @ type { Element }
* /
this . element = document . getElementById ( ` ${ type } -choice ` ) . parentElement . querySelectorAll ( "p.error" ) [ 0 ] ;
else
this . element = document . createElement ( "div" ) ;
}
2021-01-07 00:08:19 +00:00
}
2021-01-17 21:01:20 +00:00
/ * *
* @ description Error to catch incorrect input .
* @ module IncorrectInput
* /
class IncorrectInput {
/ * *
* @ class
* @ param { String } input the inputted text
* @ param { String } format the correct format
* @ param { String } sibling the id of the error node ' s sibling
* /
constructor ( input , format , sibling ) {
/ * *
* @ public
* @ type { String }
* /
this . message = ` ${ input } is incorrect. Example: ${ format } ` ;
/ * *
* @ public
* @ type { String }
* /
this . id = sibling ;
2021-01-07 00:08:19 +00:00
}
}
2021-01-17 21:01:20 +00:00
/ * *
* @ description Error that inputs an array of items to generate errors of .
* @ module ListError
* @ extends Error
* /
class ListError extends Error {
/ * *
* @ class
* @ param { Array } errors array of errors
* /
constructor ( errors ) {
let ret = [ ] ;
if ( typeof errors [ 0 ] == "string" ) {
super ( errors [ 0 ] ) ;
} else {
super ( errors [ 0 ] . message ) ;
}
for ( let i of errors ) {
if ( typeof i == "string" ) {
ret . push ( new Error ( i ) ) ;
} else {
ret . push ( i ) ;
}
}
/ * *
* @ public
* @ type { Object [ ] }
* /
this . errors = ret ;
2021-01-07 00:08:19 +00:00
}
}
2021-01-07 00:02:10 +00:00
/ * C l a s s t h a t r e p r e s e n t s a w y n n p l a y e r ' s b u i l d .
* /
class Build {
2021-01-17 21:01:20 +00:00
/ * *
* @ description Construct a build .
* @ param { Number } level : Level of the player .
* @ param { String [ ] } equipment : List of equipment names that make up the build .
2021-03-14 07:55:08 +00:00
* In order : boots , Chestplate , Leggings , Boots , Ring1 , Ring2 , Brace , Neck , Weapon .
2021-01-17 21:01:20 +00:00
* @ param { Number [ ] } powders : Powder application . List of lists of integers ( powder IDs ) .
2021-03-14 07:55:08 +00:00
* In order : boots , Chestplate , Leggings , Boots , Weapon .
2021-01-17 21:01:20 +00:00
* @ param { Object [ ] } inputerrors : List of instances of error - like classes .
2021-01-09 08:52:58 +00:00
* /
2021-01-17 21:06:40 +00:00
constructor ( level , equipment , powders , externalStats , inputerrors = [ ] ) {
2021-01-17 21:01:20 +00:00
let errors = inputerrors ;
2021-03-14 07:55:08 +00:00
//this contains the Craft objects, if there are any crafted items. this.boots, etc. will contain the statMap of the Craft (which is built to be an expandedItem).
2021-01-30 08:50:25 +00:00
this . craftedItems = [ ] ;
2021-03-14 07:55:08 +00:00
this . customItems = [ ] ;
2021-01-08 20:17:37 +00:00
// NOTE: powders is just an array of arrays of powder IDs. Not powder objects.
2021-01-09 19:50:36 +00:00
this . powders = powders ;
2021-01-09 03:53:57 +00:00
if ( itemMap . get ( equipment [ 0 ] ) && itemMap . get ( equipment [ 0 ] ) . type === "helmet" ) {
const helmet = itemMap . get ( equipment [ 0 ] ) ;
2021-01-08 20:17:37 +00:00
this . powders [ 0 ] = this . powders [ 0 ] . slice ( 0 , helmet . slots ) ;
2021-01-09 00:56:07 +00:00
this . helmet = expandItem ( helmet , this . powders [ 0 ] ) ;
2021-01-30 11:06:16 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
//let boots = getCraftFromHash(equipment[0]) ? getCraftFromHash(equipment[0]) : (getCustomFromHash(equipment[0])? getCustomFromHash(equipment[0]) : undefined);
let helmet = getCustomFromHash ( equipment [ 0 ] ) ? getCustomFromHash ( equipment [ 0 ] ) : ( getCraftFromHash ( equipment [ 0 ] ) ? getCraftFromHash ( equipment [ 0 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( helmet . statMap . get ( "type" ) !== "helmet" ) {
throw new Error ( "Not a helmet" ) ;
}
2021-03-21 05:31:56 +00:00
this . powders [ 0 ] = this . powders [ 0 ] . slice ( 0 , helmet . statMap . get ( "slots" ) ) ;
2021-01-30 08:50:25 +00:00
helmet . statMap . set ( "powders" , this . powders [ 0 ] . slice ( ) ) ;
helmet . applyPowders ( ) ;
this . helmet = helmet . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . helmet . get ( "custom" ) ) {
this . customItems . push ( helmet ) ;
} else if ( this . helmet . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( helmet ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
//console.log(Error); //fix
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 ) ) ;
}
2021-01-09 03:53:57 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 1 ] ) && itemMap . get ( equipment [ 1 ] ) . type === "chestplate" ) {
2021-01-09 03:53:57 +00:00
const chestplate = itemMap . get ( equipment [ 1 ] ) ;
2021-01-08 20:17:37 +00:00
this . powders [ 1 ] = this . powders [ 1 ] . slice ( 0 , chestplate . slots ) ;
2021-01-09 00:56:07 +00:00
this . chestplate = expandItem ( chestplate , this . powders [ 1 ] ) ;
2021-01-30 11:06:16 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let chestplate = getCustomFromHash ( equipment [ 1 ] ) ? getCustomFromHash ( equipment [ 1 ] ) : ( getCraftFromHash ( equipment [ 1 ] ) ? getCraftFromHash ( equipment [ 1 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( chestplate . statMap . get ( "type" ) !== "chestplate" ) {
throw new Error ( "Not a chestplate" ) ;
}
2021-03-21 05:31:56 +00:00
this . powders [ 1 ] = this . powders [ 1 ] . slice ( 0 , chestplate . statMap . get ( "slots" ) ) ;
2021-01-30 08:50:25 +00:00
chestplate . statMap . set ( "powders" , this . powders [ 1 ] . slice ( ) ) ;
chestplate . applyPowders ( ) ;
this . chestplate = chestplate . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . chestplate . get ( "custom" ) ) {
this . customItems . push ( chestplate ) ;
} else if ( this . chestplate . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( chestplate ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
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 ) ) ;
}
2021-01-09 03:53:57 +00:00
}
2021-01-30 11:06:16 +00:00
if ( itemMap . get ( equipment [ 2 ] ) && itemMap . get ( equipment [ 2 ] ) . type === "leggings" ) {
2021-01-09 03:53:57 +00:00
const leggings = itemMap . get ( equipment [ 2 ] ) ;
2021-01-08 20:17:37 +00:00
this . powders [ 2 ] = this . powders [ 2 ] . slice ( 0 , leggings . slots ) ;
2021-01-09 00:56:07 +00:00
this . leggings = expandItem ( leggings , this . powders [ 2 ] ) ;
2021-01-30 11:06:16 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let leggings = getCustomFromHash ( equipment [ 2 ] ) ? getCustomFromHash ( equipment [ 2 ] ) : ( getCraftFromHash ( equipment [ 2 ] ) ? getCraftFromHash ( equipment [ 2 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( leggings . statMap . get ( "type" ) !== "leggings" ) {
throw new Error ( "Not a leggings" ) ;
}
2021-03-21 05:31:56 +00:00
this . powders [ 2 ] = this . powders [ 2 ] . slice ( 0 , leggings . statMap . get ( "slots" ) ) ;
2021-01-30 08:50:25 +00:00
leggings . statMap . set ( "powders" , this . powders [ 2 ] . slice ( ) ) ;
leggings . applyPowders ( ) ;
this . leggings = leggings . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . leggings . get ( "custom" ) ) {
this . customItems . push ( leggings ) ;
} else if ( this . leggings . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( leggings ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
const leggings = itemMap . get ( "No Leggings" ) ;
this . powders [ 2 ] = this . powders [ 2 ] . slice ( 0 , leggings . slots ) ;
this . leggings = expandItem ( leggings , this . powders [ 2 ] ) ;
errors . push ( new ItemNotFound ( equipment [ 2 ] , "leggings" , true ) ) ;
}
2021-01-09 03:53:57 +00:00
}
2021-01-30 11:06:16 +00:00
if ( itemMap . get ( equipment [ 3 ] ) && itemMap . get ( equipment [ 3 ] ) . type === "boots" ) {
2021-01-09 03:53:57 +00:00
const boots = itemMap . get ( equipment [ 3 ] ) ;
2021-01-08 20:17:37 +00:00
this . powders [ 3 ] = this . powders [ 3 ] . slice ( 0 , boots . slots ) ;
2021-01-09 00:56:07 +00:00
this . boots = expandItem ( boots , this . powders [ 3 ] ) ;
2021-01-30 11:06:16 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let boots = getCustomFromHash ( equipment [ 3 ] ) ? getCustomFromHash ( equipment [ 3 ] ) : ( getCraftFromHash ( equipment [ 3 ] ) ? getCraftFromHash ( equipment [ 3 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( boots . statMap . get ( "type" ) !== "boots" ) {
throw new Error ( "Not a boots" ) ;
}
2021-03-21 05:31:56 +00:00
this . powders [ 3 ] = this . powders [ 3 ] . slice ( 0 , boots . statMap . get ( "slots" ) ) ;
2021-01-30 08:50:25 +00:00
boots . statMap . set ( "powders" , this . powders [ 3 ] . slice ( ) ) ;
boots . applyPowders ( ) ;
this . boots = boots . statMap ;
2021-02-20 05:22:19 +00:00
console . log ( boots ) ;
2021-03-14 07:55:08 +00:00
if ( this . boots . get ( "custom" ) ) {
this . customItems . push ( boots ) ;
} else if ( this . boots . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( boots ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
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 ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 4 ] ) && itemMap . get ( equipment [ 4 ] ) . type === "ring" ) {
2021-01-09 03:53:57 +00:00
const ring = itemMap . get ( equipment [ 4 ] ) ;
2021-01-09 19:50:36 +00:00
this . ring1 = expandItem ( ring , [ ] ) ;
2021-01-07 00:02:10 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let ring = getCustomFromHash ( equipment [ 4 ] ) ? getCustomFromHash ( equipment [ 4 ] ) : ( getCraftFromHash ( equipment [ 4 ] ) ? getCraftFromHash ( equipment [ 4 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( ring . statMap . get ( "type" ) !== "ring" ) {
throw new Error ( "Not a ring" ) ;
}
2021-01-30 08:50:25 +00:00
this . ring1 = ring . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . ring1 . get ( "custom" ) ) {
this . customItems . push ( ring ) ;
} else if ( this . ring1 . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( ring ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
const ring = itemMap . get ( "No Ring 1" ) ;
this . ring1 = expandItem ( ring , [ ] ) ;
errors . push ( new ItemNotFound ( equipment [ 4 ] , "ring1" , true , "ring" ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 5 ] ) && itemMap . get ( equipment [ 5 ] ) . type === "ring" ) {
2021-01-09 03:53:57 +00:00
const ring = itemMap . get ( equipment [ 5 ] ) ;
2021-01-09 19:50:36 +00:00
this . ring2 = expandItem ( ring , [ ] ) ;
2021-01-07 00:02:10 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let ring = getCustomFromHash ( equipment [ 5 ] ) ? getCustomFromHash ( equipment [ 5 ] ) : ( getCraftFromHash ( equipment [ 5 ] ) ? getCraftFromHash ( equipment [ 5 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( ring . statMap . get ( "type" ) !== "ring" ) {
throw new Error ( "Not a ring" ) ;
}
2021-01-30 08:50:25 +00:00
this . ring2 = ring . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . ring2 . get ( "custom" ) ) {
this . customItems . push ( ring ) ;
} else if ( this . ring2 . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( ring ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
const ring = itemMap . get ( "No Ring 2" ) ;
this . ring2 = expandItem ( ring , [ ] ) ;
errors . push ( new ItemNotFound ( equipment [ 5 ] , "ring2" , true , "ring" ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 6 ] ) && itemMap . get ( equipment [ 6 ] ) . type === "bracelet" ) {
2021-01-09 03:53:57 +00:00
const bracelet = itemMap . get ( equipment [ 6 ] ) ;
2021-01-09 19:50:36 +00:00
this . bracelet = expandItem ( bracelet , [ ] ) ;
2021-01-07 00:02:10 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let bracelet = getCustomFromHash ( equipment [ 6 ] ) ? getCustomFromHash ( equipment [ 6 ] ) : ( getCraftFromHash ( equipment [ 6 ] ) ? getCraftFromHash ( equipment [ 6 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( bracelet . statMap . get ( "type" ) !== "bracelet" ) {
throw new Error ( "Not a bracelet" ) ;
}
2021-01-30 08:50:25 +00:00
this . bracelet = bracelet . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . bracelet . get ( "custom" ) ) {
this . customItems . push ( bracelet ) ;
} else if ( this . bracelet . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( bracelet ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
const bracelet = itemMap . get ( "No Bracelet" ) ;
this . bracelet = expandItem ( bracelet , [ ] ) ;
errors . push ( new ItemNotFound ( equipment [ 6 ] , "bracelet" , true ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 7 ] ) && itemMap . get ( equipment [ 7 ] ) . type === "necklace" ) {
2021-01-09 03:53:57 +00:00
const necklace = itemMap . get ( equipment [ 7 ] ) ;
2021-01-09 19:50:36 +00:00
this . necklace = expandItem ( necklace , [ ] ) ;
2021-01-07 00:02:10 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let necklace = getCustomFromHash ( equipment [ 7 ] ) ? getCustomFromHash ( equipment [ 7 ] ) : ( getCraftFromHash ( equipment [ 7 ] ) ? getCraftFromHash ( equipment [ 7 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( necklace . statMap . get ( "type" ) !== "necklace" ) {
throw new Error ( "Not a necklace" ) ;
}
2021-01-30 08:50:25 +00:00
this . necklace = necklace . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . necklace . get ( "custom" ) ) {
this . customItems . push ( necklace ) ;
} else if ( this . necklace . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( necklace ) ;
}
2021-01-30 08:50:25 +00:00
} catch ( Error ) {
const necklace = itemMap . get ( "No Necklace" ) ;
this . necklace = expandItem ( necklace , [ ] ) ;
errors . push ( new ItemNotFound ( equipment [ 7 ] , "necklace" , true ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-01-12 23:14:12 +00:00
if ( itemMap . get ( equipment [ 8 ] ) && itemMap . get ( equipment [ 8 ] ) . category === "weapon" ) {
2021-01-09 03:53:57 +00:00
const weapon = itemMap . get ( equipment [ 8 ] ) ;
2021-01-08 20:17:37 +00:00
this . powders [ 4 ] = this . powders [ 4 ] . slice ( 0 , weapon . slots ) ;
2021-01-09 00:56:07 +00:00
this . weapon = expandItem ( weapon , this . powders [ 4 ] ) ;
2021-01-18 10:14:08 +00:00
if ( equipment [ 8 ] !== "No Weapon" ) {
document . getElementsByClassName ( "powder-specials" ) [ 0 ] . style . display = "grid" ;
} else {
document . getElementsByClassName ( "powder-specials" ) [ 0 ] . style . display = "none" ;
}
2021-01-07 00:02:10 +00:00
} else {
2021-01-30 08:50:25 +00:00
try {
2021-03-14 07:55:08 +00:00
let weapon = getCustomFromHash ( equipment [ 8 ] ) ? getCustomFromHash ( equipment [ 8 ] ) : ( getCraftFromHash ( equipment [ 8 ] ) ? getCraftFromHash ( equipment [ 8 ] ) : undefined ) ;
2021-01-30 11:15:31 +00:00
if ( weapon . statMap . get ( "category" ) !== "weapon" ) {
throw new Error ( "Not a weapon" ) ;
}
2021-01-30 08:50:25 +00:00
this . weapon = weapon . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . weapon . get ( "custom" ) ) {
this . customItems . push ( weapon ) ;
} else if ( this . weapon . get ( "crafted" ) ) { //customs can also be crafted, but custom takes priority.
this . craftedItems . push ( weapon ) ;
}
2021-03-21 05:31:56 +00:00
this . powders [ 4 ] = this . powders [ 4 ] . slice ( 0 , this . weapon . get ( "slots" ) ) ;
2021-01-30 08:50:25 +00:00
this . weapon . set ( "powders" , this . powders [ 4 ] . slice ( ) ) ;
document . getElementsByClassName ( "powder-specials" ) [ 0 ] . style . display = "grid" ;
} catch ( Error ) {
const weapon = itemMap . get ( "No Weapon" ) ;
this . powders [ 4 ] = this . powders [ 4 ] . slice ( 0 , weapon . slots ) ;
this . weapon = expandItem ( weapon , this . powders [ 4 ] ) ;
document . getElementsByClassName ( "powder-specials" ) [ 0 ] . style . display = "none" ;
errors . push ( new ItemNotFound ( equipment [ 8 ] , "weapon" , true ) ) ;
}
2021-01-07 00:02:10 +00:00
}
2021-03-14 07:55:08 +00:00
//console.log(this.craftedItems)
2021-01-17 21:01:20 +00:00
if ( level < 1 ) { //Should these be constants?
2021-01-07 00:02:10 +00:00
this . level = 1 ;
2021-01-17 21:01:20 +00:00
} else if ( level > 106 ) {
2021-01-07 00:02:10 +00:00
this . level = 106 ;
2021-01-17 21:01:20 +00:00
} else if ( level <= 106 && level >= 1 ) {
2021-01-07 00:02:10 +00:00
this . level = level ;
2021-01-17 21:01:20 +00:00
} 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." ) ;
2021-01-07 00:02:10 +00:00
}
2021-01-17 21:01:20 +00:00
document . getElementById ( "level-choice" ) . value = this . level ;
2021-01-07 06:41:41 +00:00
this . availableSkillpoints = levelToSkillPoints ( this . level ) ;
2021-01-09 00:56:07 +00:00
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 ] ) ;
2021-01-07 06:41:41 +00:00
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
2021-01-09 00:56:07 +00:00
let result = calculate _skillpoints ( this . equipment , this . weapon ) ;
2021-01-20 05:59:17 +00:00
console . log ( result ) ;
2021-01-07 06:41:41 +00:00
this . equip _order = result [ 0 ] ;
this . base _skillpoints = result [ 1 ] ;
this . total _skillpoints = result [ 2 ] ;
this . assigned _skillpoints = result [ 3 ] ;
2021-01-10 04:29:07 +00:00
this . activeSetCounts = result [ 4 ] ;
2021-01-14 03:17:01 +00:00
2021-01-08 20:17:37 +00:00
// For strength boosts like warscream, vanish, etc.
2021-01-09 00:56:07 +00:00
this . damageMultiplier = 1.0 ;
2021-01-14 06:58:32 +00:00
this . defenseMultiplier = 1.0 ;
2021-01-08 20:17:37 +00:00
2021-01-14 03:17:01 +00:00
// For other external boosts ;-;
this . externalStats = externalStats ;
2021-01-08 04:31:29 +00:00
this . initBuildStats ( ) ;
2021-01-17 21:01:20 +00:00
// 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 ;
2021-01-07 00:02:10 +00:00
}
/ * R e t u r n s b u i l d i n s t r i n g f o r m a t
2021-01-07 06:41:41 +00:00
* /
2021-01-07 00:02:10 +00:00
toString ( ) {
2021-01-19 17:32:27 +00:00
return [ this . equipment , this . weapon ] . flat ( ) ;
2021-01-07 00:02:10 +00:00
}
2021-01-07 06:41:41 +00:00
/* Getters */
2021-01-07 21:32:36 +00:00
/ * G e t t o t a l h e a l t h f o r b u i l d .
* /
2021-01-09 08:52:58 +00:00
getSpellCost ( spellIdx , cost ) {
cost = Math . ceil ( cost * ( 1 - skillPointsToPercentage ( this . total _skillpoints [ 2 ] ) ) ) ;
cost += this . statMap . get ( "spRaw" + spellIdx ) ;
2021-01-15 18:49:24 +00:00
return Math . max ( 1 , Math . floor ( cost * ( 1 + this . statMap . get ( "spPct" + spellIdx ) / 100 ) ) ) ;
2021-01-09 08:52:58 +00:00
}
2021-01-09 00:56:07 +00:00
2021-01-08 02:34:07 +00:00
/ * G e t m e l e e s t a t s f o r b u i l d .
Returns an array in the order :
2021-01-07 21:32:36 +00:00
* /
2021-01-08 02:34:07 +00:00
getMeleeStats ( ) {
2021-01-08 05:36:57 +00:00
const stats = this . statMap ;
2021-03-14 07:55:08 +00:00
if ( this . weapon . get ( "tier" ) === "Crafted" ) {
stats . set ( "damageBases" , [ this . weapon . get ( "nDamBaseHigh" ) , this . weapon . get ( "eDamBaseHigh" ) , this . weapon . get ( "tDamBaseHigh" ) , this . weapon . get ( "wDamBaseHigh" ) , this . weapon . get ( "fDamBaseHigh" ) , this . weapon . get ( "aDamBaseHigh" ) ] ) ;
}
2021-01-08 05:36:57 +00:00
let adjAtkSpd = attackSpeeds . indexOf ( stats . get ( "atkSpd" ) ) + stats . get ( "atkTier" ) ;
if ( adjAtkSpd > 6 ) {
adjAtkSpd = 6 ;
} else if ( adjAtkSpd < 0 ) {
adjAtkSpd = 0 ;
}
2021-03-25 07:18:33 +00:00
let damage _mult = 1 ;
if ( this . weapon . get ( "type" ) === "relik" ) {
damage _mult = 0.99 ; // CURSE YOU WYNNCRAFT
2021-03-31 06:44:56 +00:00
//One day we will create WynnWynn and no longer have shaman 99% melee injustice.
//In all seriousness 99% is because wynn uses 0.33 to estimate dividing the damage by 3 to split damage between 3 beams.
2021-03-25 07:18:33 +00:00
}
// 0spellmult for melee damage.
let results = calculateSpellDamage ( stats , [ 100 , 0 , 0 , 0 , 0 , 0 ] , stats . get ( "mdRaw" ) , stats . get ( "mdPct" ) + this . externalStats . get ( "mdPct" ) , 0 , this . weapon , this . total _skillpoints , damage _mult * this . damageMultiplier , this . externalStats ) ;
2021-01-11 02:58:39 +00:00
let dex = this . total _skillpoints [ 1 ] ;
2021-01-09 03:53:57 +00:00
2021-01-09 00:56:07 +00:00
let totalDamNorm = results [ 0 ] ;
let totalDamCrit = results [ 1 ] ;
2021-01-11 02:58:39 +00:00
totalDamNorm . push ( 1 - skillPointsToPercentage ( dex ) ) ;
totalDamCrit . push ( skillPointsToPercentage ( dex ) ) ;
2021-01-09 00:56:07 +00:00
let damages _results = results [ 2 ] ;
2021-01-11 02:58:39 +00:00
2021-01-12 22:49:57 +00:00
let singleHitTotal = ( ( totalDamNorm [ 0 ] + totalDamNorm [ 1 ] ) * ( totalDamNorm [ 2 ] )
+ ( totalDamCrit [ 0 ] + totalDamCrit [ 1 ] ) * ( totalDamCrit [ 2 ] ) ) / 2 ;
2021-01-08 04:31:29 +00:00
2021-01-08 02:34:07 +00:00
//Now do math
2021-01-08 05:36:57 +00:00
let normDPS = ( totalDamNorm [ 0 ] + totalDamNorm [ 1 ] ) / 2 * baseDamageMultiplier [ adjAtkSpd ] ;
let critDPS = ( totalDamCrit [ 0 ] + totalDamCrit [ 1 ] ) / 2 * baseDamageMultiplier [ adjAtkSpd ] ;
2021-01-09 00:56:07 +00:00
let avgDPS = ( normDPS * ( 1 - skillPointsToPercentage ( dex ) ) ) + ( critDPS * ( skillPointsToPercentage ( dex ) ) ) ;
2021-01-12 22:49:57 +00:00
//[[n n n n] [e e e e] [t t t t] [w w w w] [f f f f] [a a a a] [lowtotal hightotal normalChance] [critlowtotal crithightotal critChance] normalDPS critCPS averageDPS adjAttackSpeed, singleHit]
2021-03-31 06:44:56 +00:00
return damages _results . concat ( [ totalDamNorm , totalDamCrit , normDPS , critDPS , avgDPS , adjAtkSpd , singleHitTotal ] ) . concat ( results [ 3 ] ) ;
2021-01-07 21:32:36 +00:00
}
2021-01-10 10:02:23 +00:00
/ *
Get all defensive stats for this build .
* /
getDefenseStats ( ) {
const stats = this . statMap ;
let defenseStats = [ ] ;
let def _pct = skillPointsToPercentage ( this . total _skillpoints [ 3 ] ) ;
let agi _pct = skillPointsToPercentage ( this . total _skillpoints [ 4 ] ) ;
//total hp
let totalHp = stats . get ( "hp" ) + stats . get ( "hpBonus" ) ;
2021-01-10 12:54:25 +00:00
if ( totalHp < 5 ) totalHp = 5 ;
2021-01-10 10:02:23 +00:00
defenseStats . push ( totalHp ) ;
//EHP
2021-01-11 00:46:30 +00:00
let ehp = [ totalHp , totalHp ] ;
2021-01-10 10:02:23 +00:00
let defMult = classDefenseMultipliers . get ( this . weapon . get ( "type" ) ) ;
2021-01-14 06:58:32 +00:00
ehp [ 0 ] /= ( ( 1 - def _pct ) * ( 1 - agi _pct ) * ( 2 - defMult ) * ( 2 - this . defenseMultiplier ) ) ;
ehp [ 1 ] /= ( ( 1 - def _pct ) * ( 2 - defMult ) * ( 2 - this . defenseMultiplier ) ) ;
2021-01-10 10:02:23 +00:00
defenseStats . push ( ehp ) ;
//HPR
let totalHpr = rawToPct ( stats . get ( "hprRaw" ) , stats . get ( "hprPct" ) / 100. ) ;
defenseStats . push ( totalHpr ) ;
//EHPR
2021-01-11 00:46:30 +00:00
let ehpr = [ totalHpr , totalHpr ] ;
2021-01-14 06:58:32 +00:00
ehpr [ 0 ] /= ( ( 1 - def _pct ) * ( 1 - agi _pct ) * ( 2 - defMult ) * ( 2 - this . defenseMultiplier ) ) ;
ehpr [ 1 ] /= ( ( 1 - def _pct ) * ( 2 - defMult ) * ( 2 - this . defenseMultiplier ) ) ;
2021-01-10 10:02:23 +00:00
defenseStats . push ( ehpr ) ;
//skp stats
2021-01-14 06:58:32 +00:00
defenseStats . push ( [ ( 1 - ( ( 1 - def _pct ) * ( 2 - this . defenseMultiplier ) ) ) * 100 , agi _pct * 100 ] ) ;
2021-01-10 10:02:23 +00:00
//eledefs - TODO POWDERS
let eledefs = [ 0 , 0 , 0 , 0 , 0 ] ;
for ( const i in skp _elements ) { //kinda jank but ok
eledefs [ i ] = rawToPct ( stats . get ( skp _elements [ i ] + "Def" ) , stats . get ( skp _elements [ i ] + "DefPct" ) / 100. ) ;
}
defenseStats . push ( eledefs ) ;
2021-01-11 00:46:30 +00:00
//[total hp, [ehp w/ agi, ehp w/o agi], total hpr, [ehpr w/ agi, ehpr w/o agi], [def%, agi%], [edef,tdef,wdef,fdef,adef]]
2021-01-10 10:02:23 +00:00
return defenseStats ;
}
2021-01-08 05:36:57 +00:00
/ * G e t a l l s t a t s f o r t h i s b u i l d . S t o r e s i n t h i s . s t a t M a p .
2021-01-07 21:32:36 +00:00
@ pre The build itself should be valid . No checking of validity of pieces is done here .
* /
2021-01-08 04:31:29 +00:00
initBuildStats ( ) {
let staticIDs = [ "hp" , "eDef" , "tDef" , "wDef" , "fDef" , "aDef" ] ;
2021-01-07 21:32:36 +00:00
//Create a map of this build's stats
let statMap = new Map ( ) ;
2021-01-08 04:31:29 +00:00
for ( const staticID of staticIDs ) {
statMap . set ( staticID , 0 ) ;
2021-01-07 21:32:36 +00:00
}
2021-01-30 08:50:25 +00:00
statMap . set ( "hp" , levelToHPBase ( this . level ) ) ;
2021-01-14 06:58:32 +00:00
2021-01-30 12:03:40 +00:00
let major _ids = new Set ( ) ;
2021-01-09 00:56:07 +00:00
for ( const item of this . items ) {
2021-01-08 04:31:29 +00:00
for ( let [ id , value ] of item . get ( "maxRolls" ) ) {
statMap . set ( id , ( statMap . get ( id ) || 0 ) + value ) ;
}
for ( const staticID of staticIDs ) {
2021-01-10 13:18:53 +00:00
if ( item . get ( staticID ) ) {
statMap . set ( staticID , statMap . get ( staticID ) + item . get ( staticID ) ) ;
}
2021-01-07 21:32:36 +00:00
}
2021-01-30 12:03:40 +00:00
if ( item . get ( "majorIds" ) ) {
for ( const majorID of item . get ( "majorIds" ) ) {
major _ids . add ( majorID ) ;
}
}
2021-01-07 21:32:36 +00:00
}
2021-01-30 12:03:40 +00:00
statMap . set ( "activeMajorIDs" , major _ids ) ;
2021-01-10 04:29:07 +00:00
for ( const [ setName , count ] of this . activeSetCounts ) {
2021-01-10 03:40:15 +00:00
const bonus = sets [ setName ] . bonuses [ count - 1 ] ;
for ( const id in bonus ) {
2021-01-10 04:29:07 +00:00
if ( skp _order . includes ( id ) ) {
// pass. Don't include skillpoints in ids
}
else {
statMap . set ( id , ( statMap . get ( id ) || 0 ) + bonus [ id ] ) ;
}
2021-01-10 03:40:15 +00:00
}
}
2021-01-18 14:18:14 +00:00
statMap . set ( "poisonPct" , 100 ) ;
2021-01-07 06:41:41 +00:00
2021-01-08 04:31:29 +00:00
// The stuff relevant for damage calculation!!! @ferricles
2021-01-09 00:56:07 +00:00
statMap . set ( "atkSpd" , this . weapon . get ( "atkSpd" ) ) ;
2021-01-14 06:58:32 +00:00
2021-01-14 03:17:01 +00:00
for ( const x of skp _elements ) {
this . externalStats . set ( x + "DamPct" , 0 ) ;
}
this . externalStats . set ( "mdPct" , 0 ) ;
this . externalStats . set ( "sdPct" , 0 ) ;
this . externalStats . set ( "damageBonus" , [ 0 , 0 , 0 , 0 , 0 ] ) ;
this . externalStats . set ( "defBonus" , [ 0 , 0 , 0 , 0 , 0 ] ) ;
2021-01-14 06:58:32 +00:00
this . externalStats . set ( "poisonPct" , 0 ) ;
2021-01-08 04:31:29 +00:00
this . statMap = statMap ;
2021-01-18 14:18:14 +00:00
this . aggregateStats ( ) ;
2021-01-08 04:31:29 +00:00
}
2021-01-07 00:02:10 +00:00
2021-01-18 14:18:14 +00:00
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" ) ] ) ;
2021-03-27 18:17:58 +00:00
statMap . set ( "defMult" , classDefenseMultipliers . get ( this . weapon . get ( "type" ) ) ) ;
2021-01-18 14:18:14 +00:00
}
2021-01-07 00:02:10 +00:00
}