Merge branch 'dev' of github.com:reschan/reschan.github.io into UI_test
This commit is contained in:
commit
f292b3d4a9
16 changed files with 7658 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -4,3 +4,6 @@ sets/
|
|||
|
||||
.idea/
|
||||
*.iml
|
||||
node_modules/
|
||||
package.json
|
||||
package-lock.json
|
||||
|
|
BIN
media/icons/new/copy.png
Normal file
BIN
media/icons/new/copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 300 B |
BIN
media/icons/new/save.png
Normal file
BIN
media/icons/new/save.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 444 B |
349
normalize.css
vendored
Normal file
349
normalize.css
vendored
Normal file
|
@ -0,0 +1,349 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
440
sq2.css
Normal file
440
sq2.css
Normal file
|
@ -0,0 +1,440 @@
|
|||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: 'Nunito', sans-serif;
|
||||
}
|
||||
|
||||
input::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
input {
|
||||
-webkit-appearance : none;
|
||||
border-radius : 0;
|
||||
}
|
||||
|
||||
textarea, input { outline: none; }
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
overflow: hidden; /* makes the body non-scrollable (we will add scrolling to the sidebar and main content containers) */
|
||||
margin: 0; /* removes default style */
|
||||
display: flex; /* enables flex content for its children */
|
||||
box-sizing: border-box;
|
||||
font-family: 'Nunito', sans-serif;
|
||||
}
|
||||
|
||||
/* Works on Firefox */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgb(30, 30, 30) rgb(45, 45, 45);
|
||||
}
|
||||
|
||||
/* Works on Chrome, Edge, and Safari */
|
||||
*::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: rgb(45, 45, 45);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
|
||||
.column {
|
||||
height: 100%; /* allows both columns to span the full height of the browser window */
|
||||
display: flex;
|
||||
flex-direction: column; /* places the left and right headers above the bottom content */
|
||||
}
|
||||
|
||||
#left { /* makes sure that content is not cut off in a smaller browser window */
|
||||
flex-shrink: 1;
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
|
||||
#right {
|
||||
flex-grow: 1;
|
||||
background-color: rgb(40, 40, 40);
|
||||
color: rgb(240, 240, 240);
|
||||
padding: 2%;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
img.item-icon {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
flex-grow: 1; /* ensures that the container will take up the full height of the parent container */
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.full-border, .box {
|
||||
border: .3vw solid rgb(45, 45, 45);
|
||||
}
|
||||
|
||||
.se-border {
|
||||
border-left: .3vw solid rgb(45, 45, 45);
|
||||
border-right: .3vw solid rgb(45, 45, 45);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
font-size: .8vw;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: rgb(40, 40, 40);
|
||||
border-top: .15vw solid rgb(25, 25, 25) !important;
|
||||
border-left: .15vw solid rgb(25, 25, 25) !important;
|
||||
border-bottom: .15vw solid rgb(45, 45, 45) !important;
|
||||
border-right: .15vw solid rgb(45, 45, 45) !important;
|
||||
box-sizing: border-box !important;
|
||||
color: rgb(240, 240, 240);
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
font-size: .8vw;
|
||||
box-sizing: none;
|
||||
}
|
||||
|
||||
input.item-name {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
width: 10vw;
|
||||
height: 1.2vw;
|
||||
}
|
||||
|
||||
input.search-field {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
.equipment-container {
|
||||
background-color: rgb(30, 30, 30);
|
||||
flex-direction: column;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.all-equipment {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.weapon-container {
|
||||
display: inline-flex;
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
|
||||
.skp-container {
|
||||
width: 38vw;
|
||||
height: 10vw;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
|
||||
td.mono-font {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
td.damage-size {
|
||||
width: 5vw;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.potency {
|
||||
width: 36em;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.skp-text {
|
||||
width: 7.75em;
|
||||
}
|
||||
|
||||
.skp-input {
|
||||
width: 6vw;
|
||||
height: 1.2vw;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.center-screen {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.powder-input {
|
||||
text-align: center;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-weight: bold;
|
||||
width: 10vw;
|
||||
height: 1.2vw;
|
||||
}
|
||||
|
||||
.skp-tooltip {
|
||||
font-size: .6vw;
|
||||
}
|
||||
|
||||
.spell-container {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
background-color: rgb(30, 30, 30);
|
||||
width: 18vw;
|
||||
height: 24.5vw;
|
||||
}
|
||||
|
||||
.draggable {
|
||||
position: absolute !important;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.draggable-header {
|
||||
cursor: move;
|
||||
z-index: 10;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
text-align: center;
|
||||
}
|
||||
p.Damage {
|
||||
color: rgb(255, 198, 85)
|
||||
}
|
||||
|
||||
.Set {
|
||||
display: inline;
|
||||
color: #5f5;
|
||||
}
|
||||
|
||||
.Mana { color: #5ff;}
|
||||
.Mana:after { content: "\273A"}
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.f-w {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.shaded-table {
|
||||
background-color: rgb(30, 30, 30);
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
|
||||
border-bottom: 1px solid rgb(45, 45, 45)
|
||||
}
|
||||
|
||||
.spacer-table {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.minimal-stats-container {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
vertical-align: top;
|
||||
background-color: rgb(30, 30, 30);
|
||||
width: 18vw;
|
||||
height: 24.5vw;
|
||||
}
|
||||
|
||||
.nDam {
|
||||
color: #FFAA00;
|
||||
}
|
||||
|
||||
.eDam, .Earth, .Earth_powder {
|
||||
color: #00AA00;
|
||||
}
|
||||
|
||||
.Earth:before, .Earth_powder:before { content: "\2724" ' '; }
|
||||
|
||||
.tDam, .Thunder, .Thunder_powder {
|
||||
color: #FFFF55;
|
||||
}
|
||||
|
||||
.Thunder:before, .Thunder_powder:before { content: "\2726" ' '; }
|
||||
|
||||
.wDam, .Water, .Water_powder {
|
||||
color: #55FFFF
|
||||
}
|
||||
|
||||
.Water:before, .Water_powder:before { content: "\2749" ' '; }
|
||||
|
||||
.fDam, .Fire, .Fire_powder {
|
||||
color: #FF5555;
|
||||
}
|
||||
|
||||
.Fire:before, .Fire_powder:before { content: "\2739" ' '; }
|
||||
|
||||
.aDam, .Air, .Air_powder {
|
||||
color: #FFFFFF
|
||||
}
|
||||
|
||||
.Air:before, .Air_powder:before { content: "\274b" ' '; }
|
||||
|
||||
.Neutral { color: #fa0; }
|
||||
.Neutral:before { content: "\2724" ' '; }
|
||||
.Damage { color: rgb(255, 198, 85)}
|
||||
|
||||
.Health {
|
||||
color: #AA0000
|
||||
}
|
||||
|
||||
.Health:before {
|
||||
content: "\2764" ' ';
|
||||
}
|
||||
|
||||
.Normal {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.Unique {
|
||||
color: #FFFF55;
|
||||
}
|
||||
|
||||
.Rare {
|
||||
color: #FF55FF;
|
||||
}
|
||||
|
||||
.Legendary {
|
||||
color: #55FFFF;
|
||||
}
|
||||
|
||||
.Fabled {
|
||||
color: #FF5555;
|
||||
}
|
||||
|
||||
.Mythic {
|
||||
color: #AA00AA
|
||||
}
|
||||
|
||||
p.no-newline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.small-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.lvl {
|
||||
color: #d4d4d4
|
||||
}
|
||||
|
||||
.lvl:before {
|
||||
content: "Lv. "
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: rgb(30, 30, 30);
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.positive {
|
||||
color: #5f5;
|
||||
/*text-shadow: 2px 2px 0 #153f15;*/
|
||||
}
|
||||
|
||||
.negative {
|
||||
color: #f55;
|
||||
/*text-shadow: 2px 2px 0 #1f1515;*/
|
||||
}
|
||||
|
||||
.item-margin {
|
||||
margin-top: .8vw;
|
||||
margin-bottom: .8vw;
|
||||
}
|
||||
|
||||
.item-tooltip {
|
||||
width: 15rem;
|
||||
background-color: rgb(30, 30, 30);
|
||||
color: white;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.window-container {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
background-color: rgb(30, 30, 30);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.window-header {
|
||||
display: flex;
|
||||
cursor: move;
|
||||
background-color: rgb(45, 45, 45);
|
||||
font-size: .8vw;
|
||||
}
|
||||
|
||||
.search-result-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
flex-basis: 30vw;
|
||||
max-width: 14.4vw;
|
||||
}
|
||||
|
||||
.button-boost {
|
||||
background-color: rgb(45, 45, 45);
|
||||
width: 10rem;
|
||||
border: 5px solid rgb(50, 50, 50)
|
||||
}
|
||||
|
||||
button.toggleOn{
|
||||
background-color:#0a0;
|
||||
border: 3px solid rgb(0, 70, 0);
|
||||
}
|
||||
|
||||
.damageSubtitle {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.itemp {
|
||||
font-size: .8vw;
|
||||
}
|
||||
/*
|
||||
div:not(.item-tooltip) {
|
||||
font-size: .8vw;
|
||||
}*/
|
347
sq2.js
Normal file
347
sq2.js
Normal file
|
@ -0,0 +1,347 @@
|
|||
let equipment_keys = ['weapon', 'helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace'];
|
||||
|
||||
$(document).ready(function(){
|
||||
// inits
|
||||
|
||||
$("#overall-window").toggle();
|
||||
$("#search-container").toggle();
|
||||
$("#boost-container").toggle();
|
||||
|
||||
// pot/base damage switch for weap display
|
||||
/*
|
||||
$(".damage-size").click(function(){
|
||||
$(".damage-size").hide();
|
||||
$(".potency").show();
|
||||
});
|
||||
$(".potency").click(function(){
|
||||
$(".potency").hide();
|
||||
$(".damage-size").show();
|
||||
});*/
|
||||
|
||||
// windows
|
||||
$("#overall-window").draggable({
|
||||
handle: '#overall-window-header',
|
||||
}).resizable({
|
||||
alsoResize: "#all-stats",
|
||||
handles: 'n, e, s ,w'
|
||||
});
|
||||
|
||||
$("#search-container").draggable({
|
||||
handle: '#search-container-header',
|
||||
});
|
||||
|
||||
$("#boost-container").draggable({
|
||||
handle: '#boost-container-header',
|
||||
});
|
||||
|
||||
// window priority
|
||||
$("#overall-window").mousedown(function() {
|
||||
$(".window-container").css("z-index", 10);
|
||||
$(this).css("z-index", 11);
|
||||
});
|
||||
|
||||
$("#search-container").mousedown(function() {
|
||||
$(".window-container").css("z-index", 10);
|
||||
$(this).css("z-index", 11);
|
||||
});
|
||||
|
||||
$("#boost-container").mousedown(function() {
|
||||
$(".window-container").css("z-index", 10);
|
||||
$(this).css("z-index", 11);
|
||||
});
|
||||
|
||||
// update builds
|
||||
jQuery(document).on("input", '.skp-input', function(event){
|
||||
updateStatSchedule();
|
||||
});
|
||||
|
||||
jQuery(document).on("input", '.search-field', function(event){
|
||||
doSearchSchedule();
|
||||
});
|
||||
|
||||
// set listeners/checks
|
||||
$("#weapon-choice").on('input', function(){
|
||||
set_input_style('weapon');
|
||||
calcBuildSchedule();
|
||||
update_powder_count('weapon');
|
||||
});
|
||||
|
||||
$("#weapon-powder").on('input', function(){
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#helmet-choice").on('input', function(){
|
||||
set_input_style('helmet');
|
||||
calcBuildSchedule();
|
||||
update_powder_count('helmet', '|example: t6t6');
|
||||
});
|
||||
|
||||
$("#helmet-powder").on('input', function(){
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#chestplate-choice").on('input', function(){
|
||||
set_input_style('chestplate');
|
||||
calcBuildSchedule();
|
||||
update_powder_count('chestplate');
|
||||
});
|
||||
|
||||
$("#chestplate-powder").on('input', function(){
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#leggings-choice").on('input', function(){
|
||||
set_input_style('leggings');
|
||||
calcBuildSchedule();
|
||||
update_powder_count('leggings');
|
||||
});
|
||||
|
||||
$("#leggings-powder").on('input', function(){
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#boots-choice").on('input', function(){
|
||||
set_input_style('boots');
|
||||
calcBuildSchedule();
|
||||
update_powder_count('boots');
|
||||
});
|
||||
|
||||
$("#boots-powder").on('input', function(){
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#ring1-choice").on('input', function(){
|
||||
set_input_style('ring1');
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#ring2-choice").on('input', function(){
|
||||
set_input_style('ring2');
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#bracelet-choice").on('input', function(){
|
||||
set_input_style('bracelet');
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
$("#necklace-choice").on('input', function(){
|
||||
set_input_style('necklace');
|
||||
calcBuildSchedule();
|
||||
});
|
||||
|
||||
// control vars
|
||||
let basic_stats_ctrl = true;
|
||||
let off_stats_ctrl = false;
|
||||
let def_stats_ctrl = false;
|
||||
|
||||
$("#basic-stats-btn").click(function(){
|
||||
basic_stats_ctrl = true;
|
||||
off_stats_ctrl = false;
|
||||
def_stats_ctrl = false;
|
||||
|
||||
$("#minimal-stats").show();
|
||||
$("#minimal-offensive-stats").hide();
|
||||
$("#minimal-defensive-stats").hide();
|
||||
|
||||
$("#off-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
$("#def-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
});
|
||||
$("#basic-stats-btn").hover(
|
||||
function(){
|
||||
$("#basic-stats-btn").css("background-color", "rgb(40, 40, 40)");
|
||||
},function(){
|
||||
if (basic_stats_ctrl) {
|
||||
$("#basic-stats-btn").css("background-color", "rgb(30, 30, 30)");
|
||||
} else {
|
||||
$("#basic-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
}
|
||||
});
|
||||
|
||||
$("#off-stats-btn").click(function(){
|
||||
basic_stats_ctrl = false;
|
||||
off_stats_ctrl = true;
|
||||
def_stats_ctrl = false;
|
||||
|
||||
$("#minimal-stats").hide();
|
||||
$("#minimal-offensive-stats").show();
|
||||
$("#minimal-defensive-stats").hide();
|
||||
|
||||
$("#basic-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
$("#def-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
});
|
||||
$("#off-stats-btn").hover(
|
||||
function(){
|
||||
$("#off-stats-btn").css("background-color", "rgb(40, 40, 40)");
|
||||
},function(){
|
||||
if (off_stats_ctrl) {
|
||||
$("#off-stats-btn").css("background-color", "rgb(30, 30, 30)");
|
||||
} else {
|
||||
$("#off-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
}
|
||||
});
|
||||
|
||||
$("#def-stats-btn").click(function(){
|
||||
basic_stats_ctrl = false;
|
||||
off_stats_ctrl = false;
|
||||
def_stats_ctrl = true;
|
||||
|
||||
$("#minimal-stats").hide();
|
||||
$("#minimal-offensive-stats").hide();
|
||||
$("#minimal-defensive-stats").show();
|
||||
|
||||
$("#off-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
$("#basic-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
});
|
||||
$("#def-stats-btn").hover(
|
||||
function(){
|
||||
$("#def-stats-btn").css("background-color", "rgb(40, 40, 40)");
|
||||
},function(){
|
||||
if (def_stats_ctrl) {
|
||||
$("#def-stats-btn").css("background-color", "rgb(30, 30, 30)");
|
||||
} else {
|
||||
$("#def-stats-btn").css("background-color", "rgb(45, 45, 45)");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// item tooltip
|
||||
|
||||
$("#weapon-img-loc").hover(function(event){
|
||||
$("#weapon-tooltip").show();
|
||||
init_tooltip_loc('weapon');
|
||||
}, function(){
|
||||
$("#weapon-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#helmet-img-loc").hover(function(event){
|
||||
$("#helmet-tooltip").show();
|
||||
init_tooltip_loc('helmet');
|
||||
}, function(){
|
||||
$("#helmet-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#chestplate-img-loc").hover(function(event){
|
||||
$("#chestplate-tooltip").show();
|
||||
init_tooltip_loc('chestplate');
|
||||
}, function(){
|
||||
$("#chestplate-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#leggings-img-loc").hover(function(event){
|
||||
$("#leggings-tooltip").show();
|
||||
init_tooltip_loc('leggings');
|
||||
}, function(){
|
||||
$("#leggings-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#boots-img-loc").hover(function(event){
|
||||
$("#boots-tooltip").show();
|
||||
init_tooltip_loc('boots');
|
||||
}, function(){
|
||||
$("#boots-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#ring1-img-loc").hover(function(event){
|
||||
$("#ring1-tooltip").show();
|
||||
init_tooltip_loc('ring1');
|
||||
}, function(){
|
||||
$("#ring1-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#ring2-img-loc").hover(function(event){
|
||||
$("#ring2-tooltip").show();
|
||||
init_tooltip_loc('ring2');
|
||||
}, function(){
|
||||
$("#ring2-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#bracelet-img-loc").hover(function(event){
|
||||
$("#bracelet-tooltip").show();
|
||||
init_tooltip_loc('bracelet');
|
||||
}, function(){
|
||||
$("#bracelet-tooltip").hide();
|
||||
});
|
||||
|
||||
$("#necklace-img-loc").hover(function(event){
|
||||
$("#necklace-tooltip").show();
|
||||
init_tooltip_loc('necklace');
|
||||
}, function(){
|
||||
$("#necklace-tooltip").hide();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function set_input_style(type) {
|
||||
let item = itemMap.get($("#"+type+"-choice").val());
|
||||
if (item) {
|
||||
$("#"+type+"-choice").addClass(item.tier);
|
||||
if (type == 'weapon') {
|
||||
$("#"+type+"-img").attr('src', 'media/items/new/generic-'+item.type+'.png');
|
||||
}
|
||||
} else {
|
||||
$("#"+type+"-choice").attr('class', 'item-name');
|
||||
}
|
||||
}
|
||||
|
||||
function init_tooltip_loc(equipment){
|
||||
let ImgLoc = document.getElementById(equipment+'-img-loc').getBoundingClientRect();
|
||||
let tooltipRect = document.getElementById(equipment+"-tooltip").getBoundingClientRect();
|
||||
let windowHeight = $(window).height()
|
||||
|
||||
$("#"+equipment+"-tooltip").css('top', Math.min(ImgLoc.top, windowHeight - (tooltipRect.bottom - tooltipRect.top)));
|
||||
$("#"+equipment+"-tooltip").css('left', ImgLoc.right);
|
||||
}
|
||||
|
||||
function update_powder_count(type, alt="") {
|
||||
let item = itemMap.get($("#"+type+"-choice").val());
|
||||
if (item) {
|
||||
$("#"+type+"-powder").attr("placeholder", item["slots"]+" slots"+alt);
|
||||
}
|
||||
}
|
||||
|
||||
function init_equipUI() {
|
||||
for (const i in equipment_keys) {
|
||||
set_input_style(equipment_keys[i]);
|
||||
}
|
||||
update_powder_count('weapon');
|
||||
update_powder_count('helmet', '|example: t6t6');
|
||||
update_powder_count('chestplate');
|
||||
update_powder_count('leggings');
|
||||
update_powder_count('boots');
|
||||
}
|
||||
|
||||
// phanta method of handling input <3
|
||||
let calcBuildTask = null;
|
||||
let updateStatTask = null;
|
||||
let doSearchTask = null;
|
||||
|
||||
function calcBuildSchedule(){
|
||||
if (calcBuildTask !== null) {
|
||||
clearTimeout(calcBuildTask);
|
||||
}
|
||||
calcBuildTask = setTimeout(function(){
|
||||
calcBuildTask = null;
|
||||
calculateBuild();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function updateStatSchedule(){
|
||||
if (updateStatTask !== null) {
|
||||
clearTimeout(updateStatTask);
|
||||
}
|
||||
updateStatTask = setTimeout(function(){
|
||||
updateStatTask = null;
|
||||
updateStats();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function doSearchSchedule(){
|
||||
if (doSearchTask !== null) {
|
||||
clearTimeout(doSearchTask);
|
||||
}
|
||||
doSearchTask = setTimeout(function(){
|
||||
doSearchTask = null;
|
||||
doItemSearch();
|
||||
}, 500);
|
||||
}
|
437
sq2bs.css
Normal file
437
sq2bs.css
Normal file
|
@ -0,0 +1,437 @@
|
|||
* {
|
||||
font-family: 'Nunito', sans-serif;
|
||||
}
|
||||
|
||||
/* sidebar stuff */
|
||||
.sidebar {
|
||||
height: 100%; /* 100% Full-height */
|
||||
width: 3.5vw; /* 0 width - change this with JavaScript */
|
||||
position: fixed; /* Stay in place */
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden; /* Disable horizontal scroll */
|
||||
transition: 0.5s; /* 0.5 second transition effect to slide in the sidebar */
|
||||
}
|
||||
|
||||
.sidebar:hover {
|
||||
width: 11vw;
|
||||
}
|
||||
|
||||
.sidebar a {
|
||||
padding: .4vw .4vw .4vw .4vw;
|
||||
display: block;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar a img {
|
||||
margin-right: .6vw;
|
||||
width: 2.5vw;
|
||||
}
|
||||
|
||||
.sidebar a b {
|
||||
font-size: .8vw;
|
||||
}
|
||||
|
||||
.sidebar a:hover {
|
||||
background-color: hsl(0, 0%, 8%);
|
||||
color: rgb(210, 210, 210);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 992px) {
|
||||
.sidebar {display: none;}
|
||||
}
|
||||
|
||||
/* builder containers */
|
||||
|
||||
/* wynn-related css(es) */
|
||||
.positive {
|
||||
color: #5f5;
|
||||
}
|
||||
|
||||
.negative {
|
||||
color: #f55;
|
||||
}
|
||||
|
||||
.Health {
|
||||
color: #AA0000
|
||||
}
|
||||
|
||||
.Health:before {
|
||||
content: "\2764" ' ';
|
||||
}
|
||||
|
||||
.lvl:before {
|
||||
content: 'Lv. '
|
||||
}
|
||||
|
||||
.Damage {
|
||||
color: rgb(255, 198, 85)
|
||||
}
|
||||
|
||||
.Normal {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.Unique {
|
||||
color: #FFFF55 !important;
|
||||
}
|
||||
|
||||
.Rare {
|
||||
color: #FF55FF !important;
|
||||
}
|
||||
|
||||
.Legendary {
|
||||
color: #55FFFF !important;
|
||||
}
|
||||
|
||||
.Fabled {
|
||||
color: #FF5555 !important;
|
||||
}
|
||||
|
||||
.Mythic {
|
||||
color: #AA00AA !important;
|
||||
}
|
||||
|
||||
.Set {
|
||||
color: #5f5 !important;
|
||||
}
|
||||
|
||||
.eDam, .Earth, .Earth_powder {
|
||||
color: #00AA00;
|
||||
}
|
||||
|
||||
.eDam:before, .Earth:before, .Earth_powder:before { content: "\2724" ' '; }
|
||||
|
||||
.tDam, .Thunder, .Thunder_powder {
|
||||
color: #FFFF55;
|
||||
}
|
||||
|
||||
.tDam:before, .Thunder:before, .Thunder_powder:before { content: "\2726" ' '; }
|
||||
|
||||
.wDam, .Water, .Water_powder {
|
||||
color: #55FFFF
|
||||
}
|
||||
|
||||
.wDam:before, .Water:before, .Water_powder:before { content: "\2749" ' '; }
|
||||
|
||||
.fDam, .Fire, .Fire_powder {
|
||||
color: #FF5555;
|
||||
}
|
||||
|
||||
.fDam:before, .Fire:before, .Fire_powder:before { content: "\2739" ' '; }
|
||||
|
||||
.aDam, .Air, .Air_powder {
|
||||
color: #FFFFFF
|
||||
}
|
||||
|
||||
.aDam:before, .Air:before, .Air_powder:before { content: "\274b" ' '; }
|
||||
|
||||
.nDam, .Neutral {
|
||||
color: #FFAA00;
|
||||
}
|
||||
|
||||
.nDam:before, .Neutral:before {
|
||||
content: "\2724" ' ';
|
||||
}
|
||||
|
||||
.Mana {
|
||||
color: #5ff;
|
||||
}
|
||||
|
||||
.Mana:after {
|
||||
content: "\273A"
|
||||
}
|
||||
|
||||
/* equipment field specifics */
|
||||
/* inputs and dropdowns */
|
||||
.form-control {
|
||||
transition: none !important;
|
||||
box-shadow: none !important;
|
||||
width: 95% !important;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul.search-box {
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li.search-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li.search-item:hover {
|
||||
background-color: hsl(0, 0%, 11%) !important;
|
||||
}
|
||||
|
||||
/* boosts styles */
|
||||
.button-boost:hover {
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
}
|
||||
|
||||
.toggleOn {
|
||||
background-color: #0a0 !important;
|
||||
}
|
||||
|
||||
/* floating tooltip styles */
|
||||
.float-tooltip {
|
||||
background-color: hsl(0, 0%, 16%);
|
||||
position: absolute;
|
||||
transition: .3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* generic */
|
||||
|
||||
input {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input.equipment-input {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.spell-display p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.spell-display b {
|
||||
font-size: 3rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.spell-expand {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.scaled-font {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.skp-tooltip {
|
||||
font-size: 2.1875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.spellcost-tooltip b {
|
||||
font-size: 2.1875rem !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #ff8180;
|
||||
font-size: 1.875rem;
|
||||
margin-bottom: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.scaled-item-icon {
|
||||
width: 8rem;
|
||||
}
|
||||
|
||||
.scaled-item-icon img {
|
||||
width: 6.5rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd {
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd img {
|
||||
width: 6.5rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) and (max-width: 1400px) {
|
||||
.scaled-font {
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.skp-tooltip {
|
||||
font-size: .625rem;
|
||||
}
|
||||
|
||||
.spellcost-tooltip b {
|
||||
font-size: .625rem !important;
|
||||
}
|
||||
|
||||
.scaled-item-icon {
|
||||
width: 3.2rem;
|
||||
}
|
||||
|
||||
.scaled-item-icon img {
|
||||
width: 2.8rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd img {
|
||||
width: 2.8rem;
|
||||
}
|
||||
|
||||
.warning {
|
||||
font-size: .7rem;
|
||||
}
|
||||
|
||||
.spell-display b {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1400px) {
|
||||
.scaled-font {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.skp-tooltip {
|
||||
font-size: .78rem;
|
||||
}
|
||||
|
||||
.spellcost-tooltip b {
|
||||
font-size: .78rem !important;
|
||||
}
|
||||
|
||||
.scaled-item-icon {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.scaled-item-icon img {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd {
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
}
|
||||
|
||||
.scaled-bckgrd img {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
||||
|
||||
.warning {
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.spell-display b {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
/* WynnAtlas Mini */
|
||||
.search-field {
|
||||
background-color: hsl(0, 0%, 14%) !important;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
border-color: hsl(0, 0%, 8%);
|
||||
}
|
||||
|
||||
/* Fake button for build stats */
|
||||
.fake-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fake-button:hover {
|
||||
background-color: hsl(0, 0%, 14%) !important;
|
||||
}
|
||||
|
||||
/* material design dark mode */
|
||||
.dark-1 {
|
||||
background-color: hsl(0, 0%, 5%) !important;
|
||||
}
|
||||
|
||||
.dark-2 {
|
||||
background-color: hsl(0, 0%, 7%) !important;
|
||||
}
|
||||
|
||||
.dark-3 {
|
||||
background-color: hsl(0, 0%, 8%) !important;
|
||||
}
|
||||
|
||||
.dark-4 {
|
||||
background-color: hsl(0, 0%, 9%) !important;
|
||||
}
|
||||
|
||||
.dark-5 {
|
||||
background-color: hsl(0, 0%, 11%) !important;
|
||||
}
|
||||
|
||||
.dark-6 {
|
||||
background-color: hsl(0, 0%, 12%) !important;
|
||||
}
|
||||
|
||||
.dark-7 {
|
||||
background-color: hsl(0, 0%, 14%) !important;
|
||||
}
|
||||
|
||||
.dark-8 {
|
||||
background-color: hsl(0, 0%, 15%) !important;
|
||||
}
|
||||
|
||||
.dark-9 {
|
||||
background-color: hsl(0, 0%, 16%) !important;
|
||||
}
|
||||
|
||||
.dark-1u {
|
||||
background-color: hsl(0, 0%, 5%);
|
||||
}
|
||||
|
||||
.dark-2u {
|
||||
background-color: hsl(0, 0%, 7%);
|
||||
}
|
||||
|
||||
.dark-3u {
|
||||
background-color: hsl(0, 0%, 8%);
|
||||
}
|
||||
|
||||
.dark-4u {
|
||||
background-color: hsl(0, 0%, 9%);
|
||||
}
|
||||
|
||||
.dark-5u {
|
||||
background-color: hsl(0, 0%, 11%);
|
||||
}
|
||||
|
||||
.dark-6u {
|
||||
background-color: hsl(0, 0%, 12%);
|
||||
}
|
||||
|
||||
.dark-7u {
|
||||
background-color: hsl(0, 0%, 14%);
|
||||
}
|
||||
|
||||
.dark-8u {
|
||||
background-color: hsl(0, 0%, 15%);
|
||||
}
|
||||
|
||||
.dark-9u {
|
||||
background-color: hsl(0, 0%, 16%);
|
||||
}
|
||||
|
||||
.dark-shadow {
|
||||
box-shadow: 0rem 0rem 1.25rem 0.1875rem black;
|
||||
}
|
||||
|
||||
.dark-shadow-sm {
|
||||
box-shadow: 0rem 0rem 0.625rem 0.125rem black;
|
||||
}
|
||||
|
||||
.border-dark-7 {
|
||||
border-color:hsl(0, 0%, 14%) !important;
|
||||
}
|
1229
sq2bs.html
Normal file
1229
sq2bs.html
Normal file
File diff suppressed because it is too large
Load diff
385
sq2bs.js
Normal file
385
sq2bs.js
Normal file
|
@ -0,0 +1,385 @@
|
|||
let equipment_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace', 'weapon'];
|
||||
let weapon_keys = ['dagger', 'wand', 'bow', 'relik', 'spear'];
|
||||
let skp_keys = ['str', 'dex', 'int', 'def', 'agi'];
|
||||
|
||||
let spell_disp = ['spell0-info', 'spell1-info', 'spell2-info', 'spell3-info'];
|
||||
let other_disp = ['build-order', 'set-info', 'int-info'];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
for (const eq of equipment_keys) {
|
||||
document.querySelector("#"+eq+"-choice").setAttribute("oninput", "update_field('"+ eq +"'); calcBuildSchedule();");
|
||||
document.querySelector("#"+eq+"-powder").setAttribute("oninput", "calcBuildSchedule();");
|
||||
document.querySelector("#"+eq+"-tooltip").setAttribute("onclick", "collapse_element('#"+ eq +"-tooltip')");
|
||||
}
|
||||
|
||||
for (const i of spell_disp) {
|
||||
document.querySelector("#"+i+"Avg").setAttribute("onclick", "toggle_spell_tab('"+i+"')");
|
||||
}
|
||||
|
||||
document.querySelector("#level-choice").setAttribute("oninput", "calcBuildSchedule()")
|
||||
|
||||
let skp_fields = document.getElementsByClassName("skp-update");
|
||||
|
||||
for (i = 0; i < skp_fields.length; i++) {
|
||||
skp_fields[i].setAttribute("oninput", "updateStatSchedule()");
|
||||
}
|
||||
|
||||
let masonry = Macy({
|
||||
container: "#masonry-container",
|
||||
columns: 1,
|
||||
mobileFirst: true,
|
||||
breakAt: {
|
||||
1200: 4,
|
||||
},
|
||||
margin: {
|
||||
x: 20,
|
||||
y: 20,
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
let search_masonry = Macy({
|
||||
container: "#search-results",
|
||||
columns: 1,
|
||||
mobileFirst: true,
|
||||
breakAt: {
|
||||
1200: 4,
|
||||
},
|
||||
margin: {
|
||||
x: 20,
|
||||
y: 20,
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
document.querySelector("#search-container").addEventListener("keyup", function(event) {
|
||||
if (event.key === "Escape") {
|
||||
document.querySelector("#search-container").style.display = "none";
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// phanta scheduler
|
||||
let calcBuildTask = null;
|
||||
let updateStatTask = null;
|
||||
let doSearchTask = null;
|
||||
|
||||
function calcBuildSchedule(){
|
||||
if (calcBuildTask !== null) {
|
||||
clearTimeout(calcBuildTask);
|
||||
}
|
||||
calcBuildTask = setTimeout(function(){
|
||||
calcBuildTask = null;
|
||||
calculateBuild();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function updateStatSchedule(){
|
||||
if (updateStatTask !== null) {
|
||||
clearTimeout(updateStatTask);
|
||||
}
|
||||
updateStatTask = setTimeout(function(){
|
||||
updateStatTask = null;
|
||||
updateStats();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function doSearchSchedule(){
|
||||
if (doSearchTask !== null) {
|
||||
clearTimeout(doSearchTask);
|
||||
}
|
||||
doSearchTask = setTimeout(function(){
|
||||
doSearchTask = null;
|
||||
doItemSearch();
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// equipment field dynamic styling
|
||||
function update_field(field) {
|
||||
// built on the assumption of no one will type in CI/CR letter by letter
|
||||
// resets
|
||||
document.querySelector("#"+field+"-choice").classList.remove("text-light", "is-invalid", 'Normal', 'Unique', 'Rare', 'Legendary', 'Fabled', 'Mythic', 'Set');
|
||||
|
||||
item = document.querySelector("#"+field+"-choice").value
|
||||
let powder_slots;
|
||||
let tier;
|
||||
let category;
|
||||
let type;
|
||||
|
||||
// get item info
|
||||
if (item.slice(0, 3) == "CI-") {
|
||||
item = getCustomFromHash(item);
|
||||
powder_slots = item.statMap.get("slots");
|
||||
tier = item.statMap.get("tier");
|
||||
category = item.statMap.get("category");
|
||||
type = item.statMap.get("type");
|
||||
}
|
||||
else if (item.slice(0, 3) == "CR-") {
|
||||
item = getCraftFromHash(item);
|
||||
powder_slots = item.statMap.get("slots");
|
||||
tier = item.statMap.get("tier");
|
||||
category = item.statMap.get("category");
|
||||
type = item.statMap.get("type");
|
||||
}
|
||||
else if (itemMap.get(item)) {
|
||||
item = itemMap.get(item);
|
||||
if (!item) {return false;}
|
||||
powder_slots = item.slots;
|
||||
tier = item.tier;
|
||||
category = item.category;
|
||||
type = item.type;
|
||||
}
|
||||
else {
|
||||
// item not found
|
||||
document.querySelector("#"+field+"-choice").classList.add("text-light");
|
||||
if (item) { document.querySelector("#"+field+"-choice").classList.add("is-invalid"); }
|
||||
|
||||
document.querySelector("#"+equipment_keys[i]+"-powder").disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((type != field.replace(/[0-9]/g, '')) && (category != field.replace(/[0-9]/g, ''))) {
|
||||
document.querySelector("#"+field+"-choice").classList.add("text-light");
|
||||
if (item) { document.querySelector("#"+field+"-choice").classList.add("is-invalid"); }
|
||||
|
||||
document.querySelector("#"+equipment_keys[i]+"-powder").disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// set item color
|
||||
document.querySelector("#"+field+"-choice").classList.add(tier);
|
||||
|
||||
// set powder slots
|
||||
document.querySelector("#"+field+"-powder").setAttribute("placeholder", powder_slots+" slots");
|
||||
|
||||
if (powder_slots == 0) {
|
||||
document.querySelector("#"+field+"-powder").disabled = true;
|
||||
} else {
|
||||
document.querySelector("#"+field+"-powder").disabled = false;
|
||||
}
|
||||
|
||||
// set weapon img
|
||||
if (category == 'weapon') {
|
||||
document.querySelector("#weapon-img").setAttribute('src', 'media/items/new/generic-'+type+'.png');
|
||||
}
|
||||
|
||||
// call calc build
|
||||
}
|
||||
/* tabulars | man i hate this code but too lazy to fix /shrug */
|
||||
|
||||
let tabs = ['all-stats', 'minimal-offensive-stats', 'minimal-defensive-stats'];
|
||||
|
||||
function show_tab(tab) {
|
||||
console.log(itemFilters)
|
||||
for (const i in tabs) {
|
||||
document.querySelector("#"+tabs[i]).style.display = "none";
|
||||
}
|
||||
document.querySelector("#"+tab).style.display = "";
|
||||
}
|
||||
|
||||
function toggle_spell_tab(tab) {
|
||||
if (document.querySelector("#"+tab).style.display == "none") {
|
||||
document.querySelector("#"+tab).style.display = "";
|
||||
} else {
|
||||
document.querySelector("#"+tab).style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function toggle_boost_tab(tab) {
|
||||
for (const i of skp_keys) {
|
||||
document.querySelector("#"+i+"-boost").style.display = "none";
|
||||
}
|
||||
document.querySelector("#"+tab+"-boost").style.display = "";
|
||||
}
|
||||
|
||||
// toggle tab
|
||||
function toggle_tab(tab) {
|
||||
if (document.querySelector("#"+tab).style.display == "none") {
|
||||
document.querySelector("#"+tab).style.display = "";
|
||||
} else {
|
||||
document.querySelector("#"+tab).style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function collapse_element(elmnt) {
|
||||
elem_list = document.querySelector(elmnt).children;
|
||||
|
||||
for (elem of elem_list) {
|
||||
if (elem.classList.contains("no-collapse")) { continue; }
|
||||
if (elem.style.display == "none") {
|
||||
elem.style.display = "";
|
||||
} else {
|
||||
elem.style.display = "none";
|
||||
}
|
||||
}
|
||||
// macy quirk
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
// weird bug where display: none overrides??
|
||||
document.querySelector(elmnt).style.display = "";
|
||||
}
|
||||
|
||||
// search misc
|
||||
function set_item(item) {
|
||||
document.querySelector("#search-container").style.display = "none";
|
||||
let type;
|
||||
// if (!player_build) {return false;}
|
||||
if (item.get("category") === "weapon") {
|
||||
type = "weapon";
|
||||
} else if (item.get("type") === "ring") {
|
||||
if (!document.querySelector("#ring1-choice").value) {
|
||||
type = "ring1";
|
||||
} else {
|
||||
type = "ring2";
|
||||
}
|
||||
} else {
|
||||
type = item.get("type");
|
||||
}
|
||||
document.querySelector("#"+type+"-choice").value = item.get("displayName");
|
||||
calcBuildSchedule();
|
||||
update_field(type);
|
||||
}
|
||||
|
||||
// disable boosts
|
||||
|
||||
function reset_powder_specials() {
|
||||
let specials = ["Quake", "Chain_Lightning", "Curse", "Courage", "Wind_Prison"]
|
||||
for (const special of specials) {
|
||||
for (i = 1; i < 6; i++) {
|
||||
if (document.querySelector("#"+special+"-"+i).classList.contains("toggleOn")) {
|
||||
document.querySelector("#"+special+"-"+i).classList.remove("toggleOn");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// autocomplete initialize
|
||||
function init_autocomplete() {
|
||||
let dropdowns = new Map()
|
||||
for (const eq of equipment_keys) {
|
||||
// build dropdown
|
||||
console.log('init dropdown for '+ eq)
|
||||
let item_arr = [];
|
||||
if (eq == 'weapon') {
|
||||
for (const weaponType of weapon_keys) {
|
||||
for (const weapon of itemLists.get(weaponType)) {
|
||||
let item_obj = itemMap.get(weapon);
|
||||
if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") {
|
||||
continue;
|
||||
}
|
||||
if (item_obj["name"] == 'No '+ eq.charAt(0).toUpperCase() + eq.slice(1)) {
|
||||
continue;
|
||||
}
|
||||
item_arr.push(weapon);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const item of itemLists.get(eq.replace(/[0-9]/g, ''))) {
|
||||
let item_obj = itemMap.get(item);
|
||||
if (item_obj["restrict"] && item_obj["restrict"] === "DEPRECATED") {
|
||||
continue;
|
||||
}
|
||||
if (item_obj["name"] == 'No '+ eq.charAt(0).toUpperCase() + eq.slice(1)) {
|
||||
continue;
|
||||
}
|
||||
item_arr.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
// create dropdown
|
||||
dropdowns.set(eq, new autoComplete({
|
||||
data: {
|
||||
src: item_arr
|
||||
},
|
||||
selector: "#"+ eq +"-choice",
|
||||
wrapper: false,
|
||||
resultsList: {
|
||||
tabSelect: true,
|
||||
noResults: true,
|
||||
class: "search-box dark-7 rounded-bottom px-2 fw-bold dark-shadow-sm",
|
||||
element: (list, data) => {
|
||||
// dynamic result loc
|
||||
let position = document.getElementById(eq+'-dropdown').getBoundingClientRect();
|
||||
list.style.top = position.bottom + window.scrollY +"px";
|
||||
list.style.left = position.x+"px";
|
||||
list.style.width = position.width+"px";
|
||||
|
||||
if (!data.results.length) {
|
||||
message = document.createElement('li');
|
||||
message.classList.add('scaled-font');
|
||||
message.textContent = "No results found!";
|
||||
list.prepend(message);
|
||||
}
|
||||
},
|
||||
},
|
||||
resultItem: {
|
||||
class: "scaled-font search-item",
|
||||
selected: "dark-5",
|
||||
element: (item, data) => {
|
||||
item.classList.add(itemMap.get(data.value).tier);
|
||||
},
|
||||
},
|
||||
events: {
|
||||
input: {
|
||||
selection: (event) => {
|
||||
if (event.detail.selection.value) {
|
||||
event.target.value = event.detail.selection.value;
|
||||
}
|
||||
update_field(eq);
|
||||
calcBuildSchedule();
|
||||
},
|
||||
},
|
||||
}
|
||||
}));
|
||||
}
|
||||
let filter_loc = ["filter1", "filter2", "filter3", "filter4"];
|
||||
for (const i of filter_loc) {
|
||||
console.log(i);
|
||||
console.log('init dropdown for '+i+"-choice" )
|
||||
dropdowns.set(i+"-choice", new autoComplete({
|
||||
data: {
|
||||
src: itemFilters,
|
||||
},
|
||||
selector: "#"+i+"-choice",
|
||||
wrapper: false,
|
||||
resultsList: {
|
||||
tabSelect: true,
|
||||
noResults: true,
|
||||
class: "search-box dark-7 rounded-bottom px-2 fw-bold dark-shadow-sm",
|
||||
element: (list, data) => {
|
||||
// dynamic result loc
|
||||
console.log(i);
|
||||
list.style.zIndex = "100";
|
||||
let position = document.getElementById(i+"-dropdown").getBoundingClientRect();
|
||||
window_pos = document.getElementById("search-container").getBoundingClientRect();
|
||||
list.style.top = position.bottom - window_pos.top + 5 +"px";
|
||||
list.style.left = position.x - window_pos.x +"px";
|
||||
list.style.width = position.width+"px";
|
||||
|
||||
if (!data.results.length) {
|
||||
message = document.createElement('li');
|
||||
message.classList.add('scaled-font');
|
||||
message.textContent = "No filters found!";
|
||||
list.prepend(message);
|
||||
}
|
||||
},
|
||||
},
|
||||
resultItem: {
|
||||
class: "scaled-font search-item",
|
||||
selected: "dark-5",
|
||||
},
|
||||
events: {
|
||||
input: {
|
||||
selection: (event) => {
|
||||
if (event.detail.selection.value) {
|
||||
event.target.value = event.detail.selection.value;
|
||||
}
|
||||
doSearchSchedule();
|
||||
},
|
||||
},
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
551
sq2build.js
Normal file
551
sq2build.js
Normal file
|
@ -0,0 +1,551 @@
|
|||
|
||||
|
||||
const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.20], ["sword", 1.10]]);
|
||||
|
||||
/**
|
||||
* @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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
/*Class that represents a wynn player's build.
|
||||
*/
|
||||
class Build{
|
||||
|
||||
/**
|
||||
* @description Construct a build.
|
||||
* @param {Number} level : Level of the player.
|
||||
* @param {String[]} equipment : List of equipment names that make up the build.
|
||||
* In order: boots, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon.
|
||||
* @param {Number[]} powders : Powder application. List of lists of integers (powder IDs).
|
||||
* In order: boots, Chestplate, Leggings, Boots, Weapon.
|
||||
* @param {Object[]} inputerrors : List of instances of error-like classes.
|
||||
*/
|
||||
constructor(level,equipment, powders, externalStats, inputerrors=[]){
|
||||
|
||||
let errors = inputerrors;
|
||||
//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).
|
||||
this.craftedItems = [];
|
||||
this.customItems = [];
|
||||
// NOTE: powders is just an array of arrays of powder IDs. Not powder objects.
|
||||
this.powders = powders;
|
||||
if(itemMap.get(equipment[0]) && itemMap.get(equipment[0]).type === "helmet") {
|
||||
const helmet = itemMap.get(equipment[0]);
|
||||
this.powders[0] = this.powders[0].slice(0,helmet.slots);
|
||||
this.helmet = expandItem(helmet, this.powders[0]);
|
||||
} else {
|
||||
try {
|
||||
let helmet = getCustomFromHash(equipment[0]) ? getCustomFromHash(equipment[0]) : (getCraftFromHash(equipment[0]) ? getCraftFromHash(equipment[0]) : undefined);
|
||||
if (helmet.statMap.get("type") !== "helmet") {
|
||||
throw new Error("Not a helmet");
|
||||
}
|
||||
this.powders[0] = this.powders[0].slice(0,helmet.statMap.get("slots"));
|
||||
helmet.statMap.set("powders",this.powders[0].slice());
|
||||
this.helmet = helmet.statMap;
|
||||
applyArmorPowders(this.helmet, this.powders[0]);
|
||||
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);
|
||||
}
|
||||
|
||||
} catch (Error) {
|
||||
const helmet = itemMap.get("No Helmet");
|
||||
this.powders[0] = this.powders[0].slice(0,helmet.slots);
|
||||
this.helmet = expandItem(helmet, this.powders[0]);
|
||||
errors.push(new ItemNotFound(equipment[0], "helmet", true));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[1]) && itemMap.get(equipment[1]).type === "chestplate") {
|
||||
const chestplate = itemMap.get(equipment[1]);
|
||||
this.powders[1] = this.powders[1].slice(0,chestplate.slots);
|
||||
this.chestplate = expandItem(chestplate, this.powders[1]);
|
||||
} else {
|
||||
try {
|
||||
let chestplate = getCustomFromHash(equipment[1]) ? getCustomFromHash(equipment[1]) : (getCraftFromHash(equipment[1]) ? getCraftFromHash(equipment[1]) : undefined);
|
||||
if (chestplate.statMap.get("type") !== "chestplate") {
|
||||
throw new Error("Not a chestplate");
|
||||
}
|
||||
this.powders[1] = this.powders[1].slice(0,chestplate.statMap.get("slots"));
|
||||
chestplate.statMap.set("powders",this.powders[1].slice());
|
||||
this.chestplate = chestplate.statMap;
|
||||
applyArmorPowders(this.chesplate, this.powders[1]);
|
||||
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);
|
||||
}
|
||||
} catch (Error) {
|
||||
console.log(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));
|
||||
}
|
||||
}
|
||||
if (itemMap.get(equipment[2]) && itemMap.get(equipment[2]).type === "leggings") {
|
||||
const leggings = itemMap.get(equipment[2]);
|
||||
this.powders[2] = this.powders[2].slice(0,leggings.slots);
|
||||
this.leggings = expandItem(leggings, this.powders[2]);
|
||||
} else {
|
||||
try {
|
||||
let leggings = getCustomFromHash(equipment[2]) ? getCustomFromHash(equipment[2]) : (getCraftFromHash(equipment[2]) ? getCraftFromHash(equipment[2]) : undefined);
|
||||
if (leggings.statMap.get("type") !== "leggings") {
|
||||
throw new Error("Not a leggings");
|
||||
}
|
||||
this.powders[2] = this.powders[2].slice(0,leggings.statMap.get("slots"));
|
||||
leggings.statMap.set("powders",this.powders[2].slice());
|
||||
this.leggings = leggings.statMap;
|
||||
applyArmorPowders(this.leggings, this.powders[2]);
|
||||
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);
|
||||
}
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
if (itemMap.get(equipment[3]) && itemMap.get(equipment[3]).type === "boots") {
|
||||
const boots = itemMap.get(equipment[3]);
|
||||
this.powders[3] = this.powders[3].slice(0,boots.slots);
|
||||
this.boots = expandItem(boots, this.powders[3]);
|
||||
} else {
|
||||
try {
|
||||
let boots = getCustomFromHash(equipment[3]) ? getCustomFromHash(equipment[3]) : (getCraftFromHash(equipment[3]) ? getCraftFromHash(equipment[3]) : undefined);
|
||||
if (boots.statMap.get("type") !== "boots") {
|
||||
throw new Error("Not a boots");
|
||||
}
|
||||
this.powders[3] = this.powders[3].slice(0,boots.statMap.get("slots"));
|
||||
boots.statMap.set("powders",this.powders[3].slice());
|
||||
this.boots = boots.statMap;
|
||||
applyArmorPowders(this.boots, this.powders[3]);
|
||||
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);
|
||||
}
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[4]) && itemMap.get(equipment[4]).type === "ring") {
|
||||
const ring = itemMap.get(equipment[4]);
|
||||
this.ring1 = expandItem(ring, []);
|
||||
}else{
|
||||
try {
|
||||
let ring = getCustomFromHash(equipment[4]) ? getCustomFromHash(equipment[4]) : (getCraftFromHash(equipment[4]) ? getCraftFromHash(equipment[4]) : undefined);
|
||||
if (ring.statMap.get("type") !== "ring") {
|
||||
throw new Error("Not a ring");
|
||||
}
|
||||
this.ring1 = ring.statMap;
|
||||
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);
|
||||
}
|
||||
} catch (Error) {
|
||||
const ring = itemMap.get("No Ring 1");
|
||||
this.ring1 = expandItem(ring, []);
|
||||
errors.push(new ItemNotFound(equipment[4], "ring1", true, "ring"));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[5]) && itemMap.get(equipment[5]).type === "ring") {
|
||||
const ring = itemMap.get(equipment[5]);
|
||||
this.ring2 = expandItem(ring, []);
|
||||
}else{
|
||||
try {
|
||||
let ring = getCustomFromHash(equipment[5]) ? getCustomFromHash(equipment[5]) : (getCraftFromHash(equipment[5]) ? getCraftFromHash(equipment[5]) : undefined);
|
||||
if (ring.statMap.get("type") !== "ring") {
|
||||
throw new Error("Not a ring");
|
||||
}
|
||||
this.ring2 = ring.statMap;
|
||||
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);
|
||||
}
|
||||
} catch (Error) {
|
||||
const ring = itemMap.get("No Ring 2");
|
||||
this.ring2 = expandItem(ring, []);
|
||||
errors.push(new ItemNotFound(equipment[5], "ring2", true, "ring"));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[6]) && itemMap.get(equipment[6]).type === "bracelet") {
|
||||
const bracelet = itemMap.get(equipment[6]);
|
||||
this.bracelet = expandItem(bracelet, []);
|
||||
}else{
|
||||
try {
|
||||
let bracelet = getCustomFromHash(equipment[6]) ? getCustomFromHash(equipment[6]) : (getCraftFromHash(equipment[6]) ? getCraftFromHash(equipment[6]) : undefined);
|
||||
if (bracelet.statMap.get("type") !== "bracelet") {
|
||||
throw new Error("Not a bracelet");
|
||||
}
|
||||
this.bracelet = bracelet.statMap;
|
||||
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);
|
||||
}
|
||||
} catch (Error) {
|
||||
const bracelet = itemMap.get("No Bracelet");
|
||||
this.bracelet = expandItem(bracelet, []);
|
||||
errors.push(new ItemNotFound(equipment[6], "bracelet", true));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[7]) && itemMap.get(equipment[7]).type === "necklace") {
|
||||
const necklace = itemMap.get(equipment[7]);
|
||||
this.necklace = expandItem(necklace, []);
|
||||
}else{
|
||||
try {
|
||||
let necklace = getCustomFromHash(equipment[7]) ? getCustomFromHash(equipment[7]) : (getCraftFromHash(equipment[7]) ? getCraftFromHash(equipment[7]) : undefined);
|
||||
if (necklace.statMap.get("type") !== "necklace") {
|
||||
throw new Error("Not a necklace");
|
||||
}
|
||||
this.necklace = necklace.statMap;
|
||||
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);
|
||||
}
|
||||
} catch (Error) {
|
||||
const necklace = itemMap.get("No Necklace");
|
||||
this.necklace = expandItem(necklace, []);
|
||||
errors.push(new ItemNotFound(equipment[7], "necklace", true));
|
||||
}
|
||||
}
|
||||
if(itemMap.get(equipment[8]) && itemMap.get(equipment[8]).category === "weapon") {
|
||||
const weapon = itemMap.get(equipment[8]);
|
||||
this.powders[4] = this.powders[4].slice(0,weapon.slots);
|
||||
this.weapon = expandItem(weapon, this.powders[4]);
|
||||
}else{
|
||||
try {
|
||||
let weapon = getCustomFromHash(equipment[8]) ? getCustomFromHash(equipment[8]) : (getCraftFromHash(equipment[8]) ? getCraftFromHash(equipment[8]) : undefined);
|
||||
if (weapon.statMap.get("category") !== "weapon") {
|
||||
throw new Error("Not a weapon");
|
||||
}
|
||||
this.weapon = weapon.statMap;
|
||||
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);
|
||||
}
|
||||
this.powders[4] = this.powders[4].slice(0,this.weapon.get("slots"));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(this.craftedItems)
|
||||
|
||||
if (level < 1) { //Should these be constants?
|
||||
this.level = 1;
|
||||
} else if (level > 106) {
|
||||
this.level = 106;
|
||||
} else if (level <= 106 && level >= 1) {
|
||||
this.level = level;
|
||||
} else if (typeof level === "string") {
|
||||
this.level = level;
|
||||
errors.push(new IncorrectInput(level, "a number", "level-choice"));
|
||||
} else {
|
||||
errors.push("Level is not a string or number.");
|
||||
}
|
||||
document.getElementById("level-choice").value = this.level;
|
||||
|
||||
this.availableSkillpoints = levelToSkillPoints(this.level);
|
||||
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]);
|
||||
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
||||
let result = calculate_skillpoints(this.equipment, this.weapon);
|
||||
console.log(result);
|
||||
this.equip_order = result[0];
|
||||
// How many skillpoints the player had to assign (5 number)
|
||||
this.base_skillpoints = result[1];
|
||||
// How many skillpoints the build ended up with (5 number)
|
||||
this.total_skillpoints = result[2];
|
||||
// How many skillpoints assigned (1 number, sum of base_skillpoints)
|
||||
this.assigned_skillpoints = result[3];
|
||||
this.activeSetCounts = result[4];
|
||||
|
||||
// For strength boosts like warscream, vanish, etc.
|
||||
this.damageMultiplier = 1.0;
|
||||
this.defenseMultiplier = 1.0;
|
||||
|
||||
// For other external boosts ;-;
|
||||
this.externalStats = externalStats;
|
||||
|
||||
this.initBuildStats();
|
||||
|
||||
// Remove every error before adding specific ones
|
||||
for (let i of document.getElementsByClassName("error")) {
|
||||
i.textContent = "";
|
||||
}
|
||||
this.errors = errors;
|
||||
if (errors.length > 0) this.errored = true;
|
||||
}
|
||||
|
||||
/*Returns build in string format
|
||||
*/
|
||||
toString(){
|
||||
return [this.equipment,this.weapon].flat();
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
|
||||
getSpellCost(spellIdx, cost) {
|
||||
return Math.max(1, this.getBaseSpellCost(spellIdx, cost));
|
||||
}
|
||||
|
||||
getBaseSpellCost(spellIdx, cost) {
|
||||
cost = Math.ceil(cost * (1 - skillPointsToPercentage(this.total_skillpoints[2])));
|
||||
cost += this.statMap.get("spRaw"+spellIdx);
|
||||
return Math.floor(cost * (1 + this.statMap.get("spPct"+spellIdx) / 100));
|
||||
}
|
||||
|
||||
|
||||
/* Get melee stats for build.
|
||||
Returns an array in the order:
|
||||
*/
|
||||
getMeleeStats(){
|
||||
const stats = this.statMap;
|
||||
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")]);
|
||||
}
|
||||
let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier");
|
||||
if(adjAtkSpd > 6){
|
||||
adjAtkSpd = 6;
|
||||
}else if(adjAtkSpd < 0){
|
||||
adjAtkSpd = 0;
|
||||
}
|
||||
|
||||
let damage_mult = 1;
|
||||
if (this.weapon.get("type") === "relik") {
|
||||
damage_mult = 0.99; // CURSE YOU WYNNCRAFT
|
||||
//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.
|
||||
}
|
||||
// 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);
|
||||
|
||||
let dex = this.total_skillpoints[1];
|
||||
|
||||
let totalDamNorm = results[0];
|
||||
let totalDamCrit = results[1];
|
||||
totalDamNorm.push(1-skillPointsToPercentage(dex));
|
||||
totalDamCrit.push(skillPointsToPercentage(dex));
|
||||
let damages_results = results[2];
|
||||
|
||||
let singleHitTotal = ((totalDamNorm[0]+totalDamNorm[1])*(totalDamNorm[2])
|
||||
+(totalDamCrit[0]+totalDamCrit[1])*(totalDamCrit[2]))/2;
|
||||
|
||||
//Now do math
|
||||
let normDPS = (totalDamNorm[0]+totalDamNorm[1])/2 * baseDamageMultiplier[adjAtkSpd];
|
||||
let critDPS = (totalDamCrit[0]+totalDamCrit[1])/2 * baseDamageMultiplier[adjAtkSpd];
|
||||
let avgDPS = (normDPS * (1 - skillPointsToPercentage(dex))) + (critDPS * (skillPointsToPercentage(dex)));
|
||||
//[[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]
|
||||
return damages_results.concat([totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS,adjAtkSpd, singleHitTotal]).concat(results[3]);
|
||||
}
|
||||
|
||||
/*
|
||||
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");
|
||||
if (totalHp < 5) totalHp = 5;
|
||||
defenseStats.push(totalHp);
|
||||
//EHP
|
||||
let ehp = [totalHp, totalHp];
|
||||
let defMult = classDefenseMultipliers.get(this.weapon.get("type"));
|
||||
ehp[0] /= ((1-def_pct)*(1-agi_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
ehp[1] /= ((1-def_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
defenseStats.push(ehp);
|
||||
//HPR
|
||||
let totalHpr = rawToPct(stats.get("hprRaw"), stats.get("hprPct")/100.);
|
||||
defenseStats.push(totalHpr);
|
||||
//EHPR
|
||||
let ehpr = [totalHpr, totalHpr];
|
||||
ehpr[0] /= ((1-def_pct)*(1-agi_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
ehpr[1] /= ((1-def_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
defenseStats.push(ehpr);
|
||||
//skp stats
|
||||
defenseStats.push([ (1 - ((1-def_pct) * (2 - this.defenseMultiplier)))*100, agi_pct*100]);
|
||||
//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);
|
||||
|
||||
//[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]]
|
||||
return defenseStats;
|
||||
}
|
||||
|
||||
/* Get all stats for this build. Stores in this.statMap.
|
||||
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
||||
*/
|
||||
initBuildStats(){
|
||||
|
||||
let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef", "str", "dex", "int", "def", "agi"];
|
||||
|
||||
//Create a map of this build's stats
|
||||
let statMap = new Map();
|
||||
|
||||
for (const staticID of staticIDs) {
|
||||
statMap.set(staticID, 0);
|
||||
}
|
||||
statMap.set("hp", levelToHPBase(this.level));
|
||||
|
||||
let major_ids = new Set();
|
||||
for (const item of this.items){
|
||||
for (let [id, value] of item.get("maxRolls")) {
|
||||
if (staticIDs.includes(id)) {
|
||||
continue;
|
||||
}
|
||||
statMap.set(id,(statMap.get(id) || 0)+value);
|
||||
}
|
||||
for (const staticID of staticIDs) {
|
||||
if (item.get(staticID)) {
|
||||
statMap.set(staticID, statMap.get(staticID) + item.get(staticID));
|
||||
}
|
||||
}
|
||||
if (item.get("majorIds")) {
|
||||
for (const major_id of item.get("majorIds")) {
|
||||
major_ids.add(major_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
statMap.set("activeMajorIDs", major_ids);
|
||||
for (const [setName, count] of this.activeSetCounts) {
|
||||
const bonus = sets[setName].bonuses[count-1];
|
||||
for (const id in bonus) {
|
||||
if (skp_order.includes(id)) {
|
||||
// pass. Don't include skillpoints in ids
|
||||
}
|
||||
else {
|
||||
statMap.set(id,(statMap.get(id) || 0)+bonus[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
statMap.set("poisonPct", 100);
|
||||
|
||||
// The stuff relevant for damage calculation!!! @ferricles
|
||||
statMap.set("atkSpd", this.weapon.get("atkSpd"));
|
||||
|
||||
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]);
|
||||
this.externalStats.set("poisonPct", 0);
|
||||
this.statMap = statMap;
|
||||
|
||||
this.aggregateStats();
|
||||
}
|
||||
|
||||
aggregateStats() {
|
||||
let statMap = this.statMap;
|
||||
statMap.set("damageRaw", [this.weapon.get("nDam"), this.weapon.get("eDam"), this.weapon.get("tDam"), this.weapon.get("wDam"), this.weapon.get("fDam"), this.weapon.get("aDam")]);
|
||||
statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]);
|
||||
statMap.set("defRaw", [statMap.get("eDef"), statMap.get("tDef"), statMap.get("wDef"), statMap.get("fDef"), statMap.get("aDef")]);
|
||||
statMap.set("defBonus", [statMap.get("eDefPct"), statMap.get("tDefPct"), statMap.get("wDefPct"), statMap.get("fDefPct"), statMap.get("aDefPct")]);
|
||||
statMap.set("defMult", classDefenseMultipliers.get(this.weapon.get("type")));
|
||||
}
|
||||
}
|
985
sq2builder.js
Normal file
985
sq2builder.js
Normal file
|
@ -0,0 +1,985 @@
|
|||
const url_tag = location.hash.slice(1);
|
||||
// console.log(url_base);
|
||||
// console.log(url_tag);
|
||||
|
||||
|
||||
const BUILD_VERSION = "7.0.19";
|
||||
|
||||
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);
|
||||
}*/
|
||||
|
||||
for (let i of skp_order) {
|
||||
let elem = document.getElementById(i+"-skp");
|
||||
elem.addEventListener("change", (event) => {
|
||||
elem.classList.add("highlight");
|
||||
});
|
||||
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"
|
||||
];
|
||||
let equipment_names = [
|
||||
"Helmet",
|
||||
"Chestplate",
|
||||
"Leggings",
|
||||
"Boots",
|
||||
"Ring 1",
|
||||
"Ring 2",
|
||||
"Bracelet",
|
||||
"Necklace",
|
||||
"Weapon"
|
||||
];
|
||||
let equipmentInputs = equipment_fields.map(x => x + "-choice");
|
||||
let buildFields = equipment_fields.map(x => x+"-tooltip");
|
||||
|
||||
let powderInputs = [
|
||||
"helmet-powder",
|
||||
"chestplate-powder",
|
||||
"leggings-powder",
|
||||
"boots-powder",
|
||||
"weapon-powder",
|
||||
];
|
||||
|
||||
function init() {
|
||||
console.log("builder.js init");
|
||||
init_autocomplete();
|
||||
for (const i of equipment_keys) {
|
||||
update_field(i);
|
||||
}
|
||||
decodeBuild(url_tag);
|
||||
}
|
||||
|
||||
function getItemNameFromID(id) {
|
||||
if (redirectMap.has(id)) {
|
||||
return getItemNameFromID(redirectMap.get(id));
|
||||
}
|
||||
return idMap.get(id);
|
||||
}
|
||||
|
||||
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));
|
||||
console.log(n_blocks + " blocks");
|
||||
powder_info = powder_info.slice(1);
|
||||
for (let j = 0; j < n_blocks; ++j) {
|
||||
let block = powder_info.slice(0,5);
|
||||
console.log(block);
|
||||
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;
|
||||
}
|
||||
return powdering;
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate fields based on url, and calculate build.
|
||||
*/
|
||||
function decodeBuild(url_tag) {
|
||||
if (url_tag) {
|
||||
let equipment = [null, null, null, null, null, null, null, null, null];
|
||||
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;
|
||||
if (version === "0" || version === "1" || version === "2" || version === "3") {
|
||||
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);
|
||||
}
|
||||
if (version === "4") {
|
||||
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);
|
||||
}
|
||||
if (version === "5") {
|
||||
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);
|
||||
}
|
||||
if (version === "1") {
|
||||
let powder_info = info[1];
|
||||
powdering = parsePowdering(powder_info);
|
||||
} else if (version === "2") {
|
||||
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);
|
||||
powdering = parsePowdering(powder_info);
|
||||
} else if (version === "3" || version === "4" || version === "5"){
|
||||
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);
|
||||
|
||||
powdering = parsePowdering(powder_info);
|
||||
}
|
||||
|
||||
for (let i in powderInputs) {
|
||||
setValue(powderInputs[i], powdering[i]);
|
||||
}
|
||||
for (let i in equipment) {
|
||||
setValue(equipmentInputs[i], equipment[i]);
|
||||
}
|
||||
calculateBuild(save_skp, skillpoints);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stores the entire build in a string using B64 encryption and adds it to the URL.
|
||||
*/
|
||||
function encodeBuild() {
|
||||
|
||||
if (player_build) {
|
||||
let build_string;
|
||||
if (player_build.customItems.length > 0) { //v5 encoding
|
||||
build_string = "5_";
|
||||
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;
|
||||
} else if (item.get("crafted")) {
|
||||
build_string += "CR-"+encodeCraft(player_build.craftedItems[crafted_idx]);
|
||||
crafted_idx += 1;
|
||||
} else {
|
||||
build_string += Base64.fromIntN(item.get("id"), 3);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
build_string += Base64.fromIntN(powder_hash, 5);
|
||||
powderset = powderset.slice(6);
|
||||
}
|
||||
}
|
||||
} else { //v4 encoding
|
||||
build_string = "4_";
|
||||
let crafted_idx = 0;
|
||||
for (const item of player_build.items) {
|
||||
if (item.get("crafted")) {
|
||||
build_string += "-"+encodeCraft(player_build.craftedItems[crafted_idx]);
|
||||
crafted_idx += 1;
|
||||
} else {
|
||||
build_string += Base64.fromIntN(item.get("id"), 3);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
build_string += Base64.fromIntN(powder_hash, 5);
|
||||
powderset = powderset.slice(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
return build_string;
|
||||
}
|
||||
// this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ];
|
||||
// let build_string = "3_" + Base64.fromIntN(player_build.helmet.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.chestplate.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.leggings.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.boots.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.ring1.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.ring2.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.bracelet.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.necklace.get("id"), 3) +
|
||||
// Base64.fromIntN(player_build.weapon.get("id"), 3);
|
||||
return "";
|
||||
}
|
||||
|
||||
function calculateBuild(save_skp, skp){
|
||||
try {
|
||||
/*
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(player_build){
|
||||
reset_powder_specials();
|
||||
updateBoosts("skip", false);
|
||||
updatePowderSpecials("skip", false);
|
||||
}
|
||||
let weaponName = getValue(equipmentInputs[8]);
|
||||
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;
|
||||
/* TODO: implement level changing
|
||||
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);
|
||||
console.log(powder);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
let level = document.getElementById("level-choice").value;
|
||||
player_build = new Build(level, equipment, powderings, new Map(), errors);
|
||||
console.log(player_build);
|
||||
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());
|
||||
displaysq2EquipOrder(document.getElementById("build-order"),player_build.equip_order);
|
||||
|
||||
const assigned = player_build.base_skillpoints;
|
||||
const skillpoints = player_build.total_skillpoints;
|
||||
for (let i in skp_order){ //big bren
|
||||
setText(skp_order[i] + "-skp-base", "Original: " + skillpoints[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
calculateBuildStats();
|
||||
// setTitle();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Updates all build statistics based on (for now) the skillpoint input fields and then calculates build stats.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
updateBoosts("skip", false);
|
||||
}
|
||||
/*
|
||||
for (let id of editable_item_fields) {
|
||||
player_build.statMap.set(id, parseInt(getValue(id)));
|
||||
console.log(player_build.statMap.get(id));
|
||||
}
|
||||
}*/
|
||||
player_build.aggregateStats();
|
||||
console.log(player_build.statMap);
|
||||
calculateBuildStats();
|
||||
}
|
||||
/* Updates all spell boosts
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/* Updates all powder special boosts
|
||||
*/
|
||||
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();
|
||||
}
|
||||
displaysq2PowderSpecials(document.getElementById("powder-special-stats"), powderSpecials, player_build, true);
|
||||
}
|
||||
|
||||
/* Calculates all build statistics and updates the entire display.
|
||||
*/
|
||||
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
|
||||
setText(skp_order[i] + "-skp-assign", "Assign: " + assigned[i]);
|
||||
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 td = document.createElement("p");
|
||||
|
||||
let remainingSkp = document.createElement("p");
|
||||
remainingSkp.classList.add("scaled-font");
|
||||
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)){
|
||||
let skpWarning = document.createElement("span");
|
||||
//skpWarning.classList.add("itemp");
|
||||
skpWarning.classList.add("warning");
|
||||
// skpWarning.classList.add("skp-tooltip");
|
||||
skpWarning.textContent = "WARNING: Too many skillpoints need to be assigned!";
|
||||
let skpCount = document.createElement("p");
|
||||
skpCount.classList.add("warning");
|
||||
// skpCount.classList.add("skp-tooltip");
|
||||
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) {
|
||||
if (player_build.items[i].get("id") > 9999) {
|
||||
continue;
|
||||
}
|
||||
displaysq2ExpandedItem(player_build.items[i], buildFields[i]);
|
||||
collapse_element("#"+equipment_keys[i]+"-tooltip");
|
||||
}
|
||||
|
||||
displaysq2ArmorStats(player_build);
|
||||
displaysq2BuildStats("all-stats", player_build, build_all_display_commands);
|
||||
displaysq2BuildStats("minimal-offensive-stats",player_build, build_offensive_display_commands);
|
||||
displaysq2SetBonuses("set-info",player_build);
|
||||
|
||||
let meleeStats = player_build.getMeleeStats();
|
||||
displaysq2MeleeDamage(document.getElementById("build-melee-stats"), document.getElementById("build-melee-statsAvg"), meleeStats);
|
||||
|
||||
displaysq2DefenseStats(document.getElementById("minimal-defensive-stats"),player_build);
|
||||
|
||||
displaysq2PoisonDamage(document.getElementById("build-poison-stats"),player_build);
|
||||
|
||||
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");
|
||||
displaysq2SpellDamage(parent_elem, overallparent_elem, player_build, spells[i], i+1);
|
||||
}
|
||||
|
||||
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!";
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
function saveBuild() {
|
||||
if (player_build) {
|
||||
const savedBuilds = window.localStorage.getItem("builds") === null ? {} : JSON.parse(window.localStorage.getItem("builds"));
|
||||
const saveName = document.getElementById("build-name").value;
|
||||
const encodedBuild = encodeBuild();
|
||||
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 = "";
|
||||
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);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
|
||||
function optimizeStrDex() {
|
||||
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];
|
||||
if (Math.min(remaining, max_str_boost, max_dex_boost) < 0) return; // Unwearable
|
||||
|
||||
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();
|
||||
setTitle();
|
||||
if (player_build.errored)
|
||||
throw new ListError(player_build.errors);
|
||||
}
|
||||
catch (error) {
|
||||
handleBuilderError(error);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Learn and use await
|
||||
function init2() {
|
||||
load_ing_init(init);
|
||||
}
|
||||
load_init(init2);
|
1468
sq2display.js
Normal file
1468
sq2display.js
Normal file
File diff suppressed because it is too large
Load diff
108
sq2display_constants.js
Normal file
108
sq2display_constants.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Display commands
|
||||
*/
|
||||
let build_all_display_commands = [
|
||||
"#defense-stats",
|
||||
"str", "dex", "int", "def", "agi",
|
||||
"mr", "ms",
|
||||
"hprRaw", "hprPct",
|
||||
"sdRaw", "sdPct",
|
||||
"mdRaw", "mdPct",
|
||||
"ref", "thorns",
|
||||
"ls",
|
||||
"poison",
|
||||
"expd",
|
||||
"spd",
|
||||
"atkTier",
|
||||
"!elemental",
|
||||
"fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct",
|
||||
"!elemental",
|
||||
"spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4",
|
||||
"rainbowRaw",
|
||||
"sprint", "sprintReg",
|
||||
"jh",
|
||||
"xpb", "lb", "lq",
|
||||
"spRegen",
|
||||
"eSteal",
|
||||
"gXp", "gSpd",
|
||||
];
|
||||
|
||||
let build_offensive_display_commands = [
|
||||
"str", "dex", "int", "def", "agi",
|
||||
"mr", "ms",
|
||||
"sdRaw", "sdPct",
|
||||
"mdRaw", "mdPct",
|
||||
"ref", "thorns",
|
||||
"ls",
|
||||
"poison",
|
||||
"expd",
|
||||
"spd",
|
||||
"atkTier",
|
||||
"rainbowRaw",
|
||||
"!elemental",
|
||||
"fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct",
|
||||
"!elemental",
|
||||
"spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4",
|
||||
];
|
||||
|
||||
let build_basic_display_commands = [
|
||||
'#defense-stats',
|
||||
// defense stats [hp, ehp, hpr, ]
|
||||
// "sPot", // base * atkspd + spell raws
|
||||
// melee potential
|
||||
// "mPot", // melee% * (base * atkspd) + melee raws
|
||||
"mr", "ms",
|
||||
"ls",
|
||||
"poison",
|
||||
"spd",
|
||||
"atkTier",
|
||||
]
|
||||
|
||||
let sq2_item_display_commands = [
|
||||
"displayName",
|
||||
"atkSpd",
|
||||
"!elemental",
|
||||
"hp",
|
||||
"nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_",
|
||||
"!spacer",
|
||||
"fDef", "wDef", "aDef", "tDef", "eDef",
|
||||
"!elemental",
|
||||
"classReq",
|
||||
"lvl",
|
||||
"strReq", "dexReq", "intReq", "defReq","agiReq",
|
||||
"!spacer",
|
||||
"str", "dex", "int", "def", "agi",
|
||||
"hpBonus",
|
||||
"hprRaw", "hprPct",
|
||||
"sdRaw", "sdPct",
|
||||
"mdRaw", "mdPct",
|
||||
"mr", "ms",
|
||||
"ref", "thorns",
|
||||
"ls",
|
||||
"poison",
|
||||
"expd",
|
||||
"spd",
|
||||
"atkTier",
|
||||
"!elemental",
|
||||
"fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct",
|
||||
"fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct",
|
||||
"!elemental",
|
||||
"spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4",
|
||||
"rainbowRaw",
|
||||
"sprint", "sprintReg",
|
||||
"jh",
|
||||
"xpb", "lb", "lq",
|
||||
"spRegen",
|
||||
"eSteal",
|
||||
"gXp", "gSpd",
|
||||
"majorIds",
|
||||
"!spacer",
|
||||
"slots",
|
||||
"!spacer",
|
||||
"set",
|
||||
"lore",
|
||||
"quest",
|
||||
"restrict"
|
||||
];
|
||||
|
||||
|
6
sq2icons.js
Normal file
6
sq2icons.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
//which icons to use
|
||||
let window_storage = window.localStorage;
|
||||
console.log(window_storage);
|
||||
icon_state_stored = window_storage.getItem("newicons");
|
||||
newIcons = true;
|
||||
if (icon_state_stored === "false") {toggleIcons()}
|
195
sq2items.js
Normal file
195
sq2items.js
Normal file
|
@ -0,0 +1,195 @@
|
|||
|
||||
|
||||
const translate_mappings = {
|
||||
//"Name": "name",
|
||||
//"Display Name": "displayName",
|
||||
//"tier"Tier": ",
|
||||
//"Set": "set",
|
||||
"Powder Slots": "slots",
|
||||
//"Type": "type",
|
||||
//"armorType", (deleted)
|
||||
//"color", (deleted)
|
||||
//"lore", (deleted)
|
||||
//"material", (deleted)
|
||||
"Drop type": "drop",
|
||||
"Quest requirement": "quest",
|
||||
"Restriction": "restrict",
|
||||
//"Base Neutral Damage": "nDam",
|
||||
//"Base Fire Damage": "fDam",
|
||||
//"Base Water Damage": "wDam",
|
||||
//"Base Air Damage": "aDam",
|
||||
//"Base Thunder Damage": "tDam",
|
||||
//"Base Earth Damage": "eDam",
|
||||
//"Base Attack Speed": "atkSpd",
|
||||
"Health": "hp",
|
||||
"Raw Fire Defense": "fDef",
|
||||
"Raw Water Defense": "wDef",
|
||||
"Raw Air Defense": "aDef",
|
||||
"Raw Thunder Defense": "tDef",
|
||||
"Raw Earth Defense": "eDef",
|
||||
"Combat Level": "lvl",
|
||||
//"Class Requirement": "classReq",
|
||||
"Req Strength": "strReq",
|
||||
"Req Dexterity": "dexReq",
|
||||
"Req Intelligence": "intReq",
|
||||
"Req Agility": "agiReq",
|
||||
"Req Defense": "defReq",
|
||||
"% Health Regen": "hprPct",
|
||||
"Mana Regen": "mr",
|
||||
"% Spell Damage": "sdPct",
|
||||
"% Melee Damage": "mdPct",
|
||||
"Life Steal": "ls",
|
||||
"Mana Steal": "ms",
|
||||
"XP Bonus": "xpb",
|
||||
"Loot Bonus": "lb",
|
||||
"Reflection": "ref",
|
||||
"Strength": "str",
|
||||
"Dexterity": "dex",
|
||||
"Intelligence": "int",
|
||||
"Agility": "agi",
|
||||
"Defense": "def",
|
||||
"Thorns": "thorns",
|
||||
"Exploding": "expd",
|
||||
"Walk Speed": "spd",
|
||||
"Attack Speed Bonus": "atkTier",
|
||||
"Poison": "poison",
|
||||
"Health Bonus": "hpBonus",
|
||||
"Soul Point Regen": "spRegen",
|
||||
"Stealing": "eSteal",
|
||||
"Raw Health Regen": "hprRaw",
|
||||
"Raw Spell": "sdRaw",
|
||||
"Raw Melee": "mdRaw",
|
||||
"% Fire Damage": "fDamPct",
|
||||
"% Water Damage": "wDamPct",
|
||||
"% Air Damage": "aDamPct",
|
||||
"% Thunder Damage": "tDamPct",
|
||||
"% Earth Damage": "eDamPct",
|
||||
"% Fire Defense": "fDefPct",
|
||||
"% Water Defense": "wDefPct",
|
||||
"% Air Defense": "aDefPct",
|
||||
"% Thunder Defense": "tDefPct",
|
||||
"% Earth Defense": "eDefPct",
|
||||
"Fixed IDs": "fixID",
|
||||
"Custom Skin": "skin",
|
||||
//"Item Category": "category",
|
||||
|
||||
"1st Spell Cost %": "spPct1",
|
||||
"1st Spell Cost Raw": "spRaw1",
|
||||
"2nd Spell Cost %": "spPct2",
|
||||
"2nd Spell Cost Raw": "spRaw2",
|
||||
"3rd Spell Cost %": "spPct3",
|
||||
"3rd Spell Cost Raw": "spRaw3",
|
||||
"4th Spell Cost %": "spPct4",
|
||||
"4th Spell Cost Raw": "spRaw4",
|
||||
|
||||
"Rainbow Spell Damage": "rainbowRaw",
|
||||
"Sprint": "sprint",
|
||||
"Sprint Regen": "sprintReg",
|
||||
"Jump Height": "jh",
|
||||
"Loot Quality": "lq",
|
||||
|
||||
"Gather XP Bonus": "gXp",
|
||||
"Gather Speed Bonus": "gSpd",
|
||||
};
|
||||
|
||||
const special_mappings = {
|
||||
"Sum (skill points)": new SumQuery(["str", "dex", "int", "def", "agi"]),
|
||||
"Sum (Mana Sustain)": new SumQuery(["mr", "ms"]),
|
||||
"Sum (Life Sustain)": new SumQuery(["hpr", "ls"]),
|
||||
"Sum (Health + Health Bonus)": new SumQuery(["hp", "hpBonus"]),
|
||||
"No Strength Req": new NegateQuery("strReq"),
|
||||
"No Dexterity Req": new NegateQuery("dexReq"),
|
||||
"No Intelligence Req": new NegateQuery("intReq"),
|
||||
"No Agility Req": new NegateQuery("agiReq"),
|
||||
"No Defense Req": new NegateQuery("defReq"),
|
||||
};
|
||||
|
||||
let itemFilters = []
|
||||
for (let x in translate_mappings) {
|
||||
itemFilters.push(x);
|
||||
}
|
||||
for (let x in special_mappings) {
|
||||
itemFilters.push(x);
|
||||
}
|
||||
|
||||
let itemCategories = [ "armor", "accessory", "weapon" ];
|
||||
|
||||
function applyQuery(items, query) {
|
||||
return items.filter(query.filter, query).sort(query.compare);
|
||||
}
|
||||
|
||||
function displayItems(items_copy) {
|
||||
let items_parent = document.getElementById("search-results");
|
||||
for (let i in items_copy) {
|
||||
if (i > 200) {break;}
|
||||
let item = items_copy[i];
|
||||
let box = document.createElement("div");
|
||||
box.classList.add("col-auto", "dark-7", "dark-shadow");
|
||||
box.style.position = "absolute";
|
||||
box.id = "item"+i;
|
||||
box.addEventListener("dblclick", function() {set_item(item);});
|
||||
items_parent.appendChild(box);
|
||||
displaysq2ExpandedItem(item, box.id);
|
||||
}
|
||||
}
|
||||
|
||||
let items_expanded;
|
||||
|
||||
function doItemSearch() {
|
||||
// window.scrollTo(0, 0);
|
||||
let queries = [];
|
||||
queries.push(new NameQuery(document.getElementById("name-choice").value.trim()));
|
||||
|
||||
let categoryOrType = document.getElementById("category-choice").value;
|
||||
if (itemTypes.includes(categoryOrType)) {
|
||||
queries.push(new IdMatchQuery("type", categoryOrType));
|
||||
}
|
||||
else if (itemCategories.includes(categoryOrType)) {
|
||||
queries.push(new IdMatchQuery("category", categoryOrType));
|
||||
}
|
||||
|
||||
let rarity = document.getElementById("rarity-choice").value;
|
||||
if (rarity) {
|
||||
if (rarity === "ANY") {
|
||||
|
||||
}
|
||||
else {
|
||||
queries.push(new IdMatchQuery("tier", rarity));
|
||||
}
|
||||
}
|
||||
|
||||
let level_dat = document.getElementById("search-level-choice").value.split("-");
|
||||
queries.push(new LevelRangeQuery(parseInt(level_dat[0]), parseInt(level_dat[1])));
|
||||
|
||||
for (let i = 1; i <= 4; ++i) {
|
||||
let raw_dat = document.getElementById("filter"+i+"-choice").value;
|
||||
let filter_dat = translate_mappings[raw_dat];
|
||||
if (filter_dat !== undefined) {
|
||||
queries.push(new IdQuery(filter_dat));
|
||||
continue;
|
||||
}
|
||||
filter_dat = special_mappings[raw_dat];
|
||||
if (filter_dat !== undefined) {
|
||||
queries.push(filter_dat);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let items_copy = items_expanded.slice();
|
||||
document.getElementById("search-results").textContent = "";
|
||||
for (const query of queries) {
|
||||
console.log(items_copy.length);
|
||||
console.log(query);
|
||||
console.log(query.filter);
|
||||
items_copy = applyQuery(items_copy, query);
|
||||
console.log(items_copy.length);
|
||||
}
|
||||
// document.getElementById("summary").textContent = items_copy.length + " results."
|
||||
displayItems(items_copy);
|
||||
}
|
||||
|
||||
function init_items() {
|
||||
items_expanded = items.filter( (i) => !("remapID" in i) ).map( (i) => expandItem(i, []) );
|
||||
}
|
||||
|
||||
load_init(init_items);
|
Loading…
Add table
Reference in a new issue