├── .prettierignore
├── README.md
├── favicon.ico
├── media
├── images
│ ├── bg.png
│ ├── bow.png
│ ├── hb.png
│ ├── knx.png
│ ├── ktn.png
│ ├── md.png
│ ├── ohs.png
│ ├── stf.png
│ ├── ths.png
│ ├── potum200.webp
│ ├── menu.svg
│ ├── close.svg
│ ├── question-mark.svg
│ └── logo.svg
└── old-favicon.ico
├── fonts
├── noto-sans-v38-latin-500.woff2
├── noto-sans-v38-latin-700.woff2
└── noto-sans-v38-latin-regular.woff2
├── js
├── index.js
├── main.js
├── toramcafe.js
├── blacksmith.js
├── sp.js
├── corynclub.js
├── scroll.js
├── xp.js
└── statting.js
├── css
├── toramcafe.css
├── font.css
├── statting.css
├── sp.css
├── blacksmith.css
├── chrome.css
├── corynclub.css
├── index.css
├── xp.css
├── scroll.css
└── main.css
├── LICENSE
├── toramcafe.html
├── credits.html
├── corynclub.html
├── scroll.html
├── index.html
├── statting.html
├── xp.html
├── blacksmith.html
└── sp.html
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.html
2 | **/*.css
3 | **/*.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # toramtools.github.io
2 | Hosting toram tools
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/favicon.ico
--------------------------------------------------------------------------------
/media/images/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/bg.png
--------------------------------------------------------------------------------
/media/images/bow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/bow.png
--------------------------------------------------------------------------------
/media/images/hb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/hb.png
--------------------------------------------------------------------------------
/media/images/knx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/knx.png
--------------------------------------------------------------------------------
/media/images/ktn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/ktn.png
--------------------------------------------------------------------------------
/media/images/md.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/md.png
--------------------------------------------------------------------------------
/media/images/ohs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/ohs.png
--------------------------------------------------------------------------------
/media/images/stf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/stf.png
--------------------------------------------------------------------------------
/media/images/ths.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/ths.png
--------------------------------------------------------------------------------
/media/old-favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/old-favicon.ico
--------------------------------------------------------------------------------
/media/images/potum200.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/media/images/potum200.webp
--------------------------------------------------------------------------------
/fonts/noto-sans-v38-latin-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/fonts/noto-sans-v38-latin-500.woff2
--------------------------------------------------------------------------------
/fonts/noto-sans-v38-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/fonts/noto-sans-v38-latin-700.woff2
--------------------------------------------------------------------------------
/fonts/noto-sans-v38-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toramtools/toramtools.github.io/HEAD/fonts/noto-sans-v38-latin-regular.woff2
--------------------------------------------------------------------------------
/media/images/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/media/images/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/media/images/question-mark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/js/index.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | const showSection = function (itemId, sectionSelector, title) {
4 | $('#'+sectionSelector).show();
5 | $('#'+itemId).show();
6 | $(`${'#'+sectionSelector} .closeable-body div`).not(`#${itemId}`).hide();
7 | $('#description-title').text(title);
8 | }
9 |
10 | $('.question-mark').each(function () {
11 | let id = $(this).attr('id').split('-')[1];
12 | $(this).on("click", function () {
13 | console.log($(this).parent().find('a').text());
14 | showSection(id, "description-section", $(this).parent().find('a').text());
15 | });
16 | });
17 |
18 | $("#close-description").on("click", function () {
19 | $("#description-section").hide();
20 | });
21 |
22 | $(document).ready(function () {
23 | let img = new Image();
24 | img.src = "https://cdn.onlinewebfonts.com/svg/img_78622.png";
25 | });
--------------------------------------------------------------------------------
/css/toramcafe.css:
--------------------------------------------------------------------------------
1 | .search-container {
2 | display: flex;
3 | justify-content: center;
4 | padding: 10px 0;
5 | column-gap: 5px;
6 | row-gap: 10px;
7 | flex-wrap: wrap;
8 | }
9 |
10 | #results {
11 | display: flex;
12 | flex-direction: column;
13 | row-gap: 2px;
14 | align-items: center;
15 | }
16 |
17 | #results > a {
18 | width: max-content;
19 | display: block;
20 | }
21 |
22 | #error-msg {
23 | color: red;
24 | text-align: center;
25 | }
26 |
27 | .translator {
28 | display: flex;
29 | justify-content: center;
30 | }
31 |
32 | .category-container {
33 | flex: 1 0 100%;
34 | text-align: center;
35 | }
36 |
37 | #loading-container {
38 | width: 100%;
39 | overflow-y: hidden;
40 | text-align: center;
41 | }
42 |
43 | #loading-container > img {
44 | height: 50px;
45 | }
46 |
47 | #api-error {
48 | display: none;
49 | text-align: center;
50 | color: red;
51 | font-weight: bold;
52 | font-size: 1em;
53 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 toramtools
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/css/font.css:
--------------------------------------------------------------------------------
1 | /* noto-sans-regular - latin */
2 | @font-face {
3 | font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
4 | font-family: 'Noto Sans';
5 | font-style: normal;
6 | font-weight: 400;
7 | src: url('../fonts/noto-sans-v38-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
8 | }
9 | /* noto-sans-500 - latin */
10 | @font-face {
11 | font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
12 | font-family: 'Noto Sans';
13 | font-style: normal;
14 | font-weight: 500;
15 | src: url('../fonts/noto-sans-v38-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
16 | }
17 | /* noto-sans-700 - latin */
18 | @font-face {
19 | font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
20 | font-family: 'Noto Sans';
21 | font-style: normal;
22 | font-weight: 700;
23 | src: url('../fonts/noto-sans-v38-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
24 | }
--------------------------------------------------------------------------------
/css/statting.css:
--------------------------------------------------------------------------------
1 | body, html {
2 | overflow-x: hidden;
3 | }
4 |
5 | .ph-05 {
6 | padding: 0.5rem 0;
7 | }
8 |
9 | .mb-05:not(:last-child) {
10 | margin-bottom: 0.5rem;
11 | }
12 |
13 | .mb-05:last-child {
14 | margin-bottom: 0;
15 | }
16 |
17 | .pb-1:not(:last-child) {
18 | padding: 0;
19 | padding-bottom: 0.5rem;
20 | }
21 |
22 | .pb-1:last-child {
23 | padding: 0;
24 | }
25 |
26 | .mv-2vh {
27 | margin-top: 2vh;
28 | margin-bottom: 2vh;
29 | }
30 |
31 | .mh-1 {
32 | margin-left: 1rem;
33 | margin-right: 1rem;
34 | }
35 |
36 | @media (min-width: 100vh) {
37 | .r-grid {
38 | width: auto !important;
39 | display: grid;
40 | grid-template-columns: 1fr 1fr;
41 | grid-gap: 1rem;
42 | }
43 |
44 | .r-grid .stats {
45 | min-width: 360px;
46 | width: 100%;
47 | margin: 0 auto;
48 | grid-column: 2;
49 | grid-row: 1 / span 2;
50 | }
51 |
52 | .r-grid .configuration {
53 | min-width: 360px;
54 | grid-column: 1;
55 | grid-row: 1;
56 | }
57 |
58 | .r-grid .steps {
59 | min-width: 360px;
60 | grid-column: 1;
61 | grid-row: 2;
62 | }
63 |
64 | .r-grid .only-configuration {
65 | min-width: 360px;
66 | grid-column: 1 / span 2;
67 | margin: 0 auto;
68 | }
69 | }
70 |
71 | .button-group *:not(:last-child) {
72 | margin-right: 0.5em;
73 | }
--------------------------------------------------------------------------------
/css/sp.css:
--------------------------------------------------------------------------------
1 | .emblems-section > div {
2 | padding: 0;
3 | }
4 |
5 | .emblem-title {
6 | text-align: center;
7 | }
8 |
9 | #housing {
10 | text-align: center;
11 | grid-row-gap: 0.25rem;
12 | }
13 |
14 | #housing .col-1 {
15 | justify-content: center;
16 | }
17 |
18 | .housing-options {
19 | padding-top: 0;
20 | padding-bottom: 0;
21 | }
22 |
23 | /* Lixeiras edits starts from here */
24 | .footer{
25 | background-color: var(--primary-color);
26 | border: none;
27 | border-top: 1px solid var(--shadow-color);
28 | }
29 |
30 | .section {
31 | background-color: var(--primary-color);
32 | box-shadow: 0 0 4px 1px var(--shadow-color);
33 | border: none;
34 | }
35 |
36 | legend{
37 | background-color: var(--secondary-color);
38 | padding: 0.25rem 0.8rem;
39 | border-radius: 2rem;
40 | font-weight: 500;
41 | box-shadow: 0 0 4px 1px var(--shadow-color);
42 | }
43 |
44 | select, input, .small-input{
45 | background-color: var(--secondary-color);
46 | color: var(--text-color);
47 | padding: 0.2rem;
48 | border: 1px solid var(--shadow-color);
49 | border-radius: 0.5rem;
50 | }
51 |
52 | .small-input{
53 | border: 1px dashed var(--accent-color);
54 | }
55 |
56 | #stat-points, #skill-points{
57 | background-color: #6c7cb9;
58 | }
59 |
60 | input:focus, select:focus{
61 | outline: 1px solid rgb(128, 168, 255);
62 | box-shadow: 0px 1px 4px 2px var(--shadow-color);
63 | }
64 |
65 | select, input{
66 | text-align: center;
67 | }
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | const LV_CAP = 305;
4 |
5 | const HIGHEST_PROF = 280;
6 | const HIGHEST_ARM_POT = 54;
7 | const HIGHEST_WPN_POT = 55;
8 | const ARMOR_DIFFICULTY = 265;
9 | const WEAPON_DIFFICULTY = 300;
10 | const PRIMARY_STAT = 510;
11 | const SECONDARY_STAT = 277;
12 |
13 | const range = function (begin, end, step=1) {
14 | let list = [];
15 | for (var i = begin; i <= end; i=i+step) {
16 | list.push(i);
17 | }
18 | return list;
19 | }
20 |
21 | const fillOptions = function (values, keys=null, selected=false) {
22 | if (values.length == 0) {
23 | return;
24 | }
25 |
26 | let s = "";
27 | if (keys != null) {
28 | s += `\n`;
29 | for (var i = 1; i < values.length; i++) {
30 | s += `\n`;
31 | }
32 | }
33 | else {
34 | s += `\n`;
35 | for (var i = 1; i < values.length; i++) {
36 | s += `\n`;
37 | }
38 | }
39 | return s;
40 | }
41 |
42 | const parseInput = function (selector, std = 1) {
43 | let field = $(selector).val();
44 | return field != ""?parseInt(field):std;
45 | }
46 |
47 | const parseInputf = function (selector, std = 1) {
48 | let field = $(selector).val();
49 | return field != ""?parseFloat(field):std;
50 | }
51 |
52 | const max = Math.max;
53 | const min = Math.min;
54 | const floor = Math.floor;
55 | const ceil = Math.ceil;
56 | const abs = Math.abs;
57 | const sign = Math.sign;
58 | const trunc = Math.trunc;
--------------------------------------------------------------------------------
/css/blacksmith.css:
--------------------------------------------------------------------------------
1 | label {
2 | font-size: 0.85rem;
3 | }
4 |
5 | .crafting-type {
6 | text-align: center;
7 | }
8 |
9 | .crafting-type legend {
10 | text-align: left;
11 | }
12 |
13 | .crafting-type > select {
14 | margin: 0.5rem;
15 | padding-right: 0.5rem;
16 | }
17 |
18 | .skill-block {
19 | grid-row-gap: 0.25rem;
20 | }
21 |
22 | .skill-block label {
23 | text-align: center;
24 | }
25 |
26 | .skill-block > input {
27 | display: inline-block;
28 | margin: 0 auto;
29 | }
30 |
31 | #difficulty-divider {
32 | padding: 0 0.25rem;
33 | }
34 |
35 | #warning {
36 | grid-template-columns: none;
37 | font-weight: bold;
38 | font-size: 0.85rem;
39 | color: red;
40 | text-align: center;
41 | padding: 0.5rem 0;
42 | }
43 |
44 | #warning span {
45 | white-space: nowrap;
46 | }
47 |
48 | /* Lixeiras edits starts from here */
49 | .footer{
50 | background-color: var(--primary-color);
51 | border: none;
52 | border-top: 1px solid var(--shadow-color);
53 | }
54 |
55 | .section {
56 | background-color: var(--primary-color);
57 | box-shadow: 0px 1px 4px 1px var(--shadow-color);
58 | border: none;
59 | }
60 |
61 | legend{
62 | background-color: var(--secondary-color);
63 | padding: 0.25rem 0.8rem;
64 | border-radius: 2em;
65 | font-weight: 700;
66 | }
67 |
68 | select, input, .small-input{
69 | background-color: var(--secondary-color);
70 | color: var(--text-color);
71 | padding: 0.2em;
72 | border: 1px solid var(--shadow-color);
73 | border-radius: 0.6em;
74 | text-align: center;
75 | }
76 |
77 | input:focus, select:focus{
78 | outline: 1px solid rgb(128, 168, 255);
79 | box-shadow: 0px 1px 4px 2px var(--shadow-color);
80 | }
81 |
82 | select{
83 | padding-left: 1em;
84 | }
--------------------------------------------------------------------------------
/css/chrome.css:
--------------------------------------------------------------------------------
1 | input {
2 | vertical-align: middle;
3 | }
4 |
5 | .chrome-button {
6 | appearance: button;
7 | -webkit-writing-mode: horizontal-tb !important;
8 | writing-mode: horizontal-tb !important;
9 | text-rendering: auto;
10 | color: -internal-light-dark(black, white);
11 | letter-spacing: normal;
12 | word-spacing: normal;
13 | text-transform: none;
14 | text-indent: 0px;
15 | text-shadow: none;
16 | display: inline-block;
17 | text-align: center;
18 | align-items: flex-start;
19 | cursor: default;
20 | background-color: -internal-light-dark(rgb(239, 239, 239), rgb(59, 59, 59));
21 | box-sizing: border-box;
22 | margin: 0em;
23 | font: 400 13.3333px Arial;
24 | padding: 1px 6px;
25 | border-width: 2px;
26 | border-style: outset;
27 | border-color: -internal-light-dark(rgb(118, 118, 118), rgb(133, 133, 133));
28 | border-image: initial;
29 | }
30 |
31 | .chrome-select {
32 | -webkit-writing-mode: horizontal-tb !important;
33 | writing-mode: horizontal-tb !important;
34 | text-rendering: auto;
35 | color: -internal-light-dark(black, white);
36 | letter-spacing: normal;
37 | word-spacing: normal;
38 | text-transform: none;
39 | text-indent: 0px;
40 | text-shadow: none;
41 | display: inline-block;
42 | text-align: start;
43 | appearance: menulist;
44 | box-sizing: border-box;
45 | align-items: center;
46 | white-space: pre;
47 | -webkit-rtl-ordering: logical;
48 | background-color: -internal-light-dark(rgb(255, 255, 255), rgb(59, 59, 59));
49 | cursor: default;
50 | margin: 0em;
51 | font: 400 13.3333px Arial;
52 | border-radius: 0px;
53 | border-width: 1px;
54 | border-style: solid;
55 | border-color: -internal-light-dark(rgb(118, 118, 118), rgb(133, 133, 133));
56 | border-image: initial;
57 | }
58 |
59 | .chrome-select:disabled {
60 | color: -internal-light-dark(graytext, rgb(170, 170, 170));
61 | opacity: 0.7;
62 | border-color: rgba(118, 118, 118, 0.3);
63 | }
64 |
65 | .chrome-select:not(:-internal-list-box){
66 | overflow: visible !important;
67 | background-color: buttonface;
68 | }
--------------------------------------------------------------------------------
/css/corynclub.css:
--------------------------------------------------------------------------------
1 | .weapon-crysta {
2 | color: var(--weapon-crysta);
3 | }
4 |
5 | .normal-crysta {
6 | color: var(--normal-crysta);
7 | }
8 |
9 | .additional-crysta {
10 | color: var(--additional-crysta);
11 | }
12 |
13 | .special-crysta {
14 | color: var(--special-crysta);
15 | }
16 |
17 | .armor-crysta {
18 | color: var(--armor-crysta);
19 | }
20 |
21 | *[class*="enhancer-crysta-"] {
22 | color: var(--enhancer-crysta);
23 | }
24 |
25 | .enhancer-crysta-blue > span {
26 | text-shadow: 0 0 0.25em var(--normal-crysta);
27 | }
28 |
29 | .enhancer-crysta-green > span {
30 | text-shadow: 0 0 0.25em var(--armor-crysta);
31 | }
32 |
33 | .enhancer-crysta-red > span {
34 | text-shadow: 0 0 0.25em var(--weapon-crysta);
35 | }
36 |
37 | .enhancer-crysta-yellow > span {
38 | text-shadow: 0 0 0.25em var(--additional-crysta);
39 | }
40 |
41 | .enhancer-crysta-purple > span {
42 | text-shadow: 0 0 0.25em var(--special-crysta);
43 | }
44 |
45 | /* Lixeiras edits starts from here */
46 | .footer{
47 | background-color: var(--primary-color);
48 | border: none;
49 | border-top: 1px solid var(--shadow-color);
50 | }
51 |
52 | .main a{
53 | text-decoration: none;
54 | color: var(--text-color);
55 | }
56 |
57 | li::marker{
58 | list-style: none;
59 | }
60 |
61 | legend{
62 | background-color: var(--secondary-color);
63 | padding: 0.25rem 0.8rem;
64 | border-radius: 2em;
65 | font-weight: 500;
66 | }
67 | .section {
68 | background-color: var(--primary-color);
69 | box-shadow: 0px 1px 4px 1px var(--shadow-color);
70 | border: none;
71 | }
72 |
73 | select, input, .small-input, .chrome-select{
74 | background-color: var(--secondary-color);
75 | color: var(--text-color);
76 | padding: 0.2rem;
77 | border: 1px solid var(--shadow-color);
78 | border-radius: 0.5rem;
79 | }
80 |
81 | input:focus, select:focus{
82 | outline: 1px solid rgb(128, 168, 255);
83 | box-shadow: 0px 1px 4px 2px var(--shadow-color);
84 | }
85 |
86 | .chrome-button{
87 | padding: 0.6em 1em 0.6em 1em;
88 | border-radius: 2em;
89 | border: 0;
90 | border-style: solid;
91 | cursor: pointer;
92 | background-color: var(--accent-color);
93 |
94 | }
--------------------------------------------------------------------------------
/css/index.css:
--------------------------------------------------------------------------------
1 | .closeable-title {
2 | display: grid;
3 | grid-template-columns: auto auto;
4 | font-size: 0.75rem;
5 | margin: 0;
6 | }
7 |
8 | .closeable-title span {
9 | width: fit-content;
10 | width: -moz-fit-content;
11 | background: white;
12 | padding: 0 2px;
13 | white-space: pre;
14 | }
15 |
16 | .closeable-title span:first-child {
17 | margin-left: 1rem;
18 | text-align: left;
19 | }
20 |
21 | .closeable-title img:last-child {
22 | margin-right: 1rem;
23 | text-align: right;
24 | margin-left: auto;
25 | }
26 |
27 | .closeable-body {
28 | text-align: justify;
29 | position: relative;
30 | }
31 |
32 | .closeable-body > div {
33 | text-align: center;
34 | }
35 |
36 | .closeable-button {
37 | height: 1rem;
38 | padding: 2px;
39 | background: var(--accent-color);
40 | position: absolute;
41 | top: calc(2.5px - 1em);
42 | right: calc(0.35em + 4px);
43 | }
44 |
45 | .index-ul > li:not(:last-child) {
46 | margin-bottom: 0.5rem;
47 | }
48 |
49 | .index-ul {
50 | padding-inline-end: 40px;
51 | text-align: justify;
52 | }
53 |
54 | /*
55 | .index-ul > li > a, .index-ul > li > img {
56 | float: left;
57 | }
58 | */
59 |
60 | .index-ul .question-mark {
61 | margin-left: 5px;
62 | height: 1rem;
63 | }
64 |
65 | .index-ul > li > * {
66 | display: flex;
67 | align-items: center;
68 | }
69 |
70 | /* Lixeiras edits starts from here */
71 |
72 | .footer{
73 | background-color: var(--primary-color);
74 | border: none;
75 | border-top: 1px solid var(--shadow-color);
76 | }
77 |
78 | ul{
79 | list-style: none;
80 | display: flex;
81 | flex-direction: column;
82 | align-items: center;
83 | gap: 0.8rem;
84 | }
85 |
86 | li{
87 | font-size: 1.15rem;
88 | font-weight: 500;
89 | text-wrap: nowrap;
90 | padding: 0.5rem 1rem;
91 | min-width: 18.5rem;
92 | border-radius: 0.5rem;
93 | background-color: var(--primary-color);
94 | color: var(--text-color);
95 | box-shadow: 0 1px 2px 1px var(--shadow-color);
96 | align-content: center;
97 | text-align: center;
98 | transition: transform 0.3s ease;
99 | }
100 |
101 | li span{
102 | display: flex;
103 | justify-content: space-between;
104 | }
105 |
106 | li span a{
107 | cursor: pointer;
108 | box-sizing: border-box;
109 | }
110 |
111 | li:hover {
112 | transform: scale(1.1);
113 | box-shadow: 0 0 2px 2px var(--accent-color);
114 | }
115 |
116 | li a{
117 | color: var(--text-color);
118 | text-decoration: none;
119 | }
120 |
121 | legend{
122 | background-color: var(--primary-color);
123 | padding: 0.25rem 0.8rem;
124 | border-radius: 2em;
125 | font-weight: 500;
126 | box-shadow: 0 0 1px 1px var(--shadow-color);
127 | }
128 |
129 | .closeable-body{
130 | background-color: var(--secondary-color);
131 | color: var(--text-color);
132 | box-shadow: 0 0 1px 1px var(--shadow-color);
133 | border: none;
134 | }
--------------------------------------------------------------------------------
/js/toramcafe.js:
--------------------------------------------------------------------------------
1 | const api = "https://dot23-api.herokuapp.com/toramcafe"
2 | //const api = "http://localhost:5000/toramcafe"
3 |
4 | $("#search").on("click", async () => {
5 | const name = $("#item-name").val()
6 | const category = $("#item-category").val()
7 |
8 | if (name == "") {
9 | $("#error-msg").hide()
10 | $("#results-container").hide()
11 | $("#loading-container").hide()
12 | return;
13 | }
14 |
15 | $("#results-container").hide()
16 | $("#loading-container").show()
17 | await $.ajax({
18 | type: "GET",
19 | dataType: "json",
20 | url: api+"/"+category+"/"+name,
21 | success: function (result) {
22 | $("#error-msg").hide()
23 |
24 | const pattern = /([0-9A-Z\+]+|[\-\[\]★\(\)\&])[a-z\'\.♪\:]*/g
25 | const translator_affix = $("#translate-api").is(":checked")?"https://translate.google.com/translate?sl=ja&tl=en&u=":""
26 | let results_html = String()
27 | for (const link of result["data"]) {
28 | if (category == "boss") {
29 | const bossName = Object.keys(link)[0];
30 | const viewName = bossName.match(pattern).join(" ").replace("the ", " the ").replace("of ", " of ").replace(" -", " - ").replace("with ", " with ").replace("- lv", "- Lv")
31 | results_html += `${viewName}`
32 | }
33 | else{
34 | const viewName = link.substr(link.indexOf("#") + 1).replace("_Crysta", "").match(pattern).join(" ").replace("the ", " the ").replace("of ", " of ").replace(" - ", "-").replace("with ", " with ")
35 | results_html += `${viewName}`
36 | }
37 | }
38 |
39 | $("#results-container").show()
40 | $("#loading-container").hide()
41 |
42 | if (results_html == "") {
43 | results_html = "Seems we found nothing."
44 | }
45 |
46 | $("#results").html(results_html)
47 | },
48 | error: function (result) {
49 | $("#error-msg").show()
50 | $("#loading-container").hide()
51 | }
52 | })
53 | })
54 |
55 | $("#translate-api").on("change", function() {
56 | $("#search").click();
57 | })
58 |
59 | let wakeUpTries = 0;
60 |
61 | const wakeUpServer = async () => {
62 | await $.ajax({
63 | type: "GET",
64 | dataType: "html",
65 | url: "https://dot23-api.herokuapp.com/",
66 | success: function (result) {
67 | console.log("ready")
68 | $("#loading-container").hide()
69 | $("#tc-search").show()
70 | },
71 | error: function (result) {
72 | console.log("error:", result)
73 | wakeUpTries += 1
74 | if (wakeUpTries < 5)
75 | wakeUpServer()
76 | else {
77 | $("#loading-container").hide()
78 | $("#api-error").show()
79 | }
80 | },
81 | timeout: 3333
82 | })
83 | }
84 |
85 | $(document).ready(wakeUpServer)
--------------------------------------------------------------------------------
/css/xp.css:
--------------------------------------------------------------------------------
1 | #quest-name {
2 | padding-right: 0.5rem;
3 | }
4 |
5 | #quest-exp, #quest-times {
6 | width: 4rem;
7 | }
8 |
9 | .quest-info {
10 | text-align: center;
11 | margin: 0 auto;
12 | }
13 |
14 | .quest-info > p {
15 | margin: 0;
16 | margin-bottom: 0.25rem;
17 | }
18 |
19 | .quest-info > p:last-child {
20 | margin-bottom: 0;
21 | }
22 |
23 | .mq-block {
24 | padding: 0;
25 | }
26 |
27 | #mq-stopAt {
28 | color: green;
29 | }
30 |
31 | #mq-startFrom {
32 | color: red;
33 | }
34 |
35 | #skip-venena-label > span {
36 | font-weight: bold;
37 | font-size: 0.9em;
38 | }
39 |
40 | #skip-venena-label {
41 | display: flex;
42 | align-items: center;
43 | }
44 |
45 | #multiple-mq-label > span {
46 | font-weight: bold;
47 | font-size: 0.9em;
48 | }
49 |
50 | #multiple-mq-label {
51 | display: flex;
52 | align-items: center;
53 | }
54 |
55 | #mq-table-header {
56 | font-weight: bold;
57 | font-size: 0.8em;
58 | grid-template-columns: 10% 70% 20%;
59 | padding: 0;
60 | }
61 |
62 | #mq-table-row {
63 | font-size: 0.8em;
64 | grid-template-columns: 10% 70% 20%;
65 | padding: 0;
66 | }
67 |
68 | #mq-table-header > div, #mq-table-row > div {
69 | padding: 0.5em;
70 | display: flex;
71 | align-items: center;
72 | text-align: left;
73 | }
74 |
75 | #mq-table-header > div:not(:first-child), #mq-table-row > div:not(:first-child) {
76 | border-left: 1px solid black;
77 | }
78 |
79 | #mq-table-header:not(:last-child) > div, #mq-table-row:not(:last-child) > div {
80 | border-bottom: 1px solid black;
81 | }
82 |
83 | #mq-or {
84 | font-weight: bold;
85 | display: none;
86 | }
87 |
88 | /* Lixeiras edits starts from here */
89 | .footer{
90 | background-color: var(--primary-color);
91 | border: none;
92 | border-top: 1px solid var(--shadow-color);
93 | }
94 |
95 | #mq-group, .section {
96 | background-color: var(--primary-color);
97 | border: 1px solid var(--accent-color);
98 | }
99 |
100 | legend{
101 | background-color: var(--secondary-color);
102 | padding: 0.25rem 0.8rem;
103 | border: 1px solid var(--accent-color);
104 | border-radius: 2rem;
105 | font-weight: 500;
106 | }
107 |
108 | select, input, .grid-3 input{
109 | background-color: var(--secondary-color);
110 | color: var(--text-color);
111 | padding: 0.3rem 0;
112 | border: 1px solid hsl(0, 0%, 30%);
113 | border-radius: 0.6rem;
114 | }
115 |
116 | input:focus, select:focus, .grid-3 input:focus{
117 | outline: 1px solid rgb(128, 168, 255);
118 | }
119 |
120 | select{
121 | border-radius: 6px;
122 | text-align: center;
123 | max-width: 90dvw;
124 | }
125 |
126 | input{
127 | text-align: center;
128 | }
129 |
130 | .floating-img-container{
131 | position: absolute;
132 | bottom: 0;
133 | left: 0;
134 | z-index: -1;
135 | }
136 |
137 | .floating-img{
138 | height: 10rem;
139 | }
140 |
141 | #mq-startFrom{
142 | color: #ff4e4e;
143 | }
144 |
145 | #mq-stopAt{
146 | color: #5ecc5e;
147 | }
148 |
149 | @media (max-width:400px) {
150 | body{
151 | font-size: 14px;
152 | }
153 | .floating-img{
154 | display: none;
155 | }
156 | }
--------------------------------------------------------------------------------
/toramcafe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - ToramCafe's English Search (Descontinued)
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
59 |
60 |
61 |

