2021-10-17 15:53:48 +00:00
const url _tag = location . hash . slice ( 1 ) ;
// console.log(url_base);
// console.log(url_tag);
const BUILD _VERSION = "7.0.19" ;
2022-05-14 06:30:13 +00:00
// function setTitle() {
// let text;
// if (url_base.includes("hppeng-wynn")) {
// text = "WynnBuilder UNSTABLE version "+BUILD_VERSION+" (db version "+DB_VERSION+")";
// }
// else {
// text = "WynnBuilder version "+BUILD_VERSION+" (db version "+DB_VERSION+")";
// document.getElementById("header").classList.add("funnynumber");
// }
// document.getElementById("header").textContent = text;
// }
//
// setTitle();
2022-05-14 06:01:03 +00:00
2021-10-17 15:53:48 +00:00
let player _build ;
// THIS IS SUPER DANGEROUS, WE SHOULD NOT BE KEEPING THIS IN SO MANY PLACES
let editable _item _fields = [ "sdPct" , "sdRaw" , "mdPct" , "mdRaw" , "poison" , "fDamPct" , "wDamPct" , "aDamPct" , "tDamPct" , "eDamPct" , "fDefPct" , "wDefPct" , "aDefPct" , "tDefPct" , "eDefPct" , "hprRaw" , "hprPct" , "hpBonus" , "atkTier" , "spPct1" , "spRaw1" , "spPct2" , "spRaw2" , "spPct3" , "spRaw3" , "spPct4" , "spRaw4" ] ;
let editable _elems = [ ] ;
for ( let i of editable _item _fields ) {
let elem = document . getElementById ( i ) ;
elem . addEventListener ( "change" , ( event ) => {
elem . classList . add ( "highlight" ) ;
} ) ;
editable _elems . push ( elem ) ;
2022-05-16 06:50:47 +00:00
}
2021-10-17 15:53:48 +00:00
for ( let i of skp _order ) {
let elem = document . getElementById ( i + "-skp" ) ;
elem . addEventListener ( "change" , ( event ) => {
elem . classList . add ( "highlight" ) ;
2022-05-14 06:01:03 +00:00
} ) ;
2021-10-17 15:53:48 +00:00
editable _elems . push ( elem ) ;
}
function clear _highlights ( ) {
for ( let i of editable _elems ) {
i . classList . remove ( "highlight" ) ;
}
}
let equipment _fields = [
"helmet" ,
"chestplate" ,
"leggings" ,
"boots" ,
"ring1" ,
"ring2" ,
"bracelet" ,
"necklace" ,
"weapon"
] ;
2022-05-20 09:03:46 +00:00
let tome _fields = [
"weaponTome1" ,
"weaponTome2" ,
"armorTome1" ,
"armorTome2" ,
"armorTome3" ,
"armorTome4" ,
"guildTome1" ,
]
2021-10-17 15:53:48 +00:00
let equipment _names = [
"Helmet" ,
"Chestplate" ,
"Leggings" ,
"Boots" ,
"Ring 1" ,
"Ring 2" ,
"Bracelet" ,
"Necklace" ,
"Weapon"
] ;
2022-05-20 09:03:46 +00:00
let tome _names = [
"Weapon Tome" ,
"Weapon Tome" ,
"Armor Tome" ,
"Armor Tome" ,
"Armor Tome" ,
"Armor Tome" ,
"Guild Tome" ,
]
2021-10-17 15:53:48 +00:00
let equipmentInputs = equipment _fields . map ( x => x + "-choice" ) ;
2022-05-20 09:03:46 +00:00
let buildFields = equipment _fields . map ( x => x + "-tooltip" ) . concat ( tome _fields . map ( x => x + "-tooltip" ) ) ;
let tomeInputs = tome _fields . map ( x => x + "-choice" ) ;
2021-10-17 15:53:48 +00:00
let powderInputs = [
"helmet-powder" ,
"chestplate-powder" ,
"leggings-powder" ,
"boots-powder" ,
"weapon-powder" ,
] ;
function getItemNameFromID ( id ) {
if ( redirectMap . has ( id ) ) {
return getItemNameFromID ( redirectMap . get ( id ) ) ;
}
return idMap . get ( id ) ;
}
2022-05-21 02:01:53 +00:00
function getTomeNameFromID ( id ) {
if ( tomeRedirectMap . has ( id ) ) {
return getTomeNameFromID ( tomeRedirectMap . get ( id ) ) ;
}
return tomeIDMap . get ( id ) ;
}
2021-10-17 15:53:48 +00:00
function parsePowdering ( powder _info ) {
// TODO: Make this run in linear instead of quadratic time... ew
let powdering = [ ] ;
for ( let i = 0 ; i < 5 ; ++ i ) {
let powders = "" ;
let n _blocks = Base64 . toInt ( powder _info . charAt ( 0 ) ) ;
powder _info = powder _info . slice ( 1 ) ;
for ( let j = 0 ; j < n _blocks ; ++ j ) {
let block = powder _info . slice ( 0 , 5 ) ;
let six _powders = Base64 . toInt ( block ) ;
for ( let k = 0 ; k < 6 && six _powders != 0 ; ++ k ) {
powders += powderNames . get ( ( six _powders & 0x1f ) - 1 ) ;
six _powders >>>= 5 ;
}
powder _info = powder _info . slice ( 5 ) ;
}
powdering [ i ] = powders ;
}
2022-05-21 18:33:28 +00:00
return [ powdering , powder _info ] ;
2021-10-17 15:53:48 +00:00
}
/ *
* Populate fields based on url , and calculate build .
* /
function decodeBuild ( url _tag ) {
if ( url _tag ) {
2022-05-21 02:01:53 +00:00
//default values
2021-10-17 15:53:48 +00:00
let equipment = [ null , null , null , null , null , null , null , null , null ] ;
2022-05-21 02:01:53 +00:00
let tomes = [ null , null , null , null , null , null , null ] ;
2021-10-17 15:53:48 +00:00
let powdering = [ "" , "" , "" , "" , "" ] ;
let info = url _tag . split ( "_" ) ;
let version = info [ 0 ] ;
let save _skp = false ;
let skillpoints = [ 0 , 0 , 0 , 0 , 0 ] ;
let level = 106 ;
2022-05-21 02:01:53 +00:00
2022-05-21 18:33:28 +00:00
version _number = parseInt ( version )
2022-05-21 02:01:53 +00:00
//equipment (items)
2022-05-21 18:33:28 +00:00
// TODO: use filters
if ( version _number < 4 ) {
2021-10-17 15:53:48 +00:00
let equipments = info [ 1 ] ;
for ( let i = 0 ; i < 9 ; ++ i ) {
let equipment _str = equipments . slice ( i * 3 , i * 3 + 3 ) ;
equipment [ i ] = getItemNameFromID ( Base64 . toInt ( equipment _str ) ) ;
}
info [ 1 ] = equipments . slice ( 27 ) ;
}
2022-05-21 18:33:28 +00:00
else if ( version _number == 4 ) {
2021-10-17 15:53:48 +00:00
let info _str = info [ 1 ] ;
let start _idx = 0 ;
for ( let i = 0 ; i < 9 ; ++ i ) {
if ( info _str . charAt ( start _idx ) === "-" ) {
equipment [ i ] = "CR-" + info _str . slice ( start _idx + 1 , start _idx + 18 ) ;
start _idx += 18 ;
}
else {
let equipment _str = info _str . slice ( start _idx , start _idx + 3 ) ;
equipment [ i ] = getItemNameFromID ( Base64 . toInt ( equipment _str ) ) ;
start _idx += 3 ;
}
}
info [ 1 ] = info _str . slice ( start _idx ) ;
}
2022-05-21 18:33:28 +00:00
else if ( version _number <= 6 ) {
2021-10-17 15:53:48 +00:00
let info _str = info [ 1 ] ;
let start _idx = 0 ;
for ( let i = 0 ; i < 9 ; ++ i ) {
if ( info _str . slice ( start _idx , start _idx + 3 ) === "CR-" ) {
equipment [ i ] = info _str . slice ( start _idx , start _idx + 20 ) ;
start _idx += 20 ;
} else if ( info _str . slice ( start _idx + 3 , start _idx + 6 ) === "CI-" ) {
let len = Base64 . toInt ( info _str . slice ( start _idx , start _idx + 3 ) ) ;
equipment [ i ] = info _str . slice ( start _idx + 3 , start _idx + 3 + len ) ;
start _idx += ( 3 + len ) ;
} else {
let equipment _str = info _str . slice ( start _idx , start _idx + 3 ) ;
equipment [ i ] = getItemNameFromID ( Base64 . toInt ( equipment _str ) ) ;
start _idx += 3 ;
}
}
info [ 1 ] = info _str . slice ( start _idx ) ;
}
2022-05-21 02:01:53 +00:00
//constant in all versions
for ( let i in equipment ) {
setValue ( equipmentInputs [ i ] , equipment [ i ] ) ;
}
//level, skill point assignments, and powdering
2022-05-21 18:33:28 +00:00
if ( version _number == 1 ) {
2021-10-17 15:53:48 +00:00
let powder _info = info [ 1 ] ;
2022-05-21 18:33:28 +00:00
let res = parsePowdering ( powder _info ) ;
powdering = res [ 0 ] ;
} else if ( version _number == 2 ) {
2021-10-17 15:53:48 +00:00
save _skp = true ;
let skillpoint _info = info [ 1 ] . slice ( 0 , 10 ) ;
for ( let i = 0 ; i < 5 ; ++ i ) {
skillpoints [ i ] = Base64 . toIntSigned ( skillpoint _info . slice ( i * 2 , i * 2 + 2 ) ) ;
}
let powder _info = info [ 1 ] . slice ( 10 ) ;
2022-05-21 18:33:28 +00:00
let res = parsePowdering ( powder _info ) ;
powdering = res [ 0 ] ;
} else if ( version _number <= 6 ) {
2021-10-17 15:53:48 +00:00
level = Base64 . toInt ( info [ 1 ] . slice ( 10 , 12 ) ) ;
setValue ( "level-choice" , level ) ;
save _skp = true ;
let skillpoint _info = info [ 1 ] . slice ( 0 , 10 ) ;
for ( let i = 0 ; i < 5 ; ++ i ) {
skillpoints [ i ] = Base64 . toIntSigned ( skillpoint _info . slice ( i * 2 , i * 2 + 2 ) ) ;
}
let powder _info = info [ 1 ] . slice ( 12 ) ;
2022-05-21 18:33:28 +00:00
let res = parsePowdering ( powder _info ) ;
powdering = res [ 0 ] ;
info [ 1 ] = res [ 1 ] ;
}
// Tomes.
2022-05-25 20:17:42 +00:00
if ( version _number == 6 ) {
2022-05-21 18:33:28 +00:00
//tome values do not appear in anything before v6.
for ( let i = 0 ; i < 7 ; ++ i ) {
let tome _str = info [ 1 ] . charAt ( i ) ;
2022-05-25 20:17:42 +00:00
setValue ( tomeInputs [ i ] , getTomeNameFromID ( Base64 . toInt ( tome _str ) ) ) ;
2022-05-21 18:33:28 +00:00
}
info [ 1 ] = info [ 1 ] . slice ( 7 ) ;
2021-10-17 15:53:48 +00:00
}
2022-05-21 18:33:28 +00:00
2021-10-17 15:53:48 +00:00
for ( let i in powderInputs ) {
setValue ( powderInputs [ i ] , powdering [ i ] ) ;
}
2022-05-21 02:01:53 +00:00
2021-10-17 15:53:48 +00:00
calculateBuild ( save _skp , skillpoints ) ;
}
}
2022-05-21 22:51:09 +00:00
/ * S t o r e s t h e e n t i r e b u i l d i n a s t r i n g u s i n g B 6 4 e n c o d i n g a n d a d d s i t t o t h e U R L .
2021-10-17 15:53:48 +00:00
* /
function encodeBuild ( ) {
if ( player _build ) {
let build _string ;
2022-05-21 02:01:53 +00:00
//V6 encoding - Tomes
2022-05-21 18:33:28 +00:00
build _version = 4 ;
build _string = "" ;
tome _string = "" ;
2022-05-21 02:01:53 +00:00
2022-05-21 18:33:28 +00:00
let crafted _idx = 0 ;
let custom _idx = 0 ;
for ( const item of player _build . items ) {
if ( item . get ( "custom" ) ) {
let custom = "CI-" + encodeCustom ( player _build . customItems [ custom _idx ] , true ) ;
build _string += Base64 . fromIntN ( custom . length , 3 ) + custom ;
custom _idx += 1 ;
build _version = Math . max ( build _version , 5 ) ;
} else if ( item . get ( "crafted" ) ) {
build _string += "CR-" + encodeCraft ( player _build . craftedItems [ crafted _idx ] ) ;
crafted _idx += 1 ;
} else if ( item . get ( "category" ) === "tome" ) {
let tome _id = item . get ( "id" ) ;
if ( tome _id <= 60 ) {
// valid normal tome. ID 61-63 is for NONE tomes.
build _version = Math . max ( build _version , 6 ) ;
2021-10-17 15:53:48 +00:00
}
2022-05-21 18:33:28 +00:00
tome _string += Base64 . fromIntN ( tome _id , 1 ) ;
} else {
build _string += Base64 . fromIntN ( item . get ( "id" ) , 3 ) ;
2021-10-17 15:53:48 +00:00
}
2022-05-21 18:33:28 +00:00
}
for ( const skp of skp _order ) {
build _string += Base64 . fromIntN ( getValue ( skp + "-skp" ) , 2 ) ; // Maximum skillpoints: 2048
}
build _string += Base64 . fromIntN ( player _build . level , 2 ) ;
for ( const _powderset of player _build . powders ) {
let n _bits = Math . ceil ( _powderset . length / 6 ) ;
build _string += Base64 . fromIntN ( n _bits , 1 ) ; // Hard cap of 378 powders.
// Slice copy.
let powderset = _powderset . slice ( ) ;
while ( powderset . length != 0 ) {
let firstSix = powderset . slice ( 0 , 6 ) . reverse ( ) ;
let powder _hash = 0 ;
for ( const powder of firstSix ) {
powder _hash = ( powder _hash << 5 ) + 1 + powder ; // LSB will be extracted first.
2021-10-17 15:53:48 +00:00
}
2022-05-21 18:33:28 +00:00
build _string += Base64 . fromIntN ( powder _hash , 5 ) ;
powderset = powderset . slice ( 6 ) ;
2021-10-17 15:53:48 +00:00
}
}
2022-05-21 18:33:28 +00:00
build _string += tome _string ;
2022-05-21 02:01:53 +00:00
2022-05-21 18:33:28 +00:00
return build _version . toString ( ) + "_" + build _string ;
2021-10-17 15:53:48 +00:00
}
}
function calculateBuild ( save _skp , skp ) {
try {
2022-05-16 07:04:55 +00:00
resetEditableIDs ( ) ;
2022-05-21 02:01:53 +00:00
if ( player _build ) {
2021-10-26 12:58:30 +00:00
reset _powder _specials ( ) ;
2021-10-17 15:53:48 +00:00
updateBoosts ( "skip" , false ) ;
updatePowderSpecials ( "skip" , false ) ;
}
let weaponName = getValue ( equipmentInputs [ 8 ] ) ;
2022-05-20 09:03:46 +00:00
//bruh @hpp
2021-10-17 15:53:48 +00:00
if ( weaponName . startsWith ( "Morph-" ) ) {
let equipment = [ "Morph-Stardust" , "Morph-Steel" , "Morph-Iron" , "Morph-Gold" , "Morph-Topaz" , "Morph-Emerald" , "Morph-Amethyst" , "Morph-Ruby" , weaponName . substring ( 6 ) ] ;
for ( let i in equipment ) {
setValue ( equipmentInputs [ i ] , equipment [ i ] ) ;
}
}
//updatePowderSpecials("skip"); //jank pt 1
save _skp = ( typeof save _skp !== 'undefined' ) ? save _skp : false ;
/ * T O D O : i m p l e m e n t l e v e l c h a n g i n g
Make this entire function prettier
* /
let equipment = [ null , null , null , null , null , null , null , null , null ] ;
for ( let i in equipment ) {
let equip = getValue ( equipmentInputs [ i ] ) . trim ( ) ;
if ( equip === "" ) {
equip = "No " + equipment _names [ i ]
}
else {
setValue ( equipmentInputs [ i ] , equip ) ;
}
equipment [ i ] = equip ;
}
let powderings = [ ] ;
let errors = [ ] ;
for ( const i in powderInputs ) {
// read in two characters at a time.
// TODO: make this more robust.
let input = getValue ( powderInputs [ i ] ) . trim ( ) ;
let powdering = [ ] ;
let errorederrors = [ ] ;
while ( input ) {
let first = input . slice ( 0 , 2 ) ;
let powder = powderIDs . get ( first ) ;
if ( powder === undefined ) {
errorederrors . push ( first ) ;
} else {
powdering . push ( powder ) ;
}
input = input . slice ( 2 ) ;
}
if ( errorederrors . length > 0 ) {
if ( errorederrors . length > 1 )
errors . push ( new IncorrectInput ( errorederrors . join ( "" ) , "t6w6" , powderInputs [ i ] ) ) ;
else
errors . push ( new IncorrectInput ( errorederrors [ 0 ] , "t6 or e3" , powderInputs [ i ] ) ) ;
}
//console.log("POWDERING: " + powdering);
powderings . push ( powdering ) ;
}
2022-05-20 09:03:46 +00:00
let tomes = [ null , null , null , null , null , null , null ] ;
for ( let i in tomes ) {
let equip = getValue ( tomeInputs [ i ] ) . trim ( ) ;
if ( equip === "" ) {
equip = "No " + tome _names [ i ]
}
else {
setValue ( tomeInputs [ i ] , equip ) ;
}
tomes [ i ] = equip ;
}
2021-10-17 15:53:48 +00:00
let level = document . getElementById ( "level-choice" ) . value ;
2022-05-20 09:03:46 +00:00
player _build = new Build ( level , equipment , powderings , new Map ( ) , errors , tomes ) ;
2021-10-17 15:53:48 +00:00
console . log ( player _build ) ;
2022-05-20 09:03:46 +00:00
//isn't this deprecated?
2021-10-17 15:53:48 +00:00
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" ;
}
console . log ( player _build . toString ( ) ) ;
2021-10-27 13:51:37 +00:00
displaysq2EquipOrder ( document . getElementById ( "build-order" ) , player _build . equip _order ) ;
2021-10-17 15:53:48 +00:00
const assigned = player _build . base _skillpoints ;
const skillpoints = player _build . total _skillpoints ;
for ( let i in skp _order ) { //big bren
2021-10-21 14:11:04 +00:00
setText ( skp _order [ i ] + "-skp-base" , "Original: " + skillpoints [ i ] ) ;
2021-10-17 15:53:48 +00:00
}
if ( save _skp ) {
// TODO: reduce duplicated code, @updateStats
let skillpoints = player _build . total _skillpoints ;
let delta _total = 0 ;
for ( let i in skp _order ) {
let manual _assigned = skp [ i ] ;
let delta = manual _assigned - skillpoints [ i ] ;
skillpoints [ i ] = manual _assigned ;
player _build . base _skillpoints [ i ] += delta ;
delta _total += delta ;
}
player _build . assigned _skillpoints += delta _total ;
}
2022-05-16 07:04:55 +00:00
updateEditableIDs ( ) ;
2021-10-17 15:53:48 +00:00
calculateBuildStats ( ) ;
if ( player _build . errored )
throw new ListError ( player _build . errors ) ;
}
catch ( error ) {
console . log ( error ) ;
}
}
function handleBuilderError ( error ) {
if ( error instanceof ListError ) {
for ( let i of error . errors ) {
if ( i instanceof ItemNotFound ) {
i . element . textContent = i . message ;
} else if ( i instanceof IncorrectInput ) {
if ( document . getElementById ( i . id ) !== null ) {
document . getElementById ( i . id ) . parentElement . querySelectorAll ( "p.error" ) [ 0 ] . textContent = i . message ;
}
} else {
let msg = i . stack ;
let lines = msg . split ( "\n" ) ;
let header = document . getElementById ( "header" ) ;
header . textContent = "" ;
for ( const line of lines ) {
let p = document . createElement ( "p" ) ;
p . classList . add ( "itemp" ) ;
p . textContent = line ;
header . appendChild ( p ) ;
}
let p2 = document . createElement ( "p" ) ;
p2 . textContent = "If you believe this is an error, contact hppeng on forums or discord." ;
header . appendChild ( p2 ) ;
}
}
} else {
let msg = error . stack ;
let lines = msg . split ( "\n" ) ;
let header = document . getElementById ( "header" ) ;
header . textContent = "" ;
for ( const line of lines ) {
let p = document . createElement ( "p" ) ;
p . classList . add ( "itemp" ) ;
p . textContent = line ;
header . appendChild ( p ) ;
}
let p2 = document . createElement ( "p" ) ;
p2 . textContent = "If you believe this is an error, contact hppeng on forums or discord." ;
header . appendChild ( p2 ) ;
}
}
/ * U p d a t e s a l l b u i l d s t a t i s t i c s b a s e d o n ( f o r n o w ) t h e s k i l l p o i n t i n p u t f i e l d s a n d t h e n c a l c u l a t e s b u i l d s t a t s .
* /
function updateStats ( ) {
let specialNames = [ "Quake" , "Chain_Lightning" , "Curse" , "Courage" , "Wind_Prison" ] ;
for ( const sName of specialNames ) {
for ( let i = 1 ; i < 6 ; i ++ ) {
let elem = document . getElementById ( sName + "-" + i ) ;
let name = sName . replace ( "_" , " " ) ;
if ( elem . classList . contains ( "toggleOn" ) ) { //toggle the pressed button off
elem . classList . remove ( "toggleOn" ) ;
let special = powderSpecialStats [ specialNames . indexOf ( sName ) ] ;
console . log ( special ) ;
if ( special [ "weaponSpecialEffects" ] . has ( "Damage Boost" ) ) {
if ( name === "Courage" || name === "Curse" ) { //courage is universal damage boost
//player_build.damageMultiplier -= special.weaponSpecialEffects.get("Damage Boost")[i-1]/100;
player _build . externalStats . set ( "sdPct" , player _build . externalStats . get ( "sdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . set ( "mdPct" , player _build . externalStats . get ( "mdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . set ( "poisonPct" , player _build . externalStats . get ( "poisonPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
} else if ( name === "Wind Prison" ) {
player _build . externalStats . set ( "aDamPct" , player _build . externalStats . get ( "aDamPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . get ( "damageBonus" ) [ 4 ] -= special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ;
}
}
}
}
}
let skillpoints = player _build . total _skillpoints ;
let delta _total = 0 ;
for ( let i in skp _order ) {
let value = document . getElementById ( skp _order [ i ] + "-skp" ) . value ;
if ( value === "" ) { value = 0 ; setValue ( skp _order [ i ] + "-skp" , value ) }
let manual _assigned = 0 ;
if ( value . includes ( "+" ) ) {
let skp = value . split ( "+" ) ;
for ( const s of skp ) {
manual _assigned += parseInt ( s , 10 ) ;
}
2022-05-14 06:01:03 +00:00
} else {
2021-10-17 15:53:48 +00:00
manual _assigned = parseInt ( value , 10 ) ;
}
let delta = manual _assigned - skillpoints [ i ] ;
skillpoints [ i ] = manual _assigned ;
player _build . base _skillpoints [ i ] += delta ;
delta _total += delta ;
}
player _build . assigned _skillpoints += delta _total ;
if ( player _build ) {
updatePowderSpecials ( "skip" , false ) ;
2022-05-14 05:15:33 +00:00
updateArmorPowderSpecials ( "skip" , false ) ;
2021-10-17 15:53:48 +00:00
updateBoosts ( "skip" , false ) ;
2022-05-16 06:50:47 +00:00
for ( let id of editable _item _fields ) {
player _build . statMap . set ( id , parseInt ( getValue ( id ) ) ) ;
}
2021-10-17 15:53:48 +00:00
}
player _build . aggregateStats ( ) ;
console . log ( player _build . statMap ) ;
calculateBuildStats ( ) ;
}
2022-05-16 06:50:47 +00:00
/ * U p d a t e s a l l I D s i n t h e e d i t I D s s e c t i o n . R e s e t s e a c h i n p u t a n d o r i g i n a l v a l u e t e x t t o t h e c o r r e c t t e x t a c c o r d i n g t o t h e c u r r e n t b u i l d .
* /
function updateEditableIDs ( ) {
if ( player _build ) {
for ( const id of editable _item _fields ) {
let edit _input = document . getElementById ( id ) ;
let val = player _build . statMap . get ( id ) ;
edit _input . value = val ;
edit _input . placeholder = val ;
let value _label = document . getElementById ( id + "-base" ) ;
value _label . textContent = "Original Value: " + val ;
//a hack to make resetting easier
value _label . value = val ;
}
}
}
/ * R e s e t s a l l I D s i n t h e e d i t I D s s e c t i o n t o t h e i r " o r i g i n a l " v a l u e s .
* /
function resetEditableIDs ( ) {
2022-05-21 02:13:20 +00:00
if ( player _build ) {
for ( const id of editable _item _fields ) {
let edit _input = document . getElementById ( id ) ;
let value _label = document . getElementById ( id + "-base" ) ;
edit _input . value = value _label . value ;
edit _input . placeholder = value _label . value ;
}
} else {
//no player build, reset to 0
for ( const id of editable _item _fields ) {
let edit _input = document . getElementById ( id ) ;
2022-05-16 06:50:47 +00:00
2022-05-21 02:13:20 +00:00
edit _input . value = 0 ;
edit _input . placeholder = 0 ;
}
2022-05-16 06:50:47 +00:00
}
}
2021-10-17 15:53:48 +00:00
/ * U p d a t e s a l l s p e l l b o o s t s
* /
function updateBoosts ( buttonId , recalcStats ) {
let elem = document . getElementById ( buttonId ) ;
let name = buttonId . split ( "-" ) [ 0 ] ;
if ( buttonId !== "skip" ) {
if ( elem . classList . contains ( "toggleOn" ) ) {
player _build . damageMultiplier -= damageMultipliers . get ( name ) ;
if ( name === "warscream" ) {
player _build . defenseMultiplier -= . 20 ;
}
if ( name === "vanish" ) {
player _build . defenseMultiplier -= . 15 ;
}
elem . classList . remove ( "toggleOn" ) ;
} else {
player _build . damageMultiplier += damageMultipliers . get ( name ) ;
if ( name === "warscream" ) {
player _build . defenseMultiplier += . 20 ;
}
if ( name === "vanish" ) {
player _build . defenseMultiplier += . 15 ;
}
elem . classList . add ( "toggleOn" ) ;
}
updatePowderSpecials ( "skip" , false ) ; //jank pt 1
} else {
for ( const [ key , value ] of damageMultipliers ) {
let elem = document . getElementById ( key + "-boost" )
if ( elem . classList . contains ( "toggleOn" ) ) {
elem . classList . remove ( "toggleOn" ) ;
player _build . damageMultiplier -= value ;
if ( key === "warscream" ) { player _build . defenseMultiplier -= . 20 }
if ( key === "vanish" ) { player _build . defenseMultiplier -= . 15 }
}
}
}
if ( recalcStats ) {
calculateBuildStats ( ) ;
}
}
2022-01-09 03:36:24 +00:00
/ * U p d a t e s A C T I V E p o w d e r s p e c i a l b o o s t s ( w e a p o n s )
2021-10-17 15:53:48 +00:00
* /
function updatePowderSpecials ( buttonId , recalcStats ) {
//console.log(player_build.statMap);
let name = ( buttonId ) . split ( "-" ) [ 0 ] ;
let power = ( buttonId ) . split ( "-" ) [ 1 ] ; // [1, 5]
let specialNames = [ "Quake" , "Chain Lightning" , "Curse" , "Courage" , "Wind Prison" ] ;
let powderSpecials = [ ] ; // [ [special, power], [special, power]]
if ( name !== "skip" ) {
let elem = document . getElementById ( buttonId ) ;
if ( elem . classList . contains ( "toggleOn" ) ) { //toggle the pressed button off
elem . classList . remove ( "toggleOn" ) ;
let special = powderSpecialStats [ specialNames . indexOf ( name . replace ( "_" , " " ) ) ] ;
if ( special . weaponSpecialEffects . has ( "Damage Boost" ) ) {
name = name . replace ( "_" , " " ) ;
if ( name === "Courage" || name === "Curse" ) { //courage and curse are universal damage boost
player _build . externalStats . set ( "sdPct" , player _build . externalStats . get ( "sdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . set ( "mdPct" , player _build . externalStats . get ( "mdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . set ( "poisonPct" , player _build . externalStats . get ( "poisonPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
//poison?
} else if ( name === "Wind Prison" ) {
player _build . externalStats . set ( "aDamPct" , player _build . externalStats . get ( "aDamPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . get ( "damageBonus" ) [ 4 ] -= special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ;
}
}
} else {
for ( let i = 1 ; i < 6 ; i ++ ) { //toggle all pressed buttons of the same powder special off
//name is same, power is i
if ( document . getElementById ( name . replace ( " " , "_" ) + "-" + i ) . classList . contains ( "toggleOn" ) ) {
document . getElementById ( name . replace ( " " , "_" ) + "-" + i ) . classList . remove ( "toggleOn" ) ;
let special = powderSpecialStats [ specialNames . indexOf ( name . replace ( "_" , " " ) ) ] ;
if ( special . weaponSpecialEffects . has ( "Damage Boost" ) ) {
name = name . replace ( "_" , " " ) ; //might be redundant
if ( name === "Courage" || name === "Curse" ) { //courage is universal damage boost
//player_build.damageMultiplier -= special.weaponSpecialEffects.get("Damage Boost")[i-1]/100;
player _build . externalStats . set ( "sdPct" , player _build . externalStats . get ( "sdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . set ( "mdPct" , player _build . externalStats . get ( "mdPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . set ( "poisonPct" , player _build . externalStats . get ( "poisonPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
} else if ( name === "Wind Prison" ) {
player _build . externalStats . set ( "aDamPct" , player _build . externalStats . get ( "aDamPct" ) - special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ) ;
player _build . externalStats . get ( "damageBonus" ) [ 4 ] -= special . weaponSpecialEffects . get ( "Damage Boost" ) [ i - 1 ] ;
}
}
}
}
//toggle the pressed button on
elem . classList . add ( "toggleOn" ) ;
}
}
for ( const sName of specialNames ) {
for ( let i = 1 ; i < 6 ; i ++ ) {
if ( document . getElementById ( sName . replace ( " " , "_" ) + "-" + i ) . classList . contains ( "toggleOn" ) ) {
let powderSpecial = powderSpecialStats [ specialNames . indexOf ( sName . replace ( "_" , " " ) ) ] ;
powderSpecials . push ( [ powderSpecial , i ] ) ;
break ;
}
}
}
if ( name !== "skip" ) {
let elem = document . getElementById ( buttonId ) ;
if ( elem . classList . contains ( "toggleOn" ) ) {
let special = powderSpecialStats [ specialNames . indexOf ( name . replace ( "_" , " " ) ) ] ;
if ( special [ "weaponSpecialEffects" ] . has ( "Damage Boost" ) ) {
let name = special [ "weaponSpecialName" ] ;
if ( name === "Courage" || name === "Curse" ) { //courage and curse are is universal damage boost
player _build . externalStats . set ( "sdPct" , player _build . externalStats . get ( "sdPct" ) + special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . set ( "mdPct" , player _build . externalStats . get ( "mdPct" ) + special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . set ( "poisonPct" , player _build . externalStats . get ( "poisonPct" ) + special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
} else if ( name === "Wind Prison" ) {
player _build . externalStats . set ( "aDamPct" , player _build . externalStats . get ( "aDamPct" ) + special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ) ;
player _build . externalStats . get ( "damageBonus" ) [ 4 ] += special . weaponSpecialEffects . get ( "Damage Boost" ) [ power - 1 ] ;
}
}
}
}
if ( recalcStats ) {
calculateBuildStats ( ) ;
}
2021-10-26 11:43:51 +00:00
displaysq2PowderSpecials ( document . getElementById ( "powder-special-stats" ) , powderSpecials , player _build , true ) ;
2021-10-17 15:53:48 +00:00
}
2021-10-26 11:43:51 +00:00
2022-01-09 03:36:24 +00:00
/ * U p d a t e s P A S S I V E p o w d e r s p e c i a l b o o s t s ( a r m o r s )
* /
2022-05-14 05:15:33 +00:00
function updateArmorPowderSpecials ( elem _id , recalc _stats ) {
2022-05-14 04:32:58 +00:00
//we only update the powder special + external stats if the player has a build
2022-05-14 05:15:33 +00:00
if ( elem _id !== "skip" ) {
if ( player _build !== undefined && player _build . weapon !== undefined && player _build . weapon . get ( "name" ) !== "No Weapon" ) {
let wynn _elem = elem _id . split ( "_" ) [ 0 ] ; //str, dex, int, def, agi
//update the label associated w/ the slider
let elem = document . getElementById ( elem _id ) ;
let label = document . getElementById ( elem _id + "_label" ) ;
let prev _label = document . getElementById ( elem _id + "_prev" ) ;
let value = elem . value ;
//for use in editing build stats
let prev _value = prev _label . value ;
let value _diff = value - prev _value ;
//update the "previous" label
prev _label . value = value ;
label . textContent = label . textContent . split ( ":" ) [ 0 ] + ": " + value ;
let dmg _id = elem _chars [ skp _names . indexOf ( wynn _elem ) ] + "DamPct" ;
let new _dmgboost = player _build . externalStats . get ( dmg _id ) + value _diff ;
//update build external stats - the second one is the relevant one for damage calc purposes
player _build . externalStats . set ( dmg _id , new _dmgboost ) ;
player _build . externalStats . get ( "damageBonus" ) [ skp _names . indexOf ( wynn _elem ) ] = new _dmgboost ;
//update the slider's graphics
let bg _color = elem _colors [ skp _names . indexOf ( wynn _elem ) ] ;
let pct = Math . round ( 100 * value / powderSpecialStats [ skp _names . indexOf ( wynn _elem ) ] . cap ) ;
elem . style . background = ` linear-gradient(to right, ${ bg _color } , ${ bg _color } ${ pct } %, #AAAAAA ${ pct } %, #AAAAAA 100%) ` ;
2022-01-09 03:36:24 +00:00
2022-05-14 05:15:33 +00:00
}
} else {
2022-05-14 05:24:28 +00:00
if ( player _build !== undefined ) {
for ( let i = 0 ; i < skp _names . length ; ++ i ) {
skp _name = skp _names [ i ] ;
skp _char = elem _chars [ i ] ;
player _build . externalStats . set ( skp _char + "DamPct" , player _build . externalStats . get ( skp _char + "DamPct" ) - document . getElementById ( skp _name + "_boost_armor" ) . value ) ;
player _build . externalStats . get ( "damageBonus" ) [ i ] -= document . getElementById ( skp _name + "_boost_armor" ) . value ;
}
2022-05-14 05:15:33 +00:00
}
}
2022-01-10 06:16:24 +00:00
2022-05-14 05:15:33 +00:00
2022-05-14 05:35:31 +00:00
if ( recalc _stats && player _build ) {
2022-01-10 06:16:24 +00:00
//calc build stats and display powder special
calculateBuildStats ( ) ;
// displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true);
2022-05-14 05:15:33 +00:00
}
}
function resetArmorPowderSpecials ( ) {
for ( const skp of skp _names ) {
document . getElementById ( skp + "_boost_armor" ) . value = 0 ;
document . getElementById ( skp + "_boost_armor_prev" ) . value = 0 ;
document . getElementById ( skp + "_boost_armor" ) . style . background = ` linear-gradient(to right, #AAAAAA, #AAAAAA 0%, #AAAAAA 100%) ` ;
2022-05-18 22:14:36 +00:00
document . getElementById ( skp + "_boost_armor_label" ) . textContent = ` % ${ capitalizeFirst ( elem _names [ skp _names . indexOf ( skp ) ] ) } Damage Boost: 0 `
2022-01-10 06:16:24 +00:00
}
2022-01-09 03:36:24 +00:00
}
2021-10-17 15:53:48 +00:00
/ * C a l c u l a t e s a l l b u i l d s t a t i s t i c s a n d u p d a t e s t h e e n t i r e d i s p l a y .
* /
function calculateBuildStats ( ) {
const assigned = player _build . base _skillpoints ;
const skillpoints = player _build . total _skillpoints ;
let skp _effects = [ "% more damage dealt." , "% chance to crit." , "% spell cost reduction." , "% less damage taken." , "% chance to dodge." ] ;
for ( let i in skp _order ) { //big bren
2021-10-27 13:51:37 +00:00
setText ( skp _order [ i ] + "-skp-assign" , "Assign: " + assigned [ i ] ) ;
2021-10-17 15:53:48 +00:00
setValue ( skp _order [ i ] + "-skp" , skillpoints [ i ] ) ;
let linebreak = document . createElement ( "br" ) ;
linebreak . classList . add ( "itemp" ) ;
document . getElementById ( skp _order [ i ] + "-skp-label" ) ;
setText ( skp _order [ i ] + "-skp-pct" , ( skillPointsToPercentage ( skillpoints [ i ] ) * 100 ) . toFixed ( 1 ) . concat ( skp _effects [ i ] ) ) ;
document . getElementById ( skp _order [ i ] + "-warnings" ) . textContent = ''
if ( assigned [ i ] > 100 ) {
let skp _warning = document . createElement ( "p" ) ;
skp _warning . classList . add ( "warning" ) ;
skp _warning . classList . add ( "small-text" )
skp _warning . textContent += "Cannot assign " + assigned [ i ] + " skillpoints in " + [ "Strength" , "Dexterity" , "Intelligence" , "Defense" , "Agility" ] [ i ] + " manually." ;
document . getElementById ( skp _order [ i ] + "-warnings" ) . textContent = ''
document . getElementById ( skp _order [ i ] + "-warnings" ) . appendChild ( skp _warning ) ;
}
}
let summarybox = document . getElementById ( "summary-box" ) ;
summarybox . textContent = "" ;
let skpRow = document . createElement ( "p" ) ;
let remainingSkp = document . createElement ( "p" ) ;
2021-10-21 14:11:04 +00:00
remainingSkp . classList . add ( "scaled-font" ) ;
2021-10-17 15:53:48 +00:00
let remainingSkpTitle = document . createElement ( "b" ) ;
remainingSkpTitle . textContent = "Assigned " + player _build . assigned _skillpoints + " skillpoints. Remaining skillpoints: " ;
let remainingSkpContent = document . createElement ( "b" ) ;
remainingSkpContent . textContent = "" + ( levelToSkillPoints ( player _build . level ) - player _build . assigned _skillpoints ) ;
remainingSkpContent . classList . add ( levelToSkillPoints ( player _build . level ) - player _build . assigned _skillpoints < 0 ? "negative" : "positive" ) ;
remainingSkp . appendChild ( remainingSkpTitle ) ;
remainingSkp . appendChild ( remainingSkpContent ) ;
summarybox . append ( skpRow ) ;
summarybox . append ( remainingSkp ) ;
if ( player _build . assigned _skillpoints > levelToSkillPoints ( player _build . level ) ) {
2021-10-21 14:11:04 +00:00
let skpWarning = document . createElement ( "span" ) ;
2021-10-17 15:53:48 +00:00
//skpWarning.classList.add("itemp");
skpWarning . classList . add ( "warning" ) ;
skpWarning . textContent = "WARNING: Too many skillpoints need to be assigned!" ;
let skpCount = document . createElement ( "p" ) ;
2021-10-21 14:11:04 +00:00
skpCount . classList . add ( "warning" ) ;
2021-10-17 15:53:48 +00:00
skpCount . textContent = "For level " + ( player _build . level > 101 ? "101+" : player _build . level ) + ", there are only " + levelToSkillPoints ( player _build . level ) + " skill points available." ;
summarybox . append ( skpWarning ) ;
summarybox . append ( skpCount ) ;
}
let lvlWarning ;
for ( const item of player _build . items ) {
let item _lvl ;
if ( item . get ( "crafted" ) ) {
//item_lvl = item.get("lvlLow") + "-" + item.get("lvl");
item _lvl = item . get ( "lvlLow" ) ;
}
else {
item _lvl = item . get ( "lvl" ) ;
}
if ( player _build . level < item _lvl ) {
if ( ! lvlWarning ) {
lvlWarning = document . createElement ( "p" ) ;
lvlWarning . classList . add ( "itemp" ) ;
lvlWarning . classList . add ( "warning" ) ;
lvlWarning . textContent = "WARNING: A level " + player _build . level + " player cannot use some piece(s) of this build."
}
let baditem = document . createElement ( "p" ) ;
baditem . classList . add ( "nocolor" ) ;
baditem . classList . add ( "itemp" ) ;
baditem . textContent = item . get ( "displayName" ) + " requires level " + item . get ( "lvl" ) + " to use." ;
lvlWarning . appendChild ( baditem ) ;
}
}
if ( lvlWarning ) {
summarybox . append ( lvlWarning ) ;
}
for ( const [ setName , count ] of player _build . activeSetCounts ) {
const bonus = sets [ setName ] . bonuses [ count - 1 ] ;
// console.log(setName);
if ( bonus [ "illegal" ] ) {
let setWarning = document . createElement ( "p" ) ;
setWarning . classList . add ( "itemp" ) ;
setWarning . classList . add ( "warning" ) ;
setWarning . textContent = "WARNING: illegal item combination: " + setName
summarybox . append ( setWarning ) ;
}
}
for ( let i in player _build . items ) {
2021-10-29 08:08:36 +00:00
displaysq2ExpandedItem ( player _build . items [ i ] , buildFields [ i ] ) ;
collapse _element ( "#" + equipment _keys [ i ] + "-tooltip" ) ;
2021-10-17 15:53:48 +00:00
}
2021-10-23 15:34:47 +00:00
2021-10-18 00:25:02 +00:00
displaysq2ArmorStats ( player _build ) ;
2022-01-07 08:12:00 +00:00
displaysq2BuildStats ( 'overall-stats' , player _build , build _all _display _commands ) ;
displaysq2BuildStats ( "offensive-stats" , player _build , build _offensive _display _commands ) ;
2021-10-29 08:08:36 +00:00
displaysq2SetBonuses ( "set-info" , player _build ) ;
2022-01-07 08:12:00 +00:00
displaysq2WeaponStats ( player _build ) ;
2021-10-17 15:53:48 +00:00
let meleeStats = player _build . getMeleeStats ( ) ;
2021-10-18 00:25:02 +00:00
displaysq2MeleeDamage ( document . getElementById ( "build-melee-stats" ) , document . getElementById ( "build-melee-statsAvg" ) , meleeStats ) ;
2021-10-17 15:53:48 +00:00
2022-01-07 08:12:00 +00:00
displaysq2DefenseStats ( document . getElementById ( "defensive-stats" ) , player _build ) ;
2021-10-17 15:53:48 +00:00
2021-10-18 00:25:02 +00:00
displaysq2PoisonDamage ( document . getElementById ( "build-poison-stats" ) , player _build ) ;
2021-10-17 15:53:48 +00:00
let spells = spell _table [ player _build . weapon . get ( "type" ) ] ;
for ( let i = 0 ; i < 4 ; ++ i ) {
let parent _elem = document . getElementById ( "spell" + i + "-info" ) ;
let overallparent _elem = document . getElementById ( "spell" + i + "-infoAvg" ) ;
2021-10-18 00:25:02 +00:00
displaysq2SpellDamage ( parent _elem , overallparent _elem , player _build , spells [ i ] , i + 1 ) ;
2021-10-17 15:53:48 +00:00
}
location . hash = encodeBuild ( ) ;
clear _highlights ( ) ;
}
function copyBuild ( ) {
if ( player _build ) {
copyTextToClipboard ( url _base + location . hash ) ;
document . getElementById ( "copy-button" ) . textContent = "Copied!" ;
}
}
function shareBuild ( ) {
if ( player _build ) {
let text = url _base + location . hash + "\n" +
"WynnBuilder build:\n" +
"> " + player _build . helmet . get ( "displayName" ) + "\n" +
"> " + player _build . chestplate . get ( "displayName" ) + "\n" +
"> " + player _build . leggings . get ( "displayName" ) + "\n" +
"> " + player _build . boots . get ( "displayName" ) + "\n" +
"> " + player _build . ring1 . get ( "displayName" ) + "\n" +
"> " + player _build . ring2 . get ( "displayName" ) + "\n" +
"> " + player _build . bracelet . get ( "displayName" ) + "\n" +
"> " + player _build . necklace . get ( "displayName" ) + "\n" +
"> " + player _build . weapon . get ( "displayName" ) + " [" + player _build . weapon . get ( "powders" ) . map ( x => powderNames . get ( x ) ) . join ( "" ) + "]" ;
copyTextToClipboard ( text ) ;
document . getElementById ( "share-button" ) . textContent = "Copied!" ;
}
}
2021-10-29 08:08:36 +00:00
function populateBuildList ( ) {
const buildList = document . getElementById ( "build-choice" ) ;
const savedBuilds = window . localStorage . getItem ( "builds" ) === null ? { } : JSON . parse ( window . localStorage . getItem ( "builds" ) ) ;
for ( const buildName of Object . keys ( savedBuilds ) . sort ( ) ) {
const buildOption = document . createElement ( "option" ) ;
buildOption . setAttribute ( "value" , buildName ) ;
buildList . appendChild ( buildOption ) ;
}
}
2021-10-17 15:53:48 +00:00
function saveBuild ( ) {
if ( player _build ) {
2021-10-29 08:08:36 +00:00
const savedBuilds = window . localStorage . getItem ( "builds" ) === null ? { } : JSON . parse ( window . localStorage . getItem ( "builds" ) ) ;
const saveName = document . getElementById ( "build-name" ) . value ;
const encodedBuild = encodeBuild ( ) ;
2021-10-17 15:53:48 +00:00
if ( ( ! Object . keys ( savedBuilds ) . includes ( saveName )
|| document . getElementById ( "saved-error" ) . textContent !== "" ) && encodedBuild !== "" ) {
savedBuilds [ saveName ] = encodedBuild . replace ( "#" , "" ) ;
window . localStorage . setItem ( "builds" , JSON . stringify ( savedBuilds ) ) ;
document . getElementById ( "saved-error" ) . textContent = "" ;
2021-10-29 08:08:36 +00:00
document . getElementById ( "saved-build" ) . textContent = "Build saved locally" ;
const buildList = document . getElementById ( "build-choice" ) ;
const buildOption = document . createElement ( "option" ) ;
buildOption . setAttribute ( "value" , saveName ) ;
buildList . appendChild ( buildOption ) ;
2021-10-17 15:53:48 +00:00
} else {
document . getElementById ( "saved-build" ) . textContent = "" ;
if ( encodedBuild === "" ) {
document . getElementById ( "saved-error" ) . textContent = "Empty build" ;
}
else {
document . getElementById ( "saved-error" ) . textContent = "Exists. Overwrite?" ;
}
}
}
}
function loadBuild ( ) {
let savedBuilds = window . localStorage . getItem ( "builds" ) === null ? { } : JSON . parse ( window . localStorage . getItem ( "builds" ) ) ;
let saveName = document . getElementById ( "build-name" ) . value ;
if ( Object . keys ( savedBuilds ) . includes ( saveName ) ) {
decodeBuild ( savedBuilds [ saveName ] )
document . getElementById ( "loaded-error" ) . textContent = "" ;
document . getElementById ( "loaded-build" ) . textContent = "Build loaded" ;
} else {
document . getElementById ( "loaded-build" ) . textContent = "" ;
document . getElementById ( "loaded-error" ) . textContent = "Build doesn't exist" ;
}
}
function resetFields ( ) {
for ( let i in powderInputs ) {
setValue ( powderInputs [ i ] , "" ) ;
}
for ( let i in equipmentInputs ) {
setValue ( equipmentInputs [ i ] , "" ) ;
}
setValue ( "str-skp" , "0" ) ;
setValue ( "dex-skp" , "0" ) ;
setValue ( "int-skp" , "0" ) ;
setValue ( "def-skp" , "0" ) ;
setValue ( "agi-skp" , "0" ) ;
setValue ( "level-choice" , "106" ) ;
location . hash = "" ;
calculateBuild ( ) ;
}
function toggleID ( ) {
let button = document . getElementById ( "show-id-button" ) ;
let targetDiv = document . getElementById ( "id-edit" ) ;
if ( button . classList . contains ( "toggleOn" ) ) { //toggle the pressed button off
targetDiv . style . display = "none" ;
button . classList . remove ( "toggleOn" ) ;
}
else {
targetDiv . style . display = "block" ;
button . classList . add ( "toggleOn" ) ;
}
}
2022-05-16 06:50:47 +00:00
function toggleButton ( button _id ) {
let button = document . getElementById ( button _id ) ;
if ( button ) {
if ( button . classList . contains ( "toggleOn" ) ) {
button . classList . remove ( "toggleOn" ) ;
} else {
button . classList . add ( "toggleOn" ) ;
}
}
}
2021-10-17 15:53:48 +00:00
function optimizeStrDex ( ) {
2022-05-18 22:14:36 +00:00
if ( ! player _build ) {
return ;
}
2021-10-17 15:53:48 +00:00
const remaining = levelToSkillPoints ( player _build . level ) - player _build . assigned _skillpoints ;
const base _skillpoints = player _build . base _skillpoints ;
const max _str _boost = 100 - base _skillpoints [ 0 ] ;
const max _dex _boost = 100 - base _skillpoints [ 1 ] ;
2021-10-29 08:08:36 +00:00
if ( Math . min ( remaining , max _str _boost , max _dex _boost ) < 0 ) return ; // Unwearable
2021-10-17 15:53:48 +00:00
const base _total _skillpoints = player _build . total _skillpoints ;
let str _bonus = remaining ;
let dex _bonus = 0 ;
let best _skillpoints = player _build . total _skillpoints ;
let best _damage = 0 ;
for ( let i = 0 ; i <= remaining ; ++ i ) {
let total _skillpoints = base _total _skillpoints . slice ( ) ;
total _skillpoints [ 0 ] += Math . min ( max _str _boost , str _bonus ) ;
total _skillpoints [ 1 ] += Math . min ( max _dex _boost , dex _bonus ) ;
// Calculate total 3rd spell damage
let spell = spell _table [ player _build . weapon . get ( "type" ) ] [ 2 ] ;
const stats = player _build . statMap ;
let critChance = skillPointsToPercentage ( total _skillpoints [ 1 ] ) ;
let save _damages = [ ] ;
let spell _parts ;
if ( spell . parts ) {
spell _parts = spell . parts ;
}
else {
spell _parts = spell . variants . DEFAULT ;
for ( const majorID of stats . get ( "activeMajorIDs" ) ) {
if ( majorID in spell . variants ) {
spell _parts = spell . variants [ majorID ] ;
break ;
}
}
}
let total _damage = 0 ;
for ( const part of spell _parts ) {
if ( part . type === "damage" ) {
let _results = calculateSpellDamage ( stats , part . conversion ,
stats . get ( "sdRaw" ) , stats . get ( "sdPct" ) + player _build . externalStats . get ( "sdPct" ) ,
part . multiplier / 100 , player _build . weapon , total _skillpoints ,
player _build . damageMultiplier , player _build . externalStats ) ;
let totalDamNormal = _results [ 0 ] ;
let totalDamCrit = _results [ 1 ] ;
let results = _results [ 2 ] ;
let tooltipinfo = _results [ 3 ] ;
for ( let i = 0 ; i < 6 ; ++ i ) {
for ( let j in results [ i ] ) {
results [ i ] [ j ] = results [ i ] [ j ] . toFixed ( 2 ) ;
}
}
let nonCritAverage = ( totalDamNormal [ 0 ] + totalDamNormal [ 1 ] ) / 2 || 0 ;
let critAverage = ( totalDamCrit [ 0 ] + totalDamCrit [ 1 ] ) / 2 || 0 ;
let averageDamage = ( 1 - critChance ) * nonCritAverage + critChance * critAverage || 0 ;
save _damages . push ( averageDamage ) ;
if ( part . summary == true ) {
total _damage = averageDamage ;
}
} else if ( part . type === "total" ) {
total _damage = 0 ;
for ( let i in part . factors ) {
total _damage += save _damages [ i ] * part . factors [ i ] ;
}
}
} // END Calculate total 3rd spell damage (total_damage)
if ( total _damage > best _damage ) {
best _damage = total _damage ;
best _skillpoints = total _skillpoints . slice ( ) ;
}
str _bonus -= 1 ;
dex _bonus += 1 ;
}
// TODO: reduce duplicated code, @calculateBuild
let skillpoints = player _build . total _skillpoints ;
let delta _total = 0 ;
for ( let i in skp _order ) {
let manual _assigned = best _skillpoints [ i ] ;
let delta = manual _assigned - skillpoints [ i ] ;
skillpoints [ i ] = manual _assigned ;
player _build . base _skillpoints [ i ] += delta ;
delta _total += delta ;
}
player _build . assigned _skillpoints += delta _total ;
try {
calculateBuildStats ( ) ;
if ( player _build . errored )
throw new ListError ( player _build . errors ) ;
}
catch ( error ) {
handleBuilderError ( error ) ;
}
}
// TODO: Learn and use await
2022-05-20 09:03:46 +00:00
function init ( ) {
console . log ( "builder.js init" ) ;
init _autocomplete ( ) ;
decodeBuild ( url _tag ) ;
for ( const i of equipment _keys ) {
update _field ( i ) ;
}
}
2021-10-17 15:53:48 +00:00
function init2 ( ) {
load _ing _init ( init ) ;
}
2022-05-20 09:03:46 +00:00
function init3 ( ) {
load _tome _init ( init2 )
}
load _init ( init3 ) ;