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
|
||||
</div>
|
||||
<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')">
|
||||
War Scream
|
||||
</button>
|
||||
|
|
|
@ -198,6 +198,60 @@ input.equipment-input:not(.is-invalid) {
|
|||
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) {
|
||||
:root {
|
||||
--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:
|
||||
|
||||
|
@ -74,6 +79,7 @@ stat_bonus: {
|
|||
stat_scaling: {
|
||||
"type": "stat_scaling",
|
||||
"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_step": Optional[float],
|
||||
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;
|
||||
case 'stat_scaling':
|
||||
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) {
|
||||
const slider_val = slider_map.get(effect.slider_name).slider.value;
|
||||
total = parseInt(slider_val) * scaling[0];
|
||||
round = false;
|
||||
positive = false;
|
||||
}
|
||||
else {
|
||||
// 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 (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 (Array.isArray(effect.output)) {
|
||||
for (const output of effect.output) {
|
||||
|
|
|
@ -5242,7 +5242,9 @@ const atrees = {
|
|||
"Teleport"
|
||||
],
|
||||
"dependencies": [],
|
||||
"blockers": [],
|
||||
"blockers": [
|
||||
"Wisdom"
|
||||
],
|
||||
"cost": 1,
|
||||
"display": {
|
||||
"row": 6,
|
||||
|
@ -5387,20 +5389,6 @@ const atrees = {
|
|||
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"
|
||||
],
|
||||
"dependencies": [],
|
||||
"blockers": [],
|
||||
"blockers": [
|
||||
"Sunshower",
|
||||
"Larger Heal",
|
||||
"Orphion's Pulse"
|
||||
],
|
||||
"cost": 2,
|
||||
"display": {
|
||||
"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]]);
|
||||
|
||||
|
@ -10,15 +15,9 @@ class Build{
|
|||
/**
|
||||
* @description Construct a build.
|
||||
* @param {Number} level : Level of the player.
|
||||
* @param {String[]} equipment : List of equipment names that make up the build.
|
||||
* In order: boots, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Weapon.
|
||||
* @param {Number[]} powders : Powder application. List of lists of integers (powder IDs).
|
||||
* In order: boots, Chestplate, Leggings, Boots, Weapon.
|
||||
* @param {Object[]} inputerrors : List of instances of error-like classes.
|
||||
*
|
||||
* @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)
|
||||
* @param {String[]} items: List of equipment names that make up the build.
|
||||
* In order: Helmet, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Tomes [x7].
|
||||
* @param {Item} weapon: Weapon that this build is using.
|
||||
*/
|
||||
constructor(level, items, weapon){
|
||||
|
||||
|
@ -39,11 +38,16 @@ class Build{
|
|||
this.equipment = items;
|
||||
this.weapon = weapon;
|
||||
this.items = this.equipment.concat([this.weapon]);
|
||||
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
||||
|
||||
// calc skillpoints requires statmaps only
|
||||
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)
|
||||
this.base_skillpoints = result[1];
|
||||
// How many skillpoints the build ended up with (5 number)
|
||||
|
@ -61,7 +65,6 @@ class Build{
|
|||
return [this.equipment,this.weapon].flat();
|
||||
}
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
* @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() {
|
||||
const buildList = document.getElementById("build-choice");
|
||||
|
@ -60,6 +63,9 @@ function resetFields(){
|
|||
for (const i of equipment_inputs) {
|
||||
setValue(i, "");
|
||||
}
|
||||
for (const i of tomeInputs) {
|
||||
setValue(i, "");
|
||||
}
|
||||
setValue("str-skp", "0");
|
||||
setValue("dex-skp", "0");
|
||||
setValue("int-skp", "0");
|
||||
|
@ -231,8 +237,9 @@ function init_autocomplete() {
|
|||
for (const eq of tome_keys) {
|
||||
// build dropdown
|
||||
let tome_arr = [];
|
||||
for (const tome of tomeLists.get(eq.replace(/[0-9]/g, ''))) {
|
||||
let tome_obj = tomeMap.get(tome);
|
||||
let tome_aliases = new Map();
|
||||
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") {
|
||||
continue;
|
||||
}
|
||||
|
@ -240,8 +247,10 @@ function init_autocomplete() {
|
|||
if (tome_obj["name"].includes('No ' + eq.charAt(0).toUpperCase())) {
|
||||
continue;
|
||||
}
|
||||
let tome_name = tome;
|
||||
let tome_alias = tome_obj['alias'];
|
||||
tome_arr.push(tome_name);
|
||||
tome_arr.push(tome_alias);
|
||||
tome_aliases.set(tome_alias, tome_name);
|
||||
}
|
||||
|
||||
// create dropdown
|
||||
|
@ -276,14 +285,18 @@ function init_autocomplete() {
|
|||
class: "scaled-font search-item",
|
||||
selected: "dark-5",
|
||||
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: {
|
||||
input: {
|
||||
selection: (event) => {
|
||||
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'));
|
||||
},
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* File containing compute graph structure of the builder page.
|
||||
*/
|
||||
|
||||
let armor_powder_node = new (class extends ComputeNode {
|
||||
constructor() { super('builder-armor-powder-input'); }
|
||||
|
||||
|
|
|
@ -31,16 +31,6 @@ let player_craft;
|
|||
|
||||
|
||||
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 {
|
||||
document.getElementById("recipe-choice").addEventListener("change", (event) => {
|
||||
updateMaterials();
|
||||
|
@ -56,17 +46,16 @@ function init_crafter() {
|
|||
});
|
||||
|
||||
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-2-"+i).setAttribute("onclick", document.getElementById("mat-2-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
|
||||
document.getElementById("mat-1-"+i).addEventListener("click", (e) => calculateCraftSchedule());
|
||||
document.getElementById("mat-2-"+i).addEventListener("click", (e) => calculateCraftSchedule());
|
||||
}
|
||||
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"]) {
|
||||
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();
|
||||
decodeCraft(ing_url_tag);
|
||||
} catch (error) {
|
||||
|
@ -259,12 +248,10 @@ function populateFields() {
|
|||
ing_list.appendChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
Copies the CR Hash (CR-blahblahblah)
|
||||
*/
|
||||
* Copies the CR Hash (CR-blahblahblah)
|
||||
*/
|
||||
function copyRecipeHash() {
|
||||
if (player_craft) {
|
||||
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) {
|
||||
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",
|
||||
"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",
|
||||
|
@ -388,46 +393,45 @@ function displayExpandedItem(item, parent_id){
|
|||
}
|
||||
}
|
||||
//Show powder specials ;-;
|
||||
let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots"];//, "ring", "bracelet", "necklace"];
|
||||
if(nonConsumables.includes(item.get("type"))) {
|
||||
let powder_special = document.createElement("div");
|
||||
powder_special.classList.add("col");
|
||||
let powder_specials_check = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots"];
|
||||
if(powder_specials_check.includes(item.get("type"))) {
|
||||
let powder_special = make_elem("div", ['col']);
|
||||
let powders = item.get("powders");
|
||||
let element = "";
|
||||
let power = 0;
|
||||
let element;
|
||||
let power_index;
|
||||
for (let i = 0; i < powders.length; i++) {
|
||||
let firstPowderType = skp_elements[Math.floor(powders[i]/6)];
|
||||
if (element !== "") break;
|
||||
else if (powders[i]%6 > 2) { //t4+
|
||||
const firstPowderType = skp_elements[Math.floor(powders[i]/6)];
|
||||
const powder1_power = powders[i] % 6;
|
||||
if (powder1_power > 2) { //t4+
|
||||
for (let j = i+1; j < powders.length; j++) {
|
||||
let currentPowderType = skp_elements[Math.floor(powders[j]/6)]
|
||||
if (powders[j] % 6 > 2 && firstPowderType === currentPowderType) {
|
||||
const currentPowderType = skp_elements[Math.floor(powders[j]/6)]
|
||||
const powder2_power = powders[j] % 6;
|
||||
if (powder2_power > 2 && firstPowderType === currentPowderType) {
|
||||
element = currentPowderType;
|
||||
power = Math.round(((powders[i] % 6 + powders[j] % 6 + 2) / 2 - 4) * 2);
|
||||
power_index = powder1_power + powder2_power - 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element !== "") {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
|
||||
let powderSpecial = powderSpecialStats[ skp_elements.indexOf(element)];
|
||||
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
||||
let specialTitle = document.createElement("span");
|
||||
let specialEffects = document.createElement("span");
|
||||
addClasses(specialTitle, [damageClasses[skp_elements.indexOf(element) + 1]]);
|
||||
if (element) {//powder special is "[e,t,w,f,a]+[0,1,2,3,4]"
|
||||
const powderSpecial = powderSpecialStats[skp_elements.indexOf(element)];
|
||||
const specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
||||
const specialTitle = make_elem("span", [damageClasses[skp_elements.indexOf(element) + 1]]);
|
||||
const specialEffects = document.createElement("span");
|
||||
let effects;
|
||||
if (item.get("category") === "weapon") {//weapon
|
||||
effects = powderSpecial["weaponSpecialEffects"];
|
||||
specialTitle.textContent = powderSpecial["weaponSpecialName"];
|
||||
}else if (item.get("category") === "armor") {//armor
|
||||
} else if (item.get("category") === "armor") {//armor
|
||||
effects = powderSpecial["armorSpecialEffects"];
|
||||
specialTitle.textContent += powderSpecial["armorSpecialName"] + ": ";
|
||||
}
|
||||
for (const [key,value] of effects.entries()) {
|
||||
if (key !== "Description") {
|
||||
let effect = document.createElement("p");
|
||||
effect.classList.add("m-0");
|
||||
effect.textContent = key + ": " + value[power] + specialSuffixes.get(key);
|
||||
let effect = make_elem("p", ["m-0"], {
|
||||
textContent: key + ": " + value[power_index] + specialSuffixes.get(key)
|
||||
});
|
||||
if(key === "Damage"){
|
||||
effect.textContent += elementIcons[skp_elements.indexOf(element)];
|
||||
}
|
||||
|
@ -435,20 +439,19 @@ function displayExpandedItem(item, parent_id){
|
|||
effect.textContent += " / Mana Used";
|
||||
}
|
||||
specialEffects.appendChild(effect);
|
||||
}else{
|
||||
} else {
|
||||
specialTitle.textContent += "[ " + effects.get("Description") + " ]";
|
||||
}
|
||||
}
|
||||
powder_special.appendChild(specialTitle);
|
||||
powder_special.appendChild(specialEffects);
|
||||
powder_special.append(specialTitle, specialEffects);
|
||||
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") {
|
||||
let dura_elem = document.createElement("div");
|
||||
dura_elem.classList.add("col");
|
||||
let dura = [];
|
||||
let dura_elem = make_elem("div", ["col"]);
|
||||
let dura;
|
||||
let suffix = "";
|
||||
if(nonConsumables.includes(item.get("type"))) {
|
||||
dura = item.get("durability");
|
||||
|
@ -457,9 +460,9 @@ function displayExpandedItem(item, parent_id){
|
|||
dura = item.get("duration");
|
||||
dura_elem.textContent = "Duration: "
|
||||
suffix = " sec."
|
||||
let charges = document.createElement("b");
|
||||
charges.textContent = "Charges: " + item.get("charges");
|
||||
parent_div.appendChild(charges);
|
||||
parent_div.appendChild(make_elem('b', [], {
|
||||
textContent: "Charges: " + item.get("charges")
|
||||
}));
|
||||
}
|
||||
|
||||
if (typeof(dura) === "string") {
|
||||
|
@ -472,9 +475,7 @@ function displayExpandedItem(item, parent_id){
|
|||
}
|
||||
//Show item tier
|
||||
if (item.get("tier") && item.get("tier") !== " ") {
|
||||
let item_desc_elem = document.createElement("div");
|
||||
item_desc_elem.classList.add("col");
|
||||
item_desc_elem.classList.add(item.get("tier"));
|
||||
let item_desc_elem = make_elem("div", ["col", item.get("tier")]);
|
||||
if (tome_types.includes(item.get("type"))) {
|
||||
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"));
|
||||
|
@ -486,20 +487,19 @@ function displayExpandedItem(item, parent_id){
|
|||
|
||||
//Show item hash if applicable
|
||||
if (item.get("crafted") || item.get("custom")) {
|
||||
let item_desc_elem = document.createElement("p");
|
||||
item_desc_elem.classList.add('itemp');
|
||||
item_desc_elem.style.maxWidth = "100%";
|
||||
item_desc_elem.style.wordWrap = "break-word";
|
||||
item_desc_elem.style.wordBreak = "break-word";
|
||||
item_desc_elem.textContent = item.get("hash");
|
||||
parent_div.append(item_desc_elem);
|
||||
parent_div.append(make_elem('p', ['itemp'], {
|
||||
style: {
|
||||
maxWidth: '100%',
|
||||
wordWrap: 'break-word',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
textContent: item.get('hash')
|
||||
}));
|
||||
}
|
||||
|
||||
if (item.get("category") === "weapon") {
|
||||
let total_damages = item.get("basedps");
|
||||
let base_dps_elem = document.createElement("p");
|
||||
base_dps_elem.classList.add("left");
|
||||
base_dps_elem.classList.add("itemp");
|
||||
let base_dps_elem = make_elem("p", ["left", "itemp"]);
|
||||
if (item.get("tier") === "Crafted") {
|
||||
let base_dps_min = total_damages[0];
|
||||
let base_dps_max = total_damages[1];
|
||||
|
@ -509,8 +509,7 @@ function displayExpandedItem(item, parent_id){
|
|||
else {
|
||||
base_dps_elem.textContent = "Base DPS: "+(total_damages);
|
||||
}
|
||||
parent_div.appendChild(document.createElement("p"));
|
||||
parent_div.appendChild(base_dps_elem);
|
||||
parent_div.append(make_elem("p"), base_dps_elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1268,8 +1267,8 @@ function displayPowderSpecials(parent_elem, powderSpecials, stats, weapon, overa
|
|||
//iterate through the special and display its effects.
|
||||
let powder_special = make_elem("p", ["pt-3"]);
|
||||
let specialSuffixes = new Map([ ["Duration", " sec"], ["Radius", " blocks"], ["Chains", ""], ["Damage", "%"], ["Damage Boost", "%"], ["Knockback", " blocks"] ]);
|
||||
let specialTitle = document.createElement("p");
|
||||
let specialEffects = document.createElement("p");
|
||||
let specialTitle = make_elem("p");
|
||||
let specialEffects = make_elem("p");
|
||||
specialTitle.classList.add(damageClasses[powderSpecialStats.indexOf(special[0]) + 1]);
|
||||
let effects = special[0]["weaponSpecialEffects"];
|
||||
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}
|
||||
};
|
||||
ing.id = 4001 + ing.pid;
|
||||
ing.diplayName = ing.name;
|
||||
ing.displayName = ing.name;
|
||||
switch(i) {
|
||||
case 0:
|
||||
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
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
// skip root.
|
||||
permute_check(1, best_skillpoints, final_skillpoints, best_activeSetCounts, allFalse.slice(), 0, []);
|
||||
if (sccs.length === 1) {
|
||||
// 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
@ -892,6 +882,17 @@ function make_elem(type, classlist = [], args = {}) {
|
|||
const ret_elem = document.createElement(type);
|
||||
ret_elem.classList.add(...classlist);
|
||||
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];
|
||||
}
|
||||
return ret_elem;
|
||||
|
|
168
tomes.json
168
tomes.json
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"tomes":
|
||||
[
|
||||
"tomes": [
|
||||
{
|
||||
"name": "Retaliating Tome of Armour Mastery I",
|
||||
"tier": "Fabled",
|
||||
|
@ -14,7 +13,8 @@
|
|||
"ref": 6,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 0
|
||||
"id": 0,
|
||||
"alias": "Thorns I"
|
||||
},
|
||||
{
|
||||
"name": "Retaliating Tome of Armour Mastery II",
|
||||
|
@ -28,7 +28,8 @@
|
|||
"thorns": 8,
|
||||
"ref": 8,
|
||||
"fixID": false,
|
||||
"id": 1
|
||||
"id": 1,
|
||||
"alias": "Thorns II"
|
||||
},
|
||||
{
|
||||
"name": "Destructive Tome of Armour Mastery I",
|
||||
|
@ -43,7 +44,8 @@
|
|||
"mdPct": 5,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 2
|
||||
"id": 2,
|
||||
"alias": "Melee I"
|
||||
},
|
||||
{
|
||||
"name": "Destructive Tome of Armour Mastery II",
|
||||
|
@ -57,7 +59,8 @@
|
|||
"thorns": 6,
|
||||
"reflection": 6,
|
||||
"fixID": false,
|
||||
"id": 3
|
||||
"id": 3,
|
||||
"alias": "Melee II"
|
||||
},
|
||||
{
|
||||
"name": "Sorcerer's Tome of Armour Mastery I",
|
||||
|
@ -71,7 +74,8 @@
|
|||
"sdPct": 5,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 4
|
||||
"id": 4,
|
||||
"alias": "Spell Damage I"
|
||||
},
|
||||
{
|
||||
"name": "Sorcerer's Tome of Armour Mastery II",
|
||||
|
@ -84,7 +88,8 @@
|
|||
"defMobs": 5,
|
||||
"sdPct": 6,
|
||||
"fixID": false,
|
||||
"id": 5
|
||||
"id": 5,
|
||||
"alias": "Spell Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Everlasting Tome of Armour Mastery I",
|
||||
|
@ -98,7 +103,8 @@
|
|||
"hprRaw": 15,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 6
|
||||
"id": 6,
|
||||
"alias": "Health Regen I"
|
||||
},
|
||||
{
|
||||
"name": "Everlasting Tome of Armour Mastery II",
|
||||
|
@ -111,7 +117,8 @@
|
|||
"defMobs": 5,
|
||||
"hprRaw": 60,
|
||||
"fixID": false,
|
||||
"id": 7
|
||||
"id": 7,
|
||||
"alias": "Health Regen II"
|
||||
},
|
||||
{
|
||||
"name": "Vampiric Tome of Armour Mastery I",
|
||||
|
@ -125,7 +132,8 @@
|
|||
"ls": 25,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 8
|
||||
"id": 8,
|
||||
"alias": "Life Steal I"
|
||||
},
|
||||
{
|
||||
"name": "Vampiric Tome of Armour Mastery II",
|
||||
|
@ -138,7 +146,8 @@
|
|||
"defMobs": 5,
|
||||
"ls": 85,
|
||||
"fixID": false,
|
||||
"id": 9
|
||||
"id": 9,
|
||||
"alias": "Life Steal II"
|
||||
},
|
||||
{
|
||||
"name": "Greedy Tome of Armour Mastery I",
|
||||
|
@ -152,7 +161,8 @@
|
|||
"lb": 5,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 10
|
||||
"id": 10,
|
||||
"alias": "Loot Bonus I"
|
||||
},
|
||||
{
|
||||
"name": "Greedy Tome of Armour Mastery II",
|
||||
|
@ -165,7 +175,8 @@
|
|||
"defMobs": 5,
|
||||
"lb": 6,
|
||||
"fixID": false,
|
||||
"id": 11
|
||||
"id": 11,
|
||||
"alias": "Loot Bonus II"
|
||||
},
|
||||
{
|
||||
"name": "Weightless Tome of Armour Mastery I",
|
||||
|
@ -179,7 +190,8 @@
|
|||
"spd": 5,
|
||||
"hpBonus": 120,
|
||||
"fixID": false,
|
||||
"id": 12
|
||||
"id": 12,
|
||||
"alias": "Walk Speed I"
|
||||
},
|
||||
{
|
||||
"name": "Weightless Tome of Armour Mastery II",
|
||||
|
@ -192,7 +204,8 @@
|
|||
"defMobs": 5,
|
||||
"spd": 6,
|
||||
"fixID": false,
|
||||
"id": 13
|
||||
"id": 13,
|
||||
"alias": "Walk Speed II"
|
||||
},
|
||||
{
|
||||
"name": "Blooming Tome of Armour Mastery II",
|
||||
|
@ -206,7 +219,8 @@
|
|||
"eDefPct": 10,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 14
|
||||
"id": 14,
|
||||
"alias": "Earth Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Pulsing Tome of Armour Mastery II",
|
||||
|
@ -220,7 +234,8 @@
|
|||
"tDefPct": 10,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 15
|
||||
"id": 15,
|
||||
"alias": "Thunder Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Oceanic Tome of Armour Mastery II",
|
||||
|
@ -234,7 +249,8 @@
|
|||
"wDefPct": 10,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 16
|
||||
"id": 16,
|
||||
"alias": "Water Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Courageous Tome of Armour Mastery II",
|
||||
|
@ -248,7 +264,8 @@
|
|||
"fDefPct": 10,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 17
|
||||
"id": 17,
|
||||
"alias": "Fire Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Clouded Tome of Armour Mastery II",
|
||||
|
@ -262,7 +279,8 @@
|
|||
"aDefPct": 10,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 18
|
||||
"id": 18,
|
||||
"alias": "Air Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Radiant Tome of Armour Mastery II",
|
||||
|
@ -280,7 +298,8 @@
|
|||
"aDefPct": 6,
|
||||
"hpBonus": 150,
|
||||
"fixID": false,
|
||||
"id": 19
|
||||
"id": 19,
|
||||
"alias": "Rainbow Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Tome of Weapon Mastery I",
|
||||
|
@ -292,7 +311,8 @@
|
|||
"lvl": 60,
|
||||
"damMobs": 6,
|
||||
"fixID": false,
|
||||
"id": 20
|
||||
"id": 20,
|
||||
"alias": "Weapon Mastery I"
|
||||
},
|
||||
{
|
||||
"name": "Earthbound Tome of Weapon Mastery I",
|
||||
|
@ -305,7 +325,8 @@
|
|||
"damMobs": 7,
|
||||
"str": 3,
|
||||
"fixID": false,
|
||||
"id": 21
|
||||
"id": 21,
|
||||
"alias": "Strength I"
|
||||
},
|
||||
{
|
||||
"name": "Earthbound Tome of Weapon Mastery II",
|
||||
|
@ -318,7 +339,8 @@
|
|||
"damMobs": 8,
|
||||
"str": 3,
|
||||
"fixID": false,
|
||||
"id": 22
|
||||
"id": 22,
|
||||
"alias": "Strength II"
|
||||
},
|
||||
{
|
||||
"name": "Nimble Tome of Weapon Mastery I",
|
||||
|
@ -331,7 +353,8 @@
|
|||
"damMobs": 7,
|
||||
"dex": 3,
|
||||
"fixID": false,
|
||||
"id": 23
|
||||
"id": 23,
|
||||
"alias": "Dexterity I"
|
||||
},
|
||||
{
|
||||
"name": "Nimble Tome of Weapon Mastery II",
|
||||
|
@ -344,7 +367,8 @@
|
|||
"damMobs": 8,
|
||||
"dex": 3,
|
||||
"fixID": false,
|
||||
"id": 24
|
||||
"id": 24,
|
||||
"alias": "Dexterity II"
|
||||
},
|
||||
{
|
||||
"name": "Mystical Tome of Weapon Mastery I",
|
||||
|
@ -357,7 +381,8 @@
|
|||
"damMobs": 7,
|
||||
"int": 3,
|
||||
"fixID": false,
|
||||
"id": 25
|
||||
"id": 25,
|
||||
"alias": "Intelligence I"
|
||||
},
|
||||
{
|
||||
"name": "Mystical Tome of Weapon Mastery II",
|
||||
|
@ -370,7 +395,8 @@
|
|||
"damMobs": 8,
|
||||
"int": 3,
|
||||
"fixID": false,
|
||||
"id": 26
|
||||
"id": 26,
|
||||
"alias": "Intelligence II"
|
||||
},
|
||||
{
|
||||
"name": "Warding Tome of Weapon Mastery I",
|
||||
|
@ -383,7 +409,8 @@
|
|||
"damMobs": 7,
|
||||
"def": 3,
|
||||
"fixID": false,
|
||||
"id": 27
|
||||
"id": 27,
|
||||
"alias": "Defense I"
|
||||
},
|
||||
{
|
||||
"name": "Warding Tome of Weapon Mastery II",
|
||||
|
@ -396,7 +423,8 @@
|
|||
"damMobs": 8,
|
||||
"def": 3,
|
||||
"fixID": false,
|
||||
"id": 28
|
||||
"id": 28,
|
||||
"alias": "Defense II"
|
||||
},
|
||||
{
|
||||
"name": "Athletic Tome of Weapon Mastery I",
|
||||
|
@ -409,7 +437,8 @@
|
|||
"damMobs": 7,
|
||||
"agi": 3,
|
||||
"fixID": false,
|
||||
"id": 29
|
||||
"id": 29,
|
||||
"alias": "Agility I"
|
||||
},
|
||||
{
|
||||
"name": "Athletic Tome of Weapon Mastery II",
|
||||
|
@ -422,7 +451,8 @@
|
|||
"damMobs": 8,
|
||||
"agi": 3,
|
||||
"fixID": false,
|
||||
"id": 30
|
||||
"id": 30,
|
||||
"alias": "Agility II"
|
||||
},
|
||||
{
|
||||
"name": "Cosmic Tome of Weapon Mastery I",
|
||||
|
@ -439,7 +469,8 @@
|
|||
"def": 1,
|
||||
"agi": 1,
|
||||
"fixID": false,
|
||||
"id": 31
|
||||
"id": 31,
|
||||
"alias": "Rainbow Skillpoint I"
|
||||
},
|
||||
{
|
||||
"name": "Cosmic Tome of Weapon Mastery II",
|
||||
|
@ -456,7 +487,8 @@
|
|||
"def": 1,
|
||||
"agi": 1,
|
||||
"fixID": false,
|
||||
"id": 32
|
||||
"id": 32,
|
||||
"alias": "Rainbow Skillpoint II"
|
||||
},
|
||||
{
|
||||
"name": "Seismic Tome of Weapon Mastery II",
|
||||
|
@ -469,7 +501,8 @@
|
|||
"damMobs": 12,
|
||||
"eDamPct": 7,
|
||||
"fixID": false,
|
||||
"id": 33
|
||||
"id": 33,
|
||||
"alias": "Earth Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Voltaic Tome of Weapon Mastery II",
|
||||
|
@ -482,7 +515,8 @@
|
|||
"damMobs": 12,
|
||||
"tDamPct": 7,
|
||||
"fixID": false,
|
||||
"id": 34
|
||||
"id": 34,
|
||||
"alias": "Thunder Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Abyssal Tome of Weapon Mastery II",
|
||||
|
@ -495,7 +529,8 @@
|
|||
"damMobs": 12,
|
||||
"wDamPct": 7,
|
||||
"fixID": false,
|
||||
"id": 35
|
||||
"id": 35,
|
||||
"alias": "Water Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Infernal Tome of Weapon Mastery II",
|
||||
|
@ -508,7 +543,8 @@
|
|||
"damMobs": 12,
|
||||
"fDamPct": 7,
|
||||
"fixID": false,
|
||||
"id": 36
|
||||
"id": 36,
|
||||
"alias": "Fire Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Cyclonic Tome of Weapon Mastery II",
|
||||
|
@ -521,7 +557,8 @@
|
|||
"damMobs": 12,
|
||||
"aDamPct": 7,
|
||||
"fixID": false,
|
||||
"id": 37
|
||||
"id": 37,
|
||||
"alias": "Air Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Astral Tome of Weapon Mastery II",
|
||||
|
@ -538,7 +575,8 @@
|
|||
"fDamPct": 6,
|
||||
"aDamPct": 6,
|
||||
"fixID": false,
|
||||
"id": 38
|
||||
"id": 38,
|
||||
"alias": "Rainbow Damage II"
|
||||
},
|
||||
{
|
||||
"name": "Brute's Tome of Allegiance",
|
||||
|
@ -551,7 +589,8 @@
|
|||
"str": 3,
|
||||
"eDamPct": 2,
|
||||
"fixID": false,
|
||||
"id": 39
|
||||
"id": 39,
|
||||
"alias": "Strength"
|
||||
},
|
||||
{
|
||||
"name": "Sadist's Tome of Allegiance",
|
||||
|
@ -564,7 +603,8 @@
|
|||
"dex": 3,
|
||||
"tDamPct": 2,
|
||||
"fixID": false,
|
||||
"id": 40
|
||||
"id": 40,
|
||||
"alias": "Dexterity"
|
||||
},
|
||||
{
|
||||
"name": "Mastermind's Tome of Allegiance",
|
||||
|
@ -577,7 +617,8 @@
|
|||
"int": 3,
|
||||
"wDamPct": 2,
|
||||
"fixID": false,
|
||||
"id": 41
|
||||
"id": 41,
|
||||
"alias": "Intelligence"
|
||||
},
|
||||
{
|
||||
"name": "Arsonist's Tome of Allegiance",
|
||||
|
@ -590,7 +631,8 @@
|
|||
"def": 3,
|
||||
"fDamPct": 2,
|
||||
"fixID": false,
|
||||
"id": 42
|
||||
"id": 42,
|
||||
"alias": "Defense"
|
||||
},
|
||||
{
|
||||
"name": "Ghost's Tome of Allegiance",
|
||||
|
@ -603,7 +645,8 @@
|
|||
"agi": 3,
|
||||
"aDamPct": 2,
|
||||
"fixID": false,
|
||||
"id": 43
|
||||
"id": 43,
|
||||
"alias": "Agility"
|
||||
},
|
||||
{
|
||||
"name": "Psychopath's Tome of Allegiance",
|
||||
|
@ -616,7 +659,8 @@
|
|||
"str": 2,
|
||||
"dex": 2,
|
||||
"fixID": false,
|
||||
"id": 44
|
||||
"id": 44,
|
||||
"alias": "ET"
|
||||
},
|
||||
{
|
||||
"name": "Loner's Tome of Allegiance",
|
||||
|
@ -629,7 +673,8 @@
|
|||
"str": 2,
|
||||
"int": 2,
|
||||
"fixID": false,
|
||||
"id": 45
|
||||
"id": 45,
|
||||
"alias": "EW"
|
||||
},
|
||||
{
|
||||
"name": "Warlock's Tome of Allegiance",
|
||||
|
@ -642,7 +687,8 @@
|
|||
"dex": 2,
|
||||
"int": 2,
|
||||
"fixID": false,
|
||||
"id": 46
|
||||
"id": 46,
|
||||
"alias": "TW"
|
||||
},
|
||||
{
|
||||
"name": "Destroyer's Tome of Allegiance",
|
||||
|
@ -655,7 +701,8 @@
|
|||
"str": 2,
|
||||
"def": 2,
|
||||
"fixID": false,
|
||||
"id": 47
|
||||
"id": 47,
|
||||
"alias": "EF"
|
||||
},
|
||||
{
|
||||
"name": "Devil's Tome of Allegiance",
|
||||
|
@ -668,7 +715,8 @@
|
|||
"dex": 2,
|
||||
"def": 2,
|
||||
"fixID": false,
|
||||
"id": 48
|
||||
"id": 48,
|
||||
"alias": "TF"
|
||||
},
|
||||
{
|
||||
"name": "Alchemist's Tome of Allegiance",
|
||||
|
@ -681,7 +729,8 @@
|
|||
"int": 2,
|
||||
"def": 2,
|
||||
"fixID": false,
|
||||
"id": 49
|
||||
"id": 49,
|
||||
"alias": "WF"
|
||||
},
|
||||
{
|
||||
"name": "Barbarian's Tome of Allegiance",
|
||||
|
@ -694,7 +743,8 @@
|
|||
"str": 2,
|
||||
"agi": 2,
|
||||
"fixID": false,
|
||||
"id": 50
|
||||
"id": 50,
|
||||
"alias": "EA"
|
||||
},
|
||||
{
|
||||
"name": "Freelancer's Tome of Allegiance",
|
||||
|
@ -707,7 +757,8 @@
|
|||
"dex": 2,
|
||||
"agi": 2,
|
||||
"fixID": false,
|
||||
"id": 51
|
||||
"id": 51,
|
||||
"alias": "TA"
|
||||
},
|
||||
{
|
||||
"name": "Sycophant's Tome of Allegiance",
|
||||
|
@ -720,7 +771,8 @@
|
|||
"int": 2,
|
||||
"agi": 2,
|
||||
"fixID": false,
|
||||
"id": 52
|
||||
"id": 52,
|
||||
"alias": "WA"
|
||||
},
|
||||
{
|
||||
"name": "Fanatic's Tome of Allegiance",
|
||||
|
@ -733,7 +785,8 @@
|
|||
"def": 2,
|
||||
"agi": 2,
|
||||
"fixID": false,
|
||||
"id": 53
|
||||
"id": 53,
|
||||
"alias": "FA"
|
||||
},
|
||||
{
|
||||
"name": "Assimilator's Tome of Allegiance",
|
||||
|
@ -749,7 +802,8 @@
|
|||
"def": 1,
|
||||
"agi": 1,
|
||||
"fixID": false,
|
||||
"id": 54
|
||||
"id": 54,
|
||||
"alias": "Rainbow"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue