├── .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 |
27 | 28 |
ToramCafe English Search (Descontinued)
29 |
30 |
31 | 32 | 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 |
95 | 99 | 100 |
102 | 103 | 104 |
105 | Advanced Search [Redirects to Coryn.Club] 106 | 125 | 126 | 132 | 133 |
134 | 135 | 136 | 137 | 138 |
139 |
140 | 141 |
142 |
143 |
144 |
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 |
52 |
53 | 54 |
55 | Search by Scroll Skills 56 | 57 |
58 |
59 |
60 | 61 | 64 | 67 | 70 |
71 | 72 | 73 |
74 |
75 |
76 | 77 |
78 | 79 |
80 | Craft a Scroll 81 | 82 |
83 |
84 |
85 | 86 | 87 | 88 |
89 | 90 | 91 |
92 | 101 | 102 |
103 |
104 |
105 | 106 |
107 |
108 | 109 |
110 | Results 111 | 112 |
113 |
114 |
115 |
116 |
Oops, it seems that this combination isn't possible unless one of the 117 | skills is random ("Any" or "Random" options). Try another combination, leaving one of the fields 118 | as random.
119 |
120 |
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 | 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 |
31 | 32 |
Statting Simulator (Descontinued)
33 |
34 |
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 |
51 |
52 | Level 53 |
54 |
55 | 56 | 57 |
58 |
59 | 60 | 61 |
62 |
63 | 64 | 65 |
66 |
67 |
68 |

69 | Total XP required: 70 |

71 |
72 |
73 | 74 |
75 | 76 | 77 | 78 | 79 |
80 | 81 | 116 | 117 |
118 | Main Quest 119 |
120 |
121 | 122 | 123 |
124 | 125 |
126 | 127 | 128 |
129 | 130 |
131 | 132 |
133 | 134 |
135 | 136 |
137 | 138 |
139 |

140 |

141 |

142 |

OR

143 |

144 |
145 |
146 |
147 | 148 | 173 |
174 | 175 |
176 | pom-logo 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 |
51 |
52 | Base Stats 53 |
54 |
55 | 56 | 57 |
58 |
59 | 60 | 61 |
62 |
63 | 64 | 65 |
66 | 67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 |
75 |
76 | 77 | 78 |
79 |
80 |
81 | 82 |
83 | Equipament Stats 84 |
85 |
86 | 87 | 88 |
89 |
90 | 91 | 92 |
93 | 94 |
95 | 96 | 97 |
98 |
99 | 100 | 101 |
102 |
103 |
104 | 105 |
106 | Craft Type 107 | 108 | 120 |
121 | 122 |
123 | Skill Level 124 |
125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 |
133 |
134 |
135 | 136 |
137 | 138 |
139 | Crafting Stats 140 | 141 |
142 |
143 |
144 |
145 | 146 | 147 |
148 |
149 | / 150 | 151 |
152 |
153 | 154 |
155 |
156 |
157 | 158 | 159 |
160 |
161 | 162 | 163 |
164 | 165 |
166 | 167 | 168 |
169 |
170 | 171 | 172 |
173 |
174 | 175 |
176 | You can't craft this item because equipment difficulty > your difficulty. 177 |
178 |
179 |
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 |
53 |
54 | Level, Stat & Skill Points 55 |
56 |
57 | 58 | 59 |
60 |
61 | 62 | 63 |
64 | 65 |
66 | 67 | 68 |
69 |
70 | 71 | 72 |
73 |
74 |
75 |
76 | 77 |
78 | 79 |
80 | Emblems 81 | 82 |
83 |
84 |
85 |
86 |

Player Level

87 |
88 |
89 | 90 | 91 |
92 |
93 | 94 |

Results

95 |
96 |
97 | 98 | 99 |
100 |
101 | 102 | 103 |
104 | 105 |
106 | 107 | 108 |
109 |
110 | 111 | 112 |
113 |
114 | 115 |

Learning Skills

116 |
117 |
118 | 119 | 120 |
121 |
122 | 123 | 124 |
125 |
126 | 127 |

Consecutive Time Played

128 |
129 |
130 | 131 | 132 |
133 |
134 | 135 |

Other

136 |
137 |
138 | 139 | 140 |
141 |
142 | 143 | 144 |
145 |
146 | 147 |

Mission

148 |
149 |
150 | 151 |
152 |
153 | 167 |
168 |
169 | 170 |

Housing

171 |
172 |
173 | 174 |
175 |
176 | 177 |
178 |
179 |
180 |
181 |
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 += `
${skillList(scroll)}
\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 |
258 |
259 |
Final Chapter
260 |
Lv (%)
261 |
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 | }); --------------------------------------------------------------------------------