62 |
63 |
64 |
65 |
External API unavailable. Try reloading page or try later.
66 |
67 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/credits.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Credits
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
55 |
56 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/css/scroll.css:
--------------------------------------------------------------------------------
1 | .scroll-container {
2 | display: grid;
3 | grid-template-columns: 1fr 1fr;
4 | width: fit-content;
5 | width: -moz-fit-content;
6 | margin: 0 auto;
7 | }
8 |
9 | .scroll-container > div {
10 | height: fit-content;
11 | height: -moz-fit-content;
12 | }
13 |
14 | @media (max-width: 480px) {
15 | .scroll-container {
16 | grid-template-columns: 1fr;
17 | grid-row-gap: 2vh;
18 | }
19 | }
20 |
21 | label > select, label > button {
22 | margin-left: 5px;
23 | }
24 |
25 | .scroll-section {
26 | display: flex;
27 | flex-direction: column;
28 | align-items: center;
29 | justify-content: center;
30 | }
31 |
32 | .scroll-section button {
33 | width: fit-content;
34 | width: -moz-fit-content;
35 | }
36 |
37 | .scroll-section > label:not(:last-child) {
38 | margin-bottom: 1em;
39 | }
40 |
41 | .scroll-section > label {
42 | font-weight: bold;
43 | text-align: center;
44 | }
45 |
46 | #scroll-craft-components {
47 | height: calc(100% - 0.75rem + 3px);
48 | box-sizing: border-box;
49 | padding: 0.5em 0;
50 | }
51 |
52 | #scroll-skills {
53 | padding: 0.5em 0;
54 | }
55 |
56 | .combination-box {
57 | display: grid;
58 | grid-template-columns: repeat(1, min-content);
59 | font-weight: bold;
60 | grid-gap: 0.5vh 0vw;
61 | justify-content: center;
62 | cursor: pointer;
63 | }
64 |
65 | .combination-box div:first-child {
66 | display: flex;
67 | justify-content: center;
68 | }
69 |
70 | .combination-box span {
71 | display: inline-block;
72 | height: min-content;
73 | margin: auto 0;
74 | white-space: nowrap;
75 | text-align: center;
76 | }
77 |
78 | .combination-box img {
79 | width: 30px;
80 | border-radius: 15px;
81 | margin: 0 0.25em;
82 | }
83 |
84 | #results {
85 | display: grid;
86 | justify-content: center;
87 | grid-column-gap: 1em;
88 | margin: 2vh 1em;
89 | grid-gap: 3vh 2em;
90 | grid-template-columns: repeat(auto-fill, 175px);
91 | }
92 |
93 | #results-warning {
94 | margin: 1vh;
95 | text-align: justify;
96 | }
97 |
98 | #craft-results {
99 | text-align: center;
100 | margin-top: 1em;
101 | padding-top: 1em;
102 | border-top: 1px solid black;
103 | }
104 |
105 | #craft-results > span:first-child, #craft-results > span:nth-child(3) {
106 | font-weight: bold;
107 | display: block;
108 | }
109 |
110 | #craft-results > span:nth-child(3) {
111 | margin-top: 1vh;
112 | }
113 |
114 | .scroll-type {
115 | display: inline;
116 | white-space: nowrap;
117 | width: 100%;
118 | text-align: center;
119 | }
120 |
121 | .scroll-type > span > span {
122 | font-weight: normal;
123 | }
124 |
125 | .scroll-type span:not(:last-child):not(:nth-last-child(2))::after {
126 | content: ", ";
127 | }
128 |
129 | .scroll-type span:last-child:not(:first-child)::before {
130 | content: " or ";
131 | }
132 |
133 | #scroll-skills-container {
134 | display: flex;
135 | align-items: center;
136 | justify-content: center;
137 | }
138 |
139 | .results-parent {
140 | display: none;
141 | max-width: 90%;
142 | margin: 0 auto;
143 | min-width: 74px;
144 | margin-top: 2vh;
145 | }
146 |
147 | /* Lixeiras edits starts from here */
148 | .footer{
149 | background-color: var(--primary-color);
150 | border: none;
151 | border-top: 1px solid var(--shadow-color);
152 | }
153 |
154 | .section {
155 | background-color: var(--primary-color);
156 | box-shadow: 0px 1px 4px 1px var(--shadow-color);
157 | border: none;
158 | }
159 |
160 | legend{
161 | background-color: var(--secondary-color);
162 | padding: 0.25rem 0.8rem;
163 | border-radius: 2em;
164 | font-weight: 500;
165 | }
166 |
167 | select{
168 | background-color: var(--secondary-color);
169 | color: var(--text-color);
170 | padding: 0.3em;
171 | border: 1px solid var(--shadow-color);
172 | border-radius: 0.6em;
173 | }
174 |
175 | button{
176 | padding: 0.6em 1em 0.6em 1em;
177 | border-radius: 2em;
178 | border: 0;
179 | cursor: pointer;
180 | background: var(--accent-color);
181 | }
--------------------------------------------------------------------------------
/js/blacksmith.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | $("#crafting-popup").on("click", function() {
4 | alert("Type equipment difficulty, not yours.");
5 | });
6 |
7 | const difficultyHandler = function () {
8 | let TEC = parseInput("#TEC");
9 | let DEX = floor(parseInput("#DEX")*(100+parseInput("#eDEXp"))/100+parseInput("#eDEX"));
10 | let STR = floor(parseInput("#STR")*(100+parseInput("#eSTRp"))/100+parseInput("#eSTR"));
11 | let proeficiency = parseInput("#proeficiency", 0);
12 | let createEquipment = parseInput("#create-equipment", 0);
13 | let difficulty = proeficiency+floor(TEC/2)+floor(DEX/6);
14 | let itemDifficulty = parseInput("#equipment-difficulty", 0);
15 | $("#your-difficulty").val(difficulty);
16 | $("#success-rate").val(min(100, max(0, floor((50+5*createEquipment)/100*(10+difficulty-itemDifficulty+floor(STR/10))))));
17 |
18 | if (difficulty < itemDifficulty) {
19 | $("#warning").show();
20 | }
21 | else {
22 | $("#warning").hide();
23 | }
24 | }
25 |
26 | const potentialHandler = function () {
27 | let potential = parseInput("#base-potential", 0);
28 | potential = floor(potential*(1+parseInput("#careful-creation", 0)*0.01+parseInput("#expert-creation", 0)*0.02));
29 | let craft = $("#craft-type").val();
30 | if (craft == "Armor") {
31 | potential += floor(parseInput("#VIT")/10);
32 | }
33 | else if (craft == "1H Sword") {
34 | potential += floor((parseInput("#DEX")+parseInput("#STR"))/20);
35 | }
36 | else if (craft == "2H Sword") {
37 | potential += floor(parseInput("#STR")/10);
38 | }
39 | else if (craft == "Bow") {
40 | potential += floor((parseInput("#DEX")+parseInput("#STR"))/20);
41 | }
42 | else if (craft == "Bowgun") {
43 | potential += floor(parseInput("#DEX")/10);
44 | }
45 | else if (craft == "Staff") {
46 | potential += floor(parseInput("#INT")/10);
47 | }
48 | else if (craft == "Magic Device") {
49 | potential += floor((parseInput("#INT")+parseInput("#AGI"))/20);
50 | }
51 | else if (craft == "Knuckle") {
52 | potential += floor(parseInput("#AGI")/10);
53 | }
54 | else if (craft == "Halberd") {
55 | potential += floor((parseInput("#STR")+parseInput("#AGI"))/20);
56 | }
57 | else if (craft == "Katana") {
58 | potential += floor((parseInput("#DEX")+parseInput("#AGI"))/20);
59 | }
60 | $("#total-potential").val(potential);
61 | }
62 |
63 | const setDefaultStats = function (primary, secondary, difficulty = WEAPON_DIFFICULTY) {
64 | $("#STR").val('');
65 | $("#DEX").val('');
66 | $("#INT").val('');
67 | $("#VIT").val('');
68 | $("#AGI").val('');
69 | $("#TEC").val('');
70 |
71 | $("#"+primary).val(PRIMARY_STAT);
72 | $("#"+secondary).val(SECONDARY_STAT);
73 |
74 | $("#equipment-difficulty").val(difficulty);
75 |
76 | if (difficulty == WEAPON_DIFFICULTY) {
77 | $("#base-potential").val(HIGHEST_WPN_POT);
78 | }
79 | else {
80 | $("#base-potential").val(HIGHEST_ARM_POT);
81 | }
82 | }
83 |
84 | const craftHandler = function () {
85 | let craft = $("#craft-type").val();
86 | if (craft == "Armor") {
87 | setDefaultStats("VIT", "TEC", ARMOR_DIFFICULTY);
88 | }
89 | else if (craft == "1H Sword") {
90 | setDefaultStats("DEX", "STR");
91 | }
92 | else if (craft == "2H Sword") {
93 | setDefaultStats("STR", "DEX");
94 | }
95 | else if (craft == "Bow") {
96 | setDefaultStats("DEX", "STR");
97 | }
98 | else if (craft == "Bowgun") {
99 | setDefaultStats("DEX", "STR");
100 | }
101 | else if (craft == "Staff") {
102 | setDefaultStats("INT", "TEC");
103 | }
104 | else if (craft == "Magic Device") {
105 | setDefaultStats("INT", "AGI")
106 | }
107 | else if (craft == "Knuckle") {
108 | setDefaultStats("AGI", "DEX");
109 | }
110 | else if (craft == "Halberd") {
111 | setDefaultStats("STR", "AGI");
112 | }
113 | else if (craft == "Katana") {
114 | setDefaultStats("DEX", "AGI");
115 | }
116 | }
117 |
118 | const bothHandler = function () {
119 | difficultyHandler();
120 | potentialHandler();
121 | }
122 |
123 |
124 | $(document).ready(function () {
125 | $("#proeficiency").val(HIGHEST_PROF);
126 | $("body form").on("input", bothHandler);
127 | $("body form").trigger("input");
128 | $("#craft-type").on("input", craftHandler);
129 | $("#craft-type").trigger("input");
130 | });
--------------------------------------------------------------------------------
/corynclub.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Simplified Advanced Search
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
65 |
66 |
67 |
68 |
93 |
94 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/scroll.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Ninja Scroll Database
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
51 |
105 |
106 |
107 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools
16 |
17 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
52 |
53 |
54 |
97 |
98 |
99 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/js/sp.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // const statPoints = (level) => 2*level+5*(floor((level-level%10)/10)+floor((level%10)/5));
4 | const statPoints = (level) => level*2;
5 | const maxLvPoints = (level) => level>=5?5*(floor((level-5)/10)+1):0;
6 | const skillPoints = (level) => level+floor(level/5);
7 |
8 | const rankStatPoints = function () {
9 | let total = 0;
10 | total += ($("#attacker-rank").val() > 1)*5;
11 | total += ($("#defender-rank").val() > 1)*5;
12 | total += ($("#supporter-rank").val() > 1)*5;
13 | total += ($("#breaker-rank").val() > 1)*5;
14 | return total;
15 | }
16 |
17 | const binSearch = function (value, evalFunction) {
18 | let begin = 0;
19 | let end = parseInt($("#lvcap").val());
20 | while (begin+1 < end) {
21 | let mid = floor((begin+end)/2);
22 | let midValue = evalFunction(mid);
23 | if (midValue > value) {
24 | end = mid;
25 | }
26 | else if (midValue < value) {
27 | begin = mid;
28 | }
29 | else {
30 | $("#level").val(mid);
31 | return;
32 | }
33 | }
34 | $("#level").val(end);
35 | }
36 |
37 | const clearHighlights = function () {
38 | $("#level").removeClass("highlight");
39 | $("#stat-points").removeClass("highlight");
40 | $("#skill-points").removeClass("highlight");
41 | }
42 |
43 | var lastState = 'none';
44 | const levelChange = function () {
45 | if (this.value != "") {
46 | let level = parseInt(this.value);
47 | let highestLv = max(level, parseInput('#highest-level'));
48 | let statp = statPoints(level)+maxLvPoints(highestLv)+rankStatPoints();
49 | $("#stat-points").val(statp);
50 | $("#skill-points").val(skillPoints(level)+extraSkillPoints());
51 |
52 | $("#level").removeClass("highlight");
53 | $("#stat-points").addClass("highlight");
54 | $("#skill-points").addClass("highlight");
55 | lastState = 'level';
56 | }
57 | else {
58 | $("#stat-points").val("");
59 | $("#skill-points").val("");
60 | clearHighlights();
61 | lastState = 'none';
62 | }
63 | }
64 |
65 | const statChange = function () {
66 | let statValue = $("#stat-points").val();
67 | if (statValue != "") {
68 | let highestSP = maxLvPoints(parseInput("#highest-level"));
69 | binSearch(parseInt(this.value), (level) => statPoints(level)+max(highestSP, maxLvPoints(level))+rankStatPoints());
70 | $("#stat-points").removeClass("highlight");
71 | $("#level").addClass("highlight");
72 | $("#skill-points").addClass("highlight");
73 | $("#skill-points").val(skillPoints(parseInt($("#level").val())));
74 | lastState = 'stat';
75 | }
76 | else {
77 | $("#level").val("");
78 | $("#skill-points").val("");
79 | clearHighlights();
80 | lastState = 'none';
81 | }
82 | }
83 |
84 | const skillChange = function () {
85 | let skillValue = $("#skill-points").val();
86 | if (skillValue != "") {
87 | binSearch(parseInt(this.value), (level) => skillPoints(level)+extraSkillPoints());
88 | $("#skill-points").removeClass("highlight");
89 | $("#level").addClass("highlight");
90 | $("#stat-points").addClass("highlight");
91 | $("#stat-points").val(statPoints(parseInt($("#level").val())));
92 | lastState = 'skill';
93 | }
94 | else {
95 | $("#level").val("");
96 | $("#stat-points").val("");
97 | clearHighlights();
98 | lastState = 'none';
99 | }
100 | }
101 |
102 | const extraSkillPoints = function () {
103 | let totalPoints = 0;
104 | totalPoints += parseInt($("#attacker-rank").val());
105 | totalPoints += parseInt($("#defender-rank").val());
106 | totalPoints += parseInt($("#supporter-rank").val());
107 | totalPoints += parseInt($("#breaker-rank").val());
108 | totalPoints += parseInt($("#max-chapter").val());
109 | totalPoints += parseInt($("#first-aid").val());
110 | totalPoints += parseInt($("#KO").val());
111 | totalPoints += $("#minigame-bk").prop("checked");
112 | totalPoints += $("#minigame-cg").prop("checked");
113 | totalPoints += parseInt($("#mastered-skills").val());
114 | totalPoints += parseInt($("#mastered-trees").val());
115 | totalPoints += parseInt($("#consecutive-time").val());
116 | return totalPoints;
117 | }
118 |
119 | const extraStatPoints = function () {
120 | let totalPoints = 0;
121 | let highestSP = maxLvPoints(parseInput("#highest-level"));
122 | let levelSP = maxLvPoints(parseInput("#level"));
123 | totalPoints += max(highestSP, levelSP);
124 | totalPoints += rankStatPoints();
125 | return totalPoints;
126 | }
127 |
128 | $(document).ready(() => {
129 | $("#lvcap").val(LV_CAP);
130 | $("#level").val(LV_CAP).trigger("input");
131 | $("#attacker-rank").html(fillOptions([0, 1, 1.5, 2, 3, 4], [0, 10, 100, 1000, 10000, 100000]));
132 | $("#defender-rank").html(fillOptions([0, 1, 1.5, 2, 3, 4], [0, 10, 100, 1000, 10000, 100000]));
133 | $("#supporter-rank").html(fillOptions([0, 1, 1.5, 2, 3, 4], [0, 10, 100, 1000, 10000, 100000]));
134 | $("#breaker-rank").html(fillOptions([0, 1, 1.5, 2, 3, 4], [0, 10, 100, 1000, 10000, 100000]));
135 | $("#mastered-skills").html(fillOptions(range(0, 10), range(0, 10)));
136 | $("#mastered-trees").html(fillOptions(range(0, 3), range(0, 3)));
137 | $("#first-aid").html(fillOptions(range(0, 4), [0, 100, 400, 700, 1000]));
138 | $("#KO").html(fillOptions(range(0, 4), [0, 100, 400, 700, 1000]));
139 | $("#consecutive-time").html(fillOptions(range(0, 8), ['0min', '15min', '30min', '1h', '2h', '3h', '4h', '5h', '6h']));
140 |
141 | $("#emblem-popup").on("click", function () {
142 | alert('Subsections indicate which tabs you may find mentioned emblems.\n\nHighest Lv = Highest "Player Level" emblem you got.');
143 | });
144 |
145 | $("#lvcap").on("input", function () {
146 | $("#level").attr("max", $("#lvcap").val());
147 | });
148 | $("#lvcap, #level").on("change", () => $("#extra-sp").trigger("input"));
149 | $("#level").on("input", levelChange);
150 | $("#stat-points").on("input", statChange);
151 | $("#skill-points").on("input", skillChange);
152 |
153 | $("#extra-sp").on("input", function () {
154 | $("#extra-skill-points").val(extraSkillPoints());
155 | $("#extra-stat-points").val(extraStatPoints());
156 | if (lastState == 'level') {
157 | $("#level").trigger("input");
158 | }
159 | else if (lastState == 'stat') {
160 | $("#stat-points").trigger("input");
161 | }
162 | else if (lastState == 'skill') {
163 | $("#skill-points").trigger("input");
164 | }
165 | });
166 |
167 | let e = new Event("input");
168 | document.querySelector("#level").dispatchEvent(e);
169 | document.querySelector("#extra-sp").dispatchEvent(e);
170 | });
--------------------------------------------------------------------------------
/statting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Statting Simulator (Descontinued)
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/css/main.css:
--------------------------------------------------------------------------------
1 | /* Main end: 412x692 viewport */
2 |
3 | @import url(font.css);
4 |
5 | :root {
6 | --bg-color : #212831;
7 | --primary-color: #151b23;
8 | --secondary-color: #262c36;
9 | --text-color: #dbdbdb;
10 | --accent-color: #6c7cb9;
11 | --shadow-color: rgba(0, 0, 0, 0.15);
12 |
13 | --highlight-color: #5ecc5e;
14 | --error-color: #ff4e4e;
15 | --weapon-crysta: red;
16 | --normal-crysta: blue;
17 | --special-crysta: #7A0B83;
18 | --additional-crysta: #9C9801;
19 | --armor-crysta: #058142;
20 | --enhancer-crysta: #444444;
21 | }
22 |
23 | *{
24 | font-family: inherit;
25 | }
26 |
27 | html {
28 | font-size: 16px;
29 | width: 100%;
30 | height: 100%;
31 | }
32 |
33 | body {
34 | font-family: Noto Sans;
35 | background-color: var(--bg-color);
36 | color: var(--text-color);
37 | min-height: 100%;
38 | display: flex;
39 | flex-direction: column;
40 | align-items: stretch;
41 | height: 100%;
42 | width: 100%;
43 | margin: 0;
44 | padding: 0;
45 | }
46 |
47 | nav {
48 | height: 54px;
49 | margin-bottom: 2rem;
50 | padding-left: 8px;
51 | background-color: var(--primary-color);
52 | border-bottom: 1px solid var(--shadow-color);
53 | display: flex;
54 | justify-content: flex-end;
55 | align-items: center;
56 | }
57 |
58 | .links-container {
59 | height: 100%;
60 | width: 100%;
61 | display: flex;
62 | flex-direction: row;
63 | align-items: center;
64 | }
65 |
66 | nav a {
67 | height: 100%;
68 | padding: 0 10px;
69 | display: flex;
70 | align-items: center;
71 | text-decoration: none;
72 | color: var(--text-color);
73 | }
74 |
75 | .links-container a:hover {
76 | background-color: var(--accent-color);
77 | }
78 |
79 | .spacer{
80 | padding: 0;
81 | }
82 |
83 | nav .spacer {
84 | margin-right: auto;
85 | }
86 |
87 | nav svg {
88 | fill: var(--text-color);
89 | }
90 |
91 | .toramtools-logo{
92 | height: 1.5rem;
93 | }
94 |
95 | #sidebar-active {
96 | display: none;
97 | }
98 |
99 | .open-sidebar-button,
100 | .close-sidebar-button {
101 | display: none;
102 | }
103 |
104 | @media(max-width: 720px) {
105 | .links-container {
106 | display: none;
107 | flex-direction: column;
108 | align-items: flex-start;
109 |
110 | position: fixed;
111 | top: 0;
112 | right: 0;
113 | z-index: 10;
114 | width: 300px;
115 |
116 | background-color: var(--primary-color);
117 | box-shadow: -5px 0 5px var(--shadow-color);
118 | }
119 |
120 | nav a {
121 | box-sizing: border-box;
122 | height: auto;
123 | width: 100%;
124 | padding: 20px 30px;
125 | justify-content: flex-start;
126 | }
127 |
128 | .open-sidebar-button,
129 | .close-sidebar-button {
130 | display: block;
131 | padding: 20px;
132 | }
133 |
134 | #sidebar-active:checked~.links-container {
135 | display: flex;
136 | }
137 |
138 | #sidebar-active:checked~#overlay {
139 | height: 100%;
140 | width: 100%;
141 | position: fixed;
142 | top: 0;
143 | left: 0;
144 | z-index: 9;
145 | }
146 | }
147 |
148 | select {
149 | padding-right: 0.5rem;
150 | }
151 |
152 | /* a:-webkit-any-link {
153 | color: blue;
154 | } */
155 |
156 | .header-title {
157 | font-size: 1rem;
158 | font-weight: bold;
159 | padding: 0.25rem 0;
160 | }
161 |
162 | .header {
163 | border: 1px solid #333333;
164 | box-sizing: border-box;
165 | text-align: center;
166 | background-color: #333333;
167 | color: white;
168 | margin-bottom: 0.5rem;
169 | }
170 |
171 | .main {
172 | flex-grow: 1;
173 | box-sizing: border-box;
174 | }
175 |
176 | .main > *:not(:last-child) {
177 | margin-bottom: 2vh;
178 | }
179 |
180 | .footer {
181 | border: 1px solid #333333;
182 | box-sizing: border-box;
183 | text-align: center;
184 | font-size: 1rem;
185 | background-color: #333333;
186 | color: white;
187 | font-style: italic;
188 | margin-top: 5px;
189 | padding: 0.25rem 0;
190 | font-weight: bold;
191 | }
192 |
193 | .header, .main, .footer {
194 | flex-shrink: 0;
195 | }
196 |
197 | .header a {
198 | text-decoration: none;
199 | color: white;
200 | }
201 |
202 | .section > legend {
203 | font-size: 0.75rem;
204 | font-weight: bold;
205 | }
206 |
207 | .section {
208 | margin-left: 0.25rem;
209 | margin-right: 0.25rem;
210 | border: solid 1px;
211 | border-radius: 10px;
212 | padding-bottom: 0.5em;
213 | box-sizing: border-box;
214 | }
215 |
216 | .small-input {
217 | font-size: 1rem;
218 | height: 1rem;
219 | width: 3rem;
220 | border: 1px solid;
221 | }
222 |
223 | .medium-input {
224 | width: 4rem;
225 | }
226 |
227 | .grid {
228 | display: grid;
229 | grid-template-columns: 1fr auto 1fr;
230 | text-align: right;
231 | grid-gap: 2vh 0.5rem;
232 | padding: 0.5rem 0;
233 | }
234 |
235 | .grid-2 {
236 | grid-template-columns: 1fr repeat(2, auto) 1fr;
237 | }
238 |
239 | .grid-3 {
240 | grid-template-columns: 1fr repeat(3, auto) 1fr;
241 | }
242 |
243 | .grid-4 {
244 | grid-template-columns: 1fr repeat(4, auto) 1fr;
245 | }
246 |
247 | .grid-5 {
248 | grid-template-columns: 1fr repeat(5, auto) 1fr;
249 | }
250 |
251 | .grid-6 {
252 | grid-template-columns: 1fr repeat(6, auto) 1fr;
253 | }
254 |
255 | .col-1 {
256 | grid-column: 2;
257 | }
258 |
259 | .col-2 {
260 | grid-column: 3;
261 | }
262 |
263 | .col-3 {
264 | grid-column: 4;
265 | }
266 |
267 | .col-4 {
268 | grid-column: 5;
269 | }
270 |
271 | .col-5 {
272 | grid-column: 6;
273 | }
274 |
275 | .grid.grid-2:not(.ignore) .col-1:not(.ignore), .grid.grid-2:not(.ignore) .col-2:not(.ignore) {
276 | display: flex;
277 | justify-content: flex-end;
278 | align-items: center;
279 | }
280 |
281 | .grid.grid-2:not(.ignore) .col-1:not(.ignore) label, .grid.grid-2:not(.ignore) .col-2:not(.ignore) label {
282 | margin-right: 5px;
283 | }
284 |
285 | .nogap {
286 | grid-gap: 0;
287 | }
288 |
289 | .smaller-font {
290 | font-size: 0.75rem;
291 | }
292 |
293 | .highlight {
294 | background-color: #38ff81;
295 | }
296 |
297 | .error {
298 | background-color: #ff4141;
299 | }
300 |
301 | /* Chrome, Safari, Edge, Opera */
302 | input::-webkit-outer-spin-button,
303 | input::-webkit-inner-spin-button {
304 | -webkit-appearance: none;
305 | margin: 0;
306 | }
307 |
308 | /* Firefox */
309 | input[type=number] {
310 | -moz-appearance: textfield;
311 | }
312 |
313 | input[type=checkbox] {
314 | vertical-align: text-top;
315 | }
316 |
317 | .label-checkbox {
318 | font-size: calc(1rem + 1px);
319 | }
320 |
321 | .v-align > div {
322 | display: flex;
323 | align-items: center;
324 | align-content: center;
325 | height: 100%;
326 | }
327 |
328 | .v-align input[type="number"], .v-align select {
329 | margin-left: 0.5rem;
330 | }
331 |
332 | .subsection-title {
333 | font-size: 0.75rem;
334 | margin: 0;
335 | text-align: center;
336 | }
337 |
338 | .section > legend > div {
339 | display: flex;
340 | align-items: center;
341 | }
342 |
343 | .section > legend > div > img, .question-mark {
344 | cursor: pointer;
345 | width: 1.1em;
346 | margin-left: 3px;
347 | fill: var(--text-color);
348 | content: url(../media/images/question-mark.svg);
349 | /* content: url(https://cdn1.iconfinder.com/data/icons/material-set-6/48/543-512.png); */
350 | }
351 |
352 | .text-center {
353 | text-align: center;
354 | }
355 |
356 | .hidden {
357 | display: none;
358 | }
359 |
360 | @media (min-width: 500px) {
361 | .container {
362 | width: 480px;
363 | margin: 0 auto;
364 | }
365 | }
366 |
367 | @media (min-width: 768px) {
368 | .multiple-1 {
369 | height: calc(1rem + 2px);
370 | }
371 |
372 | .multiple-5 {
373 | height: calc(5rem + 2px);
374 | }
375 | }
376 |
377 | .radio-group {
378 | display: flex;
379 | justify-content: center;
380 | align-items: flex-start;
381 | align-content: center;
382 | }
383 |
384 | .radio-group > label:not(last-child) {
385 | margin-right: 1rem;
386 | }
387 |
388 | .h-align-center {
389 | text-align: center;
390 | }
--------------------------------------------------------------------------------
/media/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/xp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Experience Calculator
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
174 |
175 |
176 |

