Merge branch 'master' of https://github.com/hppeng-wynn/hppeng-wynn.github.io into atree
This commit is contained in:
commit
df0ab92bef
18 changed files with 323 additions and 181 deletions
File diff suppressed because one or more lines are too long
|
@ -414,9 +414,6 @@
|
||||||
Active boosts
|
Active boosts
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="vanish-boost" onclick="update_boosts('vanish-boost')">
|
|
||||||
Vanish (+80%)
|
|
||||||
</button>
|
|
||||||
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="warscream-boost" onclick="update_boosts('warscream-boost')">
|
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="warscream-boost" onclick="update_boosts('warscream-boost')">
|
||||||
War Scream
|
War Scream
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -198,6 +198,60 @@ input.equipment-input:not(.is-invalid) {
|
||||||
max-width: 95%;
|
max-width: 95%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (orientation: landscape) and (max-width: 1199px) {
|
||||||
|
:root {
|
||||||
|
--scaled-fontsize: 1rem;
|
||||||
|
}
|
||||||
|
.scaled-font {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skp-tooltip {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spellcost-tooltip b {
|
||||||
|
font-size: .625rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scaled-item-icon {
|
||||||
|
width: 3.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scaled-item-icon img {
|
||||||
|
width: 2.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scaled-bckgrd {
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scaled-bckgrd img {
|
||||||
|
width: 2.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
font-size: .7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-display b {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1200px) and (max-width: 1400px) {
|
@media screen and (min-width: 1200px) and (max-width: 1400px) {
|
||||||
:root {
|
:root {
|
||||||
--scaled-fontsize: 1rem;
|
--scaled-fontsize: 1rem;
|
||||||
|
|
13
js/atree.js
13
js/atree.js
|
@ -1,3 +1,8 @@
|
||||||
|
/**
|
||||||
|
* This file defines computation graph nodes and display code relevant to the ability tree.
|
||||||
|
* TODO: possibly split it up into compute and render... but its a bit complicated :/
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ATreeNode spec:
|
ATreeNode spec:
|
||||||
|
|
||||||
|
@ -74,6 +79,7 @@ stat_bonus: {
|
||||||
stat_scaling: {
|
stat_scaling: {
|
||||||
"type": "stat_scaling",
|
"type": "stat_scaling",
|
||||||
"slider": bool,
|
"slider": bool,
|
||||||
|
positive: bool // True to keep stat above 0. False to ignore floor. Default: True for normal, False for scaling
|
||||||
"slider_name": Optional[str],
|
"slider_name": Optional[str],
|
||||||
"slider_step": Optional[float],
|
"slider_step": Optional[float],
|
||||||
round: Optional[bool] // Control floor behavior. True for stats and false for slider by default
|
round: Optional[bool] // Control floor behavior. True for stats and false for slider by default
|
||||||
|
@ -754,10 +760,13 @@ const atree_scaling = new (class extends ComputeNode {
|
||||||
continue;
|
continue;
|
||||||
case 'stat_scaling':
|
case 'stat_scaling':
|
||||||
let total = 0;
|
let total = 0;
|
||||||
const {round = true, slider = false, scaling = [0]} = effect;
|
const {slider = false, scaling = [0]} = effect;
|
||||||
|
let { positive = true, round = true } = effect;
|
||||||
if (slider) {
|
if (slider) {
|
||||||
const slider_val = slider_map.get(effect.slider_name).slider.value;
|
const slider_val = slider_map.get(effect.slider_name).slider.value;
|
||||||
total = parseInt(slider_val) * scaling[0];
|
total = parseInt(slider_val) * scaling[0];
|
||||||
|
round = false;
|
||||||
|
positive = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: type: prop?
|
// TODO: type: prop?
|
||||||
|
@ -768,7 +777,7 @@ const atree_scaling = new (class extends ComputeNode {
|
||||||
|
|
||||||
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
|
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
|
||||||
if (round) { total = Math.floor(round_near(total)); }
|
if (round) { total = Math.floor(round_near(total)); }
|
||||||
if (total < 0) { total = 0; } // Normal stat scaling will not go negative.
|
if (positive && total < 0) { total = 0; } // Normal stat scaling will not go negative.
|
||||||
if ('max' in effect && total > effect.max) { total = effect.max; }
|
if ('max' in effect && total > effect.max) { total = effect.max; }
|
||||||
if (Array.isArray(effect.output)) {
|
if (Array.isArray(effect.output)) {
|
||||||
for (const output of effect.output) {
|
for (const output of effect.output) {
|
||||||
|
|
|
@ -5242,7 +5242,9 @@ const atrees = {
|
||||||
"Teleport"
|
"Teleport"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [
|
||||||
|
"Wisdom"
|
||||||
|
],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 6,
|
"row": 6,
|
||||||
|
@ -5387,20 +5389,6 @@ const atrees = {
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "add_spell_prop",
|
|
||||||
"base_spell": 3,
|
|
||||||
"target_part": "Lightning Damage",
|
|
||||||
"behavior": "modify",
|
|
||||||
"multipliers": [
|
|
||||||
30,
|
|
||||||
90,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -5608,7 +5596,11 @@ const atrees = {
|
||||||
"Burning Sigil"
|
"Burning Sigil"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [
|
||||||
|
"Sunshower",
|
||||||
|
"Larger Heal",
|
||||||
|
"Orphion's Pulse"
|
||||||
|
],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 15,
|
"row": 15,
|
||||||
|
@ -7675,6 +7667,17 @@ const atrees = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raw_stat",
|
||||||
|
"toggle": "Activate Backstab",
|
||||||
|
"bonuses": [
|
||||||
|
{
|
||||||
|
"type": "stat",
|
||||||
|
"name": "damMult.Backstab:3.Backstab Damage",
|
||||||
|
"value": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because one or more lines are too long
29
js/build.js
29
js/build.js
|
@ -1,4 +1,9 @@
|
||||||
|
/**
|
||||||
|
* This file defines a class representing the player Build.
|
||||||
|
*
|
||||||
|
* Keeps track of equipment list, equip order, skillpoint assignment (initial),
|
||||||
|
* Aggregates item stats into a statMap to be used in damage calculation.
|
||||||
|
*/
|
||||||
|
|
||||||
const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.0], ["sword", 1.10]]);
|
const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.0], ["sword", 1.10]]);
|
||||||
|
|
||||||
|
@ -10,15 +15,9 @@ class Build{
|
||||||
/**
|
/**
|
||||||
* @description Construct a build.
|
* @description Construct a build.
|
||||||
* @param {Number} level : Level of the player.
|
* @param {Number} level : Level of the player.
|
||||||
* @param {String[]} equipment : List of equipment names that make up the build.
|
* @param {String[]} items: List of equipment names that make up the build.
|
||||||
* In order: boots, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon.
|
* In order: Helmet, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Tomes [x7].
|
||||||
* @param {Number[]} powders : Powder application. List of lists of integers (powder IDs).
|
* @param {Item} weapon: Weapon that this build is using.
|
||||||
* In order: boots, Chestplate, Leggings, Boots, Weapon.
|
|
||||||
* @param {Object[]} inputerrors : List of instances of error-like classes.
|
|
||||||
*
|
|
||||||
* @param {Object[]} tomes: List of tomes.
|
|
||||||
* In order: 2x Weapon Mastery Tome, 4x Armor Mastery Tome, 1x Guild Tome.
|
|
||||||
* 2x Slaying Mastery Tome, 2x Dungeoneering Mastery Tome, 2x Gathering Mastery Tome are in game, but do not have "useful" stats (those that affect damage calculations or building)
|
|
||||||
*/
|
*/
|
||||||
constructor(level, items, weapon){
|
constructor(level, items, weapon){
|
||||||
|
|
||||||
|
@ -39,11 +38,16 @@ class Build{
|
||||||
this.equipment = items;
|
this.equipment = items;
|
||||||
this.weapon = weapon;
|
this.weapon = weapon;
|
||||||
this.items = this.equipment.concat([this.weapon]);
|
this.items = this.equipment.concat([this.weapon]);
|
||||||
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
|
||||||
|
|
||||||
// calc skillpoints requires statmaps only
|
// calc skillpoints requires statmaps only
|
||||||
let result = calculate_skillpoints(this.equipment.map((x) => x.statMap), this.weapon.statMap);
|
let result = calculate_skillpoints(this.equipment.map((x) => x.statMap), this.weapon.statMap);
|
||||||
this.equip_order = result[0];
|
this.equip_order = result[0].slice();
|
||||||
|
for (let i = 0; i < this.equip_order.length; i++) {
|
||||||
|
if (this.equip_order[i].get("category") === "tome" || this.equip_order[i].get("fixID") === true) {
|
||||||
|
this.equip_order.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
// How many skillpoints the player had to assign (5 number)
|
// How many skillpoints the player had to assign (5 number)
|
||||||
this.base_skillpoints = result[1];
|
this.base_skillpoints = result[1];
|
||||||
// How many skillpoints the build ended up with (5 number)
|
// How many skillpoints the build ended up with (5 number)
|
||||||
|
@ -61,7 +65,6 @@ class Build{
|
||||||
return [this.equipment,this.weapon].flat();
|
return [this.equipment,this.weapon].flat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get all stats for this build. Stores in this.statMap.
|
/* Get all stats for this build. Stores in this.statMap.
|
||||||
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/**
|
||||||
|
* File containing utility functions that are useful for the builder page.
|
||||||
|
*/
|
||||||
|
|
||||||
/*Turns the input amount of skill points into a float precision percentage.
|
/*Turns the input amount of skill points into a float precision percentage.
|
||||||
* @param skp - the integer skillpoint count to be converted
|
* @param skp - the integer skillpoint count to be converted
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/**
|
||||||
|
* File containing utility functions relevant to the builder page, as well as the setup code (at the very bottom).
|
||||||
|
*/
|
||||||
|
|
||||||
function populateBuildList() {
|
function populateBuildList() {
|
||||||
const buildList = document.getElementById("build-choice");
|
const buildList = document.getElementById("build-choice");
|
||||||
|
@ -60,6 +63,9 @@ function resetFields(){
|
||||||
for (const i of equipment_inputs) {
|
for (const i of equipment_inputs) {
|
||||||
setValue(i, "");
|
setValue(i, "");
|
||||||
}
|
}
|
||||||
|
for (const i of tomeInputs) {
|
||||||
|
setValue(i, "");
|
||||||
|
}
|
||||||
setValue("str-skp", "0");
|
setValue("str-skp", "0");
|
||||||
setValue("dex-skp", "0");
|
setValue("dex-skp", "0");
|
||||||
setValue("int-skp", "0");
|
setValue("int-skp", "0");
|
||||||
|
@ -231,8 +237,9 @@ function init_autocomplete() {
|
||||||
for (const eq of tome_keys) {
|
for (const eq of tome_keys) {
|
||||||
// build dropdown
|
// build dropdown
|
||||||
let tome_arr = [];
|
let tome_arr = [];
|
||||||
for (const tome of tomeLists.get(eq.replace(/[0-9]/g, ''))) {
|
let tome_aliases = new Map();
|
||||||
let tome_obj = tomeMap.get(tome);
|
for (const tome_name of tomeLists.get(eq.replace(/[0-9]/g, ''))) {
|
||||||
|
let tome_obj = tomeMap.get(tome_name);
|
||||||
if (tome_obj["restrict"] && tome_obj["restrict"] === "DEPRECATED") {
|
if (tome_obj["restrict"] && tome_obj["restrict"] === "DEPRECATED") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -240,8 +247,10 @@ function init_autocomplete() {
|
||||||
if (tome_obj["name"].includes('No ' + eq.charAt(0).toUpperCase())) {
|
if (tome_obj["name"].includes('No ' + eq.charAt(0).toUpperCase())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let tome_name = tome;
|
let tome_alias = tome_obj['alias'];
|
||||||
tome_arr.push(tome_name);
|
tome_arr.push(tome_name);
|
||||||
|
tome_arr.push(tome_alias);
|
||||||
|
tome_aliases.set(tome_alias, tome_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create dropdown
|
// create dropdown
|
||||||
|
@ -276,14 +285,18 @@ function init_autocomplete() {
|
||||||
class: "scaled-font search-item",
|
class: "scaled-font search-item",
|
||||||
selected: "dark-5",
|
selected: "dark-5",
|
||||||
element: (tome, data) => {
|
element: (tome, data) => {
|
||||||
tome.classList.add(tomeMap.get(data.value).tier);
|
let val = data.value;
|
||||||
|
if (tome_aliases.has(val)) { val = tome_aliases.get(val); }
|
||||||
|
tome.classList.add(tomeMap.get(val).tier);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
input: {
|
input: {
|
||||||
selection: (event) => {
|
selection: (event) => {
|
||||||
if (event.detail.selection.value) {
|
if (event.detail.selection.value) {
|
||||||
event.target.value = event.detail.selection.value;
|
let val = event.detail.selection.value;
|
||||||
|
if (tome_aliases.has(val)) { val = tome_aliases.get(val); }
|
||||||
|
event.target.value = val;
|
||||||
}
|
}
|
||||||
event.target.dispatchEvent(new Event('change'));
|
event.target.dispatchEvent(new Event('change'));
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/**
|
||||||
|
* File containing compute graph structure of the builder page.
|
||||||
|
*/
|
||||||
|
|
||||||
let armor_powder_node = new (class extends ComputeNode {
|
let armor_powder_node = new (class extends ComputeNode {
|
||||||
constructor() { super('builder-armor-powder-input'); }
|
constructor() { super('builder-armor-powder-input'); }
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,6 @@ let player_craft;
|
||||||
|
|
||||||
|
|
||||||
function init_crafter() {
|
function init_crafter() {
|
||||||
//no ing
|
|
||||||
|
|
||||||
console.log("all ingredients");
|
|
||||||
console.log(ingMap);
|
|
||||||
console.log("all recipes");
|
|
||||||
console.log(recipeMap);
|
|
||||||
/*console.log(ingList);
|
|
||||||
console.log(recipeList);
|
|
||||||
console.log(ingIDMap);
|
|
||||||
console.log(recipeIDMap);*/
|
|
||||||
try {
|
try {
|
||||||
document.getElementById("recipe-choice").addEventListener("change", (event) => {
|
document.getElementById("recipe-choice").addEventListener("change", (event) => {
|
||||||
updateMaterials();
|
updateMaterials();
|
||||||
|
@ -56,17 +46,16 @@ function init_crafter() {
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 1; i < 4; ++i) {
|
for (let i = 1; i < 4; ++i) {
|
||||||
document.getElementById("mat-1-"+i).setAttribute("onclick", document.getElementById("mat-1-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
|
document.getElementById("mat-1-"+i).addEventListener("click", (e) => calculateCraftSchedule());
|
||||||
document.getElementById("mat-2-"+i).setAttribute("onclick", document.getElementById("mat-2-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
|
document.getElementById("mat-2-"+i).addEventListener("click", (e) => calculateCraftSchedule());
|
||||||
}
|
}
|
||||||
for (let i = 1; i < 7; ++i) {
|
for (let i = 1; i < 7; ++i) {
|
||||||
document.getElementById("ing-choice-" + i ).setAttribute("oninput", "calculateCraftSchedule();");
|
document.getElementById("ing-choice-" + i ).addEventListener("oninput", (e) => calculateCraftSchedule());
|
||||||
}
|
}
|
||||||
for (const str of ["slow", "normal", "fast"]) {
|
for (const str of ["slow", "normal", "fast"]) {
|
||||||
document.getElementById(str + "-atk-button").setAttribute("onclick", document.getElementById(str + "-atk-button").getAttribute("onclick") + "; calculateCraftSchedule();");
|
document.getElementById(str + "-atk-button").addEventListener("onclick", (e) => calculateCraftSchedule());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
populateFields();
|
populateFields();
|
||||||
decodeCraft(ing_url_tag);
|
decodeCraft(ing_url_tag);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -259,12 +248,10 @@ function populateFields() {
|
||||||
ing_list.appendChild(el);
|
ing_list.appendChild(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Copies the CR Hash (CR-blahblahblah)
|
* Copies the CR Hash (CR-blahblahblah)
|
||||||
*/
|
*/
|
||||||
function copyRecipeHash() {
|
function copyRecipeHash() {
|
||||||
if (player_craft) {
|
if (player_craft) {
|
||||||
copyTextToClipboard("CR-"+location.hash.slice(1));
|
copyTextToClipboard("CR-"+location.hash.slice(1));
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["vanish", 0.80], ["warscream", 0.00], ["ragnarokkr", 0.30], ["fortitude", 0.60] ]);
|
/**
|
||||||
|
* File implementing core damage calculation logic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["warscream", 0.00], ["ragnarokkr", 0.30], ["fortitude", 0.60] ]);
|
||||||
|
|
||||||
function get_base_dps(item) {
|
function get_base_dps(item) {
|
||||||
const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))];
|
const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))];
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/**
|
||||||
|
* File containing generic display code, ex. for displaying items and spell damage.
|
||||||
|
* TODO: split this file into separate parts for each "component".
|
||||||
|
*/
|
||||||
|
|
||||||
const itemBGPositions = {"bow": "0 0", "spear": "9.090909090909088% 0", "wand": "18.181818181818183% 0", "dagger": "27.27272727272727% 0", "relik": "36.36363636363637% 0",
|
const itemBGPositions = {"bow": "0 0", "spear": "9.090909090909088% 0", "wand": "18.181818181818183% 0", "dagger": "27.27272727272727% 0", "relik": "36.36363636363637% 0",
|
||||||
"helmet": "45.45454545454546% 0", "chestplate": "54.54545454545454% 0", "leggings": "63.63636363636363% 0", "boots": "72.72727272727272% 0",
|
"helmet": "45.45454545454546% 0", "chestplate": "54.54545454545454% 0", "leggings": "63.63636363636363% 0", "boots": "72.72727272727272% 0",
|
||||||
"ring": "81.81818181818181% 0", "bracelet": "90.90909090909092% 0", "necklace": "100% 0",
|
"ring": "81.81818181818181% 0", "bracelet": "90.90909090909092% 0", "necklace": "100% 0",
|
||||||
|
@ -388,46 +393,45 @@ function displayExpandedItem(item, parent_id){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Show powder specials ;-;
|
//Show powder specials ;-;
|
||||||
let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots"];//, "ring", "bracelet", "necklace"];
|
let powder_specials_check = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots"];
|
||||||
if(nonConsumables.includes(item.get("type"))) {
|
if(powder_specials_check.includes(item.get("type"))) {
|
||||||
let powder_special = document.createElement("div");
|
let powder_special = make_elem("div", ['col']);
|
||||||
powder_special.classList.add("col");
|
|
||||||
let powders = item.get("powders");
|
let powders = item.get("powders");
|
||||||
let element = "";
|
let element;
|
||||||
let power = 0;
|
let power_index;
|
||||||
for (let i = 0; i < powders.length; i++) {
|
for (let i = 0; i < powders.length; i++) {
|
||||||
let firstPowderType = skp_elements[Math.floor(powders[i]/6)];
|
const firstPowderType = skp_elements[Math.floor(powders[i]/6)];
|
||||||
if (element !== "") break;
|
const powder1_power = powders[i] % 6;
|
||||||
else if (powders[i]%6 > 2) { //t4+
|
if (powder1_power > 2) { //t4+
|
||||||
for (let j = i+1; j < powders.length; j++) {
|
for (let j = i+1; j < powders.length; j++) {
|
||||||
let currentPowderType = skp_elements[Math.floor(powders[j]/6)]
|
const currentPowderType = skp_elements[Math.floor(powders[j]/6)]
|
||||||
if (powders[j] % 6 > 2 && firstPowderType === currentPowderType) {
|
const powder2_power = powders[j] % 6;
|
||||||
|
if (powder2_power > 2 && firstPowderType === currentPowderType) {
|
||||||
element = currentPowderType;
|
element = currentPowderType;
|
||||||
power = Math.round(((powders[i] % 6 + powders[j] % 6 + 2) / 2 - 4) * 2);
|
power_index = powder1_power + powder2_power - 6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element !== "") {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
|
if (element) {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
|
||||||
let powderSpecial = powderSpecialStats[ skp_elements.indexOf(element)];
|
const powderSpecial = powderSpecialStats[skp_elements.indexOf(element)];
|
||||||
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
const specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
||||||
let specialTitle = document.createElement("span");
|
const specialTitle = make_elem("span", [damageClasses[skp_elements.indexOf(element) + 1]]);
|
||||||
let specialEffects = document.createElement("span");
|
const specialEffects = document.createElement("span");
|
||||||
addClasses(specialTitle, [damageClasses[skp_elements.indexOf(element) + 1]]);
|
|
||||||
let effects;
|
let effects;
|
||||||
if (item.get("category") === "weapon") {//weapon
|
if (item.get("category") === "weapon") {//weapon
|
||||||
effects = powderSpecial["weaponSpecialEffects"];
|
effects = powderSpecial["weaponSpecialEffects"];
|
||||||
specialTitle.textContent = powderSpecial["weaponSpecialName"];
|
specialTitle.textContent = powderSpecial["weaponSpecialName"];
|
||||||
}else if (item.get("category") === "armor") {//armor
|
} else if (item.get("category") === "armor") {//armor
|
||||||
effects = powderSpecial["armorSpecialEffects"];
|
effects = powderSpecial["armorSpecialEffects"];
|
||||||
specialTitle.textContent += powderSpecial["armorSpecialName"] + ": ";
|
specialTitle.textContent += powderSpecial["armorSpecialName"] + ": ";
|
||||||
}
|
}
|
||||||
for (const [key,value] of effects.entries()) {
|
for (const [key,value] of effects.entries()) {
|
||||||
if (key !== "Description") {
|
if (key !== "Description") {
|
||||||
let effect = document.createElement("p");
|
let effect = make_elem("p", ["m-0"], {
|
||||||
effect.classList.add("m-0");
|
textContent: key + ": " + value[power_index] + specialSuffixes.get(key)
|
||||||
effect.textContent = key + ": " + value[power] + specialSuffixes.get(key);
|
});
|
||||||
if(key === "Damage"){
|
if(key === "Damage"){
|
||||||
effect.textContent += elementIcons[skp_elements.indexOf(element)];
|
effect.textContent += elementIcons[skp_elements.indexOf(element)];
|
||||||
}
|
}
|
||||||
|
@ -435,20 +439,19 @@ function displayExpandedItem(item, parent_id){
|
||||||
effect.textContent += " / Mana Used";
|
effect.textContent += " / Mana Used";
|
||||||
}
|
}
|
||||||
specialEffects.appendChild(effect);
|
specialEffects.appendChild(effect);
|
||||||
}else{
|
} else {
|
||||||
specialTitle.textContent += "[ " + effects.get("Description") + " ]";
|
specialTitle.textContent += "[ " + effects.get("Description") + " ]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
powder_special.appendChild(specialTitle);
|
powder_special.append(specialTitle, specialEffects);
|
||||||
powder_special.appendChild(specialEffects);
|
|
||||||
parent_div.appendChild(powder_special);
|
parent_div.appendChild(powder_special);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots", "ring", "bracelet", "necklace"];
|
||||||
if(item.get("tier") && item.get("tier") === "Crafted") {
|
if(item.get("tier") && item.get("tier") === "Crafted") {
|
||||||
let dura_elem = document.createElement("div");
|
let dura_elem = make_elem("div", ["col"]);
|
||||||
dura_elem.classList.add("col");
|
let dura;
|
||||||
let dura = [];
|
|
||||||
let suffix = "";
|
let suffix = "";
|
||||||
if(nonConsumables.includes(item.get("type"))) {
|
if(nonConsumables.includes(item.get("type"))) {
|
||||||
dura = item.get("durability");
|
dura = item.get("durability");
|
||||||
|
@ -457,9 +460,9 @@ function displayExpandedItem(item, parent_id){
|
||||||
dura = item.get("duration");
|
dura = item.get("duration");
|
||||||
dura_elem.textContent = "Duration: "
|
dura_elem.textContent = "Duration: "
|
||||||
suffix = " sec."
|
suffix = " sec."
|
||||||
let charges = document.createElement("b");
|
parent_div.appendChild(make_elem('b', [], {
|
||||||
charges.textContent = "Charges: " + item.get("charges");
|
textContent: "Charges: " + item.get("charges")
|
||||||
parent_div.appendChild(charges);
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(dura) === "string") {
|
if (typeof(dura) === "string") {
|
||||||
|
@ -472,9 +475,7 @@ function displayExpandedItem(item, parent_id){
|
||||||
}
|
}
|
||||||
//Show item tier
|
//Show item tier
|
||||||
if (item.get("tier") && item.get("tier") !== " ") {
|
if (item.get("tier") && item.get("tier") !== " ") {
|
||||||
let item_desc_elem = document.createElement("div");
|
let item_desc_elem = make_elem("div", ["col", item.get("tier")]);
|
||||||
item_desc_elem.classList.add("col");
|
|
||||||
item_desc_elem.classList.add(item.get("tier"));
|
|
||||||
if (tome_types.includes(item.get("type"))) {
|
if (tome_types.includes(item.get("type"))) {
|
||||||
tome_type_map = new Map([["weaponTome", "Weapon Tome"],["armorTome", "Armor Tome"],["guildTome", "Guild Tome"]]);
|
tome_type_map = new Map([["weaponTome", "Weapon Tome"],["armorTome", "Armor Tome"],["guildTome", "Guild Tome"]]);
|
||||||
item_desc_elem.textContent = item.get("tier")+" "+tome_type_map.get(item.get("type"));
|
item_desc_elem.textContent = item.get("tier")+" "+tome_type_map.get(item.get("type"));
|
||||||
|
@ -486,20 +487,19 @@ function displayExpandedItem(item, parent_id){
|
||||||
|
|
||||||
//Show item hash if applicable
|
//Show item hash if applicable
|
||||||
if (item.get("crafted") || item.get("custom")) {
|
if (item.get("crafted") || item.get("custom")) {
|
||||||
let item_desc_elem = document.createElement("p");
|
parent_div.append(make_elem('p', ['itemp'], {
|
||||||
item_desc_elem.classList.add('itemp');
|
style: {
|
||||||
item_desc_elem.style.maxWidth = "100%";
|
maxWidth: '100%',
|
||||||
item_desc_elem.style.wordWrap = "break-word";
|
wordWrap: 'break-word',
|
||||||
item_desc_elem.style.wordBreak = "break-word";
|
wordBreak: 'break-word'
|
||||||
item_desc_elem.textContent = item.get("hash");
|
},
|
||||||
parent_div.append(item_desc_elem);
|
textContent: item.get('hash')
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.get("category") === "weapon") {
|
if (item.get("category") === "weapon") {
|
||||||
let total_damages = item.get("basedps");
|
let total_damages = item.get("basedps");
|
||||||
let base_dps_elem = document.createElement("p");
|
let base_dps_elem = make_elem("p", ["left", "itemp"]);
|
||||||
base_dps_elem.classList.add("left");
|
|
||||||
base_dps_elem.classList.add("itemp");
|
|
||||||
if (item.get("tier") === "Crafted") {
|
if (item.get("tier") === "Crafted") {
|
||||||
let base_dps_min = total_damages[0];
|
let base_dps_min = total_damages[0];
|
||||||
let base_dps_max = total_damages[1];
|
let base_dps_max = total_damages[1];
|
||||||
|
@ -509,8 +509,7 @@ function displayExpandedItem(item, parent_id){
|
||||||
else {
|
else {
|
||||||
base_dps_elem.textContent = "Base DPS: "+(total_damages);
|
base_dps_elem.textContent = "Base DPS: "+(total_damages);
|
||||||
}
|
}
|
||||||
parent_div.appendChild(document.createElement("p"));
|
parent_div.append(make_elem("p"), base_dps_elem);
|
||||||
parent_div.appendChild(base_dps_elem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,8 +1267,8 @@ function displayPowderSpecials(parent_elem, powderSpecials, stats, weapon, overa
|
||||||
//iterate through the special and display its effects.
|
//iterate through the special and display its effects.
|
||||||
let powder_special = make_elem("p", ["pt-3"]);
|
let powder_special = make_elem("p", ["pt-3"]);
|
||||||
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
||||||
let specialTitle = document.createElement("p");
|
let specialTitle = make_elem("p");
|
||||||
let specialEffects = document.createElement("p");
|
let specialEffects = make_elem("p");
|
||||||
specialTitle.classList.add(damageClasses[powderSpecialStats.indexOf(special[0]) + 1]);
|
specialTitle.classList.add(damageClasses[powderSpecialStats.indexOf(special[0]) + 1]);
|
||||||
let effects = special[0]["weaponSpecialEffects"];
|
let effects = special[0]["weaponSpecialEffects"];
|
||||||
let power = special[1];
|
let power = special[1];
|
||||||
|
|
|
@ -197,7 +197,7 @@ function init_ing_maps() {
|
||||||
posMods: {"left": 0, "right": 0, "above": 0, "under": 0, "touching": 0, "notTouching": 0}
|
posMods: {"left": 0, "right": 0, "above": 0, "under": 0, "touching": 0, "notTouching": 0}
|
||||||
};
|
};
|
||||||
ing.id = 4001 + ing.pid;
|
ing.id = 4001 + ing.pid;
|
||||||
ing.diplayName = ing.name;
|
ing.displayName = ing.name;
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 0:
|
case 0:
|
||||||
ing.itemIDs["strReq"] = powderIng["skpReq"];
|
ing.itemIDs["strReq"] = powderIng["skpReq"];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const TOME_DB_VERSION = 3;
|
const TOME_DB_VERSION = 4;
|
||||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||||
|
|
||||||
let tdb;
|
let tdb;
|
||||||
|
|
|
@ -187,8 +187,17 @@ function calculate_skillpoints(equipment, weapon) {
|
||||||
permute_check(idx+1, skillpoints_applied, skillpoints, activeSetCounts, has_skillpoint, total_applied, order.concat(permutation.map(x => x.item)));
|
permute_check(idx+1, skillpoints_applied, skillpoints, activeSetCounts, has_skillpoint, total_applied, order.concat(permutation.map(x => x.item)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// skip root.
|
if (sccs.length === 1) {
|
||||||
permute_check(1, best_skillpoints, final_skillpoints, best_activeSetCounts, allFalse.slice(), 0, []);
|
// Only crafteds. Just do end check (check req first, then apply sp after)
|
||||||
|
const total = check_end(best_skillpoints, final_skillpoints, best_activeSetCounts, allFalse.slice());
|
||||||
|
final_skillpoints = best_skillpoints;
|
||||||
|
best_total = total;
|
||||||
|
best_activeSetCounts = best_activeSetCounts;
|
||||||
|
best = [];
|
||||||
|
} else {
|
||||||
|
// skip root.
|
||||||
|
permute_check(1, best_skillpoints, final_skillpoints, best_activeSetCounts, allFalse.slice(), 0, []);
|
||||||
|
}
|
||||||
|
|
||||||
// add extra sp bonus
|
// add extra sp bonus
|
||||||
apply_skillpoints(final_skillpoints, weapon, best_activeSetCounts);
|
apply_skillpoints(final_skillpoints, weapon, best_activeSetCounts);
|
||||||
|
|
21
js/utils.js
21
js/utils.js
|
@ -612,16 +612,6 @@ function matchType(object, target) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add multiple classes to a html element
|
|
||||||
*/
|
|
||||||
function addClasses(elem, classes) {
|
|
||||||
for (let _class of classes) {
|
|
||||||
elem.classList.add(_class);
|
|
||||||
}
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A utility function that reloads the page forcefully.
|
/** A utility function that reloads the page forcefully.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -892,6 +882,17 @@ function make_elem(type, classlist = [], args = {}) {
|
||||||
const ret_elem = document.createElement(type);
|
const ret_elem = document.createElement(type);
|
||||||
ret_elem.classList.add(...classlist);
|
ret_elem.classList.add(...classlist);
|
||||||
for (const i in args) {
|
for (const i in args) {
|
||||||
|
if (i === 'style') {
|
||||||
|
const style_obj = args[i];
|
||||||
|
if (typeof style_obj === 'string' || style_obj instanceof String) {
|
||||||
|
ret_elem.style = style_obj;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const k in style_obj) {
|
||||||
|
ret_elem.style[k] = style_obj[k];
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ret_elem[i] = args[i];
|
ret_elem[i] = args[i];
|
||||||
}
|
}
|
||||||
return ret_elem;
|
return ret_elem;
|
||||||
|
|
168
tomes.json
168
tomes.json
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"tomes":
|
"tomes": [
|
||||||
[
|
|
||||||
{
|
{
|
||||||
"name": "Retaliating Tome of Armour Mastery I",
|
"name": "Retaliating Tome of Armour Mastery I",
|
||||||
"tier": "Fabled",
|
"tier": "Fabled",
|
||||||
|
@ -14,7 +13,8 @@
|
||||||
"ref": 6,
|
"ref": 6,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 0
|
"id": 0,
|
||||||
|
"alias": "Thorns I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retaliating Tome of Armour Mastery II",
|
"name": "Retaliating Tome of Armour Mastery II",
|
||||||
|
@ -28,7 +28,8 @@
|
||||||
"thorns": 8,
|
"thorns": 8,
|
||||||
"ref": 8,
|
"ref": 8,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 1
|
"id": 1,
|
||||||
|
"alias": "Thorns II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Destructive Tome of Armour Mastery I",
|
"name": "Destructive Tome of Armour Mastery I",
|
||||||
|
@ -43,7 +44,8 @@
|
||||||
"mdPct": 5,
|
"mdPct": 5,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 2
|
"id": 2,
|
||||||
|
"alias": "Melee I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Destructive Tome of Armour Mastery II",
|
"name": "Destructive Tome of Armour Mastery II",
|
||||||
|
@ -57,7 +59,8 @@
|
||||||
"thorns": 6,
|
"thorns": 6,
|
||||||
"reflection": 6,
|
"reflection": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 3
|
"id": 3,
|
||||||
|
"alias": "Melee II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Sorcerer's Tome of Armour Mastery I",
|
"name": "Sorcerer's Tome of Armour Mastery I",
|
||||||
|
@ -71,7 +74,8 @@
|
||||||
"sdPct": 5,
|
"sdPct": 5,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 4
|
"id": 4,
|
||||||
|
"alias": "Spell Damage I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Sorcerer's Tome of Armour Mastery II",
|
"name": "Sorcerer's Tome of Armour Mastery II",
|
||||||
|
@ -84,7 +88,8 @@
|
||||||
"defMobs": 5,
|
"defMobs": 5,
|
||||||
"sdPct": 6,
|
"sdPct": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 5
|
"id": 5,
|
||||||
|
"alias": "Spell Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Everlasting Tome of Armour Mastery I",
|
"name": "Everlasting Tome of Armour Mastery I",
|
||||||
|
@ -98,7 +103,8 @@
|
||||||
"hprRaw": 15,
|
"hprRaw": 15,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 6
|
"id": 6,
|
||||||
|
"alias": "Health Regen I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Everlasting Tome of Armour Mastery II",
|
"name": "Everlasting Tome of Armour Mastery II",
|
||||||
|
@ -111,7 +117,8 @@
|
||||||
"defMobs": 5,
|
"defMobs": 5,
|
||||||
"hprRaw": 60,
|
"hprRaw": 60,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 7
|
"id": 7,
|
||||||
|
"alias": "Health Regen II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Vampiric Tome of Armour Mastery I",
|
"name": "Vampiric Tome of Armour Mastery I",
|
||||||
|
@ -125,7 +132,8 @@
|
||||||
"ls": 25,
|
"ls": 25,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 8
|
"id": 8,
|
||||||
|
"alias": "Life Steal I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Vampiric Tome of Armour Mastery II",
|
"name": "Vampiric Tome of Armour Mastery II",
|
||||||
|
@ -138,7 +146,8 @@
|
||||||
"defMobs": 5,
|
"defMobs": 5,
|
||||||
"ls": 85,
|
"ls": 85,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 9
|
"id": 9,
|
||||||
|
"alias": "Life Steal II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Greedy Tome of Armour Mastery I",
|
"name": "Greedy Tome of Armour Mastery I",
|
||||||
|
@ -152,7 +161,8 @@
|
||||||
"lb": 5,
|
"lb": 5,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 10
|
"id": 10,
|
||||||
|
"alias": "Loot Bonus I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Greedy Tome of Armour Mastery II",
|
"name": "Greedy Tome of Armour Mastery II",
|
||||||
|
@ -165,7 +175,8 @@
|
||||||
"defMobs": 5,
|
"defMobs": 5,
|
||||||
"lb": 6,
|
"lb": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 11
|
"id": 11,
|
||||||
|
"alias": "Loot Bonus II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Weightless Tome of Armour Mastery I",
|
"name": "Weightless Tome of Armour Mastery I",
|
||||||
|
@ -179,7 +190,8 @@
|
||||||
"spd": 5,
|
"spd": 5,
|
||||||
"hpBonus": 120,
|
"hpBonus": 120,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 12
|
"id": 12,
|
||||||
|
"alias": "Walk Speed I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Weightless Tome of Armour Mastery II",
|
"name": "Weightless Tome of Armour Mastery II",
|
||||||
|
@ -192,7 +204,8 @@
|
||||||
"defMobs": 5,
|
"defMobs": 5,
|
||||||
"spd": 6,
|
"spd": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 13
|
"id": 13,
|
||||||
|
"alias": "Walk Speed II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Blooming Tome of Armour Mastery II",
|
"name": "Blooming Tome of Armour Mastery II",
|
||||||
|
@ -206,7 +219,8 @@
|
||||||
"eDefPct": 10,
|
"eDefPct": 10,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 14
|
"id": 14,
|
||||||
|
"alias": "Earth Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Pulsing Tome of Armour Mastery II",
|
"name": "Pulsing Tome of Armour Mastery II",
|
||||||
|
@ -220,7 +234,8 @@
|
||||||
"tDefPct": 10,
|
"tDefPct": 10,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 15
|
"id": 15,
|
||||||
|
"alias": "Thunder Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Oceanic Tome of Armour Mastery II",
|
"name": "Oceanic Tome of Armour Mastery II",
|
||||||
|
@ -234,7 +249,8 @@
|
||||||
"wDefPct": 10,
|
"wDefPct": 10,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 16
|
"id": 16,
|
||||||
|
"alias": "Water Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Courageous Tome of Armour Mastery II",
|
"name": "Courageous Tome of Armour Mastery II",
|
||||||
|
@ -248,7 +264,8 @@
|
||||||
"fDefPct": 10,
|
"fDefPct": 10,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 17
|
"id": 17,
|
||||||
|
"alias": "Fire Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Clouded Tome of Armour Mastery II",
|
"name": "Clouded Tome of Armour Mastery II",
|
||||||
|
@ -262,7 +279,8 @@
|
||||||
"aDefPct": 10,
|
"aDefPct": 10,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 18
|
"id": 18,
|
||||||
|
"alias": "Air Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Radiant Tome of Armour Mastery II",
|
"name": "Radiant Tome of Armour Mastery II",
|
||||||
|
@ -280,7 +298,8 @@
|
||||||
"aDefPct": 6,
|
"aDefPct": 6,
|
||||||
"hpBonus": 150,
|
"hpBonus": 150,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 19
|
"id": 19,
|
||||||
|
"alias": "Rainbow Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Tome of Weapon Mastery I",
|
"name": "Tome of Weapon Mastery I",
|
||||||
|
@ -292,7 +311,8 @@
|
||||||
"lvl": 60,
|
"lvl": 60,
|
||||||
"damMobs": 6,
|
"damMobs": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 20
|
"id": 20,
|
||||||
|
"alias": "Weapon Mastery I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Earthbound Tome of Weapon Mastery I",
|
"name": "Earthbound Tome of Weapon Mastery I",
|
||||||
|
@ -305,7 +325,8 @@
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"str": 3,
|
"str": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 21
|
"id": 21,
|
||||||
|
"alias": "Strength I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Earthbound Tome of Weapon Mastery II",
|
"name": "Earthbound Tome of Weapon Mastery II",
|
||||||
|
@ -318,7 +339,8 @@
|
||||||
"damMobs": 8,
|
"damMobs": 8,
|
||||||
"str": 3,
|
"str": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 22
|
"id": 22,
|
||||||
|
"alias": "Strength II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Nimble Tome of Weapon Mastery I",
|
"name": "Nimble Tome of Weapon Mastery I",
|
||||||
|
@ -331,7 +353,8 @@
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"dex": 3,
|
"dex": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 23
|
"id": 23,
|
||||||
|
"alias": "Dexterity I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Nimble Tome of Weapon Mastery II",
|
"name": "Nimble Tome of Weapon Mastery II",
|
||||||
|
@ -344,7 +367,8 @@
|
||||||
"damMobs": 8,
|
"damMobs": 8,
|
||||||
"dex": 3,
|
"dex": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 24
|
"id": 24,
|
||||||
|
"alias": "Dexterity II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mystical Tome of Weapon Mastery I",
|
"name": "Mystical Tome of Weapon Mastery I",
|
||||||
|
@ -357,7 +381,8 @@
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"int": 3,
|
"int": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 25
|
"id": 25,
|
||||||
|
"alias": "Intelligence I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mystical Tome of Weapon Mastery II",
|
"name": "Mystical Tome of Weapon Mastery II",
|
||||||
|
@ -370,7 +395,8 @@
|
||||||
"damMobs": 8,
|
"damMobs": 8,
|
||||||
"int": 3,
|
"int": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 26
|
"id": 26,
|
||||||
|
"alias": "Intelligence II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Warding Tome of Weapon Mastery I",
|
"name": "Warding Tome of Weapon Mastery I",
|
||||||
|
@ -383,7 +409,8 @@
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"def": 3,
|
"def": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 27
|
"id": 27,
|
||||||
|
"alias": "Defense I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Warding Tome of Weapon Mastery II",
|
"name": "Warding Tome of Weapon Mastery II",
|
||||||
|
@ -396,7 +423,8 @@
|
||||||
"damMobs": 8,
|
"damMobs": 8,
|
||||||
"def": 3,
|
"def": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 28
|
"id": 28,
|
||||||
|
"alias": "Defense II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Athletic Tome of Weapon Mastery I",
|
"name": "Athletic Tome of Weapon Mastery I",
|
||||||
|
@ -409,7 +437,8 @@
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"agi": 3,
|
"agi": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 29
|
"id": 29,
|
||||||
|
"alias": "Agility I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Athletic Tome of Weapon Mastery II",
|
"name": "Athletic Tome of Weapon Mastery II",
|
||||||
|
@ -422,7 +451,8 @@
|
||||||
"damMobs": 8,
|
"damMobs": 8,
|
||||||
"agi": 3,
|
"agi": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 30
|
"id": 30,
|
||||||
|
"alias": "Agility II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Cosmic Tome of Weapon Mastery I",
|
"name": "Cosmic Tome of Weapon Mastery I",
|
||||||
|
@ -439,7 +469,8 @@
|
||||||
"def": 1,
|
"def": 1,
|
||||||
"agi": 1,
|
"agi": 1,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 31
|
"id": 31,
|
||||||
|
"alias": "Rainbow Skillpoint I"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Cosmic Tome of Weapon Mastery II",
|
"name": "Cosmic Tome of Weapon Mastery II",
|
||||||
|
@ -456,7 +487,8 @@
|
||||||
"def": 1,
|
"def": 1,
|
||||||
"agi": 1,
|
"agi": 1,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 32
|
"id": 32,
|
||||||
|
"alias": "Rainbow Skillpoint II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Seismic Tome of Weapon Mastery II",
|
"name": "Seismic Tome of Weapon Mastery II",
|
||||||
|
@ -469,7 +501,8 @@
|
||||||
"damMobs": 12,
|
"damMobs": 12,
|
||||||
"eDamPct": 7,
|
"eDamPct": 7,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 33
|
"id": 33,
|
||||||
|
"alias": "Earth Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Voltaic Tome of Weapon Mastery II",
|
"name": "Voltaic Tome of Weapon Mastery II",
|
||||||
|
@ -482,7 +515,8 @@
|
||||||
"damMobs": 12,
|
"damMobs": 12,
|
||||||
"tDamPct": 7,
|
"tDamPct": 7,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 34
|
"id": 34,
|
||||||
|
"alias": "Thunder Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Abyssal Tome of Weapon Mastery II",
|
"name": "Abyssal Tome of Weapon Mastery II",
|
||||||
|
@ -495,7 +529,8 @@
|
||||||
"damMobs": 12,
|
"damMobs": 12,
|
||||||
"wDamPct": 7,
|
"wDamPct": 7,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 35
|
"id": 35,
|
||||||
|
"alias": "Water Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Infernal Tome of Weapon Mastery II",
|
"name": "Infernal Tome of Weapon Mastery II",
|
||||||
|
@ -508,7 +543,8 @@
|
||||||
"damMobs": 12,
|
"damMobs": 12,
|
||||||
"fDamPct": 7,
|
"fDamPct": 7,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 36
|
"id": 36,
|
||||||
|
"alias": "Fire Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Cyclonic Tome of Weapon Mastery II",
|
"name": "Cyclonic Tome of Weapon Mastery II",
|
||||||
|
@ -521,7 +557,8 @@
|
||||||
"damMobs": 12,
|
"damMobs": 12,
|
||||||
"aDamPct": 7,
|
"aDamPct": 7,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 37
|
"id": 37,
|
||||||
|
"alias": "Air Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Astral Tome of Weapon Mastery II",
|
"name": "Astral Tome of Weapon Mastery II",
|
||||||
|
@ -538,7 +575,8 @@
|
||||||
"fDamPct": 6,
|
"fDamPct": 6,
|
||||||
"aDamPct": 6,
|
"aDamPct": 6,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 38
|
"id": 38,
|
||||||
|
"alias": "Rainbow Damage II"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Brute's Tome of Allegiance",
|
"name": "Brute's Tome of Allegiance",
|
||||||
|
@ -551,7 +589,8 @@
|
||||||
"str": 3,
|
"str": 3,
|
||||||
"eDamPct": 2,
|
"eDamPct": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 39
|
"id": 39,
|
||||||
|
"alias": "Strength"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Sadist's Tome of Allegiance",
|
"name": "Sadist's Tome of Allegiance",
|
||||||
|
@ -564,7 +603,8 @@
|
||||||
"dex": 3,
|
"dex": 3,
|
||||||
"tDamPct": 2,
|
"tDamPct": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 40
|
"id": 40,
|
||||||
|
"alias": "Dexterity"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mastermind's Tome of Allegiance",
|
"name": "Mastermind's Tome of Allegiance",
|
||||||
|
@ -577,7 +617,8 @@
|
||||||
"int": 3,
|
"int": 3,
|
||||||
"wDamPct": 2,
|
"wDamPct": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 41
|
"id": 41,
|
||||||
|
"alias": "Intelligence"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Arsonist's Tome of Allegiance",
|
"name": "Arsonist's Tome of Allegiance",
|
||||||
|
@ -590,7 +631,8 @@
|
||||||
"def": 3,
|
"def": 3,
|
||||||
"fDamPct": 2,
|
"fDamPct": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 42
|
"id": 42,
|
||||||
|
"alias": "Defense"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Ghost's Tome of Allegiance",
|
"name": "Ghost's Tome of Allegiance",
|
||||||
|
@ -603,7 +645,8 @@
|
||||||
"agi": 3,
|
"agi": 3,
|
||||||
"aDamPct": 2,
|
"aDamPct": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 43
|
"id": 43,
|
||||||
|
"alias": "Agility"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Psychopath's Tome of Allegiance",
|
"name": "Psychopath's Tome of Allegiance",
|
||||||
|
@ -616,7 +659,8 @@
|
||||||
"str": 2,
|
"str": 2,
|
||||||
"dex": 2,
|
"dex": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 44
|
"id": 44,
|
||||||
|
"alias": "ET"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Loner's Tome of Allegiance",
|
"name": "Loner's Tome of Allegiance",
|
||||||
|
@ -629,7 +673,8 @@
|
||||||
"str": 2,
|
"str": 2,
|
||||||
"int": 2,
|
"int": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 45
|
"id": 45,
|
||||||
|
"alias": "EW"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Warlock's Tome of Allegiance",
|
"name": "Warlock's Tome of Allegiance",
|
||||||
|
@ -642,7 +687,8 @@
|
||||||
"dex": 2,
|
"dex": 2,
|
||||||
"int": 2,
|
"int": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 46
|
"id": 46,
|
||||||
|
"alias": "TW"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Destroyer's Tome of Allegiance",
|
"name": "Destroyer's Tome of Allegiance",
|
||||||
|
@ -655,7 +701,8 @@
|
||||||
"str": 2,
|
"str": 2,
|
||||||
"def": 2,
|
"def": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 47
|
"id": 47,
|
||||||
|
"alias": "EF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Devil's Tome of Allegiance",
|
"name": "Devil's Tome of Allegiance",
|
||||||
|
@ -668,7 +715,8 @@
|
||||||
"dex": 2,
|
"dex": 2,
|
||||||
"def": 2,
|
"def": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 48
|
"id": 48,
|
||||||
|
"alias": "TF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Alchemist's Tome of Allegiance",
|
"name": "Alchemist's Tome of Allegiance",
|
||||||
|
@ -681,7 +729,8 @@
|
||||||
"int": 2,
|
"int": 2,
|
||||||
"def": 2,
|
"def": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 49
|
"id": 49,
|
||||||
|
"alias": "WF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Barbarian's Tome of Allegiance",
|
"name": "Barbarian's Tome of Allegiance",
|
||||||
|
@ -694,7 +743,8 @@
|
||||||
"str": 2,
|
"str": 2,
|
||||||
"agi": 2,
|
"agi": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 50
|
"id": 50,
|
||||||
|
"alias": "EA"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Freelancer's Tome of Allegiance",
|
"name": "Freelancer's Tome of Allegiance",
|
||||||
|
@ -707,7 +757,8 @@
|
||||||
"dex": 2,
|
"dex": 2,
|
||||||
"agi": 2,
|
"agi": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 51
|
"id": 51,
|
||||||
|
"alias": "TA"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Sycophant's Tome of Allegiance",
|
"name": "Sycophant's Tome of Allegiance",
|
||||||
|
@ -720,7 +771,8 @@
|
||||||
"int": 2,
|
"int": 2,
|
||||||
"agi": 2,
|
"agi": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 52
|
"id": 52,
|
||||||
|
"alias": "WA"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Fanatic's Tome of Allegiance",
|
"name": "Fanatic's Tome of Allegiance",
|
||||||
|
@ -733,7 +785,8 @@
|
||||||
"def": 2,
|
"def": 2,
|
||||||
"agi": 2,
|
"agi": 2,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 53
|
"id": 53,
|
||||||
|
"alias": "FA"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Assimilator's Tome of Allegiance",
|
"name": "Assimilator's Tome of Allegiance",
|
||||||
|
@ -749,7 +802,8 @@
|
||||||
"def": 1,
|
"def": 1,
|
||||||
"agi": 1,
|
"agi": 1,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 54
|
"id": 54,
|
||||||
|
"alias": "Rainbow"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in a new issue