177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/blacksmith.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Blacksmith Crafting Calculator
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/sp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Toram Tools - Stat & Skill Points Calculator
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
51 |
52 |
76 |
77 |
182 |
183 |
184 |
185 |
188 |
189 |
190 |
191 |
192 |
193 |
--------------------------------------------------------------------------------
/js/corynclub.js:
--------------------------------------------------------------------------------
1 | const EFF_NAME = {
2 | 'Base DEF': '1',
3 | 'Base ATK': '2',
4 | 'STR': '3',
5 | 'STR %': '4',
6 | 'INT': '5',
7 | 'INT %': '6',
8 | 'VIT': '7',
9 | 'VIT %': '8',
10 | 'AGI': '9',
11 | 'AGI %': '10',
12 | 'DEX': '11',
13 | 'DEX %': '12',
14 | 'Natural HP Regen': '13',
15 | 'Natural HP Regen %': '14',
16 | 'Natural MP Regen': '15',
17 | 'Natural MP Regen %': '16',
18 | 'MaxHP': '17',
19 | 'MaxHP %': '18',
20 | 'MaxMP': '19',
21 | 'ATK': '20',
22 | 'ATK %': '21',
23 | 'MATK': '22',
24 | 'MATK %': '23',
25 | 'Stability %': '24',
26 | 'Physical Pierce %': '25',
27 | 'Magic Pierce %': '26',
28 | 'DEF': '27',
29 | 'DEF %': '28',
30 | 'MDEF': '29',
31 | 'MDEF %': '30',
32 | 'Physical Resistance %': '31',
33 | 'Magical Resistance %': '32',
34 | 'Accuracy': '33',
35 | 'Accuracy %': '34',
36 | 'Dodge': '35',
37 | 'Dodge %': '36',
38 | 'ASPD': '37',
39 | 'ASPD %': '38',
40 | 'CSPD': '39',
41 | 'CSPD %': '40',
42 | 'Critical Rate': '41',
43 | 'Critical Rate %': '42',
44 | 'Critical Damage': '43',
45 | 'Critical Damage %': '44',
46 | '% stronger against Fire': '45',
47 | '% stronger against Water': '46',
48 | '% stronger against Wind': '47',
49 | '% stronger against Earth': '48',
50 | '% stronger against Light': '49',
51 | '% stronger against Dark': '50',
52 | 'Fire resistance %': '51',
53 | 'Water resistance %': '52',
54 | 'Wind resistance %': '53',
55 | 'Earth resistance %': '54',
56 | 'Light resistance %': '55',
57 | 'Dark resistance %': '56',
58 | 'Ailment Resistance %': '57',
59 | 'Guard Power %': '58',
60 | 'Guard Recharge %': '59',
61 | 'Evasion Recharge %': '60',
62 | 'Aggro %': '61',
63 | 'Fire Element': '62',
64 | 'Water Element': '63',
65 | 'Wind Element': '64',
66 | 'Earth Element': '65',
67 | 'Light Element': '66',
68 | 'Dark Element': '67',
69 | 'Attack MP Recovery': '68',
70 | 'Short Range Damage %': '69',
71 | 'Long Range Damage %': '70',
72 | 'Motion Speed %': '71',
73 | 'Weapon ATK': '73',
74 | 'Weapon ATK %': '74',
75 | 'Neutral Resistance %': '75',
76 | 'HP': '79',
77 | 'MP': '80',
78 | 'Teleport to Rugio Ruins': '81',
79 | 'Teleport to Sofya City': '82',
80 | 'Teleport to the last town you visited': '83',
81 | 'HP %': '84',
82 | 'MP %': '85',
83 | "Teleport to Ancient Empress' Tomb": '86',
84 | 'Can form a guild once': '87',
85 | 'EXP Gain %': '95',
86 | 'Drop Rate %': '96',
87 | 'MaxMP %': '101',
88 | 'Revive Time %': '104',
89 | 'Base Drop Rate %': '105',
90 | 'Damage from Boss %': '107',
91 | 'Damage to Boss %': '108',
92 | '% stronger against Neutral': '110',
93 | 'Base Stability %': '111',
94 | 'Potential': '113',
95 | 'Teleport to Ethos Fortress': '115',
96 | 'Unsheathe Attack': '116',
97 | 'Unsheathe Attack %': '117',
98 | 'Teleport to El Scaro': '119',
99 | 'Flinch Unavailable': '122',
100 | 'ATK DOWN (VIT)': '123',
101 | 'Physical Barrier': '124',
102 | 'Tumble Unavailable': '125',
103 | 'Reflect %': '126',
104 | 'Fractional Barrier %': '127',
105 | 'Magic Barrier': '128',
106 | 'Additional Melee %': '129',
107 | 'Additional Magic %': '130',
108 | 'ATK UP (INT)': '131',
109 | 'ATK DOWN (STR)': '132',
110 | 'ATK DOWN (DEX)': '133',
111 | 'ATK DOWN (AGI)': '134',
112 | 'Teleport to the Garden of Beginning': '136',
113 | 'Anticipate %': '139',
114 | 'Guard Break %': '140',
115 | 'Barrier Cooldown %': '141',
116 | 'Teleport to the Dark Manor': '142',
117 | 'ATK UP (VIT)': '143',
118 | 'Teleport to Einklang': '149',
119 | 'ATK UP (DEX)': '158',
120 | 'ATK UP (AGI)': '159',
121 | 'MATK UP (INT)': '160',
122 | 'MATK DOWN (VIT)': '161',
123 | 'MATK UP (VIT)': '162',
124 | 'MATK UP (STR)': '163',
125 | 'MATK UP (AGI)': '164',
126 | 'Attack MP Recovery %': '165',
127 | 'MATK DOWN (DEX)': '166',
128 | 'Teleport to Hora Diomedea': '167',
129 | 'Stun Unavailable': '168',
130 | 'Reduce Dmg (Player Epicenter) %': '170',
131 | 'Reduce Dmg (Foe Epicenter) %': '171',
132 | 'Recoil %': '172',
133 | 'Reduce Dmg (Floor) %': '173',
134 | 'Reduce Dmg (Charge) %': '174',
135 | 'Absolute Accuracy %': '175',
136 | 'Reduce Dmg (Bullet) %': '176',
137 | 'Reduce Dmg (Bowling) %': '177',
138 | 'Invicible Aid (sec)': '179',
139 | 'Reduce Dmg (Meteor) %': '180',
140 | 'Absolute Dodge %': '181',
141 | 'MATK DOWN (STR)': '184',
142 | 'Teleport to Nov Saterica': '185',
143 | 'ATK UP (STR)': '186',
144 | 'Reduce Dmg (Straight Line) %': '187',
145 | 'Pet EXP %': '188',
146 | 'Teleport to Rokoko Plains': '189',
147 | 'Item Cooldown': '190',
148 | 'Teleport to Garden of Beginning': '195',
149 | 'Teleport to Garden of Ice & Snow': '196',
150 | 'ATK DOWN (INT)': '197',
151 | 'MATK DOWN (INT)': '198',
152 | 'MATK DOWN (AGI)': '199',
153 | 'MATK UP (DEX)': '200',
154 | 'Teleport to Dikkit Sector': '201',
155 | 'Gem Dust Drop Amount %': '207',
156 | 'Permanently unlock an unique emotion': '208',
157 | 'Teleport to Naiata': '210',
158 | 'Attack Range (m)': '211'
159 | };
160 |
161 | const ITEM_TYPES = {
162 | 'Any': '-1',
163 | 'All Equipments': '-2',
164 | 'Armor': '8',
165 | 'Additional': '6',
166 | 'Special': '18',
167 | '1 Handed Sword': '4',
168 | '2 Handed Tword': '5',
169 | 'Arrow': '7',
170 | 'Bow': '9',
171 | 'Bowgun': '10',
172 | 'Dagger': '11',
173 | 'Halberd': '26',
174 | 'Katana': '27',
175 | 'Knuckles': '13',
176 | 'Magic Device': '15',
177 | 'Shield': '17',
178 | 'Staff': '19',
179 | 'Additional Crysta': '23',
180 | 'Armor Crysta': '22',
181 | 'Normal Crysta': '20',
182 | 'Special Crysta': '24',
183 | 'Weapon Crysta': '21',
184 | 'Enhancer Crysta (Blue)': '200',
185 | 'Enhancer Crysta (Green)': '220',
186 | 'Enhancer Crysta (Purple)': '240',
187 | 'Enhancer Crysta (Red)': '210',
188 | 'Enhancer Crysta (Yellow)': '230',
189 | 'Gem': '12',
190 | 'Usable': '1'
191 | };
192 |
193 | let statList = [];
194 | let statCounter = 0;
195 |
196 | const addStatLine = function() {
197 | $("#stat-lines-block").append(`
198 |
199 |
206 |
207 |
208 |
`);
209 | $(`#stat-input-${statCounter}`).autocomplete({
210 | source: Object.keys(EFF_NAME),
211 | close: function (e, ui) {
212 | validateEffectName(this, statCounter)
213 | }
214 | })
215 | statCounter += 1;
216 | }
217 |
218 | const validateEffectName = function (obj, id) {
219 | const textInput = $(obj).val();
220 | if (textInput == "") {
221 | $(obj).css("background-color", "unset");
222 | $(`#op-${id}`).attr("name", "");
223 | $(`#effect-${id}`).attr("name", "");
224 | return;
225 | }
226 |
227 | const textQuery = Object.keys(EFF_NAME).find(e => e.toLowerCase() == textInput.trim().toLowerCase());
228 | if (textQuery !== undefined) {
229 | $(obj).css("background-color", $(":root").css("--highlight-color"));
230 | $(`#op-${id}`).attr("name", `op[${EFF_NAME[textQuery]}]`);
231 | $(`#effect-${id}`).attr("name", `effect[${EFF_NAME[textQuery]}]`);
232 | } else {
233 | $(obj).css("background-color", $(":root").css("--error-color"));
234 | $(`#op-${id}`).attr("name", "");
235 | $(`#effect-${id}`).attr("name", "");
236 | }
237 | }
238 |
239 | const writeSelectedTypes = function () {
240 | const itemTypes = $("#item-types").val() || [];
241 | if (!itemTypes.length) {
242 | return;
243 | }
244 |
245 | const R_ITEM_TYPES = Object.fromEntries(Object.entries(ITEM_TYPES).map(e => [e[1], e[0]]));
246 | let typeNames = [];
247 | for (const type of itemTypes) {
248 | typeNames.push(R_ITEM_TYPES[type]);
249 | }
250 | let s = typeNames.join(', ')
251 | const commaPos = s.lastIndexOf(',');
252 | if (commaPos != -1) {
253 | $("#selected-types").html(s.substring(0, commaPos) + ' and ' + s.substring(commaPos + 1));
254 | }
255 | else {
256 | $("#selected-types").html(s);
257 | }
258 | }
259 |
260 | const populateItemTypes = function () {
261 | for (const type of Object.keys(ITEM_TYPES)) {
262 | $("#item-types-cg").append(`\n`);
263 | }
264 | }
265 |
266 | const fixbs = function () {
267 | if ($("#item-type-selection-pc").css("display") != "none") {
268 | if ($('.checkbox-group input[type="checkbox"]:checked').length == 0) {
269 | $($('.checkbox-group input[type="checkbox"]')[0]).prop("checked", "true");
270 | }
271 | } else {
272 | if ($("#item-type-selection-mb select")[0].value == '') {
273 | $("#item-type-selection-mb select")[0].value = '-1';
274 | }
275 | }
276 | }
277 |
278 | const setLayout = function () {
279 | if ($(window).width() <= $(window).height()) {
280 | $("#item-type-selection-pc *[name='itype[]']").prop('checked', false);
281 | $("#item-type-selection-pc").remove();
282 | $("#item-type-selection-mb").css("display", "grid");
283 | } else {
284 | $("#item-type-selection-mb *[name='itype[]']").val([]);
285 | $("#item-type-selection-mb").remove();
286 | $("#item-type-selection-pc").show();
287 | }
288 | }
289 |
290 | $("#item-types").html(fillOptions(Object.values(ITEM_TYPES), Object.keys(ITEM_TYPES)));
291 | //$("#stat-choices").html(fillOptions(Object.keys(EFF_NAME)));
292 | writeSelectedTypes();
293 | populateItemTypes();
294 | setLayout();
295 |
296 | $(document).ready(function() {
297 | $(".weapon-crysta > input").click(function() {
298 | if ($(this).is(":checked")) {
299 | $(".enhancer-crysta-red > input").prop("checked", true);
300 | }
301 | else {
302 | $(".enhancer-crysta-red > input").prop("checked", false);
303 | }
304 | })
305 | $(".additional-crysta > input").click(function() {
306 | if ($(this).is(":checked")) {
307 | $(".enhancer-crysta-yellow > input").prop("checked", true);
308 | } else {
309 | $(".enhancer-crysta-yellow > input").prop("checked", false);
310 | }
311 | })
312 | $(".special-crysta > input").click(function() {
313 | if ($(this).is(":checked")) {
314 | $(".enhancer-crysta-purple > input").prop("checked", true);
315 | } else {
316 | $(".enhancer-crysta-purple > input").prop("checked", false);
317 | }
318 | })
319 | $(".armor-crysta > input").click(function() {
320 | if ($(this).is(":checked")) {
321 | $(".enhancer-crysta-green > input").prop("checked", true);
322 | } else {
323 | $(".enhancer-crysta-green > input").prop("checked", false);
324 | }
325 | })
326 | $(".normal-crysta > input").click(function() {
327 | if ($(this).is(":checked")) {
328 | $(".enhancer-crysta-blue > input").prop("checked", true);
329 | } else {
330 | $(".enhancer-crysta-blue > input").prop("checked", false);
331 | }
332 | })
333 | })
--------------------------------------------------------------------------------
/js/scroll.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | //const SCROLL = ['1st Weapon', '2nd Weapon', '3rd Weapon', 'Scroll Type', '1st Skill', '2nd Skill', '3rd Skill']
4 |
5 | const SCROLL_COMBINATIONS = ['1234320', '1247318', '1257351', '1267346', '1277374', '1287347', '1297370', '1323453', '1342416', '1355480', '1361413', '1377453', '1382435', '1394428', '1422540', '1431518', '1453537', '1465578', '1473540', '1483504', '1496516', '1527263', '1537230', '1543250', '1564270', '1577263', '1583235', '1592240', '1624321', '1635374', '1642345', '1657371', '1671321', '1684312', '1693350', '1725783', '1736764', '1745780', '1753753', '1765752', '1785738', '1791731', '1827138', '1835185', '1842134', '1853135', '1862140', '1871138', '1893157', '1921817', '1931815', '1945873', '1954842', '1965853', '1971817', '1985871', '2137304', '2146365', '2151341', '2165308', '2171301', '2184352', '2195380', '2311541', '2343510', '2353580', '2361514', '2373507', '2383534', '2393527', '2412470', '2431410', '2452430', '2462470', '2472400', '2482450', '2492413', '2515681', '2537632', '2546651', '2565674', '2576607', '2587634', '2595647', '2614213', '2634275', '2644240', '2653275', '2675208', '2687213', '2694257', '2715831', '2735867', '2742804', '2753857', '2765853', '2787831', '2795835', '2814362', '2831381', '2847307', '2857304', '2862345', '2871301', '2897354', '2911125', '2931104', '2941170', '2952143', '2961152', '2971103', '2985178', '3122431', '3146467', '3152400', '3167435', '3177431', '3182457', '3195480', '3217513', '3243514', '3253500', '3263541', '3275578', '3283543', '3295570', '3413375', '3427340', '3457300', '3467372', '3477340', '3483358', '3497310', '3512804', '3526865', '3541851', '3565871', '3573865', '3587830', '3592842', '3611713', '3624725', '3647743', '3655700', '3673725', '3685714', '3693750', '3717531', '3723587', '3741581', '3753500', '3762504', '3787534', '3795537', '3817367', '3827304', '3844302', '3857300', '3865347', '3872304', '3897351', '3915428', '3922413', '3943475', '3952400', '3963457', '3971413', '3982475', '4123532', '4133537', '4152547', '4163530', '4173532', '4183501', '4193580', '4212415', '4232420', '4252453', '4264402', '4277473', '4282408', '4295471', '4312347', '4323354', '4357380', '4365317', '4377354', '4383305', '4397321', '4517387', '4526364', '4531301', '4565370', '4577364', '4587305', '4597341', '4611108', '4621123', '4637173', '4655174', '4671123', '4681105', '4693154', '4714302', '4725381', '4736361', '4753354', '4763350', '4785307', '4797304', '4811861', '4825837', '4834802', '4857835', '4862840', '4877837', '4893857', '4914723', '4925718', '4931715', '4952745', '4963751', '4971718', '4987703', '5127231', '5134231', '5145267', '5164235', '5171231', '5184257', '5192284', '5211613', '5234620', '5245618', '5263645', '5276678', '5282643', '5295673', '5315840', '5323856', '5345815', '5365817', '5373856', '5387830', '5395824', '5416376', '5427340', '5437318', '5462374', '5472340', '5487358', '5497315', '5611310', '5624325', '5637378', '5647340', '5677325', '5687314', '5693356', '5711130', '5725187', '5734162', '5745180', '5762154', '5781134', '5795137', '5816760', '5827734', '5835781', '5844732', '5865740', '5872734', '5895751', '5915820', '5921813', '5931813', '5945876', '5965853', '5977813', '5983875', '6127304', '6137300', '6146368', '6151341', '6172304', '6183357', '6195380', '6211210', '6234200', '6244210', '6254250', '6275270', '6282240', '6294270', '6312741', '6324752', '6345714', '6355780', '6373752', '6385731', '6395725', '6415172', '6421140', '6431100', '6451134', '6472140', '6481157', '6492104', '6517381', '6527362', '6535307', '6543354', '6576362', '6581301', '6592345', '6717634', '6726687', '6736605', '6747683', '6754652', '6781631', '6795638', '6815867', '6821831', '6835804', '6845835', '6857831', '6877831', '6895853', '6915127', '6921104', '6931100', '6944172', '6957143', '6972104', '6981175', '7127734', '7135731', '7145762', '7157743', '7165730', '7185750', '7191781', '7215813', '7234820', '7241813', '7255857', '7262840', '7285840', '7295876', '7313543', '7325508', '7345518', '7353580', '7363510', '7383530', '7397523', '7417378', '7427340', '7437310', '7452304', '7465370', '7483350', '7495318', '7511183', '7525168', '7533135', '7542154', '7561170', '7581130', '7595147', '7616614', '7625627', '7636675', '7647643', '7656672', '7686610', '7696658', '7813265', '7827230', '7832284', '7847237', '7857230', '7864240', '7893251', '7917325', '7921314', '7937310', '7945378', '7957341', '7963356', '7985370', '8121137', '8137132', '8146160', '8153145', '8167134', '8175137', '8195187', '8211318', '8237320', '8246316', '8257354', '8262340', '8277370', '8297378', '8317346', '8323350', '8347310', '8355380', '8362314', '8377350', '8393325', '8415873', '8422840', '8431816', '8455835', '8463875', '8475840', '8497813', '8515785', '8525763', '8537734', '8545750', '8564702', '8575763', '8591741', '8611815', '8622824', '8637873', '8645840', '8655871', '8675824', '8693853', '8715237', '8725284', '8731261', '8745280', '8757253', '8764257', '8791231', '8917623', '8923615', '8935618', '8947673', '8952647', '8963658', '8976615', '9127837', '9135835', '9145863', '9152842', '9165830', '9177837', '9181851', '9215107', '9234120', '9244102', '9253153', '9265147', '9272174', '9283145', '9312402', '9323451', '9345417', '9355480', '9361415', '9373451', '9387437', '9411701', '9422740', '9431712', '9455735', '9465704', '9475740', '9482754', '9515802', '9525861', '9537831', '9543857', '9565875', '9576861', '9587837', '9613105', '9621123', '9635174', '9645147', '9657173', '9677123', '9681108', '9715307', '9721381', '9732364', '9747385', '9753351', '9765358', '9787302', '9816601', '9826632', '9836687', '9842634', '9857637', '9866643', '9874632'];
6 |
7 | const SCROLL_SKILLS = {'-1': 'Any', '0': 'Random', '1': 'Fire Release', '2': 'Thunder Release', '3': 'Wind Release', '4': 'Water Release', '5': 'Earth Release', '6': 'Cloning', '7': 'Demon Wind Shuriken', '8': 'Kunai Throw'};
8 | const SLANG_NAMES = {'0': 'Random', '1': 'Fire', '2': 'Thunder', '3': 'Wind', '4': 'Water', '5': 'Earth', '6': 'Clone', '7': 'Shuriken', '8': 'Kunai'};
9 | const WEAPON_TYPES = {'-1': 'Any', '1': '1H Sword', '2': '2H Sword', '3': 'Bow', '4': 'Bowgun', '5': 'Katana', '6': 'Halberd', '7': 'Staff', '8': 'Magic Device', '9': 'Knuckles'};
10 | const WEAPON_ICONS = {'1': 'ohs', '2': 'ths', '3': 'bow', '4': 'bg', '5': 'ktn', '6': 'hb', '7': 'stf', '8': 'md', '9': 'knx'};
11 | /*const SCROLL_TYPES = {'0': 'Any Scroll', '1': 'Fire Scroll', '2': 'Water Scroll', '3': 'Earth Scroll', '4': 'Lightning Scroll', '5': 'Metal Scroll', '6': 'Dark Scroll', '7': 'Wind Scroll'};*/
12 | const SCROLL_TYPES = {'1': 'Fire', '2': 'Lightning', '3': 'Wind', '4': 'Water', '5': 'Earth', '6': 'Dark', '7': 'Metal', '8': 'Metal'};
13 | const SCROLL_STATS = {
14 | '1': 'MATK +1%, With Staffs: Magic Pierce +5%',
15 | '2': 'Stability +5%, With Katanas: Accuracy +10%',
16 | '3': 'Attack Speed +250, With Katanas: Critical Rate +5',
17 | '4': 'Ailment Resistance +5%, With Magic Tools: Aggro -10%',
18 | '5': 'MaxHP +10%, With One Handed Swords: Fractional Barrier +10%',
19 | '6': 'Aggro -10%',
20 | '7': 'Critical Rate +5'
21 | };
22 |
23 | const findCombination = function (combination, byWeapons = false) {
24 | let matches = [];
25 | for (const scroll of SCROLL_COMBINATIONS) {
26 | const scroll_components = byWeapons?scroll.slice(0, 3):scroll.slice(4);
27 | let count = 0;
28 | for (const component of combination) {
29 | if (scroll_components.search(component) != -1) {
30 | count += 1;
31 | }
32 | }
33 |
34 | let cs_randoms = combination.split('0').length-1;
35 | let ss_randoms = scroll_components.split('0').length-1;
36 |
37 | if (count == combination.length && ss_randoms >= cs_randoms) {
38 | matches.push(scroll);
39 | }
40 | }
41 | return matches;
42 | }
43 |
44 | const clickCombinationBox = function () {
45 | let combination = new String($(this).data('id'));
46 | combination.split('').map(function (value, index) {
47 | $("#scroll-component-" + (index + 1)).val(value);
48 | });
49 | craftScroll();
50 | //location.href = "#HEADER";
51 | }
52 |
53 | const scrollTypeList = function (scroll) {
54 | let skills = scroll.slice(4);
55 | if (skills.split('0').length - 1 < 2) {
56 | let types = [];
57 | skills.split('').forEach(function (value) {
58 | if (value > 0 && types.indexOf(SCROLL_TYPES[value]) == -1) {
59 | types.push(SCROLL_TYPES[value]);
60 | }
61 | });
62 | return types.map((x) => `${x}`).join('\n');
63 | }
64 | else {
65 | return "Any";
66 | }
67 | }
68 |
69 | const skillList = function (scroll) {
70 | return scroll.slice(4).split('').map((x) => SLANG_NAMES[x]).join(' | ');
71 | }
72 |
73 | const generateScrollBlock = function (array) {
74 | let result = new String();
75 | for (scroll of array) {
76 | result += `${scrollTypeList(scroll)}
\n`
77 | }
78 | return result;
79 | }
80 |
81 | const searchScroll = function () {
82 | let scroll = '';
83 | let s = [$("#scroll-skill-1").val(), $("#scroll-skill-2").val(), $("#scroll-skill-3").val()];
84 | for (const skill of s) {
85 | scroll = (skill != '-1')?scroll+skill:scroll;
86 | }
87 | let combinations = findCombination(scroll);
88 | if (combinations.length != 0) {
89 | $("#results").show();
90 | $(".results-container > div:not(#results)").hide();
91 | $("#results").html(generateScrollBlock(combinations));
92 | $(".combination-box").on("click", clickCombinationBox);
93 | }
94 | else {
95 | $("#results-warning").show();
96 | $(".results-container > div:not(#results-warning)").hide();
97 | }
98 | $('.results-parent').show();
99 | }
100 |
101 | const limitSkillOptions = function (event) {
102 | let val = $(this).val();
103 | if (val != '-1' && val != '0')
104 | $('select[id^="scroll-skill-"').not(this).each(function () {
105 | if ($(this).val() == val) {
106 | $(this).val("-1");
107 | }
108 | });
109 | }
110 |
111 | const resetChoosenSkill = function (event) {
112 | $("#scroll-skill-" + $(this).data("id")).val('0');
113 | $('select[id^="scroll-skill-"').change();
114 | }
115 |
116 | const resetScrollSkills = function () {
117 | $('select[id^="scroll-skill-"').val('-1');
118 | $('.results-parent').hide();
119 | $('select[id^="scroll-skill-"').change();
120 | }
121 |
122 | const craftScroll = function (searchAny = false) {
123 | let cArray = [];
124 | $('select[id^="scroll-component-"').each(function () {
125 | if ($(this).val() != '-1') {
126 | cArray.push($(this).val());
127 | }
128 | });
129 |
130 | let components = cArray.join('');
131 |
132 | if (cArray.length == 3) {
133 | let scroll = SCROLL_COMBINATIONS.find((x) => x.startsWith(components));
134 | let skills = scroll.slice(4);
135 |
136 | if (skills.split('0').length - 1 < 2) {
137 | let types = [];
138 | skills.split('').forEach(function (value) {
139 | if (value > 0 && types.indexOf(SCROLL_TYPES[value]) == -1) {
140 | types.push(SCROLL_TYPES[value]);
141 | }
142 | });
143 | $("#craft-results-type").html(types.map((x) => `${x}`).join('\n'));
144 | }
145 | else {
146 | $("#craft-results-type").html("Any");
147 | }
148 |
149 | //$("#craft-results-type").html(SCROLL_TYPES[scroll[3]]);
150 | $("#craft-results-skills").html(scroll.slice(4).split('').map((x) => SCROLL_SKILLS[x]).join(' | '));
151 | $("#craft-results-container").show();
152 | }
153 | else {
154 | $("#craft-results-container").hide();
155 | }
156 |
157 | if (searchAny == true) {
158 | let results = String();
159 | SCROLL_COMBINATIONS.forEach(function (scroll) {
160 | const weapons = scroll.slice(0, 3);
161 | for (const component of components) {
162 | if (weapons.search(component) == -1) {
163 | return;
164 | }
165 | }
166 | results += `\n`
167 | });
168 | $("#results").html(results);
169 | $(".combination-box").on("click", clickCombinationBox);
170 | $('.results-parent').show();
171 | $("#results-warning").hide();
172 | }
173 | }
174 |
175 | const possibleScrolls = function () {
176 |
177 | }
178 |
179 | const limitWeaponCombinations = function (event) {
180 | const val = $(this).val();
181 | $('select[id^="scroll-component-"').not(this).each(function () {
182 | if ($(this).val() == val) {
183 | $(this).val("-1");
184 | }
185 | });
186 | }
187 |
188 | const resetScrollComponents = function () {
189 | $('select[id^="scroll-component-"').val('-1');
190 | $('select[id^="scroll-component-"').change();
191 | $("#craft-results-container").hide();
192 | }
193 |
194 | $(document).ready(function () {
195 | $('select[id^="scroll-skill-"').append(fillOptions(Object.keys(SCROLL_SKILLS), Object.values(SCROLL_SKILLS))).val('-1');
196 | $('select[id^="scroll-component-"').append(fillOptions(Object.keys(WEAPON_TYPES), Object.values(WEAPON_TYPES))).val('-1');
197 | $('#scroll-search-reset').on("click", resetScrollSkills);
198 | $('#craft-scroll-reset').on("click", resetScrollComponents);
199 | $('select[id^="scroll-skill-"').change(limitSkillOptions);
200 | $('select[id^="scroll-component-"').change(limitWeaponCombinations);
201 | $('#scroll-search').on("click", searchScroll);
202 | $('#craft-scroll').on("click", () => craftScroll(true));
203 | //$('.reset-skill').on("click", resetChoosenSkill);
204 |
205 | $("#cs-popup").on("click", function () {
206 | alert("Scroll type is bound to its skills, but each type has specific stats:\n\n" + Object.keys(SCROLL_STATS).map((x) => `${SCROLL_TYPES[x]} = ${SCROLL_STATS[x]}`).join('; \n') + '.');
207 | });
208 | $("#results-popup").on("click", function () {
209 | alert("For more details, click on a combination to push it to craft section.");
210 | });
211 | $("#sss-popup").on("click", function () {
212 | alert("Random = Question Mark Skill (?)\nAny = Random (?) or Fixed (Wind, Water, etc.)");
213 | });
214 | });
--------------------------------------------------------------------------------
/js/xp.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | const quest_data = {
3 | "Custom Experience Value": "",
4 | "Nightmare Crystal (Stack)": 297000,
5 | "Lapin's Soul (Piece)": 344000,
6 | "Parasited Crystal (Stack)": 380000,
7 | "Free from Infesters! (2k f/k)": 15000000,
8 | "Defeat Metal Stinger (x100)": 3240000,
9 | "Minotaur Skin (Stack)": 999900,
10 | "Cracked Platinum Armguard (Stack)": 677000
11 | };
12 |
13 | const mq_data = {
14 | "Chapter 1":"",
15 | "First Time Visit":30,
16 | "Straye Brother and Sister":80,
17 | "A Golem on a Rampage":730,
18 | "The Goddess of Wisdom":2050,
19 | "The Dragon's Den":4700,
20 | "The Ruined Temple":9330,
21 | "The First Magic Stone":16700,
22 | "Purification Incense":27900,
23 | "The Dragon and Black Crystal":43000,
24 | "Chapter 2":"",
25 | "The Merchant Girl":64000,
26 | "Where Are the Gems?":92000,
27 | "Who is the Black Knight?!":118200,
28 | "Trials in the Palace":149000,
29 | "The Moon Wizard":172000,
30 | "The Follower and Hater":227000,
31 | "The Wizard's Cave":240000,
32 | "The Star Wizard":255000,
33 | "Chapter 3":"",
34 | "The Invincible... Enemy??":270000,
35 | "The Ancient Empress":284000,
36 | "The Culprit":319000,
37 | "Fate of the Fortress":335000,
38 | "Memory in the Lost Town":398000,
39 | "The Stolen Sorcery Gem":417000,
40 | "Living with a Dragon":462300,
41 | "Monsters from Outerworld":540000,
42 | "Chapter 4":"",
43 | "The Mage Diels":562000,
44 | "Journey for Reconstruction":585000,
45 | "The Sacred Gem in Akaku":710000,
46 | "The King of Darkan":740000,
47 | "The Lurking Evil":803000,
48 | "Find the False Black Knight!":913000,
49 | "Technista's Movement":1000000,
50 | "The Falling Feather of Death":1100000,
51 | "Chapter 5":"",
52 | "In The Unknown Darkness":1150000,
53 | "The Charm":1310000,
54 | "Parching Dark Mirror":1370000,
55 | "Fierce Battle in the Garden":1550000,
56 | "A Light in the Darkness":1750000,
57 | "The Ones Nesting in the Manor":1970000,
58 | "The Dark Castle":2210000,
59 | "To The Living World":2220000,
60 | "Chapter 6":"",
61 | "Demi Machina":2600000,
62 | "The Town of Pax Faction":2700000,
63 | "Mechanical Heart":2800000,
64 | "Black Knights of Lyark":2820000,
65 | "The Mysterious Artifact":3030000,
66 | "Truth of the Artifact":3099000,
67 | "The Price of Treachery":3320000,
68 | "The Blasphemous Factory":3640000,
69 | "Mystery of the Black Knights":4020000,
70 | "Chapter 7":"",
71 | "Monster's Forest":4730000,
72 | "The Underground Town":4820000,
73 | "The Elves in Lyark":5070000,
74 | "The Mad Laboratory":5500000,
75 | "Tragedy in the Jail":6000000,
76 | "Calamity in Droma Square":6400000,
77 | "Head for Ultimea Palace":6900000,
78 | "The Chaotic Truth":7400000,
79 | "Chapter 8":"",
80 | "The Mine Where Monsters Lurk":8400000,
81 | "The Mysterious Shadow":8500000,
82 | "The New Diel Country":8600000,
83 | "The Ruins of the Gods":8800000,
84 | "The Former God of Justice":9100000,
85 | "The Remaining Thrones in the Shrine":9700000,
86 | "Gods' Whereabouts":10400000,
87 | "The Wait at Specia's Shrine":11100000,
88 | "The Warden of Ice & Snow":11800000,
89 | "At Mountains' End":12500000,
90 | "Chapter 9":"",
91 | "Deadly Road to Eldenbaum":15800000,
92 | "Unforeseen Traps":17100000,
93 | "Traces of Technological Progress":18200000,
94 | "An Unexpected Acquaintance":19200000,
95 | "Front Line Base Operation":20300000,
96 | "Strategy to Redeem the Treetop Harbor":21500000,
97 | "The Teleporter Left Behind":22700000,
98 | "The Man Who Seeks Death":23900000,
99 | "The Battle to Recapture Eldenbaum":25000000,
100 | "A New Beginning":13000000,
101 | "Chapter 10":"",
102 | "Off to the Fateful Land":26000000,
103 | "The Inhabitants Under the Cliff":27400000,
104 | "The Nightmare Returns":28800000,
105 | "The Whereabouts of the Missing Monks":30200000,
106 | "The Goddess of Justice and the Squatters":31600000,
107 | "Navigator of the Ark":33100000,
108 | "Witch in the Woods": 34600000,
109 | "The Duel in Nov Diela": 36200000,
110 | "Chapter 11":"",
111 | "Flying the Ark":37800000,
112 | "Land of the Unknown":49000000,
113 | "The Strolling Forest":51000000,
114 | "Eumanos the Forest Dwellers": 53400000,
115 | "A Sproutling is Born": 55700000,
116 | "The Blessing-Bearer": 58100000,
117 | "Intense Battle in Coenubia's Stronghold": 60500000,
118 | "The Shadow of a Smoky Mountain": 63000000,
119 | "The Weredragons & the Underground World": 65500000,
120 | "Chapter 12": "",
121 | "The Sky with a Ceiling": 73400000,
122 | "Rivalry Between Dragons and Weredragons": 76300000,
123 | "Weredragon Couple and a Baby": 79300000,
124 | "Weredragons' Vital Point": 82300000,
125 | "Intense Battle in Propulsion System": 85300000,
126 | "Discovering a New Technology": 44200000,
127 | "Ark Repair": 92700000,
128 | "Weredragon Dispute": 96000000,
129 | "Cocoon in the Ice Wall": 99300000,
130 | "Chapter 13":"",
131 | "Underwater Inhabitants": 112600000,
132 | "Water Dome": 116500000,
133 | "Underwater City": 60200000,
134 | "The Thing in the Abandoned District": 125800000,
135 | "Shadow from the Abyss": 129900000,
136 | "The Ruthless Council": 67000000,
137 | "Mysterious Entity in the Little Shrine": 139900000,
138 | "The Great Battle Underwater": 144200000,
139 | "Chapter 14":"",
140 | "Crisis in the Sky": 159100000,
141 | "The Surviving Siblings": 164000000,
142 | "Chaotic Situation": 168900000,
143 | "The Bitter Truth": 173800000,
144 | "The Uncouth Rana Prince": 178800000,
145 | "Mutant Coenubia Village": 183900000,
146 | "Fierce Battle with Mutant Lixis": 189000000,
147 | "Chapter 15":"",
148 | "Ark Crisis": 210500000,
149 | "Coastal Clash": 216300000,
150 | "Unda's Rescue Operation": 222200000,
151 | };
152 |
153 |
154 | const splitMqInfo = function () {
155 | let mqKeys = [];
156 | let mqValues = [];
157 | let currentChapter = 0;
158 | const keys = Object.keys(mq_data);
159 | for (let i = 0; i < keys.length; i++) {
160 | if (keys[i].startsWith('Chapter')) {
161 | currentChapter += 1;
162 | }
163 | else {
164 | mqKeys.push(`CH${currentChapter} - ${keys[i]}`);
165 | mqValues.push(i);
166 | }
167 | }
168 | return [mqKeys, mqValues];
169 | }
170 |
171 | $(document).ready(function () {
172 | $("#target-level").val(LV_CAP);
173 | $("#quest-name").html(fillOptions(Object.values(quest_data), Object.keys(quest_data)));
174 | $("#quest-name").val("15000000").trigger("input");
175 | let [keys, vals] = splitMqInfo();
176 | $("#mq-from").html(fillOptions(vals, keys));
177 | $("#mq-until").html(fillOptions(vals.reverse(), keys.reverse()));
178 | $("body form").trigger("input");
179 | });
180 |
181 | $("#quest-popup").on("click", function () {
182 | alert('Use custom experience to set unlisted quest or monster experience.\n\nHint: Type "1" on "Exp" field to discover total raw XP required to reach target Lv.');
183 | });
184 |
185 |
186 | const getXP = (lv) => floor(0.025*lv**4+2*lv);
187 |
188 | const getTotalXP = function (begin, beginPercentage, end) {
189 | let xp = floor((1-beginPercentage/100)*getXP(begin));
190 | for (let i = begin+1; i < end; i++) {
191 | xp += getXP(i);
192 | }
193 | return xp;
194 | }
195 |
196 | const addXP = function (begin, beginPercentage, extraXP) {
197 | let remainingXP = extraXP
198 | let lv, lvPercentage
199 |
200 | let XPRequiredNextLv = (1-beginPercentage/100)*getXP(begin)
201 |
202 | if (extraXP < XPRequiredNextLv) {
203 | let currentXP = beginPercentage/100*getXP(begin)+extraXP
204 | return [begin, floor(100*currentXP/getXP(begin))]
205 | } else {
206 | remainingXP -= XPRequiredNextLv
207 | lv = begin + 1
208 | while (getXP(lv) <= remainingXP) {
209 | remainingXP -= getXP(lv)
210 | lv += 1
211 | }
212 | lvPercentage = floor(100*remainingXP/getXP(lv));
213 | return [lv, lvPercentage];
214 | }
215 | }
216 |
217 | const evaluateTarget = function () {
218 | let lv = parseInput("#level");
219 | let target = parseInput("#target-level");
220 | let percentage = parseInput("#level-percentage", 0);
221 | let questXP = parseInput("#quest-exp", 0);
222 | let xpRequired = getTotalXP(lv, percentage, target);
223 | let targetTimes = ceil(xpRequired/questXP);
224 | let [nLv, nLvP] = addXP(lv, percentage, questXP*parseInput("#quest-times", 0));
225 | $("#target-times").text(targetTimes);
226 | $("#times-level").text(`${nLv} (${nLvP}%)`);
227 | $("#times-value").text(parseInput("#quest-times", 0));
228 | $("#xp-required").text(new Intl.NumberFormat().format(xpRequired));
229 | }
230 |
231 | const evaluateDiaries = function () {
232 | let mqBegin = parseInt($("#mq-from").val());
233 | let mqEnd = parseInt($("#mq-until").val());
234 | const skipVenena = $("#skip-venena").prop("checked");
235 | if (mqBegin <= mqEnd) {
236 | const keys = Object.keys(mq_data);
237 | let lv = parseInput("#level");
238 | let initialLv = lv;
239 | let lvP = parseInput("#level-percentage", 0);
240 | let initialLvP = lvP;
241 | let targetLv = parseInput("#target-level");
242 | let targetXP = getTotalXP(lv, lvP, targetLv); // 1
243 |
244 | let mqXP = 0;
245 | for (let i = mqBegin; i <= mqEnd; i++) {
246 | mqXP += Number(mq_data[keys[i]]);
247 | if (i == 85 && !skipVenena) { // 85 = metacoenubia quest, not skipping gives +12.5m xp after decel fight
248 | mqXP += 12500000;
249 | }
250 | } // 2
251 |
252 | const runs = floor(targetXP/mqXP);
253 | const exact_runs = (runs == ceil(targetXP/mqXP)); //#####PAREI AQUI
254 |
255 | if (runs <= 100) {
256 | $("#mq-table-results").html(`
257 |
262 | `);
263 | } else {
264 | $("#mq-table-results").html(`
265 |
266 | Error: Too many runs required (${runs+1}), select a wider range between quests.
267 |
268 | `);
269 | return;
270 | }
271 |
272 | for (let i = 1; i <= runs; i++) {
273 | [lv, lvP] = addXP(lv, lvP, mqXP);
274 | $("#mq-table-results").append(`
275 |
276 |
${i}
277 |
${$(`#mq-until option[value="${mqEnd}"]`).text()}
278 |
${lv} (${lvP}%)
279 |
280 | `);
281 | }
282 |
283 | if (!exact_runs) {
284 | let mqStopIndex = mqBegin;
285 | let curXP = getTotalXP(initialLv, initialLvP, lv)+lvP/100*getXP(lv+1);
286 | let stackedXP = 0;
287 | for (let i = mqBegin; i <= mqEnd; i++) {
288 | curXP += Number(mq_data[keys[i]]);
289 | stackedXP += Number(mq_data[keys[i]]);
290 | if (i == 85 && !skipVenena) { // 85 = metacoenubia quest, not skipping gives +12.5m xp after decel fight
291 | curXP += 12500000;
292 | stackedXP += Number(mq_data[keys[i]]);
293 | }
294 | if (curXP > targetXP) {
295 | mqStopIndex = i;
296 | [lv, lvP] = addXP(lv, lvP, stackedXP);
297 | break;
298 | }
299 | }
300 | $("#mq-table-results").append(`
301 |
302 |
${runs+1}
303 |
${$(`#mq-until option[value="${mqStopIndex}"]`).text()}
304 |
${lv} (${lvP}%)
305 |
306 | `);
307 | }
308 | }
309 | }
310 |
311 | const evaluateMQ = function () {
312 | let mqBegin = parseInt($("#mq-from").val());
313 | let mqEnd = parseInt($("#mq-until").val());
314 | const skipVenena = $("#skip-venena").prop("checked");
315 | if (mqBegin <= mqEnd) {
316 | const keys = Object.keys(mq_data);
317 | let mqXP = 0;
318 | let mqXPReverse = 0;
319 | let lv = parseInput("#level");
320 | let lvP = parseInput("#level-percentage", 0);
321 | let targetLv = parseInput("#target-level");
322 | let targetXP = getTotalXP(lv, lvP, targetLv);
323 | let mqStopIndex = mqBegin;
324 | let mqStartIndex = mqEnd;
325 | let mqStopAt = false;
326 | let mqStartFrom = false;
327 | for (let i = mqBegin; i <= mqEnd; i++) {
328 | mqXP += Number(mq_data[keys[i]]);
329 | mqXPReverse += Number(mq_data[keys[mqEnd-(i-mqBegin)]])
330 | if (i == 85 && !skipVenena) { // 85 = metacoenubia quest, not skipping gives +12.5m xp after decel fight
331 | mqXP += 12500000;
332 | }
333 | if (mqEnd-(i-mqBegin) == 85 && !skipVenena) {
334 | mqXPReverse += 12500000;
335 | }
336 | if (!mqStopAt && mqXP > targetXP) {
337 | mqStopAt = true;
338 | mqStopIndex = i;
339 | }
340 | if (!mqStartFrom && mqXPReverse > targetXP) {
341 | mqStartFrom = true;
342 | mqStartIndex = mqEnd-(i-mqBegin);
343 | }
344 | }
345 | $("#mq-xp").html(`XP: ${new Intl.NumberFormat().format(mqXP)}`);
346 | let [mqLv, mqLvP] = addXP(lv, lvP, mqXP);
347 | $("#mq-eval").html(`After doing Main Quest's above range you'll reach Lv.${mqLv} (${mqLvP}%)`);
348 |
349 | const spamAdv = $("#multiple-mq").prop("checked");
350 |
351 | if (mqStopAt && !spamAdv) {
352 | let quest = $(`#mq-until option[value="${mqStopIndex}"]`).text();
353 | $("#mq-stopAt").html(`You may stop after quest ${quest} to reach target level`);
354 | $("#mq-or").show();
355 | }
356 | else {
357 | $("#mq-stopAt").html("");
358 | $("#mq-or").hide();
359 | }
360 |
361 | if (mqStartFrom && !spamAdv) {
362 | let quest = $(`#mq-until option[value="${mqStartIndex}"]`).text();
363 | $("#mq-startFrom").html(`You may start from quest ${quest} to reach target level`);
364 | }
365 | else {
366 | $("#mq-startFrom").html("");
367 | }
368 | }
369 | else {
370 | $("#mq-eval").html("Seems we have a time travel here");
371 | $("#mq-stop").html("");
372 | }
373 | }
374 |
375 | $('input[name="ui-select"]').on("change", function() {
376 | let tag = $(this).attr("id").split('-')[0];
377 | $('.ui-group').not(`.${tag}-group`).hide();
378 | $(`.${tag}-group`).show();
379 |
380 | const spamAdv = $("#multiple-mq").prop("checked");
381 | if (spamAdv && tag == "mq") {
382 | evaluateDiaries();
383 | $("#mq-table").show();
384 | }
385 | else {
386 | $("#mq-table").hide();
387 | }
388 | });
389 | $("#quest-name").on("input", function () {
390 | $("#quest-exp").val(this.value);
391 | });
392 | $("body form").on("input", function () {
393 | evaluateTarget();
394 | evaluateMQ();
395 |
396 | const spamAdv = $("#multiple-mq").prop("checked");
397 | if (spamAdv) {
398 | evaluateDiaries();
399 | $("#mq-table").show();
400 | }
401 | else {
402 | $("#mq-table").hide();
403 | }
404 | });
405 |
--------------------------------------------------------------------------------
/js/statting.js:
--------------------------------------------------------------------------------
1 | /* this code is retarded and even myself have difficulty to understand what the fuck I wrote */
2 |
3 | "use strict"
4 |
5 | const MAX_FIELDS = 8;
6 |
7 | const DB = [
8 | ['', 0, 0, 0.0, 0, 0, 0, 'Choose a stat', '0', 0, 0, 1, 0, 200],
9 | ['STR', 1, 5, 25.0, 20, 1, 1, 'Enhance Stats', 'U', 1, 1, 10, 0, 210],
10 | ['STR %', 1, 10, 50.0, 10, 1, 0, 'Enhance Stats', 'U', 1, 0, 1, 0, 200],
11 | ['INT', 2, 5, 25.0, 20, 1, 1, 'Enhance Stats', 'U', 1, 1, 10, 0, 210],
12 | ['INT %', 2, 10, 50.0, 10, 1, 0, 'Enhance Stats', 'U', 1, 0, 1, 0, 200],
13 | ['VIT', 3, 5, 25.0, 20, 1, 1, 'Enhance Stats', 'U', 1, 1, 10, 0, 210],
14 | ['VIT %', 3, 10, 50.0, 10, 1, 0, 'Enhance Stats', 'U', 1, 0, 1, 0, 200],
15 | ['AGI', 4, 5, 25.0, 20, 1, 1, 'Enhance Stats', 'U', 1, 1, 10, 0, 210],
16 | ['AGI %', 4, 10, 50.0, 10, 1, 0, 'Enhance Stats', 'U', 1, 0, 1, 0, 200],
17 | ['DEX', 5, 5, 25.0, 20, 1, 1, 'Enhance Stats', 'U', 1, 1, 10, 0, 210],
18 | ['DEX %', 5, 10, 50.0, 10, 1, 0, 'Enhance Stats', 'U', 1, 0, 1, 0, 200],
19 | ['Natural HP Regen', 3, 5, 25.0, 20, 1, 1, 'Enhance HP/MP', 'A', 1, 1, 10, 0, 210],
20 | ['Natural HP Regen %', 3, 10, 50.0, 10, 1, 0, 'Enhance HP/MP', 'A', 1, 0, 1, 0, 200],
21 | ['Natural MP Regen', 2, 10, 50.0, 10, 1, 1, 'Enhance HP/MP', 'A', 1, 1, 20, 0, 220],
22 | ['Natural MP Regen %', 2, 20, 100.0, 5, 1, 0, 'Enhance HP/MP', 'A', 1, 0, 1, 0, 200],
23 | ['MaxHP', 3, 3, 16.49, 20, 10, 160, 'Enhance HP/MP', 'U', 1, 1, 10, 0, 210],
24 | ['MaxHP %', 3, 10, 50.0, 10, 1, 1, 'Enhance HP/MP', 'U', 1, 1, 10, 0, 230],
25 | ['MaxMP', 2, 6, 33.49, 15, 10, 10, 'Enhance HP/MP', 'U', 1, 1, 20, -15, 220],
26 | ['ATK', 1, 3, 16.49, 20, 1, 1, 'Enhance Attack', 'W', 1, 1, 10, 0, 210],
27 | ['ATK %', 1, 10, 50.0, 10, 1, 1, 'Enhance Attack', 'W', 1, 1, 20, 0, 220],
28 | ['MATK', 2, 3, 16.49, 20, 1, 1, 'Enhance Attack', 'W', 1, 1, 10, 0, 210],
29 | ['MATK %', 2, 10, 50.0, 10, 1, 1, 'Enhance Attack', 'W', 1, 1, 20, 0, 220],
30 | ['Stability %', 5, 20, 100.0, 5, 1, 0, 'Enhance Attack', 'U', 1, 0, 1, 0, 200],
31 | ['Physical Pierce %', 1, 20, 100.0, 5, 1, 1, 'Enhance Attack', 'W', 1, 1, 20, 0, 230],
32 | ['Magic Pierce %', 2, 20, 100.0, 5, 1, 1, 'Enhance Attack', 'W', 1, 1, 20, 0, 230],
33 | ['DEF', 3, 3, 16.49, 20, 1, 10, 'Enhance Defense', 'A', 1, 1, 10, 0, 210],
34 | ['DEF %', 3, 10, 50.0, 10, 1, 1, 'Enhance Defense', 'A', 1, 1, 20, 0, 230],
35 | ['MDEF', 3, 3, 16.49, 20, 1, 10, 'Enhance Defense', 'A', 1, 1, 10, 0, 210],
36 | ['MDEF %', 3, 10, 50.0, 10, 1, 1, 'Enhance Defense', 'A', 1, 1, 20, 0, 230],
37 | ['Physical Resistance %', 3, 10, 50.0, 10, 1, 1, 'Enhance Defense', 'A', 1, 1, 20, 0, 230],
38 | ['Magical Resistance %', 2, 10, 50.0, 10, 1, 1, 'Enhance Defense', 'A', 1, 1, 20, 0, 230],
39 | ['Accuracy', 5, 10, 50.0, 10, 1, 2, 'Enhance Accuracy', 'W', 1, 1, 10, 0, 220],
40 | ['Accuracy %', 5, 20, 100.0, 5, 1, 0, 'Enhance Accuracy', 'W', 1, 0, 1, 0, 200],
41 | ['Dodge', 4, 10, 50.0, 10, 1, 2, 'Enhance Dodge', 'A', 1, 1, 10, 0, 220],
42 | ['Dodge %', 4, 20, 100.0, 5, 1, 0, 'Enhance Dodge', 'A', 1, 0, 1, 0, 200],
43 | ['ASPD', 4, 1, 1.49, 20, 1, 16, 'Enhance Speed', 'U', 1, 1, 10, 0, 210],
44 | ['ASPD %', 4, 1, 5.0, 20, 1, 0, 'Enhance Speed', 'U', 1, 0, 1, 0, 200],
45 | ['CSPD', 5, 1, 1.49, 20, 1, 16, 'Enhance Speed', 'U', 1, 1, 10, 0, 210],
46 | ['CSPD %', 5, 1, 5.0, 20, 1, 0, 'Enhance Speed', 'U', 1, 0, 1, 0, 200],
47 | ['Critical Rate', 6, 1, 5.0, 20, 1, 1, 'Enhance Critical', 'U', 1, 1, 10, -20, 210],
48 | ['Critical Rate %', 6, 1, 5.0, 20, 1, 1, 'Enhance Critical', 'U', 1, 1, 10, -20, 210],
49 | ['Critical Damage', 6, 3, 16.49, 20, 1, 1, 'Enhance Critical', 'U', 1, 1, 10, 0, 230],
50 | ['Critical Damage %', 6, 10, 50.0, 10, 1, 0, 'Enhance Critical', 'U', 1, 0, 1, 0, 200],
51 | ['% stronger against Fire', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
52 | ['% stronger against Water', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
53 | ['% stronger against Wind', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
54 | ['% stronger against Earth', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
55 | ['% stronger against Light', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
56 | ['% stronger against Dark', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'W', 1, 1, 10, 0, 230],
57 | ['Fire resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
58 | ['Water resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
59 | ['Wind resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
60 | ['Earth resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
61 | ['Light resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
62 | ['Dark resistance %', 6, 5, 25.0, 20, 1, 1, 'Enhance Elements', 'A', 1, 1, 10, 0, 220],
63 | ['Ailment Resistance %', 6, 20, 100.0, 5, 1, 0, 'Special Enhancement', 'U', 1, 0, 1, 0, 200],
64 | ['Guard Power %', 6, 20, 100.0, 5, 1, 0, 'Special Enhancement', 'U', 1, 0, 1, 0, 200],
65 | ['Guard Recharge %', 6, 20, 100.0, 5, 1, 0, 'Special Enhancement', 'U', 1, 0, 1, 0, 200],
66 | ['Evasion Recharge %', 6, 20, 100.0, 5, 1, 0, 'Special Enhancement', 'U', 1, 0, 1, 0, 200],
67 | ['Aggro %', 6, 6, 33.49, 15, 1, 1, 'Special Enhancement', 'U', 1, 1, 20, -15, 220],
68 | ['Reduce Dmg (Player Epicenter) %', 3, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
69 | ['Reduce Dmg (Foe Epicenter) %', 3, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
70 | ['Reduce Dmg (Floor) %', 5, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
71 | ['Reduce Dmg (Charge) %', 1, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
72 | ['Reduce Dmg (Bullet) %', 2, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
73 | ['Reduce Dmg (Bowling) %', 2, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
74 | ['Reduce Dmg (Meteor) %', 5, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
75 | ['Reduce Dmg (Straight Line) %', 1, 3, 13.0, 0, 0, 1, 'Enhance Defense', 'A', 0, 1, 10, 0, 210],
76 | ['Fire Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200],
77 | ['Water Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200],
78 | ['Wind Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200],
79 | ['Earth Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200],
80 | ['Light Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200],
81 | ['Dark Element', 6, 100, 150.0, 1, 1, 0, 'Awaken Elements', 'E', 0, 0, 1, 0, 200]
82 | ];
83 |
84 | /* ['Stat Name', 'Base Material Type', 'Potential Cost', 'Base Material Cost', 'Legacy Stat Cap','View Increment', 'Model Increment', 'Stat Category', 'Stat Nature', 'Signed?', 'View Increment After Cap', 'Level Gap Requirement', 'Bottom Cap? [0=No]', 'Min Level to Apply After Cap']; */
85 |
86 | let ZEROES = [];
87 | for (let i = 0; i < MAX_FIELDS; i++) {
88 | ZEROES.push("0");
89 | }
90 |
91 | angular.module("StattingSim", []).controller("StattingSimController", function ($scope) {
92 | var SS = this;
93 | SS.DB = DB;
94 |
95 | SS.ARMOR_CHOICES = DB.slice(0, DB.length-6).map((entry) => entry[0]);
96 | SS.WEAPON_CHOICES = DB.map((entry) => entry[0]);
97 |
98 | SS.lvcap = LV_CAP;
99 | SS.recipePot = 0;
100 | SS.itemNature = "W";
101 | SS.startingPot = floor(HIGHEST_WPN_POT*1.3)+floor((PRIMARY_STAT+SECONDARY_STAT)/20);
102 |
103 | SS.showthisbs = function () {
104 | }
105 |
106 | SS.trackShownSteps = (index, step) => step.amount;
107 |
108 | SS.getPenalty = function () {
109 | let groups = {};
110 | for (let i = 0; i < MAX_FIELDS; i++) {
111 | const group = DB[SS.statList[i].id][7];
112 | if (group == 'Choose a stat') {
113 | continue;
114 | }
115 |
116 | if (groups.hasOwnProperty(group)) {
117 | groups[group] += 1;
118 | }
119 | else {
120 | groups[group] = 1;
121 | }
122 | }
123 |
124 | let penalty = 100;
125 | for (const key of Object.keys(groups)) {
126 | const n = groups[key];
127 | penalty += (n > 1)?5*n**2:0;
128 | }
129 |
130 | return penalty/100;
131 | }
132 |
133 | SS.deltaPotential = function (index, prev, post) {
134 | const statNature = DB[SS.statList[index].id][8];
135 | const statCap = DB[SS.statList[index].id][4];
136 | const potCost = DB[SS.statList[index].id][2];
137 |
138 | let multiplier = 1000;
139 | if (statNature != SS.itemNature && (statNature == "A" || statNature == "W")) {
140 | multiplier = 2000;
141 | }
142 | if (statNature == "E" && SS.matchingElement) {
143 | multiplier = 100;
144 | }
145 |
146 | let delta = 0;
147 | if (post > prev) {
148 | for (let i = prev+1; i <= post; i++) {
149 | if (i <= statCap) {
150 | delta -= potCost*multiplier;
151 | }
152 | else {
153 | delta -= 2*potCost*multiplier;
154 | }
155 | }
156 | }
157 | else {
158 | for (let i = prev-1; i >= post; i--) {
159 | if (i < -statCap) {
160 | delta += potCost*0.1525*multiplier;
161 | }
162 | else {
163 | delta += potCost*0.305*multiplier;
164 | }
165 | }
166 | }
167 |
168 | return trunc(delta/1000);
169 | }
170 |
171 | SS.evaluatePotential = function () {
172 | SS.curPot = SS.prevPot;
173 | let delta = 0;
174 | for (let i = 0; i < MAX_FIELDS; i++) {
175 | if (SS.stepList.length != 0 && SS.stepList[SS.stepList.length-1].id == 0) {
176 | continue;
177 | }
178 |
179 | const refValue = (SS.stepList.length != 0)?SS.stepList[SS.stepList.length-1].stats[i].amount:0;
180 | SS.statList[i].delta = SS.deltaPotential(i, refValue, SS.statList[i].amount);
181 | delta += SS.statList[i].delta;
182 |
183 | const shownPost200 = DB[SS.statList[i].id][6];
184 | const shownPre200 = DB[SS.statList[i].id][5];
185 | const statCap = DB[SS.statList[i].id][4];
186 |
187 | if (SS.statList[i].amount >= 0) {
188 | SS.statList[i].shownAmount = min(SS.statList[i].amount, statCap)*shownPre200+max(0, SS.statList[i].amount-statCap)*shownPost200;
189 | }
190 | else {
191 | SS.statList[i].shownAmount = max(SS.statList[i].amount, -statCap)*shownPre200+min(0, SS.statList[i].amount+statCap)*shownPost200;
192 | }
193 | }
194 | SS.curPot = SS.curPot+trunc(delta*SS.getPenalty());
195 | }
196 |
197 | SS.setPot = function () {
198 | SS.curPot = SS.startingPot;
199 | SS.prevPot = SS.curPot;
200 | SS.configDisabled = true;
201 | SS.statNames = (SS.itemNature == "A")?SS.ARMOR_CHOICES:SS.WEAPON_CHOICES;
202 | SS.disabledStats = 0;
203 | SS.finished = false;
204 | SS.successRate = 100;
205 |
206 | SS.stepList = [];
207 | SS.statList = [];
208 | SS.shownSteps = [];
209 | for (let i = 0; i < MAX_FIELDS; i++) {
210 | SS.statList.push({id: "0", amount: 0, shownAmount: 0, delta: 0});
211 | }
212 | }
213 |
214 | SS.resetPot = function () {
215 | SS.configDisabled = false;
216 | }
217 |
218 | SS.setZero = function (i) {
219 | SS.statList[i].amount = 0;
220 | SS.statList[i].delta = 0;
221 | SS.evaluatePotential();
222 | }
223 |
224 | SS.addOne = function (i) {
225 | const statCap = DB[SS.statList[i].id][4];
226 | const overCapInc = DB[SS.statList[i].id][10];
227 | const lvUnitInc = DB[SS.statList[i].id][11];
228 | const minLv = DB[SS.statList[i].id][13];
229 |
230 | if (SS.statList[i].amount == statCap && overCapInc == 0)
231 | return;
232 |
233 | if (abs(SS.statList[i].amount+1) > statCap) {
234 | const nextValue = SS.statList[i].amount+overCapInc;
235 | if (SS.lvcap >= minLv+floor(((abs(nextValue)-statCap)/overCapInc-1)*lvUnitInc)) {
236 | SS.statList[i].amount = nextValue;
237 | SS.evaluatePotential();
238 | }
239 | }
240 | else {
241 | SS.statList[i].amount = min(SS.statList[i].amount+1, statCap);
242 | SS.evaluatePotential();
243 | }
244 | }
245 |
246 | SS.addMax = function (i) {
247 | const statCap = DB[SS.statList[i].id][4];
248 | const overCapInc = DB[SS.statList[i].id][10];
249 | const lvUnitInc = DB[SS.statList[i].id][11];
250 | const minLv = DB[SS.statList[i].id][13];
251 |
252 | let maxAmount = statCap+max(0, overCapInc*(floor((SS.lvcap-minLv)/lvUnitInc)+1));
253 | SS.statList[i].amount = maxAmount;
254 | SS.evaluatePotential();
255 | }
256 |
257 | SS.subOne = function (i) {
258 | const statCap = DB[SS.statList[i].id][4];
259 | const overCapInc = DB[SS.statList[i].id][10];
260 | const lvUnitInc = DB[SS.statList[i].id][11];
261 | const canBeNegative = DB[SS.statList[i].id][9];
262 | const lowestNegative = DB[SS.statList[i].id][12];
263 | const minLv = DB[SS.statList[i].id][13];
264 |
265 | if (SS.statList[i].amount == 0 && canBeNegative == 0) {
266 | return;
267 | }
268 |
269 | if (SS.statList[i].amount == -statCap && overCapInc == 0) {
270 | return;
271 | }
272 |
273 | if (lowestNegative != 0 && SS.statList[i].amount == lowestNegative) {
274 | return;
275 | }
276 |
277 | if (abs(SS.statList[i].amount-1) > statCap) {
278 | let nextValue = SS.statList[i].amount-overCapInc;
279 | if (SS.lvcap >= minLv+floor(((abs(nextValue)-statCap)/overCapInc-1)*lvUnitInc)) {
280 | SS.statList[i].amount = nextValue;
281 | SS.evaluatePotential();
282 | }
283 | }
284 | else {
285 | SS.statList[i].amount = min(SS.statList[i].amount-1, statCap);
286 | SS.evaluatePotential();
287 | }
288 | }
289 |
290 | SS.subMax = function (i) {
291 | const statCap = DB[SS.statList[i].id][4];
292 | const overCapInc = DB[SS.statList[i].id][10];
293 | const lvUnitInc = DB[SS.statList[i].id][11];
294 | const canBeNegative = DB[SS.statList[i].id][9];
295 | const lowestNegative = DB[SS.statList[i].id][12];
296 | const minLv = DB[SS.statList[i].id][13];
297 |
298 | if (SS.statList[i].amount >= 0 && canBeNegative == 0) {
299 | SS.statList[i].amount = 0;
300 | SS.statList[i].delta = 0;
301 | SS.evaluatePotential();
302 | return;
303 | }
304 |
305 | let maxAmount = statCap+max(0, overCapInc*(floor((SS.lvcap-minLv)/lvUnitInc)+1));
306 | let minAmount = (lowestNegative != 0)?lowestNegative:-maxAmount;
307 |
308 | SS.statList[i].amount = minAmount;
309 | SS.evaluatePotential();
310 | }
311 |
312 | SS.statDisabled = function (index) {
313 | return SS.disabledStats >> index & 1;
314 | }
315 |
316 | SS.disableOption = function (index) {
317 | if (!SS.stepList.length) {
318 | return;
319 | }
320 |
321 | for (let i = 0; i < MAX_FIELDS; i++) {
322 | if (SS.stepList[i].id == index) {
323 | return true;
324 | }
325 | }
326 | }
327 |
328 | SS.clearStatChoice = function (index) {
329 | SS.statList[index].amount = 0;
330 | SS.statList[index].delta = 0;
331 |
332 | SS.evaluatePotential();
333 | }
334 |
335 | SS.addStep = function () {
336 | if (!SS.finished) {
337 | SS.disabledStats = 0;
338 |
339 | let changed = 0;
340 | for (let i = 0; i < MAX_FIELDS; i++) {
341 | const refStat = (SS.stepList.length != 0)?SS.stepList[SS.stepList.length-1].stats:0;
342 |
343 | if (SS.statList[i].amount == 0) {
344 | if (SS.stepList.length != 0) {
345 | if (SS.statList[i].id != refStat[i].id) {
346 | SS.statList[i].id = "0";
347 | SS.statList[i].amount = 0;
348 | }
349 | }
350 | else {
351 | SS.statList[i].id = "0";
352 | SS.statList[i].amount = 0;
353 | }
354 | }
355 |
356 | if (SS.statList[i].id != 0) {
357 | SS.disabledStats += 2**i;
358 | }
359 |
360 | changed += ((refStat && refStat[i].amount == SS.statList[i].amount) || (!refStat && SS.statList[i].amount == 0))?0:1;
361 | }
362 |
363 | if (!changed) {
364 | return;
365 | }
366 |
367 | SS.evaluatePotential();
368 | SS.prevPot = SS.curPot;
369 | SS.stepList.push({stats: SS.statList, pot: SS.curPot});
370 |
371 | const oldStats = SS.stepList[SS.stepList.length-1].stats;
372 | SS.statList = [];
373 | for (let i = 0; i < MAX_FIELDS; i++) {
374 | SS.statList.push({id: oldStats[i].id, amount: oldStats[i].amount, shownAmount: oldStats[i].shownAmount, delta: 0});
375 | }
376 |
377 | if (SS.prevPot <= 0) {
378 | SS.finished = true;
379 | }
380 |
381 | SS.addShownStep();
382 | };
383 | }
384 |
385 | SS.addShownStep = function () {
386 | if (SS.stepList.length == 0) {
387 | return;
388 | }
389 | else if (SS.stepList.length == 1) {
390 | SS.shownSteps.push({repr: SS.formatStepLine(SS.stepList[0].stats), delta:SS.stepList[0].stats, pot: SS.stepList[0].pot, repeat: 1});
391 | return;
392 | }
393 | else {
394 | let delta = [];
395 | let isSameStep = 0;
396 | let addedStep = SS.stepList[SS.stepList.length-1];
397 | let lastStep = SS.stepList[SS.stepList.length-2];
398 | let lastShownStep = SS.shownSteps[SS.shownSteps.length-1];
399 |
400 | for (let j = 0; j < MAX_FIELDS; j++) {
401 | delta.push({id: "0", amount: 0});
402 | if (addedStep.stats[j].id != 0) {
403 | delta[j].id = addedStep.stats[j].id;
404 | delta[j].amount = addedStep.stats[j].amount-lastStep.stats[j].amount;
405 | delta[j].shownAmount = addedStep.stats[j].shownAmount-lastStep.stats[j].shownAmount;
406 | }
407 |
408 | if (delta[j].id == lastShownStep.delta[j].id && delta[j].amount == lastShownStep.delta[j].amount) {
409 | isSameStep += 1;
410 | }
411 | }
412 |
413 | if (isSameStep == MAX_FIELDS) {
414 | lastShownStep.repeat += 1;
415 | lastShownStep.pot = addedStep.pot;
416 | }
417 | else {
418 | SS.shownSteps.push({repr: SS.formatStepLine(delta), delta: delta, pot: addedStep.pot, repeat: 1});
419 | }
420 | return;
421 | }
422 | }
423 |
424 | SS.formatStepLine = function (delta) {
425 | let formatted = String();
426 | for (let i = 0; i < MAX_FIELDS; i++) {
427 | if (delta[i].id != 0 && delta[i].amount != 0) {
428 | formatted += `${DB[delta[i].id][0]} ${delta[i].shownAmount < 0?'':'+'}${delta[i].shownAmount}, `;
429 | }
430 | }
431 |
432 | return formatted.slice(0, formatted.length-2);
433 | }
434 |
435 | SS.repeatStep = function () {
436 | for (let i = 0; i < MAX_FIELDS; i++) {
437 | const statCap = DB[SS.statList[i].id][4];
438 | const overCapInc = DB[SS.statList[i].id][10];
439 | const lvUnitInc = DB[SS.statList[i].id][11];
440 | const lowestNegative = DB[SS.statList[i].id][12];
441 | const minLv = DB[SS.statList[i].id][13];
442 | const maxAmount = statCap+max(0, overCapInc*(floor((SS.lvcap-minLv)/lvUnitInc)+1));
443 | const minAmount = (lowestNegative != 0)?lowestNegative:-maxAmount;
444 |
445 | const lastValue = (SS.stepList.length > 0)?SS.stepList[SS.stepList.length-1].stats[i].amount:0;
446 | const beforeLast = (SS.stepList.length > 1)?SS.stepList[SS.stepList.length-2].stats[i].amount:0;
447 |
448 | SS.statList[i].amount = min(maxAmount, max(minAmount, SS.statList[i].amount+lastValue-beforeLast));
449 | }
450 | SS.addStep();
451 | SS.evaluatePotential();
452 | }
453 |
454 | SS.undoStep = function () {
455 | if (SS.finished) {
456 | SS.finished = false;
457 | }
458 |
459 | if (SS.stepList.length == 0) {
460 | return;
461 | }
462 | else if (SS.stepList.length == 1) {
463 | SS.stepList.pop();
464 | SS.disabledStats = 0;
465 | for (let i = 0; i < MAX_FIELDS; i++) {
466 | SS.statList[i].id = 0;
467 | SS.statList[i].amount = 0;
468 | SS.statList[i].delta = 0
469 | }
470 | SS.prevPot = SS.curPot = SS.startingPot;
471 | }
472 | else {
473 | SS.stepList.pop();
474 | let lastStep = SS.stepList[SS.stepList.length-1];
475 | SS.disabledStats = 0;
476 | for (let i = 0; i < MAX_FIELDS; i++) {
477 | SS.statList[i].id = lastStep.stats[i].id;
478 | SS.statList[i].amount = lastStep.stats[i].amount;
479 | SS.statList[i].delta = 0;
480 |
481 | if (SS.statList[i].id != 0) {
482 | SS.disabledStats += 2**i;
483 | }
484 | }
485 | SS.prevPot = SS.curPot = lastStep.pot;
486 | }
487 | SS.evaluatePotential();
488 |
489 | let lastShownStep = SS.shownSteps.length?SS.shownSteps[SS.shownSteps.length-1]:[];
490 | if (SS.shownSteps.length && lastShownStep.repeat > 1) {
491 | lastShownStep.pot = SS.stepList[SS.stepList.length-1].pot;
492 | lastShownStep.repeat -= 1;
493 | }
494 | else {
495 | SS.shownSteps.pop();
496 | }
497 | }
498 |
499 | $scope.$watch("SS.curPot", function () {
500 | if (SS.finished) {
501 | return;
502 | }
503 |
504 | if (SS.curPot < 0) {
505 | const sr = 160+230*SS.curPot/max(SS.prevPot, max(1, SS.recipePot));
506 | //$scope.SS.successRate = min(100, max(0, trunc(sr)));
507 | $scope.SS.successRate = Math.trunc(sr*100)/100;
508 | }
509 | else {
510 | $scope.SS.successRate = 100;
511 | }
512 | });
513 | });
--------------------------------------------------------------------------------