From 2d719e9a4e4a5d43e10699c91d951d1542b52d3a Mon Sep 17 00:00:00 2001 From: ferricles Date: Sun, 19 Jun 2022 12:05:01 -0700 Subject: [PATCH 01/68] BitVector class --- js/utils.js | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/js/utils.js b/js/utils.js index fed7df8..07e984b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -98,6 +98,8 @@ function log(b, n) { // https://stackoverflow.com/a/27696695 // Modified for fixed precision +// Base64.fromInt(-2147483648); // gives "200000" +// Base64.toInt("200000"); // gives -2147483648 Base64 = (function () { var digitsStr = // 0 8 16 24 32 40 48 56 63 @@ -149,8 +151,38 @@ Base64 = (function () { }; })(); -// Base64.fromInt(-2147483648); // gives "200000" -// Base64.toInt("200000"); // gives -2147483648 + +/** A class used to represent an arbitrary length bit vector. Very useful for encoding and decoding. + * + */ + class BitVector { + + /** Constructs an arbitrary-length bit vector. + * @class + * @param {String | Number} + */ + constructor(data, length) { + + /** @private + * @type {UInt8Array} + */ + if (length) { + if (typeof data === "string") { + this.bits = Uint8Array(); + } else if (typeof data === "number") { + this.bits = Uint8Array(); + } + } else { + if (typeof data === "string") { + this.bits = Uint8Array(); + } else if (typeof data === "number") { + this.bits = Uint8Array(); + } + } + + + } +} /* Turns a raw stat and a % stat into a final stat on the basis that - raw and >= 100% becomes 0 and + raw and <=-100% becomes negative. From 28955fe66172a9d9fad38bbf4a90d34339b9c15a Mon Sep 17 00:00:00 2001 From: ferricles Date: Mon, 20 Jun 2022 12:07:25 -0700 Subject: [PATCH 02/68] temp --- js/utils.js | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/js/utils.js b/js/utils.js index 07e984b..885db24 100644 --- a/js/utils.js +++ b/js/utils.js @@ -163,27 +163,14 @@ Base64 = (function () { */ constructor(data, length) { - /** @private - * @type {UInt8Array} - */ - if (length) { - if (typeof data === "string") { - this.bits = Uint8Array(); - } else if (typeof data === "number") { - this.bits = Uint8Array(); - } - } else { - if (typeof data === "string") { - this.bits = Uint8Array(); - } else if (typeof data === "number") { - this.bits = Uint8Array(); - } - } + this.bitvector = NumberInt(); } } +let bitv = new BitVector(123123, 1); + /* Turns a raw stat and a % stat into a final stat on the basis that - raw and >= 100% becomes 0 and + raw and <=-100% becomes negative. Pct would be 0.80 for 80%, -1.20 for 120%, etc From 64e076cbb483e97d622f6bb11aa00c679553bd30 Mon Sep 17 00:00:00 2001 From: ferricles Date: Tue, 21 Jun 2022 21:51:26 -0700 Subject: [PATCH 03/68] dummy commit --- js/utils.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/js/utils.js b/js/utils.js index 885db24..d83681c 100644 --- a/js/utils.js +++ b/js/utils.js @@ -159,17 +159,96 @@ Base64 = (function () { /** Constructs an arbitrary-length bit vector. * @class - * @param {String | Number} + * @param {String | Number} data + * @param {Number} length - a set length for the data. Must be in the range [0, 32] if data is a Number. + * + * The structure of the Uint32Array should be [[last, ..., first], ..., [last, ..., first], [empty space, last, ..., first]] */ constructor(data, length) { + let bit_vec = []; + if (length < 0) { + throw new RangeError("BitVector must have nonnegative length."); + } - this.bitvector = NumberInt(); + if (typeof data === "string") { + //string in B64 + let str_len = data.length; + let curr = 0; + let curr_bits = 0; + } else if (typeof data === "number") { + //convert to int just in case + data = Math.round(data); - + //range of numbers that won't fit in a uint32 + if (data > 2**32 - 1 || data < -(2 ** 32 - 1)) { + throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); + } + bit_vec.push(data); + } else if (data instanceof Array) [ + + ] + + this.length = length; + this.bits = new Uint32Array(bit_vec); } -} -let bitv = new BitVector(123123, 1); + + readBitsSigned() { + + } + + readBitsUnsigned() { + + } + + setBits() { + + } + + clearBits() { + + } + + append(data, length) { + if (length < 0) { + throw new RangeError("BitVector length must increase by a nonnegative number."); + } + + this.length += length; + } + + /** Creates a string version of the bit vector + * + * @returns A bit vector in string format + */ + toString() { + if (this.length == 0) { + return ""; + } + + let bitstr = ""; + //extract bits from first uint32 - may not be all 32 bits + let length_first = this.length % 32; + let curr = this.bits[0]; + for (let i = 0; i < length_first; ++i) { + bitstr = (curr % 2 == 0 ? '0' : '1') + bitstr; + curr >>= 1; + } + + //extract bits from rest of uint32s - always all 32 bits + for (let i = 1; i < this.bits.length; ++i) { + curr = this.bits[i]; + for (let j = 0; j < 32; ++j) { + bitstr = (curr % 2 == 0 ? '0' : '1') + bitstr; + curr >>= 1; + } + } + + //return the formed bitstring + return bitstr; + } +}; + /* Turns a raw stat and a % stat into a final stat on the basis that - raw and >= 100% becomes 0 and + raw and <=-100% becomes negative. From cac7e6b04b3c30b361cfb98d1ed8611fd0156df2 Mon Sep 17 00:00:00 2001 From: ferricles Date: Wed, 22 Jun 2022 17:45:13 -0700 Subject: [PATCH 04/68] functional set bit, clear bit, read bit, slice --- js/utils.js | 93 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/js/utils.js b/js/utils.js index d83681c..7c2657f 100644 --- a/js/utils.js +++ b/js/utils.js @@ -184,40 +184,88 @@ Base64 = (function () { throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); } bit_vec.push(data); - } else if (data instanceof Array) [ - - ] + } else if (data instanceof Array) { + + } this.length = length; this.bits = new Uint32Array(bit_vec); } - - readBitsSigned() { - + /** Return value of bit at index idx. + * + * @param {Number} idx - the index to read + */ + read_bit(idx) { + if (idx < 0 || idx > this.length) { + throw new RangeError("Cannot read bit outside the range of the BitVector."); + } + return ((this.bits[Math.floor(idx / 32)] & (1 << (idx % 32))) == 0 ? 0 : 1); } - readBitsUnsigned() { + /** Returns an integer value (if possible) made from the range of bits [start, end). Undefined behavior if the range to read is too big. + * + * @param {Number} start - the index to start slicing from. Inclusive + * @param {Number} end - the index to end slicing at. Exclusive + */ + slice(start, end) { + if (end < start) { + throw new RangeError("Cannot slice a range where the end is before the start."); + } else if (end == start) { + return 0; + } + let res = 0; + if (Math.floor((end - 1) / 32) == Math.floor(start / 32)) { + //the range is within 1 uint32 section - do some relatively fast bit twiddling + res = (this.bits[Math.floor(start / 32)] & ~((((~0) << ((end - 1) % 32)) << 1) | ~((~0) << (start % 32)))) >>> (start % 32); + } else { + //range is not within 1 section of the array - do ugly + for (let i = start; i < end; i++) { + res |= (get_bit(i) << (i - start)); + } + } + + return res; } - setBits() { - + /** Assign bit at index idx to 1. + * + * @param {Number} idx - the index to set + */ + set_bit(idx) { + if (idx < 0 || idx > this.length) { + throw new RangeError("Cannot set bit outside the range of the BitVector."); + } + this.bits[Math.floor(idx / 32)] |= (1 << idx % 32); } - clearBits() { - + /** Assign bit at index idx to 0. + * + * @param {Number} idx - the index to clear + */ + clear_bit(idx) { + if (idx < 0 || idx > this.length) { + throw new RangeError("Cannot clear bit outside the range of the BitVector."); + } + this.bits[Math.floor(idx / 32)] &= ~(1 << idx % 32); } + /** Appends data to the BitVector. + * + * @param {Number | String | Array} data + * @param {Number} length - the length, in bits, of the new data + */ append(data, length) { if (length < 0) { throw new RangeError("BitVector length must increase by a nonnegative number."); } this.length += length; + //add in new data } - /** Creates a string version of the bit vector + /** Creates a string version of the bit vector in B64. Does not keep the order of elements a sensible human readable format. * * @returns A bit vector in string format */ @@ -226,26 +274,7 @@ Base64 = (function () { return ""; } - let bitstr = ""; - //extract bits from first uint32 - may not be all 32 bits - let length_first = this.length % 32; - let curr = this.bits[0]; - for (let i = 0; i < length_first; ++i) { - bitstr = (curr % 2 == 0 ? '0' : '1') + bitstr; - curr >>= 1; - } - - //extract bits from rest of uint32s - always all 32 bits - for (let i = 1; i < this.bits.length; ++i) { - curr = this.bits[i]; - for (let j = 0; j < 32; ++j) { - bitstr = (curr % 2 == 0 ? '0' : '1') + bitstr; - curr >>= 1; - } - } - - //return the formed bitstring - return bitstr; + } }; From ab4de136f2d518423304323e2e84be3937ba5fbd Mon Sep 17 00:00:00 2001 From: ferricles Date: Thu, 23 Jun 2022 09:44:03 -0700 Subject: [PATCH 05/68] optimized slice(), string construction, toB64 and toString --- js/utils.js | 146 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/js/utils.js b/js/utils.js index 7c2657f..7be0df3 100644 --- a/js/utils.js +++ b/js/utils.js @@ -172,9 +172,32 @@ Base64 = (function () { if (typeof data === "string") { //string in B64 - let str_len = data.length; let curr = 0; - let curr_bits = 0; + let total_bits = 0; + let i = 0; + while (i < data.length && total_bits < length) { + let int = Base64.toInt(data[i]) + //total_bits implicitly % 32 here + curr |= (int << total_bits); + + if (total_bits % 32 > 25) { + //push and roll over uncaught bits + bit_vec.push(curr); + curr = (int >>> (32 - (total_bits % 32))); + } + + i++; + total_bits += 6; + } + + //need to push remaining bits if not pushed yet + if (total_bits % 32 <= 25) { + bit_vec.push(curr); + } + + //override length passed in if it's > length of string naturally to save space + length = Math.min(length, data.length * 6); + } else if (typeof data === "number") { //convert to int just in case data = Math.round(data); @@ -184,8 +207,8 @@ Base64 = (function () { throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); } bit_vec.push(data); - } else if (data instanceof Array) { - + } else { + throw new TypeError("BitVector must be instantiated with a Number or a B64 String"); } this.length = length; @@ -195,6 +218,8 @@ Base64 = (function () { /** Return value of bit at index idx. * * @param {Number} idx - the index to read + * + * @returns the bit value at position idx */ read_bit(idx) { if (idx < 0 || idx > this.length) { @@ -207,26 +232,39 @@ Base64 = (function () { * * @param {Number} start - the index to start slicing from. Inclusive * @param {Number} end - the index to end slicing at. Exclusive + * + * @returns an integer representation of the sliced bits. */ slice(start, end) { + //TO NOTE: JS shifting is ALWAYS in mod 32. a << b will do a << (b mod 32) implicitly. + if (end < start) { throw new RangeError("Cannot slice a range where the end is before the start."); } else if (end == start) { return 0; + } else if (end - start > 32) { + //requesting a slice of longer than 32 bits (safe integer "length") + throw new RangeError("Cannot slice a range of longer than 32 bits (unsafe to store in an integer)."); } let res = 0; if (Math.floor((end - 1) / 32) == Math.floor(start / 32)) { //the range is within 1 uint32 section - do some relatively fast bit twiddling - res = (this.bits[Math.floor(start / 32)] & ~((((~0) << ((end - 1) % 32)) << 1) | ~((~0) << (start % 32)))) >>> (start % 32); + res = (this.bits[Math.floor(start / 32)] & ~((((~0) << ((end - 1))) << 1) | ~((~0) << (start)))) >>> (start % 32); } else { - //range is not within 1 section of the array - do ugly - for (let i = start; i < end; i++) { - res |= (get_bit(i) << (i - start)); - } + //the number of bits in the uint32s + let start_pos = (start % 32); + let int_idx = Math.floor(start/32); + res = (this.bits[int_idx] & ((~0) << (start))) >>> (start_pos); + res |= (this.bits[int_idx + 1] & ~((~0) << (end))) << (32 - start_pos); } return res; + + // General code - slow + // for (let i = start; i < end; i++) { + // res |= (get_bit(i) << (i - start)); + // } } /** Assign bit at index idx to 1. @@ -251,30 +289,94 @@ Base64 = (function () { this.bits[Math.floor(idx / 32)] &= ~(1 << idx % 32); } + /** Creates a string version of the bit vector in B64. Does not keep the order of elements a sensible human readable format. + * + * @returns a b64 string representation of the BitVector + */ + toB64() { + if (this.length == 0) { + return ""; + } + let b64_str = ""; + let i = 0; + while (i < this.length) { + b64_str += Base64.fromIntV(this.slice(i, i + 6), 1); + i += 6; + } + + return b64_str; + } + + /** Returns a BitVector in bitstring format. Probably only useful for dev debugging. + * + * @returns a bit string representation of the BitVector + */ + toString() { + let ret_str = ""; + for (let i = 0; i < this.length; i++) { + ret_str += this.read_bit(i) == 0 ? "0": "1"; + } + return ret_str; + } + /** Appends data to the BitVector. * - * @param {Number | String | Array} data + * @param {Number | String} data * @param {Number} length - the length, in bits, of the new data */ - append(data, length) { + append(data, length) { if (length < 0) { throw new RangeError("BitVector length must increase by a nonnegative number."); } - this.length += length; - //add in new data - } + let bit_vec = []; + for (uint of this.bits) { + bit_vec.push(uint); + } + if (typeof data === "string") { + //string in B64 + let curr = 0; + let total_bits = 0; + let i = 0; + while (i < data.length && total_bits < length) { + let int = Base64.toInt(data[i]) + //total_bits implicitly % 32 here + curr |= (int << total_bits); - /** Creates a string version of the bit vector in B64. Does not keep the order of elements a sensible human readable format. - * - * @returns A bit vector in string format - */ - toString() { - if (this.length == 0) { - return ""; + if (total_bits % 32 > 25) { + //push and roll over uncaught bits + bit_vec.push(curr); + curr = (int >>> (32 - (total_bits % 32))); + } + + i++; + total_bits += 6; + } + + //need to push remaining bits if not pushed yet + if (total_bits % 32 <= 25) { + bit_vec.push(curr); + } + + //override length passed in if it's > length of string naturally to save space + length = Math.min(length, data.length * 6); + + } else if (typeof data === "number") { + //convert to int just in case + data = Math.round(data); + + //range of numbers that "could" fit in a uint32 -> [0, 2^32) U (-2^31, 2^31) + if (data > 2**32 - 1 || data < -(2 ** 31 - 1)) { + throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); + } + bit_vec.push(data); + } else { + throw new TypeError("BitVector must be appended with a Number or a B64 String"); } - + this.bits = new Uint32Array(bit_vec); + this.length += length; + //add in new data } }; From 738286275e091cde2a1daa5cd0e372f4f7584362 Mon Sep 17 00:00:00 2001 From: ferricles Date: Thu, 23 Jun 2022 11:20:23 -0700 Subject: [PATCH 06/68] toString() change, b64 constructor fix, append() functionality --- js/utils.js | 54 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/js/utils.js b/js/utils.js index 7be0df3..55e6c72 100644 --- a/js/utils.js +++ b/js/utils.js @@ -175,6 +175,10 @@ Base64 = (function () { let curr = 0; let total_bits = 0; let i = 0; + + //override length passed in if it's > length of string naturally to save space + length = Math.min(length, data.length * 6); + while (i < data.length && total_bits < length) { let int = Base64.toInt(data[i]) //total_bits implicitly % 32 here @@ -184,6 +188,7 @@ Base64 = (function () { //push and roll over uncaught bits bit_vec.push(curr); curr = (int >>> (32 - (total_bits % 32))); + console.log(curr); } i++; @@ -191,13 +196,9 @@ Base64 = (function () { } //need to push remaining bits if not pushed yet - if (total_bits % 32 <= 25) { + if (total_bits % 32 != 0) { bit_vec.push(curr); } - - //override length passed in if it's > length of string naturally to save space - length = Math.min(length, data.length * 6); - } else if (typeof data === "number") { //convert to int just in case data = Math.round(data); @@ -309,12 +310,12 @@ Base64 = (function () { /** Returns a BitVector in bitstring format. Probably only useful for dev debugging. * - * @returns a bit string representation of the BitVector + * @returns a bit string representation of the BitVector. Goes from higher-indexed bits to lower-indexed bits. */ toString() { let ret_str = ""; for (let i = 0; i < this.length; i++) { - ret_str += this.read_bit(i) == 0 ? "0": "1"; + ret_str = (this.read_bit(i) == 0 ? "0": "1") + ret_str; } return ret_str; } @@ -330,53 +331,64 @@ Base64 = (function () { } let bit_vec = []; - for (uint of this.bits) { + for (const uint of this.bits) { bit_vec.push(uint); } if (typeof data === "string") { //string in B64 - let curr = 0; - let total_bits = 0; + let curr = bit_vec[Math.floor(this.length / 32)]; + let total_bits = this.length; let i = 0; - while (i < data.length && total_bits < length) { + + //override length passed in if it's > length of string naturally to save space + length = Math.min(length, data.length * 6); + + while (i < data.length && total_bits < this.length + length) { let int = Base64.toInt(data[i]) //total_bits implicitly % 32 here curr |= (int << total_bits); if (total_bits % 32 > 25) { //push and roll over uncaught bits - bit_vec.push(curr); + if (bit_vec.length == (Math.floor(this.length / 32) + 1)) { + bit_vec[Math.floor(this.length / 32)] = curr; + } else { + bit_vec.push(curr); + } curr = (int >>> (32 - (total_bits % 32))); } i++; total_bits += 6; } - + //need to push remaining bits if not pushed yet - if (total_bits % 32 <= 25) { + if (total_bits % 32 != 0) { bit_vec.push(curr); } - - //override length passed in if it's > length of string naturally to save space - length = Math.min(length, data.length * 6); - } else if (typeof data === "number") { //convert to int just in case - data = Math.round(data); + let int = Math.round(data); //range of numbers that "could" fit in a uint32 -> [0, 2^32) U (-2^31, 2^31) if (data > 2**32 - 1 || data < -(2 ** 31 - 1)) { throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); } - bit_vec.push(data); + + //could be split between multiple new ints + //reminder that shifts implicitly mod 32 + bit_vec[Math.floor(this.length / 32)] |= ((int & ~((~0) << length)) << (this.length)); + console.log((int & ~(~(0) << length))); + if (Math.floor((this.length + length) / 32) > Math.floor(this.length / 32)) { + bit_vec.push(int >>> (this.length)); + } } else { throw new TypeError("BitVector must be appended with a Number or a B64 String"); } + console.log(bit_vec); this.bits = new Uint32Array(bit_vec); this.length += length; - //add in new data } }; From bbede794b92f80a0c675f2fc92e388550a4543d7 Mon Sep 17 00:00:00 2001 From: ferricles Date: Thu, 23 Jun 2022 11:21:11 -0700 Subject: [PATCH 07/68] removed remaining printouts --- js/utils.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/utils.js b/js/utils.js index 55e6c72..5a56be2 100644 --- a/js/utils.js +++ b/js/utils.js @@ -188,7 +188,6 @@ Base64 = (function () { //push and roll over uncaught bits bit_vec.push(curr); curr = (int >>> (32 - (total_bits % 32))); - console.log(curr); } i++; @@ -378,7 +377,6 @@ Base64 = (function () { //could be split between multiple new ints //reminder that shifts implicitly mod 32 bit_vec[Math.floor(this.length / 32)] |= ((int & ~((~0) << length)) << (this.length)); - console.log((int & ~(~(0) << length))); if (Math.floor((this.length + length) / 32) > Math.floor(this.length / 32)) { bit_vec.push(int >>> (this.length)); } @@ -386,7 +384,6 @@ Base64 = (function () { throw new TypeError("BitVector must be appended with a Number or a B64 String"); } - console.log(bit_vec); this.bits = new Uint32Array(bit_vec); this.length += length; } From 95cd93ad4d78f81caf1c3142a836737dbc2f431c Mon Sep 17 00:00:00 2001 From: ferricles Date: Fri, 24 Jun 2022 00:15:06 -0700 Subject: [PATCH 08/68] major bug fixes, append number yet to be unit tested --- js/utils.js | 150 ++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 74 deletions(-) diff --git a/js/utils.js b/js/utils.js index 5a56be2..dd68037 100644 --- a/js/utils.js +++ b/js/utils.js @@ -159,46 +159,40 @@ Base64 = (function () { /** Constructs an arbitrary-length bit vector. * @class - * @param {String | Number} data - * @param {Number} length - a set length for the data. Must be in the range [0, 32] if data is a Number. + * @param {String | Number} data - The data to append. + * @param {Number} length - A set length for the data. Ignored if data is a string. * * The structure of the Uint32Array should be [[last, ..., first], ..., [last, ..., first], [empty space, last, ..., first]] */ constructor(data, length) { let bit_vec = []; - if (length < 0) { - throw new RangeError("BitVector must have nonnegative length."); - } if (typeof data === "string") { - //string in B64 - let curr = 0; - let total_bits = 0; - let i = 0; + let int = 0; + let bv_idx = 0; + length = data.length * 6; - //override length passed in if it's > length of string naturally to save space - length = Math.min(length, data.length * 6); - - while (i < data.length && total_bits < length) { - let int = Base64.toInt(data[i]) - //total_bits implicitly % 32 here - curr |= (int << total_bits); - - if (total_bits % 32 > 25) { - //push and roll over uncaught bits - bit_vec.push(curr); - curr = (int >>> (32 - (total_bits % 32))); + for (let i = 0; i < data.length; i++) { + let char = Base64.toInt(data[i]); + let pre_pos = bv_idx % 32; + int |= (char << bv_idx); + bv_idx += 6; + let post_pos = bv_idx % 32; + if (post_pos < pre_pos) { //we have to have filled up the integer + bit_vec.push(int); + int = (char >>> (6 - post_pos)); } - i++; - total_bits += 6; - } - - //need to push remaining bits if not pushed yet - if (total_bits % 32 != 0) { - bit_vec.push(curr); + if (i == data.length - 1 && post_pos != 0) { + bit_vec.push(int); + } } } else if (typeof data === "number") { + if (typeof length === "undefined") + if (length < 0) { + throw new RangeError("BitVector must have nonnegative length."); + } + //convert to int just in case data = Math.round(data); @@ -217,12 +211,12 @@ Base64 = (function () { /** Return value of bit at index idx. * - * @param {Number} idx - the index to read + * @param {Number} idx - The index to read * - * @returns the bit value at position idx + * @returns The bit value at position idx */ read_bit(idx) { - if (idx < 0 || idx > this.length) { + if (idx < 0 || idx >= this.length) { throw new RangeError("Cannot read bit outside the range of the BitVector."); } return ((this.bits[Math.floor(idx / 32)] & (1 << (idx % 32))) == 0 ? 0 : 1); @@ -230,10 +224,10 @@ Base64 = (function () { /** Returns an integer value (if possible) made from the range of bits [start, end). Undefined behavior if the range to read is too big. * - * @param {Number} start - the index to start slicing from. Inclusive - * @param {Number} end - the index to end slicing at. Exclusive + * @param {Number} start - The index to start slicing from. Inclusive. + * @param {Number} end - The index to end slicing at. Exclusive. * - * @returns an integer representation of the sliced bits. + * @returns An integer representation of the sliced bits. */ slice(start, end) { //TO NOTE: JS shifting is ALWAYS in mod 32. a << b will do a << (b mod 32) implicitly. @@ -269,7 +263,7 @@ Base64 = (function () { /** Assign bit at index idx to 1. * - * @param {Number} idx - the index to set + * @param {Number} idx - The index to set. */ set_bit(idx) { if (idx < 0 || idx > this.length) { @@ -280,7 +274,7 @@ Base64 = (function () { /** Assign bit at index idx to 0. * - * @param {Number} idx - the index to clear + * @param {Number} idx - The index to clear. */ clear_bit(idx) { if (idx < 0 || idx > this.length) { @@ -291,7 +285,7 @@ Base64 = (function () { /** Creates a string version of the bit vector in B64. Does not keep the order of elements a sensible human readable format. * - * @returns a b64 string representation of the BitVector + * @returns A b64 string representation of the BitVector. */ toB64() { if (this.length == 0) { @@ -309,7 +303,7 @@ Base64 = (function () { /** Returns a BitVector in bitstring format. Probably only useful for dev debugging. * - * @returns a bit string representation of the BitVector. Goes from higher-indexed bits to lower-indexed bits. + * @returns A bit string representation of the BitVector. Goes from higher-indexed bits to lower-indexed bits. (n ... 0) */ toString() { let ret_str = ""; @@ -319,10 +313,22 @@ Base64 = (function () { return ret_str; } + /** Returns a BitVector in bitstring format. Probably only useful for dev debugging. + * + * @returns A bit string representation of the BitVector. Goes from lower-indexed bits to higher-indexed bits. (0 ... n) + */ + toStringR() { + let ret_str = ""; + for (let i = 0; i < this.length; i++) { + ret_str += (this.read_bit(i) == 0 ? "0": "1"); + } + return ret_str; + } + /** Appends data to the BitVector. * - * @param {Number | String} data - * @param {Number} length - the length, in bits, of the new data + * @param {Number | String} data - The data to append. + * @param {Number} length - The length, in bits, of the new data. This is ignored if data is a string. */ append(data, length) { if (length < 0) { @@ -334,56 +340,52 @@ Base64 = (function () { bit_vec.push(uint); } if (typeof data === "string") { - //string in B64 - let curr = bit_vec[Math.floor(this.length / 32)]; - let total_bits = this.length; - let i = 0; - - //override length passed in if it's > length of string naturally to save space - length = Math.min(length, data.length * 6); - - while (i < data.length && total_bits < this.length + length) { - let int = Base64.toInt(data[i]) - //total_bits implicitly % 32 here - curr |= (int << total_bits); - - if (total_bits % 32 > 25) { - //push and roll over uncaught bits - if (bit_vec.length == (Math.floor(this.length / 32) + 1)) { - bit_vec[Math.floor(this.length / 32)] = curr; + let int = bit_vec[bit_vec.length - 1]; + let bv_idx = this.length; + length = data.length * 6; + let updated_curr = false; + for (let i = 0; i < data.length; i++) { + let char = Base64.toInt(data[i]); + let pre_pos = bv_idx % 32; + int |= (char << bv_idx); + bv_idx += 6; + let post_pos = bv_idx % 32; + if (post_pos < pre_pos) { //we have to have filled up the integer + if (bit_vec.length == this.bits.length && !updated_curr) { + bit_vec[bit_vec.length - 1] = int; + updated_curr = true; } else { - bit_vec.push(curr); + bit_vec.push(int); } - curr = (int >>> (32 - (total_bits % 32))); + int = (char >>> (6 - post_pos)); } - i++; - total_bits += 6; - } - - //need to push remaining bits if not pushed yet - if (total_bits % 32 != 0) { - bit_vec.push(curr); + if (i == data.length - 1) { + if (bit_vec.length == this.bits.length && !updated_curr) { + bit_vec[bit_vec.length - 1] = int; + } else if (post_pos != 0) { + bit_vec.push(int); + } + } } } else if (typeof data === "number") { //convert to int just in case let int = Math.round(data); - //range of numbers that "could" fit in a uint32 -> [0, 2^32) U (-2^31, 2^31) - if (data > 2**32 - 1 || data < -(2 ** 31 - 1)) { + //range of numbers that "could" fit in a uint32 -> [0, 2^32) U [-2^31, 2^31) + if (data > 2**32 - 1 || data < -(2 ** 31)) { throw new RangeError("Numerical data has to fit within a 32-bit integer range to instantiate a BitVector."); } - //could be split between multiple new ints //reminder that shifts implicitly mod 32 - bit_vec[Math.floor(this.length / 32)] |= ((int & ~((~0) << length)) << (this.length)); - if (Math.floor((this.length + length) / 32) > Math.floor(this.length / 32)) { - bit_vec.push(int >>> (this.length)); + bit_vec[bit_vec.length - 1] |= ((int & ~((~0) << length)) << (this.length)); + if (((this.length + length) % 32 < ((this.length - 1) % 32) + 1) || ((this.length + length) % 32 != 0)) { + bit_vec.push(int >>> (32 - this.length)); } } else { throw new TypeError("BitVector must be appended with a Number or a B64 String"); } - + this.bits = new Uint32Array(bit_vec); this.length += length; } @@ -650,4 +652,4 @@ async function hardReload() { function capitalizeFirst(str) { return str[0].toUpperCase() + str.substring(1); -} \ No newline at end of file +} From 7e82213b36eb91a3994f62d800833355e8c9ffc0 Mon Sep 17 00:00:00 2001 From: ferricles Date: Fri, 24 Jun 2022 00:29:43 -0700 Subject: [PATCH 09/68] simple range bug fix in set and clear bit --- js/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/utils.js b/js/utils.js index dd68037..0aae108 100644 --- a/js/utils.js +++ b/js/utils.js @@ -266,7 +266,7 @@ Base64 = (function () { * @param {Number} idx - The index to set. */ set_bit(idx) { - if (idx < 0 || idx > this.length) { + if (idx < 0 || idx >= this.length) { throw new RangeError("Cannot set bit outside the range of the BitVector."); } this.bits[Math.floor(idx / 32)] |= (1 << idx % 32); @@ -277,7 +277,7 @@ Base64 = (function () { * @param {Number} idx - The index to clear. */ clear_bit(idx) { - if (idx < 0 || idx > this.length) { + if (idx < 0 || idx >= this.length) { throw new RangeError("Cannot clear bit outside the range of the BitVector."); } this.bits[Math.floor(idx / 32)] &= ~(1 << idx % 32); From c7054ce25a1e7a979a35a866eb6e2d215588482f Mon Sep 17 00:00:00 2001 From: ferricles Date: Fri, 24 Jun 2022 00:43:24 -0700 Subject: [PATCH 10/68] append() number bug fix --- js/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/utils.js b/js/utils.js index 0aae108..ca9687b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -379,7 +379,7 @@ Base64 = (function () { //could be split between multiple new ints //reminder that shifts implicitly mod 32 bit_vec[bit_vec.length - 1] |= ((int & ~((~0) << length)) << (this.length)); - if (((this.length + length) % 32 < ((this.length - 1) % 32) + 1) || ((this.length + length) % 32 != 0)) { + if (((this.length - 1) % 32 + 1) + length > 32) { bit_vec.push(int >>> (32 - this.length)); } } else { From 2b187743959f9faf62a751de29ca81cd0cd48acc Mon Sep 17 00:00:00 2001 From: hppeng Date: Fri, 24 Jun 2022 03:35:03 -0700 Subject: [PATCH 11/68] Wynn2 damage calculation --- js/build.js | 22 ++-- js/build_utils.js | 40 ++++++- js/builder_graph.js | 24 ++-- js/damage_calc.js | 272 ++++++++++++++++++++++++++++++-------------- js/display.js | 61 ++-------- js/optimize.js | 8 +- 6 files changed, 267 insertions(+), 160 deletions(-) diff --git a/js/build.js b/js/build.js index ccd25a6..fc57316 100644 --- a/js/build.js +++ b/js/build.js @@ -155,6 +155,17 @@ class Build{ let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef", "str", "dex", "int", "def", "agi", "dmgMobs", "defMobs"]; + let must_ids = [ + "eMdPct","eMdRaw","eSdPct","eSdRaw","eDamPct","eDamRaw","eDamAddMin","eDamAddMax", + "tMdPct","tMdRaw","tSdPct","tSdRaw","tDamPct","tDamRaw","tDamAddMin","tDamAddMax", + "wMdPct","wMdRaw","wSdPct","wSdRaw","wDamPct","wDamRaw","wDamAddMin","wDamAddMax", + "fMdPct","fMdRaw","fSdPct","fSdRaw","fDamPct","fDamRaw","fDamAddMin","fDamAddMax", + "aMdPct","aMdRaw","aSdPct","aSdRaw","aDamPct","aDamRaw","aDamAddMin","aDamAddMax", + "nMdPct","nMdRaw","nSdPct","nSdRaw","nDamPct","nDamRaw","nDamAddMin","nDamAddMax", // neutral which is now an element + "mdPct","mdRaw","sdPct","sdRaw","damPct","damRaw","damAddMin","damAddMax", // These are the old ids. Become proportional. + "rMdPct","rMdRaw","rSdPct","rSdRaw","rDamPct","rDamRaw","rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). rSdRaw is rainraw + ] + //Create a map of this build's stats let statMap = new Map(); statMap.set("damageMultiplier", 1); @@ -163,6 +174,9 @@ class Build{ for (const staticID of staticIDs) { statMap.set(staticID, 0); } + for (const staticID of must_ids) { + statMap.set(staticID, 0); + } statMap.set("hp", levelToHPBase(this.level)); let major_ids = new Set(); @@ -211,13 +225,5 @@ class Build{ statMap.set("atkSpd", this.weapon.statMap.get("atkSpd")); this.statMap = statMap; - - this.aggregateStats(); - } - - aggregateStats() { - let statMap = this.statMap; - let weapon_stats = this.weapon.statMap; - statMap.set("damageRaw", [weapon_stats.get("nDam"), weapon_stats.get("eDam"), weapon_stats.get("tDam"), weapon_stats.get("wDam"), weapon_stats.get("fDam"), weapon_stats.get("aDam")]); } } diff --git a/js/build_utils.js b/js/build_utils.js index a92d38a..80db2f1 100644 --- a/js/build_utils.js +++ b/js/build_utils.js @@ -66,12 +66,23 @@ let itemTypes = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(tom let elementIcons = ["\u2724","\u2726", "\u2749", "\u2739", "\u274b" ]; let skpReqs = skp_order.map(x => x + "Req"); -let item_fields = [ "name", "displayName", "lore", "color", "tier", "set", "slots", "type", "material", "drop", "quest", "restrict", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "str", "dex", "int", "agi", "def", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "fixID", "category", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd", "id", "majorIds", "dmgMobs", "defMobs"]; +let item_fields = [ "name", "displayName", "lore", "color", "tier", "set", "slots", "type", "material", "drop", "quest", "restrict", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "str", "dex", "int", "agi", "def", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "fixID", "category", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rSdRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd", "id", "majorIds", "damMobs", "defMobs", + +// wynn2 damages. +"eMdPct","eMdRaw","eSdPct","eSdRaw",/*"eDamPct"*/,"eDamRaw","eDamAddMin","eDamAddMax", +"tMdPct","tMdRaw","tSdPct","tSdRaw",/*"tDamPct"*/,"tDamRaw","tDamAddMin","tDamAddMax", +"wMdPct","wMdRaw","wSdPct","wSdRaw",/*"wDamPct"*/,"wDamRaw","wDamAddMin","wDamAddMax", +"fMdPct","fMdRaw","fSdPct","fSdRaw",/*"fDamPct"*/,"fDamRaw","fDamAddMin","fDamAddMax", +"aMdPct","aMdRaw","aSdPct","aSdRaw",/*"aDamPct"*/,"aDamRaw","aDamAddMin","aDamAddMax", +"nMdPct","nMdRaw","nSdPct","nSdRaw","nDamPct","nDamRaw","nDamAddMin","nDamAddMax", // neutral which is now an element +/*"mdPct","mdRaw","sdPct","sdRaw",*/"damPct","damRaw","damAddMin","damAddMax", // These are the old ids. Become proportional. +"rMdPct","rMdRaw","rSdPct",/*"rSdRaw",*/"rDamPct","rDamRaw","rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). rSdRaw is rainraw +]; let str_item_fields = [ "name", "displayName", "lore", "color", "tier", "set", "type", "material", "drop", "quest", "restrict", "category", "atkSpd" ] //File reading for ID translations for JSON purposes let reversetranslations = new Map(); -let translations = new Map([["name", "name"], ["displayName", "displayName"], ["tier", "tier"], ["set", "set"], ["sockets", "slots"], ["type", "type"], ["dropType", "drop"], ["quest", "quest"], ["restrictions", "restrict"], ["damage", "nDam"], ["fireDamage", "fDam"], ["waterDamage", "wDam"], ["airDamage", "aDam"], ["thunderDamage", "tDam"], ["earthDamage", "eDam"], ["attackSpeed", "atkSpd"], ["health", "hp"], ["fireDefense", "fDef"], ["waterDefense", "wDef"], ["airDefense", "aDef"], ["thunderDefense", "tDef"], ["earthDefense", "eDef"], ["level", "lvl"], ["classRequirement", "classReq"], ["strength", "strReq"], ["dexterity", "dexReq"], ["intelligence", "intReq"], ["agility", "agiReq"], ["defense", "defReq"], ["healthRegen", "hprPct"], ["manaRegen", "mr"], ["spellDamage", "sdPct"], ["damageBonus", "mdPct"], ["lifeSteal", "ls"], ["manaSteal", "ms"], ["xpBonus", "xpb"], ["lootBonus", "lb"], ["reflection", "ref"], ["strengthPoints", "str"], ["dexterityPoints", "dex"], ["intelligencePoints", "int"], ["agilityPoints", "agi"], ["defensePoints", "def"], ["thorns", "thorns"], ["exploding", "expd"], ["speed", "spd"], ["attackSpeedBonus", "atkTier"], ["poison", "poison"], ["healthBonus", "hpBonus"], ["soulPoints", "spRegen"], ["emeraldStealing", "eSteal"], ["healthRegenRaw", "hprRaw"], ["spellDamageRaw", "sdRaw"], ["damageBonusRaw", "mdRaw"], ["bonusFireDamage", "fDamPct"], ["bonusWaterDamage", "wDamPct"], ["bonusAirDamage", "aDamPct"], ["bonusThunderDamage", "tDamPct"], ["bonusEarthDamage", "eDamPct"], ["bonusFireDefense", "fDefPct"], ["bonusWaterDefense", "wDefPct"], ["bonusAirDefense", "aDefPct"], ["bonusThunderDefense", "tDefPct"], ["bonusEarthDefense", "eDefPct"], ["type", "type"], ["identified", "fixID"], ["skin", "skin"], ["category", "category"], ["spellCostPct1", "spPct1"], ["spellCostRaw1", "spRaw1"], ["spellCostPct2", "spPct2"], ["spellCostRaw2", "spRaw2"], ["spellCostPct3", "spPct3"], ["spellCostRaw3", "spRaw3"], ["spellCostPct4", "spPct4"], ["spellCostRaw4", "spRaw4"], ["rainbowSpellDamageRaw", "rainbowRaw"], ["sprint", "sprint"], ["sprintRegen", "sprintReg"], ["jumpHeight", "jh"], ["lootQuality", "lq"], ["gatherXpBonus", "gXp"], ["gatherSpeed", "gSpd"]]); +let translations = new Map([["name", "name"], ["displayName", "displayName"], ["tier", "tier"], ["set", "set"], ["sockets", "slots"], ["type", "type"], ["dropType", "drop"], ["quest", "quest"], ["restrictions", "restrict"], ["damage", "nDam"], ["fireDamage", "fDam"], ["waterDamage", "wDam"], ["airDamage", "aDam"], ["thunderDamage", "tDam"], ["earthDamage", "eDam"], ["attackSpeed", "atkSpd"], ["health", "hp"], ["fireDefense", "fDef"], ["waterDefense", "wDef"], ["airDefense", "aDef"], ["thunderDefense", "tDef"], ["earthDefense", "eDef"], ["level", "lvl"], ["classRequirement", "classReq"], ["strength", "strReq"], ["dexterity", "dexReq"], ["intelligence", "intReq"], ["agility", "agiReq"], ["defense", "defReq"], ["healthRegen", "hprPct"], ["manaRegen", "mr"], ["spellDamage", "sdPct"], ["damageBonus", "mdPct"], ["lifeSteal", "ls"], ["manaSteal", "ms"], ["xpBonus", "xpb"], ["lootBonus", "lb"], ["reflection", "ref"], ["strengthPoints", "str"], ["dexterityPoints", "dex"], ["intelligencePoints", "int"], ["agilityPoints", "agi"], ["defensePoints", "def"], ["thorns", "thorns"], ["exploding", "expd"], ["speed", "spd"], ["attackSpeedBonus", "atkTier"], ["poison", "poison"], ["healthBonus", "hpBonus"], ["soulPoints", "spRegen"], ["emeraldStealing", "eSteal"], ["healthRegenRaw", "hprRaw"], ["spellDamageRaw", "sdRaw"], ["damageBonusRaw", "mdRaw"], ["bonusFireDamage", "fDamPct"], ["bonusWaterDamage", "wDamPct"], ["bonusAirDamage", "aDamPct"], ["bonusThunderDamage", "tDamPct"], ["bonusEarthDamage", "eDamPct"], ["bonusFireDefense", "fDefPct"], ["bonusWaterDefense", "wDefPct"], ["bonusAirDefense", "aDefPct"], ["bonusThunderDefense", "tDefPct"], ["bonusEarthDefense", "eDefPct"], ["type", "type"], ["identified", "fixID"], ["skin", "skin"], ["category", "category"], ["spellCostPct1", "spPct1"], ["spellCostRaw1", "spRaw1"], ["spellCostPct2", "spPct2"], ["spellCostRaw2", "spRaw2"], ["spellCostPct3", "spPct3"], ["spellCostRaw3", "spRaw3"], ["spellCostPct4", "spPct4"], ["spellCostRaw4", "spRaw4"], ["rainbowSpellDamageRaw", "rSdRaw"], ["sprint", "sprint"], ["sprintRegen", "sprintReg"], ["jumpHeight", "jh"], ["lootQuality", "lq"], ["gatherXpBonus", "gXp"], ["gatherSpeed", "gSpd"]]); //does not include dmgMobs (wep tomes) and defMobs (armor tomes) for (const [k, v] of translations) { reversetranslations.set(v, k); @@ -103,7 +114,17 @@ let nonRolledIDs = [ "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", - "majorIds"]; + "majorIds", +// wynn2 damages. +"eDamAddMin","eDamAddMax", +"tDamAddMin","tDamAddMax", +"wDamAddMin","wDamAddMax", +"fDamAddMin","fDamAddMax", +"aDamAddMin","aDamAddMax", +"nDamAddMin","nDamAddMax", // neutral which is now an element +"damAddMin","damAddMax", // all +"rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). +]; let rolledIDs = [ "hprPct", "mr", @@ -131,13 +152,22 @@ let rolledIDs = [ "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", - "rainbowRaw", + "pDamRaw", "sprint", "sprintReg", "jh", "lq", "gXp", - "gSpd" + "gSpd", +// wynn2 damages. +"eMdPct","eMdRaw","eSdPct","eSdRaw",/*"eDamPct"*/,"eDamRaw","eDamAddMin","eDamAddMax", +"tMdPct","tMdRaw","tSdPct","tSdRaw",/*"tDamPct"*/,"tDamRaw","tDamAddMin","tDamAddMax", +"wMdPct","wMdRaw","wSdPct","wSdRaw",/*"wDamPct"*/,"wDamRaw","wDamAddMin","wDamAddMax", +"fMdPct","fMdRaw","fSdPct","fSdRaw",/*"fDamPct"*/,"fDamRaw","fDamAddMin","fDamAddMax", +"aMdPct","aMdRaw","aSdPct","aSdRaw",/*"aDamPct"*/,"aDamRaw","aDamAddMin","aDamAddMax", +"nMdPct","nMdRaw","nSdPct","nSdRaw","nDamPct","nDamRaw","nDamAddMin","nDamAddMax", // neutral which is now an element +/*"mdPct","mdRaw","sdPct","sdRaw",*/"damPct","damRaw","damAddMin","damAddMax", // These are the old ids. Become proportional. +"rMdPct","rMdRaw","rSdPct",/*"rSdRaw",*/"rDamPct","rDamRaw","rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). rSdRaw is rainraw ]; let reversedIDs = [ "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ]; diff --git a/js/builder_graph.js b/js/builder_graph.js index 899fd6d..63d08d1 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -313,9 +313,10 @@ class ItemDisplayNode extends ComputeNode { */ class WeaponInputDisplayNode extends ComputeNode { - constructor(name, image_field) { + constructor(name, image_field, dps_field) { super(name); this.image = image_field; + this.dps_field = dps_field; } compute_func(input_map) { @@ -324,6 +325,12 @@ class WeaponInputDisplayNode extends ComputeNode { const type = item.statMap.get('type'); this.image.setAttribute('src', '../media/items/new/generic-'+type+'.png'); + let dps = get_base_dps(item.statMap); + if (isNaN(dps)) { + dps = dps[1]; + if (isNaN(dps)) dps = 0; + } + this.dps_field.textContent = dps; //as of now, we NEED to have the dropdown tab visible/not hidden in order to properly display atree stuff. if (!document.getElementById("toggle-atree").classList.contains("toggleOn")) { @@ -577,9 +584,11 @@ class SpellDamageCalcNode extends ComputeNode { for (const part of spell_parts) { if (part.type === "damage") { - let results = calculateSpellDamage(stats, part.conversion, - stats.get("sdRaw") + stats.get("rainbowRaw"), stats.get("sdPct"), - part.multiplier / 100, weapon, skillpoints, damage_mult); + let tmp_conv = []; + for (let i in part.conversion) { + tmp_conv.push(part.conversion[i] * part.multiplier/100); + } + let results = calculateSpellDamage(stats, weapon, tmp_conv, true); spell_results.push(results); } else if (part.type === "heal") { // TODO: wynn2 formula @@ -651,8 +660,7 @@ function getMeleeStats(stats, weapon) { //One day we will create WynnWynn and no longer have shaman 99% melee injustice. //In all seriousness 99% is because wynn uses 0.33 to estimate dividing the damage by 3 to split damage between 3 beams. } - // 0spellmult for melee damage. - let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], stats.get("mdRaw"), stats.get("mdPct"), 0, weapon_stats, skillpoints, damage_mult); + let results = calculateSpellDamage(stats, weapon_stats, [100, 0, 0, 0, 0, 0], false, true); let dex = skillpoints[1]; @@ -973,7 +981,6 @@ function builder_graph_init() { //new PrintNode(eq+'-debug').link_to(item_input); //document.querySelector("#"+eq+"-tooltip").setAttribute("onclick", "collapse_element('#"+ eq +"-tooltip');"); //toggle_plus_minus('" + eq + "-pm'); } - console.log(none_tomes); for (const [eq, none_item] of zip2(tome_fields, [none_tomes[0], none_tomes[0], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[2]])) { let input_field = document.getElementById(eq+"-choice"); let item_image = document.getElementById(eq+"-img"); @@ -985,7 +992,8 @@ function builder_graph_init() { // weapon image changer node. let weapon_image = document.getElementById("weapon-img"); - new WeaponInputDisplayNode('weapon-type', weapon_image).link_to(item_nodes[8]); + let weapon_dps = document.getElementById("weapon-dps"); + new WeaponInputDisplayNode('weapon-type', weapon_image, weapon_dps).link_to(item_nodes[8]); // Level input node. let level_input = new InputNode('level-input', document.getElementById('level-choice')); diff --git a/js/damage_calc.js b/js/damage_calc.js index 490713f..058ba96 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -1,31 +1,67 @@ const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["vanish", 0.80], ["warscream", 0.10], ["bash", 0.50] ]); -// Calculate spell damage given a spell elemental conversion table, and a spell multiplier. -// If spell mult is 0, its melee damage and we don't multiply by attack speed. -function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier) { - let buildStats = new Map(stats); - //6x for damages, normal min normal max crit min crit max - let powders = weapon.get("powders").slice(); - - // Array of neutral + ewtfa damages. Each entry is a pair (min, max). - let damages = []; - const rawDamages = buildStats.get("damageRaw"); - for (let i = 0; i < rawDamages.length; i++) { - const damage_vals = rawDamages[i].split("-").map(Number); - damages.push(damage_vals); +// GRR THIS MUTATES THE ITEM +function get_base_dps(item) { + const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; + //SUPER JANK @HPP PLS FIX + let damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; + if (item.get("tier") !== "Crafted") { + let weapon_result = apply_weapon_powder(item); + let damages = weapon_result[0]; + let total_damage = 0; + for (const i in damage_keys) { + total_damage += damages[i][0] + damages[i][1]; + item.set(damage_keys[i], damages[i][0]+"-"+damages[i][1]); + } + total_damage = total_damage / 2; + return total_damage * attack_speed_mult; + } else { + let base_low = [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]; + let results_low = apply_weapon_powder(item, base_low); + let damage_low = results_low[2]; + let base_high = [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]; + let results_high = apply_weapon_powder(item, base_high); + let damage_high = results_high[2]; + + let total_damage_min = 0; + let total_damage_max = 0; + for (const i in damage_keys) { + total_damage_min += damage_low[i][0] + damage_low[i][1]; + total_damage_max += damage_high[i][0] + damage_high[i][1]; + item.set(damage_keys[i], damage_low[i][0]+"-"+damage_low[i][1]+"\u279c"+damage_high[i][0]+"-"+damage_high[i][1]); + } + total_damage_min = attack_speed_mult * total_damage_min / 2; + total_damage_max = attack_speed_mult * total_damage_max / 2; + return [total_damage_min, total_damage_max]; } +} + +/** + * weapon: Weapon to apply powder to + * damageBases: used by crafted + */ +function apply_weapon_powder(weapon, damageBases) { + let powders = weapon.get("powders").slice(); + + // Array of neutral + ewtfa damages. Each entry is a pair (min, max). + let damages = [ + weapon.get('nDam').split('-').map(Number), + weapon.get('eDam').split('-').map(Number), + weapon.get('tDam').split('-').map(Number), + weapon.get('wDam').split('-').map(Number), + weapon.get('fDam').split('-').map(Number), + weapon.get('aDam').split('-').map(Number) + ]; // Applying spell conversions let neutralBase = damages[0].slice(); let neutralRemainingRaw = damages[0].slice(); - //powder application for custom crafted weapons is inherently fucked because there is no base. Unsure what to do. //Powder application for Crafted weapons - this implementation is RIGHT YEAAAAAAAAA //1st round - apply each as ingred, 2nd round - apply as normal - if (weapon.get("tier") === "Crafted") { - let damageBases = buildStats.get("damageBases").slice(); + if (weapon.get("tier") === "Crafted" && !weapon.get("custom")) { for (const p of powders.concat(weapon.get("ingredPowders"))) { let powder = powderStats[p]; //use min, max, and convert let element = Math.floor((p+0.01)/6); //[0,4], the +0.01 attempts to prevent division error @@ -34,26 +70,13 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, damageBases[element+1] += diff + Math.floor( (powder.min + powder.max) / 2 ); } //update all damages - if(!weapon.get("custom")) { - for (let i = 0; i < damages.length; i++) { - damages[i] = [Math.floor(damageBases[i] * 0.9), Math.floor(damageBases[i] * 1.1)]; - } + for (let i = 0; i < damages.length; i++) { + damages[i] = [Math.floor(damageBases[i] * 0.9), Math.floor(damageBases[i] * 1.1)]; } - neutralRemainingRaw = damages[0].slice(); neutralBase = damages[0].slice(); } - for (let i = 0; i < 5; ++i) { - let conversionRatio = spellConversions[i+1]/100; - let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]); - let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]); - damages[i+1][0] = Math.floor(round_near(damages[i+1][0] + min_diff)); - damages[i+1][1] = Math.floor(round_near(damages[i+1][1] + max_diff)); - neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff)); - neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff)); - } - //apply powders to weapon for (const powderID of powders) { const powder = powderStats[powderID]; @@ -72,69 +95,148 @@ function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, damages[element+1][1] += powder.max; } + // The ordering of these two blocks decides whether neutral is present when converted away or not. + let present_elements = [] + for (const damage of damages) { + present_elements.push(damage[1] > 0); + } + + // The ordering of these two blocks decides whether neutral is present when converted away or not. damages[0] = neutralRemainingRaw; + return [damages, present_elements]; +} - let damageMult = damageMultiplier; - let melee = false; - // If we are doing melee calculations: - if (spellMultiplier == 0) { - spellMultiplier = 1; - melee = true; - } - else { - damageMult *= spellMultiplier * baseDamageMultiplier[attackSpeeds.indexOf(buildStats.get("atkSpd"))]; - } - //console.log(damages); - //console.log(damageMult); - rawModifier *= spellMultiplier * damageMultiplier; - let totalDamNorm = [0, 0]; - let totalDamCrit = [0, 0]; - let damages_results = []; - // 0th skillpoint is strength, 1st is dex. - let str = total_skillpoints[0]; - let strBoost = 1 + skillPointsToPercentage(str); - if(!melee){ - let baseDam = rawModifier * strBoost; - let baseDamCrit = rawModifier * (1 + strBoost); - totalDamNorm = [baseDam, baseDam]; - totalDamCrit = [baseDamCrit, baseDamCrit]; - } - let staticBoost = (pctModifier / 100.); - let skillBoost = [0]; - for (let i in total_skillpoints) { - skillBoost.push(skillPointsToPercentage(total_skillpoints[i]) + buildStats.get(skp_elements[i]+"DamPct") / 100.); +function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, ignore_speed=false) { + // TODO: Roll all the loops together maybe + + // Array of neutral + ewtfa damages. Each entry is a pair (min, max). + // 1. Get weapon damage (with powders). + let weapon_result = apply_weapon_powder(weapon); + let weapon_damages = weapon_result[0]; + let present = weapon_result[1]; + + // 2. Conversions. + // 2.1. First, apply neutral conversion (scale weapon damage). Keep track of total weapon damage here. + let damages = []; + const neutral_convert = conversions[0] / 100; + let weapon_min = 0; + let weapon_max = 0; + for (const damage of weapon_damages) { + let min_dmg = damage[0] * neutral_convert; + let max_dmg = damage[1] * neutral_convert; + damages.push([min_dmg, max_dmg]); + weapon_min += damage[0]; + weapon_max += damage[1]; } + // 2.2. Next, apply elemental conversions using damage computed in step 1.1. + // Also, track which elements are present. (Add onto those present in the weapon itself.) + for (let i = 1; i <= 5; ++i) { + if (conversions[i] > 0) { + damages[i][0] += conversions[i]/100 * weapon_min; + damages[i][1] += conversions[i]/100 * weapon_max; + present[i] = true; + } + } + + // Also theres prop and rainbow!! + const damage_elements = ['n'].concat(skp_elements); // netwfa + + if (!ignore_speed) { + // 3. Apply attack speed multiplier. Ignored for melee single hit + const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(weapon.get("atkSpd"))]; + for (let i = 0; i < 6; ++i) { + damages[i][0] *= attack_speed_mult; + damages[i][1] *= attack_speed_mult; + } + } + + // 4. Add additive damage. TODO: Is there separate additive damage? + for (let i = 0; i < 6; ++i) { + if (present[i]) { + damages[i][0] += stats.get(damage_elements[i]+'DamAddMin'); + damages[i][1] += stats.get(damage_elements[i]+'DamAddMax'); + } + } + + // 5. ID bonus. + let specific_boost_str = 'Md'; + if (use_spell_damage) { + specific_boost_str = 'Sd'; + } + // 5.1: %boost application + let skill_boost = [0]; // no neutral skillpoint booster + for (const skp of skp_order) { + skill_boost.push(skillPointsToPercentage(stats.get(skp))); + } + let static_boost = (stats.get(specific_boost_str.toLowerCase()+'Pct') + stats.get('damPct')) / 100; + + // These do not count raw damage. I think. Easy enough to change + let total_min = 0; + let total_max = 0; for (let i in damages) { - let damageBoost = 1 + skillBoost[i] + staticBoost; - damages_results.push([ - Math.max(damages[i][0] * strBoost * Math.max(damageBoost,0) * damageMult, 0), // Normal min - Math.max(damages[i][1] * strBoost * Math.max(damageBoost,0) * damageMult, 0), // Normal max - Math.max(damages[i][0] * (strBoost + 1) * Math.max(damageBoost,0) * damageMult, 0), // Crit min - Math.max(damages[i][1] * (strBoost + 1) * Math.max(damageBoost,0) * damageMult, 0), // Crit max - ]); - totalDamNorm[0] += damages_results[i][0]; - totalDamNorm[1] += damages_results[i][1]; - totalDamCrit[0] += damages_results[i][2]; - totalDamCrit[1] += damages_results[i][3]; + let damage_prefix = damage_elements[i] + specific_boost_str; + let damageBoost = 1 + skill_boost[i] + static_boost + (stats.get(damage_prefix+'Pct')/100); + damages[i][0] *= Math.max(damageBoost, 0); + damages[i][1] *= Math.max(damageBoost, 0); + // Collect total damage post %boost + total_min += damages[i][0]; + total_max += damages[i][1]; } - if (melee) { - totalDamNorm[0] += Math.max(strBoost*rawModifier, -damages_results[0][0]); - totalDamNorm[1] += Math.max(strBoost*rawModifier, -damages_results[0][1]); - totalDamCrit[0] += Math.max((strBoost+1)*rawModifier, -damages_results[0][2]); - totalDamCrit[1] += Math.max((strBoost+1)*rawModifier, -damages_results[0][3]); + + let total_elem_min = total_min - damages[0][0]; + let total_elem_max = total_max - damages[0][1]; + + // 5.2: Raw application. + let prop_raw = stats.get(specific_boost_str.toLowerCase()+'Raw') + stats.get('damRaw'); + let rainbow_raw = stats.get('r'+specific_boost_str+'Raw') + stats.get('rDamRaw'); + for (let i in damages) { + let damages_obj = damages[i]; + let damage_prefix = damage_elements[i] + specific_boost_str; + // Normie raw + let raw_boost = 0; + if (present[i]) { + raw_boost += stats.get(damage_prefix+'Raw') + stats.get(damage_elements[i]+'DamRaw'); + } + // Next, rainraw and propRaw + let new_min = damages_obj[0] + raw_boost + (damages_obj[0] / total_min) * prop_raw; + let new_max = damages_obj[1] + raw_boost + (damages_obj[1] / total_max) * prop_raw; + if (i != 0) { // rainraw + new_min += (damages_obj[0] / total_elem_min) * rainbow_raw; + new_max += (damages_obj[1] / total_elem_max) * rainbow_raw; + } + damages_obj[0] = new_min; + damages_obj[1] = new_max; } - damages_results[0][0] += strBoost*rawModifier; - damages_results[0][1] += strBoost*rawModifier; - damages_results[0][2] += (strBoost + 1)*rawModifier; - damages_results[0][3] += (strBoost + 1)*rawModifier; - if (totalDamNorm[0] < 0) totalDamNorm[0] = 0; - if (totalDamNorm[1] < 0) totalDamNorm[1] = 0; - if (totalDamCrit[0] < 0) totalDamCrit[0] = 0; - if (totalDamCrit[1] < 0) totalDamCrit[1] = 0; + // 6. Strength boosters + // str/dex, as well as any other mutually multiplicative effects + let strBoost = 1 + skill_boost[1]; + let total_dam_norm = [0, 0]; + let total_dam_crit = [0, 0]; + let damages_results = []; + const damage_mult = stats.get("damageMultiplier"); - return [totalDamNorm, totalDamCrit, damages_results]; + for (const damage of damages) { + const res = [ + damage[0] * strBoost * damage_mult, // Normal min + damage[1] * strBoost * damage_mult, // Normal max + damage[0] * (strBoost + 1) * damage_mult, // Crit min + damage[1] * (strBoost + 1) * damage_mult, // Crit max + ]; + damages_results.push(res); + total_dam_norm[0] += res[0]; + total_dam_norm[1] += res[1]; + total_dam_crit[0] += res[2]; + total_dam_crit[1] += res[3]; + } + + if (total_dam_norm[0] < 0) total_dam_norm[0] = 0; + if (total_dam_norm[1] < 0) total_dam_norm[1] = 0; + if (total_dam_crit[0] < 0) total_dam_crit[0] = 0; + if (total_dam_crit[1] < 0) total_dam_crit[1] = 0; + + return [total_dam_norm, total_dam_crit, damages_results]; } diff --git a/js/display.js b/js/display.js index 8f7017d..631f0c0 100644 --- a/js/display.js +++ b/js/display.js @@ -174,50 +174,7 @@ function displayExpandedItem(item, parent_id){ // !elemental is some janky hack for elemental damage. // normals just display a thing. if (item.get("category") === "weapon") { - let stats = new Map(); - stats.set("atkSpd", item.get("atkSpd")); - stats.set("eDamPct", 0); - stats.set("tDamPct", 0); - stats.set("wDamPct", 0); - stats.set("fDamPct", 0); - stats.set("aDamPct", 0); - - //SUPER JANK @HPP PLS FIX - let damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; - if (item.get("tier") !== "Crafted") { - stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]); - let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); - let damages = results[2]; - let total_damage = 0; - for (const i in damage_keys) { - total_damage += damages[i][0] + damages[i][1]; - item.set(damage_keys[i], damages[i][0]+"-"+damages[i][1]); - } - total_damage = total_damage / 2; - item.set("basedps", total_damage); - - } else { - stats.set("damageRaw", [item.get("nDamLow"), item.get("eDamLow"), item.get("tDamLow"), item.get("wDamLow"), item.get("fDamLow"), item.get("aDamLow")]); - stats.set("damageBases", [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]); - let resultsLow = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); - let damagesLow = resultsLow[2]; - stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]); - stats.set("damageBases", [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]); - let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, [0, 0, 0, 0, 0], 1, undefined); - let damages = results[2]; - console.log(damages); - - let total_damage_min = 0; - let total_damage_max = 0; - for (const i in damage_keys) { - total_damage_min += damagesLow[i][0] + damagesLow[i][1]; - total_damage_max += damages[i][0] + damages[i][1]; - item.set(damage_keys[i], damagesLow[i][0]+"-"+damagesLow[i][1]+"\u279c"+damages[i][0]+"-"+damages[i][1]); - } - total_damage_min = total_damage_min / 2; - total_damage_max = total_damage_max / 2; - item.set("basedps", [total_damage_min, total_damage_max]); - } + item.set('basedps', get_base_dps(item)); } else if (item.get("category") === "armor") { } @@ -555,19 +512,18 @@ function displayExpandedItem(item, parent_id){ } if (item.get("category") === "weapon") { - let damage_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; 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"); if (item.get("tier") === "Crafted") { - let base_dps_min = total_damages[0] * damage_mult; - let base_dps_max = total_damages[1] * damage_mult; + let base_dps_min = total_damages[0]; + let base_dps_max = total_damages[1]; base_dps_elem.textContent = "Base DPS: "+base_dps_min.toFixed(3)+"\u279c"+base_dps_max.toFixed(3); } else { - base_dps_elem.textContent = "Base DPS: "+(total_damages * damage_mult); + base_dps_elem.textContent = "Base DPS: "+(total_damages); } parent_div.appendChild(document.createElement("p")); parent_div.appendChild(base_dps_elem); @@ -1502,9 +1458,12 @@ function displayPowderSpecials(parent_elem, powderSpecials, stats, weapon, overa if (powderSpecialStats.indexOf(special[0]) == 0 || powderSpecialStats.indexOf(special[0]) == 1 || powderSpecialStats.indexOf(special[0]) == 3) { //Quake, Chain Lightning, or Courage let spell = (powderSpecialStats.indexOf(special[0]) == 3 ? spells[2] : spells[powderSpecialStats.indexOf(special[0])]); let part = spell["parts"][0]; - let _results = calculateSpellDamage(stats, part.conversion, - stats.get("mdRaw"), stats.get("mdPct"), - 0, weapon, skillpoints, stats.get('damageMultiplier') * ((part.multiplier[power-1] / 100)));//part.multiplier[power] / 100 + + let tmp_conv = []; + for (let i in part.conversion) { + tmp_conv.push(part.conversion[i] * part.multiplier[power-1]); + } + let _results = calculateSpellDamage(stats, weapon, tmp_conv, false); let critChance = skillPointsToPercentage(skillpoints[1]); let save_damages = []; diff --git a/js/optimize.js b/js/optimize.js index 2343d47..988da77 100644 --- a/js/optimize.js +++ b/js/optimize.js @@ -39,9 +39,11 @@ function optimizeStrDex() { let total_damage = 0; for (const part of spell_parts) { if (part.type === "damage") { - let _results = calculateSpellDamage(stats, part.conversion, - stats.get("sdRaw"), stats.get("sdPct"), - part.multiplier / 100, player_build.weapon.statMap, total_skillpoints, 1); + let tmp_conv = []; + for (let i in part.conversion) { + tmp_conv.push(part.conversion[i] * part.multiplier); + } + let _results = calculateSpellDamage(stats, player_build.weapon.statMap, tmp_conv, true); let totalDamNormal = _results[0]; let totalDamCrit = _results[1]; let results = _results[2]; From 83157f22c87772c44bf3fcd467f7178eec084647 Mon Sep 17 00:00:00 2001 From: hppeng Date: Fri, 24 Jun 2022 04:30:47 -0700 Subject: [PATCH 12/68] Add some atree images (not using wynn ones) --- media/atree/highlight_angle.png | Bin 0 -> 1042 bytes media/atree/highlight_c.png | Bin 0 -> 1027 bytes media/atree/highlight_line.png | Bin 0 -> 974 bytes media/atree/highlight_t.png | Bin 0 -> 632 bytes media/atree/node_0.png | Bin 0 -> 5644 bytes media/atree/node_0_blocked.png | Bin 0 -> 5163 bytes media/atree/node_1.png | Bin 0 -> 5384 bytes media/atree/node_1_blocked.png | Bin 0 -> 5066 bytes media/atree/node_2.png | Bin 0 -> 5421 bytes media/atree/node_2_blocked.png | Bin 0 -> 5111 bytes media/atree/node_3.png | Bin 0 -> 5218 bytes media/atree/node_3_blocked.png | Bin 0 -> 4913 bytes media/atree/node_4.png | Bin 0 -> 5277 bytes media/atree/node_4_blocked.png | Bin 0 -> 5031 bytes media/atree/node_highlight.png | Bin 0 -> 23515 bytes 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 media/atree/highlight_angle.png create mode 100644 media/atree/highlight_c.png create mode 100644 media/atree/highlight_line.png create mode 100644 media/atree/highlight_t.png create mode 100644 media/atree/node_0.png create mode 100644 media/atree/node_0_blocked.png create mode 100644 media/atree/node_1.png create mode 100644 media/atree/node_1_blocked.png create mode 100644 media/atree/node_2.png create mode 100644 media/atree/node_2_blocked.png create mode 100644 media/atree/node_3.png create mode 100644 media/atree/node_3_blocked.png create mode 100644 media/atree/node_4.png create mode 100644 media/atree/node_4_blocked.png create mode 100644 media/atree/node_highlight.png diff --git a/media/atree/highlight_angle.png b/media/atree/highlight_angle.png new file mode 100644 index 0000000000000000000000000000000000000000..accb200b454435f89aae297ec862ec8b779e7f17 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fn>1)7d$|)7e=epeR2rGbfdS zLF4??iQXD6filPH)An3CaY#p{d$&Z`6oF|{O0JnbpQ3hrKi52~+V^{3j?UDzn?Br- z(8*bIGwO!cQX8*nVPQwycKv&P?ut*=l;Gu`Ut2%_ZS~w*;6%F5>9z0JPM@>fxN(J< zwfXw1djq^X6qvWXUN(E~9J$`$!kT-5ORwG5n|k!WTe8y2SpiEq`DaF|tM5^{vwz-c zt$V_Jvrkt!{qWgwc_KHLy~bUQ533(-InOv%vh2~u#D^O;Ow&tV+;cYdxX?S{J{6tl zPt2QH{WR_csS#h^u)SWrwCDK}(uheI{gn5p~_ zbJ3l*gLMZl$lwFt-|xEXSiipXIya-8|L>dH^1IkxY<|xPHnC)PGsBmg-yt>ul`;H! zQw_1=?mGpB+HbZHv-8RY8ti`018Z^EZvEnizR~}S>ysPGuf64a)ttZjw(J%5`(fLy zSMcv!n^%6};qrTu4P|BwZ*v%K-DKFZnK2`s`NBE21#@{FtfdEyL@#qq?O(Rc#4M*N SH@bF%{O0NE=d#Wzp$P!rB&AFM literal 0 HcmV?d00001 diff --git a/media/atree/highlight_c.png b/media/atree/highlight_c.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa028df6daccfbde7f4c9662ab8550ccfbd9431 GIT binary patch literal 1027 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fn=|)7d$|)7e=epeR2rGbfdS zLF4??iMAex14LT=gSRS)vRZdoq^!`35)dt%q9JzBDN}pPtAtON>@zM+ShB-{YaJ_l zz1V6#y>q*)c5pR4;O|&GdGey}DHZWS8G>3r9(=MpSN*);er-d5w&B@VGZ;+nnh6Jb z`lN>)J)phof&J!tJ5H%WD+h zZah`ly*X^v2DkZtS`V(-H|dGhRf9zlPCSJj0RfJJsy8|=tec#q==eNH`u~L2{gb^F z!v%X}xHX)c-~2lG|H1d1wRf&8nJzM=;hgyKpAw8ryB+qvvbcY|FW8>(&-nvW?|qq` zec+Ay%d5-8?3jLSYwUi#Y}p&e>DC7xOjew|N&Dx@mKeSY`^EXE7?`&^oS$XB{g|bn ze1pi@te6jA&EJ|V6^nn6j4;s1XI zZEYZPJ!eH1kYX(f@(cbC1Ps5o@dX0~I14-?iy0XB4ude`@%$AjzzF^6>Eakt5%>0% zp`Wv(2#ce1&41(OrG4Uy1d~=z_S~~6?&$xIv%da#_w!@&`S0(mj5r*uIe=y{FqAx1 z1k)ELJ2KpI1Tzt$Y%!W z`Eoh*eCGVv$`_mG_f>t_ew}T>UNeTbTNyLf^Ey=LGTh2$z7Qwf@a-1E7W`8Bu5N!1 z`loFB>9q#v)fdbEZ?@;SV1Bsy-v4jWgTm9m&>pkw*5Ogt(uJ=1)7d$|)7e=epeR2rGbfdS zLF4??iQXD6filPH)An3CaY#p{d$&Z`6oF|{O0JnbpQ3hrKi52~+V^{3j?UDzn?Br- z(8*bIGwO!cQX8*nVPQwycKv&P?ut*=l;Gu`Ut2%_ZS~w*;6%F5>9z0JPM@>fxN(J< zwfXw1djq^X6qvWXUN(E~9J$`$!kT-5ORwG5n|k!WTe8y2SpiEq`DaF|tM5^{vwz-c zt$V_Jvrkt!{qWgwc_KHLy~bUQ533(-InOv%vh2~u#D^O;Ow&tV+;cYdxX?S{J{6tl zPt2QH{WR_cM1MG7z~PkFjHhE&A8y`Y%q z%*exfaLNCF<#}4VWjBKl=ooHneE#)JRc+P(KevD9ub=G5Fsm784g-Tjyc{S|Ff{nF zF=p^FftU=nl`LS|N|I%PB?p-K<*6W;evu;3@Js>ByfEDzOfMKU3>Xg73bPNb4Cg;{ YAANO5o_mvf87P1~UHx3vIVCg!0No2qo&W#< literal 0 HcmV?d00001 diff --git a/media/atree/highlight_t.png b/media/atree/highlight_t.png new file mode 100644 index 0000000000000000000000000000000000000000..7629abf158e6fb5e152a4eeed06327a39f7d5be3 GIT binary patch literal 632 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBK7W8uh%1n0P*P&}|DQoy8^~PGS&5c$z5c&nooe6r>t*2je`RJ2 zZ*v%K-DKFZnK2`s`NBE21#@{Ftfd?9Nz`f@MaOe_My<_nBUTIPmQYQ{w!((<&-JGt V%6&c*-$ literal 0 HcmV?d00001 diff --git a/media/atree/node_0.png b/media/atree/node_0.png new file mode 100644 index 0000000000000000000000000000000000000000..538b41afe28fec84f738fd98993d1ded17d05e4b GIT binary patch literal 5644 zcmX|Fc|26@`#v)UV+bARspInQ-n&oiUzI@|~W1ONcsdb*k>0004p z5CF~r-tIguvOBaqOmx(NvQ8m7Xu#}=*N6b{J^{IRj~%qR+;uHH0D!0Y@Pf3u6+Hj| z-fTTh;td~b25l>W*G!~!<)gkmU0lof93O#j;{see_E~gJl=d}U19@52l*q&yiunRh zmo9oHOS~UrmCDW@Mk0w{%Y%#8>)L1SDyudxj;eSRcGcN@xBJbWWxv%KfS>X2On)e{-w?yNhWU$u)s^Q0FZorvHzC+BqOe^ERpgI2QF z_!@KKPOp~D%TPBl0?wVq@fG>&@>qo77yn*Oocl?|XV}iH0&RZ;#W$Q-;q%_f!OhLh z#nG{PDu^Di8JmML|420Q5;Beiin`1vOxIVIPjICFd9pmIbX8Q#k?imYIqCtrzpozU zaMhu1C}B@RsKOCh#zA3#u#c>Y5mT9nW}2>JLz=qIg*K+0K3L6+&T8tqlt484r6N8l zeSHFpCK_2K1>Hl4z=&^h_HwvmvYMp%P(-7sp|)M=??nkU(I;WPtiSvl6M9J+xC9D+ zL_z^Z7QVWPG~R>fIh;x?v?*|1F=a02646ryuB*#2GIOHGv}QRzu#n*BvF{?shrMRg zy{K!}8n_a?QcJ?Gzp}6on;ND}-8-3~IDPzumV~}GefWdFocYWo6<>JBg}p=!-lX(8 zIWI!DkhsU%e7_^(f^B9~t%p{}* zSBU(+3pH{5wu7&)|3`^^(KkQ)1uO*gLv z()0FPBi1?ND=(lBd`>%ch@=J>f5T}-U8$e&Q!E_oTe;=%nTt-TB3BUyEpGowIxkQpD&YP-eSa}M+nqZ-{w2(AtRc|ufVFSem8mxU z_1W=GindA9A~ba$b&mCtU&XVinzb|Ek*D|KC-`E=lR+zcWW7$p$rQZh?b|Lgvt5%x zG&6ty+GC?%#U1bNY{Y&X%6bhYITP5ipw;-`BE`DVF z5o^y^5Uvw1BzwEcRl#|%OhNF{!*>~>4G9kY2$IwW-NHc_Xc5Ve*i1jF2XRGh9&7RlYr0Qf_{rRIc!P#$y(H({r%h%;wzg zJ03fnCw&@6zzR+OIA30o8@QcgmFg%=yhq-El%AM>mPZJzsc<|Yia9jUu z!H%-_K~&N5+3V>J(;aE{uC>jVTjC*&fSGy@26KPUHo`8%Tu5wdcs^7}Al9@8GT|34NL{pRnCcyRL zlIb(ar8+j4Utfm}Qf3d~Lk6?9?FC^qp^au?(=aYbdHZ)Wo#4u{<(X9HGTAQtL7m0B zyCJlST=s^#%3W*mWlX^RZ?Upfqkbj(mbE-|j=kQ<|0Gy50cGv;Z(3(X5~XMzsS53v z_t$$jQyYf%PxA#S2y9n!`~Lm$%5G({#mkSNIBxjSij=}b>c*45gmI=tAhD_TS%Cxb zJHB_Okm}_TP-9wmhvL}7CFQ&3+4v4Gh;^sB_5px-*`>CXUcJ_-%1EZ=bZqSR3^l&L z-};kNB;f9q-32)h=JLH6H>&O{DV#fJ zrw%{eumrro#g3&)YN0Yk! z59`U^W~Cm#-s{P;3ib4Yw4X834GwN0|G=8e%GJpGTVI5?EA!12m)&zB^<%Q*8xKH71oaLq5vagSf%4pCiozAfD%!u`b5Z?YRHT}L=OZqwn~Fi@hqyOhMYSCMZn zO4(fVu+`Q%<^Cs5afsg7S8STGbQ<1ef1VNi1cl#w=eypm!!Y#|XU$fhBG>a;3KGuX zD}S62B$chrvjQ3Rh0H&>=+~EAQW

{^-mbjJcAG%8G-Nv&XW^)|};SEAc^=-qi=J z-HtHS6^BTa$YKCis@#fHcrRv?qRLR9IxyUV0BmR_aYC|8QAJEm%6-%~1UY;{(7ATorY`2jeI^d8W8u4GM_sUXvURWaIXS*tzaM`xX zD)&W7XZ^hgJuL5@&=;G``8Z{MmmUqP-#_2TG5+*!yjJjOwOB~v%kZo=Ed3`Yh@Lyc zC7yoPFw;P3aImy}=GCgM=+D>_atngar!&?y|EOy?I z{Hn8CWLc-X8CfG&pnz?eFqqoEk?&+~Bp$mu()WM_o?S2WGQ&#~I2ZO77$};Rg|}ojqZ< zHmYam`Y$$HatrKNPUz&qbAvZ$U(;zRo_n`Gm&VD}a%3p^U6f4O|Df*-)SPa#B$$1g zKMOcf|BAWD{=42L^#o#hWGZ=L2m|~)Xm|KZRqcCMD!*ISu;Wy#YNW``Yf+k7z*eN5 zKprUiGJ@ar)FSi(YWXK#DK)n{bWv`ybm9d525?#w@{klAisJ$C+^zY+5gXMXi6}qU zW)K{H|1>Mk0Nu_9eie$V8pvwP-g}0GGf*-z4x?fWC+&6nBdEX4P6IX6rmX0!-TgJ4 zwct`V%(mY3{xaAN7$Hd-;?#vt(_Yn|SN)I8Q-_lpaZ*h7;V+q)^HXsJ5TUU}IPmn+ z{;Z{};ZBD%tuH^02x3^LHvv#uU%Y~Vd}2+f#Fz3xHyU_mL0@zO;RXf)#Cx2DHfDQo z{_Ujf^;-YWBx{yte_}nhoysbM&VIuc_zA;F$KqJ2*vD&zEXM>+E5g}M=CKYgi+$<% z(;`c&fmdiya#0$ok8f3Idy)zU@#a(k-+=G$Yjy7K6Jtm) z0w<{f303c%j{}NaBn2uErX4S3nt}cQoE#$@tF?zhYVBs;*#158*R_!tK6NJ`` z^5{4)hbRJoX$?Nu*Wnz;0aukyMQgR*wgTY5JlG;H5CYxj`p!WciNH%CRj;3AY-E0= z(F{20dGk}$@F#SO`&8S}_^RC7zy+Izk!{oW;y?vD%68nxJBLktduuG1QHO46{9m@S zh{g~$PNj2*agZ!*<`$&{w$}zg8&|;19u2UQyAMDf(P@qYg#5P_D@&T&s%W*|9_h89 zL)Ck+0(2t~?6*PC)Q`%WPJJ$YN$CvsHA=SrnMNMG30k-rpLdLoe!fc~Rx# zTSihB`o_3{0mxfwM#xyuZfX59*zcS_1&%^XTSk;*Iv_yJ1S+3DM0N7GFuT{|^n>G$ z0^ANP=Ek7Su0>0m>^(x(-dSSRwyZ>%(Nl)vkjU@1z!-p(cAmCfE z`tya|pTgS#SZV8@ky!$D0~dq|K+Q;A@gXPrB_Wg>xV!nrd(^kp3mBne4Nx;4)#mA4 zDRe83Z}GzO0qiM!neqbM0`hGjE__>Gqz!KiY7&=(;Hor#lw7C4BbZ@QQl#7K&{PV)Tcam;ppR$G%I_vZAewYx%;LWyh((`I5L> zbqy263hd|t$Q63h1jnllxDs%Y~@|-enZrk`X6h1!wdv)OEX%jaD z&VVg7FA(Zix_%_2J69)dqWNiBGGD5Mw5Oxt)*W%eM%k6i1MPwo21R}jP`b}XJ)=%j zS_fMhoJXKelKHrd^{Uou)&lG8 z9xiQ^z3H~8i(lr|vHhRS9ybGJMF+S&bTmaEJ1QJ|4a%+S(<$dJJ<+xaSc#wwmiwP~ z*xrv(1H#eE<)EIho26z?XFol8ac#OoE>}D5F{|M9`Vl;XJ}Btp^eQWGpVcoO#3gx{ zh2|W`KL)SwPIqOw*>$Enavb3w-@7I|+fDQPntI(@t>vjP#kV7#bxa(L?O^TfTtXi# z&w6tuu;!4TzPb4C)kQ^=BeL8z(`04dvE34TuWYOimrG%C0olkX0w{wRP2-20pyKZ2 z*JqzJ+K!hl&KIj?1+%Jue{xBqDd^RT+)3=VfpU`2&qz|YqiM{ z8WABXY^A5fh)AEI(!y)kYhnwzZEIc@c4uC~TM}njWp*mSDcG@`U9KC;eyfR4B1Fcq zM{HNtbwtUd-^~2?d89FQ@v=)__vuk^XI-!lG$fMSeI5?S>D&U#xP!WCMWF9F8?PJ( z&Sg7>*04o{Ub(S{U}q1xbRv#lw#kdz@4;^nSgwJplc9cpTS}Ahtrwah)hmn-8Yvr^ z*VC!dE=N^v)zn)^)+1<=K0~|A{x`d|puYPk4A%Tyz7aKEV@t!PR%CIkw+>%6SQ+~g#{ffdC4olXp(`>}|#+sGsj$p;Hb)T~?{H2WnCm_l%t z**rrA5E3TZnR>(@F>WgX$e)WJ7~?eq;HLm4#(qVA!4w!^BdteW1acOnNF&eu*Hd(% zO&E0tGnfzGX(VlL(>D7bE{5fC4B9|K4-v(KW~&19m{? zc`4=mB7jy0B2pqJQ~Lgc$OsdR^YWQzo&iPM`p2McwG|nE^b8<(%nG4Ro`7#3nR&dp zMU0IAhhWqNVr-uCfQ?Lac9aa#(*V;W-MQ+qqHhTWA5UE!im~az0P1iY_Jh&h^G}Cg zd6WEVGDV&PtZ`f31zt*?0{90J3Lca)&vZa=;lRaHF)h-LD4_TRR2_|Tw2%z?u6`Kx z#*fD<`Zo`w=4ppDr5N~C5-1T+cZvPAZ_-KM@^u;;vSFM2i zQP}d=`xE+$b7#5^qs&Q67LA#WvJnI#NoZJ$$&@jrVJ9Ee|sc#0ZKNY!{}Bj#7-g*V^n6S^(pqkYl4R!G+Tod>iy{O z2vO>C2sSzT82l8b&V4bGgq0NtX(p_KHgBDKLu4#g-Y+|xXzs`ziAL57%{XfM-221p z$A9Cv7D4mYNWZ)Fw{WbA#e0~#w!73nB&?cRG#^L0|2gVhfHrh!cz8G+AC1VF*BPDK f-)hI*XQ4)BQYXENt%Sf6TtH9jx@MXB-O&F7-D$q8 literal 0 HcmV?d00001 diff --git a/media/atree/node_0_blocked.png b/media/atree/node_0_blocked.png new file mode 100644 index 0000000000000000000000000000000000000000..e62898d6afbba094ba0c18a0e828e861b68624b6 GIT binary patch literal 5163 zcmW+)c|6nqAOGwylgS)qQ`sD$Qgh4kWv(1qMj|Rk%yN|^39}&y6}j&vgs)Ok>0lFI z5n_&Vq1+4A=Ry}wxL z3ji`KJ1cXSYo5Q0+%sgY_uL4Cq42w7W0LGt_iE6DJ;+bF5U-ddXT>7dlg8-H_W|b(nh^>SYD7Bnk8r#7~!e zcxSWpz0w=rHJyLyYqis%5oI2i1p8f=+w=|^-%R3-*luLC;@JM80}tEu&g!|!Ov7a+ zvsbD#u2V{q-9cf|I~&e_&~#39%K<1V-Iz8}AZ`MO20Q%-Uf)uM(bU=&g2rdl!H36iL0=+kJn z#j-N5LERhbL{aA8>;`VWY7K!Z#u}EIW-5_o;L9nB(UsPz$B-j(7QEi1AqQ+3PRET0 z$5azZ(B@gy1f0ddP1hvFJxhFXJCvxG5{VA192slgGyXtZ0;)TmsBvZRWOat{lbhj zdlj`Fa(QblIPA;o@J=3r``^{w#C41k)n=$6^n6{+)|&78JNr7sac|RtMqhNp&mF_2 z{|e_Jrx$gyb8@=11fK8vA3Byaj=u_1dlk7tzPvg&`0Yd1p^n>o3{pe!FNbvL_S+Oq zlmZA_)r8ybqSZt!Tn6E=t}y<0Qy(^R)A%Zu(_>>V$KCM6%x=s_Vih zG8`sHo(FbpuKdUlmpg*e>Fv3{FUSuRPTt98DywjW>Es3eYg=-QT1Sl#LDP4xB9C}A z1*ulmL1JKUj`{&f6AH;Q$!oPt!RuQa0h4wckCRRBYUmJM8O3zfe|PHbYF5y9U<}mA zf7&%Xq5LpVOf2@t$D)phCDi=rwPF8`bY&Zdfu3JOZ|*duXz$Wf9xUWd#!KGoG21qY zTx?wLnuFGN=6Z@(YGd=(b?%;(4gY3Ex460>ObXU!%-DV-e0Dy~qsii}3@R2G?IW=`;4XWT-jj z_u-?&8S;%NV5&AT;qm^)i1EnxR(w<+zfS#6;GRFP!hSgDGyc$m81mr+5`k-U_e(l) zddG*S-YtpWX4wxq-Yhl+Y6GoI`E%muWX|n*lu)Tla`V=!KWuz+yS!HCfR6Yrfkc{9 zlQ1T-XvvFtCElhj=k?Fo951Tfi6Wz{FK;4nd@QgRy4 z>t^f4EdM8$ao3dFo(obXx5~Z*z6~tu>eHB3;W=HJf!|(?VHUPA!ErK##X8f1U8Bc&Qvn^w?_x) z+m@!>atvpdN{tB?oF=T(7rG55bbE-j!OU*3efQbE?Lo@J{E#^(ogK^TH`m0}A^il` z5wgUf_nNC!Tu<@%12H(i^!=SG*`eowa(<_^P7d?SKxqOw24!U=ur^Nv;M$bBVeq$4 zFA&cW^12!|Ay_`<{;i6~OjUVy+rG>!zqXp2HTXz%kbP-IMro=uVUD`q-e%Jy!z%ny zcd*l6HOESCd%Q8KJGgOD)kA`qSg|jjcqbH+TfJ?!?MC#d3N)Wv)R*7$ySsM|@h|w0 z?1fwe1L_f|y1E`;Bik!Ls3)S&(Mp?~WAzI*;`5&mwVg7R2 z#3lBNkl&)DsC763Ydvc12M!X5$=!a$HTg1T2!`0QTPK|+zP22#g$ZeStt#)0%C7T; zHYC6@Q(jwZ3h!5J57;;E(xfRS3+%=7WWPS(1G#)Sf|S(ixNfH4qp;W!WBM-w`-y76eRuZIgfP3j@uMWxp&RafX?e;zW3X9P9EIO0%`|EYLM>y$`GcRmH*pv= zYhckXIr0Fpl57$yc>7a6e&TGyrRK8jr|Vb97xMoWm%Ll8=l7lFciE3mWQB3U$nl^q z{5rJIIO2{5>%0mz>$1smq`t6f2TYtr^E6my1578h&B{g93QiA#W{ThW0W9FHIMxA@ z?1rk;>4lG*9;y&^d=xm-{&Eh(jPkzZgF$Jm777ol#%ym)OZMBr%!sWgf3}5u^wFeA zS3-Nslu8@!zTh3?K3g!$@!!AQ0O}RZr7Lyh>G(Ss;t4;G1bh+*wid~o*|SWG^u!Lp zzVz{*s*?}9zJU!4W4QG{KR@}wG(q7-22N!^xO}E6N>hK81sqJ%gFbJ}Yy>SZcI69u zqPz@t73X`Z%IpHb0qyARk2_I#)SC;M*ZhUKO>f1WR9*EVpnu;34d5fh1>9e?8WKjd z{AWf(51k|t44A#nV9-6Wr7tu=FG`&on3p}kls$>27K4beOnfIj* znfJQs;LC=lwbL0*Gg`J@CHK9GUj>i8;K(?XX1biY@%ho2oS?DSdhTzo26JU7aRGuw z=5}$rSKPs$%-kGd=q^@c6hCl&jYsj+o%)%|(e1H_2}MCR14;osg7Y~2j&1NEH6kW_ zlesywCoBrrm~~Y>`OhoynyvLk$BAYW7x4Vp8w11Z97^5!_ji1~>1EXjkCBr&>tDQs z#_n^6Yz8@AvVK6<5Uf&-@z0!BEdM!rZ|P~R55)uX{r5ST<(J3N^b8SQtMu5GM2U{( zc+m`D-K!Po2iwPjr)NV;;N zt#$6Tw4qg%k_qZoH^<@HoO8I50YDdX@ed7U`wB;jy|z2|8D$2Izcu9B70#lmBX(62 z&5R>vPD~@6R$L95h82I3R7d|k`m*32X`(5nqp#1In{l)^BZ`xxNAPS^oBRAQgd=ww zfhU1ioi5@F64&O3Gxi!@RvCUC=(bdFQ}+Aw0>__CA=6n)x45epr1{pnAV^=(VMZMu zP0L1{+D+-u)Kw-%cpXwo=5k|VbT{XFRk$f_FsvrXxblFyGEtSGK$pMKlmi<b__aW)2t#+$FLSIfg(@IRltko@KPxweUWaPvFFWMCqSN;pU+s$i^r%0H8NR!X<6*ncJVWG4!gc6Dk@^5e5Wd@@aqd|PMa(g9 zBbL9KGu-;%dWk%9UyxO-6Bj3W&hNst*$@PRA?l(qEBtAA@KdTXR9&Z6yYxCdhEa4! z`gL(yjh{*IXx8lN4=e7~3m#kk1B9Pi^kSkbw%I=s3rSO?#HWW0j@S96xVuvzdVgfU z54QGm8$DP3lm8eYV+@9p1*LsvC^AruQ=uYQQoe9)a9-TbEQGdjhWC8_`?Pxtcl8&+ z(rJd_#xDpRDD2!hI4AvrE9LRvv*OoZVXB;YY~y0FJ3H2)q`ayC1b1LL)oFP1^o;9D zekf}B+pHPN82Us&3fNw{T7Z_Gval7cJvp`Ie|k}&J5(K@;P;FK222S5`<3wi3)bP^0SIEV$X>XM)%`kL~JMib~ueWx90oVSU8`f@4`BZ>~;7T(|Xe7gi`!Vs2HXsZy;L5$Ch*Mx+p|3Jd z9@qa$FaVaJ&4!xu-sLF(-+|V+LsN1wC{`ElmKc7vLI3@hI!OESagezopy-Shc-9X+ z6z&dC%CcTgX_6447peO=*{gx{*9tb&o%c=%(_8?0R2A@? zPT9DT@)w{>(j~39vwFgmXl@&-)US1aO}=H>EQ^1Zz<23_=u-HJjf2#$@qguot^Uj6 zUVjT^5+U+V&Xdxq_SXgHg!+_R6PlJA2nH+DUcl{m?`$CL*gdq5aKZ-KbdS(CBiv#a zb7>5K?g!Odh zTDA@f(WaI-o|CVhPa6h}5m)jHw2DwaX21G4Xcl6Rw@iC;wH`P}V%rh(eJoPmbQl(r zi^I_y5qY{isb_BqWa0GP4`@2}kh&KK!T^$i_OicK zeDg>PylkKiD!PRhX$ry(XNm)$GL7ZHnVzOI`5W2>0>IvO^uRj(id_NV&N0%(S>3s| zIuYv6J)Fb1PE27BipDNzPoqZo)9<%HF|g}r#cDFhiQhNoMs5vK9+s~R5vE^p`4vv9 z-WF0HRlR>~c&yvEJVYhH$EQ?zG?>dRRcA%D^-g6Qk1KnuS`dWQ=0h_v8M)U)6%22< zD;f|x?-DQZ6#l_+pVK(pZzL}NS-g*m!PXcs zl=*X?V3V6=Btb#Jjz=1%rlu}mgGWR(;@SSNbtX@iOy5po!9+(4(2acgQ|YjUJA3Q3 z5R!4FNTww|IJ5la(?U{pr2uloO*k&q13&xn%8|~A9EtL2Wq8*eG*v)KtwbS5(xhAC z&vo{@r?q}ycP7brmnphb+9-0}H(7W+UF0kg=4Q(l^J<6l5gI6*vnES~`8{K$TbU7X znn8{k=Cg5gHjvo(G?OMB#agjzNG_t=ECvv?rxG5Iq9LOZ{tR>SBP{A!!Ja;L%9t7F zl=4k>(tM*}y{*d$C2^JUOrt+{V+;yWQnD3eL59$VFTb&L*&RrPzvoB7PkZWY^WC=) zQMjyubd3z)|JQ@wSjgxQ59KB#YeRxarCS_gK=8=Zmor zvCr35L2dIvG)X*A1vMw0HqF@ct zo=Ea8zJQFA#IeGfDA&2QBqZH2C>||3SO-Vd_qS<9!rT+T4Zy4Le2GYNz4YziH{!>+U$m@hrBivld4DmYc<_#`4h z_NVhFNXs5rAlI=`0u8{RK9OeFwZW7OY5F9QW@q0^^m6n7Dbh)Ro6!UPD8N_ipi>bH zXh^qLC8rHO0&#eAx4J^KSP0~8^Y43~v@KVVplhC>=Vo`m05Buzw7P<>28=aSyPQ0qI zYzUf~E+i8%LI=kl)6n}SvgEoO=R8ISt%D*WFkQK7GL#{QoCdXbUR3(?ll^*aZ3Rd~ znwkKdK(UbGO?Iy(a{^7$OXAy_N0~AuFH^nVPs{!zkg7ej1Pg`hd-@h1XpU`~$+kA% zScIeVHQ55o=&&30vB{0j)@p;Yuk*7tRkLsMq}^{~B6Q~pg#{ak=PWH0Y6&kH@YlAN z$TVLBPFp*GkJ9ODYa()JE^YlZJG+Uoqh4HmA!K}fvCF}Y6T!}61@g!_@@jAJI{&_V zE!1?~u(C&`@DeL38twPGUKhDvwLBZsj5CXa@*RifcrAQ<IX*Qve4MFiyG6ng1i`FVOSGF8_g?v)`zQ4(N^x#7rG0b1sp~3t@Uajz5nZ9Z*HSBzte!Hksd=Bahr&hI*+TQTs;QiBbF$RbG zT9q-4+q<(?wm03A2yuE!p+N)j=ackBe-570eHz~uI@BgxUS96vk<{7Vlag{9@E`h= zmP)+pJmH;pBlzZXnSY-u?oa>diQ{q8DkMU@ z%ii{t;emtaw$q&c84oqM3Yzrn526C8@3*E*N3yz>>Yo{KXoNx!PONdIVU;C6g7Krc zB-fHfC@yqK#FtgJ*SCILAMT(3<0wGPbTS&+>&is&A4-#w!*au1MWu^BM{A0&{8BN| z3X9Y-<2mkB!{Wc13zbe=hWAA5>vK27l9#@`iEtLS&g4rpXpT#9z!Cs<-;axrdM=HK z20T}*V5*~YrJDD%HM{t4OW|&><@Z017ej!^fu~CcE6}b%x5*Inm&up@&E+D z-fIxa-L(IobdR36)3q^QO$U&7sFKJ*);R1Ega?M4;8_nMtx>nbUI_a`Q|w@s8uW>d zLR&6Ms#rVL-Uo|(DPq*DXU3$*WZ89aH=jJbKy3|G9b0?awVbptndTrmgie0!5K&5_ ziKpk&a-8biv{)a`xmxP6+wWP)aK69+%0KdI^}+jj+SvoR%gsK1jRUNP^mD&I$(NkC z2taJ3Xisxl%bHr}o*?^nqdXI^STQsUY&{e8mWFc-;os1X_{(ftrQQiLn z`r*TF4KGG$n;H?`?6EstCh``J|8+Z%-XSo!(1uP_j$STNcDrtW=u9O8&dTnBnd9Dy zf(gAscK@s>U?mMv`()odnbSN}xLSGYBL3suI-6K;E;^^N1Cdqgsm8mqf98&z$UZ(d zT?VC>$M?ZpTMDQVA*8t?=gZd0W>KMQ3Y835Xi!CxU6sJ64rzHSmrLgF-PmkDerh-H zLmK!3X)SC%)EBa5FPLr(*h^M_ny6%GzyW?xEo-UA&Xy>W96Q+-C*FR9{;PNkctme*t&bM2J>UC|4e z&s%gsLWuD7H&Y)kS28F}S;mBTmvDOJ>3~xsv{|q8yZqkwQbHK-?EH*O>wOep;*~8$ z8KVmdS+2j^IulHsv2ueG=%H^#;HlJ^W3+}=ftjFvQ&skKq%hRHN%it47>3;lOls$n zLqN?cha^t;@BidKBqk*%cN|B9xR3X0x3179dwq6aHwQ?aVZ-?TlrI zn~9(7Px!PPkk0SBblucd-3AM_UB_L z@La7rz|-*b=C@9F=T(zRLgw$~Z~_7<<%4x~)HxTfFHQ;y`invNbiF@bsOd;WpJ8VC z+y3YX_)aze8-RirOPn);gi?%p^Tzlah0=gLz$l-9j#Ua{CUd})3bLZd%hV);w zYElfBH@_=h!C=)vIxVy{hyihd8tzQi0Tej<-VzFE8()261JC-$@w?wky*p6}3y@bG z{R;c!P3T-hKCLppf47r-^pQ68FSs(YBfeF9pmLd-kox_E;b`35PWnnj)zYFcw{bHq zgG%}6Dt8`)+&`Ueam7)_XFSrb45q`F?zBJdw$O?uz^cxNdp|S7TkJ45Tg9rw(J)7j zw`(Xf&ab7f?_#B**RtAd#Q~>XNIr|v}}*6SD#U5`Er9=ANwmo5rO9{hcBT~RS5HoD4P^H$b_Y1T^@g}^|gsL`xt zbc!rGwaRE{tXqGP7J$}6N>#SP;3an2SiVfVUX?w(CD_f3_Jll)fjQFhqag(L%T8!0AQ$aD~#V*J(x){q-LjNRg`H)b$nof|a;3o=6$Fz{TMz z^iRdrE&=b!@maAMG`4T$i|_RB!h|^1zvs^!+uCY6(M+!;$zN{E>a4uJNMOW|r1|k~ z!=ird)b}XOWJD?pu!A62Nsjw!;hPHqiTe7S@M~%lJcXTj-_N@g#r~g5@49mfS)j*F ztR=!~Lq=NrgOZgDzSG84BD=VA?{iys_SImPAmN~7)$BFFZ<%meThP znk!61BfhnjrlzL4Fg?;c$!Qm0s-*GHUxVj&TCzb4Q~2lEzM|(A2e!{VsI~-lFaR>h zRzIf-+!k5V6bHZ`4C&c*A6-Z4q$YP0iyXaw%SPsjFw(<@AcCL>rpAjnB_FnuaCecr zv2K)SR6o>&&bv5AC8Lqj>}gktQ1j~8cF@`Cp$705?XfD1Q>wl1iV+cuSv>Id^ zMPmaZ_%;`cs1tfxkyGd-;thRfAqU9x$t?X=e(L+Jul2l^qh<0N60dH(I<0?6GXxql z!*|X$h}j4nW<8wbrkRG9EJZa0#Wa!^D#$N*2{SAuk(KZ9jsFT7HUbYMBK`QKeS=`^ zCA2*lhu<~qPGnH@5F5z~qds=LV2wI}@$^{hoZprH;{U{VXixdv$4e|Q1QfjKb+eCn zILJKq_9OPf%Unvd{hp5{-{IUK@2@5z!|PS8Y97FfaS|309I35H@~scezwE|L_WXL~ z`QAcQO>UxygkHU0PEH>_iwVTbG}8}0(F+>b^ZeKlfRWCU4Uu0_Q@uzVu=@d8WGrHT zC57_iHjs;h&dpi#bjIcdT$h%1^xiIKlF@A5+0WrCE-X)&{58ST^x@=)TgaAMe58d} z-^+)Fx@lfPFqs+jNNr6_<~3`*Y{84g?)s`6ytjAe`7z%a4l=LUh*;-(Be%9Q=S<~7p-`v_l zJ9*xq_}$3flZ0R0_@!@yN#VL)v$B^j5m62&gbOD2_ZL$n?!4QX{4TdMygVTH`iKpJ zJ3-sb%nf$S+W{j^e+4y%5BUA#QdLiL=^0YH3 z`VE6=Q4u(ALJy?=zWg^_ca&?u>Cw}Uo(p(5=?=j9*9rjN+kBvZBW%m90)ds{eT_<% z#H)S;Pzf#P=LRKGXJEjCY<<951cQbD4pCXL22N*y(*yB|x+|7In8qsxU*6Qc44jZK zbK2Ddo_>xW5a{xf^0>7&MQI0c!#MCo#(lq5#1c4sD*Oz9EqCM&i@sM!wzYxNdPd7t zaci>Z`P`E{auY6Yyixs@9(?CN0{A{GA=~oPVH1481<|Wh%dJ93{wp%xlWj-nAm@vq zLe88l^;7AT4p``AgRWaiM2cAgxga{H>>tum3ZqBb7=VT zKQ{s;s!QUJG=R+z$_WX7UwmOn{4xdvA>r65aSO>KL9b-;Pti*kAg6{adneX|fEd5V{-}7UKlOp1EAPh35!*%N1%KmZhxSze8aR_GO32#;mZ?c}^ z*L!IdXh@1%BYADvW76#g20U_CH*BnlO-ZuOSrle)CP^jh^}J1UgHki%c@Y-UNU`=( zb{t7wy+FfwQ!@qvZ$DpVxi2TjP|y(awq>PK>8UQ-q{?Fb{7NUUbDLV{cJyg$cuRDQ z+enBol)At^?%eFkgh*h{b&d+=S1#TcVv5zpu`w{RXb5auK6Ppf`@SJ(*pUkPSJqm# zL@siAyGMm`A!+w@eT*XuE%|o*PDB={n9QV^*x}OQ@-P5*it;dZ<&A7yB1I&7uil&M TdDC;+?IkeMGt;fmc8d8w)7HIR literal 0 HcmV?d00001 diff --git a/media/atree/node_1_blocked.png b/media/atree/node_1_blocked.png new file mode 100644 index 0000000000000000000000000000000000000000..f7b0e5ad463971b1895660ba297875f1a0b14f56 GIT binary patch literal 5066 zcmX9?c|4Tg_rEg+gD{pP`s6z;V(@|e{ z{qkM@N&Y5RuYi&Pz9p&vbJa4`0-*dk6Um;IDl_Ga8W0)PXpucLK4 z*mmuAtUvFMz|Jl01Q;6V>u2l4yq`*uweEIWt%@1{T0Wvb9&nDrLCH5zTN@2rldKk% zsGj^VLbw&(pDNi)##wpFwM%y~k;!a2*i{@dud3hPu?;O?j;%EfoTVgfy zXIZYpgOT>L1b{4O)ap|KXPK=B<9n|qZ6kp%|p?s(*V^i{f z(1@*xb1Yf7w@jIl4?3?3DLxCIZ3&t4tj^mci=O(D?0=#YUrRu9wC#B7fhdizpAYo8`#cWY$59 zx(;*XZfYS$6&IdX%VHU)W#uDVqQ|?AUO0_iHO-~hO3CD_)V!;t0;?c?mBbJo91u=x z47W&bvF^eNIT9mPL@7-0Hxc-GQ)SCwk-j7NV}{?T@k~&uc_nq>o=`vQ+u5s56+BS) z@EJ~|NNPLc+Qh@$O}2VjTCH>e+4kpOyRO5t7a~kZ*WSoJLh%TQwLjPKWQRR1EzL%@ zM710J5!D~&f$C#@Iguvf@xlqC^m<#O$-`VweT*?xC1)s{P(`n^CCV|(4%H7;^&S`XY^>6o~7NA$=>I(F$sU;z87QEFNjX{Gst<_ zQPmg>EB=>YzQQvyz6^>V6WkPD=3#IQ*V>}-j`2VWjg8=eIs--u5dajAX&})bT_U}t zB(Xwv_6oFjpkRsPr-@KLu-m7kCeS8WIcJB`^Q0c6N5w{;wuz6{mOktArE;wbfZiP|y2y}F)H6YuuKCYq zq{eU5ts>*ezwPE?V{XxVeh2eV5pMYbiWBB(|n1JFT)Y)uWS=L2gl%% zcyVc}F+0AJm1C!XY{}GtJ^dz`UzLs4Ies^r!plSs@=_Th0WBM}L>^W#b~+iSkYRd@ z@zm~v?*5w2`3zoBzcmvhml*Wvqy2^A72U&rg~9IUQ+(wQS^gA!{E^ZS1o}=OBM!lH zJ<$zVcT}BfrRi>eku`s-O`&Ko>grH+P(4t9w2UKBR>U)dEZuvBZHXC8H`34a()(@v zNm5UI{MB+8Xx}ij&$6ESZ;NCel&kt&j;uV~v!}9A|R% zb+`*oaQFRNG#O(O#W?SZc-yz$C4ozK^dF)vwZX5*M9n;VJ9~V9ev?C_xu`NFhpfLp z&SD-s79jK=6VNNWYDH?sZp5A1y&t3CHuoW8dj!WP0fUYeX=ITPW_R_%g5NXDKA1lVA}>e#vlic`Z%N!ku2F=^ySAGB5*p_uj#Ol3 z+|1enfE;0!(vfVxC@_p_j-IFgL4ZyQ0jnW}wHZ~)ZW`a<1iCz`?qq6>0~iuqh8K2L zrSonzg`uY!zU=W7--hD%aQw)Ipy4S?J=Kh}D@iXtJRH#Qzf|a~il+ikF7plr!GEoHR;xr?Cs~j_c%ZxVSrNm6iW@GsNNH8+uWC` z_}_a-%TaU3!cN;N$+e5v-M}aKpV|=b_lx`}{<*xLmwVXBMIAD!1n9Cb@E}~GNQ9VL z{ylX%Ogz=`^N-o+(V_n4fyqQOHj{h1!StDY0izIzv92=Z+|4b0q-Ay?y9QVA?F_ts`8Jp{BeK9oVLR*eblHLhp!kg(4-Ca`aD?sSa#SG zDxcvfn8m}7*Zx6~xNQ0|B)swWfSe?><(=Tsy9=-i@2qC)?ZXCtRv6wfIC_5?*4D0} zf{pu87YTd`EJ_tdrCXmbcf0t|LhQcnQ55r{;}Zw{rOP5g88u7mvkH>z<1i1-WU|c& z0ojMTn#4A-@Wu=;m?|9HP{@mlGa*c;zI&erF%HWZl!4eS>!Qdo{H@)94NJ|`0Ymm{s#A-hS&*%z89jvtAieI3mZ+H z4qR{Lyi4!fMFiZuYoCyEbT0M`zR}{KPlr4K2Q79mV5bNLim$dHiZx|YVaKv?!^-Bt zJfzGVjopU^i3PbSCcAVRXiEosOGT%hB1`F^FtnwjhB{=1_(p@W)m1;?1o!>@|M~tk zHRXS=m9zd)Q#>g1y0>i$UaYP!%x_gz_z!xO!diBBtNeRqc^AAFxeScQ2``gB$t}M9 zMF6rndxlh1nY-L!bqzzfF1Yiy-@9u-{>c~43G4cbW}m+TDDTw4{2D?#N=Ced?qd5s z%j>4o)MW^F?5urUG*P7r_(TBTjb7dXIVZ~y83|UwVwD3FxV#=-BO4YbOH*<0zB4+- z{4(twEpT~EImp>PzAZ6uVfz^$pYK^;TG6JS9_huX%4eRMwt-YqG;&{Syeq3xlb}nj zBe13&H%aaK1=r3RCo7pdKqfISrP)v z#G|PjVM9W^e{EO0d)osS1wJlGB8NB9G1A6Mx?0a&e<}7bHug>I#^QLsUmUqhgT`L+ z!TFsU_IBUfJnu8w3HPxpu97oyQ4xO?H2Am2#A-3n>k)99jYT5!n64>hkefrw<|nn8 z!hJr$r~i$TIceqZ+Gm=qWPJYvk|+NcT^L6))iC_hTx+0 zv^GfWF@Ijdunx^JE4ra-@Nbq1H8VBJ+XZG6(u~Y*^>HndUmqXam9T()2+vU3{7RVD zxtvyy0__vZ${7sd$p^}sXT7!&}bsC*No{G1OsAy>K zB#ljHh|*Nsg0fS-S_(?xl(9Ikdx`Jvr=isojF7kiT4dnoVoNH z%13TzI@HMHbD{IYw4*hj8-yu)Y?=HB@y4HvZAO`uOFvK#t%~byy)SxLPKIvII_sZc zQU~9}M%pHkTRZ(L`VNk1Bi&_$4)QGKV@t0GK!qz}DF^EGy`>3d}h2l4pho1VH^%sn`p7a?; zjL=rOXEooDH(=>`ZSf?h^htlKi>)kwSMlKAwUo@>u-`iuj%8{tkPiP5|ia^Jwkit4YH^{YWgLMht z;Nfg$lm(nND0~$!@rhu3&-|U#9o`*+73CzL`(%m=p^yenJ{AMxM|fPFvSLV`Q0f5d z*}z=X1o?Qx`EaFCw|+BikL>BXZ()0t-v$K_u=HIw(2}>-^7R@zbk^(d+vs+EVB2;6 zH73H13i77Mi@+jp$<8lK>SzrZaXE`=^G6I2Su?$Qwzs3y-&!t?+M>oY$jOB=ki6Vn zX^L%-o-@>4jg;!cwa{kdy0D+&TuTX7{+@ZM%yys~-6YrRLvhv9Je(`~zO7(N`m>Tx zJy()AFWR7VcKda;+XZTUtKAgXqGG#!(gLf0l$!luHOjzRIm8Pl3Ax}Fj?mR6;yz@8 zxf}#RV_%$Di9j0n%8gOm2<(~ZK2nKnsoS^G2@BNvhJVZjgS8T}45@ne5z3%S zX2`JZX*qUjy+{AukPJs&X!elcZ`s015~-KwcqF0c^~82Swb$S-XZXd)baHYYrDYie zgufGw2iM@tur-#OnaeK*23TY`Ro9FqcNd+1F0+U3oWz>*XNX+z_%Y#9I=OIpl0^+|M7m|>g{P{ z*-6z&#RlIUZ*oebd!FviatZB(%4QD{N@WT(L%?SrQb*2JL!u zk+b=_6_C6F3Q|&LE%Z+TUAR#4@NJTG!M{mmUmuS_i>m-mVf^iDj$4J<^mq?$Xp9hQ za@dL_&HN7{W|AI@&Jq6y`RaCyD1G`o`$ZV17QW1>fM~`;lNEUn zBz9Z_P%^~McM6+=kRJj;R@-Ao7^+0B4VIWPQLvVA%pq-@v=Wj5cvXIhjKK3uz z&Gwg;%~o7gBSLr?c_y@TiERbnzxkM+8#wx2Apkx)!zCkIWX}yAeK&yP86yEFmiYyg z3Rir&w1(9^${Y6(i8uvyyW`)3JeJ_?zG$ zf5dwk-zUE`Rr$*HiHwnq&_Bi?gMIF&1j}9DaYh>F>q4-qiw>)F_=nujs@qV`;s~g8 zaCu|Y$F{Nm>oZkBSs#Xefkz`^>jgTTbuJHW#fTwHBFnjHSVH|? zanZ#!!e&ICavK^NGGA6s=F-_S8gn8a<|K4YgQuQ(ikH4%VyXQ%ps#yVr{s!VujlLee!pI?_quOwX~x4T$_W7AIc;ui0|10ogaE_=*6+fN zS3di-n>J>Kp!~D=BC7)T#aZA0sCvM~@ML4vIfBfcZUVsje*c4X2EOtJ0Nrug7-tvi zw)BG|$Zj)|eP!|>e`9)lJTJ_;;G0JO9{dfWDYHt1p7K|;cjcoh6ck<2G zgUhYElYQJpo6(Oto8D~h>_+cxPLvzMqta3COn7G&aw>a9H%jq#Sy1yG?kK6hTsPY1 zVe!Kv2vO+F1-+IrP0Vcp$v2 zE43Oc9+W=@S1GMKD;R0bsVA8cL%29>7^?Q^*oC!fbcEg!D5SIEbSNZs$dxV^8o&*Q zrd^C%=~%qz_txyESfXmBkXxxD|9xXEH0P&RMl}0l=$5*a1GuqezCkRwF=S7d3-evz zhKWy~oTBhO&Na-HGxTr2q8x#4X$p>y8RL7tTks+gDoc!G))9Ot91>xtIGA_lwu8LwjWIo*{-V-1qV z5Zf6aN|7hK55jR#H*(f-0=Y)mdsf^D$h%#_a9p^dT$HNGTNGk2quYsv*)MH{f)`(l zT`^Yu9jD~IaDcH3XO)&>$9d>m?M3uI3-IaAl;}VsFi_~ z>;x*ie5fXToIxz2;}qPuA@#eRa#87zMhvlvtzpn4$ynu1wSrqVwHacNblUwwIu7He zJ^b{Vjx_@qX3Y|cG#9M2Gk^IC0%31{u&`els6W<8*XD=dc=p_*{`V8N~}~^bLHj zXjLmqG-u|^7I093K?%xPDr}{^pm!Hwf?oTSUX^DN!PJDy6J!8k&+#p~QUS26kCOk2 zR+qt8nvT+VC8t3)M?R2MCk>_)Yh(pj$XXxL1Y!|@!w#cdoS7*`G0(ecRHmWvO~rId z@O&a67Z}jO?>Wy%&7N?se--mfA3Oz=QI9q^1V zyeN<9(NI60&p6o8uIt7D&}}_mVk?{-Ei7)mS=^xNlpJ=GZ@p6Sv&&vvlX1lLuddZ} z#xw$+=p+Jd+$}Ob#Ag#klLi;aCT*=72mMQ3PXAV@Kj+l!9MS2@{CV`tSO_7^>uGS< z)I0)~cZrMec>7ClH7}q9B9*u6l3n~}2kUB|-C!5A$V^@i9ZDaRXuh)^T@p@;n>ff| z>mVOFe+yy?1vPE3cPsTLbPd0YPMBm4t$S6p1%J*jHgbqMQ>M$#2gj`10TR8e-K5Qb z;N#5INt<<5!H;-K2qWO|7=A}5$~bY%-2~;>m4xbFd;h<&L#3rkKA|^n_gz4MRgBWB zXOj~v^3E>J7JoPj2K-VsLRyU3m0MG=l?G`yA^t6MFY00BKY?lm>ymD(QDbhadFWK3 z`z`Iab;D9O+_nO>Beq^5pc%clAz}Me6IfIgqtkC|MvYeWgt!f5YUTYokhU&iiV~jj zXVFY`y3iP}*RX}Rv#L+ly`iIao3Oh|ACW&kAiF_0=wpaI)H;`OeIxMdRkRCQokiZ)C4Ke7rR*-!1%j(KOGjZ_-V4yPAs~mz zL#6JuWT}woJPJ==7g|lyG{YtvC#_nuJj^GyKV_p>5>t6$dNlz^`#wdXaB_<6bmBr& z+1@>Tg6P5$^yh>)4il*A!uu z@JfRAY7u>D1pR|xY0y^sBjW8oA|G*O=g)9O*xb+^Z*ot}WW%ae&@D3bi4LgUTctth ziviJAv)6k~EnV#2Anwh?QPXs@kL7x{ zfW+*JOC~O_Os~tm`#rI}*&nce=PX@<4&zjzpTAUO@RE?<! zO?!EKNJid)@2<;sy@Pv`5!o^c1hp+y2y89lp3BbA^H!Y#v&Y z1~;ZoY+o&7YN|o?f39jaU1Ji2amW3E2b0(yKCEkMVk_tcj~cpAn|WTvMb`A+|Ll7f zK=stO=%GUP4+zG+y!n z$M(eDMBAs3`#7mG!Fx%Q{L*{fEIl$pn6#RCxUAhY*J zs@QPkXm9UMr8Z^LbWTY6-Q_KJzHLFZSdybnRes^XE8!Sc>)b=l2m4E93RW&FafF%? zH;2apo0aZ1O+h6uIIbfbUat~a|DUK=I_Z@R>STDORbt>YY~jEYo3P;N`d&Xe=oeaVpEoBekGCC zDF8y6T8~zG21_?NEj2M)VhH5UD~*|(*v_&jJ5-aniF{ZrK;KFh{ebBrdEo>zGoNvJ zAb^QU_n|5_^;bF0hU;9jjGDiTn_Imcz$p;=TCqKR?@~v0_=)p@LedS-VAhY79p&B{ zV7NGg`q+(tTvDNo7ngSxiDZ7Yn+HOYLrhC}Ro}l$%SCcSNCu!wRul(R7h!}zs6qi* z%-CCi!}IUO!8XpLM^D&jv>K!sVE7avk5F+~nQ;y+E(pM?!2#g|3IP5LJ@A>QZZO#U z3`>Y6!uXuK22s`cW;IPwQ-eD7_V(UWYVhPB-IF~+!E`|-$ck`+m;V6>Hm~F|puhvO)aWXlX3utUp2FR6vCYE!1Kt3ASp zWj_GcE1wLQe6{h_!kwolL$Dxz)Q>nCOA-^2#tUAe1?HHkhjUff)LZ2j z=&5n6j2%%6ddPo2UbtJ{#i9t-MNO1#&0x$3uhdWUQ)U7t(nX-y4xwN*jO>Qh!8~~qT-u)p($(AY9_tMN?qjg5z zmX^00{6!=T4vw>}Tspjx{W*82cC!QT1^O%w%M$aJ>8!xgR(=TgW$UJot9wtAz@qkp((?yrM> z!L{M~Pg}N%g=2(hf_d|O%MZ7e+QOuO26Yn=QNJYlNKyeZ5gZY$|8()x5mOQy)F3g2 z<`!1G&M_`Fg=7BgSsUzLo?6}gmsj(}3JLPryW*CQPEKyZ)SxOka>B)dLa2r-|(UGgjsNS=dX`= zyCo9kK_z!TAy6%Hu1i1zLm}qg=*i5@SYyyCsCS9nwZn?qK!AQ@XsC=xamU<-w0+ua zc-z*l!#q1E4i=#5P3l201$tYZ=m(apeYW25UB+(RQqQ{yqDhwX(~)mAS6Rp4M5!7s zhra$d5`D>hqw<)=!oXT4+by2A$+{i~vH<2}@Rsb_^qa|#y3pfiFwwt>w!Yla<3kD! zKHDiT?L+>K%fH3C%ApIt|H@mW)rHH6s_=)mb4E~R^8(zBY4gusGJPAgfg&uJia$3W zZaGl!R{#0^*xz0%IbV(D7rqr)719F;G6WvwP2x*kvx6_6nb(iPOkH!d&rF{BhhFEN zF5uFc$(ya>R(*EO6Bc=OI-^!`T#C+gO3zl4A^sOD1Jd6V9T+yx5F#(Yz`S&NIoAdQK%A9Up$llY(8yI=@!!U z<5G*Za4s`9>n3aJ&Qe|M-CI_4$5!VgWkzaMB`3}60$12Bwd}o^(Tqa39jnEhXavc2 zLL&oNv&aEv&m{iE^INHt}^*RGXB@%=WU5Is6WMxAIiJ}RiEZDPPPPXe49C~SGzNp z%Noog@IXMWC@Q-ehREY88$4w-~_l1(|FrVC79W->NY+8)d;qqs;SW*T8lfA zjNwf%^uJKVRVl*We)mbh7svWX!`VN~*l7GTiRgxdEv9DWEtc#R&4vzU+N#qoir@bb z&sUsWTmr(4ATj>E=W7*r%Mg{w^uMJ|5Bz;ZDIv|tBbyB0uN7k)HdX1DxZlg7 zmYqj6%(b;zy7FlIpE37K&ta^=Wv{rTy}|#w{DZ1wXJ>u3P7wd9fqLzAPPu@-r@q^e zd%;PZ1Wd?p!89ceDPDY~NEiK}lVU}9TKa^UTfS$o2z@-Q@`3UItRUQue3AQsyJ^oQ zXv|sit}@pQv!#ldJPvl9tqlzW;qA=5m1JDsa}Gxl!f6R8h@<;cgs8gB%aDfLs=G z78D$>XsDcuejJ!|l5Ccrxa<;V#f-+y+leho7~0Ii;+S)D8Z+p_#3}8Kiq>lE|S*ZkiXH99xUiw_lM}n@7GOF)8Zp74~`Xt?=;YJ9atv;IM%w^jnRvT zkWo++B1$f5u5LfzS2Wwu`m0|10Q5)1B;p-SmPssnEKRs@ zEEt~~q54K4SVn-=znipUZTm(DzBBR>bID`>Z1-W_Da%p%7#N`Fi%^9_MrF)dHDRC- z44cX!3AX;PZ=Zli6A7cg8V*zyImj4MPU2SM-B{GVjE9Iw5|K@wl_3ySr7orDMiSe; z0jcWV?UGm)3LN5BSheCb^-HE}A16H{r6%e%i5>KaLAh~Qp^IGYi<&!ks4(5)v!)#CT>`p<>*8lgya>ovtYrM_FbcrHk~=}805OqjO~w|yg0 zI6kJ18>9PPtpMhhulN{?IEqu1zN-L_dEeW+q1dy`2Zs~X?mC;t#~jaDdKxFxD{gz` zG`vGmfUTnA`c;&h*6$p>s>67!qxA}RXF1!-p|SVD!j&X=tO;9RP_r|)$}6TKN1UA- z&jBtjU5PZ?ys3m+S+kz$_az{n7q9!qP7g|jKKn6ij-|uXOoXOPHhI5wfX)K;c#1<1 s?$ARy!Mqf%L+kGSaOTz)YG4lro;CRn|E5Q?o;bm26HDWALyy@11DHtf$p8QV literal 0 HcmV?d00001 diff --git a/media/atree/node_2_blocked.png b/media/atree/node_2_blocked.png new file mode 100644 index 0000000000000000000000000000000000000000..97bcb14caa107bf7d44c1cf332b2417cb369df0d GIT binary patch literal 5111 zcmX9icRUpC|IeMnWknx*i$Z28WZfAVsjMQhM_G}`ndi)qoDoVy*`s71l9iAV$=>Vi zkaf;+zw7(^<9R*L`~7-9@AbT&_xpK2F@|?^80om_004}7x?08nKqyNHfYVSW%cq48 z|3TiyIvU_pAMYv!fIU*btqwprmY!rsO@Yrm(KYu5fT``@fOL2kIs))toSv5YT|ev1 zsTgmbW&e&H+F9yzvqFilw2XecDDSY0)TQHMrhJu><==FXzafeTZz(U-c&PXW|K5@6 zNOihd@l8M14+A@sggk`Uj50?%a0J?-X0}A-9DiweaYH)+c5l}+>9gkr z;Au<}DIcA(4|%~gop7q}-GXX69eMNxGVr2ww#=r}ILBC0leya$AX_#2=HJ50JdZCv8qDAo~Sba2E6Le7HMTLlyhra>kDeb5q1 zU=8}>w?a3%%=7v39V3FcIK zo_{V=6NyZ>zSS{buswGpO;GptRPJ1)?3ysEybqOL2qcaOw@Pma6+!sN3MA^e!A16C zOi0m|+?s+e2I;LjGkN0hq&-J*^fzq_4MA~(SMxd>xk9j{Z4nB};<;dSaB%y{nHniH zoq$);Z|3OTxqYPVI86K+LNu=IDjw4}?T#J-Sews!*&zQNkEY)A)J+Fyb#Jx6EJ6g&+wn4s z0LcU%&g9j}3zhi3?=7*s85?h}eY?>wG%E_kPC1Xhc4nfg65b{Rd02jr+P$KZkUY7A zb1bI9%S;tHVwVIPglRi2jLC2~p+X)oVVPW;gn5ag(h%g%p?Tx1j?Q<-O9-ju=Xl4$ zB)KNW5xab`_2*}uN^s&GqB<~*Z($4&19DD#dwbk&PP+lv3uQlPCxzW&>+6o33}Z0+ z-s4GhLsUvh1RmzzA5Yvr(TPy+9H&NV2G_ISr$z2O*L;EYb+^v%c(i2yC!N7myT@~W zwRx3^pS>y3N|ZtVW_N_TZrB<$;0(|v!=2}BR1Zrf;}8;ct}QC*lFCER{6C+(EZvwE zg+tj(KsF)V=;nstiVL+iB2#AOo`l54JU!t(c!i)A*)IV5L%ibcPW3giBG$_Nu?0AXvv zQ2Wq2q2x$FzvhZF|LxkRz6Pl^O+HFto-6R6zZ2AcX8`^b@~gG!ioc1+okrHN)dt+y zN43;IgRiMWjkGXzERh?qhIoFD>R3ukBOB2@omR20t*=ifk$^+rspb+%9=hfBu&RLvMq9?k=4J;$>CY5DlEQ= zW|a*v`VG0kan~(IpYAJs1LS#Zx@Np&5&d3GkxJM6;iT?VKLe<*qc=C+e}k4D5#`5EtNFAa^&C_{+5 z<270a^~0XE5w?3$Lj~4#&MqdWpcEBX!bYT<_t`X`=osvr9IOe5 zoq}E_sm`C$O{Vmwe#7PTE3BZ3%P89TYx>~z$XXTt)O@+-QR4^)e@mIW4^ zLuM>F>rIc{sV!Z`hHB}+I9a-iuuq4`#C~XEr~BD;1WmiI;5|W&TLaGIEO~@ixCF^w z!!wEaV`KfwySG;;CzlWSR||+9na45an!ItQqKixPWltYwH^@x|dxQQ{RQAUvbneKo zGU40U-GdL4>FAbH^}5x`249LJ5dBnlf^rqU;&*EoEz#qpEsXg~tEjmZN zKrYY)KXQv&DX_R(6j&BkpL&O66+d`ZFr@X+^xYf(uG05!zXL@%a={5A54DxIZxH{& zfj)yxwth&K56PiKoOwMzYn-&gk*K2F_J&&lj*;HeSH|@r{G}OWI*)eDE2A#XppIck z+5p+ro2OirQ6d8i*8=2BeN4{+JXuNwHMcaL=p-`OGt2ho4bFCWW2h)~6^!=}gh->> zN`+$fy3O`VMy|a1q|i~#4(X42cXPhV=I`yZeH71iKrITNoxqUv0gL2cqt__ByG^4O ziHq1??sOL*OZKdg-Dl7_HE|5^yK}K)S zuT^%G#Tw6B(Cg=6Tw(5e_|QG^;?KS>B5&3(=9(5Ok6<|Oey)4a>`;EvTdp?>Zo2=e zUhsRC;ewQdX17o>(_%4oWmFXx4_8_!q`pBLh79jg$r9AB^tvu%!agILJM;!42eI81 zZ;l!8et5&<8~Ikvk$M^zy7cqRTwpv;b$o;8{MQ1dkj|e=dIfxh*AV zGpB&lsb_e3viKX`>f_>OZ5Sp|fJ;GNSFZ89gWAuu`rj;oDU-Y$$<)lQNp%ad1_vE` zD|zE)w_2Dq!`mi>n*{-HQoLE5DA;Td1Gbl; z;4>!#-0vZRQN{a-uJ~`IE$k_-?UG}?M4+fRmX`BA$vj-Dcu3AB#^pjjh`*V_)GYsH zxd0AmmBWMoU*f`#MDsAIJC|UX^MF@J)Tt8oAmeU)Z_*US`njD@im{i*9L&Y16x@6R zFM-t5)Se`(n@ho!Fdkke);vGlm+OK#`b@tJZ?mzCtd@d6PaldxnZ8(ix{`F_O@EdI?H#1=Ly{?cEV7a?f zMTv{`cBE?w&Mq}U`}x=hmC-tf;p`Q_tuk(vv>>SyJ?OgbY!&-l`C+fxM;a6*2CdJ2 z_NsCpPLMx#y0b4Y4ANDm&9CX}CWqfL`r{ewG;F8?u9}Namu*VwruF`f9oh_0h9UpU zq>lrE=w&Yf^m`Do^oL@EGys&TUIhX7jJ;;Cg3z74!w^f9NfMrdYF9 znc|~ZT;8YoPoQ@U8q)KroEN&Qv2Lh%^@`1|SrDYz_C}v*n=8kqtbxOM-3p9QDe5{jzpX zGlLOJo(v$Ks_MOP*OX{&FZX=uB5dCbi9 zpvcr8X>Eq~#2Tcw$4s}c=2RmFi3(mO4L(4%-+>3XDLI9R1@pa)&{v&6(?R%tDQ$%WXpn*H=a; zZ#dP#u@YZM|6lCD_`{v@pvsdXbIsRP1jPL#nKALlZ**p9O)wah(XYZb9Cabc*Jv^H z*S5=IncBqE=lA~CvGhwOcXiga#*thPvMxN}x{5sy5BRump;E~rv|N9*7eYwL zj5Jznhb-YaffdFeplB_#_vhl~^N`|R7q8TJYK>+@OSSvxO5gabd2H0gd_FzAbJVb9 zmB!=8%dX{B8V0_7gmp-R@2jlV!%uDZ>aEr%x>wNnOd$|ZKnu6YILYf_kbbSRk>h=` z6^n9oS(o@Tv!z+K+4PqU#4@jB^7G*C-%p6_dSIF<-tSAcTaBNbB553Cv_AU1m6GFyfWK=QJCim=g+Ef?mLp2cK(gVXwsDNuZYNQ= zG}b0XFYk8#SDS^6`U;3RIR!AY@0GC}Cy>m6nzsCil77HdAHNu8%=g&!Gd? zRn67DF0dLr-MVJj_ovHvRnC8Xpy@|P_g3fBM;WoxZ71%v>Jn?ZbZNo!#JLZxow+^O znZnyF--}J~3Oji@jp&c{(<;yEaNl?lBI_>tR%#v3f#B@H@D~ndjy@tX z9NNnc&q|R^FFY3rMjzX4rXLhrLClNp_IR?;GS5AT zGfNmt^yeyK@3Dz6(D82+$eLzc&9+Rc{)MVeeD?vXZJ5*acMtJI31r$h@B9ZYzYk47 z)rY?s=)RJ`mCzD8XvoPUt!UNyiox_LUZ!zSL&gcUxQ!DDeBNMuX{%eW-DO7~n^8w{ zX&Ic>DVtiEG0gh3KMoPo5X`^IS~2FnsYJyXRk|w>d@E$F32{7Z=GJa`JWxA)w6&lq zwP(M1IaZZFjQ1oZ3m85+fI|V?z|fnlG*Uo6xt3rEg5WtdBwr9)1ehzbACT*tl>tcH zQN_@*0I4jP2}F?7ZrIq64+sG*iRe{jO1IV5%CAMGmq^3Q41=B<4sFs_M}b?^m?zXq z&T`biUaVMMZbcl)X9CIAF{(O!W=D-V4+Gc_l4!OgR?Gqf85F?B2)f%O)yINP|U#3 z;U?)dU>E^PIiAm(m0zc6_5n4~`a30P7^Ml-g9~oX*I*AF=nO}mUdn#WB>1wPHN?iX zJc|;Cko!XM?PWwhN_-=W+p7upc%euZsBWGjM^mgm5Yqrf=MLx1yy(CUxFB1SA?cFG zzfB?*#<4c-mjSB~M(d{WP6>{NVpf8fo&=h0`JW!=gksvu=J`SKW4KrtI7$6IZ>9(T z$09Y!l5|P@AB%6=X{}~4g&#%!d88lZB92a}0)~8=NER4eKRwpw!ey|wLc{!~iVba* zL`BgFZe{Vp=7K6TFZO@N7`Suo z^W;&Oz@fPLitT%AYZrR|$@OtuD4Y@7gk;x8Va~%h>~{-iI-@|LFdR9jP%i$DTz_o( zPp!QJ5Hl0XhKD)s%FauyueA*SqcM(cMRgqfZxz;h7zGHS>&%8Q^)G&sLG53+Y=x_| zbrP6azaq?c%l6qhICxMDR=(9aD@^yv>Q@6M@zsY_tHCw=JUKCy;S9nN@J9^tbT!|0(s x=7k8+*~{y)CwmIJ)`G!!?#cdzgibP5T|n7n+_v>F<+Bdx-MFLmNy9em{{ZY6o#Oxi literal 0 HcmV?d00001 diff --git a/media/atree/node_3.png b/media/atree/node_3.png new file mode 100644 index 0000000000000000000000000000000000000000..b55c8963146856bb2783d0b1cf7084c10b16ee62 GIT binary patch literal 5218 zcmW+)c|26#8$PpO>{D4$2RjDzd!Ehp7-4Mea`c|=RN1#dmkAYXfZRKX8-^&>u6uU2>^uJga8CB^=9Mu z(&fbRzo~T%RP=EzQ4P2&Rv!yMWfJ3&0}a)t_tm!Y2Y}`C$p!i9^U?``GkZGMv8Exn zSH?qqZ5FJ)Znz5RR^REYcIuWJP4x1esihT3R6o5C>8?m$10AB5a3)Obn=cX-?r5|B6}Snt}u6`H@N;u`E9DckWo-@Uai9onGX`Q(e^Ufh<1LkKoos+-1+ zb;0h*2DDA8I&!i;m^jYhGT9U!B<7c!bZM6GRbcx$YkBSG(^zd^?=OTXuDlkF{3?DQ zQ^a)3z4ND7?$kor!_66*o)IEi6fW?yxcD-2Hj2^M84@s4N6fLXpYoFr3_pbqVNkw2 za>*?! zgqe%0JAuumpo5)p!hhOiyLVoIDUKVv^lw=iYA?y4R(wPYak(q)VoW-RMUrL@um$Tf zaj5k#^CD|yB=k|h)>(MpkBE4~+}29eU$V(~qS8 z3Y?Y6A_R3Rw^?T(0ep^T(W4f7twYKu;(M% zS$jNOB(673VK!hqSN=1W?qWez-(yO4NcmyB>u*Cb{s+5W-DOaBXtpn zDyaPd%f5dONsuZuq-kXVns^la?yz2_1Wh|@wD{jLU;~Kb7zpu;$jzxI9reXW{L9&^f%Ah0QJKp8@)&2H~+g52Qr<$L63M0tvddyA1 zyW&`+(ST&ZFnRm=%wn_qkZ?VXTGhImTjKb8m+zBaniLwBrsX)HKXs}D!$L|U#Eh}+ zDkcNH4$B)O3fU_OS>|TzxyM!+`7DHQYJ#2_;wk;h6B243d$xOmWrtg7uAEg(ZzCflY{PNCwJ518rsfWsOQ7wmCtb@T@4(+gmV2w8 z=;oj0PC9eeG{`E7+Nt_Qd$*Ko)&r>%K|t~OQpc{GOLP(GUudgd5}8yO<8(Y&yek)* znjw?=tr=^5)V$HO*GVUz6@KB4=Mz^}-lzW^AMeV&EWO5wtcBTc`y_KvO7*%8H{?oO zJ#I9)wVI6RS#r8rjvu_qKqiox2XgK|n|!ZzRX)I7>IN|}soRcQxkClULt26IAL?N& zmV}z5)OOFd^YS+;ZSDoHJvEEx7@cg1$+pG30R_i8~z1L*6d*&jILJCGAiF4m=KU`TDUm1`%0YR1!vZY9&&aP zz>T6ZNYmV(Gh^6Qx>buQg*As#j%~OR5eqDYUA(FagyPuGW2Le2)w@Pvm-lzw6XeSl z!#9^{+>AC9DVpYoIhvE|>xK1e)uAto94+k7RKR}&Gb2hz0jhC-4)(8jI_2y~)ine` zo+*M~l)8y#oJufB==#X_v@nmupt|k_&U||g6Og}c8_ql4FuKY|e^637UlX)E)rAS) z`gpiWl}p6lqNrWoBG)z%U=zn7p5@A)@3(N>R^0o@4OS?j0iWD2_$=waF1;T*ziL*# z%+p}cFqJZ~yv0~<@modk+vTCG@R?_!nGD~rmUfE(<$)iRAy(z&tp26`ccHhe=LCLN zkE(n(IS;n}P^u{JpN+kZFx=8f(Xx0w^@?Cde7FSu4t%4WQ$0{NGtV(tvFJ4gJEuV4 zVn)#G7dwV|T1raJhrd1qu{y5?9Ktco2b%f$E@lep0gZn$YVK5qzAQNldMIL~58O&l zR;|s67lu_D+)|b;nAo zZ)!V1StwVDg6G#p41sBZ7)7nl@xi!yw!~H27AdbWw>={R7-1iuRjU8HL*&TmYek>I z{;999Mr(a4_S?>aLl9L#>OB%ya)4%29h)rSa5cax{KeOIQW;)_keLf0mK981JV?0>2@YqTwbmU^%ejL z-jd7;&Tp1>uLcE~!j!TV8w{ z>f6o)F=}CJ$?WMr#F;vAakq#=TQcXIeES6LfC-hve`AQbT%FrnP-x59tlX+wzU}b; zlT)9a4Pun6{a_!_pe*mUH+EG7?5_NFtr@#4t>{rR71_PA;C~DbpR} z(s)Hxl9Q_m_I7Z}fLefuklPEVja_yo8{BJ*u7fm%>+zX77S^}sC;M_MLof1!uA{Yd zu?J6RM*V!9u1gL=delMMH}{q%&yi)GclIyd=r;wf=8mgB;({1`k~7RrHs*lI%nrP{ z<(D9)%m(kje`ucX&xcd9Xfk`Qm5XNA21c7$ZEJE$xEVF{oF9X>TO4i6VSe6;y z@J}Eqz0bY`!m}t*($6E0lCxxW%Pw+hqU?W;shci^60dY4IS9AC5Aveu_Fblh2Ws}o zONHtULsF=I2!_*Wv@-&-zfz>-9EptWrIFb=c#XzY>{*x>n=b_JzOn|UN8K-%SHvvl z*81~nLSs`WQjcRwNd4=_xI%jdWGY2I)V#?fk`M}iUer#ZbLk4a?>j)I#SWie5|b=n z9j_npF0|?E(Ot8Bula1U$(Cch$qOGZy~v(nn3Iw}L+mv?Bzgn_Jy_VFuCb48lX$bc z!S|f7hZr}5Ott*5I8=W+jYn?z9gd%koYc`d%Mb_g0v{zu@1;n|d(l z;=jMCh7-a0W8KW^%=hjFn350P)YN`oNSWNV8&;CZqJ#8pa)H3EGWwl-a3Si46r$kjHE#As^b=Zod2 zZ^qg_X2)Njh|JFt8_hF^990`r{^mb?I49%ML>wWZ$sr*U-X96cuU8k7S?~Nr@m|K? zuQj#w?O{92=T#9c)t}zN;V2$s#TRbS6)ZxpJ?9nO+@V(D?BQPb9yk6>ck;O%ii3T@ z+b&{_smW2{rs;beLyjcM>EqS6t~(z0JZ3dZE7%stQ>B<#y3}&qQzX*{SLGx-7KulR z%Uie6P*m-ec+T!Ko9>W8G*mn*iIHd(~(_HLKC zj7mtudlQb*fXel3^bw^lNdLBcut8t*p`-w=;hTiaR7)zx}6U1u9Q5l zTIE+9Q1zknmvi@=NKgLoC63&_rKC*n>r&&)*{8^de@bzhGhVBnu^N^|&6_(?nUXEJ zcm)X@6vY>iT`>MBN=0RG;+JUr@88akX|K7K-nr^fDc+J7^Q$jk4o};=i0e%FJEEU5 zd7099tgi0Y$)UUwe&o?}9KW+Uw_M5A6b<>>AqKRqb9y8 zxwQ9Xg_>&*@9{nR5X*|p{f6qTgBXp5KaBp{7FZ~zmk|O5u?Cj@l;;CJYUL?L02=$e zIx+~vl>ubs+glX=U~dfFJCSw3qX|sIka{!(-|JSo4uK#VAc@i?YkClZVEla~vyjG( zwMfj6wd4IF9|0jj#hy z3eTAc7wZ{O{xdwsW`dC9{)NyLmv%Y>PS7))Fk^A|@!)GZU?y8mV$Xm?2zvy{aajOq zc5w8lSSiVq!Klp?yv-gx;B4on&In;E)#ym{k|)rkn~HnE*6cxL9iAEu-buPIgvgWt z4faxK+!A>A(qKcbm?P)hNywR0%cEDLkOBn6$@*rzoe&>j<0I(Z@Y^VV0jE+;M(ar7 z(q90hXmFX2xt*BGK@GyZDlR6Ooj$2*?P6K><{KX1;x$l~T0LW-!vZuADE2|iBhe*D z!K;S^e#F2XcL`kj!xMp4=ZP5EwshlWQw}N!iXg(nXy;sU`yJQGxcZWb2gUDrz$Vqn}80KTcdeRcO7=}j>_Ci=7 z8c4zT{#J|JLt47R%Zia{1?y4M_Llo$s;+6AsMjm4(@DElW7&zw;h^^e~^ZE3=;= zjKTvpshCXmf~k10pQ#&_V!=MU0TW4Z*6 v!!!ES8qD~qUrb|sAmaIsd~{QLjsi(bf4{kc{;N;@F9>ur46avPvyc2Aq^-LE literal 0 HcmV?d00001 diff --git a/media/atree/node_3_blocked.png b/media/atree/node_3_blocked.png new file mode 100644 index 0000000000000000000000000000000000000000..26f82cd074326890caadb16f51eb1cf8cc9390b8 GIT binary patch literal 4913 zcmW+)XH*kP6WxShLJt_4v`~~HMX6GR&;&$jN>NI9Qi9SYB2q#GK?O8+5EMcaR3sD? zMY_^Eh&(|`Kq*o}=mC;^yzj@J-8*M?=FZ(8J7?}X*je#$AL0f8@Yz^fH~|3JKSBWF z!2afOwb=hZ6yaoL21*3e>K0EAj> zEKJWwc`c3I4fPnl)=KXT{-p89^6B?e?U9TB+N8+w^&JZSCBm8cDu7kQ$WMSNPkt;- z{1l#2ec_Pd{TBmH7U6=2QzX@=Mk1sqtiMuKL*uu`c9|f}U&%20Pxi#gtvbEX1H5l0 zRre}Si@6IoWclW(h{T*v)9YMGe$x9Vfp(kjsyR-a5_Va+P8;V7Ev&4mksR-knlAUQ znQU&WnX6P;F8PfVO6!KM$jvHV>mPObZR3aJPaAx((&T^Cx&MpP3bTM0))JH)b$rm) zW4#U)YoZLjNzW3}@V;8klaoL?Vv0U?|KL0+J`pE^#B7JcpsL71sgT|EL-mybvYh$XB(Ov!1Ye7s{i87#HE z{Y^PmKoItlv3^TA76}WEy^$A}n$xspdkejir|S{_sB34geG47NXg|InFO*~6(5!fh zDlaIL*ziHof-WySVb)NnI9R!@9Q&+>(Z^NhxG zdrE0PDw006{;4=#599@PoDWRT5od0vvX|L=)kE}xy+=l-3%E^R= zot+9MBvOsQEu;JT3gX|rNhQMh)57KrKj5e6`H$X+Ky{6kQe>XG6e7!(AdY)sX3k~} zui)nNugcB{h`ThRSwQipG*s6Jks@PPsSoQQ0F+6McOc>kL#Ak(DlB16E@2;Q7SQ-9 z0!^gmxRAH0)zUsS3k4ZPno#oe!NP4SPgYBGe=xjR;8wLNocmq7oFUQaqGW@M=aD+I zg@R%*w^NY8ylKnLbJIx=qDwcS!nO&Ic|x%J3kb*V-nPwe(zkZTz0ZOiuc< zuHCh@8N;jW?7h0;Dc5rYXKU2Pnqyok2T0VI>&qFT*!qz17uo#M@*NKgjI|a(26HW! z^IF8ErY_rXwe~cVi{814xnqs#1L8q6T2||-Iqm_eq?)Jz!R%sz+8)L8^QF2YNffOR z;o!Du)+!@n%^Pp*S59YlRvrFMD0}bAI+HE43u9b)JzO^x zx&I*IgO{RQQ>GRkKlcAOH;?A$YLL)dD8K#aKKjFZPs|J8y_6%Xwl|E!b?eQ}aE~=s zwLh-ZTHD3-c6}Z5OhD&4aS*5M{i|KH;;&C9e?Bz6HRft%HS_p`PGwB2BW*KPimHrBPHo%(lX4XV<-|t7|S`TjIBJ#~t5I zd+SuT;V>m@SiGxzsq@h!$2=@s`w%s>&;GVL`Wk$n#RC!cu3o6q9@o8`>`Yp3Z#~mW8Z|O9(3GK+R_KeF{!&M;iksg#B|v8mzBEL| zCx?*IGHBzU1Yt)nE$Aa-ID!0$BWf(#M77@${cq`?EiW9{+nAD*eNgVT1X+sbZS2x$ zrUbhF#yNXUkX&3&ocY)Mg&(jb@@nGsS6Fh+;dQy!(SB3?i!W){qYw4{m??mwn$+e17;#LQCs=tp_!S_iCjO;8}MaR`9kh)nG&wOYVGGV4q zdTK-Am|b>C$O-yGubA57`r@&+LU}%1$cNdBYr0uyT?Ts=H7K4w%6+3r>N(&J#+_Y% z!2|!-X{wo`QQ>lLGlAiA%+K<}q>slphgKears${&=mXp{C7 z>}*DS(%2(VZ>)82e9e_|@fF9M8IBzjq~M%MV5AT>Mu5a8PeI^0m#e_P>pYPMV;Ieb z;)U=`7zSRwRwIT#1H!ro@Xf-d=N-lG4$#UJOF$3>2rr%?WJfF(sXowBWTQ?Mf z6$WzhDV@F|;!!XQt7$ZD;KT!2Pj-Z*{?!hl;d z0qoji*RNhGUG=KB0JreB#g+#njJ$A_TZf^Txt*L;0wcdAw;>$?%F$}Mgl5#9gM{?V zA&4v#(-lS)prqNt8%|B?LosRL0c}U4hbAxBbC8)vIXsZb1slvk7}0e-j3%YNEkx!( zRv)>AO=bjy5nWBwj)~Q1bv+~kc`R?a{G!zOS_F*feQX=|V9RJS4$RqLrdwO7C$|&U zK+g>sz~kf7ICN=Jw7M=r6#__tfY^!v4L&e1d7Q@Ky)oJFqD=Pp%X6hH$rWR;X=m4E zoWr@&BMw1&bD{0Tc*m(HO|14?xWxFV-d;g4b?4yCnuw+tX*BpoZMTWysXK85Kw-oa zla;_rUs_UIU~}th4B-nBbar-9)#?|eq?4;A6I=Qo++a;vM)ii`L0)(may&tR-?#m` z^&A`l=mDXghPd5|@4H`n?4kr8%@_3YqQjo@5Ru-U^^&6OH4cL>zi9UGs_`S0`Krouz#<|8Ka8V3&`*w zF@1CUwN2*loDiLE?crvP;o-!it>lsHc2f4ty&f^D=b|-y<$-y^)2)E`3GFDEFLEGy z8y|d6o!o@qWRGbvv3R5^Gb=wUj>!M9kjGntTrJ%(f;H5i*m&djs>+zo^^2BIopRw~&+Zolg7Y|-v6nlK zx(dWF?pjn^k-pC*?N+ixf=o&2)evIR$AS&^pOypf;^Rf1?JUVZk0Tnd*R1yb^sY$p zYM#&ExOS1P>v$#owJPMKN?FUWt^0HxZ1tRR(@O;80a03b`?V_Pwn6zS(~;C?jUL>w zx_Y@Gk{djO2+k?Lk|`+(6YLjyXWP%79XX`9hev+!7q3;G%Ur`29GuKbN-e_q1&FpN zG6(J&U7d#-41Sok{}hSIUH8oq@SDL6QYzIyjD**Y1b?sibdPG2{|}*CXO=s+nH{RR z7D{Ilo_mjUw8e1|?GGd7V5@_wEF3D{Ke~Hes>+!*UMn$f_5~tN9)9(zYink<``B$R ztwJjg*2^i{QM+AA^jTL`j!OgPjuQK#S!p_8`?!4l&kyt&&8c3nLld3!yx(zcEQwRg9;r|f8x_C`^hq?26KoDl+2_|4kX8UER;ab>T75S0nui zDoGSIlcKFt>Ast;j+NIf9Ieu;ZHG`gS)tD)gK2IHFk4@;woNg^>-BxB@vQP`D zCZ?UamzFVHC=rE=d=`Q(sATo}zN38ELlI(6_6&3va5&&0;{7^H6kWZNP5vp?((%a^4iIJhs)^ zefueYdBD&T6clwP9Og>UJB%p3RUa|b(SDcF{8-UH^=#c4g|WTB(^4P>+17%8Cjx66 zo4*{-8NHviRMZNV%B0o$bm)ri?lUZU zcp*in>?nz;H}IDo=GPpn+B;vh`a+5Ii|_sSK&%aSraBqDL(Tiy?-*fk0A1ppQR&lM z2%=!$mWtYYhG@G@&nl$;#9G>M+dRD(b&#{assF=jk%Yudq7|vD*YCiP_|Qk1(g1DB z-S{M5&-iX`*Sbu*&yc)S^bv(-Z1KMbqX(X4tCJN*gy&vSyYF&o$tCIO==z78PCw@C zojb2e8J-?AzrL&amF;L|gWEaR6R2e2Qdys}p1>R6^iWax9u`ASyIotw+h-wf7qdxJYFNQYEk~%Q`bfrp|5+}9!2g8 zSoS2jiHs`E#*rJz3r5VBENylj^PYf{XNvwd7a`o=rC{#bpk2IG`KWB?Pi!Fem<+R6-KElV0XJql5J2F3JLgfO$-#6067em@u`0_mfhmZ3n!L!6r5 z5CjRulvlXbRl-2fvn_>8o0Rw7=Eyc{FNyef70bYl8!$TX1O8mVt+?1mYvC~Fpe+QQ zD|eCoss@S?gksKEiqxybay1ZuH_3G$pZtTQHRZeph@c?y|{B38) zO6^?;M$}KZe(D(7A+O>KH4jQG1W0??u^W!I#3TDWi@Sc*zn%jQw?GZfoPIQL6S(m= zh<-%XtH^_DW1Ia!MP+bWdO0lM?qNCy~Xb;^nUR^)D;K@VPtjRS z2@93YFBJ6A3Xk`e%%e2Fct86TM$p5_aT>yC64<1OTUxfz%0_x@_ zhV~&>mdAblU1yy+)@GM#N(S5p-5%cWY>cDU&pK-vE7csX3%wk33uj%ky<`{8x; zvZ@CiL<>88C^&o9R5xIDX{2H5(Q2I@JC~xaNWSnpN6NAw$_P5@3F^}Krd#HS4!^AL zA$f+a!=nWkl^xHiT7GyvrH-uo7K%{p)9XA}Yr(?Dkac@4v4V5YmfOreT%MLf)=B8Z z3VNjxsgi_M@iwx%lQZ{ROMZ_=^(~bo17%}s*jFE9|NT@f4AS$gy3LHr(e5dN6Z3;A znyHy`UN7wFihk`%m)r3lLBJZMEB2pd#e-p90?IBp25jMOEE)c^gc{<~78D@_Re5;S zX$8_fOG;W>nr5@`bQf&rxCKhyjRThCoH-!PQkD7#yW9r;2Ii{S;0LrdE7MI z+hSAd;lFQJ`#CJ_c_5;bBAh63o0ABSFk`t0|8uX959hyWC`SnB4^xjJN-D)fClIFL zYXr`5%-AGgNqJr4m}l;~NhqkaFQQ|UK%}Gn)#ET@S2Q?LMzVIuj(JKk9j)$hD607_ zR=~g{l?#oG7fzgtKkv&Ae^gsrK_bVoJdT%3^hKEbqZHB64pSmfoA9f05ecQu1dM>Y zKoaVjvNam{N;r0kL%!n#y!h`mEJG?wD;8sa1(Ad*5!gf~v?XKKWBQB5p;t*jz(5ZD z9F6?V6sPc7Bwjn7dW8RpQUv0SQl}8#Z9#}HWyh#HcY!Ffr_Hx$wpHBd3d=9tXsxW#Bq4^fjykU zTPNG)vKAH(OG1&0)q**9Mj-GrX^@B6wLt=OeUP#bHVH2c$h82o$VRA0v2)F|~U>EJgZ454W< z0L$Rp2!7<7nZH!r)b3MEJ)Xrgukl~VqoyCh+Y!{_{ad_wu4j!ZbB|^Xab{i~D>9OK zy?rXy*t?h?$n8JOVVl(NH=nl~51iT0ZPfNRX7s!F4Sn?ao2%ETLpoPF4uzs|SK{#1 zq>{xJPui3jh{Y#IEI#57`u?|P!0c3`dY~KQxT|c9cv;ll<;=?yMH7Cn&|LQi<-qfW zKJ{*GAV4x`o?F$mFRTgM@t$9|Y8m{`j&b~HS?vRA52-}Hwb3}7IgqNhmgwk)&tRD22^3IPAH2I4p4zfHUrvzq>-n~l zLN|Xa;U-4>5UJJ@Rr`bwF1c|GuC!Nw^7VOt4Z+s zbvNXC?8o=L<`VA8XoPN$hdbW6R(WKZm9MZAv%R)H2@U3{#Y}U*M6a1MLE)Kk`|pYB zdKhH$bkpIwBS2(NuY*9^jWu0d{mLFpSGno=TSjpl(_Li_k1{S|2T7ATy|JcMDCHi8 z`MuF_9nWs7URwE){`aX>eR=*zpbkSJ<5bjArFie|xd#*Uu^@rStUqbhJsYxr8vk9W ztWTBFa?oMbn2O-XK$plG6JhJ3wcMQW&vWehF}KMofnO0_ zS&K>MtY%)x`73R{&PD%h!GWhvqE+_0ROkQxZmmu7A}i>7gse75XXcIybz>BRTELJ5 zFpZ2?kY>i879bfra@6)|>c7H{ct!6)Q(wK9bT|}6orLID&i?pw!X?{9up2MdPw-Y-iB*{>B{1=>9Mqu-pCHVyJs0{mdcguq;Pr`6p= zAIx&=Of4~Dz6LJB!U`ZuUgZua+5A80evh1&OZ^j1s71@YEw@rKJRH=z6AHm^k=Rrs z^xM;BiO8Cng11)lBa$!SGF5K)QXa6(jA&gw_UxxHpYJ;{jqRV@y=BxxT2b z3DP#3D3bedMpfXZV}q7@&yT2;_h&%QzUGH&=FaNl%y%&tGrxtes?QXd3S+-n%udw9 zFuTk%6F&p53O)I2I?$W(x?*odFW__*-n<#Byz;i30EUjNKa zuBH*i#$S6+&-&+K6g>fM-`#9oxVLc-wOl(L_wjdxKcR)>g;A=ka#kk7ybA+zR$H-* zJHd+K@weYf(L497?g_$V9N-7+aRc&U`sFkY2_+p{+taxiH_$8bRf;|!b_OdQi^jr4}?9DPe zrONV&M|c>da05;5IF!PpK05c-YN()1qwuIUh?-^o`EUAZIiJ$CJYn3?uHRb}k&z>i0DQA|d;cGa@TH z#3U2mEm$@Z#C3(AZ5fRBWoA(`$a+vX9FNvZRL#Je`}BOmOFk3oVyX0_#hH$uOA`eZ zBrY|;D)hR&+(AVsKlU0z2V8244;zZ`wp6O*mcSdXQto3iZTraKO33`dmfgG~e~=5(kKgv^R@ zL*~8Cl@sA_ZXY!mQheOsqzb<0>nTcBmIfZtf!M1zgl48Y_H3RE1aV^vH6d_?^PUM! zukS!ajDbj~yD#xWo<6HI`c~%bm4qniE;n26!|_D{>OEP~*A96&PPFNxjzGzcsSk_< zXD;7N-QSb~u~SA4y3ib}TReS5k(6x=D;GvPzBd-WO>dFwbDyHhHlV3H2ZOtz(bn$T zGLJD1JKy-TzG@x%6bmYX+3p&TWZkA|({6G=F#{P&{9D~+brxtWSEmu)U71n;eU>YA=vA)4@Rf>K6&i? z5D8)uo$#-vz|Fu&X`2xzj0&-K+vXZu7}FOGZmwzI=t|!?9)A8bh(5ZbZoOY=%=$K{ z>!ruI{df~jB(zTZrP$u)abym(L;PtGP6{YakNdVgiBHTZ{2gxVwvPkdmKT{~0~*?R zc5VHF+Of0jQ_D4$@s*3d*C0F?pz+XkVE(USvx(LU`xQ&Og{Mw<7!p_oGS2b1VN%9l z;ZpY9Kjt&p73?BUfjU%SYDbcF!>kO8+={8VoMmkt^zEjo1m^Ivsjym0(0L_8*RHo` z&F5=rGOE>5tmgD@y5Erx+-ZyVU)}kInepb)h(GON*eQHC@YW3@CBuFR1I_5^{crD1 z&(!jOB@S=AS^9fbNhdv|VdoRsip9exX3}O!0u2&*~k+apGA^i;)yya1ZO<@)bv#M*7O)2q5U!>ySG4<775GmcYaAzoJz#KlrrS-1$Y&S8ye7 z>u5&-e|#Ee%6>#rs_M@k+^{F}dOiQA;YGjCQ9Pt80CyAzDYzE;cf|T>Ga(ESH?y*O zp?6KzR_kXuPu1z<)3Z?2?a5V16G6r9SFHOMLnx1~=&Fj0omM;&IQ3s>#eLD&^et!^ zkThpzSZ_zJ$bIKqvni!Vw#Hk~11@%Jh|MpqIOyH|oe~0nrC~+`LyrH zw;g7#*7xC*$)vokg42sYjk_+9_uO*CHjf_TtC{!G_regNG3|R-)5{F{2~*pUGN3Ql zwc4wruV&Kc*hx7>>#y`f6}5N2;#2;ao4eO@GqY2JOxW;?khV@`rUQ&+na|O01f4 zKAX2Q$fvzAV%;m8EV8ag3!E+Z90b&2@tPJ#j*g#+#?7W!3wzGYBiQTTY5eh<&b&Na zHu1zR%Lmy!8~oSnaRk+y%Kx-1=MF0-FL8K|*`Lh(`J#WFgWg0%=?H#RyCE~5zms7V zs|2`@<%tx!q_4)#P`|I8b+L#W2E(5SpSLsrqH9ywb)BsxL}{lFmOuGt==rS53U+ct z;6&|0_Vg|}nOfkye`DJCmZmMC_9F(w7WNA2rk6K8;%V80ooxxx)xL`Tr}BR2qkQDO zc%FB|HloXxC&pg1U%WlLFC!}fj1jT1s%L-a#fd{de?R`ps>Emcr%vFFTULxXCcPwY zgqc@7MG+U&+z6Z-;IXLY7ff!($s(>i*zX#2S8D;+cl(;@e1PvmU+ff|`rFvqqES|E zB&)bTgoEmoE|gZ==fbpF&)vGC6S>`MV{sdqRr|ZrU;5&VYfjvi#ga@a-v0yf9q*Nl zHzenR$7h#;h>=vWmO%RF<1?LK8rNwmKIYXMwN!oki1*vg8*BgjSYG*rZt&6I#(tW0 zJ9ETpd5AwNIG;(ee!F(>?9M5($jUEKNDKh<&Z;-0&ws?CHO%FJ|A(|60i%#Qm>V#b z1vH7;%aKQJA7V$k*Kqi&LJL=t$@YLO7BQIaC;^Osl+%?9lPB3gf;x%A=Avy0XD|X9 z(oriBIq-G`s0o6#C*?6`SocFdf&RkzO#yOjCBPdSHtx%ipm;PK+~TaKJJamI5-&*L zF@TY~SD+Ye!?gXbC!i-N+(h@qZX1;iED4*gHx!!su(Z6TUQBsuaUqb!b*(=Op}-CT z!l3itW1d2@S+gPAZtYnaaB|44{bA(3(lQjEj1|N-<r zE7TVpGfsjF2xwi$wV$Wv7tZ}Ypz*e#*pQwsLC7v~z!+I^Zia<8Avhx>;3UOa90+n2 zo53VWK^Wed6A~wtpeZJ;Z&xE}&kc@5V{GN_``Ys!Nc?j5!;rwQK^)3uh*UmvxZvuj zChkOke5#ZTmcD|!foQ4mjr-AN=7==pNy@*}w8>u3P>%$sQ@BgUhcO%1s2*W4h9V(f zuToFlnzq8tXyD+6ZHVZ4Ck-?L`rEV7i(B6ei3H!ZZld|v2XT$OJPz49HNVplv3e?; z6S2#~=oeb6%@Z$6ETlrPYh0r>9CiGAKef5Cm7-`iA5Pt>m2BtSERem5Ret_~cC~1z zEqLL`i(%Y7N%l=TA5vfFKfPfUShS!-4F-yqsZ)*vihA1ihhewE_#Pr7jSzuut3te@ l!X}%f`bT?v6eN`i^PFt8J$irgIqR1qFh6H)Qe%XR{y+Usv^f9( literal 0 HcmV?d00001 diff --git a/media/atree/node_4_blocked.png b/media/atree/node_4_blocked.png new file mode 100644 index 0000000000000000000000000000000000000000..d8592524a3d817a46ddde156f81dc8af720c5e5e GIT binary patch literal 5031 zcmX9?c{mi__rAjzV;>o0-#?bJw8+koH9~}B87ZV>j|ekkZ%{&_g$Y?IWM4BR*|L{? zSC(YUHkO(BPQTwD_qq4H&$;hC=iKEy_dK#RH)3PvX9fVUnHcL^0RW*5Apj1eb&mdp z?*F6!D<3U2|xrD>wCd-Z|y z+SDT-!KIM)Eswp~Pn!B&)p@n)UhR*cAPx8l%Hy^2%#wcn1nLQDAwid=_TC){@01+x z)bl}JQUs~)ba{Nc|8rA?{bkKozK2zlH`iCm5x_vuJ}Agz>EKh}QEyo~0Uo=)Veq-k z280s+(n3q+7tqd0fCJ#$1>Jg)hSfJBgc;G2Z$w8(5} zJyG9d!!PWtioSE!o0Moc^zlOSs9#Go|C;RaCOqnv&E(7(_u$~*z?s`~jB*k3p&PuP zS;{!FNguvy8zqX#d$2g}7&|wYU~h)O1_#`pAafb<8=Nx&Z)7Mt(8;9*AqY+>^7WSF zjD$8rwj!jS?(qTVpF~q+gb4!LlF`H^bDSa$KR$ENb0inROdJh^;mYp2%nKB3vgsqt z+y@2nH+2z-XMQF1%11EIoYszPjvtpfdU@-6yIDS?Zsv?&u6EcNHE0*D{Fh3E%+SkB`(vbbWCj=XZPClKjhu$zlAoi!3Clj%D&VmFPR z{XSo?`Bd6~4W~&|#f!vPeL-}rvgDGk7#pzQG@E2-kZm5KV}d1zbcNY~38(q#BwpmL zRWzcbo8=AZ%B2tvoMt1O2Bj|{Iu02ukCpVCFN$_k1Mnh-oj2jPb}?pKt;QiNIQ-E= z1dAL5=Z`^d4bFoQWw%+=D)T{R zY>^LsK%`c@3egeBnLHo2;{F{aCzfmo%)%s)I=-^q*NsD4aPy2|U9MM@I@v|5LRc+b z9}QpmeHSEBns3>EV3gzrl@t`*bHw<>HVa-PUZ!{#Yi2=D2bbI{LQO)NmpQ(O7Qc8@ z@s>csWk_jpyD$T!g_kw1mJT~0VvHJ8PP@j4+M?geure(Rg!n;GUTbh{pn;PaVVBV= zH$2v`c@YM z7j%w$6?guQVyIJH?%K?;5Y0Q?i-7MGt*x&cuAD?X)VJvaky*xdq5y9_^Fj{XylRySPJ~>eb*_et`q$wvl0ygwHlIeSELb~ba?(x zUCjRee~&5gB}DbK3Y9Ne*4bSirGn}Cq#tEdEt<#X){ilh&$o3NSk)yx@|>5L$016G z?Pdu#Ht$?!Z~Bp5aeah52zwWh67-$pe{dl9Zb7uF~?D(T2Y4?ePJh5(KW!^aZc(R@W6NFgS zJ*fjz{~b)7Oo^k8=97&6=md-R)ExTnjVJHo(hiaw4XN?4yW(p^p^gP1W(-d~&i8W= zBtjh+QsII68V~P@GU}{b9c$lK>8CtAN_OzLEXo$)nm(W-DNotnz-xwPedc&KVE?pW z#`)QF6Q76SywV$%_(__BaX%A}eXb)h#?svd{u{*?J$j<=HJ#j#%_uQben|kfM?sn$$Vi(m_Rz9UHrIQN2UPO;Nrpv z@1=}Ze?HzD*}(8*Mxoh`5p_h(n-)^o=wS&r{=J~0;d*b7DY^wID!NqC+0Wgj>6FH8O)wgD?)GYF&CZKMXtw4Are2n8w?b!lurj$61S+ZMAqHvhm7dZ? z77webk_Ly(C|RsUXj$Jt_W{LIPEWx`5q5T%%`OLr#jN#fVG zlDLYTmfYVky(-BD8O>@NRKca=Zi2PW^C2HU9uIytut>cbs(4**uZ9vVp z^Tqiq;J?Btg4=1XaNC6gQ@gKfqj2n*&>re@3!yp(8J4@b;?J1lj#T$LGNxC#S8N}y z^K`jVLsO+0os=bkq3Zt8jO$iu;!c{&(OZ^a7GXLU{r#~wg2jGgKAy^QR>l6Q{W3J{ zUTU04+E_~!SJBDi=42BOx)Lb1vj7y!8^)atC}Dbl^K6z;2hV${9MyG8#GUlI(+`l4 z*}=GoWjHRyq3YHRTm?j!uGwbl{L!T|)|%s*Csz5bwKyQNo*z${5k?+VW^L3v%of(H z98({p4q@^?@?2xwM1bmTkHcO&vlc`U*i6KlLb1iwy$6_7*7P-27qNa_Fe+zynmO~Q z@0vbLU_JK6*V63}abWfd-f>-w@p4YV!wJl1J;HoP4ciJV>E;jB9qxy^Wl)za{sb%@ zd}OnyQ{u?3i=vI*X)1J`w~b*(@ri&?&i*<7p{YpO*zd$v5>UnDOD`#Vb1EmbA)8x} zz|eIt_z?iCh5*1M0EnW^NZ`0z-oJE1G`|eC&JlY~8{8@2t{XnH(~C$gV_tS)cBwdg zg}h*%4Yh<~d*&x{lg|A-7mNTG5>~O_E;7!F0xzDLSOJew34nyS2xOH>dZn~EI}NXI zA>h0E;LqAxold5kZ&!4`5OJ|u9cw7eObEZ>P>=pH*W%M zd(B6}VD#q-!WW#hAua(5Fm>nP8q1(og}d6c9T-|9C@~~7p(TK0)Wug6UkM zojE=p9N-&b%K0koj|GfCVjXFIlFZ~*?pZ_KeKN@w76VRN6Ft-zS-RYI=W?!Hwxzan zf}4T-AIsZ!fm`{wQ_3%nI+6!n0>~g7wxDePM8ST2Jn*$Sd=m0!NRl7e^(JJ5$yu%# z=sN6Yz|vxz7w;Xm=?vX@!R~?|r|!L$ZYPYE2wljdlr`W^!LhO*Qr|cd`{X|x)a(%c zdzSuxAm6)x^bU;kPZBeh&3YuMU#uzfDDoKvAGxw3fVgVg&ZHfA~skU1;hsrbK$Nd;!v| z-YgjEbg&l}2nort@T=cruQ__WZQT$E#FnQbHPF5|OXm+WPH8QWnN>v5-)PBKa#nMmbH>kw8Id~f^i*KO$2SQT**Gt<`75g|Q+d$B z(e_jLQS}kmSNn9Ss@Dv4)F=tH_gl(0{RYn|I8e>E`ndAQb`|P0gCQ$Lg$YJW{;S!; zZfma`;urka{4QRgRGDu{V`Wivhm5@bvh zhs9D8I!=L$m9>`?^Xd;U4(0BB`@4d)q|HujyUdG7ZFyn5fAFRf{YGGOxsbTE&A=yY zMY{2=_L53EJ8FR8i~drjDKV%4(n<_5UOH64RIDT(hMFk1iJU?!3*>!Vp>xf@OF!ko zIQX#T>~AxivwU4Z@a5mc3XWzj;aNU|v;j1O&{%1h6%-ZNTRB^Y3q&K;M&*JLf5NI2 zR*CP%w!?T1<`F@((5eBX7~;u|)|3DZxPmvwuPyVCNE9!rnp*qcr(72M#`X|$t-cWX zS*bF1YRYM2gMp0|N?7}tCEu^MHAM94C~laDi5PA+d}!lM2{QFQzIB;rTA<_ah71LH zO=4HwE+aCZ#rV;*qoe@0TEkGVdQ?=;aWI2Aair8{LufpgoaMB+XPW=x30g3h`1dt3 z=-uX*gf!2&WwougeFJ`<38xlC{=NA66-_p2i=75iQ(4V|1VZ=*N>IFPecroY-r42V+olc|2dFvUZNNx`s29u}_&dQE!}$Ua%Xd6~ z@U1Y?dykr2bj&3(?t;qvE_g5$?qdQqAg}BpHZJ4?#O#F65zO3gO-I?<$CYK zUccns)9+)4k@H?t2WFFB~=y z85bXN_LuT8F^EP=-Z^!Lk?`MMOduU9Y~Gu!RTd0@6;}v&A_4wug6GqrG*dpjtyKql zz}QZ3C^#RWvZS=)zov*wTth%zQ@($mDXi51G`(_Hp~_4;pq4gF;M+$ww_XKs*`(o_ z)T=;755Q%5=Ix3sAlEp+Ux`j&T;2dKNv{o{rA~l`hK7+T5$Pu1dN6BZk0f5Yo93;#mQ(j0Tt9z}rgy@&G&n^@jT`$wrtS#YrcVC(cdmy8F+m z7^}*8yAXC@04E^u*N){jAcXu_tT;TmDu;(Cr}s~#?&{BZI|C+~im1vWvPn+=9=Ghj z^}ao$@eRU8?>1d|PgP`D_JuS+4T5%1S7?|sq=($Ax4|IobPXGV_ literal 0 HcmV?d00001 diff --git a/media/atree/node_highlight.png b/media/atree/node_highlight.png new file mode 100644 index 0000000000000000000000000000000000000000..76fa3f815860e7a0a055b808cdc9770b48b80320 GIT binary patch literal 23515 zcmX_ncUY2t)IRQ&S-EmIwQ_&WJ)2hMD09!E!onGDWT=_ttgJNm$h1^&<`&e{hKd_C z5l4ZFGei&(UV7i(_4~t1pX(By=X}mN_c`Z2_w&NR&RSelUK9WTh+n^U`8EK+!~K&7 zAS}rJ<@u!i;lC@$ZR?8w)S%)r_ktgE!S(_GP?Ijkx+}oF774!Q1_1yLcK`d~=?f~q z4*+-sU%!0ePNer*-ivU>pHI9BG^T3*T&TrN`m9F1Hv2Z&G!v84*}w9*u$AW}Y{De1 za;38W=-F1%JI?*P573uWfR? zml}YphdCPyvu(t%mL0`QI(@~9lug-IDV8^*y>2tSGns_b4Nto(;Py)SR*lPc9Zx?6 zMS;)qd7}%5ZuUz(6i_dlYo8?$hr?P6fWjo#P?iDfqxd{M#eIgIiuMXQZP%wBThL&= z%Fa+fQ~g~uv?mE_fXsXAiEC&jC;7S$ZG}Y|Ac=qt=%S%Z8dyzwPU?Z1E-u7)0|#mg zH>2a#MCyy<&Z%GPQ$Or7*Gd_O^-U^K`c7rZgvOY|GoEciFQ1*|^!iNI7JGywMf6}= zg1rXy2|^PpeOQY0xl=|xWyj{F&~f=JOIeg!D=BHzP$YaO+Drkfjr`TI)gFGJY^XZ; zw4JN2DTdiHbKBYTfq+Qa^O_7!Xh={GN^h$D!G7q0Ht!3=H=X@zi*qZ>wYL!3>z&PM z;E0V{_&X~x6N_{ZAA`4PKmik8+m+qb?OdKAs`P8?NB9iws13>mj$N)`$ET@%^qZ5) zjH@`R~+A(3>OP#|fkqm-j&^7A1PQkZhe~7lQK*`Vy zSVw5Vy4Y4Je7S7#$W4zsihrbJWSnD4FIEN5ORVEJpQPzJ%J- z@ny_2AVn|iQAr~#g53N+7k&$u6CVh23?N+euPG-v-mD2l(l1)FFwb& zxr3pl%C;6?yzPHm_uQap(;Y?tp!H$l(gS=1ZaIpWN5RS^CJHNJm?mEFMy1Fac`x+T;8tOtHyPqJchy2ZO$vy6uy5Ebo!%FTeya_ z^p`tGhYRcS7u<$3Ip7e99XEVv`jqewxkTlu0oBTe3QyFF^j~#2+%4)k4}5?& zZ3Kr(M1DGqe1w~y0t6x(_p5?#HdM!bUXm(acq*-(d$AxijT)eMdl=kmIo4PgM=TP_ z`Q92T-qJU-vD7H-sbcC@GjJ8@^x=890bhdo6>Sb#3`*Sfir0@w1yrOn#Xg!R+RqAG zG)4q*e&d}TQlu5aMSW_{-Mb>r>FIr^zSa5#+8hKMHr#*OwRQ9BiUVq0X-a8^nnKuD zZS&p*NW1kUI%PT3IAfDqx)Prw9u(o~ zNf1V7BkMr;pP*X*aK)znt7-rqvQSI z&kIi5u03gQy-lqvHfvB63-x)v0Eq+JI<#P~Zi`>EG~s$ly#iBtk2Mb?JRqfkImM7V zwQ#5W(EJyXdY&`z%5B3(lCJu^^!md~V$LcJ!W?XpsfWKk@zroQ75N6_Ilz!PXgfVw@v!*qfDsF`^SFBDe|AGg(v)Y|ft)_+ zR>4(vS5tq_=fjNCz9*5=?Y4yjg|>yM*f264Ii@ni^6nMVk4v9&YTF;!DB664dovEaRr>vPr{hSQ+8)P19jBaKw3` zhT1NDPzH(mIssw}1GoZD36WA`run6+ivuP7_+DD40;c&Zrz(Yp${-9)d2Cov%+LuN z37+3CuU$4t*ie9pB9eUO_Y}c5=Ya$joiE>HFc+%|%{68{yi6lTXw@U;N_Zg=XM6(w z>+Q(Yw}p7=Vj$&2S!50A$+Yph{+CtdRrQqdnJnNH8_A_iWUB8tzjG><9Kc_77yLnm z2^h z%h`lWEsgL<@o0(F)q}ml{ieY)V8}>~{yFKYunfngk>1t?&u;UT%&i<7YGrU#&M#pp zV^)xMuB|U#*b_`wi?zrKTGNGp7u;kUVg$Y{DGT;&c=*h#`wRSY;h+lxM!6&*>x&S3 z{7SP)$iKEANy$c{EYW(9#)aizjZQ^;Qj}(Y>t;)MnhoWSnED;?r2Atvk7OsuB@+~` zqsueP<%zA*A*~ZTqqA2FCw~bm{^BphO$ob74l*0A`exD#whFIqW_iuhNsZOY$`Y4) z(w{#9hn=G^m%Di41ji zMPoaE(OpDQ{bHYY&ggW~7-XP5lBlys3 z3gU$R$*@(hN*2_7C?V40QZ4E_uO2Kw6a?fgLbz7bpCFW6p2|#IL|pMSFvGmA4$Y0|4zz8Z9S?AJ>hQeF-VM=XrNul`Z@8zhY!BsvRWtN z8z5x?Jh=rfqy;GPEK(bqASatPRu(+@hGaDa#&&|wOzeKg9Dyxw47#wCPtk*Ye1{8r zRy#X)s6o~RuTZDGFhV_BX}+MIHmz`sQeNV24qm+#NO>Fp{#4V@>pbH=)vKAuE&gR8 zIlz?*sWI_%8>?51Ja1Sev-~X^`wHg??O z;N_si=8j!Ap`Dl8NZ+$r0(aV^zs%_K6r6<~i`MzDch5$r@19}45i=m6q;8n#3|v+G z>9#l$eFk#Po>%OyBlQ(zd!lfyx~ZHNXRmC*fpy1d@ z`vbeEKk&E~2W`rANo10Hkqe7+8i?V~-Js^bB}4(pkLjNjuxmtCN3%--%aP%l!v`ty zIat}#vR+go6I*;HW>qTsyJFQHh9gV!{C%QyC%3hEQ9`ufwFZ5{4Ak)F3oX5WnKYpn z*MQ2;Jj=RHZaCaz0e$T_Nwuol&#($P8F|GgI^DRRCRPmU(;I>C%$-NA zjXT!|yOj$*^LTPd1qlsVGU@k@`|=ZT?6Wb=(bT#$frk=1=Z9smyy}nruUIM|yE0Mp z(L>#QgrFn;@3z3OiD)#ayCy82+U6^b4s)JNnyGu52V9CNh)}s}Zm#e=OHUWWe~vv~ zz<*x6fTl>BaRB4QnmqTkCjm2J;9|`WSE{dxP8lM4?D(>R5Tv0qOj2ScA@1BwG2gqT z0$p}nmkK)Ftu(-2Udq(*kIGa)G5Ei^WlB&!42Ns(@1mXkxkZiKXQ?}c~&0#YnJtr|B@K!uvB#r{HwS$ONtXi^>Dz4 zS!PuDodr~WlZI_vCtt!>2d8*oosOI4yAt;D=BCcHxu{E*frQU_u4n}S>JC?C$8H?fBrQuoPtw$?>OQc|U2+o) zc&}J~-*6=}+bHgOl#MBeq36(X{@<)4)v??DG&34Yu^>}>2;eMG2lU7q&ryk0XC|q% zLaD7UEdZE!l2JBM*zA$S4t31^++DpvXW;*JNld7GH^t?whP5@ z2|{G^L!vr@;B=i3)rKz6&EcaSR$}uTGDn>m>RXvs>Li*Z{%-y)R6F_TG{6k#ijxEJ zf%&p*k$Pib@}#h*OQejEdNtQwZCxCkoDcQ%5F~8(fO$QSC!HjudEnG1nIf*EZ28I= zMdF>7;#sCdmgXUmQ?E|F`RZOS>a(TJJPXf%i)xhY5E+h3D~Pm=c2}QnC>!`WcahGsP zKwNT{^Y47M)z61F4^Z9sL+5vDBE^26MiAC0rKw2o;@KL+E&R4geP=1LK+Ujh;xuO{)0;D$jZV zj(|>FM+L!~j=&X=R1MJ{p!vi@l`D@I&cz7$puVCvqdK}0`O^e61&!XmQCokOe;22; z$+{Z==+M#9j~&^|Hzl>46-qs4$PbUckAH z@M1WZ15?6gzMg@{wY@o(!Jl(1-%xiQ6uXvfEkKKwslP%ijEpq9c_ftewGZf|@JLA= zjuQQ&1g5T(yO+21g zm3;f71}Q@V|D8R;Z>NC^>k^w(+jIX||oeTQ;Y~Jmj7gA;nJ3K}2hpv-<;$)BA@u<`!ieI5AFQpuut_qGm4Uab$?I75z zXy$kMNI#Z&PSm*F6IAmG6v>X<)5Zu-7H3h zn}jOj4R{*HRRQ#-O=(WP;Lw1Qg3jQP?OSty4#aSqp`0`Bg)&zMyS|-;KdQM=xZm%( z3lpR^f3J(AKvV=^l{f=L4uE{=3y-G>FaS{5J-u>4vphaea4c5)q90$m%!h2g>59&a zmWzLhY=T4Ls-0lUB7Y@AdiR{~H#1(6+l06Y=kRK%<$GhjAnFLcBE61QV~Rjy4F zKayMn(sECGc3}%n4Vd)8CpTVqAkrS9U2@so z-0taQp#<~fi%v#=ytWK(y0mV|=35M4uu1#IQ}K#dZ|$7jr}TOBqeVs6<@*O*y9XaS z7yyjoUkg5nsC!lYP;BT!&gNVFdDV8IahitK5M0W6&z_^Iki0u=mmNP1ZgL0KT40$* zA|~ACCB1js-k|ZfZ+_4BDSoqL(*2bO9U3ksH6oK5&bC&XNof)xwtT^okB$kJFn$51 zr;aKdz+8%Zbj+4{Gh6^;Q!n&ZpLBtL)Ixq#We9qkQ<^vwA9P{}vO-A#c>*2ySq@GW_@!DX zGfr}1EXFQk_F|J;UlD|?3lB0mRhgWuK4SYO@tNnI3Pa}%UkFU%<##G)G=Wp`zJeod zn=x}47Y{0{ zu1{)uN6aem^BScFF3wpV;@y`>Wc6L(TspzZd|D{K$#O(Y35w7BnU?dDN(}W7zm7Tm(A>INF^L^@$magB&m?o(DXioJT|+7srA*IdLmpg0*|R zv%J>q?J@*s!)Jh3weU)O9rduHII_`{m+t6uE=KY~?KLE2rTWFOV;Ejl@d+eoNN=;7 ze})HwVb&D0S6aPhnxZwo54Y{i*5iX4&|{6va$If5QI+5ssAO(Dn>6+Bne1~36&>$Z z9$1qBy}d!~em&3e=TWYt!Q6r_pZu6TN_CzX4_yq4sNR(HnTM`z^aluy-HpFJ>B#a{ zXDbIvZhhpRIRx=RQygLSk*8pK_f=s<5|GYD380d#DP}* z8KGZW^$&Wy28qabP|{b=_qd7vns>xf+|OjjPq82bmnV_k+WX$Ec5s0tj%I+13ND)Q zxh2v<$Ku_#fcrCOZZ>8k1)P&I^%rh?w`T>0x0r-O1kq0HvvSJNBcLvvox3=~wB?vl-l4B4e*U z(38ZT-F<+6BC*`jFj`PzoC!B=@fmCbtcg-Ly<0kDo%bTq;k6eFxTWH?P-WDApsK1b zK=SqAH=`Sq`hZ-3Ng|_&cgGQKfb5{j{Q_hWxxGC<09Lp6v5%RqFzd(~A`4GkzAMhW zvuS9>z3&6qSkR;653Y0o$vf_Y=FXnGBha*(jJ&#*9dC3hQI}sSJ}s8aA9^4S-YToL zwz%Qy`f5)=CxFaoi_!&=AWoEtHsfCJuebPy&OYKpicVwJ)R_i63j6~Lt7V8~bA`)% zh7Q8@>DZYH3#<$eIJQvNN}w`Jy9Q^4r!Y_NZ8ZIDz*MbgRv5RE!y!NJdE1|n(p+MA zXYEa(%FD~rqQ&zr&7`CfbKP(gG5LJoAk$Bh>%;+NQIM1DU2RU=A8D8ZfPNUmS&{IP zC=>3tI>bcrSP|KR;Cpii{_4z`7VZIQpDf&uJ(}tL%{cPjqh-QVr6p)T3+~m@m`v7O zb%$t}$mCwCk>7x0xTl-Mc8*>jAE_S<={RPMH5p{u!2AA7+&YJuMD2?jVA=)M#vNI)nKS|}r@1t}qfakR)93uRBwF4WR z^PGY@eBUQqM9C1od@9GN=qMmFn1|{`7}7(6)lZU$g$FO>Ju1FAbo2H33#y-9tQ-eS zTX(kG#QbOQ=s+q&nf2XCS#`i>3ie=s7-QpU?t$8wP}{HIq=IEnZoA>*2riud#>vzT z0s4?cc~G_StJcWW;U+7ZfzOxI^s#9a4_4FJ^2F^bvFc-YSf*wE!bvKBb5p-wj(VJAf6&Y_E;5jHj-a~>T6%T=-jQx~QL- z9l@hur9$^;hUcHV(-x*c?v74fN{PsaBDT+;lTA&Sbl#H7qm!NBlcy3wKXxI|j0W5OTb-TtbSpZax6S^4C@23X%9|s*ul3~-5I~vAp?>i2 z9=ycahus~kYpB86|r;6{X_AwT~;UU}9BOir~b@2mm=n0B1qA2%3D>TJNe8!u{b#~Ty40z(_?`Lhwo zoXwIiGak#%d5?KQ8X~u%pq7$uK1c~c>)``hjMtv~8bZkzEL z>g=g7)!kHMGd=?L)X}C+LlJKq$p=SHXK|6l;)&BYxkLei^aR7RPrqmn>E7paSWk7T zsmM6M8%O#QMff9?l(rGOE<&*fj?qh8J^AirIHvFOmMf2=vvY0d_6h(Qbt2VSIVc0l zGqc5(!cGO>_`prU*$?lLkAhO0weZy)*xunt5)VP?j$caZ`2G({O>{`0WZsuCMhbvRneme7DrFaUM7v0|<2-Jl z^INh`9(xD=&Sy5Gs$=LG@U^b+g2GWxfddf< z@x_Z!EUmSXZ6$UxHU83aXRd8w&Dw%Gx_fPQBr_zZJ>@W1xnIN|mA&}h<55};82{L= z;hr~96k_QQ?4BUXrRy5w!>&b!x!IyZKdDyOd^7o5rcj-u81S1W#i4X*>ukF93kDpK zufCvQw8WUm0=F8D74$lAT(%>Cuk{Q>>M>#uSD%nPvgstafxCafqYlt4H}kFNPkTS+ zh0t0;mdO7M$Cj?wXVql+eshVxEWXY*tN1 zSp<2y3)ho_a~d}THsL9|(vDU%K%60`TixFv9uBbTh(q^>_QcG6BLwH(blG*45Y2S=&e<6`v29 zuyW^vv{%GaLF~J_=%5$tiQ}2Q<3@@hvx%k9q!*99C&9vqv!!OHC5Jx0;M0J4@Ag0-}~W*&CdVFBVJb2m27ak>1{ z&_d|A(0+lgr%7mP86`HYfN@yQy0&>{yu?{~9LOE+oOKRXCksu`YuU-4oEnT8M5Ga6 zOfPD?uLij*xX~z7>29GlPc(7v<{NIrini)Eqb-@v9P-`nojGGX$V);UH@_A%ii@Yf zg7R;G|DzlSd3^};6Su;{rCP|hG)gge#1WG)(Q%M**ke8iG+Nwu#IBQ1tJ=LutV3(( zq7HZb6%@bui;Ls=!In#GCa((|eek{ifq%S|@%hA|?DNE`?$288%kmZOmFw-YUZY08 z&nX)Lk?NQVr!e;_lYIC6Se9jy?2{_S16ggav4n)qD&Fkafw>>hyA5BUE7tq*6-RF@ z4h=>QE~;a;A|iifB4x7eAy8YdaQ(9zsq39hTT6>t`Mrgh$I^CrsIQg{qHc?2+5ojq zt!V*rF;Ny;bYYE`Vm?{;yF`cnmRXw4v>@tKLsB2~^4HtvT0?}sgPSWxE7Q50Hv~4< zL=Q|LSTIjgDBDUat<@rx+wN7UZDw9lqhV`SctfFrI{a?1NuW;M8S&Y<4@(Rg*D5@W zc149kzfV@|DKhUxGe`xIdzk<~Z&03lCZWKuRld_23nR_88vR%{J@)FcbF52=bvCV8 zr31jaH7Fn<8-17WwRpeowjtkZZXy>#f8-HIz=(L*NAL?S=c|zISlMi_QPo#z4;F&; z>U%c25?ZBO)V{FCf|^XgFy%@9G0Ipa{j*!x96UYu`&1N~>4f$A`T|yMi;Z$nyUgb?mqLj(!PUp$5!x*3ElcrRhC1@91x5Si2zvod$j>#Y3MqC!yenJhFznVKPf5@*O zQfv?=a=wo=+fr{=VbV3Y6~*x5dK*cDrBNUkMn2zd8mYm+@GSa;AoyY+583V0GV4BH za2i$RMY9iV*u_ZFhx1de+mrKRuPeqQapEH_J8U&*h|I0K&RLXZwMzTij__4ID=vF- zlVFlR!&X49o|uK`i8x=Vd@Y{m!Mmne<6gISaesvPoo!JdFb&M*n9^VT^jlX0nUkAB zJ8-;fC3CY+m`#5P&2jM!BQ*<|4WrCT>B4nm}}*C*otl6AQIz{=)3M?M8f*wWONY(b}n)ysF&1 z+zWADR*k(g5)*2Xq-tNaCQL7N0AW7(r(ZrB+E?WWHlnPs{+`r<4H0cZEndVuc5EMP zgzv)gCEh~*+wOq4=b1>P=W538+{&`RzQvesT^b@6Fe3X~>H{lO9hm+9m+Nc!Pnc)+ z2co)Ehprw=&&DnzxT{*q!+R#PTOT0vUsq<$=h*5TXQAF^3!y80_GZc?Ov9_Xw2Z+J zxGtK@`XNVMri>l#u*Nq(K)iRmd&KgFzEg|x7(bVTl@L-bnNXD)i=X3W!u9qsW)Hmz zX?5?cZ3|)^vN%!p?eLiJEH z&JMy-iyS=BDes1!zD~X|6v8Esz)ke+5O4Ig*Qc13565d*^AXyrrXjUCvCB7=ES@k= z&UG+#V0odlF?Rnp3SHB#l6_T+l|hL3u8<7^Un{KX*(hc?;+EIv@w3qzFwD9{wS>_+ zAK~&%A?RAWiTJ-`+glOy++EuDw%ppS{%i{t^zZ?j1pMz*?-9Z@cRRy2;AtB9tBzG`*GjdFs<* z!P1=H6WKQjgG-Zg7NV`~D>fO^-MYp#E%euUncG~WF`B5K%ascC9~&x6_|{Gin^V%^ z>#Vl|FX9~gGSH9?iD*cOmwNJBM^i3|+3~I9_dEL-?|x?gwA-RrRqW2J>zbn_5}!ds z6f@t9Q|&zo+eN$8VlrW?&kMuDINq*RJ}SS5I}cHrFK_}BM=00i5*=8}B<#V?e=|_#dPeCOsm_=L}!#wT}s?Ppdsahba(J4B zsHx9Us5xwA-+*ks)vOCP1W!W?1V(W-_@1$icXd2St}rKIxu45|Z?)I_0{@Y4w%DR= z<}+cv+4cpqD<$&m3qSWI0gP_Ci1t$C!fS{+h$xTM9BQ}B39@ffvDWX|q2rt>ClRC| z5X@y&T^uu;BR=QN@c#~9c#+=Qem-QoE1xm1!c!2*z3xNl&XnGrY2}$rMJ?Z;U*31! z-F9QeECd*RKKliO2(60P^MNAn86=hTZl%}p80}UONGTaAuNZpQ!&2Vb$C$^AGnIBt z5v^DJ(ehudoEg6LuSA=3YNUq@JMsm^#55}Q$bKf^tP;Iu=8j&(N%CnlcfTd zuF_>werdFstDO*K#Z}21`i4Dj`Qu`xpAPd?&70pk8)^t#{Aqn4`90-*u!u+SK@m?rFfIMra`4GZqkot zD#dAf^dpe}JCZk%%V3(x9TqUtfVl@IsVyt#>3GhGM&zKqu3F3StVs?vd! zGunASXE|q-dq-nK$yB&02k$;~Q2B+!)Z-#2$|h9an3=#i|- z2&)VTFx66dv2M7Z#YVZ_DRcb!hq9qDlLKOFm&*itgF+)sydw#FkijZl`qv-JkbN$U zNTK%d9O)_$*c5E`zeIh(cjiI0&%YA9>J&2awF1wB~{*RX`-FDz)b5RJI z>EONC7@khX2$;!Nz49Cn^|p`8Yu68_K*Y;%5YIcAOFhry4(mzjVp=9g*pjx7UC?oLj26@gD1Fr;GS6)KK&xB`FDlJ z*q<9eZ!2M5UqLi&b=k2kiIwy`y&iPJ=%eMJLB470Lg+iDOXtQ{bOL#k)rh2oXo0F? z^0zg&!dAe>I8e-bw4Dck%6&bD zgm%Ja>c%peOBZ%4QcBr-p1WV6Aq1D(kRWq+j8X(Gqo)n7?M$)RKSyhXUn<}^zrI#KY|ic15}RiM(I>a}Ufo znscCB-1q*Ps32Q+btCX(vxVh9u8oeQeezdq-+&;$c77so_6M9>Egxm|wB2G3d2;oa z3V@*^!IIIijzx=;T%zqMCET9N-PWzjAL8Z=Y$&%eyzW^AN%K8EY_4R^8-g$bW>pe- z#Xt8wj<^Cx!x2nF

1;vq;lRg7s0XmhgsYStn7ll}7MDoU({U{^&jKRRRrd>!sSv zO)H-7bA<#cRi-vj8bVRI;8{s84D<$U1ZM;1du_@rjxt zUfjuGwa;5*WU{<#YTj^1pn*qJf3{15hkjt>9ld`(Rp>q^W4wPAVZak+tlv7iuI^Ut z^);d8+lORhqH4A1)%>$@ON@7}Rg_uoxJfUKKjkGB8k0iYvY89e&2gNX*;r|)aKpRZ zjo`E|b<~Dndu#qG@g5N#uWa#Jb~4#$g}dE6j!XEETq(2o-gyKWI_Vo8i&ZVj!Z%)~ zYtWkOk5&|8oivIU)n=cO#%h}LY3}1cY9Li_!EdafHkA{r9eQcfWjL&0VR(go(_`L2 z#A&geXX4l%Pu~$^3ob{?GjL*i_S_l1(OLP5FoKKa_H`9n^R_o|bN7f}`j%;oh^Gn= z0{A0{nSoJqro0Yp>EXXkLgiPCMR}8H49$l?d0aUN4ixbB*GpI zF<%T(!apT%sl!FMic+HDV9U1&-Y*ta$bbeb3Dtn)j2o=9^kUKlFFhB<4EMM97G?fF)BzYT)#$ng5PiB#rj>vT8pX$ z_Z}?dl+@?(m3sHEN@sQU#{FA@T4%I1HCoHx1|l=#9{Xl+c?93}WJ_iTwIJR=LLoQg zI$m&EO{;{490;P$M%Qaq#p}Pc+7k}lkV|LVF`@fHbv)(cq8RtE!7<8Tj**{if|kKl zk5`sH@`3?YFHZN{5x<}p%@4U_y3+w_HLXQ=%O4*SP}qKeSd7Qms-!pWJr4ZPoIwh8 z5`qx7J|7HTKgnggTV$QNQR72{GKoj|zdMz!IC!!54NYlhG07^mXZTv*kF0;%psB2YjU{}I#mLcKKJ0ZJAw6x>(%YCeB`g!(JR7zdkrq$wx$`Q z4AG8KN`Z{bSV1&gqBQeB`5@E-F3%9VPMFl{0coVhUhe)hkf&8KureCv{e9s8z?rAJ z`Ic-!PV*}T0ACPRyt>mAB&f;F#IG}#R)oHUjL~Zcu*Mb;DHSOt&SRY~?tT{ix29MZ zpS1mePy^C(K!xpUByU%)f(6)3bUH9(Omj;uw(aq;o#1NiEHD%)5I}ZB+#e8lU-As0 zEeGbq5)cfi9$C zqZbajhwAs5${l14=Aw4EB+S2!6)1&9sKNIF6_LEK9Dz?^l>oD0dVF)5Nd5jDb{7KK&ELgp5Q~b^%I!l7Y zQ=2!h|M$Cn*t|u1Ol9#^YG=GCC))E8aOZvVM2bi2f;I3@hQDHP?^MkD^!F7bG4J)N zc84z(3UK)`LeP`m*5s*4c?pN~0Kn4C0jK2gW0j2YlI$1(1rbE>>m2Xt$pIIIy0jOY zfGnh3n~08xYVj5Qv)ohhjz^OlCsK2L8 z(Z-Z%f@D&f3J)D4MLlN#e3JUOMn0FxUA7$(|4dBc2-O~*yC@cAmH!A3c7L27d+xBH zrR03B%;eK+g)pfW41B)C-+yE>eAUx$W(0PFjrTv<`y<2|A3VNts;@nf-GlAFqy2#BG+ zF8}15hi}u3XXiV)?y7jpOekOyTuB$6fh3H$a)+Y5iS+OHXnSrlR5-eH_a)O}arzHv zoIm#$>%3Yp^SDWe+Dw_nc_Hf%L#|=%j~&)JS5V9fMufPPc}Lv9Wi>06t}h~7K{*5Q zEP&T!MAi4=%^&BE>zy6CZ_ufFoeSdjpMqK^<%#Q>hG>Po4~bv*tC_m6zfAL7aFjTK z*mN3h@XSf;#)8kEUXZ6yOJm29EO!_)A2Q#*z{yS~VVmSt?jNK^$rQdn%U(g{w!~X6 z;Ne97uJ1_*JmAp&4>_eRw~5Db4=?^u{rVy6=#t41zl{X$ma(*>(`i@%BoQqE2WscU ze_!{QKr^E>$?ocQ1t~CDOzsxW6Ki2f#m>^4EacTy9tQSb0fJLV6}q1+iKL}Z;)U9? zpG-*=?FPsK>@!Kbu~-8hnIK7I*!@2@^8mJX65ns#a}VA1bC8;!yw}-V8jzA&mB@Jx z6Ur9~S_+Ao&?h+h_)@i!qhR2Em=aF$z2xG5y-t;> zwrfR7Up?p1uI-M|)$Q9R9lMCg51GonhF@+OiZKpH^qGbq3`gm^sr>#ymo`7*tu2urRzig|#e-l$Ew!txu&a@|cU^uj((Jme~AHyFtSoPr>}v9rlVRL+6| zhi1tBCCes=aR`kyEJJP9FWLX-LEe5tyr8>$ES30~MMJ+bYV&C9tO%rF-DkyTKP)Bh z{FhpYSIMe{dfX#1uy<>T&;+&US`jco$2frt{OiN!r-$OwxGNtCir#k2uemW15azeC zPxQ)n{Yp)ck}az-h-FV?sQ55cI@}lqm@N$EWz@=Z>LtCUsU>4Znin5HPy~cDk~qx4 zL?1s<#&aw>2k>rh(+7UC^YzgTa%^wN(*T!~g$6u1@r3HU!4Ct+8e<7O5cIP3e%+bd zoYYcJ!iHW31bw~GE4IbY<<1*r*7d>X;c057h$rh}vCiE2r`Y0JjJ~qG0@(u=JSc7Y zj=JHxU#^Cy_Iy0ZrWm5WN^pJ}ewM7~8NZ6_sa*#tAQO&XQ&ctLb(ri}-rFhT8Io!W zD$xm+>?0X1m8Au7Uv|ho#CKl{cj#2-pq2Pzg&8FsdN%yp{uud*sA6kN;#<#%_H|v6 zdUXfz+J~-6&9ZXsDd|=pk$P@flcZf((c3B)BQE7`jsGG-;m0=>>s42<5HwajIveT3 zZy-$Ttg9vq#yudU%L66_C^<9OLq@iMd7Py{6UmU21$fs1El7R^MuRMx*}eC7bzl!WYzIasUhD4#bIaG5P1(SN#TDXz-r* zf&h&poeR~S@@Ik~`2VMcbMa^L{r~vA8QPo@Qxb`&9FmWmKF*0kMJMMRQVk;{=ZzUl z5&Gm)gl1HqRI?E)$8FA)!$x8ijVV(ObC~ArclUk#{sH%OU-z}^dV625=W|viWhnx3 zk1D<+5PGUywg|BJ5(bm_l@IVDnA$fau)Ds4GqdQ;&|a#GZSOc}kwSY2Q>6x2;evuU zJbrsq1`jp=nG=rr>L$C2rIZ4Tr$7J|px0hZ!*)v_(D=Q1 zXq4uU*e_O}BRgt&$88jmYyzmXN$;8e3S5KArZs9#&_C{-mVaK0RvEu8ZP!T(nv(L4 z=&a;j%8mmOOt#_VE^rJ1U^3W#-u}3&n44s#f1fT!VBxQNRxGq#d7?48V?$VyvS!cN zwl4ILqnq(pBr6tOmo?er62P?`+biIei}HHBTlD!gBoka3-wU=6nE-?e&R3uk911~o zfDcbTfX{6iZW#L5sfs$anD|X>LnhdRBmokb)O5^mHCVK-4|&!KvE;Ht;rs9!Z(&_y zF4NyCI9#^-hxy{TOIJ0ya-+LM2KOHmYqRkw)!xRNB@S44;bt2)bfvwk)uDj!?D8GrO zYG13a7*X0pV=>*7(g8NR8Cck_{G+ntMnm_i&3-BqdWxpX_br{DxnOi|h8fE5_YgRY zcDvj*Fif7>rcz7F66^+gjqgdQheN?oy?A69Tsxtm?N}ZfUvwqQ13Ghpl)O#ggf-2{ z{7^M*=X-YS;l#}J#;5vc3HeK`UEl8_GZQxCBU7;dta2Oed8V$!_Yam!S@jvKFJccH z<5m`GAmyEitqTh3<<)NM{imY>BwmL?F<-g^3gqBVA@}wxgx@b3y{L&(k}w(50#n() zvI;g&>yXqs)IPjU@Qgyl`BBY818IKQ)gYK3V+T&W_sq{g>}wLwg{! z@vQSr)9F;dQLXu|kL(xdQElYbBPt-)VnUK=t=A?#?Ky6rN4~hO^k2p&9<6+Pu+5H- z2iQsdX4=_(@h*!b+<~5abDyfIX)|m;S6NIiR%8QRb<@4m?)jczUc~P=`Wzi{9ZOs? z8xNhh?>8XLFhmUj1K>T{iMv!RzCq&f^ewg{&R)j(AJc;j=(PZetF}zBtNlfh3M1*P zr>66-#NeC7U<>~Pcr~2Yag81ub~x73NHUg-wCil2-8?~}n_b6zZ>g?P*nAcpZ2jE* zW!|CnPeTi5*295?qmk3B+Vu!XOZH6wH446#d79CYK{2z-keuDNd50fyTgg{@b_9cW z8=H5&l~hH}Saq^%`Aw=G(MeXKUz<(0z$c*WHqttR{oG|ps7h27iY*Z^9Q@zkULjYO z?x$Bn$ZaXc+ZMcUYMQ=*j~0x~oWezZf_Zjf_1Y-#Ih#-~WPlQ6RyMS=1b!lU#V1A3 zlysIni_A~nItlU;USrYM-CIidtmp%e_|?B$vW4Px{q4^TuFy)sFfQ)*(VKJnkwL1> zh7BsdSn*v?ztdB{j7?uBho21tD&Jq1_m&1xJAjfF-d76#FA&J57BKSL8ZuXIqlk}c zg=;7~Y>~A+Z=x8CNFFnfp0!M}LKk24zh{CQ>5BT*l0W_uUT#;{IWeUs$;H<_lC6P{ z9%&qa?FKj7$uOAyyR(L)dbb_^S;S?PR0~(!7_3!`5_6t%l zo;8cH=v(Gpp?D+uM|^gG)+WOLWrJzZ2++IXgDX;bTJy1j4s}me5$XgCis|ogq7MMq z&XNc;+xs*Z(uPif;VHWKtC$beTR*F#gnBjb_+Cpiv10T6p`<~}pxNiz?und`QW-#h zj%?siWZO<{+6~+Ao7{GkV*-Jy&q<6hSNubRq1Q&kVM_0zhlENKr&13aL)r5lCxR@x z{Kd07qo!m%%1T-?7VlQ1vl2(ia~}M?s~W>_2FB=SY<8DF^mihmR)evpiT2Q6~f4#Y_NJ3Ttx! zh~~SnCD_`L$~%u@hJoJFoJkG^UL&=;=1#3pEAowejhp`9%K%HcxYNw;kdo!y1vK4? zMQ7onUQhJX$Nbwd!?{KuydJj*9_3pt($@AhmeDsw2a`F7* zx!m45RFgr|q0J&Yer^<{XtLnUuUe;lByF&`zOw9ZZfMAE>o$N4zO7X}C$Aeupz8!= z1@A*LGFn@C`@lG*D@M<|$lFO@cb%xr%0`V(*UdM^pE1iT?)hXcvZVIb$>3J3_`$c9 z!l1tp!CaZV7}@--)_nomYK3}vsB1JG+oUF~wcoY< zbDU!!`_sxoe^7!zFgaXQ@ID{Z)FktwNWWXEP{$G_0#yK^IH?j@$L}^&`f?;p8)v2X zlHa@2!$FYJ-MaNfZjk#(&MLpyffH@U;u@a8Y>M5#fgU(3eg(hHxo@8%{UiRrL`Tb=)2+(i^;UUfcPZc2^N2|-n!$emYr|{O+X**5}aNiM%tk&?D+utC=*$a>V-sm}|T`Nk=q6xJQo2Lo?$zp&C^e9zzsK*1?ocBdB;3s~0p{PND7L*hqJ-B_59Kaw>^K+>O@`Y_T^oa}9rPrG zHJ@5tN6gW~6mUw(pSC&wscY{9xiMPM(^m+&OPE6eFKTsvJ0-`_r)qO)zkQdrem=)= z*Fi8jF#elomT?m0L)UVf3{YUpx$LE$RYv*>yQVqk$AHB@l(^hCY%hsC>~ssc@)8pK z7@g|b>S$Y)vm5fKQarH9w9NGza{l!S)TXd5whN>#Yb6U-8c@M;Ipqu#YH7mX7)Var zyu(~6i;C~?9WrW9Zm6#A$T$i_)ydb&4VHNwk-EBXeFqM4X^iC<@MJO{K-Yo*b)NHm zWVDK%3XV7Ay?=7?UKvfko9A?-qF{)jJ7GSZ(D$%db=rB^laR81)6XcDj<#i54-Q6; z=07P}ppPKIqCIG$;@dj$1yPgLQ&&CjIF=={(*O257tc|W_1<0x;D752hHTq&e^?7$ zB}-@pYO=UIZ7+Er7=exk*gT(_KmLW`SA^+Ze>@q~oP^(rJsfl=QJE}U7fRcSSIk`% z&yC69x6_8Z3cb**w%H!)91Xi@uad!kA7ifTDH7xNw(blCm>ZSsW9N?Uh%nr4D8Arg z3mOkR-$xt;3MCfxE2nz#I^GCUx$f^v3b<;xXPei%wjy>* zP(pfgls@v#9%R6_$1z~;LKk3RPt7}u9EWu!50e$B!1mVb>~B>^8J0?RVr#TOXPTb7 zhz^bAcdhCAP||ZRRwB63kE&P zdG|p;jzg!y2?ln5PVe~?^af4KxIgi5joX;FhZks-C?-k{U9&;kjgXeUHLb`uM5GXM zW7K4De9!UoO)Kr;9!cDMTn$q{xCrMD1slUjy;J!(LW#H};uCaVuvc^bMi0t6Ko4F2 zTd&rA??f%QU{!m28)cq9d*U@`{_@?aDwCuBgYOeHyl<1_ z7ZtY@tr_hHYbEuN+h4J8&)Q_T&=u;ymB7)Qgf2M#CDsxoY5d4j zGc`aiwYWtP^Rrs1p=M5>o&+i}*oFl|LoIx6lI+A{Q>?FrQx6D_d#6t&xV3RIle7}U z2`r8ku;#5WbuAp5rW;D2hXP23zcj^&C6<7)VJ_cLjnKnHm0XNi(+VgpjktMy#wXbX zN}kRKdT@?x`!T;+s=EHagdz=(W$(_%7FoRoOUg;3!>$b)94|xafx{d0)@O@`DWb%y zabZ1U&dbEKOs_Ll=+fxtb0bBKo(jRL*yuHFk5RCAd9nOxs%USbk}t#9z+l|P7~Fac zAe>e>sOs*ztVl4(Vm?`MNnH_wAo&kOX+C9fJE#>&>a|Fl*^%;eZg#g1Q& z+tQ0gJr#L?S)fez-#%!43W5G) z5d(%#S+tQ8uivg&+zQA++jR!``DZ0KCeGBx=9DJH_!h>YZ6DL_?+$Tc*{3Wj4+Vvb zjCW3aUR8H5$H^bPFq%ofu#B`pFHb}?eID|@++0@=dS=wGFKUgJR?gjX1dyV$n)kXF zrSQhVFv?f4Ck9F~I=-2|#`3jH!CL;tUBNytz_Cl%YUHa9lv`0JVz968FNX zL3bZ_PR;?o5oLCm{1R#9R3n>+U zGk1HZyymsz6-;CUujDk-KvLzl%vCjY=B5(svW{nP)pJgq(yFii&2Ulbtd9kJ!gIRg z#AKZ(=qU7kbKTp?k9NNp?b3c}sy4d*;aa5uv(R+$v_2^!EL|G=vQ6_i3o+BlT5xNq5e&zg`>UGr$=AId>L9V)9-;a<%j$DO3T3>i~emM_mT@!T>({2NLu@)@V_G9KbBW>YySf$!FImBg$ zTKaor&1t41DMl{@W*uZyB`;L3w_(2FSZ&*L_lA}*WlOHd!AV*GY|X z0WFSTf7vAD%=5?N6!DS00ol|QjS|pyr|AbC1Yns{B|_4{8S{-BJZZC^O>B+m1KQSh zr)D&_j+Le&h8#zSa1pB}soq7nY^L_*pr{SCQyUP83xSDdHF*|e`ImwmL@yu1KAt(+ z`Nb)Sa;a~<;FYGy^VewRDv(+wUtI@2Y;T_?2f^S`Cv(#UejSm6BVzvm~d0#vDHVER;5in2ueeH+Qw zD$Ebzd&XjMpHLeI9B*h~jdU+?ztEe(hG64`PTgaRhM}R#h7X*5Rj;=GciG_ zP1mMr1D#;h<8r!~!NL|)7#&62$M)-}hUm?0+Q6U6*xKp1 zfgc9YnZ5A|M)HSR^Sv7!*=e$=Z!#PcE8SyFDGwHR|8WgQ<%}u58lpAKe{jZC_}|SQ zzdKh&pAT%mG%vFDg>z}Tn2seU=*(5jjZ}#%lS4p$>k1`J02N z(UJR%47Mo%{R<#*it`E5TNf&DjAHfx)*rgKN;h56RZ z6cd~ie>y!P?}gl}Jz_KFpe7X=zr~P=--T2kd@BU4hhY6$)ZA#Jk~&3`=SWvByZw3| zX(_ieHpc^YLWGNz#Fj_oh6MTimnpY01XBw8gk7BMoFbG0N!e`v%QT0v%bj#~B2EBiW6Bn<}X*%2;89eR@)p@pg7 zU3{0>5c@67`r{G^1Ww6;APVT2tcDD4&kcdO{iEaA=3}S3@Ok^5q!APeT}J_bp>Bhw z*b2g*8tJWVp8wgCZjg&^2r@nmarUf^TbmAY@e1La;q>BpVWstC5H{a7Nw&ln+0~{nNX;2bN=59Zgq{fn%vuzY`C2A_m?juW~k6RwMP$uJKaOjd5?~zuk zDX{?qY%yIW7t}<3^U->(Q4r)gf0JCRV^R(nz)PY)Lzn<2*Pt|=yh@_Jo(CnP<5_Tj z%xP--+U9=X?g3;z89+Y6SKyHGo&DOCh5SWIhJFKebHEu}GH-iiMpoDGln(JwIiiBs z`VeuUN@w)Y&+A{3i0LMg?vR#P)?BTk72Z zTadM@yU|Lxa&eDGnWq^|CfPUJrKz!tJ;(;KhxF^xRu$yfYKZTXO6i1a?xl0O)Ni2Dtq|=Ii7jG@jUxg6u)csM=gDFYCm|T z#TwtKu--;heO%kK6B2p%QWf4O3h~AlzJ5~3jtRZG5e0gTOIuPAFt`|MqQrp#kV*)@@ULUJy65NF4w2dd)%t^h4i1b?@>keO>RFJ%ZVu zl@nxt-9O=hzt?&AlI5l{q+m@0=qU;cgZ~H6EN0WOU!`II4v`)*RQ(kudL2=W> zC5TWB93=M^IK?tiMd18Infp~i9|xHcMy8%{M}6ZQNJ!+scSSAtGlrtoNmCB3eiO71 za&K`@fgd*bBirQ7+(ZOlP!u+tH6NQvNqGwPbM ax@94jVrlnX4i5^s0Vjtu$0^4G@c##|V&2~X literal 0 HcmV?d00001 From 2e287447ff03abbe0e93f07613151ab485dc9305 Mon Sep 17 00:00:00 2001 From: hppeng Date: Fri, 24 Jun 2022 04:48:48 -0700 Subject: [PATCH 13/68] Add some display info to atree --- js/atree_constants.js | 263 ++++++++++++++++++++++++++---------------- 1 file changed, 162 insertions(+), 101 deletions(-) diff --git a/js/atree_constants.js b/js/atree_constants.js index add793f..26dc309 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -2028,7 +2028,8 @@ const atrees = "cost": 1, "display": { "row": 0, - "col": 4 + "col": 4, + "icon": "node_4" }, "properties": { "aoe": 4, @@ -2072,7 +2073,8 @@ const atrees = "cost": 1, "display": { "row": 2, - "col": 4 + "col": 4, + "icon": "node_0" }, "properties": { "melee_range": 1 @@ -2102,7 +2104,8 @@ const atrees = "cost": 1, "display": { "row": 2, - "col": 2 + "col": 2, + "icon": "node_0" }, "properties": { @@ -2126,7 +2129,8 @@ const atrees = "cost": 1, "display": { "row": 4, - "col": 4 + "col": 4, + "icon": "node_1" }, "properties": { "range": 3 @@ -2163,7 +2167,8 @@ const atrees = "cost": 1, "display": { "row": 6, - "col": 4 + "col": 4, + "icon": "node_4" }, "properties": { }, @@ -2206,7 +2211,8 @@ const atrees = "cost": 1, "display": { "row": 9, - "col": 1 + "col": 1, + "icon": "node_1" }, "properties": { "aoe": 4 @@ -2233,7 +2239,8 @@ const atrees = "cost": 1, "display": { "row": 6, - "col": 2 + "col": 2, + "icon": "node_0" }, "properties": { }, @@ -2272,7 +2279,8 @@ const atrees = "cost": 1, "display": { "row": 6, - "col": 6 + "col": 6, + "icon": "node_0" }, "properties": { }, @@ -2321,7 +2329,8 @@ const atrees = "cost": 1, "display": { "row": 8, - "col": 2 + "col": 2, + "icon": "node_4" }, "properties": { "aoe": 3, @@ -2366,7 +2375,8 @@ const atrees = "cost": 1, "display": { "row": 8, - "col": 4 + "col": 4, + "icon": "node_0" }, "properties": { }, @@ -2390,7 +2400,8 @@ const atrees = "cost": 1, "display": { "row": 8, - "col": 6 + "col": 6, + "icon": "node_4" }, "properties": { "duration": 30, @@ -2429,7 +2440,8 @@ const atrees = "cost": 1, "display": { "row": 10, - "col": 0 + "col": 0, + "icon": "node_0" }, "properties": { }, @@ -2463,7 +2475,8 @@ const atrees = "cost": 1, "display": { "row": 10, - "col": 2 + "col": 2, + "icon": "node_0" }, "properties": { }, @@ -2497,7 +2510,8 @@ const atrees = "cost": 1, "display": { "row": 11, - "col": 4 + "col": 4, + "icon": "node_0" }, "properties": { }, @@ -2531,7 +2545,8 @@ const atrees = "cost": 1, "display": { "row": 10, - "col": 6 + "col": 6, + "icon": "node_0" }, "properties": { }, @@ -2565,7 +2580,8 @@ const atrees = "cost": 1, "display": { "row": 10, - "col": 8 + "col": 8, + "icon": "node_0" }, "properties": { }, @@ -2599,7 +2615,8 @@ const atrees = "cost": 2, "display": { "row": 12, - "col": 0 + "col": 0, + "icon": "node_1" }, "properties": { "range": 6 @@ -2635,7 +2652,8 @@ const atrees = "cost": 2, "display": { "row": 12, - "col": 2 + "col": 2, + "icon": "node_1" }, "properties": { }, @@ -2670,7 +2688,8 @@ const atrees = "cost": 2, "display": { "row": 13, - "col": 4 + "col": 4, + "icon": "node_1" }, "properties": { "range": 4 @@ -2702,7 +2721,8 @@ const atrees = "cost": 2, "display": { "row": 12, - "col": 6 + "col": 6, + "icon": "node_1" }, "properties": { "aoe": 2 @@ -2729,7 +2749,8 @@ const atrees = "cost": 2, "display": { "row": 12, - "col": 8 + "col": 8, + "icon": "node_1" }, "properties": { "duration": 3, @@ -2775,7 +2796,8 @@ const atrees = "cost": 1, "display": { "row": 13, - "col": 7 + "col": 7, + "icon": "node_0" }, "properties": { }, @@ -2801,7 +2823,8 @@ const atrees = "cost": 2, "display": { "row": 15, - "col": 2 + "col": 2, + "icon": "node_3" }, "properties": { }, @@ -2821,7 +2844,8 @@ const atrees = "cost": 2, "display": { "row": 15, - "col": 4 + "col": 4, + "icon": "node_1" }, "properties": { "chance": 30 @@ -2848,7 +2872,8 @@ const atrees = "cost": 2, "display": { "row": 15, - "col": 7 + "col": 7, + "icon": "node_3" }, "properties": { "mantle_charge": 3 @@ -2869,7 +2894,8 @@ const atrees = "cost": 2, "display": { "row": 16, - "col": 1 + "col": 1, + "icon": "node_3" }, "properties": { "cooldown": 15 @@ -2901,7 +2927,8 @@ const atrees = "cost": 1, "display": { "row": 17, - "col": 0 + "col": 0, + "icon": "node_0" }, "properties": { "melee_range": 1 @@ -2931,7 +2958,8 @@ const atrees = "cost": 1, "display": { "row": 17, - "col": 3 + "col": 3, + "icon": "node_0" }, "properties": { }, @@ -2955,7 +2983,8 @@ const atrees = "cost": 2, "display": { "row": 17, - "col": 5 + "col": 5, + "icon": "node_1" }, "properties": { }, @@ -2975,7 +3004,8 @@ const atrees = "cost": 1, "display": { "row": 17, - "col": 7 + "col": 7, + "icon": "node_1" }, "properties": { }, @@ -2999,7 +3029,8 @@ const atrees = "cost": 1, "display": { "row": 18, - "col": 2 + "col": 2, + "icon": "node_0" }, "properties": { }, @@ -3028,7 +3059,8 @@ const atrees = "cost": 2, "display": { "row": 18, - "col": 6 + "col": 6, + "icon": "node_1" }, "properties": { @@ -3055,7 +3087,8 @@ const atrees = "cost": 2, "display": { "row": 20, - "col": 0 + "col": 0, + "icon": "node_2" }, "properties": { }, @@ -3090,7 +3123,8 @@ const atrees = "cost": 2, "display": { "row": 20, - "col": 3 + "col": 3, + "icon": "node_1" }, "properties": { }, @@ -3111,12 +3145,13 @@ const atrees = "archetype": "Paladin", "archetype_req": 0, "parents": ["Manachism", "Flying Kick"], - "dependencies": [], + "dependencies": ["Mantle of the Bovemists"], "blockers": [], "cost": 1, "display": { "row": 20, - "col": 6 + "col": 6, + "icon": "node_0" }, "properties": { "mantle_charge": 2 @@ -3137,7 +3172,8 @@ const atrees = "cost": 2, "display": { "row": 20, - "col": 8 + "col": 8, + "icon": "node_2" }, "properties": { "cooldown": 1 @@ -3158,7 +3194,8 @@ const atrees = "cost": 2, "display": { "row": 22, - "col": 0 + "col": 0, + "icon": "node_1" }, "properties": { }, @@ -3184,7 +3221,8 @@ const atrees = "cost": 2, "display": { "row": 22, - "col": 2 + "col": 2, + "icon": "node_2" }, "properties": { "damage_bonus": 30, @@ -3210,7 +3248,8 @@ const atrees = "cost": 1, "display": { "row": 22, - "col": 4 + "col": 4, + "icon": "node_0" }, "properties": { "chance": 30 @@ -3231,7 +3270,8 @@ const atrees = "cost": 1, "display": { "row": 22, - "col": 6 + "col": 6, + "icon": "node_0" }, "properties": { }, @@ -3267,7 +3307,8 @@ const atrees = "cost": 1, "display": { "row": 22, - "col": 8 + "col": 8, + "icon": "node_0" }, "properties": { }, @@ -3293,7 +3334,8 @@ const atrees = "cost": 2, "display": { "row": 23, - "col": 1 + "col": 1, + "icon": "node_1" }, "properties": { }, @@ -3313,7 +3355,8 @@ const atrees = "cost": 2, "display": { "row": 24, - "col": 2 + "col": 2, + "icon": "node_1" }, "properties": { }, @@ -3348,7 +3391,8 @@ const atrees = "cost": 2, "display": { "row": 23, - "col": 5 + "col": 5, + "icon": "node_1" }, "properties": { "aoe": 4 @@ -3375,7 +3419,8 @@ const atrees = "cost": 2, "display": { "row": 23, - "col": 7 + "col": 7, + "icon": "node_3" }, "properties": { }, @@ -3395,7 +3440,8 @@ const atrees = "cost": 1, "display": { "row": 26, - "col": 0 + "col": 0, + "icon": "node_0" }, "properties": { "cooldown": -5 @@ -3427,7 +3473,8 @@ const atrees = "cost": 1, "display": { "row": 26, - "col": 2 + "col": 2, + "icon": "node_0" }, "properties": { }, @@ -3462,7 +3509,8 @@ const atrees = "cost": 2, "display": { "row": 26, - "col": 4 + "col": 4, + "icon": "node_1" }, "properties": { "range": 2 @@ -3489,7 +3537,8 @@ const atrees = "cost": 2, "display": { "row": 26, - "col": 7 + "col": 7, + "icon": "node_1" }, "properties": { }, @@ -3518,7 +3567,8 @@ const atrees = "cost": 2, "display": { "row": 27, - "col": 1 + "col": 1, + "icon": "node_2" }, "properties": { "duration": 5 @@ -3539,7 +3589,8 @@ const atrees = "cost": 2, "display": { "row": 27, - "col": 6 + "col": 6, + "icon": "node_1" }, "properties": { }, @@ -3565,7 +3616,8 @@ const atrees = "cost": 2, "display": { "row": 27, - "col": 8 + "col": 8, + "icon": "node_2" }, "properties": { "aoe": 6 @@ -3592,7 +3644,8 @@ const atrees = "cost": 2, "display": { "row": 28, - "col": 0 + "col": 0, + "icon": "node_2" }, "properties": { }, @@ -3623,7 +3676,8 @@ const atrees = "cost": 2, "display": { "row": 28, - "col": 2 + "col": 2, + "icon": "node_1" }, "properties": { "aoe": 16 @@ -3668,7 +3722,8 @@ const atrees = "cost": 1, "display": { "row": 28, - "col": 4 + "col": 4, + "icon": "node_0" }, "properties": { }, @@ -3702,7 +3757,8 @@ const atrees = "cost": 2, "display": { "row": 29, - "col": 1 + "col": 1, + "icon": "node_1" }, "properties": { }, @@ -3722,7 +3778,8 @@ const atrees = "cost": 1, "display": { "row": 29, - "col": 3 + "col": 3, + "icon": "node_0" }, "properties": { }, @@ -3748,7 +3805,8 @@ const atrees = "cost": 2, "display": { "row": 29, - "col": 5 + "col": 5, + "icon": "node_2" }, "properties": { "cooldown": 15 @@ -3769,7 +3827,8 @@ const atrees = "cost": 1, "display": { "row": 29, - "col": 7 + "col": 7, + "icon": "node_0" }, "properties": { }, @@ -3793,7 +3852,8 @@ const atrees = "cost": 1, "display": { "row": 31, - "col": 0 + "col": 0, + "icon": "node_0" }, "properties": { }, @@ -3817,7 +3877,8 @@ const atrees = "cost": 2, "display": { "row": 31, - "col": 2 + "col": 2, + "icon": "node_3" }, "properties": { }, @@ -3841,22 +3902,30 @@ const atrees = "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", "archetype": "Battle Monk", "archetype_req": 8, - "parents": ["Spirit of the Rabbit"], + "parents": ["Cyclone"], "dependencies": [], "blockers": [], "cost": 2, "display": { - "row": 31, - "col": 4 - }, - "properties": { - "aoe": 2 + "row": 32, + "col": 5, + "icon": "node_1" }, + "properties": {}, "effects": [ { "type": "convert_spell_conv", "target_part": "all", "conversion": "thunder" + }, + { + "type": "raw_stat", + "bonuses": [{ + "type": "prop", + "abil_name": "Bash", + "name": "aoe", + "value": 3 + }] } ] }, @@ -3871,8 +3940,9 @@ const atrees = "blockers": [], "cost": 1, "display": { - "row": 32, - "col": 5 + "row": 31, + "col": 4 + "icon": "node_1" }, "properties": { "aoe": 4, @@ -3910,13 +3980,11 @@ const atrees = "cost": 2, "display": { "row": 32, - "col": 7 + "col": 7, + "icon": "node_3" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [] }, { @@ -3930,13 +3998,11 @@ const atrees = "cost": 2, "display": { "row": 34, - "col": 1 + "col": 1, + "icon": "node_3" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [] }, { @@ -3950,13 +4016,11 @@ const atrees = "cost": 1, "display": { "row": 35, - "col": 2 + "col": 2, + "icon": "node_1" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [] }, { @@ -3970,13 +4034,11 @@ const atrees = "cost": 2, "display": { "row": 35, - "col": 4 + "col": 4, + "icon": "node_2" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [] }, { @@ -3990,10 +4052,10 @@ const atrees = "cost": 1, "display": { "row": 35, - "col": 6 - }, - "properties": { + "col": 6, + "icon": "node_0" }, + "properties": {}, "effects": [ { "type": "add_spell_prop", @@ -4014,15 +4076,14 @@ const atrees = "cost": 2, "display": { "row": 35, - "col": 8 + "col": 8, + "icon": "node_1" }, "properties": { "duration": 3, "aoe": 12 }, - "effects": [ - - ] + "effects": [] } ], } From eb84f1de6e1d40e40aa03b6d9406e6bf7039fafc Mon Sep 17 00:00:00 2001 From: hppeng Date: Fri, 24 Jun 2022 04:56:56 -0700 Subject: [PATCH 14/68] Rudimentary display code and repair atree file --- js/atree_constants.js | 6 +++--- js/atree_constants_min.js | 3 +-- js/display_atree.js | 6 +++++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/js/atree_constants.js b/js/atree_constants.js index 26dc309..765249f 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -3871,7 +3871,7 @@ const atrees = "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", "archetype": "Battle Monk", "archetype_req": 12, - "parents": ["Thunderclap"], + "parents": ["Cyclone"], "dependencies": [], "blockers": [], "cost": 2, @@ -3935,13 +3935,13 @@ const atrees = "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", "archetype": "Battle Monk", "archetype_req": 0, - "parents": ["Thunderclap"], + "parents": ["Spirit of the Rabbit"], "dependencies": [], "blockers": [], "cost": 1, "display": { "row": 31, - "col": 4 + "col": 4, "icon": "node_1" }, "properties": { diff --git a/js/atree_constants_min.js b/js/atree_constants_min.js index 714b6d0..73d3e29 100644 --- a/js/atree_constants_min.js +++ b/js/atree_constants_min.js @@ -1,2 +1 @@ -// Minified version of js/atree_constants.js -const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:["Power Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}]},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:["Heart Shatter"],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}]},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}]},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:["Phantom Ray","Fire Mastery","Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}]},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:["Fire Creep","Earth Mastery"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}]},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:["Thunder Mastery","Arrow Rain"],dependencies:["Arrow Storm"],blockers:["Phantom Ray"],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}]},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:["Double Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}]},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:["Triple Shots","Frenzy"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}]},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}]},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:["Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}]},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:["Guardian Angels","Cheaper Arrow Storm"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}]},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:["Focus","More Shields","Cheaper Arrow Storm"],dependencies:[],blockers:["Escape Artist"],cost:2,display:{row:21,col:5},properties:{range:20},effects:[]},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:["Grappling Hook","More Shields"],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:["More Focus","Traveler"],dependencies:["Focus"],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}]},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:["Refined Gunpowder","Traveler"],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}]},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:["Twain's Arc"],dependencies:["Fire Creep"],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}]},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:["Refined Gunpowder","Homing Shots"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[]},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:["Twain's Arc","Better Arrow Shield","Homing Shots"],dependencies:["Arrow Bomb"],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:["More Traps","Better Arrow Shield"],dependencies:["Fire Creep"],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}]},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:["Better Guardian Angels","Leap"],dependencies:[],blockers:["Grappling Hook"],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}]},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:["Shocking Bomb","Better Arrow Shield","Cheaper Arrow Storm (2)"],dependencies:["Focus"],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}]},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:["Initiator","Cheaper Arrow Storm (2)"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:["Precise Shot","Escape Artist"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}]},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:["Shrapnel Bomb"],dependencies:["Fierce Stomp"],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}]},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:["Cheaper Arrow Shield"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}]},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:["Cheaper Escape (2)"],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}]},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}]},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:["Geyser Stomp","More Focus (2)"],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3}},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:["Snow Storm"],dependencies:["Guardian Angels"],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}]},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:["Grape Bomb","Cheaper Arrow Bomb (2)"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}]},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:["Arrow Bomb"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}]},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Grappling Hook","Windstorm","Focus"],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Arrow Storm","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:["Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Escape","Thunder Mastery","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Thunder Mastery","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:["Grappling Hook","Basaltic Trap"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2}},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:["Windy Feet"],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}]},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}]},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:["Bouncing Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2}},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:["Mana Trap","Shocking Bomb","Twain's Arc"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}]},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:["Leap","Homing Shots"],dependencies:["Leap"],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1}},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:["Escape Artist","Homing Shots"],dependencies:["Guardian Angels"],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}]},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Initiator","Mana Trap"],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Better Guardian Angels","Cheaper Arrow Shield","Arrow Hurricane"],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}]},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:["Precise Shot","Initiator"],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:["Cheaper Arrow Storm (2)","Initiator"],dependencies:["Arrow Bomb"],blockers:[],cost:1,display:{row:33,col:6},properties:{}},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Call of the Hound","Decimator"],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:["Cheaper Escape (2)"],dependencies:["Grappling Hook"],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8}},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["More Focus (2)","Minefield"],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:["More Shields"],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}]},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:["Leap","Shocking Bomb"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[]},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:["Arrow Hurricane","Precise Shot"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}]},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:["Geyser Stomp"],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[]},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Power Shots"],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Rain","Frenzy"],dependencies:["Double Shots"],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Double Shots"],cost:1,display:{row:7,col:6},properties:{},effects:[]},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:["Phantom Ray"],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:3}]},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Storm","Grappling Hook"],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:5}]},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Crepuscular Ray","Snow Storm"],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:7}]},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:["Refined Gunpowder","Twain's Arc"],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}]},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:["More Shields"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[]},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Patient Hunter"],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[]},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:["Triple Shots","Nimble String"],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}]},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:["Water Mastery","Fire Creep"],dependencies:["Arrow Storm"],blockers:["Windstorm","Nimble String","Arrow Hurricane"],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}]},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:["Nimble String","Air Mastery"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}]},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Shield"],dependencies:["Phantom Ray"],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}]}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}]},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bash"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:2,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}]},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}]},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:["Double Bash"],dependencies:[],blockers:[],cost:1,display:{row:6,col:4},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:9,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}]},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Tougher Skin"],cost:1,display:{row:6,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}]},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Vehement"],cost:1,display:{row:6,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}]},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:["Vehement"],dependencies:[],blockers:[],cost:1,display:{row:8,col:2},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}]},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:["Uppercut","War Scream"],dependencies:[],blockers:[],cost:1,display:{row:8,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:["Tougher Skin"],dependencies:[],blockers:[],cost:1,display:{row:8,col:6},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}]},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:10,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Charge","Thunder Mastery","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:11,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["War Scream","Thunder Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:["War Scream"],dependencies:[],blockers:[],cost:1,display:{row:10,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:["Earth Mastery","Fireworks"],dependencies:[],blockers:[],cost:2,display:{row:12,col:0},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}]},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:["Thunder Mastery","Quadruple Bash"],dependencies:[],blockers:[],cost:2,display:{row:12,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}]},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:["Water Mastery"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:13,col:4},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}]},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:["Air Mastery","Flaming Uppercut"],dependencies:[],blockers:[],cost:2,display:{row:12,col:6},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}]},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:["Fire Mastery","Flyby Jab"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:12,col:8},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}]},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:["Flyby Jab","Flaming Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:13,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}]},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:["Counter"],dependencies:[],blockers:[],cost:2,display:{row:15,col:2},properties:{},effects:[]},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:["Half-Moon Swipe"],dependencies:[],blockers:[],cost:2,display:{row:15,col:4},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}]},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:["Iron Lungs"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:15,col:7},properties:{mantle_charge:3},effects:[]},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:["Quadruple Bash","Fireworks"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:16,col:1},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}]},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bak'al's Grasp","Cheaper Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:17,col:0},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:["Spear Proficiency 2","Aerodynamics","Counter"],dependencies:[],blockers:[],cost:1,display:{row:17,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Uppercut","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:17,col:5},properties:{},effects:[]},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:["Aerodynamics","Mantle of the Bovemists"],dependencies:[],blockers:[],cost:1,display:{row:17,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Cheaper Uppercut","Spear Proficiency 2"],dependencies:[],blockers:[],cost:1,display:{row:18,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}]},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:["Aerodynamics","Provoke"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:18,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}]},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:["Spear Proficiency 2"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:20,col:0},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"dmgPct"},scaling:[2],max:200}]},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:["Cheaper Uppercut","Stronger Mantle"],dependencies:[],blockers:[],cost:2,display:{row:20,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}]},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:["Manachism","Flying Kick"],dependencies:[],blockers:[],cost:1,display:{row:20,col:6},properties:{mantle_charge:2},effects:[]},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:["Stronger Mantle","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:20,col:8},properties:{cooldown:1},effects:[]},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:["Enraged Blow","Ragnarokkr"],dependencies:[],blockers:[],cost:2,display:{row:22,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}]},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:["Boiling Blood","Flying Kick"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:22,col:2},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}]},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:["Flying Kick","Stronger Mantle","Burning Heart"],dependencies:["Counter"],blockers:[],cost:1,display:{row:22,col:4},properties:{chance:30},effects:[]},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:["Ambidextrous","Stronger Bash"],dependencies:[],blockers:[],cost:1,display:{row:22,col:6},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}]},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:["Burning Heart","Manachism"],dependencies:[],blockers:[],cost:1,display:{row:22,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}]},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:["Ragnarokkr","Boiling Blood"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:23,col:1},properties:{},effects:[]},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:["Ragnarokkr"],dependencies:["Fireworks"],blockers:[],cost:2,display:{row:24,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}]},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:["Ambidextrous","Burning Heart"],dependencies:["Flying Kick"],blockers:[],cost:2,display:{row:23,col:5},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}]},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:["Burning Heart","Stronger Bash"],dependencies:[],blockers:[],cost:2,display:{row:23,col:7},properties:{},effects:[]},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:["Boiling Blood","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:1,display:{row:26,col:0},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}]},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:["Whirlwind Strike","Uncontainable Corruption"],dependencies:[],blockers:[],cost:1,display:{row:26,col:2},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}]},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:["Ambidextrous","Radiant Devotee"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:26,col:4},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}]},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:["Rejuvenating Skin"],dependencies:[],blockers:[],cost:2,display:{row:26,col:7},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}]},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:["Uncontainable Corruption","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:27,col:1},properties:{duration:5},effects:[]},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin","Sparkling Hope"],dependencies:[],blockers:[],cost:2,display:{row:27,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}]},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin"],dependencies:[],blockers:[],cost:2,display:{row:27,col:8},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}]},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:["Tempest","Uncontainable Corruption"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}]},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:["Massive Bash","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}]},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:["Tempest","Whirlwind Strike"],dependencies:[],blockers:[],cost:1,display:{row:28,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}]},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:["Tempest","Massive Bash"],dependencies:[],blockers:[],cost:2,display:{row:29,col:1},properties:{},effects:[]},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:["Tempest","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:29,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}]},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:["Spirit of the Rabbit","Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:29,col:5},properties:{cooldown:15},effects:[]},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Radiance","Shield Strike","Sparkling Hope"],dependencies:[],blockers:[],cost:1,display:{row:29,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:["Massive Bash"],dependencies:[],blockers:[],cost:1,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:["Thunderclap"],dependencies:[],blockers:[],cost:2,display:{row:31,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}]},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:["Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:31,col:4},properties:{aoe:2},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:["Thunderclap"],dependencies:[],blockers:[],cost:1,display:{row:32,col:5},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}]},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:["Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[]},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:["Cheaper War Scream"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[]},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:["Blood Pact"],dependencies:["Blood Pact"],blockers:[],cost:1,display:{row:35,col:2},properties:{},effects:[]},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:["Blood Pact","Cheaper Uppercut 2"],dependencies:[],blockers:[],cost:2,display:{row:35,col:4},properties:{},effects:[]},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:["Second Chance","Brink of Madness"],dependencies:[],blockers:[],cost:1,display:{row:35,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:["Second Chance"],dependencies:[],blockers:[],cost:2,display:{row:35,col:8},properties:{duration:3,aoe:12},effects:[]}]},atree_example=[{title:"skill",desc:"desc",image:"../media/atree/node.png",connector:!1,row:5,col:3},{image:"../media/atree/connect_angle.png",connector:!0,rotate:270,row:4,col:3},{title:"skill2",desc:"desc",image:"../media/atree/node.png",connector:!1,row:0,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:1,col:2},{title:"skill3",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:90,row:2,col:3},{title:"skill4",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:4},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:3,col:2},{title:"skill5",desc:"desc",image:"../media/atree/node.png",connector:!1,row:4,col:2},] +const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:["Power Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}]},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:["Heart Shatter"],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}]},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}]},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:["Phantom Ray","Fire Mastery","Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}]},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:["Fire Creep","Earth Mastery"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}]},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:["Thunder Mastery","Arrow Rain"],dependencies:["Arrow Storm"],blockers:["Phantom Ray"],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}]},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:["Double Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}]},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:["Triple Shots","Frenzy"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}]},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}]},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:["Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}]},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:["Guardian Angels","Cheaper Arrow Storm"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}]},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:["Focus","More Shields","Cheaper Arrow Storm"],dependencies:[],blockers:["Escape Artist"],cost:2,display:{row:21,col:5},properties:{range:20},effects:[]},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:["Grappling Hook","More Shields"],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:["More Focus","Traveler"],dependencies:["Focus"],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}]},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:["Refined Gunpowder","Traveler"],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}]},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:["Twain's Arc"],dependencies:["Fire Creep"],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}]},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:["Refined Gunpowder","Homing Shots"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[]},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:["Twain's Arc","Better Arrow Shield","Homing Shots"],dependencies:["Arrow Bomb"],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:["More Traps","Better Arrow Shield"],dependencies:["Fire Creep"],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}]},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:["Better Guardian Angels","Leap"],dependencies:[],blockers:["Grappling Hook"],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}]},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:["Shocking Bomb","Better Arrow Shield","Cheaper Arrow Storm (2)"],dependencies:["Focus"],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}]},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:["Initiator","Cheaper Arrow Storm (2)"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:["Precise Shot","Escape Artist"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}]},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:["Shrapnel Bomb"],dependencies:["Fierce Stomp"],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}]},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:["Cheaper Arrow Shield"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}]},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:["Cheaper Escape (2)"],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}]},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}]},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:["Geyser Stomp","More Focus (2)"],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3}},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:["Snow Storm"],dependencies:["Guardian Angels"],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}]},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:["Grape Bomb","Cheaper Arrow Bomb (2)"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}]},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:["Arrow Bomb"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}]},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Grappling Hook","Windstorm","Focus"],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Arrow Storm","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:["Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Escape","Thunder Mastery","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Thunder Mastery","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:["Grappling Hook","Basaltic Trap"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2}},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:["Windy Feet"],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}]},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}]},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:["Bouncing Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2}},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:["Mana Trap","Shocking Bomb","Twain's Arc"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}]},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:["Leap","Homing Shots"],dependencies:["Leap"],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1}},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:["Escape Artist","Homing Shots"],dependencies:["Guardian Angels"],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}]},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Initiator","Mana Trap"],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Better Guardian Angels","Cheaper Arrow Shield","Arrow Hurricane"],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}]},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:["Precise Shot","Initiator"],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:["Cheaper Arrow Storm (2)","Initiator"],dependencies:["Arrow Bomb"],blockers:[],cost:1,display:{row:33,col:6},properties:{}},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Call of the Hound","Decimator"],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:["Cheaper Escape (2)"],dependencies:["Grappling Hook"],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8}},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["More Focus (2)","Minefield"],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:["More Shields"],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}]},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:["Leap","Shocking Bomb"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[]},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:["Arrow Hurricane","Precise Shot"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}]},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:["Geyser Stomp"],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[]},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Power Shots"],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Rain","Frenzy"],dependencies:["Double Shots"],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Double Shots"],cost:1,display:{row:7,col:6},properties:{},effects:[]},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:["Phantom Ray"],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:3}]},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Storm","Grappling Hook"],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:5}]},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Crepuscular Ray","Snow Storm"],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:7}]},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:["Refined Gunpowder","Twain's Arc"],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}]},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:["More Shields"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[]},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Patient Hunter"],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[]},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:["Triple Shots","Nimble String"],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}]},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:["Water Mastery","Fire Creep"],dependencies:["Arrow Storm"],blockers:["Windstorm","Nimble String","Arrow Hurricane"],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}]},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:["Nimble String","Air Mastery"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}]},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Shield"],dependencies:["Phantom Ray"],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}]}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}]},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bash"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}]},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}]},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:["Double Bash"],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}]},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Tougher Skin"],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}]},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Vehement"],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}]},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:["Vehement"],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}]},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:["Uppercut","War Scream"],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:["Tougher Skin"],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}]},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Charge","Thunder Mastery","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["War Scream","Thunder Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:["War Scream"],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:["Earth Mastery","Fireworks"],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}]},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:["Thunder Mastery","Quadruple Bash"],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}]},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:["Water Mastery"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}]},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:["Air Mastery","Flaming Uppercut"],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}]},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:["Fire Mastery","Flyby Jab"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}]},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:["Flyby Jab","Flaming Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}]},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:["Counter"],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[]},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:["Half-Moon Swipe"],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}]},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:["Iron Lungs"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[]},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:["Quadruple Bash","Fireworks"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}]},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bak'al's Grasp","Cheaper Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:["Spear Proficiency 2","Aerodynamics","Counter"],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Uppercut","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[]},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:["Aerodynamics","Mantle of the Bovemists"],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Cheaper Uppercut","Spear Proficiency 2"],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}]},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:["Aerodynamics","Provoke"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}]},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:["Spear Proficiency 2"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"dmgPct"},scaling:[2],max:200}]},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:["Cheaper Uppercut","Stronger Mantle"],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}]},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:["Manachism","Flying Kick"],dependencies:["Mantle of the Bovemists"],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[]},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:["Stronger Mantle","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[]},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:["Enraged Blow","Ragnarokkr"],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}]},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:["Boiling Blood","Flying Kick"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}]},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:["Flying Kick","Stronger Mantle","Burning Heart"],dependencies:["Counter"],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[]},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:["Ambidextrous","Stronger Bash"],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}]},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:["Burning Heart","Manachism"],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}]},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:["Ragnarokkr","Boiling Blood"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:["Ragnarokkr"],dependencies:["Fireworks"],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}]},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:["Ambidextrous","Burning Heart"],dependencies:["Flying Kick"],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}]},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:["Burning Heart","Stronger Bash"],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:["Boiling Blood","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}]},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:["Whirlwind Strike","Uncontainable Corruption"],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}]},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:["Ambidextrous","Radiant Devotee"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}]},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:["Rejuvenating Skin"],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}]},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:["Uncontainable Corruption","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[]},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin","Sparkling Hope"],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}]},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin"],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}]},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:["Tempest","Uncontainable Corruption"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}]},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:["Massive Bash","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}]},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:["Tempest","Whirlwind Strike"],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}]},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:["Tempest","Massive Bash"],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:["Tempest","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}]},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:["Spirit of the Rabbit","Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[]},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Radiance","Shield Strike","Sparkling Hope"],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:["Massive Bash"],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}]},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}]},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:["Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}]},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:["Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:["Cheaper War Scream"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[]},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:["Blood Pact"],dependencies:["Blood Pact"],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[]},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:["Blood Pact","Cheaper Uppercut 2"],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[]},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:["Second Chance","Brink of Madness"],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:["Second Chance"],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[]}]},atree_example=[{title:"skill",desc:"desc",image:"../media/atree/node.png",connector:!1,row:5,col:3},{image:"../media/atree/connect_angle.png",connector:!0,rotate:270,row:4,col:3},{title:"skill2",desc:"desc",image:"../media/atree/node.png",connector:!1,row:0,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:1,col:2},{title:"skill3",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:90,row:2,col:3},{title:"skill4",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:4},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:3,col:2},{title:"skill5",desc:"desc",image:"../media/atree/node.png",connector:!1,row:4,col:2},] \ No newline at end of file diff --git a/js/display_atree.js b/js/display_atree.js index 888383e..044939b 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -100,7 +100,11 @@ function construct_AT(elem, tree) { // create node let node_elem = document.createElement('div') - node_elem.style = "background-image: url('../media/atree/node.png'); background-size: cover; width: 100%; height: 100%;"; + let icon = node.display.icon; + if (icon === undefined) { + icon = "node"; + } + node_elem.style = "background-image: url('../media/atree/"+icon+".png'); background-size: cover; width: 100%; height: 100%;"; // add tooltip node_elem.addEventListener('mouseover', function(e) { From 8ce25cf2c92befa89fe2e678fc1358b7904cd410 Mon Sep 17 00:00:00 2001 From: reschan Date: Fri, 24 Jun 2022 19:04:58 +0700 Subject: [PATCH 15/68] space out and confine active abil window --- builder/index.html | 2 +- js/display_atree.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/index.html b/builder/index.html index 1a14ed3..f26eb5e 100644 --- a/builder/index.html +++ b/builder/index.html @@ -619,7 +619,7 @@

-
+
diff --git a/js/display_atree.js b/js/display_atree.js index 0c5254a..f90536a 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -121,7 +121,7 @@ function construct_AT(elem, tree) { node_elem.classList.add("fake-button"); let active_tooltip = document.createElement('div'); - active_tooltip.classList.add("rounded-bottom", "dark-7", "border", "mb-2", "mx-auto"); + active_tooltip.classList.add("rounded-bottom", "dark-4", "border", "p-0", "mx-2", "my-4", "dark-shadow"); //was causing active element boxes to be 0 width // active_tooltip.style.width = elem.getBoundingClientRect().width * .80 + "px"; active_tooltip.style.display = "none"; From e5c2205bd5176bf4e3cfc6ac0bc9adb7ff2fd4e5 Mon Sep 17 00:00:00 2001 From: reschan Date: Sat, 25 Jun 2022 22:03:03 +0700 Subject: [PATCH 16/68] add script to convert string reference to numerical id for atree d ata --- py_script/atree-generateID.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 py_script/atree-generateID.py diff --git a/py_script/atree-generateID.py b/py_script/atree-generateID.py new file mode 100644 index 0000000..4355e72 --- /dev/null +++ b/py_script/atree-generateID.py @@ -0,0 +1,35 @@ +""" +Generate a JSON Ability Tree with: + - All references replaced by numerical IDs + - Extra JSON File with Original name as key and Assigned IDs as value. +given a JSON Ability Tree. +""" +import json + +id = 0 +abilDict = {} +with open("atree-parse.json") as f: + data = json.loads(f.read()) + for classType, info in data.items(): + for abil in info: + abilDict[abil["display_name"]] = id + id += 1 + + with open("atree-ids.json", "w", encoding='utf-8') as id_dest: + json.dump(abilDict, id_dest, ensure_ascii=False, indent=4) + + for classType, info in data.items(): + for abil in range(len(info)): + info[abil]["id"] = abilDict[info[abil]["display_name"]] + for ref in range(len(info[abil]["parents"])): + info[abil]["parents"][ref] = abilDict[info[abil]["parents"][ref]] + + for ref in range(len(info[abil]["dependencies"])): + info[abil]["dependencies"][ref] = abilDict[info[abil]["dependencies"][ref]] + + for ref in range(len(info[abil]["blockers"])): + info[abil]["blockers"][ref] = abilDict[info[abil]["blockers"][ref]] + data[classType] = info + + with open('atree-constants-id.json', 'w', encoding='utf-8') as abil_dest: + json.dump(data, abil_dest, ensure_ascii=False, indent=4) From 975c0faa1fc6bb6f995a6d2c230d0b3b462d4476 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 00:08:02 -0700 Subject: [PATCH 17/68] Fix crafter page, fix damage calculation for crafted and normal items (no longer rounded powder damage) --- crafter/index.html | 2 -- item/index.html | 2 -- items_adv/index.html | 2 -- js/build_utils.js | 2 +- js/builder_graph.js | 11 ++++-- js/crafter.js | 15 +++++--- js/damage_calc.js | 86 +++++++++++++++++++++++++++++--------------- js/display.js | 15 ++++++++ 8 files changed, 91 insertions(+), 44 deletions(-) diff --git a/crafter/index.html b/crafter/index.html index 76f6cf3..0359611 100644 --- a/crafter/index.html +++ b/crafter/index.html @@ -301,8 +301,6 @@ - - diff --git a/item/index.html b/item/index.html index 758c902..00cfade 100644 --- a/item/index.html +++ b/item/index.html @@ -62,8 +62,6 @@ - - diff --git a/items_adv/index.html b/items_adv/index.html index fb9da0f..fd5d749 100644 --- a/items_adv/index.html +++ b/items_adv/index.html @@ -79,8 +79,6 @@ - - diff --git a/js/build_utils.js b/js/build_utils.js index 80db2f1..430d55c 100644 --- a/js/build_utils.js +++ b/js/build_utils.js @@ -58,7 +58,7 @@ const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ]; const classes = ["Warrior", "Assassin", "Mage", "Archer", "Shaman"]; const wep_to_class = new Map([["dagger", "Assassin"], ["spear", "Warrior"], ["wand", "Mage"], ["bow", "Archer"], ["relik", "Shaman"]]) const tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"] //I'm not sure why you would make a custom crafted but if you do you should be able to use it w/ the correct powder formula -const types = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(consumableTypes).concat(tome_types).map(x => x.substring(0,1).toUpperCase() + x.substring(1)); +const all_types = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(consumableTypes).concat(tome_types).map(x => x.substring(0,1).toUpperCase() + x.substring(1)); //weaponTypes.push("sword"); //console.log(types) let itemTypes = armorTypes.concat(accessoryTypes).concat(weaponTypes).concat(tome_types); diff --git a/js/builder_graph.js b/js/builder_graph.js index 63d08d1..7eae496 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -204,8 +204,13 @@ class ItemInputNode extends InputNode { type_match = item.statMap.get('type') === this.none_item.statMap.get('type'); } if (type_match) { - if (item.statMap.get('category') === 'armor' && powdering !== undefined) { - applyArmorPowders(item.statMap, powdering); + if (powdering !== undefined) { + if (item.statMap.get('category') === 'armor') { + applyArmorPowders(item.statMap, powdering); + } + else if (item.statMap.get('category') === 'weapon') { + apply_weapon_powders(item.statMap, powdering); + } } return item; } @@ -330,7 +335,7 @@ class WeaponInputDisplayNode extends ComputeNode { dps = dps[1]; if (isNaN(dps)) dps = 0; } - this.dps_field.textContent = dps; + this.dps_field.textContent = Math.round(dps); //as of now, we NEED to have the dropdown tab visible/not hidden in order to properly display atree stuff. if (!document.getElementById("toggle-atree").classList.contains("toggleOn")) { diff --git a/js/crafter.js b/js/crafter.js index 66b9087..bb40c7e 100644 --- a/js/crafter.js +++ b/js/crafter.js @@ -172,16 +172,17 @@ function calculateCraft() { document.getElementById("mat-2").textContent = recipe.get("materials")[1].get("item").split(" ").slice(1).join(" ") + " Tier:"; //Display Recipe Stats - displaysq2RecipeStats(player_craft, "recipe-stats"); + displayRecipeStats(player_craft, "recipe-stats"); //Display Craft Stats // displayCraftStats(player_craft, "craft-stats"); let mock_item = player_craft.statMap; - displaysq2ExpandedItem(mock_item, "craft-stats"); + apply_weapon_powders(mock_item); + displayExpandedItem(mock_item, "craft-stats"); //Display Ingredients' Stats for (let i = 1; i < 7; i++) { - displaysq2ExpandedIngredient(player_craft.ingreds[i-1] , "ing-"+i+"-stats"); + displayExpandedIngredient(player_craft.ingreds[i-1] , "ing-"+i+"-stats"); } //Display Warnings - only ingred type warnings for now let warning_elem = document.getElementById("craft-warnings"); @@ -341,7 +342,7 @@ function toggleMaterial(buttonId) { */ function updateCraftedImage() { let input = document.getElementById("recipe-choice"); - if (item_types.includes(input.value)) { + if (all_types.includes(input.value)) { document.getElementById("recipe-img").src = "../media/items/" + (newIcons ? "new/":"old/") + "generic-" + input.value.toLowerCase() + ".png"; } @@ -364,4 +365,8 @@ function resetFields() { calculateCraft(); } -load_ing_init(init_crafter); +(async function() { + let load_promises = [ load_ing_init() ]; + await Promise.all(load_promises); + init_crafter(); +})(); diff --git a/js/damage_calc.js b/js/damage_calc.js index 058ba96..856743d 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -1,34 +1,25 @@ const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["vanish", 0.80], ["warscream", 0.10], ["bash", 0.50] ]); -// GRR THIS MUTATES THE ITEM +const damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; +const damage_present_key = 'damagePresent'; function get_base_dps(item) { const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; //SUPER JANK @HPP PLS FIX - let damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; if (item.get("tier") !== "Crafted") { - let weapon_result = apply_weapon_powder(item); - let damages = weapon_result[0]; let total_damage = 0; - for (const i in damage_keys) { - total_damage += damages[i][0] + damages[i][1]; - item.set(damage_keys[i], damages[i][0]+"-"+damages[i][1]); + for (const damage_k of damage_keys) { + damages = item.get(damage_k); + total_damage += damages[0] + damages[1]; } - total_damage = total_damage / 2; - return total_damage * attack_speed_mult; - } else { - let base_low = [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]; - let results_low = apply_weapon_powder(item, base_low); - let damage_low = results_low[2]; - let base_high = [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]; - let results_high = apply_weapon_powder(item, base_high); - let damage_high = results_high[2]; - + return total_damage * attack_speed_mult / 2; + } + else { let total_damage_min = 0; let total_damage_max = 0; - for (const i in damage_keys) { - total_damage_min += damage_low[i][0] + damage_low[i][1]; - total_damage_max += damage_high[i][0] + damage_high[i][1]; - item.set(damage_keys[i], damage_low[i][0]+"-"+damage_low[i][1]+"\u279c"+damage_high[i][0]+"-"+damage_high[i][1]); + for (const damage_k of damage_keys) { + damages = item.get(damage_k); + total_damage_min += damages[0][0] + damages[0][1]; + total_damage_max += damages[1][0] + damages[1][1]; } total_damage_min = attack_speed_mult * total_damage_min / 2; total_damage_max = attack_speed_mult * total_damage_max / 2; @@ -36,11 +27,38 @@ function get_base_dps(item) { } } +// THIS MUTATES THE ITEM +function apply_weapon_powders(item) { + let present; + if (item.get("tier") !== "Crafted") { + let weapon_result = calc_weapon_powder(item); + let damages = weapon_result[0]; + present = weapon_result[1]; + for (const i in damage_keys) { + item.set(damage_keys[i], damages[i]); + } + } else { + let base_low = [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]; + let results_low = calc_weapon_powder(item, base_low); + let damage_low = results_low[0]; + let base_high = [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]; + let results_high = calc_weapon_powder(item, base_high); + let damage_high = results_high[0]; + present = results_high[1]; + + for (const i in damage_keys) { + item.set(damage_keys[i], [damage_low[i], damage_high[i]]); + } + } + console.log(item); + item.set(damage_present_key, present); +} + /** * weapon: Weapon to apply powder to * damageBases: used by crafted */ -function apply_weapon_powder(weapon, damageBases) { +function calc_weapon_powder(weapon, damageBases) { let powders = weapon.get("powders").slice(); // Array of neutral + ewtfa damages. Each entry is a pair (min, max). @@ -86,10 +104,15 @@ function apply_weapon_powder(weapon, damageBases) { if (neutralRemainingRaw[1] > 0) { let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]); let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]); - damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff)); - damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff)); - neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff)); - neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff)); + + //damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff)); + //damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff)); + //neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff)); + //neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff)); + damages[element+1][0] += min_diff; + damages[element+1][1] += max_diff; + neutralRemainingRaw[0] -= min_diff; + neutralRemainingRaw[1] -= max_diff; } damages[element+1][0] += powder.min; damages[element+1][1] += powder.max; @@ -111,9 +134,14 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno // Array of neutral + ewtfa damages. Each entry is a pair (min, max). // 1. Get weapon damage (with powders). - let weapon_result = apply_weapon_powder(weapon); - let weapon_damages = weapon_result[0]; - let present = weapon_result[1]; + let weapon_damages; + if (weapon.get('tier') === 'Crafted') { + weapon_damages = damage_keys.map(x => weapon.get(x)[1]); + } + else { + weapon_damages = damage_keys.map(x => weapon.get(x)); + } + let present = weapon.get(damage_present_key); // 2. Conversions. // 2.1. First, apply neutral conversion (scale weapon damage). Keep track of total weapon damage here. diff --git a/js/display.js b/js/display.js index 631f0c0..a45eae1 100644 --- a/js/display.js +++ b/js/display.js @@ -173,6 +173,7 @@ function displayExpandedItem(item, parent_id){ // #commands create a new element. // !elemental is some janky hack for elemental damage. // normals just display a thing. + item = new Map(item); // shallow copy if (item.get("category") === "weapon") { item.set('basedps', get_base_dps(item)); } else if (item.get("category") === "armor") { @@ -341,7 +342,21 @@ function displayExpandedItem(item, parent_id){ bckgrd.appendChild(img); } } else { + if (id.endsWith('Dam_')) { + // TODO: kinda jank but replacing lists with txt at this step + let damages = item.get(id); + if (item.get("tier") !== "Crafted") { + damages = damages.map(x => Math.round(x)); + item.set(id, damages[0]+"-"+damages[1]); + } + else { + damages = damages.map(x => x.map(y => Math.round(y))); + item.set(id, damages[0][0]+"-"+damages[0][1]+"\u279c"+damages[1][0]+"-"+damages[1][1]); + } + } + let p_elem; + // TODO: wtf is this if statement if ( !(item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") && (!skp_order.includes(id)) || (skp_order.includes(id) && item.get("tier") !== "Crafted" && parent_div.nodeName === "table") ) { //skp warp p_elem = displayFixedID(parent_div, id, item.get(id), elemental_format); } else if (item.get("tier") === "Crafted" && item.get("category") === "armor" && id === "hp") { From 6561731a594bb4cc58b576ce98a542a9112ea3dd Mon Sep 17 00:00:00 2001 From: ferricles Date: Sun, 26 Jun 2022 00:48:42 -0700 Subject: [PATCH 18/68] node highlighting + cost display in tooltip --- js/display_atree.js | 75 +++++++++++++++++++++++++++++---------------- js/utils.js | 1 + 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index e21ce61..e419c75 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -10,7 +10,19 @@ function construct_AT(elem, tree) { // add in the "Active" title to atree let active_row = document.createElement("div"); active_row.classList.add("row", "item-title", "mx-auto", "justify-content-center"); - active_row.textContent = "Active:"; + + let active_word = document.createElement("div"); + active_word.classList.add("col"); + active_word.textContent = "Active:"; + + let active_AP_container = document.createElement("div"); + active_AP_container.classList.add("col"); + active_AP_container.textContent = "(0/45 AP)"; + + //I can't believe we can't pass in multiple children at once + active_row.appendChild(active_word); + active_row.appendChild(active_AP_container); + document.getElementById("atree-active").appendChild(active_row); atree_map = new Map(); @@ -104,29 +116,18 @@ function construct_AT(elem, tree) { if (icon === undefined) { icon = "node"; } - node_elem.style = "background-image: url('../media/atree/"+icon+".png'); background-size: cover; width: 100%; height: 100%;"; - - // add tooltip - node_elem.addEventListener('mouseover', function(e) { - if (e.target !== this) {return;} - let tooltip = this.children[0]; - tooltip.style.top = this.getBoundingClientRect().bottom + window.scrollY * 1.02 + "px"; - tooltip.style.left = this.parentElement.parentElement.getBoundingClientRect().left + (elem.getBoundingClientRect().width * .2 / 2) + "px"; - tooltip.style.display = "block"; - }); - - node_elem.addEventListener('mouseout', function(e) { - if (e.target !== this) {return;} - let tooltip = this.children[0]; - tooltip.style.display = "none"; - }); - + let node_img = document.createElement('img'); + node_img.src = '../media/atree/' + icon + '.png'; + node_img.style = 'width: 100%; height:100%'; + // node_elem.style = "background-image: url('../media/atree/"+icon+".png'); background-size: cover; width: 100%; height: 100%;"; + node_elem.style = 'background-size: cover; width: 100%; height:100%; padding: 8%;' + node_elem.appendChild(node_img); node_elem.classList.add("fake-button"); let active_tooltip = document.createElement('div'); active_tooltip.classList.add("rounded-bottom", "dark-4", "border", "p-0", "mx-2", "my-4", "dark-shadow"); //was causing active element boxes to be 0 width - // active_tooltip.style.width = elem.getBoundingClientRect().width * .80 + "px"; + active_tooltip.style.maxWidth = elem.getBoundingClientRect().width * .80 + "px"; active_tooltip.style.display = "none"; // tooltip text formatting @@ -135,12 +136,17 @@ function construct_AT(elem, tree) { active_tooltip_title.classList.add("scaled-font"); active_tooltip_title.innerHTML = node.display_name; - let active_tooltip_text = document.createElement('p'); - active_tooltip_text.classList.add("scaled-font-sm"); - active_tooltip_text.textContent = node.desc; + let active_tooltip_desc = document.createElement('p'); + active_tooltip_desc.classList.add("scaled-font-sm", "my-0", "mx-1", "text-wrap"); + active_tooltip_desc.textContent = node.desc; + + let active_tooltip_cost = document.createElement('p'); + active_tooltip_cost.classList.add("scaled-font-sm", "my-0", "mx-1", "text-start"); + active_tooltip_cost.textContent = "Cost: " + node.cost + " AP"; active_tooltip.appendChild(active_tooltip_title); - active_tooltip.appendChild(active_tooltip_text); + active_tooltip.appendChild(active_tooltip_desc); + active_tooltip.appendChild(active_tooltip_cost); node_tooltip = active_tooltip.cloneNode(true); @@ -153,19 +159,36 @@ function construct_AT(elem, tree) { document.getElementById("atree-active").appendChild(active_tooltip); node_elem.addEventListener('click', function(e) { - if (e.target !== this) {return;} + if (e.target !== this && e.target!== this.children[0]) {return;} let tooltip = document.getElementById("atree-ab-" + node.display_name.replaceAll(" ", "")); if (tooltip.style.display == "block") { tooltip.style.display = "none"; this.classList.remove("atree-selected"); - this.style.backgroundImage = 'url("../media/atree/node.png")'; + this.style.backgroundImage = ''; } else { tooltip.style.display = "block"; this.classList.add("atree-selected"); - this.style.backgroundImage = 'url("../media/atree/node-selected.png")'; + this.style.backgroundImage = 'url("../media/atree/node_highlight.png")'; } }); + + // add tooltip + + node_elem.addEventListener('mouseover', function(e) { + if (e.target !== this && e.target!== this.children[0]) {return;} + let tooltip = this.children[this.children.length - 1]; + tooltip.style.top = this.getBoundingClientRect().bottom + window.scrollY * 1.02 + "px"; + tooltip.style.left = this.parentElement.parentElement.getBoundingClientRect().left + (elem.getBoundingClientRect().width * .2 / 2) + "px"; + tooltip.style.display = "block"; + }); + + node_elem.addEventListener('mouseout', function(e) { + if (e.target !== this && e.target!== this.children[0]) {return;} + let tooltip = this.children[this.children.length - 1]; + tooltip.style.display = "none"; + }); + document.getElementById("atree-row-" + node.display.row).children[node.display.col].appendChild(node_elem); }; diff --git a/js/utils.js b/js/utils.js index 5691ac9..70ec6dc 100644 --- a/js/utils.js +++ b/js/utils.js @@ -389,3 +389,4 @@ async function hardReload() { function capitalizeFirst(str) { return str[0].toUpperCase() + str.substring(1); } + From 056ff84972e98d815678566f74457cd368672845 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 01:07:43 -0700 Subject: [PATCH 19/68] Misc. changes to powdering workings Items no longer have powders array defined by default (only weapons/armors) --- js/build_utils.js | 1 - js/builder_graph.js | 21 ++++++++++++++------- js/display.js | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/js/build_utils.js b/js/build_utils.js index 430d55c..58e863d 100644 --- a/js/build_utils.js +++ b/js/build_utils.js @@ -218,7 +218,6 @@ function expandItem(item) { } expandedItem.set("minRolls",minRolls); expandedItem.set("maxRolls",maxRolls); - expandedItem.set("powders", []); return expandedItem; } diff --git a/js/builder_graph.js b/js/builder_graph.js index be33da8..e54fd02 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -203,13 +203,11 @@ class ItemInputNode extends InputNode { type_match = item.statMap.get('type') === this.none_item.statMap.get('type'); } if (type_match) { - if (powdering !== undefined) { - if (item.statMap.get('category') === 'armor') { - applyArmorPowders(item.statMap, powdering); - } - else if (item.statMap.get('category') === 'weapon') { - apply_weapon_powders(item.statMap, powdering); - } + if (item.statMap.get('category') === 'armor') { + applyArmorPowders(item.statMap, powdering); + } + else if (item.statMap.get('category') === 'weapon') { + apply_weapon_powders(item.statMap, powdering); } return item; } @@ -247,6 +245,7 @@ class ItemInputDisplayNode extends ComputeNode { this.input_field = document.getElementById(eq+"-choice"); this.health_field = document.getElementById(eq+"-health"); this.level_field = document.getElementById(eq+"-lv"); + this.powder_field = document.getElementById(eq+"-powder"); // possibly None this.image = item_image; this.fail_cb = true; } @@ -271,10 +270,18 @@ class ItemInputDisplayNode extends ComputeNode { this.input_field.classList.add("is-invalid"); return null; } + if (item.statMap.has('powders')) { + this.powder_field.placeholder = "powders"; + } if (item.statMap.has('NONE')) { return null; } + + if (item.statMap.has('powders')) { + this.powder_field.placeholder = item.statMap.get('slots') + ' slots'; + } + const tier = item.statMap.get('tier'); this.input_field.classList.add(tier); if (this.health_field) { diff --git a/js/display.js b/js/display.js index a45eae1..a3edcf9 100644 --- a/js/display.js +++ b/js/display.js @@ -419,7 +419,7 @@ function displayExpandedItem(item, parent_id){ } } //Show powder specials ;-; - let nonConsumables = ["relik", "wand", "bow", "spear", "dagger", "chestplate", "helmet", "leggings", "boots", "ring", "bracelet", "necklace"]; + 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"); From 8d357f7531dac775368863690702f63965338150 Mon Sep 17 00:00:00 2001 From: ferricles Date: Sun, 26 Jun 2022 01:15:26 -0700 Subject: [PATCH 20/68] current AP count display --- js/display_atree.js | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index e419c75..ed2b3f3 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -12,14 +12,37 @@ function construct_AT(elem, tree) { active_row.classList.add("row", "item-title", "mx-auto", "justify-content-center"); let active_word = document.createElement("div"); - active_word.classList.add("col"); - active_word.textContent = "Active:"; + active_word.classList.add("col-auto"); + active_word.textContent = "Active Abilities:"; let active_AP_container = document.createElement("div"); - active_AP_container.classList.add("col"); - active_AP_container.textContent = "(0/45 AP)"; - + active_AP_container.classList.add("col-auto"); + + let active_AP_subcontainer = document.createElement("div"); + active_AP_subcontainer.classList.add("row"); + + let active_AP_cost = document.createElement("div"); + active_AP_cost.classList.add("col-auto", "mx-0", "px-0"); + active_AP_cost.id = "active_AP_cost"; + active_AP_cost.textContent = "0"; + let active_AP_slash = document.createElement("div"); + active_AP_slash.classList.add("col-auto", "mx-0", "px-0"); + active_AP_slash.textContent = "/"; + let active_AP_cap = document.createElement("div"); + active_AP_cap.classList.add("col-auto", "mx-0", "px-0"); + active_AP_cap.id = "active_AP_cap"; + active_AP_cap.textContent = "45"; + let active_AP_end = document.createElement("div"); + active_AP_end.classList.add("col-auto", "mx-0", "px-0"); + active_AP_end.textContent = " AP"; + //I can't believe we can't pass in multiple children at once + active_AP_subcontainer.appendChild(active_AP_cost); + active_AP_subcontainer.appendChild(active_AP_slash); + active_AP_subcontainer.appendChild(active_AP_cap); + active_AP_subcontainer.appendChild(active_AP_end); + active_AP_container.appendChild(active_AP_subcontainer); + active_row.appendChild(active_word); active_row.appendChild(active_AP_container); @@ -165,11 +188,13 @@ function construct_AT(elem, tree) { tooltip.style.display = "none"; this.classList.remove("atree-selected"); this.style.backgroundImage = ''; + document.getElementById("active_AP_cost").textContent = parseInt(document.getElementById("active_AP_cost").textContent) - node.cost; } else { tooltip.style.display = "block"; this.classList.add("atree-selected"); this.style.backgroundImage = 'url("../media/atree/node_highlight.png")'; + document.getElementById("active_AP_cost").textContent = parseInt(document.getElementById("active_AP_cost").textContent) + node.cost; } }); From 92f4df365913e7cc1b6666075599010985c1c26d Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 15:59:02 +0700 Subject: [PATCH 21/68] implement atree connector highlighting --- js/display_atree.js | 167 +++++++++++++++--- media/atree/connect_t.png | Bin 692 -> 962 bytes media/atree/highlight_c_2_a.png | Bin 0 -> 1099 bytes media/atree/highlight_c_2_l.png | Bin 0 -> 1107 bytes media/atree/highlight_c_3.png | Bin 0 -> 1090 bytes media/atree/highlight_t_2_a.png | Bin 0 -> 708 bytes media/atree/highlight_t_2_l.png | Bin 0 -> 666 bytes .../{highlight_t.png => highlight_t_3.png} | Bin 632 -> 654 bytes 8 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 media/atree/highlight_c_2_a.png create mode 100644 media/atree/highlight_c_2_l.png create mode 100644 media/atree/highlight_c_3.png create mode 100644 media/atree/highlight_t_2_a.png create mode 100644 media/atree/highlight_t_2_l.png rename media/atree/{highlight_t.png => highlight_t_3.png} (96%) diff --git a/js/display_atree.js b/js/display_atree.js index e21ce61..c5130e2 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -1,5 +1,6 @@ let atree_map; let atree_connectors_map; +let atree_active_connections = []; function construct_AT(elem, tree) { console.log("constructing ability tree UI"); document.getElementById("atree-active").innerHTML = ""; //reset all atree actives - should be done in a more general way later @@ -16,7 +17,7 @@ function construct_AT(elem, tree) { atree_map = new Map(); atree_connectors_map = new Map() for (let i of tree) { - atree_map.set(i.display_name, {display: i.display, parents: i.parents, connectors: []}); + atree_map.set(i.display_name, {display: i.display, parents: i.parents, connectors: new Map(), active: false}); } for (let i = 0; i < tree.length; i++) { @@ -54,9 +55,10 @@ function construct_AT(elem, tree) { } - let connector_list = []; // create connectors based on parent location for (let parent of node.parents) { + atree_map.get(node.display_name).connectors.set(parent, []); + let parent_node = atree_map.get(parent); let connect_elem = document.createElement("div"); @@ -65,8 +67,8 @@ function construct_AT(elem, tree) { for (let i = node.display.row - 1; i > parent_node.display.row; i--) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; - atree_map.get(node.display_name).connectors.push(i + "," + node.display.col); - atree_connectors_map.get(i + "," + node.display.col).push({connector: connector, type: "line"}); + atree_map.get(node.display_name).connectors.get(parent).push(i + "," + node.display.col); + atree_connectors_map.get(i + "," + node.display.col).push({connector: connector, type: "line", owner: [node.display_name, parent]}); resolve_connector(i + "," + node.display.col, node); } // connect horizontally @@ -76,8 +78,8 @@ function construct_AT(elem, tree) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; connector.classList.add("rotate-90"); - atree_map.get(node.display_name).connectors.push(parent_node.display.row + "," + i); - atree_connectors_map.get(parent_node.display.row + "," + i).push({connector: connector, type: "line"}); + atree_map.get(node.display_name).connectors.get(parent).push(parent_node.display.row + "," + i); + atree_connectors_map.get(parent_node.display.row + "," + i).push({connector: connector, type: "line", owner: [node.display_name, parent]}); resolve_connector(parent_node.display.row + "," + i, node); } @@ -86,8 +88,8 @@ function construct_AT(elem, tree) { if (parent_node.display.row != node.display.row && parent_node.display.col != node.display.col) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_angle.png')"; - atree_map.get(node.display_name).connectors.push(parent_node.display.row + "," + node.display.col); - atree_connectors_map.get(parent_node.display.row + "," + node.display.col).push({connector: connector, type: "angle"}); + atree_map.get(node.display_name).connectors.get(parent).push(parent_node.display.row + "," + node.display.col); + atree_connectors_map.get(parent_node.display.row + "," + node.display.col).push({connector: connector, type: "angle", owner: [node.display_name, parent]}); if (parent_node.display.col > node.display.col) { connector.classList.add("rotate-180"); } @@ -99,12 +101,13 @@ function construct_AT(elem, tree) { } // create node - let node_elem = document.createElement('div') + let node_elem = document.createElement('div'); let icon = node.display.icon; if (icon === undefined) { icon = "node"; } node_elem.style = "background-image: url('../media/atree/"+icon+".png'); background-size: cover; width: 100%; height: 100%;"; + node_elem.classList.add("atree-circle"); // add tooltip node_elem.addEventListener('mouseover', function(e) { @@ -158,13 +161,13 @@ function construct_AT(elem, tree) { if (tooltip.style.display == "block") { tooltip.style.display = "none"; this.classList.remove("atree-selected"); - this.style.backgroundImage = 'url("../media/atree/node.png")'; } else { tooltip.style.display = "block"; this.classList.add("atree-selected"); - this.style.backgroundImage = 'url("../media/atree/node-selected.png")'; } + atree_toggle_state(node); + atree_update_connector(node); }); document.getElementById("atree-row-" + node.display.row).children[node.display.col].appendChild(node_elem); }; @@ -179,29 +182,33 @@ function resolve_connector(pos, node) { let line = false; let angle = false; let t = false; + let owners = []; for (let i of atree_connectors_map.get(pos)) { if (i.type == "line") { - line += true; + line = true; } else if (i.type == "angle") { - angle += true; + angle = true; } else if (i.type == "t") { - t += true; + t = true; } + owners = owners.concat(i.owner); } + owners = [...new Set(owners)] + let connect_elem = document.createElement("div"); if ((line && angle)) { - connect_elem.style = "background-image: url('../media/atree/connect_t.png'); background-size: cover; width: 100%; height: 100%;" - connect_elem.classList.add("rotate-180") - atree_connectors_map.set(pos, [{connector: connect_elem, type: "t"}]) + connect_elem.style = "background-image: url('../media/atree/connect_t.png'); background-size: cover; width: 100%; height: 100%;"; + atree_connectors_map.set(pos, [{connector: connect_elem, type: "t", owner: owners, connector_state: {up: 0, left: 0, right: 0, down: 0}}]); } if (node.parents.length == 3 && t && atree_same_row(node)) { - connect_elem.style = "background-image: url('../media/atree/connect_c.png'); background-size: cover; width: 100%; height: 100%;" - atree_connectors_map.set(pos, [{connector: connect_elem, type: "c"}]) + connect_elem.style = "background-image: url('../media/atree/connect_c.png'); background-size: cover; width: 100%; height: 100%;"; + atree_connectors_map.set(pos, [{connector: connect_elem, type: "c", owner: owners, connector_state: {up: 0, left: 0, right: 0, down: 0}}]); } // override the conflict with the first children - atree_connectors_map.set(pos, [atree_connectors_map.get(pos)[0]]) + atree_connectors_map.set(pos, [atree_connectors_map.get(pos)[0]]); + atree_connectors_map.get(pos)[0].owner = owners; } // check if a node doesn't have same row w/ its parents (used to solve conflict) @@ -216,7 +223,125 @@ function atree_same_row(node) { function atree_render_connection() { for (let i of atree_connectors_map.keys()) { if (atree_connectors_map.get(i).length != 0) { - document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].appendChild(atree_connectors_map.get(i)[0].connector) + document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].appendChild(atree_connectors_map.get(i)[0].connector); } } } + +function atree_toggle_state(node) { + if (atree_map.get(node.display_name).active) { + atree_map.get(node.display_name).active = false; + } else { + atree_map.get(node.display_name).active = true; + } +} + +function atree_update_connector() { + atree_map.forEach((v) => { + if (v.active) { + atree_compute_highlight(v); + } + }); +} + +function atree_compute_highlight(node) { + node.connectors.forEach((v, k) => { + console.log(node.active); + if (node.active && atree_map.get(k).active) { + for (let i of v) { + connector_data = atree_connectors_map.get(i)[0]; + if (connector_data.type == "c" || connector_data.type == "t") { + connector_data.connector_state = atree_get_state(i); + let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type) + connector_data.connector.className = ""; + connector_data.connector.classList.add("rotate-" + connector_img.rotate); + connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + connector_img.attrib + ".png')"; + } else { + connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + ".png')"; + } + } + } else { + for (let i of v) { + connector_data = atree_connectors_map.get(i)[0]; + if (connector_data.type == "c" || connector_data.type == "t") { + connector_data.connector_state = atree_get_state(i); + let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type) + if (!connector_img) { + connector_data.connector.className = ""; + connector_data.connector.style.backgroundImage = "url('../media/atree/connect_" + connector_data.type + ".png')"; + } else { + connector_data.connector.className = ""; + connector_data.connector.classList.add("rotate-" + connector_img.rotate); + connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + connector_img.attrib + ".png')"; + }; + } else { + connector_data.connector.style.backgroundImage = "url('../media/atree/connect_" + connector_data.type + ".png')"; + } + } + } + }); +} + +function atree_get_state(connector) { + let connector_state = {left: 0, right: 0, up: 0, down: 0} + + for (let abil_name of atree_connectors_map.get(connector)[0].owner) { + state = atree_map.get(abil_name).active; + if (atree_map.get(abil_name).display.col > parseInt(connector.split(",")[1])) { + if (state) { + connector_state.right = 1; + } else { + connector_state.right = 0; + } + } + if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { + if (state) { + connector_state.left = 1; + } else { + connector_state.left = 0; + } + } + if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { + if (state) { + connector_state.up = 1; + } else { + connector_state.up = 0; + } + } + if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { + if (state) { + connector_state.down = 1; + } else { + connector_state.down = 0; + } + } + } + return connector_state; +} + +function atree_parse_connector(orient, type) { + // left, right, up, down + // todo + let connector_dict = { + "1100": {attrib: "_2_l", rotate: 0}, + "1010": {attrib: "_2_a", rotate: 0}, + "1001": {attrib: "_2_a", rotate: 270}, + "0110": {attrib: "_2_a", rotate: 90}, + "0101": {attrib: "_2_a", rotate: 180}, + "0011": {attrib: "_2_l", rotate: 90}, + "1110": {attrib: "_3", rotate: 0}, + "1101": {attrib: "_3", rotate: 180}, + "1011": {attrib: "_3", rotate: 270}, + "0111": {attrib: "_3", rotate: 90}, + "1111": {attrib: "", rotate: 0} + } + + console.log(orient); + + let res = "" + for (let i in orient) { + res += orient[i]; + } + + return connector_dict[res]; +} diff --git a/media/atree/connect_t.png b/media/atree/connect_t.png index 8ed976eb9f0d5d3c8d87891a0c058fa5598b8603..9acedd6f7eeff3efc12c7e1987097b695f6c75a2 100644 GIT binary patch literal 962 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBK4*bPWHAE+-(e7DJf6QIg@J)7&(p;*q$2L^4MVQO1_BI@n*aZAUX)O- zcPZ)(4@Z3d#tvzqPWpg9hTkKvb6lx;r!SzwAfN_DX4lKkJM@S%v~bcGovpoQS~P3x zy^pV-{fSlfd&0_)$OJ>%%%4}}{E6GgQnH=z0kQ;K#VCV_5Qt2!VO$l@r@XJq(*=~G hJYD@<);T3K(K>4BZhlJab^A0)(Qk)X*rp+S6aZ>!tVRF; literal 692 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;3=B+po-U3d z6?5L+Fyv!0$Te-*MEOd-G7;z z;W-CG3+E^zJp^pi)8@xD?SB$`w}G4C5DN@lyLUUC*JUSzf)9;R&e=0|dszzFkSqr# d3HpEsi^UU5cvNTD9S{Lo=;`X`vd$@?2>@Frgo6M8 diff --git a/media/atree/highlight_c_2_a.png b/media/atree/highlight_c_2_a.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d3f899961ec602c87d61fb8ac2452c2d1febab GIT binary patch literal 1099 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fn=|)7d$|)7e=epeR2rGbfdS zLF4??iMAex14LT=gSRS)vRZdoq^!`35)dt%q9JzBDN}pPtAtON>@zM+ShB-{YaJ_l zz1V6#y>q*)c5pR4;O|&GdGey}DHZWS8G>3r9(=MpSN*);er-d5w&B@VGZ;+nnh6Jb z`lN>)J)phof&J!tJ5H%WD+h zZah`ly*X^v2DkZtS`V(-H|dGhRf9zlPCSJj0RfJJsy8|=tec#q==eNH`u~L2{gb^F z!v%X}xHX)c-~2lG|H1d1wRf&8nJzM=;hgyKpAw8ryB+qvvbcY|FW8>(&-nvW?|qq` zec+Ay%d5-8?3jLSYwUi#Y}p&e>DC7xOjew|N&Dx@mKeSY`^EXE7?`&^oS$XB{g|bn ze1pi@te6j4F}J|V6^nn6kF|Ns9C z+S&|2l7V6U!aXa26kADEakt z5%>0%VV<&~fU9F>>fQgRvYGXl$<_)u?QJ_w(ZSfBW-uopv)r2_F;C zGzNy;N)9kxk}A+}&JoO9pvw@zM+ShB-{YaJ_l zz1V6#y>q*)c5pR4;O|&GdGey}DHZWS8G>3r9(=MpSN*);er-d5w&B@VGZ;+nnh6Jb z`lN>)J)phof&J!tJ5H%WD+h zZah`ly*X^v2DkZtS`V(-H|dGhRf9zlPCSJj0RfJJsy8|=tec#q==eNH`u~L2{gb^F z!v%X}xHX)c-~2lG|H1d1wRf&8nJzM=;hgyKpAw8ryB+qvvbcY|FW8>(&-nvW?|qq` zec+Ay%d5-8?3jLSYwUi#Y}p&e>DC7xOjew|N&Dx@mKeSY`^EXE7?`&^oS$XB{g|bn ze1pi@te6j4F}J|V6^nn6kF|Ns9C z+S&|2l7V6U!aXa26kAD(9hXXgvC+%!{7Bh9K)xq36hmS!;1AzTik+*Xohfh@$XU7w)J(VTXJDd)HD zf&IK7Js14LZI|yYf4cB{oz<(4g_R7qvY9W$NjH4E#jxc%+k(Aj3~#qGW~}FRsLsVF z^(!dliu@m!wAt&A0Bvok`(^*TnW5I$=Ed*(b=-9KATUJ840{8XioJG>XHrZWSD9Fd zfkM{P)z4*}Q$o`-1rQGyx9(ti0Wj!I;BkuxdP`W`3NkP_H(Y-$3^Hpo_kI(QE|^&W D_;rF+ literal 0 HcmV?d00001 diff --git a/media/atree/highlight_c_3.png b/media/atree/highlight_c_3.png new file mode 100644 index 0000000000000000000000000000000000000000..546bd342fc7fff98613ba6a8ef8a45850c867973 GIT binary patch literal 1090 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fn=|)7d$|)7e=epeR2rGbfdS zLF4??iMAex14LT=gSRS)vRZdoq^!`35)dt%q9JzBDN}pPtAtON>@zM+ShB-{YaJ_l zz1V6#y>q*)c5pR4;O|&GdGey}DHZWS8G>3r9(=MpSN*);er-d5w&B@VGZ;+nnh6Jb z`lN>)J)phof&J!tJ5H%WD+h zZah`ly*X^v2DkZtS`V(-H|dGhRf9zlPCSJj0RfJJsy8|=tec#q==eNH`u~L2{gb^F z!v%X}xHX)c-~2lG|H1d1wRf&8nJzM=;hgyKpAw8ryB+qvvbcY|FW8>(&-nvW?|qq` zec+Ay%d5-8?3jLSYwUi#Y}p&e>DC7xOjew|N&Dx@mKeSY`^EXE7?`&^oS$XB{g|bn ze1pi@te6j4F}J|V6^nn6kF|Ns9C z+S&|2l7V6U!aXa26kADEakt z5%>0%VP3SO2#ez-llS$h-VVpLU74Gs=lUFC{iyY?|NENb;pg|;fBW+<)}M_rgB_GM z7#h~uuz+ZWDkBaDYYs58sAqI@0?(*-^zuvly*MERE#frc^x zu+WQB&JgA5%?w+b!Ays6If!ywNtOk&5W9ALf+|0$!0=W9tn9+nc8GE`ryUSWxSh{v zXT|`u&A~qQ>zr?|PC2iyvwC&$ew=i}w_6NbuCp!JYsT<)D`UobUWe*jhFjUp7w}8% z6OsJ->vQsJ|CDXEyFXoMuUEYWwEfHF^Ka}~Ud(>zc>n*m=mvUw6y$sI;-EqC!0*5O zcP|D0HD_(^1)1aN>gTe~DWR!h8#HpQfRS4a3G38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBzEFTqh%1n0P*P&}|DQoy`#+FmV5qH00|~N~1o;I6MSxAr*0NZyEN9IEuI&jGeak|5V18H+ipxclSJBV!U=0 zSGC=~^S^%Fecr$S+t26awM7CA-xPqxF)&=vmS+Mp2D8`$u?O4gS%2g+gIs&TfBi3; zx2wbLzFhV1|MlX=_b;E#7-WCX+jS$9!RniB>BiLzC2y)>DleHU14w+4fIUC3EXPV;kv)GBbv^ISjXMGHlt* sn32wW;T+q7xx5b6gGZv5xu*U38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBzEFTqh%1n0P*VE;|38DaHUp4kU|7F!&q^T0RubeF3={{7ZQj3RKTw3T zz$3Dlfr0N32s4Umcr^emxaaBO7*Y}U_LgCujH3XHW6+hq|4%nHY;oUoYo*8XInonk zztz^XZNXe#2W#nuGBbv^ISjXMGHlt*n2|n+BqnY9E%*NQ_X;xH_ABVgiuv*X z-z=XmcXhf`cy0O9#jopMnlZ%wLJSusH#2Nuhe)rhVF8O(6$vzaQvfqBOzj8L z4*q;h7vvz)yFLkm#a^6rWVqD~kq)zopr5}FtqZmynpUjEge!uU(3+iZ{}K?(pEYu?EK literal 0 HcmV?d00001 diff --git a/media/atree/highlight_t.png b/media/atree/highlight_t_3.png similarity index 96% rename from media/atree/highlight_t.png rename to media/atree/highlight_t_3.png index 7629abf158e6fb5e152a4eeed06327a39f7d5be3..a8d7e9235070347ed350265943aca9e72ab81bcb 100644 GIT binary patch delta 30 hcmeyt(#N`?f=Mj9FVdQ&MBb@gaNn83!VS~ delta 7 OcmeBU{lT)Kf(ZZ%@dCO4 From 5748af5f7db12bb06d005a6c64d4b9960e0118af Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 16:01:31 +0700 Subject: [PATCH 22/68] atree node highlighting --- css/sq2bs.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/css/sq2bs.css b/css/sq2bs.css index 0532fc0..6e41131 100644 --- a/css/sq2bs.css +++ b/css/sq2bs.css @@ -483,3 +483,13 @@ a:hover { .hide-scroll::-webkit-scrollbar { display: none; /* Safari and Chrome */ } + +.atree-selected { + outline: 5px solid rgba(95, 214, 223, 0.8); +} + +.atree-circle { + border-radius:50%; + -moz-border-radius:50%; + -webkit-border-radius:50%; +} \ No newline at end of file From 5992d5db7ff05136248cda2fd5368e22cce40aee Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 16:04:02 +0700 Subject: [PATCH 23/68] fix: connector not updating when node is unselected --- js/display_atree.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index c5130e2..dfb905b 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -238,9 +238,7 @@ function atree_toggle_state(node) { function atree_update_connector() { atree_map.forEach((v) => { - if (v.active) { - atree_compute_highlight(v); - } + atree_compute_highlight(v); }); } @@ -336,8 +334,6 @@ function atree_parse_connector(orient, type) { "1111": {attrib: "", rotate: 0} } - console.log(orient); - let res = "" for (let i in orient) { res += orient[i]; From 72f9b2b30d87a9e4345c80f465760b23845c8e52 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 16:25:54 +0700 Subject: [PATCH 24/68] fix: tri connector rotation --- js/display_atree.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index dfb905b..366944e 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -244,7 +244,6 @@ function atree_update_connector() { function atree_compute_highlight(node) { node.connectors.forEach((v, k) => { - console.log(node.active); if (node.active && atree_map.get(k).active) { for (let i of v) { connector_data = atree_connectors_map.get(i)[0]; @@ -307,20 +306,25 @@ function atree_get_state(connector) { } } if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { + if (state) { connector_state.down = 1; + if (abil_name == "Scorched Earth") { + alert('a') + } } else { connector_state.down = 0; } } } + console.log(connector_state); return connector_state; } function atree_parse_connector(orient, type) { // left, right, up, down // todo - let connector_dict = { + let c_connector_dict = { "1100": {attrib: "_2_l", rotate: 0}, "1010": {attrib: "_2_a", rotate: 0}, "1001": {attrib: "_2_a", rotate: 270}, @@ -334,10 +338,21 @@ function atree_parse_connector(orient, type) { "1111": {attrib: "", rotate: 0} } + let t_connector_dict = { + "1100": {attrib: "_2_l", rotate: 0}, + "1001": {attrib: "_2_a", rotate: "flip"}, + "0101": {attrib: "_2_a", rotate: 0}, + "1101": {attrib: "_3", rotate: 0} + } + let res = "" for (let i in orient) { res += orient[i]; } - return connector_dict[res]; + if (type == "c") { + return c_connector_dict[res]; + } else { + return t_connector_dict[res]; + } } From ab38e5cf5f2509e6e1b4da519e0a1a0004a42cbb Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 16:32:41 +0700 Subject: [PATCH 25/68] remove debug code --- js/display_atree.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index 366944e..36f4c06 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -309,15 +309,11 @@ function atree_get_state(connector) { if (state) { connector_state.down = 1; - if (abil_name == "Scorched Earth") { - alert('a') - } } else { connector_state.down = 0; } } } - console.log(connector_state); return connector_state; } From 295e8f3e364bbb820cf00871704b525a0ef1a686 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 03:14:31 -0700 Subject: [PATCH 26/68] Fix damage calc... somewhat unify powder format --- js/builder.js | 1 - js/builder_graph.js | 64 ++++++++-------------- js/damage_calc.js | 119 ++++------------------------------------ js/powders.js | 131 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 148 deletions(-) diff --git a/js/builder.js b/js/builder.js index 3b6cf33..96513d8 100644 --- a/js/builder.js +++ b/js/builder.js @@ -147,7 +147,6 @@ function toggle_tab(tab) { } else { document.querySelector("#"+tab).style.display = "none"; } - console.log(document.querySelector("#"+tab).style.display); } // toggle spell arrow diff --git a/js/builder_graph.js b/js/builder_graph.js index e54fd02..f079f40 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -22,7 +22,6 @@ function update_armor_powder_specials(elem_id) { //update the label associated w/ the slider let elem = document.getElementById(elem_id); let label = document.getElementById(elem_id + "_label"); - let value = elem.value; label.textContent = label.textContent.split(":")[0] + ": " + value @@ -86,23 +85,18 @@ let powder_special_input = new (class extends ComputeNode { })(); function updatePowderSpecials(buttonId) { - let name = (buttonId).split("-")[0]; - let power = (buttonId).split("-")[1]; // [1, 5] - + let prefix = (buttonId).split("-")[0].replace(' ', '_') + '-'; let elem = document.getElementById(buttonId); - if (elem.classList.contains("toggleOn")) { //toggle the pressed button off - elem.classList.remove("toggleOn"); - } else { + if (elem.classList.contains("toggleOn")) { elem.classList.remove("toggleOn"); } + else { for (let i = 1;i < 6; i++) { //toggle all pressed buttons of the same powder special off //name is same, power is i - if(document.getElementById(name.replace(" ", "_") + "-" + i).classList.contains("toggleOn")) { - document.getElementById(name.replace(" ", "_") + "-" + i).classList.remove("toggleOn"); - } + const elem2 = document.getElementById(prefix + i); + if(elem2.classList.contains("toggleOn")) { elem2.classList.remove("toggleOn"); } } //toggle the pressed button on elem.classList.add("toggleOn"); } - powder_special_input.mark_dirty().update(); } @@ -129,6 +123,7 @@ class PowderSpecialCalcNode extends ComputeNode { } class PowderSpecialDisplayNode extends ComputeNode { + // TODO: Refactor this entirely to be adding more spells to the spell list constructor() { super('builder-powder-special-display'); this.fail_cb = true; @@ -137,27 +132,11 @@ class PowderSpecialDisplayNode extends ComputeNode { compute_func(input_map) { const powder_specials = input_map.get('powder-specials'); const stats = input_map.get('stats'); - const weapon = input_map.get('weapon'); + const weapon = input_map.get('build').weapon; displayPowderSpecials(document.getElementById("powder-special-stats"), powder_specials, stats, weapon.statMap, true); } } -/** - * Apply armor powders. - * Encoding shortcut assumes that all powders give +def to one element - * and -def to the element "behind" it in cycle ETWFA, which is true - * as of now and unlikely to change in the near future. - */ -function applyArmorPowders(expandedItem, powders) { - for(const id of powders){ - let powder = powderStats[id]; - let name = powderNames.get(id).charAt(0); - let prevName = skp_elements[(skp_elements.indexOf(name) + 4 )% 5]; - expandedItem.set(name+"Def", (expandedItem.get(name+"Def") || 0) + powder["defPlus"]); - expandedItem.set(prevName+"Def", (expandedItem.get(prevName+"Def") || 0) - powder["defMinus"]); - } -} - /** * Node for getting an item's stats from an item input field. * @@ -174,6 +153,11 @@ class ItemInputNode extends InputNode { constructor(name, item_input_field, none_item) { super(name, item_input_field); this.none_item = new Item(none_item); + this.category = this.none_item.statMap.get('category'); + if (this.category == 'armor' || this.category == 'weapon') { + this.none_item.statMap.set('powders', []); + apply_weapon_powders(this.none_item.statMap); // Needed to put in damagecalc zeros + } this.none_item.statMap.set('NONE', true); } @@ -197,17 +181,17 @@ class ItemInputNode extends InputNode { item.statMap.set('powders', powdering); } let type_match; - if (this.none_item.statMap.get('category') === 'weapon') { - type_match = item.statMap.get('category') === 'weapon'; + if (this.category == 'weapon') { + type_match = item.statMap.get('category') == 'weapon'; } else { - type_match = item.statMap.get('type') === this.none_item.statMap.get('type'); + type_match = item.statMap.get('type') == this.none_item.statMap.get('type'); } if (type_match) { - if (item.statMap.get('category') === 'armor') { - applyArmorPowders(item.statMap, powdering); + if (item.statMap.get('category') == 'armor') { + applyArmorPowders(item.statMap); } - else if (item.statMap.get('category') === 'weapon') { - apply_weapon_powders(item.statMap, powdering); + else if (item.statMap.get('category') == 'weapon') { + apply_weapon_powders(item.statMap); } return item; } @@ -579,7 +563,7 @@ class SpellDamageCalcNode extends ComputeNode { } compute_func(input_map) { - const weapon = new Map(input_map.get('weapon-input').statMap); + const weapon = input_map.get('build').weapon.statMap; const spell_info = input_map.get('spell-info'); const spell_parts = spell_info[1]; const stats = input_map.get('stats'); @@ -647,6 +631,7 @@ class SpellDisplayNode extends ComputeNode { Returns an array in the order: */ function getMeleeStats(stats, weapon) { + stats = new Map(stats); // Shallow copy const weapon_stats = weapon.statMap; const skillpoints = [ stats.get('str'), @@ -665,9 +650,8 @@ function getMeleeStats(stats, weapon) { adjAtkSpd = 0; } - let damage_mult = stats.get("damageMultiplier"); if (weapon_stats.get("type") === "relik") { - damage_mult = 0.99; // CURSE YOU WYNNCRAFT + stats.set('damageMultiplier', 0.99); // CURSE YOU WYNNCRAFT //One day we will create WynnWynn and no longer have shaman 99% melee injustice. //In all seriousness 99% is because wynn uses 0.33 to estimate dividing the damage by 3 to split damage between 3 beams. } @@ -1076,7 +1060,7 @@ function builder_graph_init() { // Powder specials. let powder_special_calc = new PowderSpecialCalcNode().link_to(powder_special_input, 'powder-specials'); new PowderSpecialDisplayNode().link_to(powder_special_input, 'powder-specials') - .link_to(stat_agg_node, 'stats').link_to(item_nodes[8], 'weapon'); + .link_to(stat_agg_node, 'stats').link_to(build_node, 'build'); stat_agg_node.link_to(powder_special_calc, 'powder-boost'); stat_agg_node.link_to(armor_powder_node, 'armor-powder'); powder_special_input.update(); @@ -1093,7 +1077,7 @@ function builder_graph_init() { spell_node.link_to(stat_agg_node, 'stats') let calc_node = new SpellDamageCalcNode(i); - calc_node.link_to(item_nodes[8], 'weapon-input').link_to(stat_agg_node, 'stats') + calc_node.link_to(build_node, 'build').link_to(stat_agg_node, 'stats') .link_to(spell_node, 'spell-info'); spelldmg_nodes.push(calc_node); diff --git a/js/damage_calc.js b/js/damage_calc.js index 856743d..e3b2f14 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -1,7 +1,5 @@ const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["vanish", 0.80], ["warscream", 0.10], ["bash", 0.50] ]); -const damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; -const damage_present_key = 'damagePresent'; function get_base_dps(item) { const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; //SUPER JANK @HPP PLS FIX @@ -27,107 +25,6 @@ function get_base_dps(item) { } } -// THIS MUTATES THE ITEM -function apply_weapon_powders(item) { - let present; - if (item.get("tier") !== "Crafted") { - let weapon_result = calc_weapon_powder(item); - let damages = weapon_result[0]; - present = weapon_result[1]; - for (const i in damage_keys) { - item.set(damage_keys[i], damages[i]); - } - } else { - let base_low = [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]; - let results_low = calc_weapon_powder(item, base_low); - let damage_low = results_low[0]; - let base_high = [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]; - let results_high = calc_weapon_powder(item, base_high); - let damage_high = results_high[0]; - present = results_high[1]; - - for (const i in damage_keys) { - item.set(damage_keys[i], [damage_low[i], damage_high[i]]); - } - } - console.log(item); - item.set(damage_present_key, present); -} - -/** - * weapon: Weapon to apply powder to - * damageBases: used by crafted - */ -function calc_weapon_powder(weapon, damageBases) { - let powders = weapon.get("powders").slice(); - - // Array of neutral + ewtfa damages. Each entry is a pair (min, max). - let damages = [ - weapon.get('nDam').split('-').map(Number), - weapon.get('eDam').split('-').map(Number), - weapon.get('tDam').split('-').map(Number), - weapon.get('wDam').split('-').map(Number), - weapon.get('fDam').split('-').map(Number), - weapon.get('aDam').split('-').map(Number) - ]; - - // Applying spell conversions - let neutralBase = damages[0].slice(); - let neutralRemainingRaw = damages[0].slice(); - - //powder application for custom crafted weapons is inherently fucked because there is no base. Unsure what to do. - - //Powder application for Crafted weapons - this implementation is RIGHT YEAAAAAAAAA - //1st round - apply each as ingred, 2nd round - apply as normal - if (weapon.get("tier") === "Crafted" && !weapon.get("custom")) { - for (const p of powders.concat(weapon.get("ingredPowders"))) { - let powder = powderStats[p]; //use min, max, and convert - let element = Math.floor((p+0.01)/6); //[0,4], the +0.01 attempts to prevent division error - let diff = Math.floor(damageBases[0] * powder.convert/100); - damageBases[0] -= diff; - damageBases[element+1] += diff + Math.floor( (powder.min + powder.max) / 2 ); - } - //update all damages - for (let i = 0; i < damages.length; i++) { - damages[i] = [Math.floor(damageBases[i] * 0.9), Math.floor(damageBases[i] * 1.1)]; - } - neutralRemainingRaw = damages[0].slice(); - neutralBase = damages[0].slice(); - } - - //apply powders to weapon - for (const powderID of powders) { - const powder = powderStats[powderID]; - // Bitwise to force conversion to integer (integer division). - const element = (powderID/6) | 0; - let conversionRatio = powder.convert/100; - if (neutralRemainingRaw[1] > 0) { - let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]); - let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]); - - //damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff)); - //damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff)); - //neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff)); - //neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff)); - damages[element+1][0] += min_diff; - damages[element+1][1] += max_diff; - neutralRemainingRaw[0] -= min_diff; - neutralRemainingRaw[1] -= max_diff; - } - damages[element+1][0] += powder.min; - damages[element+1][1] += powder.max; - } - - // The ordering of these two blocks decides whether neutral is present when converted away or not. - let present_elements = [] - for (const damage of damages) { - present_elements.push(damage[1] > 0); - } - - // The ordering of these two blocks decides whether neutral is present when converted away or not. - damages[0] = neutralRemainingRaw; - return [damages, present_elements]; -} function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, ignore_speed=false) { // TODO: Roll all the loops together maybe @@ -227,10 +124,18 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno raw_boost += stats.get(damage_prefix+'Raw') + stats.get(damage_elements[i]+'DamRaw'); } // Next, rainraw and propRaw - let new_min = damages_obj[0] + raw_boost + (damages_obj[0] / total_min) * prop_raw; - let new_max = damages_obj[1] + raw_boost + (damages_obj[1] / total_max) * prop_raw; - if (i != 0) { // rainraw - new_min += (damages_obj[0] / total_elem_min) * rainbow_raw; + let new_min = damages_obj[0] + raw_boost; + let new_max = damages_obj[1] + raw_boost; + if (total_max > 0) { // TODO: what about total negative all raw? + if (total_elem_min > 0) { + new_min += (damages_obj[0] / total_min) * prop_raw; + } + new_max += (damages_obj[1] / total_max) * prop_raw; + } + if (i != 0 && total_elem_max > 0) { // rainraw TODO above + if (total_elem_min > 0) { + new_min += (damages_obj[0] / total_elem_min) * rainbow_raw; + } new_max += (damages_obj[1] / total_elem_max) * rainbow_raw; } damages_obj[0] = new_min; diff --git a/js/powders.js b/js/powders.js index db0d195..cd2ab00 100644 --- a/js/powders.js +++ b/js/powders.js @@ -61,3 +61,134 @@ let powderSpecialStats = [ _ps("Courage",new Map([ ["Duration", [6,6.5,7,7.5,8]],["Damage", [75,87.5,100,112.5,125]],["Damage Boost", [70,90,110,130,150]] ]),"Endurance",new Map([ ["Damage", [2,3,4,5,6]],["Duration", [8,8,8,8,8]],["Description", "Hit Taken"] ]),200), //f _ps("Wind Prison",new Map([ ["Duration", [3,3.5,4,4.5,5]],["Damage Boost", [400,450,500,550,600]],["Knockback", [8,12,16,20,24]] ]),"Dodge",new Map([ ["Damage",[2,3,4,5,6]],["Duration",[2,3,4,5,6]],["Description","Near Mobs"] ]),150) //a ]; + +/** + * Apply armor powders. + * Encoding shortcut assumes that all powders give +def to one element + * and -def to the element "behind" it in cycle ETWFA, which is true + * as of now and unlikely to change in the near future. + */ +function applyArmorPowders(expandedItem) { + const powders = expandedItem.get('powders'); + for(const id of powders){ + let powder = powderStats[id]; + let name = powderNames.get(id).charAt(0); + let prevName = skp_elements[(skp_elements.indexOf(name) + 4 )% 5]; + expandedItem.set(name+"Def", (expandedItem.get(name+"Def") || 0) + powder["defPlus"]); + expandedItem.set(prevName+"Def", (expandedItem.get(prevName+"Def") || 0) - powder["defMinus"]); + } +} + +const damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ]; +const damage_present_key = 'damagePresent'; +/** + * Apply weapon powders. MUTATES THE ITEM! + * Adds entries for `damage_keys` and `damage_present_key` + * For normal items, `damage_keys` is 6x2 list (elem: [min, max]) + * For crafted items, `damage_keys` is 6x2x2 list (elem: [minroll: [min, max], maxroll: [min, max]]) + */ +function apply_weapon_powders(item) { + let present; + if (item.get("tier") !== "Crafted") { + let weapon_result = calc_weapon_powder(item); + let damages = weapon_result[0]; + present = weapon_result[1]; + for (const i in damage_keys) { + item.set(damage_keys[i], damages[i]); + } + } else { + let base_low = [item.get("nDamBaseLow"),item.get("eDamBaseLow"),item.get("tDamBaseLow"),item.get("wDamBaseLow"),item.get("fDamBaseLow"),item.get("aDamBaseLow")]; + let results_low = calc_weapon_powder(item, base_low); + let damage_low = results_low[0]; + let base_high = [item.get("nDamBaseHigh"),item.get("eDamBaseHigh"),item.get("tDamBaseHigh"),item.get("wDamBaseHigh"),item.get("fDamBaseHigh"),item.get("aDamBaseHigh")]; + let results_high = calc_weapon_powder(item, base_high); + let damage_high = results_high[0]; + present = results_high[1]; + + for (const i in damage_keys) { + item.set(damage_keys[i], [damage_low[i], damage_high[i]]); + } + } + item.set(damage_present_key, present); +} + +/** + * Calculate weapon damage from powder. + * + * Params: + * weapon: Weapon to apply powder to + * damageBases: used by crafted + * + * Return: + * [damages, damage_present] + */ +function calc_weapon_powder(weapon, damageBases) { + let powders = weapon.get("powders").slice(); + + // Array of neutral + ewtfa damages. Each entry is a pair (min, max). + let damages = [ + weapon.get('nDam').split('-').map(Number), + weapon.get('eDam').split('-').map(Number), + weapon.get('tDam').split('-').map(Number), + weapon.get('wDam').split('-').map(Number), + weapon.get('fDam').split('-').map(Number), + weapon.get('aDam').split('-').map(Number) + ]; + + // Applying spell conversions + let neutralBase = damages[0].slice(); + let neutralRemainingRaw = damages[0].slice(); + + //powder application for custom crafted weapons is inherently fucked because there is no base. Unsure what to do. + + //Powder application for Crafted weapons - this implementation is RIGHT YEAAAAAAAAA + //1st round - apply each as ingred, 2nd round - apply as normal + if (weapon.get("tier") === "Crafted" && !weapon.get("custom")) { + for (const p of powders.concat(weapon.get("ingredPowders"))) { + let powder = powderStats[p]; //use min, max, and convert + let element = Math.floor((p+0.01)/6); //[0,4], the +0.01 attempts to prevent division error + let diff = Math.floor(damageBases[0] * powder.convert/100); + damageBases[0] -= diff; + damageBases[element+1] += diff + Math.floor( (powder.min + powder.max) / 2 ); + } + //update all damages + for (let i = 0; i < damages.length; i++) { + damages[i] = [Math.floor(damageBases[i] * 0.9), Math.floor(damageBases[i] * 1.1)]; + } + neutralRemainingRaw = damages[0].slice(); + neutralBase = damages[0].slice(); + } + + //apply powders to weapon + for (const powderID of powders) { + const powder = powderStats[powderID]; + // Bitwise to force conversion to integer (integer division). + const element = (powderID/6) | 0; + let conversionRatio = powder.convert/100; + if (neutralRemainingRaw[1] > 0) { + let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]); + let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]); + + //damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff)); + //damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff)); + //neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff)); + //neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff)); + damages[element+1][0] += min_diff; + damages[element+1][1] += max_diff; + neutralRemainingRaw[0] -= min_diff; + neutralRemainingRaw[1] -= max_diff; + } + damages[element+1][0] += powder.min; + damages[element+1][1] += powder.max; + } + + // The ordering of these two blocks decides whether neutral is present when converted away or not. + let present_elements = [] + for (const damage of damages) { + present_elements.push(damage[1] > 0); + } + + // The ordering of these two blocks decides whether neutral is present when converted away or not. + damages[0] = neutralRemainingRaw; + return [damages, present_elements]; +} From d3c11a8a726170c80da875dc12bd2cb8267d8f3b Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 17:48:00 +0700 Subject: [PATCH 27/68] fix: tri failing case --- js/display_atree.js | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index 36f4c06..9d4292c 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -237,6 +237,11 @@ function atree_toggle_state(node) { } function atree_update_connector() { + atree_connectors_map.forEach((v) => { + if (v.length != 0) { + v[0].connector.style.backgroundImage = "url('../media/atree/connect_" + v[0].type + ".png')"; + } + }); atree_map.forEach((v) => { atree_compute_highlight(v); }); @@ -249,33 +254,15 @@ function atree_compute_highlight(node) { connector_data = atree_connectors_map.get(i)[0]; if (connector_data.type == "c" || connector_data.type == "t") { connector_data.connector_state = atree_get_state(i); - let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type) + let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type); connector_data.connector.className = ""; connector_data.connector.classList.add("rotate-" + connector_img.rotate); connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + connector_img.attrib + ".png')"; } else { connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + ".png')"; - } - } - } else { - for (let i of v) { - connector_data = atree_connectors_map.get(i)[0]; - if (connector_data.type == "c" || connector_data.type == "t") { - connector_data.connector_state = atree_get_state(i); - let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type) - if (!connector_img) { - connector_data.connector.className = ""; - connector_data.connector.style.backgroundImage = "url('../media/atree/connect_" + connector_data.type + ".png')"; - } else { - connector_data.connector.className = ""; - connector_data.connector.classList.add("rotate-" + connector_img.rotate); - connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + connector_img.attrib + ".png')"; - }; - } else { - connector_data.connector.style.backgroundImage = "url('../media/atree/connect_" + connector_data.type + ".png')"; - } - } - } + }; + }; + }; }); } @@ -283,37 +270,38 @@ function atree_get_state(connector) { let connector_state = {left: 0, right: 0, up: 0, down: 0} for (let abil_name of atree_connectors_map.get(connector)[0].owner) { + state = atree_map.get(abil_name).active; if (atree_map.get(abil_name).display.col > parseInt(connector.split(",")[1])) { if (state) { connector_state.right = 1; - } else { + } else if (!connector_state.right) { connector_state.right = 0; } } if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { if (state) { connector_state.left = 1; - } else { + } else if (!connector_state.left) { connector_state.left = 0; } } if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { if (state) { connector_state.up = 1; - } else { + } else if (!connector_state.up) { connector_state.up = 0; } } if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { - if (state) { connector_state.down = 1; - } else { + } else if (!connector_state.down) { connector_state.down = 0; } } } + console.log(connector_state) return connector_state; } From b9e04c4c9fab87fd3e129aef7ad61f0978c8feaf Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 17:55:06 +0700 Subject: [PATCH 28/68] add general comments --- js/display_atree.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index 9d4292c..d02965f 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -167,7 +167,7 @@ function construct_AT(elem, tree) { this.classList.add("atree-selected"); } atree_toggle_state(node); - atree_update_connector(node); + atree_update_connector(); }); document.getElementById("atree-row-" + node.display.row).children[node.display.col].appendChild(node_elem); }; @@ -175,7 +175,7 @@ function construct_AT(elem, tree) { atree_render_connection(); }; -// resolve connector conflict +// resolve connector conflict, when they occupy the same cell. function resolve_connector(pos, node) { if (atree_connectors_map.get(pos).length < 2) {return false;} @@ -228,6 +228,7 @@ function atree_render_connection() { } } +// toggle the state of a node. function atree_toggle_state(node) { if (atree_map.get(node.display_name).active) { atree_map.get(node.display_name).active = false; @@ -236,6 +237,7 @@ function atree_toggle_state(node) { } } +// refresh all connector to default state, then try to calculate the connector for all node function atree_update_connector() { atree_connectors_map.forEach((v) => { if (v.length != 0) { @@ -247,6 +249,7 @@ function atree_update_connector() { }); } +// set the correct connector highlight for an active node, given a node. function atree_compute_highlight(node) { node.connectors.forEach((v, k) => { if (node.active && atree_map.get(k).active) { @@ -266,6 +269,7 @@ function atree_compute_highlight(node) { }); } +// get the current active state of different directions, given a connector coordinate. function atree_get_state(connector) { let connector_state = {left: 0, right: 0, up: 0, down: 0} @@ -305,6 +309,7 @@ function atree_get_state(connector) { return connector_state; } +// parse a sequence of left, right, up, down to appropriate connector image function atree_parse_connector(orient, type) { // left, right, up, down // todo From aa9041bd010a11cad7bc2a3d1e0006a7f0e9b654 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 04:08:54 -0700 Subject: [PATCH 29/68] Fix tome damage calculation... --- js/build.js | 5 +++-- js/build_utils.js | 5 ++++- js/builder_graph.js | 1 + js/damage_calc.js | 3 ++- js/load_tome.js | 2 +- tomes.json | 38 +++++++++++++++++++------------------- 6 files changed, 30 insertions(+), 24 deletions(-) diff --git a/js/build.js b/js/build.js index fc57316..ff14bee 100644 --- a/js/build.js +++ b/js/build.js @@ -153,7 +153,7 @@ class Build{ */ initBuildStats(){ - let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef", "str", "dex", "int", "def", "agi", "dmgMobs", "defMobs"]; + let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef", "str", "dex", "int", "def", "agi", "damMobs", "defMobs"]; let must_ids = [ "eMdPct","eMdRaw","eSdPct","eSdRaw","eDamPct","eDamRaw","eDamAddMin","eDamAddMax", @@ -188,9 +188,10 @@ class Build{ } statMap.set(id,(statMap.get(id) || 0)+value); } + console.log(item_stats); for (const staticID of staticIDs) { if (item_stats.get(staticID)) { - if (staticID === "dmgMobs") { + if (staticID == "damMobs") { statMap.set('damageMultiplier', statMap.get('damageMultiplier') * item_stats.get(staticID)); } else if (staticID === "defMobs") { diff --git a/js/build_utils.js b/js/build_utils.js index 58e863d..17dfd4e 100644 --- a/js/build_utils.js +++ b/js/build_utils.js @@ -78,12 +78,13 @@ let item_fields = [ "name", "displayName", "lore", "color", "tier", "set", "slot /*"mdPct","mdRaw","sdPct","sdRaw",*/"damPct","damRaw","damAddMin","damAddMax", // These are the old ids. Become proportional. "rMdPct","rMdRaw","rSdPct",/*"rSdRaw",*/"rDamPct","rDamRaw","rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). rSdRaw is rainraw ]; +// Extra fake IDs (reserved for use in spell damage calculation) : damageMultiplier, defMultiplier, poisonPct, activeMajorIDs let str_item_fields = [ "name", "displayName", "lore", "color", "tier", "set", "type", "material", "drop", "quest", "restrict", "category", "atkSpd" ] //File reading for ID translations for JSON purposes let reversetranslations = new Map(); let translations = new Map([["name", "name"], ["displayName", "displayName"], ["tier", "tier"], ["set", "set"], ["sockets", "slots"], ["type", "type"], ["dropType", "drop"], ["quest", "quest"], ["restrictions", "restrict"], ["damage", "nDam"], ["fireDamage", "fDam"], ["waterDamage", "wDam"], ["airDamage", "aDam"], ["thunderDamage", "tDam"], ["earthDamage", "eDam"], ["attackSpeed", "atkSpd"], ["health", "hp"], ["fireDefense", "fDef"], ["waterDefense", "wDef"], ["airDefense", "aDef"], ["thunderDefense", "tDef"], ["earthDefense", "eDef"], ["level", "lvl"], ["classRequirement", "classReq"], ["strength", "strReq"], ["dexterity", "dexReq"], ["intelligence", "intReq"], ["agility", "agiReq"], ["defense", "defReq"], ["healthRegen", "hprPct"], ["manaRegen", "mr"], ["spellDamage", "sdPct"], ["damageBonus", "mdPct"], ["lifeSteal", "ls"], ["manaSteal", "ms"], ["xpBonus", "xpb"], ["lootBonus", "lb"], ["reflection", "ref"], ["strengthPoints", "str"], ["dexterityPoints", "dex"], ["intelligencePoints", "int"], ["agilityPoints", "agi"], ["defensePoints", "def"], ["thorns", "thorns"], ["exploding", "expd"], ["speed", "spd"], ["attackSpeedBonus", "atkTier"], ["poison", "poison"], ["healthBonus", "hpBonus"], ["soulPoints", "spRegen"], ["emeraldStealing", "eSteal"], ["healthRegenRaw", "hprRaw"], ["spellDamageRaw", "sdRaw"], ["damageBonusRaw", "mdRaw"], ["bonusFireDamage", "fDamPct"], ["bonusWaterDamage", "wDamPct"], ["bonusAirDamage", "aDamPct"], ["bonusThunderDamage", "tDamPct"], ["bonusEarthDamage", "eDamPct"], ["bonusFireDefense", "fDefPct"], ["bonusWaterDefense", "wDefPct"], ["bonusAirDefense", "aDefPct"], ["bonusThunderDefense", "tDefPct"], ["bonusEarthDefense", "eDefPct"], ["type", "type"], ["identified", "fixID"], ["skin", "skin"], ["category", "category"], ["spellCostPct1", "spPct1"], ["spellCostRaw1", "spRaw1"], ["spellCostPct2", "spPct2"], ["spellCostRaw2", "spRaw2"], ["spellCostPct3", "spPct3"], ["spellCostRaw3", "spRaw3"], ["spellCostPct4", "spPct4"], ["spellCostRaw4", "spRaw4"], ["rainbowSpellDamageRaw", "rSdRaw"], ["sprint", "sprint"], ["sprintRegen", "sprintReg"], ["jumpHeight", "jh"], ["lootQuality", "lq"], ["gatherXpBonus", "gXp"], ["gatherSpeed", "gSpd"]]); -//does not include dmgMobs (wep tomes) and defMobs (armor tomes) +//does not include damMobs (wep tomes) and defMobs (armor tomes) for (const [k, v] of translations) { reversetranslations.set(v, k); } @@ -115,6 +116,8 @@ let nonRolledIDs = [ "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds", + "damMobs", + "defMobs", // wynn2 damages. "eDamAddMin","eDamAddMax", "tDamAddMin","tDamAddMax", diff --git a/js/builder_graph.js b/js/builder_graph.js index f079f40..b18204b 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -832,6 +832,7 @@ class AggregateStatsNode extends ComputeNode { } } } + console.log(output_stats); return output_stats; } } diff --git a/js/damage_calc.js b/js/damage_calc.js index e3b2f14..a2ad42d 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -101,7 +101,8 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno let total_max = 0; for (let i in damages) { let damage_prefix = damage_elements[i] + specific_boost_str; - let damageBoost = 1 + skill_boost[i] + static_boost + (stats.get(damage_prefix+'Pct')/100); + let damageBoost = 1 + skill_boost[i] + static_boost + + ((stats.get(damage_prefix+'Pct') + stats.get(damage_elements[i]+'DamPct')) /100); damages[i][0] *= Math.max(damageBoost, 0); damages[i][1] *= Math.max(damageBoost, 0); // Collect total damage post %boost diff --git a/js/load_tome.js b/js/load_tome.js index 7b75451..6cde49d 100644 --- a/js/load_tome.js +++ b/js/load_tome.js @@ -1,4 +1,4 @@ -const TOME_DB_VERSION = 2; +const TOME_DB_VERSION = 3; // @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA let tdb; diff --git a/tomes.json b/tomes.json index 0b4c213..dc60657 100644 --- a/tomes.json +++ b/tomes.json @@ -290,7 +290,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 60, - "dmgMobs": 6, + "damMobs": 6, "fixID": false, "id": 20 }, @@ -302,7 +302,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "str": 3, "fixID": false, "id": 21 @@ -315,7 +315,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "str": 3, "fixID": false, "id": 22 @@ -328,7 +328,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "dex": 3, "fixID": false, "id": 23 @@ -341,7 +341,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "dex": 3, "fixID": false, "id": 24 @@ -354,7 +354,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "int": 3, "fixID": false, "id": 25 @@ -367,7 +367,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "int": 3, "fixID": false, "id": 26 @@ -380,7 +380,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "def": 3, "fixID": false, "id": 27 @@ -393,7 +393,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "def": 3, "fixID": false, "id": 28 @@ -406,7 +406,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "agi": 3, "fixID": false, "id": 29 @@ -419,7 +419,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "agi": 3, "fixID": false, "id": 30 @@ -432,7 +432,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 7, + "damMobs": 7, "str": 1, "dex": 1, "int": 1, @@ -449,7 +449,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 8, + "damMobs": 8, "str": 1, "dex": 1, "int": 1, @@ -466,7 +466,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "eDamPct": 7, "fixID": false, "id": 33 @@ -479,7 +479,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "tDamPct": 7, "fixID": false, "id": 34 @@ -492,7 +492,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "wDamPct": 7, "fixID": false, "id": 35 @@ -505,7 +505,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "fDamPct": 7, "fixID": false, "id": 36 @@ -518,7 +518,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "aDamPct": 7, "fixID": false, "id": 37 @@ -531,7 +531,7 @@ "drop": "never", "restrict": "Soulbound Item", "lvl": 80, - "dmgMobs": 12, + "damMobs": 12, "eDamPct": 6, "tDamPct": 6, "wDamPct": 6, From 762120d1895085c37c4a8359d94c7cd8a65d71d6 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 04:12:04 -0700 Subject: [PATCH 30/68] Fix tomes (for real...) --- js/build.js | 11 ++--------- js/builder_graph.js | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/js/build.js b/js/build.js index ff14bee..4ce69b1 100644 --- a/js/build.js +++ b/js/build.js @@ -168,7 +168,6 @@ class Build{ //Create a map of this build's stats let statMap = new Map(); - statMap.set("damageMultiplier", 1); statMap.set("defMultiplier", 1); for (const staticID of staticIDs) { @@ -191,15 +190,7 @@ class Build{ console.log(item_stats); for (const staticID of staticIDs) { if (item_stats.get(staticID)) { - if (staticID == "damMobs") { - statMap.set('damageMultiplier', statMap.get('damageMultiplier') * item_stats.get(staticID)); - } - else if (staticID === "defMobs") { - statMap.set('defMultiplier', statMap.get('defMultiplier') * item_stats.get(staticID)); - } - else { statMap.set(staticID, statMap.get(staticID) + item_stats.get(staticID)); - } } } if (item_stats.get("majorIds")) { @@ -208,6 +199,8 @@ class Build{ } } } + statMap.set('damageMultiplier', 1 + (statMap.get('damMobs') / 100)); + statMap.set('defMultiplier', 1 - (statMap.get('defMobs') / 100)); statMap.set("activeMajorIDs", major_ids); for (const [setName, count] of this.activeSetCounts) { const bonus = sets.get(setName).bonuses[count-1]; diff --git a/js/builder_graph.js b/js/builder_graph.js index b18204b..8bb8c67 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -524,7 +524,7 @@ function getDefenseStats(stats) { defenseStats.push(totalHp); //EHP let ehp = [totalHp, totalHp]; - let defMult = (2 - stats.get("classDef")) * (2 - stats.get("defMultiplier")); + let defMult = (2 - stats.get("classDef")) * stats.get("defMultiplier"); ehp[0] /= (1-def_pct)*(1-agi_pct)*defMult; ehp[1] /= (1-def_pct)*defMult; defenseStats.push(ehp); From 9d79a6de7eeb6b0db163a9f5555bc26681c51bb2 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 18:18:27 +0700 Subject: [PATCH 31/68] push rotate-flip css --- css/sq2bs.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/css/sq2bs.css b/css/sq2bs.css index 6e41131..9b42afe 100644 --- a/css/sq2bs.css +++ b/css/sq2bs.css @@ -474,6 +474,11 @@ a:hover { transform: rotate(270deg); } +.rotate-flip { + -webkit-transform: scaleX(-1); + transform: scaleX(-1); +} + .hide-scroll { From dcc65516cd0b58999e53a718748717af4904922c Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 18:29:55 +0700 Subject: [PATCH 32/68] fix: unsafe connector rotation --- js/display_atree.js | 64 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index d02965f..d83725e 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -156,7 +156,7 @@ function construct_AT(elem, tree) { document.getElementById("atree-active").appendChild(active_tooltip); node_elem.addEventListener('click', function(e) { - if (e.target !== this) {return;} + if (e.target !== this) {return;}; let tooltip = document.getElementById("atree-ab-" + node.display_name.replaceAll(" ", "")); if (tooltip.style.display == "block") { tooltip.style.display = "none"; @@ -165,7 +165,7 @@ function construct_AT(elem, tree) { else { tooltip.style.display = "block"; this.classList.add("atree-selected"); - } + }; atree_toggle_state(node); atree_update_connector(); }); @@ -194,7 +194,7 @@ function resolve_connector(pos, node) { owners = owners.concat(i.owner); } - owners = [...new Set(owners)] + owners = [...new Set(owners)]; let connect_elem = document.createElement("div"); @@ -215,18 +215,18 @@ function resolve_connector(pos, node) { function atree_same_row(node) { for (let i of node.parents) { if (node.display.row == atree_map.get(i).display.row) { return false; } - } + }; return true; -} +}; // draw the connector onto the screen function atree_render_connection() { for (let i of atree_connectors_map.keys()) { if (atree_connectors_map.get(i).length != 0) { document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].appendChild(atree_connectors_map.get(i)[0].connector); - } - } -} + }; + }; +}; // toggle the state of a node. function atree_toggle_state(node) { @@ -234,8 +234,8 @@ function atree_toggle_state(node) { atree_map.get(node.display_name).active = false; } else { atree_map.get(node.display_name).active = true; - } -} + }; +}; // refresh all connector to default state, then try to calculate the connector for all node function atree_update_connector() { @@ -267,52 +267,50 @@ function atree_compute_highlight(node) { }; }; }); -} +}; // get the current active state of different directions, given a connector coordinate. function atree_get_state(connector) { - let connector_state = {left: 0, right: 0, up: 0, down: 0} + let connector_state = [0, 0, 0, 0]; // left, right, up, down for (let abil_name of atree_connectors_map.get(connector)[0].owner) { state = atree_map.get(abil_name).active; if (atree_map.get(abil_name).display.col > parseInt(connector.split(",")[1])) { if (state) { - connector_state.right = 1; + connector_state[1] = 1; } else if (!connector_state.right) { - connector_state.right = 0; + connector_state[1] = 0; } } if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { if (state) { - connector_state.left = 1; + connector_state[0] = 1; } else if (!connector_state.left) { - connector_state.left = 0; + connector_state[0] = 0; } } if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { if (state) { - connector_state.up = 1; + connector_state[2] = 1; } else if (!connector_state.up) { - connector_state.up = 0; + connector_state[2] = 0; } } if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { if (state) { - connector_state.down = 1; + connector_state[3] = 1; } else if (!connector_state.down) { - connector_state.down = 0; - } - } - } - console.log(connector_state) + connector_state[3] = 0; + }; + }; + }; return connector_state; } // parse a sequence of left, right, up, down to appropriate connector image function atree_parse_connector(orient, type) { // left, right, up, down - // todo let c_connector_dict = { "1100": {attrib: "_2_l", rotate: 0}, "1010": {attrib: "_2_a", rotate: 0}, @@ -325,23 +323,23 @@ function atree_parse_connector(orient, type) { "1011": {attrib: "_3", rotate: 270}, "0111": {attrib: "_3", rotate: 90}, "1111": {attrib: "", rotate: 0} - } + }; let t_connector_dict = { "1100": {attrib: "_2_l", rotate: 0}, "1001": {attrib: "_2_a", rotate: "flip"}, "0101": {attrib: "_2_a", rotate: 0}, "1101": {attrib: "_3", rotate: 0} - } + }; - let res = "" - for (let i in orient) { - res += orient[i]; - } + let res = ""; + for (let i of orient) { + res += i; + }; if (type == "c") { return c_connector_dict[res]; } else { return t_connector_dict[res]; - } -} + }; +}; From 01e02d603b19f50ffc2582efc161535da561680f Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 18:34:35 +0700 Subject: [PATCH 33/68] fix: unsafe connector rotation (for real this time) --- js/display_atree.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/display_atree.js b/js/display_atree.js index d83725e..d97ca36 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -279,28 +279,28 @@ function atree_get_state(connector) { if (atree_map.get(abil_name).display.col > parseInt(connector.split(",")[1])) { if (state) { connector_state[1] = 1; - } else if (!connector_state.right) { + } else if (!connector_state[1]) { connector_state[1] = 0; } } if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { if (state) { connector_state[0] = 1; - } else if (!connector_state.left) { + } else if (!connector_state[0]) { connector_state[0] = 0; } } if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { if (state) { connector_state[2] = 1; - } else if (!connector_state.up) { + } else if (!connector_state[2]) { connector_state[2] = 0; } } if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { if (state) { connector_state[3] = 1; - } else if (!connector_state.down) { + } else if (!connector_state[3]) { connector_state[3] = 0; }; }; From 89879e6a02a0d9b1431c8a484987fd73a7bc67c7 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 18:42:58 +0700 Subject: [PATCH 34/68] fix: correct connector assets --- media/atree/highlight_t_2_a.png | Bin 708 -> 708 bytes media/atree/highlight_t_3.png | Bin 654 -> 654 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/media/atree/highlight_t_2_a.png b/media/atree/highlight_t_2_a.png index 1d808274b041f41fb0fa784c14a04ae6ce1f34a4..e6cd87a670763959d4639d0911ee28777eb60db6 100644 GIT binary patch literal 708 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBzEFTqh%1n0P*P&}|DQoy`#+FmV5qH00|~N~1o;I6MSxMiM=PMX)-DKFZnK2`s`NBE21#@{Ftfd>u%oyJ03?2!GOJ)0y|Ni+g0^kv0rzG*Ok;Rz0L6DR6oO)%d3B#|KM2f|9d|}ZIM93 uHw9p9Ffd%uwr2t}2D8`$fd|i@+dtIzy3M1qgA?RjPgg&ebxsLQAPfMu_VwTZ literal 708 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBzEFTqh%1n0P*P&}|DQoy`#+FmV5qH00|~N~1o;I6MSxAr*0NZyEN9IEuI&jGeak|5V18H+ipxclSJBV!U=0 zSGC=~^S^%Fecr$S+t26awM7CA-xPqxF)&=vmS+Mp2D8`$u?O4gS%2g+gIs&TfBi3; zx2wbLzFhV1|MlX=_b;E#7-WCX+jS$9!RniB>BiLzC2y)>DleHU14w+4fIUC3EXPV;kv)GBbv^ISjXMGHlt* sn32wW;T+q7xx5b6gGZv5xu*U3)MtDyDC!36Y6V^O;%vC zo2}qZR delta 336 zcmeBU?PHzLRR7S^#WAEJ?(MCOdD4LbERL5R{jcAwyWsKUMZ7jwPpZ@?Yv5 z>%Y&B-@Cv6^+`vDTg?n0;1F)d0%lYd2{e3D05dO4qVnZWGWp8{a|MLm_xLo@Dx?t$F>tUvOZK@NMdJbbVJ?^mbV_x*Yqxc*<68N=J0 z$tH~AlNcqrYc-9c6@gsq>FVdQ&MBcO OyW{Djj2FlvAW;AW`fVlv From 72999c3014780ba2ce98b7388381ba6c9b184752 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 05:18:23 -0700 Subject: [PATCH 35/68] Fix set initial load --- js/build.js | 1 - js/builder_graph.js | 1 - js/display_atree.js | 6 ++++++ js/load.js | 7 ++++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/js/build.js b/js/build.js index 4ce69b1..fee67cf 100644 --- a/js/build.js +++ b/js/build.js @@ -187,7 +187,6 @@ class Build{ } statMap.set(id,(statMap.get(id) || 0)+value); } - console.log(item_stats); for (const staticID of staticIDs) { if (item_stats.get(staticID)) { statMap.set(staticID, statMap.get(staticID) + item_stats.get(staticID)); diff --git a/js/builder_graph.js b/js/builder_graph.js index 8bb8c67..c03feea 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -832,7 +832,6 @@ class AggregateStatsNode extends ComputeNode { } } } - console.log(output_stats); return output_stats; } } diff --git a/js/display_atree.js b/js/display_atree.js index d97ca36..2a65058 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -1,4 +1,5 @@ let atree_map; +let atree_head; let atree_connectors_map; let atree_active_connections = []; function construct_AT(elem, tree) { @@ -26,6 +27,11 @@ function construct_AT(elem, tree) { // create rows if not exist let missing_rows = [node.display.row]; + if (node.parents.length == 0) { + // Assuming there is only one head. + atree_head = node; + } + for (let parent of node.parents) { missing_rows.push(tree.find(object => {return object.display_name === parent;}).display.row); } diff --git a/js/load.js b/js/load.js index 521765e..678e012 100644 --- a/js/load.js +++ b/js/load.js @@ -103,7 +103,7 @@ async function load() { let url = baseUrl + "/compress.json?"+new Date(); let result = await (await fetch(url)).json(); items = result.items; - sets = result.sets; + let sets_ = result.sets; let add_tx = db.transaction(['item_db', 'set_db'], 'readwrite'); add_tx.onabort = function(e) { @@ -121,8 +121,9 @@ async function load() { add_promises.push(req); } let sets_store = add_tx.objectStore('set_db'); - for (const set in sets) { - add_promises.push(sets_store.add(sets[set], set)); + for (const set in sets_) { + add_promises.push(sets_store.add(sets_[set], set)); + sets.set(set, sets_[set]); } add_promises.push(add_tx.complete); From 83fcfd15f414230a69dc654b858597768bf84610 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 19:40:17 +0700 Subject: [PATCH 36/68] change to id, from display_name --- js/atree_constants.js | 4141 ++++++++++++++++------------ js/atree_constants_min.js | 2 +- js/atree_constants_str_old.js | 4160 +++++++++++++++++++++++++++++ js/atree_constants_str_old_min.js | 1 + js/display_atree.js | 29 +- 5 files changed, 6651 insertions(+), 1682 deletions(-) create mode 100644 js/atree_constants_str_old.js create mode 100644 js/atree_constants_str_old_min.js diff --git a/js/atree_constants.js b/js/atree_constants.js index 765249f..8e9ae98 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -1,12 +1,14 @@ -const atrees = -{ +const atrees = { "Archer": [ { "display_name": "Arrow Shield", "desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)", "archetype": "", "archetype_req": 0, - "parents": ["Power Shots", "Cheaper Escape"], + "parents": [ + 60, + 34 + ], "dependencies": [], "blockers": [], "cost": 1, @@ -31,7 +33,14 @@ const atrees = { "name": "Shield Damage", "type": "damage", - "multipliers": [90, 0, 0, 0, 0, 10] + "multipliers": [ + 90, + 0, + 0, + 0, + 0, + 10 + ] }, { "name": "Total Damage", @@ -42,955 +51,1258 @@ const atrees = } ] } - ] + ], + "id": 0 }, - { "display_name": "Escape", "desc": "Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": ["Heart Shatter"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 3 + ], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 7, - "col": 4 + "row": 7, + "col": 4 }, "properties": { - "aoe": 0, - "range": 0 + "aoe": 0, + "range": 0 }, "effects": [ - { - "type": "replace_spell", - "name": "Escape", - "cost": 25, - "display_text": "Max Damage", - "base_spell": 2, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "None", - "type": "damage", - "multipliers": [0, 0, 0, 0, 0, 0] - }, { - "name": "Total Damage", - "type": "total", - "hits": { - "None": 0 - } + "type": "replace_spell", + "name": "Escape", + "cost": 25, + "display_text": "Max Damage", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } + } + ] } - ] - } - ] + ], + "id": 1 }, { "display_name": "Arrow Bomb", "desc": "Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)", - "archetype": "", - "archetype_req": 0, - "parents": [], + "archetype": "", + "archetype_req": 0, + "parents": [], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 0, - "col": 4 + "row": 0, + "col": 4 }, "properties": { - "aoe": 4.5, - "range": 26 + "aoe": 4.5, + "range": 26 }, "effects": [ - { - "type": "replace_spell", - "name": "Arrow Bomb", - "cost": 50, - "display_text": "Average Damage", - "base_spell": 3, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Arrow Bomb", - "type": "damage", - "multipliers": [160, 0, 0, 0, 20, 0] - }, { - "name": "Total Damage", - "type": "total", - "hits": { - "Arrow Bomb": 1 - } + "type": "replace_spell", + "name": "Arrow Bomb", + "cost": 50, + "display_text": "Average Damage", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Arrow Bomb", + "type": "damage", + "multipliers": [ + 160, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Arrow Bomb": 1 + } + } + ] } - ] - } - ] + ], + "id": 2 }, { "display_name": "Heart Shatter", "desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.", - "archetype": "", - "archetype_req": 0, - "parents": ["Bow Proficiency I"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 31 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 4, - "col": 4 + "row": 4, + "col": 4 }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] - }, - { - - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + }, + {} + ], + "id": 3 }, { "display_name": "Fire Creep", "desc": "Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.", - "archetype": "", - "archetype_req": 0, - "parents": ["Phantom Ray", "Fire Mastery", "Bryophyte Roots"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 68, + 86, + 5 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 16, - "col": 6 + "row": 16, + "col": 6 }, - "properties": { - "aoe": 0.8, - "duration": 6 + "properties": { + "aoe": 0.8, + "duration": 6 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [30, 0, 0, 0, 20, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fire Creep": 15 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fire Creep": 15 + } } - } - ] + ], + "id": 4 }, { "display_name": "Bryophyte Roots", "desc": "When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.", - "archetype": "Trapper", - "archetype_req": 1, - "parents": ["Fire Creep", "Earth Mastery"], - "dependencies": ["Arrow Storm"], + "archetype": "Trapper", + "archetype_req": 1, + "parents": [ + 4, + 82 + ], + "dependencies": [ + 7 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 16, - "col": 8 + "row": 16, + "col": 8 }, "properties": { - "aoe": 2, - "duration": 5, - "slowness": 0.4 - }, + "aoe": 2, + "duration": 5, + "slowness": 0.4 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Bryophyte Roots", - "cost": 0, - "multipliers": [40, 20, 0, 0, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Bryophyte Roots", + "cost": 0, + "multipliers": [ + 40, + 20, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 5 }, { "display_name": "Nimble String", "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", - "archetype": "", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Arrow Rain"], - "dependencies": ["Arrow Storm"], - "blockers": ["Phantom Ray"], - "cost": 2, + "archetype": "", + "archetype_req": 0, + "parents": [ + 83, + 69 + ], + "dependencies": [ + 7 + ], + "blockers": [ + 68 + ], + "cost": 2, "display": { - "row": 15, - "col": 2 + "row": 15, + "col": 2 }, "properties": { - "shootspeed": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [-15, 0, 0, 0, 0, 0] + "shootspeed": 2 }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Stream", - "cost": 0, - "hits": { - "Single Arrow": 8 + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + -15, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Stream", + "cost": 0, + "hits": { + "Single Arrow": 8 + } } - } - ] + ], + "id": 6 }, { "display_name": "Arrow Storm", "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", - "archetype": "", - "archetype_req": 0, - "parents": ["Double Shots", "Cheaper Escape"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 58, + 34 + ], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 9, - "col": 2 + "row": 9, + "col": 2 }, "properties": { - "aoe": 0, - "range": 16 + "aoe": 0, + "range": 16 }, "effects": [ - { - "type": "replace_spell", - "name": "Arrow Storm", - "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [30, 0, 10, 0, 0, 0] - }, - { - "name": "Single Stream", - "type": "total", - "hits": { - "Single Arrow": 8 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Stream": 2 - } + { + "type": "replace_spell", + "name": "Arrow Storm", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 30, + 0, + 10, + 0, + 0, + 0 + ] + }, + { + "name": "Single Stream", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Stream": 2 + } + } + ] } - ] - } - ] + ], + "id": 7 }, { "display_name": "Guardian Angels", "desc": "Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)", "archetype": "Boltslinger", - "archetype_req": 3, - "parents": ["Triple Shots", "Frenzy"], - "dependencies": ["Arrow Shield"], + "archetype_req": 3, + "parents": [ + 59, + 67 + ], + "dependencies": [ + 0 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 19, - "col": 1 + "row": 19, + "col": 1 }, "properties": { - "range": 4, - "duration": 60, - "shots": 8, - "count": 2 - }, + "range": 4, + "duration": 60, + "shots": 8, + "count": 2 + }, "effects": [ - { - "type": "replace_spell", - "name": "Guardian Angels", - "cost": 30, - "display_text": "Total Damage Average", - "base_spell": 4, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [40, 0, 0, 0, 0, 20] - }, - { - "name": "Single Bow", - "type": "total", - "hits": { - "Single Arrow": 8 + { + "type": "replace_spell", + "name": "Guardian Angels", + "cost": 30, + "display_text": "Total Damage Average", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 20 + ] + }, + { + "name": "Single Bow", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Bow": 2 + } } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Bow": 2 - } - } - ] - } - ] + ] + } + ], + "id": 8 }, { "display_name": "Windy Feet", "base_abil": "Escape", "desc": "When casting Escape, give speed to yourself and nearby allies.", "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Arrow Storm"], - "dependencies": [], + "archetype_req": 0, + "parents": [ + 7 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 10, - "col": 1 + "row": 10, + "col": 1 }, "properties": { - "aoe": 8, - "duration": 120 - }, + "aoe": 8, + "duration": 120 + }, "type": "stat_bonus", "bonuses": [ - { - "type": "stat", - "name": "spd", - "value": 20 + { + "type": "stat", + "name": "spd", + "value": 20 } - ] + ], + "id": 9 }, { "display_name": "Basaltic Trap", "desc": "When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)", "archetype": "Trapper", - "archetype_req": 2, - "parents": ["Bryophyte Roots"], - "dependencies": [], + "archetype_req": 2, + "parents": [ + 5 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 19, - "col": 8 + "row": 19, + "col": 8 }, "properties": { - "aoe": 7, - "traps": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [140, 30, 0, 0, 30, 0] - } - ] + "aoe": 7, + "traps": 2 }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [ + 140, + 30, + 0, + 0, + 30, + 0 + ] + } + ], + "id": 10 + }, { "display_name": "Windstorm", "desc": "Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.", - "archetype": "", - "archetype_req": 0, - "parents": ["Guardian Angels", "Cheaper Arrow Storm"], - "dependencies": [], - "blockers": ["Phantom Ray"], - "cost": 2, + "archetype": "", + "archetype_req": 0, + "parents": [ + 8, + 33 + ], + "dependencies": [], + "blockers": [ + 68 + ], + "cost": 2, "display": { "row": 21, "col": 1 - }, + }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [-11, 0, -7, 0, 0, 3] - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 1 + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + -11, + 0, + -7, + 0, + 0, + 3 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 1 + } } - } - ] - }, + ], + "id": 11 + }, { "display_name": "Grappling Hook", "base_abil": "Escape", "desc": "When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Focus", "More Shields", "Cheaper Arrow Storm"], - "dependencies": [], - "blockers": ["Escape Artist"], - "cost": 2, + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 61, + 40, + 33 + ], + "dependencies": [], + "blockers": [ + 20 + ], + "cost": 2, "display": { "row": 21, "col": 5 - }, + }, "properties": { "range": 20 }, - "effects": [ - ] - }, + "effects": [], + "id": 12 + }, { "display_name": "Implosion", "desc": "Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Grappling Hook", "More Shields"], - "dependencies": [], + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 12, + 40 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 6 - }, + }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [40, 0, 0, 0, 0, 0] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] } - ] - }, + ], + "id": 13 + }, { "display_name": "Twain's Arc", "desc": "When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)", - "archetype": "Sharpshooter", - "archetype_req": 4, - "parents": ["More Focus", "Traveler"], - "dependencies": ["Focus"], + "archetype": "Sharpshooter", + "archetype_req": 4, + "parents": [ + 62, + 64 + ], + "dependencies": [ + 61 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 25, "col": 4 - }, - "properties": { - "range": 64, - "focusReq": 2 - }, - "effects": [ - - { - "type": "replace_spell", - "name": "Twain's Arc", - "cost": 0, - "display_text": "Twain's Arc", - "base_spell": 5, - "spell_type": "damage", - "scaling": "melee", - "display": "Twain's Arc Damage", - "parts": [ - { - "name": "Twain's Arc Damage", - "type": "damage", - "multipliers": [200, 0, 0, 0, 0, 0] - } - ] - } - ] }, + "properties": { + "range": 64, + "focusReq": 2 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Twain's Arc", + "cost": 0, + "display_text": "Twain's Arc", + "base_spell": 5, + "spell_type": "damage", + "scaling": "melee", + "display": "Twain's Arc Damage", + "parts": [ + { + "name": "Twain's Arc Damage", + "type": "damage", + "multipliers": [ + 200, + 0, + 0, + 0, + 0, + 0 + ] + } + ] + } + ], + "id": 14 + }, { "display_name": "Fierce Stomp", "desc": "When using Escape, hold shift to quickly drop down and deal damage.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Refined Gunpowder", "Traveler"], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 42, + 64 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 26, - "col": 1 + "row": 26, + "col": 1 }, "properties": { - "aoe": 4 + "aoe": 4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fierce Stomp": 1 + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fierce Stomp": 1 + } } - } - ] + ], + "id": 15 }, { "display_name": "Scorched Earth", "desc": "Fire Creep become much stronger.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Twain's Arc"], - "dependencies": ["Fire Creep"], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 14 + ], + "dependencies": [ + 4 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 26 , - "col": 5 + "row": 26, + "col": 5 }, "properties": { - "duration": 2, - "aoe": 0.4 + "duration": 2, + "aoe": 0.4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [10, 0, 0, 0, 5, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [ + 10, + 0, + 0, + 0, + 5, + 0 + ] + } + ], + "id": 16 }, { "display_name": "Leap", "desc": "When you double tap jump, leap foward. (2s Cooldown)", - "archetype": "Boltslinger", - "archetype_req": 5, - "parents": ["Refined Gunpowder", "Homing Shots"], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 5, + "parents": [ + 42, + 55 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 0 + "row": 28, + "col": 0 }, "properties": { - "cooldown": 2 - }, - "effects": [ - - ] + "cooldown": 2 }, + "effects": [], + "id": 17 + }, { "display_name": "Shocking Bomb", "desc": "Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.", - "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": ["Twain's Arc", "Better Arrow Shield", "Homing Shots"], - "dependencies": ["Arrow Bomb"], + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": [ + 14, + 44, + 55 + ], + "dependencies": [ + 2 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 4 + "row": 28, + "col": 4 }, "properties": { - "gravity": 0 + "gravity": 0 }, "effects": [ - { - "type": "convert_spell_conv", - "target_part": "all", - "conversion": "thunder" - } - ] + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + } + ], + "id": 18 }, { "display_name": "Mana Trap", "desc": "Your Traps will give you 4 Mana per second when you stay close to them.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": ["More Traps", "Better Arrow Shield"], - "dependencies": ["Fire Creep"], + "archetype": "Trapper", + "archetype_req": 5, + "parents": [ + 43, + 44 + ], + "dependencies": [ + 4 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 8 + "row": 28, + "col": 8 }, "properties": { - "range": 12, - "manaRegen": 4 + "range": 12, + "manaRegen": 4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 10, - "multipliers": [0, 0, 0, 0, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 10, + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 19 }, { "display_name": "Escape Artist", "desc": "When casting Escape, release 100 arrows towards the ground.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Better Guardian Angels", "Leap"], - "dependencies": [], - "blockers": ["Grappling Hook"], - "cost": 2, + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 46, + 17 + ], + "dependencies": [], + "blockers": [ + 12 + ], + "cost": 2, "display": { - "row": 31, - "col": 0 - }, - "properties": { + "row": 31, + "col": 0 }, + "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Escape Artist", - "cost": 0, - "multipliers": [30, 0, 10, 0, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Escape Artist", + "cost": 0, + "multipliers": [ + 30, + 0, + 10, + 0, + 0, + 0 + ] + } + ], + "id": 20 }, { "display_name": "Initiator", "desc": "If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.", "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": ["Shocking Bomb", "Better Arrow Shield", "Cheaper Arrow Storm (2)"], - "dependencies": ["Focus"], + "archetype_req": 5, + "parents": [ + 18, + 44, + 47 + ], + "dependencies": [ + 61 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 31, - "col": 5 + "row": 31, + "col": 5 }, "properties": { - "focus": 1, - "timer": 5 - }, - "type": "stat_bonus", + "focus": 1, + "timer": 5 + }, + "type": "stat_bonus", "bonuses": [ - { - "type": "stat", - "name": "damPct", - "value": 50 + { + "type": "stat", + "name": "damPct", + "value": 50 } - ] + ], + "id": 21 }, { "display_name": "Call of the Hound", "desc": "Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.", "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Initiator", "Cheaper Arrow Storm (2)"], - "dependencies": ["Arrow Shield"], + "archetype_req": 0, + "parents": [ + 21, + 47 + ], + "dependencies": [ + 0 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 32, - "col": 7 + "row": 32, + "col": 7 }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Call of the Hound", - "cost": 0, - "multipliers": [40, 0, 0, 0, 0, 0] - } - ] + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Call of the Hound", + "cost": 0, + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 22 }, { "display_name": "Arrow Hurricane", "desc": "Arrow Storm will shoot +2 stream of arrows.", - "archetype": "Boltslinger", - "archetype_req": 8, - "parents": ["Precise Shot", "Escape Artist"], - "dependencies": [], - "blockers": ["Phantom Ray"], - "cost": 2, + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": [ + 48, + 20 + ], + "dependencies": [], + "blockers": [ + 68 + ], + "cost": 2, "display": { - "row": 33, - "col": 0 + "row": 33, + "col": 0 }, "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 2 + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 2 + } } - } - ] + ], + "id": 23 }, { "display_name": "Geyser Stomp", "desc": "Fierce Stomp will create geysers, dealing more damage and vertical knockback.", - "archetype": "", - "archetype_req": 0, - "parents": ["Shrapnel Bomb"], - "dependencies": ["Fierce Stomp"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 56 + ], + "dependencies": [ + 15 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 1 + "row": 37, + "col": 1 }, "properties": { - "aoe": 1 + "aoe": 1 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [0, 0, 0, 50, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 50, + 0, + 0 + ] + } + ], + "id": 24 }, { "display_name": "Crepuscular Ray", "desc": "If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.", - "archetype": "Sharpshooter", - "archetype_req": 10, - "parents": ["Cheaper Arrow Shield"], - "dependencies": ["Arrow Storm"], + "archetype": "Sharpshooter", + "archetype_req": 10, + "parents": [ + 49 + ], + "dependencies": [ + 7 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 4 + "row": 37, + "col": 4 }, "properties": { - "focusReq": 5, - "focusRegen": -1 - }, + "focusReq": 5, + "focusRegen": -1 + }, "effects": [ - { - "type": "replace_spell", - "name": "Crepuscular Ray", - "base_spell": 5, - "spell_type": "damage", - "scaling": "spell", - "display": "One Focus", - "cost": 0, - - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [10, 0, 0, 5, 0, 0] - }, { - "name": "One Focus", - "type": "total", - "hits": { - "Single Arrow": 20 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "One Focus": 7 - } + "type": "replace_spell", + "name": "Crepuscular Ray", + "base_spell": 5, + "spell_type": "damage", + "scaling": "spell", + "display": "One Focus", + "cost": 0, + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 10, + 0, + 0, + 5, + 0, + 0 + ] + }, + { + "name": "One Focus", + "type": "total", + "hits": { + "Single Arrow": 20 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "One Focus": 7 + } + } + ] } - ] - } - ] + ], + "id": 25 }, { "display_name": "Grape Bomb", "desc": "Arrow bomb will throw 3 additional smaller bombs when exploding.", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Escape (2)"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 51 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 7 + "row": 37, + "col": 7 }, "properties": { - "miniBombs": 3, - "aoe": 2 + "miniBombs": 3, + "aoe": 2 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Grape Bomb", - "cost": 0, - "multipliers": [30, 0, 0, 0, 10, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Grape Bomb", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 10, + 0 + ] + } + ], + "id": 26 }, { "display_name": "Tangled Traps", "desc": "Your Traps will be connected by a rope that deals damage to enemies every 0.2s.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Grape Bomb"], - "dependencies": ["Basaltic Trap"], + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 26 + ], + "dependencies": [ + 10 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 38, - "col": 6 + "row": 38, + "col": 6 }, "properties": { - "attackSpeed": 0.2 + "attackSpeed": 0.2 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Tangled Traps", - "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 20] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Tangled Traps", + "cost": 0, + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 20 + ] + } + ], + "id": 27 }, { "display_name": "Snow Storm", "desc": "Enemies near you will be slowed down.", "archetype": "", - "archetype_req": 0, - "parents": ["Geyser Stomp", "More Focus (2)"], - "dependencies": [], + "archetype_req": 0, + "parents": [ + 24, + 63 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 39, - "col": 2 + "row": 39, + "col": 2 }, "properties": { - "range": 2.5, - "slowness": 0.3 - } + "range": 2.5, + "slowness": 0.3 + }, + "id": 28 }, { "display_name": "All-Seeing Panoptes", "desc": "Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.", "archetype": "Boltslinger", - "archetype_req": 11, - "parents": ["Snow Storm"], - "dependencies": ["Guardian Angels"], + "archetype_req": 11, + "parents": [ + 28 + ], + "dependencies": [ + 8 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 40, - "col": 1 + "row": 40, + "col": 1 }, "properties": { - "range": 10, - "shots": 5 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [0, 0, 0, 0, 20, 0] + "range": 10, + "shots": 5 }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Bow", - "cost": 0, - "hits": { - "Single Arrow": 5 + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 5 + } } - } - ] + ], + "id": 29 }, { "display_name": "Minefield", "desc": "Allow you to place +6 Traps, but with reduced damage and range.", "archetype": "Trapper", - "archetype_req": 10, - "parents": ["Grape Bomb", "Cheaper Arrow Bomb (2)"], - "dependencies": ["Basaltic Trap"], + "archetype_req": 10, + "parents": [ + 26, + 53 + ], + "dependencies": [ + 10 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 40, "col": 7 - }, + }, "properties": { "aoe": -2, "traps": 6 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [-80, 0, 0, 0, 0, 0] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [ + -80, + 0, + 0, + 0, + 0, + 0 + ] } - ] - }, + ], + "id": 30 + }, { "display_name": "Bow Proficiency I", "desc": "Improve your Main Attack's damage and range when using a bow.", - "archetype": "", - "archetype_req": 0, - "parents": ["Arrow Bomb"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 2 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 4 - }, + }, "properties": { "mainAtk_range": 6 }, @@ -1005,94 +1317,103 @@ const atrees = } ] } - ] + ], + "id": 31 }, { "display_name": "Cheaper Arrow Bomb", "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["Bow Proficiency I"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 31 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 6 - }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -10 } - ] + ], + "id": 32 }, { "display_name": "Cheaper Arrow Storm", "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": ["Grappling Hook", "Windstorm", "Focus"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 12, + 11, + 61 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 21, "col": 3 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ] + ], + "id": 33 }, { "display_name": "Cheaper Escape", "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": ["Arrow Storm", "Arrow Shield"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 7, + 0 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 9, "col": 4 - }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ] + ], + "id": 34 }, { "display_name": "Earth Mastery", "desc": "Increases your base damage from all Earth attacks", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Arrow Shield"], - "dependencies": [], + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 0 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 8 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -1105,27 +1426,34 @@ const atrees = { "type": "stat", "name": "eDam", - "value": [2, 4] + "value": [ + 2, + 4 + ] } ] } - ] + ], + "id": 82 }, { "display_name": "Thunder Mastery", "desc": "Increases your base damage from all Thunder attacks", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Arrow Storm", "Fire Mastery"], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 7, + 86, + 34 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 2 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -1138,27 +1466,34 @@ const atrees = { "type": "stat", "name": "tDam", - "value": [1, 8] + "value": [ + 1, + 8 + ] } ] } - ] + ], + "id": 83 }, { "display_name": "Water Mastery", "desc": "Increases your base damage from all Water attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Cheaper Escape", "Thunder Mastery", "Fire Mastery"], - "dependencies": [], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 34, + 83, + 86 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 14, "col": 4 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -1171,27 +1506,32 @@ const atrees = { "type": "stat", "name": "wDam", - "value": [2, 4] + "value": [ + 2, + 4 + ] } ] } - ] + ], + "id": 84 }, { "display_name": "Air Mastery", "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Arrow Storm"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 7 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 0 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -1204,27 +1544,34 @@ const atrees = { "type": "stat", "name": "aDam", - "value": [3, 4] + "value": [ + 3, + 4 + ] } ] } - ] + ], + "id": 85 }, { "display_name": "Fire Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Arrow Shield"], - "dependencies": [], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 83, + 0, + 34 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 6 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -1237,156 +1584,210 @@ const atrees = { "type": "stat", "name": "fDam", - "value": [3, 5] + "value": [ + 3, + 5 + ] } ] } - ] + ], + "id": 86 }, { "display_name": "More Shields", "desc": "Give +2 charges to Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": ["Grappling Hook", "Basaltic Trap"], - "dependencies": ["Arrow Shield"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 12, + 10 + ], + "dependencies": [ + 0 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 21, "col": 7 - }, + }, "properties": { "shieldCharges": 2 - } + }, + "id": 40 }, { "display_name": "Stormy Feet", "desc": "Windy Feet will last longer and add more speed.", - "archetype": "", - "archetype_req": 0, - "parents": ["Windstorm"], - "dependencies": ["Windy Feet"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 11 + ], + "dependencies": [ + 9 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 23, - "col": 1 + "row": 23, + "col": 1 }, "properties": { - "duration": 60 + "duration": 60 }, "effects": [ - { - "type": "stat_bonus", - "bonuses": [ - { - "type": "stat", - "name": "spdPct", - "value": 20 + { + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spdPct", + "value": 20 + } + ] } - ] - } - ] + ], + "id": 41 }, { "display_name": "Refined Gunpowder", "desc": "Increase the damage of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["Windstorm"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 11 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 25, - "col": 0 + "row": 25, + "col": 0 }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [50, 0, 0, 0, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 50, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 42 }, { "display_name": "More Traps", "desc": "Increase the maximum amount of active Traps you can have by +2.", "archetype": "Trapper", - "archetype_req": 10, - "parents": ["Bouncing Bomb"], - "dependencies": ["Basaltic Trap"], + "archetype_req": 10, + "parents": [ + 54 + ], + "dependencies": [ + 10 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 8 - }, + }, "properties": { "traps": 2 - } + }, + "id": 43 }, { "display_name": "Better Arrow Shield", "desc": "Arrow Shield will gain additional area of effect, knockback and damage.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Mana Trap", "Shocking Bomb", "Twain's Arc"], - "dependencies": ["Arrow Shield"], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 19, + 18, + 14 + ], + "dependencies": [ + 0 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 28, - "col": 6 + "row": 28, + "col": 6 }, "properties": { - "aoe": 1 - }, + "aoe": 1 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Shield", - "multipliers": [40, 0, 0, 0, 0, 0] - } - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Shield", + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 44 }, { "display_name": "Better Leap", "desc": "Reduce leap's cooldown by 1s.", "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Leap", "Homing Shots"], - "dependencies": ["Leap"], + "archetype_req": 0, + "parents": [ + 17, + 55 + ], + "dependencies": [ + 17 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 1 - }, + }, "properties": { "cooldown": -1 - } + }, + "id": 45 }, { "display_name": "Better Guardian Angels", "desc": "Your Guardian Angels can shoot +4 arrows before disappearing.", "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Escape Artist", "Homing Shots"], - "dependencies": ["Guardian Angels"], + "archetype_req": 0, + "parents": [ + 20, + 55 + ], + "dependencies": [ + 8 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 31, - "col": 2 - }, - "properties": { + "row": 31, + "col": 2 }, + "properties": {}, "effects": [ { "type": "add_spell_prop", @@ -1397,44 +1798,52 @@ const atrees = "Single Arrow": 4 } } - ] + ], + "id": 46 }, { "display_name": "Cheaper Arrow Storm (2)", "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": ["Initiator", "Mana Trap"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 21, + 19 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 8 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ] + ], + "id": 47 }, { "display_name": "Precise Shot", "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Better Guardian Angels", "Cheaper Arrow Shield", "Arrow Hurricane"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 46, + 49, + 23 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 2 - }, + }, "properties": { "mainAtk_range": 6 }, @@ -1449,118 +1858,138 @@ const atrees = } ] } - ] + ], + "id": 48 }, { "display_name": "Cheaper Arrow Shield", "desc": "Reduce the Mana cost of Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": ["Precise Shot", "Initiator"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 48, + 21 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 4 - }, - "properties": { }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ] + ], + "id": 49 }, { "display_name": "Rocket Jump", "desc": "Arrow Bomb's self-damage will knockback you farther away.", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Arrow Storm (2)", "Initiator"], - "dependencies": ["Arrow Bomb"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 47, + 21 + ], + "dependencies": [ + 2 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 6 - }, - "properties": { - } + }, + "properties": {}, + "id": 50 }, { "display_name": "Cheaper Escape (2)", "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": ["Call of the Hound", "Decimator"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 22, + 70 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 34, "col": 7 - }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ] + ], + "id": 51 }, { "display_name": "Stronger Hook", "desc": "Increase your Grappling Hook's range, speed and strength.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": ["Cheaper Escape (2)"], - "dependencies": ["Grappling Hook"], + "archetype": "Trapper", + "archetype_req": 5, + "parents": [ + 51 + ], + "dependencies": [ + 12 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 8 - }, + }, "properties": { - "range": 8 - } + "range": 8 + }, + "id": 52 }, { "display_name": "Cheaper Arrow Bomb (2)", "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["More Focus (2)", "Minefield"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 63, + 30 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 40, "col": 5 - }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -5 } - ] + ], + "id": 53 }, { "display_name": "Bouncing Bomb", "desc": "Arrow Bomb will bounce once when hitting a block or enemy", "archetype": "", "archetype_req": 0, - "parents": ["More Shields"], + "parents": [ + 40 + ], "dependencies": [], "blockers": [], "cost": 2, @@ -1568,9 +1997,7 @@ const atrees = "row": 25, "col": 7 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", @@ -1581,14 +2008,18 @@ const atrees = "Arrow Bomb": 2 } } - ] + ], + "id": 54 }, { "display_name": "Homing Shots", "desc": "Your Main Attack arrows will follow nearby enemies and not be affected by gravity", "archetype": "", "archetype_req": 0, - "parents": ["Leap", "Shocking Bomb"], + "parents": [ + 17, + 18 + ], "dependencies": [], "blockers": [], "cost": 2, @@ -1596,45 +2027,53 @@ const atrees = "row": 28, "col": 2 }, - "properties": { - - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 55 }, { "display_name": "Shrapnel Bomb", "desc": "Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area", "archetype": "Boltslinger", "archetype_req": 8, - "parents": ["Arrow Hurricane", "Precise Shot"], + "parents": [ + 23, + 48 + ], "dependencies": [], "blockers": [], "cost": 2, "display": { "row": 34, - "col": 1 - }, - "properties": { - + "col": 1 }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Shrapnel Bomb", "cost": 0, - "multipliers": [40, 0, 0, 0, 20, 0] + "multipliers": [ + 40, + 0, + 0, + 0, + 20, + 0 + ] } - ] + ], + "id": 56 }, { "display_name": "Elusive", "desc": "If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)", "archetype": "Boltslinger", "archetype_req": 0, - "parents": ["Geyser Stomp"], + "parents": [ + 24 + ], "dependencies": [], "blockers": [], "cost": 2, @@ -1642,21 +2081,22 @@ const atrees = "row": 38, "col": 0 }, - "properties": { - - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 57 }, { "display_name": "Double Shots", "desc": "Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)", "archetype": "Boltslinger", "archetype_req": 0, - "parents": ["Escape"], + "parents": [ + 1 + ], "dependencies": [], - "blockers": ["Power Shots"], + "blockers": [ + 60 + ], "cost": 1, "display": { "row": 7, @@ -1673,15 +2113,21 @@ const atrees = "cost": 0, "multipliers": 0.7 } - ] + ], + "id": 58 }, { "display_name": "Triple Shots", "desc": "Triple Main Attack arrows, but they deal -20% damage per arrow", "archetype": "Boltslinger", "archetype_req": 0, - "parents": ["Arrow Rain", "Frenzy"], - "dependencies": ["Double Shots"], + "parents": [ + 69, + 67 + ], + "dependencies": [ + 58 + ], "blockers": [], "cost": 1, "display": { @@ -1699,34 +2145,38 @@ const atrees = "cost": 0, "multipliers": 0.7 } - ] + ], + "id": 59 }, { "display_name": "Power Shots", "desc": "Main Attack arrows have increased speed and knockback", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": ["Escape"], + "parents": [ + 1 + ], "dependencies": [], - "blockers": ["Double Shots"], + "blockers": [ + 58 + ], "cost": 1, "display": { "row": 7, "col": 6 }, - "properties": { - - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 60 }, { "display_name": "Focus", "desc": "When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once", "archetype": "Sharpshooter", "archetype_req": 2, - "parents": ["Phantom Ray"], + "parents": [ + 68 + ], "dependencies": [], "blockers": [], "cost": 2, @@ -1734,9 +2184,7 @@ const atrees = "row": 19, "col": 4 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -1747,17 +2195,23 @@ const atrees = "abil_name": "Focus", "name": "dmgPct" }, - "scaling": [35], + "scaling": [ + 35 + ], "max": 3 } - ] + ], + "id": 61 }, { "display_name": "More Focus", "desc": "Add +2 max Focus", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": ["Cheaper Arrow Storm", "Grappling Hook"], + "parents": [ + 33, + 12 + ], "dependencies": [], "blockers": [], "cost": 1, @@ -1765,9 +2219,7 @@ const atrees = "row": 22, "col": 4 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -1778,17 +2230,23 @@ const atrees = "abil_name": "Focus", "name": "dmgPct" }, - "scaling": [35], + "scaling": [ + 35 + ], "max": 5 } - ] + ], + "id": 62 }, { "display_name": "More Focus (2)", "desc": "Add +2 max Focus", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": ["Crepuscular Ray", "Snow Storm"], + "parents": [ + 25, + 28 + ], "dependencies": [], "blockers": [], "cost": 1, @@ -1796,9 +2254,7 @@ const atrees = "row": 39, "col": 4 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -1809,17 +2265,23 @@ const atrees = "abil_name": "Focus", "name": "dmgPct" }, - "scaling": [35], + "scaling": [ + 35 + ], "max": 7 } - ] + ], + "id": 63 }, { "display_name": "Traveler", "desc": "For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)", "archetype": "", "archetype_req": 0, - "parents": ["Refined Gunpowder", "Twain's Arc"], + "parents": [ + 42, + 14 + ], "dependencies": [], "blockers": [], "cost": 1, @@ -1827,9 +2289,7 @@ const atrees = "row": 25, "col": 2 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -1844,18 +2304,25 @@ const atrees = "type": "stat", "name": "sdRaw" }, - "scaling": [1], + "scaling": [ + 1 + ], "max": 100 } - ] + ], + "id": 64 }, { "display_name": "Patient Hunter", "desc": "Your Traps will deal +20% more damage for every second they are active (Max +80%)", "archetype": "Trapper", "archetype_req": 0, - "parents": ["More Shields"], - "dependencies": ["Basaltic Trap"], + "parents": [ + 40 + ], + "dependencies": [ + 10 + ], "blockers": [], "cost": 2, "display": { @@ -1865,17 +2332,20 @@ const atrees = "properties": { "max": 80 }, - "effects": [ - - ] + "effects": [], + "id": 65 }, { "display_name": "Stronger Patient Hunter", "desc": "Add +80% Max Damage to Patient Hunter", "archetype": "Trapper", "archetype_req": 0, - "parents": ["Grape Bomb"], - "dependencies": ["Patient Hunter"], + "parents": [ + 26 + ], + "dependencies": [ + 65 + ], "blockers": [], "cost": 1, "display": { @@ -1885,16 +2355,18 @@ const atrees = "properties": { "max": 80 }, - "effects": [ - - ] + "effects": [], + "id": 66 }, { "display_name": "Frenzy", "desc": "Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second", "archetype": "Boltslinger", "archetype_req": 0, - "parents": ["Triple Shots", "Nimble String"], + "parents": [ + 59, + 6 + ], "dependencies": [], "blockers": [], "cost": 2, @@ -1902,9 +2374,7 @@ const atrees = "row": 17, "col": 2 }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -1914,93 +2384,127 @@ const atrees = "type": "stat", "name": "spd" }, - "scaling": [6], + "scaling": [ + 6 + ], "max": 200 } - ] + ], + "id": 67 }, { "display_name": "Phantom Ray", "desc": "Condense Arrow Storm into a single ray that damages enemies 10 times per second", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": ["Water Mastery", "Fire Creep"], - "dependencies": ["Arrow Storm"], - "blockers": ["Windstorm", "Nimble String", "Arrow Hurricane"], + "parents": [ + 84, + 4 + ], + "dependencies": [ + 7 + ], + "blockers": [ + 11, + 6, + 23 + ], "cost": 2, "display": { "row": 16, "col": 4 }, - "properties": { - }, + "properties": {}, "effects": [ - { + { "type": "replace_spell", "name": "Phantom Ray", "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", "scaling": "spell", - "display": "Total Damage", + "display": "Total Damage", "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [25, 0, 5, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Arrow": 16 + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 25, + 0, + 5, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Arrow": 16 + } } - } ] } - ] + ], + "id": 68 }, { "display_name": "Arrow Rain", "desc": "When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies", "archetype": "Trapper", "archetype_req": 0, - "parents": ["Nimble String", "Air Mastery"], - "dependencies": ["Arrow Shield"], + "parents": [ + 6, + 85 + ], + "dependencies": [ + 0 + ], "blockers": [], "cost": 2, "display": { "row": 15, "col": 0 }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "Arrow Rain", "cost": 0, - "multipliers": [120, 0, 0, 0, 0, 80] + "multipliers": [ + 120, + 0, + 0, + 0, + 0, + 80 + ] } - ] + ], + "id": 69 }, { "display_name": "Decimator", "desc": "Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": ["Cheaper Arrow Shield"], - "dependencies": ["Phantom Ray"], + "parents": [ + 49 + ], + "dependencies": [ + 68 + ], "blockers": [], "cost": 1, "display": { "row": 34, "col": 5 }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -2013,19 +2517,20 @@ const atrees = "scaling": 10, "max": 50 } - ] + ], + "id": 70 } ], "Warrior": [ { "display_name": "Bash", "desc": "Violently bash the ground, dealing high damage in a large area", - "archetype": "", - "archetype_req": 0, - "parents": [], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 0, "col": 4, @@ -2049,7 +2554,14 @@ const atrees = { "name": "Single Hit", "type": "damage", - "multipliers": [130, 20, 0, 0, 0, 0] + "multipliers": [ + 130, + 20, + 0, + 0, + 0, + 0 + ] }, { "name": "Total Damage", @@ -2060,17 +2572,20 @@ const atrees = } ] } - ] + ], + "id": 71 }, { "display_name": "Spear Proficiency 1", "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": ["Bash"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 71 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 4, @@ -2090,43 +2605,46 @@ const atrees = } ] } - ] + ], + "id": 72 }, - { "display_name": "Cheaper Bash", "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 1"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 72 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 2, "icon": "node_0" }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -10 } - ] + ], + "id": 73 }, { "display_name": "Double Bash", "desc": "Bash will hit a second time at a farther range", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 1"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 72 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 4, "col": 4, @@ -2151,27 +2669,35 @@ const atrees = "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [-50, 0, 0, 0, 0, 0] + "multipliers": [ + -50, + 0, + 0, + 0, + 0, + 0 + ] } - ] + ], + "id": 74 }, - { "display_name": "Charge", "desc": "Charge forward at high speed (hold shift to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": ["Double Bash"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 74 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 6, "col": 4, "icon": "node_4" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "replace_spell", @@ -2186,7 +2712,14 @@ const atrees = { "name": "None", "type": "damage", - "multipliers": [0, 0, 0, 0, 0, 0] + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] }, { "name": "Total Damage", @@ -2197,18 +2730,20 @@ const atrees = } ] } - ] + ], + "id": 75 }, - { "display_name": "Heavy Impact", "desc": "After using Charge, violently crash down into the ground and deal damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Uppercut"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 79 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 9, "col": 1, @@ -2223,27 +2758,37 @@ const atrees = "base_spell": 2, "target_part": "Heavy Impact", "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] } - ] + ], + "id": 76 }, - { "display_name": "Vehement", "desc": "For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Charge"], - "dependencies": [], - "blockers": ["Tougher Skin"], - "cost": 1, + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 75 + ], + "dependencies": [], + "blockers": [ + 78 + ], + "cost": 1, "display": { "row": 6, "col": 2, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -2262,28 +2807,34 @@ const atrees = "type": "stat", "name": "spd" }, - "scaling": [1, 1], + "scaling": [ + 1, + 1 + ], "max": 20 } - ] + ], + "id": 77 }, - { "display_name": "Tougher Skin", "desc": "Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Charge"], - "dependencies": [], - "blockers": ["Vehement"], - "cost": 1, + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 75 + ], + "dependencies": [], + "blockers": [ + 77 + ], + "cost": 1, "display": { "row": 6, "col": 6, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2312,21 +2863,26 @@ const atrees = "type": "stat", "name": "hpBonus" }, - "scaling": [10, 10], + "scaling": [ + 10, + 10 + ], "max": 100 } - ] + ], + "id": 78 }, - { "display_name": "Uppercut", "desc": "Rocket enemies in the air and deal massive damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Vehement"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 77 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 2, @@ -2350,7 +2906,14 @@ const atrees = { "name": "Uppercut", "type": "damage", - "multipliers": [150, 50, 50, 0, 0, 0] + "multipliers": [ + 150, + 50, + 50, + 0, + 0, + 0 + ] }, { "name": "Total Damage", @@ -2361,43 +2924,47 @@ const atrees = } ] } - ] + ], + "id": 79 }, - { "display_name": "Cheaper Charge", "desc": "Reduce the Mana cost of Charge", - "archetype": "", - "archetype_req": 0, - "parents": ["Uppercut", "War Scream"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 79, + 81 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 4, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ] + ], + "id": 80 }, - { "display_name": "War Scream", "desc": "Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies", - "archetype": "", - "archetype_req": 0, - "parents": ["Tougher Skin"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 78 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 6, @@ -2422,29 +2989,37 @@ const atrees = { "name": "War Scream", "type": "damage", - "multipliers": [50, 0, 0, 0, 50, 0] + "multipliers": [ + 50, + 0, + 0, + 0, + 50, + 0 + ] } ] } - ] + ], + "id": 81 }, - { "display_name": "Earth Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uppercut"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 79 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 0, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2457,29 +3032,35 @@ const atrees = { "type": "stat", "name": "eDam", - "value": [2, 4] + "value": [ + 2, + 4 + ] } ] } - ] + ], + "id": 82 }, - { "display_name": "Thunder Mastery", "desc": "Increases base damage from all Thunder attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uppercut", "Air Mastery"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 79, + 85, + 80 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 2, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2492,29 +3073,35 @@ const atrees = { "type": "stat", "name": "tDam", - "value": [1, 8] + "value": [ + 1, + 8 + ] } ] } - ] + ], + "id": 83 }, - { "display_name": "Water Mastery", "desc": "Increases base damage from all Water attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Cheaper Charge", "Thunder Mastery", "Air Mastery"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 80, + 83, + 85 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 11, "col": 4, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2527,29 +3114,35 @@ const atrees = { "type": "stat", "name": "wDam", - "value": [2, 4] + "value": [ + 2, + 4 + ] } ] } - ] + ], + "id": 84 }, - { "display_name": "Air Mastery", "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["War Scream", "Thunder Mastery"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 81, + 83, + 80 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 6, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2562,29 +3155,33 @@ const atrees = { "type": "stat", "name": "aDam", - "value": [3, 4] + "value": [ + 3, + 4 + ] } ] } - ] + ], + "id": 85 }, - { "display_name": "Fire Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["War Scream"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 81 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 8, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -2597,22 +3194,28 @@ const atrees = { "type": "stat", "name": "fDam", - "value": [3, 5] + "value": [ + 3, + 5 + ] } ] } - ] + ], + "id": 86 }, - { "display_name": "Quadruple Bash", "desc": "Bash will hit 4 times at an even larger range", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Earth Mastery", "Fireworks"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 82, + 88 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 0, @@ -2629,41 +3232,57 @@ const atrees = "cost": 0, "hits": { "Single Hit": 2 - } + } }, { "type": "add_spell_prop", "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [-20, 0, 0, 0, 0, 0] + "multipliers": [ + -20, + 0, + 0, + 0, + 0, + 0 + ] } - ] + ], + "id": 87 }, - { "display_name": "Fireworks", "desc": "Mobs hit by Uppercut will explode mid-air and receive additional damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Quadruple Bash"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 83, + 87 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 2, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Fireworks", "cost": 0, - "multipliers": [80, 0, 20, 0, 0, 0] + "multipliers": [ + 80, + 0, + 20, + 0, + 0, + 0 + ] }, { "type": "add_spell_prop", @@ -2674,18 +3293,22 @@ const atrees = "Fireworks": 1 } } - ] + ], + "id": 88 }, - { "display_name": "Half-Moon Swipe", "desc": "Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Water Mastery"], - "dependencies": ["Uppercut"], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 84 + ], + "dependencies": [ + 79 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 13, "col": 4, @@ -2700,25 +3323,35 @@ const atrees = "base_spell": 3, "target_part": "Uppercut", "cost": -10, - "multipliers": [-70, 0, 0, 0, 0, 0] + "multipliers": [ + -70, + 0, + 0, + 0, + 0, + 0 + ] }, { "type": "convert_spell_conv", "target_part": "all", "conversion": "water" } - ] + ], + "id": 89 }, - { "display_name": "Flyby Jab", "desc": "Damage enemies in your way when using Charge", - "archetype": "", - "archetype_req": 0, - "parents": ["Air Mastery", "Flaming Uppercut"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 85, + 91 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 6, @@ -2733,20 +3366,32 @@ const atrees = "base_spell": 2, "target_part": "Flyby Jab", "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 40] + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 40 + ] } - ] + ], + "id": 90 }, - { "display_name": "Flaming Uppercut", "desc": "Uppercut will light mobs on fire, dealing damage every 0.6 seconds", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Fire Mastery", "Flyby Jab"], - "dependencies": ["Uppercut"], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 86, + 90 + ], + "dependencies": [ + 79 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 8, @@ -2762,7 +3407,14 @@ const atrees = "base_spell": 3, "target_part": "Flaming Uppercut", "cost": 0, - "multipliers": [0, 0, 0, 0, 50, 0] + "multipliers": [ + 0, + 0, + 0, + 0, + 50, + 0 + ] }, { "type": "add_spell_prop", @@ -2782,66 +3434,76 @@ const atrees = "Flaming Uppercut": 5 } } - ] + ], + "id": 91 }, - { "display_name": "Iron Lungs", "desc": "War Scream deals more damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Flyby Jab", "Flaming Uppercut"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 90, + 91 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 7, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "War Scream", "cost": 0, - "multipliers": [30, 0, 0, 0, 0, 30] + "multipliers": [ + 30, + 0, + 0, + 0, + 0, + 30 + ] } - ] + ], + "id": 92 }, - { "display_name": "Generalist", "desc": "After casting 3 different spells in a row, your next spell will cost 5 mana", - "archetype": "Battle Monk", - "archetype_req": 3, - "parents": ["Counter"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 3, + "parents": [ + 94 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 2, "icon": "node_3" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 93 }, - { "display_name": "Counter", "desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Half-Moon Swipe"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 89 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 4, @@ -2856,20 +3518,31 @@ const atrees = "base_spell": 5, "target_part": "Counter", "cost": 0, - "multipliers": [60, 0, 20, 0, 0, 20] + "multipliers": [ + 60, + 0, + 20, + 0, + 0, + 20 + ] } - ] + ], + "id": 94 }, - { "display_name": "Mantle of the Bovemists", "desc": "When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": ["Iron Lungs"], - "dependencies": ["War Scream"], + "archetype": "Paladin", + "archetype_req": 3, + "parents": [ + 92 + ], + "dependencies": [ + 81 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 7, @@ -2878,20 +3551,23 @@ const atrees = "properties": { "mantle_charge": 3 }, - "effects": [ - - ] + "effects": [], + "id": 95 }, - { "display_name": "Bak'al's Grasp", "desc": "After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)", - "archetype": "Fallen", - "archetype_req": 2, - "parents": ["Quadruple Bash", "Fireworks"], - "dependencies": ["War Scream"], + "archetype": "Fallen", + "archetype_req": 2, + "parents": [ + 87, + 88 + ], + "dependencies": [ + 81 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 16, "col": 1, @@ -2907,24 +3583,29 @@ const atrees = "slider_name": "Corrupted", "output": { "type": "stat", - "name": "raw" + "name": "raw" }, - "scaling": [4], + "scaling": [ + 4 + ], "slider_step": 2, "max": 120 } - ] + ], + "id": 96 }, - { "display_name": "Spear Proficiency 2", "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": ["Bak'al's Grasp", "Cheaper Uppercut"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 96, + 98 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 0, @@ -2944,96 +3625,103 @@ const atrees = } ] } - ] + ], + "id": 97 }, - { "display_name": "Cheaper Uppercut", "desc": "Reduce the Mana Cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 2", "Aerodynamics", "Counter"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 97, + 99, + 94 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 3, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -5 } - ] + ], + "id": 98 }, - { "display_name": "Aerodynamics", "desc": "During Charge, you can steer and change direction", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Cheaper Uppercut", "Provoke"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 98, + 100 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 17, "col": 5, "icon": "node_1" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 99 }, - { "display_name": "Provoke", "desc": "Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Aerodynamics", "Mantle of the Bovemists"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 99, + 95 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 7, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ] + ], + "id": 100 }, - { "display_name": "Precise Strikes", "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Uppercut", "Spear Proficiency 2"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 98, + 97 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 18, "col": 2, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -3045,53 +3733,66 @@ const atrees = } ] } - ] + ], + "id": 101 }, - { "display_name": "Air Shout", "desc": "War Scream will fire a projectile that can go through walls and deal damage multiple times", - "archetype": "", - "archetype_req": 0, - "parents": ["Aerodynamics", "Provoke"], - "dependencies": ["War Scream"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 99, + 100 + ], + "dependencies": [ + 81 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 18, "col": 6, "icon": "node_1" }, - "properties": { - - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "Air Shout", "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 5] + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 5 + ] } - ] + ], + "id": 102 }, - { "display_name": "Enraged Blow", "desc": "While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Spear Proficiency 2"], - "dependencies": ["Bak'al's Grasp"], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 97 + ], + "dependencies": [ + 96 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 0, "icon": "node_2" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -3104,50 +3805,66 @@ const atrees = ], "output": { "type": "stat", - "name": "dmgPct" + "name": "dmgPct" }, - "scaling": [2], + "scaling": [ + 2 + ], "max": 200 } - ] + ], + "id": 103 }, - { "display_name": "Flying Kick", "desc": "When using Charge, mobs hit will halt your momentum and get knocked back", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Cheaper Uppercut", "Stronger Mantle"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 98, + 105 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 3, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "target_part": "Flying Kick", "cost": 0, - "multipliers": [120, 0, 0, 10, 0, 20] + "multipliers": [ + 120, + 0, + 0, + 10, + 0, + 20 + ] } - ] + ], + "id": 104 }, - { "display_name": "Stronger Mantle", "desc": "Add +2 additional charges to Mantle of the Bovemists", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Manachism", "Flying Kick"], - "dependencies": ["Mantle of the Bovemists"], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 106, + 104 + ], + "dependencies": [ + 95 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 20, "col": 6, @@ -3156,20 +3873,21 @@ const atrees = "properties": { "mantle_charge": 2 }, - "effects": [ - - ] + "effects": [], + "id": 105 }, - { "display_name": "Manachism", "desc": "If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": ["Stronger Mantle", "Provoke"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 3, + "parents": [ + 105, + 100 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 8, @@ -3178,47 +3896,59 @@ const atrees = "properties": { "cooldown": 1 }, - "effects": [ - - ] + "effects": [], + "id": 106 }, - { "display_name": "Boiling Blood", "desc": "Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds", - "archetype": "", - "archetype_req": 0, - "parents": ["Enraged Blow", "Ragnarokkr"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 103, + 108 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 0, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "target_part": "Boiling Blood", "cost": 0, - "multipliers": [25, 0, 0, 0, 5, 0] + "multipliers": [ + 25, + 0, + 0, + 0, + 5, + 0 + ] } - ] + ], + "id": 107 }, - { "display_name": "Ragnarokkr", "desc": "War Scream become deafening, increasing its range and giving damage bonus to players", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Boiling Blood", "Flying Kick"], - "dependencies": ["War Scream"], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 107, + 104 + ], + "dependencies": [ + 81 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 2, @@ -3234,18 +3964,24 @@ const atrees = "base_spell": 4, "cost": 10 } - ] + ], + "id": 108 }, - { "display_name": "Ambidextrous", "desc": "Increase your chance to attack with Counter by +30%", - "archetype": "", - "archetype_req": 0, - "parents": ["Flying Kick", "Stronger Mantle", "Burning Heart"], - "dependencies": ["Counter"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 104, + 105, + 110 + ], + "dependencies": [ + 94 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 4, @@ -3254,27 +3990,27 @@ const atrees = "properties": { "chance": 30 }, - "effects": [ - - ] + "effects": [], + "id": 109 }, - { "display_name": "Burning Heart", "desc": "For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Ambidextrous", "Stronger Bash"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 109, + 111 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 6, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -3289,106 +4025,134 @@ const atrees = "type": "stat", "name": "fDamPct" }, - "scaling": [2], + "scaling": [ + 2 + ], "max": 100, "slider_step": 100 } - ] + ], + "id": 110 }, - { "display_name": "Stronger Bash", "desc": "Increase the damage of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Burning Heart", "Manachism"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 110, + 106 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 8, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [30, 0, 0, 0, 0, 0] + "multipliers": [ + 30, + 0, + 0, + 0, + 0, + 0 + ] } - ] + ], + "id": 111 }, - { "display_name": "Intoxicating Blood", "desc": "After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted", - "archetype": "Fallen", - "archetype_req": 5, - "parents": ["Ragnarokkr", "Boiling Blood"], - "dependencies": ["Bak'al's Grasp"], + "archetype": "Fallen", + "archetype_req": 5, + "parents": [ + 108, + 107 + ], + "dependencies": [ + 96 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 1, "icon": "node_1" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 112 }, - { "display_name": "Comet", "desc": "After being hit by Fireworks, enemies will crash into the ground and receive more damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Ragnarokkr"], - "dependencies": ["Fireworks"], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 108 + ], + "dependencies": [ + 88 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 24, "col": 2, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Comet", "cost": 0, - "multipliers": [80, 20, 0, 0, 0, 0] + "multipliers": [ + 80, + 20, + 0, + 0, + 0, + 0 + ] }, { - "type":"add_spell_prop", + "type": "add_spell_prop", "base_spell": 3, "target_part": "Total Damage", - "cost": 0, + "cost": 0, "hits": { "Comet": 1 } } - ] + ], + "id": 113 }, - { "display_name": "Collide", "desc": "Mobs thrown into walls from Flying Kick will explode and receive additonal damage", - "archetype": "Battle Monk", - "archetype_req": 4, - "parents": ["Ambidextrous", "Burning Heart"], - "dependencies": ["Flying Kick"], + "archetype": "Battle Monk", + "archetype_req": 4, + "parents": [ + 109, + 110 + ], + "dependencies": [ + 104 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 5, @@ -3403,41 +4167,53 @@ const atrees = "base_spell": 2, "target_part": "Collide", "cost": 0, - "multipliers": [100, 0, 0, 0, 50, 0] + "multipliers": [ + 100, + 0, + 0, + 0, + 50, + 0 + ] } - ] + ], + "id": 114 }, - { "display_name": "Rejuvenating Skin", "desc": "Regain back 30% of the damage you take as healing over 30s", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Burning Heart", "Stronger Bash"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 110, + 111 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 7, "icon": "node_3" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 115 }, - { "display_name": "Uncontainable Corruption", "desc": "Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1", - "archetype": "", - "archetype_req": 0, - "parents": ["Boiling Blood", "Radiant Devotee"], - "dependencies": ["Bak'al's Grasp"], + "archetype": "", + "archetype_req": 0, + "parents": [ + 107, + 117 + ], + "dependencies": [ + 96 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 0, @@ -3453,31 +4229,35 @@ const atrees = "slider_name": "Corrupted", "output": { "type": "stat", - "name": "raw" + "name": "raw" }, - "scaling": [1], + "scaling": [ + 1 + ], "slider_step": 2, "max": 50 } - ] + ], + "id": 116 }, - { "display_name": "Radiant Devotee", "desc": "For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Whirlwind Strike", "Uncontainable Corruption"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 118, + 116 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 2, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -3491,29 +4271,36 @@ const atrees = "type": "stat", "name": "mr" }, - "scaling": [1], + "scaling": [ + 1 + ], "max": 10, "slider_step": 4 } - ] + ], + "id": 117 }, - { "display_name": "Whirlwind Strike", "desc": "Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": ["Ambidextrous", "Radiant Devotee"], - "dependencies": ["Uppercut"], + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": [ + 109, + 117 + ], + "dependencies": [ + 79 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 26, "col": 4, "icon": "node_1" }, "properties": { - "range": 2 + "range": 2 }, "effects": [ { @@ -3521,27 +4308,35 @@ const atrees = "base_spell": 3, "target_part": "Uppercut", "cost": 0, - "multipliers": [0, 0, 0, 0, 0, 50] + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 50 + ] } - ] + ], + "id": 118 }, - { "display_name": "Mythril Skin", "desc": "Gain +5% Base Resistance and become immune to knockback", - "archetype": "Paladin", - "archetype_req": 6, - "parents": ["Rejuvenating Skin"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 6, + "parents": [ + 115 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 26, "col": 7, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "raw_stat", @@ -3553,18 +4348,23 @@ const atrees = } ] } - ] + ], + "id": 119 }, - { "display_name": "Armour Breaker", "desc": "While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uncontainable Corruption", "Radiant Devotee"], - "dependencies": ["Bak'al's Grasp"], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 116, + 117 + ], + "dependencies": [ + 96 + ], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 1, @@ -3573,47 +4373,56 @@ const atrees = "properties": { "duration": 5 }, - "effects": [ - - ] + "effects": [], + "id": 120 }, - { "display_name": "Shield Strike", "desc": "When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Mythril Skin", "Sparkling Hope"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 119, + 122 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 6, "icon": "node_1" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 5, "target_part": "Shield Strike", "cost": 0, - "multipliers": [60, 0, 20, 0, 0, 0] + "multipliers": [ + 60, + 0, + 20, + 0, + 0, + 0 + ] } - ] + ], + "id": 121 }, - { "display_name": "Sparkling Hope", "desc": "Everytime you heal 5% of your max health, deal damage to all nearby enemies", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Mythril Skin"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 119 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 8, @@ -3628,27 +4437,36 @@ const atrees = "base_spell": 5, "target_part": "Sparkling Hope", "cost": 0, - "multipliers": [10, 0, 5, 0, 0, 0] + "multipliers": [ + 10, + 0, + 5, + 0, + 0, + 0 + ] } - ] + ], + "id": 122 }, - { "display_name": "Massive Bash", "desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)", - "archetype": "Fallen", - "archetype_req": 8, - "parents": ["Tempest", "Uncontainable Corruption"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 8, + "parents": [ + 124, + 116 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 28, "col": 0, "icon": "node_2" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -3656,24 +4474,29 @@ const atrees = "slider_name": "Corrupted", "output": { "type": "stat", - "name": "bashAoE" + "name": "bashAoE" }, - "scaling": [1], + "scaling": [ + 1 + ], "max": 10, "slider_step": 3 } - ] + ], + "id": 123 }, - { "display_name": "Tempest", "desc": "War Scream will ripple the ground and deal damage 3 times in a large area", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Massive Bash", "Spirit of the Rabbit"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 123, + 125 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 28, "col": 2, @@ -3688,7 +4511,14 @@ const atrees = "base_spell": 4, "target_part": "Tempest", "cost": "0", - "multipliers": [30, 10, 0, 0, 0, 10] + "multipliers": [ + 30, + 10, + 0, + 0, + 0, + 10 + ] }, { "type": "add_spell_prop", @@ -3708,25 +4538,27 @@ const atrees = "Tempest": 3 } } - ] + ], + "id": 124 }, - { "display_name": "Spirit of the Rabbit", "desc": "Reduce the Mana cost of Charge and increase your Walk Speed by +20%", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": ["Tempest", "Whirlwind Strike"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": [ + 124, + 118 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 28, "col": 4, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", @@ -3743,66 +4575,78 @@ const atrees = } ] } - ] + ], + "id": 125 }, - { "display_name": "Massacre", "desc": "While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar", - "archetype": "Fallen", - "archetype_req": 5, - "parents": ["Tempest", "Massive Bash"], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 5, + "parents": [ + 124, + 123 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 29, "col": 1, "icon": "node_1" }, - "properties": { - }, - "effects": [ - - ] + "properties": {}, + "effects": [], + "id": 126 }, - { "display_name": "Axe Kick", "desc": "Increase the damage of Uppercut, but also increase its mana cost", - "archetype": "", - "archetype_req": 0, - "parents": ["Tempest", "Spirit of the Rabbit"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 124, + 125 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 3, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Uppercut", "cost": 10, - "multipliers": [100, 0, 0, 0, 0, 0] + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] } - ] + ], + "id": 127 }, - { "display_name": "Radiance", "desc": "Bash will buff your allies' positive IDs. (15s Cooldown)", - "archetype": "Paladin", - "archetype_req": 2, - "parents": ["Spirit of the Rabbit", "Cheaper Bash 2"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 2, + "parents": [ + 125, + 129 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 29, "col": 5, @@ -3811,77 +4655,80 @@ const atrees = "properties": { "cooldown": 15 }, - "effects": [ - - ] + "effects": [], + "id": 128 }, - { "display_name": "Cheaper Bash 2", "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Radiance", "Shield Strike", "Sparkling Hope"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 128, + 121, + 122 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 7, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ] + ], + "id": 129 }, - { "display_name": "Cheaper War Scream", "desc": "Reduce the Mana cost of War Scream", - "archetype": "", - "archetype_req": 0, - "parents": ["Massive Bash"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 123 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 0, "icon": "node_0" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ] + ], + "id": 130 }, - { "display_name": "Discombobulate", "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", - "archetype": "Battle Monk", - "archetype_req": 12, - "parents": ["Cyclone"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 12, + "parents": [ + 133 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 31, "col": 2, "icon": "node_3" }, - "properties": { - }, + "properties": {}, "effects": [ { "type": "stat_scaling", @@ -3889,23 +4736,27 @@ const atrees = "slider_name": "Hits dealt", "output": { "type": "stat", - "name": "rainrawButDifferent" + "name": "rainrawButDifferent" }, - "scaling": [2], + "scaling": [ + 2 + ], "max": 50 } - ] + ], + "id": 131 }, - { "display_name": "Thunderclap", "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", - "archetype": "Battle Monk", - "archetype_req": 8, - "parents": ["Cyclone"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 8, + "parents": [ + 133 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 32, "col": 5, @@ -3920,25 +4771,29 @@ const atrees = }, { "type": "raw_stat", - "bonuses": [{ - "type": "prop", - "abil_name": "Bash", - "name": "aoe", - "value": 3 - }] + "bonuses": [ + { + "type": "prop", + "abil_name": "Bash", + "name": "aoe", + "value": 3 + } + ] } - ] + ], + "id": 132 }, - { "display_name": "Cyclone", "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Spirit of the Rabbit"], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 125 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 4, @@ -3954,7 +4809,14 @@ const atrees = "base_spell": 4, "target_part": "Cyclone", "cost": 0, - "multipliers": [10, 0, 0, 0, 5, 10] + "multipliers": [ + 10, + 0, + 0, + 0, + 5, + 10 + ] }, { "type": "add_spell_prop", @@ -3964,92 +4826,105 @@ const atrees = "hits": { "Cyclone": 40 } - } - ] + ], + "id": 133 }, - { "display_name": "Second Chance", "desc": "When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)", - "archetype": "Paladin", - "archetype_req": 12, - "parents": ["Cheaper Bash 2"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 12, + "parents": [ + 129 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 32, "col": 7, "icon": "node_3" }, "properties": {}, - "effects": [] + "effects": [], + "id": 134 }, - { "display_name": "Blood Pact", "desc": "If you do not have enough mana to cast a spell, spend health instead (1% health per mana)", - "archetype": "", - "archetype_req": 10, - "parents": ["Cheaper War Scream"], - "dependencies": [], + "archetype": "", + "archetype_req": 10, + "parents": [ + 130 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 34, "col": 1, "icon": "node_3" }, "properties": {}, - "effects": [] + "effects": [], + "id": 135 }, - { "display_name": "Haemorrhage", "desc": "Reduce Blood Pact's health cost. (0.5% health per mana)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Blood Pact"], - "dependencies": ["Blood Pact"], + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 135 + ], + "dependencies": [ + 135 + ], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 2, "icon": "node_1" }, "properties": {}, - "effects": [] + "effects": [], + "id": 136 }, - { "display_name": "Brink of Madness", "desc": "If your health is 25% full or less, gain +40% Resistance", - "archetype": "", - "archetype_req": 0, - "parents": ["Blood Pact", "Cheaper Uppercut 2"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 135, + 138 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 35, "col": 4, "icon": "node_2" }, "properties": {}, - "effects": [] + "effects": [], + "id": 137 }, - { "display_name": "Cheaper Uppercut 2", "desc": "Reduce the Mana cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": ["Second Chance", "Brink of Madness"], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [ + 134, + 137 + ], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 6, @@ -4062,18 +4937,20 @@ const atrees = "base_spell": 3, "cost": -5 } - ] + ], + "id": 138 }, - { "display_name": "Martyr", "desc": "When you receive a fatal blow, all nearby allies become invincible", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Second Chance"], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 134 + ], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 35, "col": 8, @@ -4083,78 +4960,8 @@ const atrees = "duration": 3, "aoe": 12 }, - "effects": [] + "effects": [], + "id": 139 } - ], -} - -const atree_example = [ - { - "title": "skill", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 5, - "col": 3, - }, - { - "image": "../media/atree/connect_angle.png", - "connector": true, - "rotate": 270, - "row": 4, - "col": 3, - }, - { - "title": "skill2", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 0, - "col": 2 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 0, - "row": 1, - "col": 2 - }, - { - "title": "skill3", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 2, - "col": 2 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 90, - "row": 2, - "col": 3 - }, - { - "title": "skill4", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 2, - "col": 4 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 0, - "row": 3, - "col": 2 - }, - { - "title": "skill5", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 4, - "col": 2 - }, -]; + ] +} \ No newline at end of file diff --git a/js/atree_constants_min.js b/js/atree_constants_min.js index 73d3e29..f79809c 100644 --- a/js/atree_constants_min.js +++ b/js/atree_constants_min.js @@ -1 +1 @@ -const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:["Power Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}]},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:["Heart Shatter"],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}]},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}]},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:["Phantom Ray","Fire Mastery","Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}]},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:["Fire Creep","Earth Mastery"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}]},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:["Thunder Mastery","Arrow Rain"],dependencies:["Arrow Storm"],blockers:["Phantom Ray"],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}]},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:["Double Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}]},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:["Triple Shots","Frenzy"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}]},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}]},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:["Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}]},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:["Guardian Angels","Cheaper Arrow Storm"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}]},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:["Focus","More Shields","Cheaper Arrow Storm"],dependencies:[],blockers:["Escape Artist"],cost:2,display:{row:21,col:5},properties:{range:20},effects:[]},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:["Grappling Hook","More Shields"],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:["More Focus","Traveler"],dependencies:["Focus"],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}]},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:["Refined Gunpowder","Traveler"],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}]},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:["Twain's Arc"],dependencies:["Fire Creep"],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}]},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:["Refined Gunpowder","Homing Shots"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[]},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:["Twain's Arc","Better Arrow Shield","Homing Shots"],dependencies:["Arrow Bomb"],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:["More Traps","Better Arrow Shield"],dependencies:["Fire Creep"],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}]},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:["Better Guardian Angels","Leap"],dependencies:[],blockers:["Grappling Hook"],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}]},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:["Shocking Bomb","Better Arrow Shield","Cheaper Arrow Storm (2)"],dependencies:["Focus"],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}]},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:["Initiator","Cheaper Arrow Storm (2)"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:["Precise Shot","Escape Artist"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}]},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:["Shrapnel Bomb"],dependencies:["Fierce Stomp"],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}]},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:["Cheaper Arrow Shield"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}]},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:["Cheaper Escape (2)"],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}]},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}]},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:["Geyser Stomp","More Focus (2)"],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3}},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:["Snow Storm"],dependencies:["Guardian Angels"],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}]},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:["Grape Bomb","Cheaper Arrow Bomb (2)"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}]},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:["Arrow Bomb"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}]},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Grappling Hook","Windstorm","Focus"],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Arrow Storm","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:["Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Escape","Thunder Mastery","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Thunder Mastery","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:["Grappling Hook","Basaltic Trap"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2}},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:["Windy Feet"],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}]},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}]},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:["Bouncing Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2}},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:["Mana Trap","Shocking Bomb","Twain's Arc"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}]},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:["Leap","Homing Shots"],dependencies:["Leap"],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1}},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:["Escape Artist","Homing Shots"],dependencies:["Guardian Angels"],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}]},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Initiator","Mana Trap"],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Better Guardian Angels","Cheaper Arrow Shield","Arrow Hurricane"],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}]},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:["Precise Shot","Initiator"],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:["Cheaper Arrow Storm (2)","Initiator"],dependencies:["Arrow Bomb"],blockers:[],cost:1,display:{row:33,col:6},properties:{}},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Call of the Hound","Decimator"],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:["Cheaper Escape (2)"],dependencies:["Grappling Hook"],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8}},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["More Focus (2)","Minefield"],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:["More Shields"],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}]},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:["Leap","Shocking Bomb"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[]},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:["Arrow Hurricane","Precise Shot"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}]},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:["Geyser Stomp"],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[]},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Power Shots"],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Rain","Frenzy"],dependencies:["Double Shots"],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Double Shots"],cost:1,display:{row:7,col:6},properties:{},effects:[]},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:["Phantom Ray"],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:3}]},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Storm","Grappling Hook"],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:5}]},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Crepuscular Ray","Snow Storm"],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:7}]},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:["Refined Gunpowder","Twain's Arc"],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}]},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:["More Shields"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[]},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Patient Hunter"],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[]},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:["Triple Shots","Nimble String"],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}]},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:["Water Mastery","Fire Creep"],dependencies:["Arrow Storm"],blockers:["Windstorm","Nimble String","Arrow Hurricane"],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}]},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:["Nimble String","Air Mastery"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}]},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Shield"],dependencies:["Phantom Ray"],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}]}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}]},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bash"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}]},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}]},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:["Double Bash"],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}]},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Tougher Skin"],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}]},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Vehement"],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}]},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:["Vehement"],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}]},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:["Uppercut","War Scream"],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:["Tougher Skin"],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}]},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Charge","Thunder Mastery","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["War Scream","Thunder Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:["War Scream"],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:["Earth Mastery","Fireworks"],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}]},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:["Thunder Mastery","Quadruple Bash"],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}]},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:["Water Mastery"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}]},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:["Air Mastery","Flaming Uppercut"],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}]},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:["Fire Mastery","Flyby Jab"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}]},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:["Flyby Jab","Flaming Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}]},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:["Counter"],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[]},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:["Half-Moon Swipe"],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}]},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:["Iron Lungs"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[]},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:["Quadruple Bash","Fireworks"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}]},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bak'al's Grasp","Cheaper Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:["Spear Proficiency 2","Aerodynamics","Counter"],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Uppercut","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[]},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:["Aerodynamics","Mantle of the Bovemists"],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Cheaper Uppercut","Spear Proficiency 2"],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}]},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:["Aerodynamics","Provoke"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}]},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:["Spear Proficiency 2"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"dmgPct"},scaling:[2],max:200}]},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:["Cheaper Uppercut","Stronger Mantle"],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}]},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:["Manachism","Flying Kick"],dependencies:["Mantle of the Bovemists"],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[]},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:["Stronger Mantle","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[]},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:["Enraged Blow","Ragnarokkr"],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}]},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:["Boiling Blood","Flying Kick"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}]},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:["Flying Kick","Stronger Mantle","Burning Heart"],dependencies:["Counter"],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[]},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:["Ambidextrous","Stronger Bash"],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}]},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:["Burning Heart","Manachism"],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}]},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:["Ragnarokkr","Boiling Blood"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:["Ragnarokkr"],dependencies:["Fireworks"],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}]},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:["Ambidextrous","Burning Heart"],dependencies:["Flying Kick"],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}]},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:["Burning Heart","Stronger Bash"],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:["Boiling Blood","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}]},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:["Whirlwind Strike","Uncontainable Corruption"],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}]},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:["Ambidextrous","Radiant Devotee"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}]},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:["Rejuvenating Skin"],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}]},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:["Uncontainable Corruption","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[]},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin","Sparkling Hope"],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}]},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin"],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}]},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:["Tempest","Uncontainable Corruption"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}]},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:["Massive Bash","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}]},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:["Tempest","Whirlwind Strike"],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}]},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:["Tempest","Massive Bash"],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:["Tempest","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}]},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:["Spirit of the Rabbit","Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[]},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Radiance","Shield Strike","Sparkling Hope"],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:["Massive Bash"],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}]},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}]},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:["Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}]},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:["Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:["Cheaper War Scream"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[]},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:["Blood Pact"],dependencies:["Blood Pact"],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[]},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:["Blood Pact","Cheaper Uppercut 2"],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[]},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:["Second Chance","Brink of Madness"],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:["Second Chance"],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[]}]},atree_example=[{title:"skill",desc:"desc",image:"../media/atree/node.png",connector:!1,row:5,col:3},{image:"../media/atree/connect_angle.png",connector:!0,rotate:270,row:4,col:3},{title:"skill2",desc:"desc",image:"../media/atree/node.png",connector:!1,row:0,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:1,col:2},{title:"skill3",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:90,row:2,col:3},{title:"skill4",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:4},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:3,col:2},{title:"skill5",desc:"desc",image:"../media/atree/node.png",connector:!1,row:4,col:2},] \ No newline at end of file +const atrees={"Archer":[{"display_name":"Arrow Shield","desc":"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)","archetype":"","archetype_req":0,"parents":[60,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":6},"properties":{"duration":60},"effects":[{"type":"replace_spell","name":"Arrow Shield","cost":30,"display_text":"Max Damage","base_spell":4,"spell_type":"damage","scaling":"spell","display":"","parts":[{"name":"Shield Damage","type":"damage","multipliers":[90,0,0,0,0,10]},{"name":"Total Damage","type":"total","hits":{"Shield Damage":2}}]}],"id":0},{"display_name":"Escape","desc":"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":7,"col":4},"properties":{"aoe":0,"range":0},"effects":[{"type":"replace_spell","name":"Escape","cost":25,"display_text":"Max Damage","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":1},{"display_name":"Arrow Bomb","desc":"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4},"properties":{"aoe":4.5,"range":26},"effects":[{"type":"replace_spell","name":"Arrow Bomb","cost":50,"display_text":"Average Damage","base_spell":3,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Arrow Bomb","type":"damage","multipliers":[160,0,0,0,20,0]},{"name":"Total Damage","type":"total","hits":{"Arrow Bomb":1}}]}],"id":2},{"display_name":"Heart Shatter","desc":"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[100,0,0,0,0,0]},{}],"id":3},{"display_name":"Fire Creep","desc":"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.","archetype":"","archetype_req":0,"parents":[68,86,5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":16,"col":6},"properties":{"aoe":0.8,"duration":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[30,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fire Creep":15}}],"id":4},{"display_name":"Bryophyte Roots","desc":"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.","archetype":"Trapper","archetype_req":1,"parents":[4,82],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":16,"col":8},"properties":{"aoe":2,"duration":5,"slowness":0.4},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Bryophyte Roots","cost":0,"multipliers":[40,20,0,0,0,0]}],"id":5},{"display_name":"Nimble String","desc":"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.","archetype":"","archetype_req":0,"parents":[83,69],"dependencies":[7],"blockers":[68],"cost":2,"display":{"row":15,"col":2},"properties":{"shootspeed":2},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-15,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":8}}],"id":6},{"display_name":"Arrow Storm","desc":"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.","archetype":"","archetype_req":0,"parents":[58,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":2},"properties":{"aoe":0,"range":16},"effects":[{"type":"replace_spell","name":"Arrow Storm","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,10,0,0,0]},{"name":"Single Stream","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Stream":2}}]}],"id":7},{"display_name":"Guardian Angels","desc":"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)","archetype":"Boltslinger","archetype_req":3,"parents":[59,67],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":19,"col":1},"properties":{"range":4,"duration":60,"shots":8,"count":2},"effects":[{"type":"replace_spell","name":"Guardian Angels","cost":30,"display_text":"Total Damage Average","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[40,0,0,0,0,20]},{"name":"Single Bow","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Bow":2}}]}],"id":8},{"display_name":"Windy Feet","base_abil":"Escape","desc":"When casting Escape, give speed to yourself and nearby allies.","archetype":"Boltslinger","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":1},"properties":{"aoe":8,"duration":120},"type":"stat_bonus","bonuses":[{"type":"stat","name":"spd","value":20}],"id":9},{"display_name":"Basaltic Trap","desc":"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)","archetype":"Trapper","archetype_req":2,"parents":[5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":8},"properties":{"aoe":7,"traps":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[140,30,0,0,30,0]}],"id":10},{"display_name":"Windstorm","desc":"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.","archetype":"","archetype_req":0,"parents":[8,33],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":21,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-11,0,-7,0,0,3]},{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":1}}],"id":11},{"display_name":"Grappling Hook","base_abil":"Escape","desc":"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)","archetype":"Trapper","archetype_req":0,"parents":[61,40,33],"dependencies":[],"blockers":[20],"cost":2,"display":{"row":21,"col":5},"properties":{"range":20},"effects":[],"id":12},{"display_name":"Implosion","desc":"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.","archetype":"Trapper","archetype_req":0,"parents":[12,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":13},{"display_name":"Twain's Arc","desc":"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)","archetype":"Sharpshooter","archetype_req":4,"parents":[62,64],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":25,"col":4},"properties":{"range":64,"focusReq":2},"effects":[{"type":"replace_spell","name":"Twain's Arc","cost":0,"display_text":"Twain's Arc","base_spell":5,"spell_type":"damage","scaling":"melee","display":"Twain's Arc Damage","parts":[{"name":"Twain's Arc Damage","type":"damage","multipliers":[200,0,0,0,0,0]}]}],"id":14},{"display_name":"Fierce Stomp","desc":"When using Escape, hold shift to quickly drop down and deal damage.","archetype":"Boltslinger","archetype_req":0,"parents":[42,64],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":1},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[100,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":2,"target_part":"Total Damage","cost":0,"hits":{"Fierce Stomp":1}}],"id":15},{"display_name":"Scorched Earth","desc":"Fire Creep become much stronger.","archetype":"Sharpshooter","archetype_req":0,"parents":[14],"dependencies":[4],"blockers":[],"cost":1,"display":{"row":26,"col":5},"properties":{"duration":2,"aoe":0.4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[10,0,0,0,5,0]}],"id":16},{"display_name":"Leap","desc":"When you double tap jump, leap foward. (2s Cooldown)","archetype":"Boltslinger","archetype_req":5,"parents":[42,55],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0},"properties":{"cooldown":2},"effects":[],"id":17},{"display_name":"Shocking Bomb","desc":"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.","archetype":"Sharpshooter","archetype_req":5,"parents":[14,44,55],"dependencies":[2],"blockers":[],"cost":2,"display":{"row":28,"col":4},"properties":{"gravity":0},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"}],"id":18},{"display_name":"Mana Trap","desc":"Your Traps will give you 4 Mana per second when you stay close to them.","archetype":"Trapper","archetype_req":5,"parents":[43,44],"dependencies":[4],"blockers":[],"cost":2,"display":{"row":28,"col":8},"properties":{"range":12,"manaRegen":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":10,"multipliers":[0,0,0,0,0,0]}],"id":19},{"display_name":"Escape Artist","desc":"When casting Escape, release 100 arrows towards the ground.","archetype":"Boltslinger","archetype_req":0,"parents":[46,17],"dependencies":[],"blockers":[12],"cost":2,"display":{"row":31,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Escape Artist","cost":0,"multipliers":[30,0,10,0,0,0]}],"id":20},{"display_name":"Initiator","desc":"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.","archetype":"Sharpshooter","archetype_req":5,"parents":[18,44,47],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":31,"col":5},"properties":{"focus":1,"timer":5},"type":"stat_bonus","bonuses":[{"type":"stat","name":"damPct","value":50}],"id":21},{"display_name":"Call of the Hound","desc":"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.","archetype":"Trapper","archetype_req":0,"parents":[21,47],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":32,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Call of the Hound","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":22},{"display_name":"Arrow Hurricane","desc":"Arrow Storm will shoot +2 stream of arrows.","archetype":"Boltslinger","archetype_req":8,"parents":[48,20],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":33,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":2}}],"id":23},{"display_name":"Geyser Stomp","desc":"Fierce Stomp will create geysers, dealing more damage and vertical knockback.","archetype":"","archetype_req":0,"parents":[56],"dependencies":[15],"blockers":[],"cost":2,"display":{"row":37,"col":1},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[0,0,0,50,0,0]}],"id":24},{"display_name":"Crepuscular Ray","desc":"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.","archetype":"Sharpshooter","archetype_req":10,"parents":[49],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":37,"col":4},"properties":{"focusReq":5,"focusRegen":-1},"effects":[{"type":"replace_spell","name":"Crepuscular Ray","base_spell":5,"spell_type":"damage","scaling":"spell","display":"One Focus","cost":0,"parts":[{"name":"Single Arrow","type":"damage","multipliers":[10,0,0,5,0,0]},{"name":"One Focus","type":"total","hits":{"Single Arrow":20}},{"name":"Total Damage","type":"total","hits":{"One Focus":7}}]}],"id":25},{"display_name":"Grape Bomb","desc":"Arrow bomb will throw 3 additional smaller bombs when exploding.","archetype":"","archetype_req":0,"parents":[51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":37,"col":7},"properties":{"miniBombs":3,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Grape Bomb","cost":0,"multipliers":[30,0,0,0,10,0]}],"id":26},{"display_name":"Tangled Traps","desc":"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":38,"col":6},"properties":{"attackSpeed":0.2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Tangled Traps","cost":0,"multipliers":[20,0,0,0,0,20]}],"id":27},{"display_name":"Snow Storm","desc":"Enemies near you will be slowed down.","archetype":"","archetype_req":0,"parents":[24,63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":39,"col":2},"properties":{"range":2.5,"slowness":0.3},"id":28},{"display_name":"All-Seeing Panoptes","desc":"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.","archetype":"Boltslinger","archetype_req":11,"parents":[28],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":40,"col":1},"properties":{"range":10,"shots":5},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Arrow","cost":0,"multipliers":[0,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":5}}],"id":29},{"display_name":"Minefield","desc":"Allow you to place +6 Traps, but with reduced damage and range.","archetype":"Trapper","archetype_req":10,"parents":[26,53],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":40,"col":7},"properties":{"aoe":-2,"traps":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[-80,0,0,0,0,0]}],"id":30},{"display_name":"Bow Proficiency I","desc":"Improve your Main Attack's damage and range when using a bow.","archetype":"","archetype_req":0,"parents":[2],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":31},{"display_name":"Cheaper Arrow Bomb","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-10}],"id":32},{"display_name":"Cheaper Arrow Storm","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[12,11,61],"dependencies":[],"blockers":[],"cost":1,"display":{"row":21,"col":3},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":33},{"display_name":"Cheaper Escape","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[7,0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":34},{"display_name":"Earth Mastery","desc":"Increases your base damage from all Earth attacks","archetype":"Trapper","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":8},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":82},{"display_name":"Thunder Mastery","desc":"Increases your base damage from all Thunder attacks","archetype":"Boltslinger","archetype_req":0,"parents":[7,86,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":2},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":83},{"display_name":"Water Mastery","desc":"Increases your base damage from all Water attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[34,83,86],"dependencies":[],"blockers":[],"cost":1,"display":{"row":14,"col":4},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":84},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":0},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":85},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[83,0,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":6},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":86},{"display_name":"More Shields","desc":"Give +2 charges to Arrow Shield.","archetype":"","archetype_req":0,"parents":[12,10],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":21,"col":7},"properties":{"shieldCharges":2},"id":40},{"display_name":"Stormy Feet","desc":"Windy Feet will last longer and add more speed.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[9],"blockers":[],"cost":1,"display":{"row":23,"col":1},"properties":{"duration":60},"effects":[{"type":"stat_bonus","bonuses":[{"type":"stat","name":"spdPct","value":20}]}],"id":41},{"display_name":"Refined Gunpowder","desc":"Increase the damage of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[50,0,0,0,0,0]}],"id":42},{"display_name":"More Traps","desc":"Increase the maximum amount of active Traps you can have by +2.","archetype":"Trapper","archetype_req":10,"parents":[54],"dependencies":[10],"blockers":[],"cost":1,"display":{"row":26,"col":8},"properties":{"traps":2},"id":43},{"display_name":"Better Arrow Shield","desc":"Arrow Shield will gain additional area of effect, knockback and damage.","archetype":"Sharpshooter","archetype_req":0,"parents":[19,18,14],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":28,"col":6},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Shield","multipliers":[40,0,0,0,0,0]}],"id":44},{"display_name":"Better Leap","desc":"Reduce leap's cooldown by 1s.","archetype":"Boltslinger","archetype_req":0,"parents":[17,55],"dependencies":[17],"blockers":[],"cost":1,"display":{"row":29,"col":1},"properties":{"cooldown":-1},"id":45},{"display_name":"Better Guardian Angels","desc":"Your Guardian Angels can shoot +4 arrows before disappearing.","archetype":"Boltslinger","archetype_req":0,"parents":[20,55],"dependencies":[8],"blockers":[],"cost":1,"display":{"row":31,"col":2},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":4}}],"id":46},{"display_name":"Cheaper Arrow Storm (2)","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[21,19],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":8},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":47},{"display_name":"Precise Shot","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[46,49,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":2},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdCritPct","value":30}]}],"id":48},{"display_name":"Cheaper Arrow Shield","desc":"Reduce the Mana cost of Arrow Shield.","archetype":"","archetype_req":0,"parents":[48,21],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":49},{"display_name":"Rocket Jump","desc":"Arrow Bomb's self-damage will knockback you farther away.","archetype":"","archetype_req":0,"parents":[47,21],"dependencies":[2],"blockers":[],"cost":1,"display":{"row":33,"col":6},"properties":{},"id":50},{"display_name":"Cheaper Escape (2)","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[22,70],"dependencies":[],"blockers":[],"cost":1,"display":{"row":34,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":51},{"display_name":"Stronger Hook","desc":"Increase your Grappling Hook's range, speed and strength.","archetype":"Trapper","archetype_req":5,"parents":[51],"dependencies":[12],"blockers":[],"cost":1,"display":{"row":35,"col":8},"properties":{"range":8},"id":52},{"display_name":"Cheaper Arrow Bomb (2)","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[63,30],"dependencies":[],"blockers":[],"cost":1,"display":{"row":40,"col":5},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":53},{"display_name":"Bouncing Bomb","desc":"Arrow Bomb will bounce once when hitting a block or enemy","archetype":"","archetype_req":0,"parents":[40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":25,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Arrow Bomb":2}}],"id":54},{"display_name":"Homing Shots","desc":"Your Main Attack arrows will follow nearby enemies and not be affected by gravity","archetype":"","archetype_req":0,"parents":[17,18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2},"properties":{},"effects":[],"id":55},{"display_name":"Shrapnel Bomb","desc":"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area","archetype":"Boltslinger","archetype_req":8,"parents":[23,48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Shrapnel Bomb","cost":0,"multipliers":[40,0,0,0,20,0]}],"id":56},{"display_name":"Elusive","desc":"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)","archetype":"Boltslinger","archetype_req":0,"parents":[24],"dependencies":[],"blockers":[],"cost":2,"display":{"row":38,"col":0},"properties":{},"effects":[],"id":57},{"display_name":"Double Shots","desc":"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)","archetype":"Boltslinger","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[60],"cost":1,"display":{"row":7,"col":2},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":58},{"display_name":"Triple Shots","desc":"Triple Main Attack arrows, but they deal -20% damage per arrow","archetype":"Boltslinger","archetype_req":0,"parents":[69,67],"dependencies":[58],"blockers":[],"cost":1,"display":{"row":17,"col":0},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":59},{"display_name":"Power Shots","desc":"Main Attack arrows have increased speed and knockback","archetype":"Sharpshooter","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[58],"cost":1,"display":{"row":7,"col":6},"properties":{},"effects":[],"id":60},{"display_name":"Focus","desc":"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once","archetype":"Sharpshooter","archetype_req":2,"parents":[68],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":3}],"id":61},{"display_name":"More Focus","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[33,12],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":5}],"id":62},{"display_name":"More Focus (2)","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[25,28],"dependencies":[],"blockers":[],"cost":1,"display":{"row":39,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":7}],"id":63},{"display_name":"Traveler","desc":"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)","archetype":"","archetype_req":0,"parents":[42,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"spd"}],"output":{"type":"stat","name":"sdRaw"},"scaling":[1],"max":100}],"id":64},{"display_name":"Patient Hunter","desc":"Your Traps will deal +20% more damage for every second they are active (Max +80%)","archetype":"Trapper","archetype_req":0,"parents":[40],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":8},"properties":{"max":80},"effects":[],"id":65},{"display_name":"Stronger Patient Hunter","desc":"Add +80% Max Damage to Patient Hunter","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[65],"blockers":[],"cost":1,"display":{"row":38,"col":8},"properties":{"max":80},"effects":[],"id":66},{"display_name":"Frenzy","desc":"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second","archetype":"Boltslinger","archetype_req":0,"parents":[59,6],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"spd"},"scaling":[6],"max":200}],"id":67},{"display_name":"Phantom Ray","desc":"Condense Arrow Storm into a single ray that damages enemies 10 times per second","archetype":"Sharpshooter","archetype_req":0,"parents":[84,4],"dependencies":[7],"blockers":[11,6,23],"cost":2,"display":{"row":16,"col":4},"properties":{},"effects":[{"type":"replace_spell","name":"Phantom Ray","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[25,0,5,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Arrow":16}}]}],"id":68},{"display_name":"Arrow Rain","desc":"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies","archetype":"Trapper","archetype_req":0,"parents":[6,85],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":15,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Arrow Rain","cost":0,"multipliers":[120,0,0,0,0,80]}],"id":69},{"display_name":"Decimator","desc":"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)","archetype":"Sharpshooter","archetype_req":0,"parents":[49],"dependencies":[68],"blockers":[],"cost":1,"display":{"row":34,"col":5},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Phantom Ray hits","output":{"type":"stat","name":"PhRayDmg"},"scaling":10,"max":50}],"id":70}],"Warrior":[{"display_name":"Bash","desc":"Violently bash the ground, dealing high damage in a large area","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4,"icon":"node_4"},"properties":{"aoe":4,"range":3},"effects":[{"type":"replace_spell","name":"Bash","cost":45,"display_text":"Total Damage Average","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Hit","type":"damage","multipliers":[130,20,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Hit":1}}]}],"id":71},{"display_name":"Spear Proficiency 1","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[71],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":72},{"display_name":"Cheaper Bash","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[72],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-10}],"id":73},{"display_name":"Double Bash","desc":"Bash will hit a second time at a farther range","archetype":"","archetype_req":0,"parents":[72],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4,"icon":"node_1"},"properties":{"range":3},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"name":"Single Hit","value":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-50,0,0,0,0,0]}],"id":74},{"display_name":"Charge","desc":"Charge forward at high speed (hold shift to cancel)","archetype":"","archetype_req":0,"parents":[74],"dependencies":[],"blockers":[],"cost":1,"display":{"row":6,"col":4,"icon":"node_4"},"properties":{},"effects":[{"type":"replace_spell","name":"Charge","cost":25,"display_text":"Total Damage Average","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":75},{"display_name":"Heavy Impact","desc":"After using Charge, violently crash down into the ground and deal damage","archetype":"","archetype_req":0,"parents":[79],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":1,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Heavy Impact","cost":0,"multipliers":[100,0,0,0,0,0]}],"id":76},{"display_name":"Vehement","desc":"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)","archetype":"Fallen","archetype_req":0,"parents":[75],"dependencies":[],"blockers":[78],"cost":1,"display":{"row":6,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"mdPct"},{"type":"stat","name":"mdRaw"}],"output":{"type":"stat","name":"spd"},"scaling":[1,1],"max":20}],"id":77},{"display_name":"Tougher Skin","desc":"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)","archetype":"Paladin","archetype_req":0,"parents":[75],"dependencies":[],"blockers":[77],"cost":1,"display":{"row":6,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":"5"}]},{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hprRaw"},{"type":"stat","name":"hprPct"}],"output":{"type":"stat","name":"hpBonus"},"scaling":[10,10],"max":100}],"id":78},{"display_name":"Uppercut","desc":"Rocket enemies in the air and deal massive damage","archetype":"","archetype_req":0,"parents":[77],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":2,"icon":"node_4"},"properties":{"aoe":3,"range":5},"effects":[{"type":"replace_spell","name":"Uppercut","cost":45,"display_text":"Total Damage Average","base_spell":3,"spell_type":"damage","scaling":"spell","display":"total","parts":[{"name":"Uppercut","type":"damage","multipliers":[150,50,50,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Uppercut":1}}]}],"id":79},{"display_name":"Cheaper Charge","desc":"Reduce the Mana cost of Charge","archetype":"","archetype_req":0,"parents":[79,81],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":80},{"display_name":"War Scream","desc":"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies","archetype":"","archetype_req":0,"parents":[78],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":6,"icon":"node_4"},"properties":{"duration":30,"aoe":12,"defense_bonus":10},"effects":[{"type":"replace_spell","name":"War Scream","cost":35,"display_text":"War Scream","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage Average","parts":[{"name":"War Scream","type":"damage","multipliers":[50,0,0,0,50,0]}]}],"id":81},{"display_name":"Earth Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Fallen","archetype_req":0,"parents":[79],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":82},{"display_name":"Thunder Mastery","desc":"Increases base damage from all Thunder attacks","archetype":"Fallen","archetype_req":0,"parents":[79,85,80],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":83},{"display_name":"Water Mastery","desc":"Increases base damage from all Water attacks","archetype":"Battle Monk","archetype_req":0,"parents":[80,83,85],"dependencies":[],"blockers":[],"cost":1,"display":{"row":11,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":84},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[81,83,80],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":85},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Paladin","archetype_req":0,"parents":[81],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":86},{"display_name":"Quadruple Bash","desc":"Bash will hit 4 times at an even larger range","archetype":"Fallen","archetype_req":0,"parents":[82,88],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":0,"icon":"node_1"},"properties":{"range":6},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Hit":2}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-20,0,0,0,0,0]}],"id":87},{"display_name":"Fireworks","desc":"Mobs hit by Uppercut will explode mid-air and receive additional damage","archetype":"Fallen","archetype_req":0,"parents":[83,87],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fireworks","cost":0,"multipliers":[80,0,20,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fireworks":1}}],"id":88},{"display_name":"Half-Moon Swipe","desc":"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water","archetype":"Battle Monk","archetype_req":1,"parents":[84],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":13,"col":4,"icon":"node_1"},"properties":{"range":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":-10,"multipliers":[-70,0,0,0,0,0]},{"type":"convert_spell_conv","target_part":"all","conversion":"water"}],"id":89},{"display_name":"Flyby Jab","desc":"Damage enemies in your way when using Charge","archetype":"","archetype_req":0,"parents":[85,91],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":6,"icon":"node_1"},"properties":{"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flyby Jab","cost":0,"multipliers":[20,0,0,0,0,40]}],"id":90},{"display_name":"Flaming Uppercut","desc":"Uppercut will light mobs on fire, dealing damage every 0.6 seconds","archetype":"Paladin","archetype_req":0,"parents":[86,90],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":12,"col":8,"icon":"node_1"},"properties":{"duration":3,"tick":0.6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut","cost":0,"multipliers":[0,0,0,0,50,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut Total Damage","cost":0,"hits":{"Flaming Uppercut":5}},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Flaming Uppercut":5}}],"id":91},{"display_name":"Iron Lungs","desc":"War Scream deals more damage","archetype":"","archetype_req":0,"parents":[90,91],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"War Scream","cost":0,"multipliers":[30,0,0,0,0,30]}],"id":92},{"display_name":"Generalist","desc":"After casting 3 different spells in a row, your next spell will cost 5 mana","archetype":"Battle Monk","archetype_req":3,"parents":[94],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":2,"icon":"node_3"},"properties":{},"effects":[],"id":93},{"display_name":"Counter","desc":"When dodging a nearby enemy attack, get 30% chance to instantly attack back","archetype":"Battle Monk","archetype_req":0,"parents":[89],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":4,"icon":"node_1"},"properties":{"chance":30},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Counter","cost":0,"multipliers":[60,0,20,0,0,20]}],"id":94},{"display_name":"Mantle of the Bovemists","desc":"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)","archetype":"Paladin","archetype_req":3,"parents":[92],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":15,"col":7,"icon":"node_3"},"properties":{"mantle_charge":3},"effects":[],"id":95},{"display_name":"Bak'al's Grasp","desc":"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)","archetype":"Fallen","archetype_req":2,"parents":[87,88],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":16,"col":1,"icon":"node_3"},"properties":{"cooldown":15},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[4],"slider_step":2,"max":120}],"id":96},{"display_name":"Spear Proficiency 2","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[96,98],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":0,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":97},{"display_name":"Cheaper Uppercut","desc":"Reduce the Mana Cost of Uppercut","archetype":"","archetype_req":0,"parents":[97,99,94],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":98},{"display_name":"Aerodynamics","desc":"During Charge, you can steer and change direction","archetype":"Battle Monk","archetype_req":0,"parents":[98,100],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":5,"icon":"node_1"},"properties":{},"effects":[],"id":99},{"display_name":"Provoke","desc":"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream","archetype":"Paladin","archetype_req":0,"parents":[99,95],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":100},{"display_name":"Precise Strikes","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[98,97],"dependencies":[],"blockers":[],"cost":1,"display":{"row":18,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"critDmg","value":30}]}],"id":101},{"display_name":"Air Shout","desc":"War Scream will fire a projectile that can go through walls and deal damage multiple times","archetype":"","archetype_req":0,"parents":[99,100],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":18,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Air Shout","cost":0,"multipliers":[20,0,0,0,0,5]}],"id":102},{"display_name":"Enraged Blow","desc":"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)","archetype":"Fallen","archetype_req":0,"parents":[97],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":20,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"dmgPct"},"scaling":[2],"max":200}],"id":103},{"display_name":"Flying Kick","desc":"When using Charge, mobs hit will halt your momentum and get knocked back","archetype":"Battle Monk","archetype_req":1,"parents":[98,105],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":3,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flying Kick","cost":0,"multipliers":[120,0,0,10,0,20]}],"id":104},{"display_name":"Stronger Mantle","desc":"Add +2 additional charges to Mantle of the Bovemists","archetype":"Paladin","archetype_req":0,"parents":[106,104],"dependencies":[95],"blockers":[],"cost":1,"display":{"row":20,"col":6,"icon":"node_0"},"properties":{"mantle_charge":2},"effects":[],"id":105},{"display_name":"Manachism","desc":"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)","archetype":"Paladin","archetype_req":3,"parents":[105,100],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":8,"icon":"node_2"},"properties":{"cooldown":1},"effects":[],"id":106},{"display_name":"Boiling Blood","desc":"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds","archetype":"","archetype_req":0,"parents":[103,108],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":0,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Boiling Blood","cost":0,"multipliers":[25,0,0,0,5,0]}],"id":107},{"display_name":"Ragnarokkr","desc":"War Scream become deafening, increasing its range and giving damage bonus to players","archetype":"Fallen","archetype_req":0,"parents":[107,104],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":22,"col":2,"icon":"node_2"},"properties":{"damage_bonus":30,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":10}],"id":108},{"display_name":"Ambidextrous","desc":"Increase your chance to attack with Counter by +30%","archetype":"","archetype_req":0,"parents":[104,105,110],"dependencies":[94],"blockers":[],"cost":1,"display":{"row":22,"col":4,"icon":"node_0"},"properties":{"chance":30},"effects":[],"id":109},{"display_name":"Burning Heart","desc":"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)","archetype":"Paladin","archetype_req":0,"parents":[109,111],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"fDamPct"},"scaling":[2],"max":100,"slider_step":100}],"id":110},{"display_name":"Stronger Bash","desc":"Increase the damage of Bash","archetype":"","archetype_req":0,"parents":[110,106],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[30,0,0,0,0,0]}],"id":111},{"display_name":"Intoxicating Blood","desc":"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted","archetype":"Fallen","archetype_req":5,"parents":[108,107],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":23,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":112},{"display_name":"Comet","desc":"After being hit by Fireworks, enemies will crash into the ground and receive more damage","archetype":"Fallen","archetype_req":0,"parents":[108],"dependencies":[88],"blockers":[],"cost":2,"display":{"row":24,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Comet","cost":0,"multipliers":[80,20,0,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Comet":1}}],"id":113},{"display_name":"Collide","desc":"Mobs thrown into walls from Flying Kick will explode and receive additonal damage","archetype":"Battle Monk","archetype_req":4,"parents":[109,110],"dependencies":[104],"blockers":[],"cost":2,"display":{"row":23,"col":5,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Collide","cost":0,"multipliers":[100,0,0,0,50,0]}],"id":114},{"display_name":"Rejuvenating Skin","desc":"Regain back 30% of the damage you take as healing over 30s","archetype":"Paladin","archetype_req":0,"parents":[110,111],"dependencies":[],"blockers":[],"cost":2,"display":{"row":23,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":115},{"display_name":"Uncontainable Corruption","desc":"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1","archetype":"","archetype_req":0,"parents":[107,117],"dependencies":[96],"blockers":[],"cost":1,"display":{"row":26,"col":0,"icon":"node_0"},"properties":{"cooldown":-5},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[1],"slider_step":2,"max":50}],"id":116},{"display_name":"Radiant Devotee","desc":"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)","archetype":"Battle Monk","archetype_req":1,"parents":[118,116],"dependencies":[],"blockers":[],"cost":1,"display":{"row":26,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","inputs":[{"type":"stat","name":"ref"}],"output":{"type":"stat","name":"mr"},"scaling":[1],"max":10,"slider_step":4}],"id":117},{"display_name":"Whirlwind Strike","desc":"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)","archetype":"Battle Monk","archetype_req":5,"parents":[109,117],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":26,"col":4,"icon":"node_1"},"properties":{"range":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":0,"multipliers":[0,0,0,0,0,50]}],"id":118},{"display_name":"Mythril Skin","desc":"Gain +5% Base Resistance and become immune to knockback","archetype":"Paladin","archetype_req":6,"parents":[115],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":5}]}],"id":119},{"display_name":"Armour Breaker","desc":"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage","archetype":"Fallen","archetype_req":0,"parents":[116,117],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":27,"col":1,"icon":"node_2"},"properties":{"duration":5},"effects":[],"id":120},{"display_name":"Shield Strike","desc":"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost","archetype":"Paladin","archetype_req":0,"parents":[119,122],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Shield Strike","cost":0,"multipliers":[60,0,20,0,0,0]}],"id":121},{"display_name":"Sparkling Hope","desc":"Everytime you heal 5% of your max health, deal damage to all nearby enemies","archetype":"Paladin","archetype_req":0,"parents":[119],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":8,"icon":"node_2"},"properties":{"aoe":6},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Sparkling Hope","cost":0,"multipliers":[10,0,5,0,0,0]}],"id":122},{"display_name":"Massive Bash","desc":"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)","archetype":"Fallen","archetype_req":8,"parents":[124,116],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"bashAoE"},"scaling":[1],"max":10,"slider_step":3}],"id":123},{"display_name":"Tempest","desc":"War Scream will ripple the ground and deal damage 3 times in a large area","archetype":"Battle Monk","archetype_req":0,"parents":[123,125],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2,"icon":"node_1"},"properties":{"aoe":16},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest","cost":"0","multipliers":[30,10,0,0,0,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest Total Damage","cost":"0","hits":{"Tempest":3}},{"type":"add_spell_prop","base_spell":4,"target_part":"Total Damage","cost":"0","hits":{"Tempest":3}}],"id":124},{"display_name":"Spirit of the Rabbit","desc":"Reduce the Mana cost of Charge and increase your Walk Speed by +20%","archetype":"Battle Monk","archetype_req":5,"parents":[124,118],"dependencies":[],"blockers":[],"cost":1,"display":{"row":28,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5},{"type":"raw_stat","bonuses":[{"type":"stat","name":"spd","value":20}]}],"id":125},{"display_name":"Massacre","desc":"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar","archetype":"Fallen","archetype_req":5,"parents":[124,123],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":126},{"display_name":"Axe Kick","desc":"Increase the damage of Uppercut, but also increase its mana cost","archetype":"","archetype_req":0,"parents":[124,125],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":10,"multipliers":[100,0,0,0,0,0]}],"id":127},{"display_name":"Radiance","desc":"Bash will buff your allies' positive IDs. (15s Cooldown)","archetype":"Paladin","archetype_req":2,"parents":[125,129],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":5,"icon":"node_2"},"properties":{"cooldown":15},"effects":[],"id":128},{"display_name":"Cheaper Bash 2","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[128,121,122],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":129},{"display_name":"Cheaper War Scream","desc":"Reduce the Mana cost of War Scream","archetype":"","archetype_req":0,"parents":[123],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":130},{"display_name":"Discombobulate","desc":"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second","archetype":"Battle Monk","archetype_req":12,"parents":[133],"dependencies":[],"blockers":[],"cost":2,"display":{"row":31,"col":2,"icon":"node_3"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"rainrawButDifferent"},"scaling":[2],"max":50}],"id":131},{"display_name":"Thunderclap","desc":"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder","archetype":"Battle Monk","archetype_req":8,"parents":[133],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":5,"icon":"node_1"},"properties":{},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"},{"type":"raw_stat","bonuses":[{"type":"prop","abil_name":"Bash","name":"aoe","value":3}]}],"id":132},{"display_name":"Cyclone","desc":"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s","archetype":"Battle Monk","archetype_req":0,"parents":[125],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":4,"icon":"node_1"},"properties":{"aoe":4,"duration":20},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone","cost":0,"multipliers":[10,0,0,0,5,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone Total Damage","cost":0,"hits":{"Cyclone":40}}],"id":133},{"display_name":"Second Chance","desc":"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)","archetype":"Paladin","archetype_req":12,"parents":[129],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":134},{"display_name":"Blood Pact","desc":"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)","archetype":"","archetype_req":10,"parents":[130],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1,"icon":"node_3"},"properties":{},"effects":[],"id":135},{"display_name":"Haemorrhage","desc":"Reduce Blood Pact's health cost. (0.5% health per mana)","archetype":"Fallen","archetype_req":0,"parents":[135],"dependencies":[135],"blockers":[],"cost":1,"display":{"row":35,"col":2,"icon":"node_1"},"properties":{},"effects":[],"id":136},{"display_name":"Brink of Madness","desc":"If your health is 25% full or less, gain +40% Resistance","archetype":"","archetype_req":0,"parents":[135,138],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":4,"icon":"node_2"},"properties":{},"effects":[],"id":137},{"display_name":"Cheaper Uppercut 2","desc":"Reduce the Mana cost of Uppercut","archetype":"","archetype_req":0,"parents":[134,137],"dependencies":[],"blockers":[],"cost":1,"display":{"row":35,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":138},{"display_name":"Martyr","desc":"When you receive a fatal blow, all nearby allies become invincible","archetype":"Paladin","archetype_req":0,"parents":[134],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":8,"icon":"node_1"},"properties":{"duration":3,"aoe":12},"effects":[],"id":139}]} \ No newline at end of file diff --git a/js/atree_constants_str_old.js b/js/atree_constants_str_old.js new file mode 100644 index 0000000..e0c7bc3 --- /dev/null +++ b/js/atree_constants_str_old.js @@ -0,0 +1,4160 @@ +const atrees = +{ + "Archer": [ + { + "display_name": "Arrow Shield", + "desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)", + "archetype": "", + "archetype_req": 0, + "parents": ["Power Shots", "Cheaper Escape"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 6 + }, + "properties": { + "duration": 60 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Shield", + "cost": 30, + "display_text": "Max Damage", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "", + "parts": [ + { + "name": "Shield Damage", + "type": "damage", + "multipliers": [90, 0, 0, 0, 0, 10] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Shield Damage": 2 + } + } + ] + } + ] + }, + + { + "display_name": "Escape", + "desc": "Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)", + "archetype": "", + "archetype_req": 0, + "parents": ["Heart Shatter"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 7, + "col": 4 + }, + "properties": { + "aoe": 0, + "range": 0 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Escape", + "cost": 25, + "display_text": "Max Damage", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [0, 0, 0, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } + } + ] + } + ] + }, + { + "display_name": "Arrow Bomb", + "desc": "Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)", + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 0, + "col": 4 + }, + "properties": { + "aoe": 4.5, + "range": 26 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Bomb", + "cost": 50, + "display_text": "Average Damage", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Arrow Bomb", + "type": "damage", + "multipliers": [160, 0, 0, 0, 20, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Arrow Bomb": 1 + } + } + ] + } + ] + }, + { + "display_name": "Heart Shatter", + "desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.", + "archetype": "", + "archetype_req": 0, + "parents": ["Bow Proficiency I"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 4, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [100, 0, 0, 0, 0, 0] + }, + { + + } + ] + }, + { + "display_name": "Fire Creep", + "desc": "Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.", + "archetype": "", + "archetype_req": 0, + "parents": ["Phantom Ray", "Fire Mastery", "Bryophyte Roots"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 6 + }, + "properties": { + "aoe": 0.8, + "duration": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [30, 0, 0, 0, 20, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fire Creep": 15 + } + } + ] + }, + { + "display_name": "Bryophyte Roots", + "desc": "When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.", + "archetype": "Trapper", + "archetype_req": 1, + "parents": ["Fire Creep", "Earth Mastery"], + "dependencies": ["Arrow Storm"], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 8 + }, + "properties": { + "aoe": 2, + "duration": 5, + "slowness": 0.4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Bryophyte Roots", + "cost": 0, + "multipliers": [40, 20, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Nimble String", + "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", + "archetype": "", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Arrow Rain"], + "dependencies": ["Arrow Storm"], + "blockers": ["Phantom Ray"], + "cost": 2, + "display": { + "row": 15, + "col": 2 + }, + "properties": { + "shootspeed": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [-15, 0, 0, 0, 0, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Stream", + "cost": 0, + "hits": { + "Single Arrow": 8 + } + } + ] + }, + { + "display_name": "Arrow Storm", + "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", + "archetype": "", + "archetype_req": 0, + "parents": ["Double Shots", "Cheaper Escape"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 2 + }, + "properties": { + "aoe": 0, + "range": 16 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Storm", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [30, 0, 10, 0, 0, 0] + }, + { + "name": "Single Stream", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Stream": 2 + } + } + ] + } + ] + }, + { + "display_name": "Guardian Angels", + "desc": "Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)", + "archetype": "Boltslinger", + "archetype_req": 3, + "parents": ["Triple Shots", "Frenzy"], + "dependencies": ["Arrow Shield"], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 1 + }, + "properties": { + "range": 4, + "duration": 60, + "shots": 8, + "count": 2 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Guardian Angels", + "cost": 30, + "display_text": "Total Damage Average", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [40, 0, 0, 0, 0, 20] + }, + { + "name": "Single Bow", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Bow": 2 + } + } + ] + } + ] + }, + { + "display_name": "Windy Feet", + "base_abil": "Escape", + "desc": "When casting Escape, give speed to yourself and nearby allies.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Arrow Storm"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 1 + }, + "properties": { + "aoe": 8, + "duration": 120 + }, + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spd", + "value": 20 + } + ] + }, + { + "display_name": "Basaltic Trap", + "desc": "When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)", + "archetype": "Trapper", + "archetype_req": 2, + "parents": ["Bryophyte Roots"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 8 + }, + "properties": { + "aoe": 7, + "traps": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [140, 30, 0, 0, 30, 0] + } + ] + }, + { + "display_name": "Windstorm", + "desc": "Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.", + "archetype": "", + "archetype_req": 0, + "parents": ["Guardian Angels", "Cheaper Arrow Storm"], + "dependencies": [], + "blockers": ["Phantom Ray"], + "cost": 2, + "display": { + "row": 21, + "col": 1 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [-11, 0, -7, 0, 0, 3] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 1 + } + } + ] + }, + { + "display_name": "Grappling Hook", + "base_abil": "Escape", + "desc": "When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Focus", "More Shields", "Cheaper Arrow Storm"], + "dependencies": [], + "blockers": ["Escape Artist"], + "cost": 2, + "display": { + "row": 21, + "col": 5 + }, + "properties": { + "range": 20 + }, + "effects": [ + ] + }, + { + "display_name": "Implosion", + "desc": "Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Grappling Hook", "More Shields"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 6 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [40, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Twain's Arc", + "desc": "When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)", + "archetype": "Sharpshooter", + "archetype_req": 4, + "parents": ["More Focus", "Traveler"], + "dependencies": ["Focus"], + "blockers": [], + "cost": 2, + "display": { + "row": 25, + "col": 4 + }, + "properties": { + "range": 64, + "focusReq": 2 + }, + "effects": [ + + { + "type": "replace_spell", + "name": "Twain's Arc", + "cost": 0, + "display_text": "Twain's Arc", + "base_spell": 5, + "spell_type": "damage", + "scaling": "melee", + "display": "Twain's Arc Damage", + "parts": [ + { + "name": "Twain's Arc Damage", + "type": "damage", + "multipliers": [200, 0, 0, 0, 0, 0] + } + ] + } + ] + }, + { + "display_name": "Fierce Stomp", + "desc": "When using Escape, hold shift to quickly drop down and deal damage.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Refined Gunpowder", "Traveler"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 1 + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [100, 0, 0, 0, 0, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fierce Stomp": 1 + } + } + ] + }, + { + "display_name": "Scorched Earth", + "desc": "Fire Creep become much stronger.", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Twain's Arc"], + "dependencies": ["Fire Creep"], + "blockers": [], + "cost": 1, + "display": { + "row": 26 , + "col": 5 + }, + "properties": { + "duration": 2, + "aoe": 0.4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [10, 0, 0, 0, 5, 0] + } + ] + }, + { + "display_name": "Leap", + "desc": "When you double tap jump, leap foward. (2s Cooldown)", + "archetype": "Boltslinger", + "archetype_req": 5, + "parents": ["Refined Gunpowder", "Homing Shots"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 0 + }, + "properties": { + "cooldown": 2 + }, + "effects": [ + + ] + }, + { + "display_name": "Shocking Bomb", + "desc": "Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.", + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": ["Twain's Arc", "Better Arrow Shield", "Homing Shots"], + "dependencies": ["Arrow Bomb"], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 4 + }, + "properties": { + "gravity": 0 + }, + "effects": [ + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + } + ] + }, + { + "display_name": "Mana Trap", + "desc": "Your Traps will give you 4 Mana per second when you stay close to them.", + "archetype": "Trapper", + "archetype_req": 5, + "parents": ["More Traps", "Better Arrow Shield"], + "dependencies": ["Fire Creep"], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 8 + }, + "properties": { + "range": 12, + "manaRegen": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 10, + "multipliers": [0, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Escape Artist", + "desc": "When casting Escape, release 100 arrows towards the ground.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Better Guardian Angels", "Leap"], + "dependencies": [], + "blockers": ["Grappling Hook"], + "cost": 2, + "display": { + "row": 31, + "col": 0 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Escape Artist", + "cost": 0, + "multipliers": [30, 0, 10, 0, 0, 0] + } + ] + }, + { + "display_name": "Initiator", + "desc": "If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.", + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": ["Shocking Bomb", "Better Arrow Shield", "Cheaper Arrow Storm (2)"], + "dependencies": ["Focus"], + "blockers": [], + "cost": 2, + "display": { + "row": 31, + "col": 5 + }, + "properties": { + "focus": 1, + "timer": 5 + }, + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "damPct", + "value": 50 + } + ] + }, + { + "display_name": "Call of the Hound", + "desc": "Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Initiator", "Cheaper Arrow Storm (2)"], + "dependencies": ["Arrow Shield"], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 7 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Call of the Hound", + "cost": 0, + "multipliers": [40, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Arrow Hurricane", + "desc": "Arrow Storm will shoot +2 stream of arrows.", + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": ["Precise Shot", "Escape Artist"], + "dependencies": [], + "blockers": ["Phantom Ray"], + "cost": 2, + "display": { + "row": 33, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 2 + } + } + ] + }, + { + "display_name": "Geyser Stomp", + "desc": "Fierce Stomp will create geysers, dealing more damage and vertical knockback.", + "archetype": "", + "archetype_req": 0, + "parents": ["Shrapnel Bomb"], + "dependencies": ["Fierce Stomp"], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 1 + }, + "properties": { + "aoe": 1 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [0, 0, 0, 50, 0, 0] + } + ] + }, + { + "display_name": "Crepuscular Ray", + "desc": "If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.", + "archetype": "Sharpshooter", + "archetype_req": 10, + "parents": ["Cheaper Arrow Shield"], + "dependencies": ["Arrow Storm"], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 4 + }, + "properties": { + "focusReq": 5, + "focusRegen": -1 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Crepuscular Ray", + "base_spell": 5, + "spell_type": "damage", + "scaling": "spell", + "display": "One Focus", + "cost": 0, + + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [10, 0, 0, 5, 0, 0] + }, + { + "name": "One Focus", + "type": "total", + "hits": { + "Single Arrow": 20 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "One Focus": 7 + } + } + ] + } + ] + }, + { + "display_name": "Grape Bomb", + "desc": "Arrow bomb will throw 3 additional smaller bombs when exploding.", + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Escape (2)"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 7 + }, + "properties": { + "miniBombs": 3, + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Grape Bomb", + "cost": 0, + "multipliers": [30, 0, 0, 0, 10, 0] + } + ] + }, + { + "display_name": "Tangled Traps", + "desc": "Your Traps will be connected by a rope that deals damage to enemies every 0.2s.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Grape Bomb"], + "dependencies": ["Basaltic Trap"], + "blockers": [], + "cost": 2, + "display": { + "row": 38, + "col": 6 + }, + "properties": { + "attackSpeed": 0.2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Tangled Traps", + "cost": 0, + "multipliers": [20, 0, 0, 0, 0, 20] + } + ] + }, + { + "display_name": "Snow Storm", + "desc": "Enemies near you will be slowed down.", + "archetype": "", + "archetype_req": 0, + "parents": ["Geyser Stomp", "More Focus (2)"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 39, + "col": 2 + }, + "properties": { + "range": 2.5, + "slowness": 0.3 + } + }, + { + "display_name": "All-Seeing Panoptes", + "desc": "Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.", + "archetype": "Boltslinger", + "archetype_req": 11, + "parents": ["Snow Storm"], + "dependencies": ["Guardian Angels"], + "blockers": [], + "cost": 2, + "display": { + "row": 40, + "col": 1 + }, + "properties": { + "range": 10, + "shots": 5 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [0, 0, 0, 0, 20, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 5 + } + } + ] + }, + { + "display_name": "Minefield", + "desc": "Allow you to place +6 Traps, but with reduced damage and range.", + "archetype": "Trapper", + "archetype_req": 10, + "parents": ["Grape Bomb", "Cheaper Arrow Bomb (2)"], + "dependencies": ["Basaltic Trap"], + "blockers": [], + "cost": 2, + "display": { + "row": 40, + "col": 7 + }, + "properties": { + "aoe": -2, + "traps": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [-80, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Bow Proficiency I", + "desc": "Improve your Main Attack's damage and range when using a bow.", + "archetype": "", + "archetype_req": 0, + "parents": ["Arrow Bomb"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 4 + }, + "properties": { + "mainAtk_range": 6 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ] + }, + { + "display_name": "Cheaper Arrow Bomb", + "desc": "Reduce the Mana cost of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": ["Bow Proficiency I"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 6 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -10 + } + ] + }, + { + "display_name": "Cheaper Arrow Storm", + "desc": "Reduce the Mana cost of Arrow Storm.", + "archetype": "", + "archetype_req": 0, + "parents": ["Grappling Hook", "Windstorm", "Focus"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 21, + "col": 3 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ] + }, + { + "display_name": "Cheaper Escape", + "desc": "Reduce the Mana cost of Escape.", + "archetype": "", + "archetype_req": 0, + "parents": ["Arrow Storm", "Arrow Shield"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 4 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ] + }, + { + "display_name": "Earth Mastery", + "desc": "Increases your base damage from all Earth attacks", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Arrow Shield"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 8 + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "eDamPct", + "value": 20 + }, + { + "type": "stat", + "name": "eDam", + "value": [2, 4] + } + ] + } + ] + }, + { + "display_name": "Thunder Mastery", + "desc": "Increases your base damage from all Thunder attacks", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Arrow Storm", "Fire Mastery"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 2 + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "tDamPct", + "value": 10 + }, + { + "type": "stat", + "name": "tDam", + "value": [1, 8] + } + ] + } + ] + }, + { + "display_name": "Water Mastery", + "desc": "Increases your base damage from all Water attacks", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Cheaper Escape", "Thunder Mastery", "Fire Mastery"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 14, + "col": 4 + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "wDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "wDam", + "value": [2, 4] + } + ] + } + ] + }, + { + "display_name": "Air Mastery", + "desc": "Increases base damage from all Air attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Arrow Storm"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 0 + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "aDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "aDam", + "value": [3, 4] + } + ] + } + ] + }, + { + "display_name": "Fire Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Arrow Shield"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 6 + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "fDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "fDam", + "value": [3, 5] + } + ] + } + ] + }, + { + "display_name": "More Shields", + "desc": "Give +2 charges to Arrow Shield.", + "archetype": "", + "archetype_req": 0, + "parents": ["Grappling Hook", "Basaltic Trap"], + "dependencies": ["Arrow Shield"], + "blockers": [], + "cost": 1, + "display": { + "row": 21, + "col": 7 + }, + "properties": { + "shieldCharges": 2 + } + }, + { + "display_name": "Stormy Feet", + "desc": "Windy Feet will last longer and add more speed.", + "archetype": "", + "archetype_req": 0, + "parents": ["Windstorm"], + "dependencies": ["Windy Feet"], + "blockers": [], + "cost": 1, + "display": { + "row": 23, + "col": 1 + }, + "properties": { + "duration": 60 + }, + "effects": [ + { + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spdPct", + "value": 20 + } + ] + } + ] + }, + { + "display_name": "Refined Gunpowder", + "desc": "Increase the damage of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": ["Windstorm"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 25, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [50, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "More Traps", + "desc": "Increase the maximum amount of active Traps you can have by +2.", + "archetype": "Trapper", + "archetype_req": 10, + "parents": ["Bouncing Bomb"], + "dependencies": ["Basaltic Trap"], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 8 + }, + "properties": { + "traps": 2 + } + }, + { + "display_name": "Better Arrow Shield", + "desc": "Arrow Shield will gain additional area of effect, knockback and damage.", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Mana Trap", "Shocking Bomb", "Twain's Arc"], + "dependencies": ["Arrow Shield"], + "blockers": [], + "cost": 1, + "display": { + "row": 28, + "col": 6 + }, + "properties": { + "aoe": 1 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Shield", + "multipliers": [40, 0, 0, 0, 0, 0] + } + ] + }, + { + "display_name": "Better Leap", + "desc": "Reduce leap's cooldown by 1s.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Leap", "Homing Shots"], + "dependencies": ["Leap"], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 1 + }, + "properties": { + "cooldown": -1 + } + }, + { + "display_name": "Better Guardian Angels", + "desc": "Your Guardian Angels can shoot +4 arrows before disappearing.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Escape Artist", "Homing Shots"], + "dependencies": ["Guardian Angels"], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 2 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 4 + } + } + ] + }, + { + "display_name": "Cheaper Arrow Storm (2)", + "desc": "Reduce the Mana cost of Arrow Storm.", + "archetype": "", + "archetype_req": 0, + "parents": ["Initiator", "Mana Trap"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 8 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ] + }, + { + "display_name": "Precise Shot", + "desc": "+30% Critical Hit Damage", + "archetype": "", + "archetype_req": 0, + "parents": ["Better Guardian Angels", "Cheaper Arrow Shield", "Arrow Hurricane"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 2 + }, + "properties": { + "mainAtk_range": 6 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdCritPct", + "value": 30 + } + ] + } + ] + }, + { + "display_name": "Cheaper Arrow Shield", + "desc": "Reduce the Mana cost of Arrow Shield.", + "archetype": "", + "archetype_req": 0, + "parents": ["Precise Shot", "Initiator"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 4 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ] + }, + { + "display_name": "Rocket Jump", + "desc": "Arrow Bomb's self-damage will knockback you farther away.", + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Arrow Storm (2)", "Initiator"], + "dependencies": ["Arrow Bomb"], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 6 + }, + "properties": { + } + }, + { + "display_name": "Cheaper Escape (2)", + "desc": "Reduce the Mana cost of Escape.", + "archetype": "", + "archetype_req": 0, + "parents": ["Call of the Hound", "Decimator"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 34, + "col": 7 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ] + }, + { + "display_name": "Stronger Hook", + "desc": "Increase your Grappling Hook's range, speed and strength.", + "archetype": "Trapper", + "archetype_req": 5, + "parents": ["Cheaper Escape (2)"], + "dependencies": ["Grappling Hook"], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 8 + }, + "properties": { + "range": 8 + } + }, + { + "display_name": "Cheaper Arrow Bomb (2)", + "desc": "Reduce the Mana cost of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": ["More Focus (2)", "Minefield"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 40, + "col": 5 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ] + }, + { + "display_name": "Bouncing Bomb", + "desc": "Arrow Bomb will bounce once when hitting a block or enemy", + "archetype": "", + "archetype_req": 0, + "parents": ["More Shields"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 25, + "col": 7 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Arrow Bomb": 2 + } + } + ] + }, + { + "display_name": "Homing Shots", + "desc": "Your Main Attack arrows will follow nearby enemies and not be affected by gravity", + "archetype": "", + "archetype_req": 0, + "parents": ["Leap", "Shocking Bomb"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 2 + }, + "properties": { + + }, + "effects": [ + + ] + }, + { + "display_name": "Shrapnel Bomb", + "desc": "Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area", + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": ["Arrow Hurricane", "Precise Shot"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 34, + "col": 1 + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Shrapnel Bomb", + "cost": 0, + "multipliers": [40, 0, 0, 0, 20, 0] + } + ] + }, + { + "display_name": "Elusive", + "desc": "If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Geyser Stomp"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 38, + "col": 0 + }, + "properties": { + + }, + "effects": [ + + ] + }, + { + "display_name": "Double Shots", + "desc": "Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Escape"], + "dependencies": [], + "blockers": ["Power Shots"], + "cost": 1, + "display": { + "row": 7, + "col": 2 + }, + "properties": { + "arrow": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 0, + "target_part": "Melee Damage", + "cost": 0, + "multipliers": 0.7 + } + ] + }, + { + "display_name": "Triple Shots", + "desc": "Triple Main Attack arrows, but they deal -20% damage per arrow", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Arrow Rain", "Frenzy"], + "dependencies": ["Double Shots"], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 0 + }, + "properties": { + "arrow": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 0, + "target_part": "Melee Damage", + "cost": 0, + "multipliers": 0.7 + } + ] + }, + { + "display_name": "Power Shots", + "desc": "Main Attack arrows have increased speed and knockback", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Escape"], + "dependencies": [], + "blockers": ["Double Shots"], + "cost": 1, + "display": { + "row": 7, + "col": 6 + }, + "properties": { + + }, + "effects": [ + + ] + }, + { + "display_name": "Focus", + "desc": "When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once", + "archetype": "Sharpshooter", + "archetype_req": 2, + "parents": ["Phantom Ray"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 4 + }, + "properties": { + + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [35], + "max": 3 + } + ] + }, + { + "display_name": "More Focus", + "desc": "Add +2 max Focus", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Cheaper Arrow Storm", "Grappling Hook"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 4 + }, + "properties": { + + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [35], + "max": 5 + } + ] + }, + { + "display_name": "More Focus (2)", + "desc": "Add +2 max Focus", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Crepuscular Ray", "Snow Storm"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 39, + "col": 4 + }, + "properties": { + + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [35], + "max": 7 + } + ] + }, + { + "display_name": "Traveler", + "desc": "For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)", + "archetype": "", + "archetype_req": 0, + "parents": ["Refined Gunpowder", "Twain's Arc"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 25, + "col": 2 + }, + "properties": { + + }, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "spd" + } + ], + "output": { + "type": "stat", + "name": "sdRaw" + }, + "scaling": [1], + "max": 100 + } + ] + }, + { + "display_name": "Patient Hunter", + "desc": "Your Traps will deal +20% more damage for every second they are active (Max +80%)", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["More Shields"], + "dependencies": ["Basaltic Trap"], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 8 + }, + "properties": { + "max": 80 + }, + "effects": [ + + ] + }, + { + "display_name": "Stronger Patient Hunter", + "desc": "Add +80% Max Damage to Patient Hunter", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Grape Bomb"], + "dependencies": ["Patient Hunter"], + "blockers": [], + "cost": 1, + "display": { + "row": 38, + "col": 8 + }, + "properties": { + "max": 80 + }, + "effects": [ + + ] + }, + { + "display_name": "Frenzy", + "desc": "Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Triple Shots", "Nimble String"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 17, + "col": 2 + }, + "properties": { + + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Hits dealt", + "output": { + "type": "stat", + "name": "spd" + }, + "scaling": [6], + "max": 200 + } + ] + }, + { + "display_name": "Phantom Ray", + "desc": "Condense Arrow Storm into a single ray that damages enemies 10 times per second", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Water Mastery", "Fire Creep"], + "dependencies": ["Arrow Storm"], + "blockers": ["Windstorm", "Nimble String", "Arrow Hurricane"], + "cost": 2, + "display": { + "row": 16, + "col": 4 + }, + "properties": { + }, + "effects": [ + { + "type": "replace_spell", + "name": "Phantom Ray", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [25, 0, 5, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Arrow": 16 + } + } + ] + } + ] + }, + { + "display_name": "Arrow Rain", + "desc": "When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies", + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Nimble String", "Air Mastery"], + "dependencies": ["Arrow Shield"], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 0 + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Arrow Rain", + "cost": 0, + "multipliers": [120, 0, 0, 0, 0, 80] + } + ] + }, + { + "display_name": "Decimator", + "desc": "Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Cheaper Arrow Shield"], + "dependencies": ["Phantom Ray"], + "blockers": [], + "cost": 1, + "display": { + "row": 34, + "col": 5 + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Phantom Ray hits", + "output": { + "type": "stat", + "name": "PhRayDmg" + }, + "scaling": 10, + "max": 50 + } + ] + } + ], + "Warrior": [ + { + "display_name": "Bash", + "desc": "Violently bash the ground, dealing high damage in a large area", + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 0, + "col": 4, + "icon": "node_4" + }, + "properties": { + "aoe": 4, + "range": 3 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Bash", + "cost": 45, + "display_text": "Total Damage Average", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Hit", + "type": "damage", + "multipliers": [130, 20, 0, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Hit": 1 + } + } + ] + } + ] + }, + { + "display_name": "Spear Proficiency 1", + "desc": "Improve your Main Attack's damage and range w/ spear", + "archetype": "", + "archetype_req": 0, + "parents": ["Bash"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 4, + "icon": "node_0" + }, + "properties": { + "melee_range": 1 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ] + }, + + { + "display_name": "Cheaper Bash", + "desc": "Reduce the Mana cost of Bash", + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 1"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 2, + "icon": "node_0" + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -10 + } + ] + }, + { + "display_name": "Double Bash", + "desc": "Bash will hit a second time at a farther range", + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 1"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 4, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 3 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "name": "Single Hit", + "value": 1 + } + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [-50, 0, 0, 0, 0, 0] + } + ] + }, + + { + "display_name": "Charge", + "desc": "Charge forward at high speed (hold shift to cancel)", + "archetype": "", + "archetype_req": 0, + "parents": ["Double Bash"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 6, + "col": 4, + "icon": "node_4" + }, + "properties": { + }, + "effects": [ + { + "type": "replace_spell", + "name": "Charge", + "cost": 25, + "display_text": "Total Damage Average", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [0, 0, 0, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } + } + ] + } + ] + }, + + { + "display_name": "Heavy Impact", + "desc": "After using Charge, violently crash down into the ground and deal damage", + "archetype": "", + "archetype_req": 0, + "parents": ["Uppercut"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 1, + "icon": "node_1" + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Heavy Impact", + "cost": 0, + "multipliers": [100, 0, 0, 0, 0, 0] + } + ] + }, + + { + "display_name": "Vehement", + "desc": "For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Charge"], + "dependencies": [], + "blockers": ["Tougher Skin"], + "cost": 1, + "display": { + "row": 6, + "col": 2, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "mdPct" + }, + { + "type": "stat", + "name": "mdRaw" + } + ], + "output": { + "type": "stat", + "name": "spd" + }, + "scaling": [1, 1], + "max": 20 + } + ] + }, + + { + "display_name": "Tougher Skin", + "desc": "Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Charge"], + "dependencies": [], + "blockers": ["Vehement"], + "cost": 1, + "display": { + "row": 6, + "col": 6, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "baseResist", + "value": "5" + } + ] + }, + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hprRaw" + }, + { + "type": "stat", + "name": "hprPct" + } + ], + "output": { + "type": "stat", + "name": "hpBonus" + }, + "scaling": [10, 10], + "max": 100 + } + ] + }, + + { + "display_name": "Uppercut", + "desc": "Rocket enemies in the air and deal massive damage", + "archetype": "", + "archetype_req": 0, + "parents": ["Vehement"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 2, + "icon": "node_4" + }, + "properties": { + "aoe": 3, + "range": 5 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Uppercut", + "cost": 45, + "display_text": "Total Damage Average", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "total", + "parts": [ + { + "name": "Uppercut", + "type": "damage", + "multipliers": [150, 50, 50, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Uppercut": 1 + } + } + ] + } + ] + }, + + { + "display_name": "Cheaper Charge", + "desc": "Reduce the Mana cost of Charge", + "archetype": "", + "archetype_req": 0, + "parents": ["Uppercut", "War Scream"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 4, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ] + }, + + { + "display_name": "War Scream", + "desc": "Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies", + "archetype": "", + "archetype_req": 0, + "parents": ["Tougher Skin"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 6, + "icon": "node_4" + }, + "properties": { + "duration": 30, + "aoe": 12, + "defense_bonus": 10 + }, + "effects": [ + { + "type": "replace_spell", + "name": "War Scream", + "cost": 35, + "display_text": "War Scream", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage Average", + "parts": [ + { + "name": "War Scream", + "type": "damage", + "multipliers": [50, 0, 0, 0, 50, 0] + } + ] + } + ] + }, + + { + "display_name": "Earth Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uppercut"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 0, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "eDamPct", + "value": 20 + }, + { + "type": "stat", + "name": "eDam", + "value": [2, 4] + } + ] + } + ] + }, + + { + "display_name": "Thunder Mastery", + "desc": "Increases base damage from all Thunder attacks", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uppercut", "Air Mastery", "Cheaper Charge"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 2, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "tDamPct", + "value": 10 + }, + { + "type": "stat", + "name": "tDam", + "value": [1, 8] + } + ] + } + ] + }, + + { + "display_name": "Water Mastery", + "desc": "Increases base damage from all Water attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Cheaper Charge", "Thunder Mastery", "Air Mastery"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 11, + "col": 4, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "wDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "wDam", + "value": [2, 4] + } + ] + } + ] + }, + + { + "display_name": "Air Mastery", + "desc": "Increases base damage from all Air attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["War Scream", "Thunder Mastery", "Cheaper Charge"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 6, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "aDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "aDam", + "value": [3, 4] + } + ] + } + ] + }, + + { + "display_name": "Fire Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["War Scream"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 8, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "fDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "fDam", + "value": [3, 5] + } + ] + } + ] + }, + + { + "display_name": "Quadruple Bash", + "desc": "Bash will hit 4 times at an even larger range", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Earth Mastery", "Fireworks"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 0, + "icon": "node_1" + }, + "properties": { + "range": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Hit": 2 + } + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [-20, 0, 0, 0, 0, 0] + } + ] + }, + + { + "display_name": "Fireworks", + "desc": "Mobs hit by Uppercut will explode mid-air and receive additional damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Quadruple Bash"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 2, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fireworks", + "cost": 0, + "multipliers": [80, 0, 20, 0, 0, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fireworks": 1 + } + } + ] + }, + + { + "display_name": "Half-Moon Swipe", + "desc": "Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Water Mastery"], + "dependencies": ["Uppercut"], + "blockers": [], + "cost": 2, + "display": { + "row": 13, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": -10, + "multipliers": [-70, 0, 0, 0, 0, 0] + }, + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "water" + } + ] + }, + + { + "display_name": "Flyby Jab", + "desc": "Damage enemies in your way when using Charge", + "archetype": "", + "archetype_req": 0, + "parents": ["Air Mastery", "Flaming Uppercut"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 6, + "icon": "node_1" + }, + "properties": { + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Flyby Jab", + "cost": 0, + "multipliers": [20, 0, 0, 0, 0, 40] + } + ] + }, + + { + "display_name": "Flaming Uppercut", + "desc": "Uppercut will light mobs on fire, dealing damage every 0.6 seconds", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Fire Mastery", "Flyby Jab"], + "dependencies": ["Uppercut"], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 8, + "icon": "node_1" + }, + "properties": { + "duration": 3, + "tick": 0.6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Flaming Uppercut", + "cost": 0, + "multipliers": [0, 0, 0, 0, 50, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Flaming Uppercut Total Damage", + "cost": 0, + "hits": { + "Flaming Uppercut": 5 + } + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Flaming Uppercut": 5 + } + } + ] + }, + + { + "display_name": "Iron Lungs", + "desc": "War Scream deals more damage", + "archetype": "", + "archetype_req": 0, + "parents": ["Flyby Jab", "Flaming Uppercut"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 7, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "War Scream", + "cost": 0, + "multipliers": [30, 0, 0, 0, 0, 30] + } + ] + }, + + { + "display_name": "Generalist", + "desc": "After casting 3 different spells in a row, your next spell will cost 5 mana", + "archetype": "Battle Monk", + "archetype_req": 3, + "parents": ["Counter"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 2, + "icon": "node_3" + }, + "properties": { + }, + "effects": [ + + ] + }, + + { + "display_name": "Counter", + "desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Half-Moon Swipe"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 4, + "icon": "node_1" + }, + "properties": { + "chance": 30 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Counter", + "cost": 0, + "multipliers": [60, 0, 20, 0, 0, 20] + } + ] + }, + + { + "display_name": "Mantle of the Bovemists", + "desc": "When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)", + "archetype": "Paladin", + "archetype_req": 3, + "parents": ["Iron Lungs"], + "dependencies": ["War Scream"], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 7, + "icon": "node_3" + }, + "properties": { + "mantle_charge": 3 + }, + "effects": [ + + ] + }, + + { + "display_name": "Bak'al's Grasp", + "desc": "After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)", + "archetype": "Fallen", + "archetype_req": 2, + "parents": ["Quadruple Bash", "Fireworks"], + "dependencies": ["War Scream"], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 1, + "icon": "node_3" + }, + "properties": { + "cooldown": 15 + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "raw" + }, + "scaling": [4], + "slider_step": 2, + "max": 120 + } + ] + }, + + { + "display_name": "Spear Proficiency 2", + "desc": "Improve your Main Attack's damage and range w/ spear", + "archetype": "", + "archetype_req": 0, + "parents": ["Bak'al's Grasp", "Cheaper Uppercut"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 0, + "icon": "node_0" + }, + "properties": { + "melee_range": 1 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ] + }, + + { + "display_name": "Cheaper Uppercut", + "desc": "Reduce the Mana Cost of Uppercut", + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 2", "Aerodynamics", "Counter"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 3, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ] + }, + + { + "display_name": "Aerodynamics", + "desc": "During Charge, you can steer and change direction", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Cheaper Uppercut", "Provoke"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 17, + "col": 5, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + + ] + }, + + { + "display_name": "Provoke", + "desc": "Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Aerodynamics", "Mantle of the Bovemists"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 7, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ] + }, + + { + "display_name": "Precise Strikes", + "desc": "+30% Critical Hit Damage", + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Uppercut", "Spear Proficiency 2"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 18, + "col": 2, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "critDmg", + "value": 30 + } + ] + } + ] + }, + + { + "display_name": "Air Shout", + "desc": "War Scream will fire a projectile that can go through walls and deal damage multiple times", + "archetype": "", + "archetype_req": 0, + "parents": ["Aerodynamics", "Provoke"], + "dependencies": ["War Scream"], + "blockers": [], + "cost": 2, + "display": { + "row": 18, + "col": 6, + "icon": "node_1" + }, + "properties": { + + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Air Shout", + "cost": 0, + "multipliers": [20, 0, 0, 0, 0, 5] + } + ] + }, + + { + "display_name": "Enraged Blow", + "desc": "While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Spear Proficiency 2"], + "dependencies": ["Bak'al's Grasp"], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 0, + "icon": "node_2" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hpBonus" + } + ], + "output": { + "type": "stat", + "name": "dmgPct" + }, + "scaling": [2], + "max": 200 + } + ] + }, + + { + "display_name": "Flying Kick", + "desc": "When using Charge, mobs hit will halt your momentum and get knocked back", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Cheaper Uppercut", "Stronger Mantle"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 3, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Flying Kick", + "cost": 0, + "multipliers": [120, 0, 0, 10, 0, 20] + } + ] + }, + + { + "display_name": "Stronger Mantle", + "desc": "Add +2 additional charges to Mantle of the Bovemists", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Manachism", "Flying Kick"], + "dependencies": ["Mantle of the Bovemists"], + "blockers": [], + "cost": 1, + "display": { + "row": 20, + "col": 6, + "icon": "node_0" + }, + "properties": { + "mantle_charge": 2 + }, + "effects": [ + + ] + }, + + { + "display_name": "Manachism", + "desc": "If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)", + "archetype": "Paladin", + "archetype_req": 3, + "parents": ["Stronger Mantle", "Provoke"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 8, + "icon": "node_2" + }, + "properties": { + "cooldown": 1 + }, + "effects": [ + + ] + }, + + { + "display_name": "Boiling Blood", + "desc": "Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds", + "archetype": "", + "archetype_req": 0, + "parents": ["Enraged Blow", "Ragnarokkr"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 0, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Boiling Blood", + "cost": 0, + "multipliers": [25, 0, 0, 0, 5, 0] + } + ] + }, + + { + "display_name": "Ragnarokkr", + "desc": "War Scream become deafening, increasing its range and giving damage bonus to players", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Boiling Blood", "Flying Kick"], + "dependencies": ["War Scream"], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 2, + "icon": "node_2" + }, + "properties": { + "damage_bonus": 30, + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": 10 + } + ] + }, + + { + "display_name": "Ambidextrous", + "desc": "Increase your chance to attack with Counter by +30%", + "archetype": "", + "archetype_req": 0, + "parents": ["Flying Kick", "Stronger Mantle", "Burning Heart"], + "dependencies": ["Counter"], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 4, + "icon": "node_0" + }, + "properties": { + "chance": 30 + }, + "effects": [ + + ] + }, + + { + "display_name": "Burning Heart", + "desc": "For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Ambidextrous", "Stronger Bash"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 6, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hpBonus" + } + ], + "output": { + "type": "stat", + "name": "fDamPct" + }, + "scaling": [2], + "max": 100, + "slider_step": 100 + } + ] + }, + + { + "display_name": "Stronger Bash", + "desc": "Increase the damage of Bash", + "archetype": "", + "archetype_req": 0, + "parents": ["Burning Heart", "Manachism"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 8, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [30, 0, 0, 0, 0, 0] + } + ] + }, + + { + "display_name": "Intoxicating Blood", + "desc": "After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted", + "archetype": "Fallen", + "archetype_req": 5, + "parents": ["Ragnarokkr", "Boiling Blood"], + "dependencies": ["Bak'al's Grasp"], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 1, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + + ] + }, + + { + "display_name": "Comet", + "desc": "After being hit by Fireworks, enemies will crash into the ground and receive more damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Ragnarokkr"], + "dependencies": ["Fireworks"], + "blockers": [], + "cost": 2, + "display": { + "row": 24, + "col": 2, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Comet", + "cost": 0, + "multipliers": [80, 20, 0, 0, 0, 0] + }, + { + "type":"add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Comet": 1 + } + } + ] + }, + + { + "display_name": "Collide", + "desc": "Mobs thrown into walls from Flying Kick will explode and receive additonal damage", + "archetype": "Battle Monk", + "archetype_req": 4, + "parents": ["Ambidextrous", "Burning Heart"], + "dependencies": ["Flying Kick"], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 5, + "icon": "node_1" + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Collide", + "cost": 0, + "multipliers": [100, 0, 0, 0, 50, 0] + } + ] + }, + + { + "display_name": "Rejuvenating Skin", + "desc": "Regain back 30% of the damage you take as healing over 30s", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Burning Heart", "Stronger Bash"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 7, + "icon": "node_3" + }, + "properties": { + }, + "effects": [ + + ] + }, + + { + "display_name": "Uncontainable Corruption", + "desc": "Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1", + "archetype": "", + "archetype_req": 0, + "parents": ["Boiling Blood", "Radiant Devotee"], + "dependencies": ["Bak'al's Grasp"], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 0, + "icon": "node_0" + }, + "properties": { + "cooldown": -5 + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "raw" + }, + "scaling": [1], + "slider_step": 2, + "max": 50 + } + ] + }, + + { + "display_name": "Radiant Devotee", + "desc": "For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Whirlwind Strike", "Uncontainable Corruption"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 2, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "inputs": [ + { + "type": "stat", + "name": "ref" + } + ], + "output": { + "type": "stat", + "name": "mr" + }, + "scaling": [1], + "max": 10, + "slider_step": 4 + } + ] + }, + + { + "display_name": "Whirlwind Strike", + "desc": "Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)", + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": ["Ambidextrous", "Radiant Devotee"], + "dependencies": ["Uppercut"], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": 0, + "multipliers": [0, 0, 0, 0, 0, 50] + } + ] + }, + + { + "display_name": "Mythril Skin", + "desc": "Gain +5% Base Resistance and become immune to knockback", + "archetype": "Paladin", + "archetype_req": 6, + "parents": ["Rejuvenating Skin"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 7, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "baseResist", + "value": 5 + } + ] + } + ] + }, + + { + "display_name": "Armour Breaker", + "desc": "While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uncontainable Corruption", "Radiant Devotee"], + "dependencies": ["Bak'al's Grasp"], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 1, + "icon": "node_2" + }, + "properties": { + "duration": 5 + }, + "effects": [ + + ] + }, + + { + "display_name": "Shield Strike", + "desc": "When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Mythril Skin", "Sparkling Hope"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 6, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Shield Strike", + "cost": 0, + "multipliers": [60, 0, 20, 0, 0, 0] + } + ] + }, + + { + "display_name": "Sparkling Hope", + "desc": "Everytime you heal 5% of your max health, deal damage to all nearby enemies", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Mythril Skin"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 8, + "icon": "node_2" + }, + "properties": { + "aoe": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Sparkling Hope", + "cost": 0, + "multipliers": [10, 0, 5, 0, 0, 0] + } + ] + }, + + { + "display_name": "Massive Bash", + "desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)", + "archetype": "Fallen", + "archetype_req": 8, + "parents": ["Tempest", "Uncontainable Corruption"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 0, + "icon": "node_2" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "bashAoE" + }, + "scaling": [1], + "max": 10, + "slider_step": 3 + } + ] + }, + + { + "display_name": "Tempest", + "desc": "War Scream will ripple the ground and deal damage 3 times in a large area", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Massive Bash", "Spirit of the Rabbit"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 2, + "icon": "node_1" + }, + "properties": { + "aoe": 16 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Tempest", + "cost": "0", + "multipliers": [30, 10, 0, 0, 0, 10] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Tempest Total Damage", + "cost": "0", + "hits": { + "Tempest": 3 + } + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Total Damage", + "cost": "0", + "hits": { + "Tempest": 3 + } + } + ] + }, + + { + "display_name": "Spirit of the Rabbit", + "desc": "Reduce the Mana cost of Charge and increase your Walk Speed by +20%", + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": ["Tempest", "Whirlwind Strike"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 28, + "col": 4, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + }, + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "spd", + "value": 20 + } + ] + } + ] + }, + + { + "display_name": "Massacre", + "desc": "While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar", + "archetype": "Fallen", + "archetype_req": 5, + "parents": ["Tempest", "Massive Bash"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 29, + "col": 1, + "icon": "node_1" + }, + "properties": { + }, + "effects": [ + + ] + }, + + { + "display_name": "Axe Kick", + "desc": "Increase the damage of Uppercut, but also increase its mana cost", + "archetype": "", + "archetype_req": 0, + "parents": ["Tempest", "Spirit of the Rabbit"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 3, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": 10, + "multipliers": [100, 0, 0, 0, 0, 0] + } + ] + }, + + { + "display_name": "Radiance", + "desc": "Bash will buff your allies' positive IDs. (15s Cooldown)", + "archetype": "Paladin", + "archetype_req": 2, + "parents": ["Spirit of the Rabbit", "Cheaper Bash 2"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 29, + "col": 5, + "icon": "node_2" + }, + "properties": { + "cooldown": 15 + }, + "effects": [ + + ] + }, + + { + "display_name": "Cheaper Bash 2", + "desc": "Reduce the Mana cost of Bash", + "archetype": "", + "archetype_req": 0, + "parents": ["Radiance", "Shield Strike", "Sparkling Hope"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 7, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ] + }, + + { + "display_name": "Cheaper War Scream", + "desc": "Reduce the Mana cost of War Scream", + "archetype": "", + "archetype_req": 0, + "parents": ["Massive Bash"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 0, + "icon": "node_0" + }, + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ] + }, + + { + "display_name": "Discombobulate", + "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", + "archetype": "Battle Monk", + "archetype_req": 12, + "parents": ["Cyclone"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 31, + "col": 2, + "icon": "node_3" + }, + "properties": { + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Hits dealt", + "output": { + "type": "stat", + "name": "rainrawButDifferent" + }, + "scaling": [2], + "max": 50 + } + ] + }, + + { + "display_name": "Thunderclap", + "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", + "archetype": "Battle Monk", + "archetype_req": 8, + "parents": ["Cyclone"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 5, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + }, + { + "type": "raw_stat", + "bonuses": [{ + "type": "prop", + "abil_name": "Bash", + "name": "aoe", + "value": 3 + }] + } + ] + }, + + { + "display_name": "Cyclone", + "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Spirit of the Rabbit"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 4, + "icon": "node_1" + }, + "properties": { + "aoe": 4, + "duration": 20 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Cyclone", + "cost": 0, + "multipliers": [10, 0, 0, 0, 5, 10] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Cyclone Total Damage", + "cost": 0, + "hits": { + "Cyclone": 40 + } + + } + ] + }, + + { + "display_name": "Second Chance", + "desc": "When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)", + "archetype": "Paladin", + "archetype_req": 12, + "parents": ["Cheaper Bash 2"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 7, + "icon": "node_3" + }, + "properties": {}, + "effects": [] + }, + + { + "display_name": "Blood Pact", + "desc": "If you do not have enough mana to cast a spell, spend health instead (1% health per mana)", + "archetype": "", + "archetype_req": 10, + "parents": ["Cheaper War Scream"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 34, + "col": 1, + "icon": "node_3" + }, + "properties": {}, + "effects": [] + }, + + { + "display_name": "Haemorrhage", + "desc": "Reduce Blood Pact's health cost. (0.5% health per mana)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Blood Pact"], + "dependencies": ["Blood Pact"], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 2, + "icon": "node_1" + }, + "properties": {}, + "effects": [] + }, + + { + "display_name": "Brink of Madness", + "desc": "If your health is 25% full or less, gain +40% Resistance", + "archetype": "", + "archetype_req": 0, + "parents": ["Blood Pact", "Cheaper Uppercut 2"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 35, + "col": 4, + "icon": "node_2" + }, + "properties": {}, + "effects": [] + }, + + { + "display_name": "Cheaper Uppercut 2", + "desc": "Reduce the Mana cost of Uppercut", + "archetype": "", + "archetype_req": 0, + "parents": ["Second Chance", "Brink of Madness"], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 6, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ] + }, + + { + "display_name": "Martyr", + "desc": "When you receive a fatal blow, all nearby allies become invincible", + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Second Chance"], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 35, + "col": 8, + "icon": "node_1" + }, + "properties": { + "duration": 3, + "aoe": 12 + }, + "effects": [] + } + ], +} + +const atree_example = [ + { + "title": "skill", + "desc": "desc", + "image": "../media/atree/node.png", + "connector": false, + "row": 5, + "col": 3, + }, + { + "image": "../media/atree/connect_angle.png", + "connector": true, + "rotate": 270, + "row": 4, + "col": 3, + }, + { + "title": "skill2", + "desc": "desc", + "image": "../media/atree/node.png", + "connector": false, + "row": 0, + "col": 2 + }, + { + "image": "../media/atree/connect_line.png", + "connector": true, + "rotate": 0, + "row": 1, + "col": 2 + }, + { + "title": "skill3", + "desc": "desc", + "image": "../media/atree/node.png", + "connector": false, + "row": 2, + "col": 2 + }, + { + "image": "../media/atree/connect_line.png", + "connector": true, + "rotate": 90, + "row": 2, + "col": 3 + }, + { + "title": "skill4", + "desc": "desc", + "image": "../media/atree/node.png", + "connector": false, + "row": 2, + "col": 4 + }, + { + "image": "../media/atree/connect_line.png", + "connector": true, + "rotate": 0, + "row": 3, + "col": 2 + }, + { + "title": "skill5", + "desc": "desc", + "image": "../media/atree/node.png", + "connector": false, + "row": 4, + "col": 2 + }, +]; diff --git a/js/atree_constants_str_old_min.js b/js/atree_constants_str_old_min.js new file mode 100644 index 0000000..73d3e29 --- /dev/null +++ b/js/atree_constants_str_old_min.js @@ -0,0 +1 @@ +const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:["Power Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}]},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:["Heart Shatter"],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}]},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}]},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:["Phantom Ray","Fire Mastery","Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}]},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:["Fire Creep","Earth Mastery"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}]},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:["Thunder Mastery","Arrow Rain"],dependencies:["Arrow Storm"],blockers:["Phantom Ray"],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}]},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:["Double Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}]},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:["Triple Shots","Frenzy"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}]},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}]},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:["Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}]},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:["Guardian Angels","Cheaper Arrow Storm"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}]},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:["Focus","More Shields","Cheaper Arrow Storm"],dependencies:[],blockers:["Escape Artist"],cost:2,display:{row:21,col:5},properties:{range:20},effects:[]},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:["Grappling Hook","More Shields"],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:["More Focus","Traveler"],dependencies:["Focus"],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}]},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:["Refined Gunpowder","Traveler"],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}]},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:["Twain's Arc"],dependencies:["Fire Creep"],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}]},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:["Refined Gunpowder","Homing Shots"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[]},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:["Twain's Arc","Better Arrow Shield","Homing Shots"],dependencies:["Arrow Bomb"],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:["More Traps","Better Arrow Shield"],dependencies:["Fire Creep"],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}]},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:["Better Guardian Angels","Leap"],dependencies:[],blockers:["Grappling Hook"],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}]},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:["Shocking Bomb","Better Arrow Shield","Cheaper Arrow Storm (2)"],dependencies:["Focus"],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}]},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:["Initiator","Cheaper Arrow Storm (2)"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:["Precise Shot","Escape Artist"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}]},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:["Shrapnel Bomb"],dependencies:["Fierce Stomp"],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}]},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:["Cheaper Arrow Shield"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}]},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:["Cheaper Escape (2)"],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}]},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}]},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:["Geyser Stomp","More Focus (2)"],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3}},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:["Snow Storm"],dependencies:["Guardian Angels"],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}]},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:["Grape Bomb","Cheaper Arrow Bomb (2)"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}]},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:["Arrow Bomb"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}]},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Grappling Hook","Windstorm","Focus"],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Arrow Storm","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:["Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Escape","Thunder Mastery","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Thunder Mastery","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:["Grappling Hook","Basaltic Trap"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2}},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:["Windy Feet"],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}]},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}]},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:["Bouncing Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2}},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:["Mana Trap","Shocking Bomb","Twain's Arc"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}]},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:["Leap","Homing Shots"],dependencies:["Leap"],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1}},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:["Escape Artist","Homing Shots"],dependencies:["Guardian Angels"],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}]},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Initiator","Mana Trap"],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Better Guardian Angels","Cheaper Arrow Shield","Arrow Hurricane"],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}]},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:["Precise Shot","Initiator"],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:["Cheaper Arrow Storm (2)","Initiator"],dependencies:["Arrow Bomb"],blockers:[],cost:1,display:{row:33,col:6},properties:{}},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Call of the Hound","Decimator"],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:["Cheaper Escape (2)"],dependencies:["Grappling Hook"],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8}},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["More Focus (2)","Minefield"],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:["More Shields"],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}]},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:["Leap","Shocking Bomb"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[]},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:["Arrow Hurricane","Precise Shot"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}]},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:["Geyser Stomp"],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[]},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Power Shots"],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Rain","Frenzy"],dependencies:["Double Shots"],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Double Shots"],cost:1,display:{row:7,col:6},properties:{},effects:[]},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:["Phantom Ray"],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:3}]},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Storm","Grappling Hook"],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:5}]},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Crepuscular Ray","Snow Storm"],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:7}]},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:["Refined Gunpowder","Twain's Arc"],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}]},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:["More Shields"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[]},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Patient Hunter"],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[]},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:["Triple Shots","Nimble String"],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}]},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:["Water Mastery","Fire Creep"],dependencies:["Arrow Storm"],blockers:["Windstorm","Nimble String","Arrow Hurricane"],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}]},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:["Nimble String","Air Mastery"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}]},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Shield"],dependencies:["Phantom Ray"],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}]}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}]},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bash"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}]},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}]},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:["Double Bash"],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}]},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Tougher Skin"],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}]},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Vehement"],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}]},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:["Vehement"],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}]},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:["Uppercut","War Scream"],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:["Tougher Skin"],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}]},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Charge","Thunder Mastery","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["War Scream","Thunder Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:["War Scream"],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:["Earth Mastery","Fireworks"],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}]},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:["Thunder Mastery","Quadruple Bash"],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}]},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:["Water Mastery"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}]},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:["Air Mastery","Flaming Uppercut"],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}]},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:["Fire Mastery","Flyby Jab"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}]},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:["Flyby Jab","Flaming Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}]},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:["Counter"],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[]},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:["Half-Moon Swipe"],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}]},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:["Iron Lungs"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[]},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:["Quadruple Bash","Fireworks"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}]},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bak'al's Grasp","Cheaper Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:["Spear Proficiency 2","Aerodynamics","Counter"],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Uppercut","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[]},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:["Aerodynamics","Mantle of the Bovemists"],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Cheaper Uppercut","Spear Proficiency 2"],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}]},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:["Aerodynamics","Provoke"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}]},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:["Spear Proficiency 2"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"dmgPct"},scaling:[2],max:200}]},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:["Cheaper Uppercut","Stronger Mantle"],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}]},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:["Manachism","Flying Kick"],dependencies:["Mantle of the Bovemists"],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[]},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:["Stronger Mantle","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[]},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:["Enraged Blow","Ragnarokkr"],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}]},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:["Boiling Blood","Flying Kick"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}]},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:["Flying Kick","Stronger Mantle","Burning Heart"],dependencies:["Counter"],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[]},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:["Ambidextrous","Stronger Bash"],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}]},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:["Burning Heart","Manachism"],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}]},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:["Ragnarokkr","Boiling Blood"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:["Ragnarokkr"],dependencies:["Fireworks"],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}]},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:["Ambidextrous","Burning Heart"],dependencies:["Flying Kick"],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}]},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:["Burning Heart","Stronger Bash"],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:["Boiling Blood","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}]},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:["Whirlwind Strike","Uncontainable Corruption"],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}]},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:["Ambidextrous","Radiant Devotee"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}]},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:["Rejuvenating Skin"],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}]},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:["Uncontainable Corruption","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[]},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin","Sparkling Hope"],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}]},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin"],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}]},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:["Tempest","Uncontainable Corruption"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}]},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:["Massive Bash","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}]},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:["Tempest","Whirlwind Strike"],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}]},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:["Tempest","Massive Bash"],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:["Tempest","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}]},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:["Spirit of the Rabbit","Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[]},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Radiance","Shield Strike","Sparkling Hope"],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:["Massive Bash"],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}]},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}]},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:["Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}]},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:["Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:["Cheaper War Scream"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[]},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:["Blood Pact"],dependencies:["Blood Pact"],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[]},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:["Blood Pact","Cheaper Uppercut 2"],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[]},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:["Second Chance","Brink of Madness"],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:["Second Chance"],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[]}]},atree_example=[{title:"skill",desc:"desc",image:"../media/atree/node.png",connector:!1,row:5,col:3},{image:"../media/atree/connect_angle.png",connector:!0,rotate:270,row:4,col:3},{title:"skill2",desc:"desc",image:"../media/atree/node.png",connector:!1,row:0,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:1,col:2},{title:"skill3",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:90,row:2,col:3},{title:"skill4",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:4},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:3,col:2},{title:"skill5",desc:"desc",image:"../media/atree/node.png",connector:!1,row:4,col:2},] \ No newline at end of file diff --git a/js/display_atree.js b/js/display_atree.js index d97ca36..bbdc014 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -17,7 +17,7 @@ function construct_AT(elem, tree) { atree_map = new Map(); atree_connectors_map = new Map() for (let i of tree) { - atree_map.set(i.display_name, {display: i.display, parents: i.parents, connectors: new Map(), active: false}); + atree_map.set(i.id, {display: i.display, parents: i.parents, connectors: new Map(), active: false}); } for (let i = 0; i < tree.length; i++) { @@ -27,7 +27,7 @@ function construct_AT(elem, tree) { let missing_rows = [node.display.row]; for (let parent of node.parents) { - missing_rows.push(tree.find(object => {return object.display_name === parent;}).display.row); + missing_rows.push(tree.find(object => {return object.id === parent;}).display.row); } for (let missing_row of missing_rows) { if (document.getElementById("atree-row-" + missing_row) == null) { @@ -57,7 +57,7 @@ function construct_AT(elem, tree) { // create connectors based on parent location for (let parent of node.parents) { - atree_map.get(node.display_name).connectors.set(parent, []); + atree_map.get(node.id).connectors.set(parent, []); let parent_node = atree_map.get(parent); @@ -67,8 +67,8 @@ function construct_AT(elem, tree) { for (let i = node.display.row - 1; i > parent_node.display.row; i--) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; - atree_map.get(node.display_name).connectors.get(parent).push(i + "," + node.display.col); - atree_connectors_map.get(i + "," + node.display.col).push({connector: connector, type: "line", owner: [node.display_name, parent]}); + atree_map.get(node.id).connectors.get(parent).push(i + "," + node.display.col); + atree_connectors_map.get(i + "," + node.display.col).push({connector: connector, type: "line", owner: [node.id, parent]}); resolve_connector(i + "," + node.display.col, node); } // connect horizontally @@ -78,8 +78,8 @@ function construct_AT(elem, tree) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; connector.classList.add("rotate-90"); - atree_map.get(node.display_name).connectors.get(parent).push(parent_node.display.row + "," + i); - atree_connectors_map.get(parent_node.display.row + "," + i).push({connector: connector, type: "line", owner: [node.display_name, parent]}); + atree_map.get(node.id).connectors.get(parent).push(parent_node.display.row + "," + i); + atree_connectors_map.get(parent_node.display.row + "," + i).push({connector: connector, type: "line", owner: [node.id, parent]}); resolve_connector(parent_node.display.row + "," + i, node); } @@ -88,8 +88,8 @@ function construct_AT(elem, tree) { if (parent_node.display.row != node.display.row && parent_node.display.col != node.display.col) { let connector = connect_elem.cloneNode(); connector.style.backgroundImage = "url('../media/atree/connect_angle.png')"; - atree_map.get(node.display_name).connectors.get(parent).push(parent_node.display.row + "," + node.display.col); - atree_connectors_map.get(parent_node.display.row + "," + node.display.col).push({connector: connector, type: "angle", owner: [node.display_name, parent]}); + atree_map.get(node.id).connectors.get(parent).push(parent_node.display.row + "," + node.display.col); + atree_connectors_map.get(parent_node.display.row + "," + node.display.col).push({connector: connector, type: "angle", owner: [node.id, parent]}); if (parent_node.display.col > node.display.col) { connector.classList.add("rotate-180"); } @@ -147,7 +147,7 @@ function construct_AT(elem, tree) { node_tooltip = active_tooltip.cloneNode(true); - active_tooltip.id = "atree-ab-" + node.display_name.replaceAll(" ", ""); + active_tooltip.id = "atree-ab-" + node.id; node_tooltip.style.position = "absolute"; node_tooltip.style.zIndex = "100"; @@ -157,7 +157,7 @@ function construct_AT(elem, tree) { node_elem.addEventListener('click', function(e) { if (e.target !== this) {return;}; - let tooltip = document.getElementById("atree-ab-" + node.display_name.replaceAll(" ", "")); + let tooltip = document.getElementById("atree-ab-" + node.id); if (tooltip.style.display == "block") { tooltip.style.display = "none"; this.classList.remove("atree-selected"); @@ -222,6 +222,7 @@ function atree_same_row(node) { // draw the connector onto the screen function atree_render_connection() { for (let i of atree_connectors_map.keys()) { + if (document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].children.length != 0) {continue;} if (atree_connectors_map.get(i).length != 0) { document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].appendChild(atree_connectors_map.get(i)[0].connector); }; @@ -230,10 +231,10 @@ function atree_render_connection() { // toggle the state of a node. function atree_toggle_state(node) { - if (atree_map.get(node.display_name).active) { - atree_map.get(node.display_name).active = false; + if (atree_map.get(node.id).active) { + atree_map.get(node.id).active = false; } else { - atree_map.get(node.display_name).active = true; + atree_map.get(node.id).active = true; }; }; From af3c76681bcace86bd7e28d31f93983e54a66058 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 19:46:04 +0700 Subject: [PATCH 37/68] fix: cosmetic defect on tri connector --- js/display_atree.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/display_atree.js b/js/display_atree.js index f95d1a0..cb5a723 100644 --- a/js/display_atree.js +++ b/js/display_atree.js @@ -289,6 +289,7 @@ function atree_get_state(connector) { } else if (!connector_state[1]) { connector_state[1] = 0; } + continue; } if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { if (state) { @@ -296,6 +297,7 @@ function atree_get_state(connector) { } else if (!connector_state[0]) { connector_state[0] = 0; } + continue; } if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { if (state) { @@ -303,6 +305,7 @@ function atree_get_state(connector) { } else if (!connector_state[2]) { connector_state[2] = 0; } + continue; } if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { if (state) { @@ -310,6 +313,7 @@ function atree_get_state(connector) { } else if (!connector_state[3]) { connector_state[3] = 0; }; + continue; }; }; return connector_state; From 18524b44fa70ec8c62f80f9414cdd89b1a1dc6b4 Mon Sep 17 00:00:00 2001 From: reschan Date: Sun, 26 Jun 2022 19:47:12 +0700 Subject: [PATCH 38/68] atree name to id json --- js/atree-ids.json | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 js/atree-ids.json diff --git a/js/atree-ids.json b/js/atree-ids.json new file mode 100644 index 0000000..d04db13 --- /dev/null +++ b/js/atree-ids.json @@ -0,0 +1,137 @@ +{ + "Arrow Shield": 0, + "Escape": 1, + "Arrow Bomb": 2, + "Heart Shatter": 3, + "Fire Creep": 4, + "Bryophyte Roots": 5, + "Nimble String": 6, + "Arrow Storm": 7, + "Guardian Angels": 8, + "Windy Feet": 9, + "Basaltic Trap": 10, + "Windstorm": 11, + "Grappling Hook": 12, + "Implosion": 13, + "Twain's Arc": 14, + "Fierce Stomp": 15, + "Scorched Earth": 16, + "Leap": 17, + "Shocking Bomb": 18, + "Mana Trap": 19, + "Escape Artist": 20, + "Initiator": 21, + "Call of the Hound": 22, + "Arrow Hurricane": 23, + "Geyser Stomp": 24, + "Crepuscular Ray": 25, + "Grape Bomb": 26, + "Tangled Traps": 27, + "Snow Storm": 28, + "All-Seeing Panoptes": 29, + "Minefield": 30, + "Bow Proficiency I": 31, + "Cheaper Arrow Bomb": 32, + "Cheaper Arrow Storm": 33, + "Cheaper Escape": 34, + "Earth Mastery": 82, + "Thunder Mastery": 83, + "Water Mastery": 84, + "Air Mastery": 85, + "Fire Mastery": 86, + "More Shields": 40, + "Stormy Feet": 41, + "Refined Gunpowder": 42, + "More Traps": 43, + "Better Arrow Shield": 44, + "Better Leap": 45, + "Better Guardian Angels": 46, + "Cheaper Arrow Storm (2)": 47, + "Precise Shot": 48, + "Cheaper Arrow Shield": 49, + "Rocket Jump": 50, + "Cheaper Escape (2)": 51, + "Stronger Hook": 52, + "Cheaper Arrow Bomb (2)": 53, + "Bouncing Bomb": 54, + "Homing Shots": 55, + "Shrapnel Bomb": 56, + "Elusive": 57, + "Double Shots": 58, + "Triple Shots": 59, + "Power Shots": 60, + "Focus": 61, + "More Focus": 62, + "More Focus (2)": 63, + "Traveler": 64, + "Patient Hunter": 65, + "Stronger Patient Hunter": 66, + "Frenzy": 67, + "Phantom Ray": 68, + "Arrow Rain": 69, + "Decimator": 70, + "Bash": 71, + "Spear Proficiency 1": 72, + "Cheaper Bash": 73, + "Double Bash": 74, + "Charge": 75, + "Heavy Impact": 76, + "Vehement": 77, + "Tougher Skin": 78, + "Uppercut": 79, + "Cheaper Charge": 80, + "War Scream": 81, + "Quadruple Bash": 87, + "Fireworks": 88, + "Half-Moon Swipe": 89, + "Flyby Jab": 90, + "Flaming Uppercut": 91, + "Iron Lungs": 92, + "Generalist": 93, + "Counter": 94, + "Mantle of the Bovemists": 95, + "Bak'al's Grasp": 96, + "Spear Proficiency 2": 97, + "Cheaper Uppercut": 98, + "Aerodynamics": 99, + "Provoke": 100, + "Precise Strikes": 101, + "Air Shout": 102, + "Enraged Blow": 103, + "Flying Kick": 104, + "Stronger Mantle": 105, + "Manachism": 106, + "Boiling Blood": 107, + "Ragnarokkr": 108, + "Ambidextrous": 109, + "Burning Heart": 110, + "Stronger Bash": 111, + "Intoxicating Blood": 112, + "Comet": 113, + "Collide": 114, + "Rejuvenating Skin": 115, + "Uncontainable Corruption": 116, + "Radiant Devotee": 117, + "Whirlwind Strike": 118, + "Mythril Skin": 119, + "Armour Breaker": 120, + "Shield Strike": 121, + "Sparkling Hope": 122, + "Massive Bash": 123, + "Tempest": 124, + "Spirit of the Rabbit": 125, + "Massacre": 126, + "Axe Kick": 127, + "Radiance": 128, + "Cheaper Bash 2": 129, + "Cheaper War Scream": 130, + "Discombobulate": 131, + "Thunderclap": 132, + "Cyclone": 133, + "Second Chance": 134, + "Blood Pact": 135, + "Haemorrhage": 136, + "Brink of Madness": 137, + "Cheaper Uppercut 2": 138, + "Martyr": 139 +} \ No newline at end of file From a99f164a29ddf7dc9864aee030e99846cf1cf99c Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 06:13:05 -0700 Subject: [PATCH 39/68] Clean up js files rename display_atree -> atree remove d3_export --- builder/doc.html | 3 +-- builder/index.html | 2 +- js/{display_atree.js => atree.js} | 0 js/d3_export.js | 30 ------------------------------ js/damage_calc.js | 2 -- js/render_compute_graph.js | 29 +++++++++++++++++++++++++++++ 6 files changed, 31 insertions(+), 35 deletions(-) rename js/{display_atree.js => atree.js} (100%) delete mode 100644 js/d3_export.js diff --git a/builder/doc.html b/builder/doc.html index 23a0216..579bc38 100644 --- a/builder/doc.html +++ b/builder/doc.html @@ -1420,7 +1420,7 @@ - + @@ -1433,7 +1433,6 @@ savelink - diff --git a/builder/index.html b/builder/index.html index cd2d180..2c3ceda 100644 --- a/builder/index.html +++ b/builder/index.html @@ -1422,7 +1422,7 @@ - + diff --git a/js/display_atree.js b/js/atree.js similarity index 100% rename from js/display_atree.js rename to js/atree.js diff --git a/js/d3_export.js b/js/d3_export.js deleted file mode 100644 index 4e92c07..0000000 --- a/js/d3_export.js +++ /dev/null @@ -1,30 +0,0 @@ -// http://bl.ocks.org/rokotyan/0556f8facbaf344507cdc45dc3622177 - -// Set-up the export button -function set_export_button(svg, button_id, output_id) { - d3.select('#'+button_id).on('click', function(){ - //get svg source. - var serializer = new XMLSerializer(); - var source = serializer.serializeToString(svg.node()); - console.log(source); - - source = source.replace(/^$/, ''); - //add name spaces. - if(!source.match(/^]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){ - source = source.replace(/^]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){ - source = source.replace(/^$/, ''); + //add name spaces. + if(!source.match(/^]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){ + source = source.replace(/^]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){ + source = source.replace(/^ Date: Sun, 26 Jun 2022 11:18:20 -0700 Subject: [PATCH 40/68] prevent node unrendering --- js/atree.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/atree.js b/js/atree.js index 2daa244..f70242d 100644 --- a/js/atree.js +++ b/js/atree.js @@ -207,7 +207,6 @@ function construct_AT(elem, tree) { if (tooltip.style.display == "block") { tooltip.style.display = "none"; this.classList.remove("atree-selected"); - this.style.backgroundImage = ''; document.getElementById("active_AP_cost").textContent = parseInt(document.getElementById("active_AP_cost").textContent) - node.cost; } else { From 8ff0afa685a85c90d93d0c564e5a58283c45edb2 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 16:49:35 -0700 Subject: [PATCH 41/68] Begin atree integration also don't re-render the entire thing every time something changes -- local updates --- js/atree.js | 455 +++++++++++++++++++++------------- js/atree_constants.js | 16 +- js/atree_constants_min.js | 2 +- js/atree_constants_str_old.js | 18 +- js/builder_graph.js | 17 +- 5 files changed, 299 insertions(+), 209 deletions(-) diff --git a/js/atree.js b/js/atree.js index cb5a723..eb221e7 100644 --- a/js/atree.js +++ b/js/atree.js @@ -1,108 +1,199 @@ -let atree_map; -let atree_head; -let atree_connectors_map; -let atree_active_connections = []; -function construct_AT(elem, tree) { +let abil_points_current; + +/** + * Update ability tree internal representation. (topologically sorted node list) + * + * Signature: AbilityTreeUpdateNode(build: Build) => ATree + */ +const atree_node = new (class extends ComputeNode { + constructor() { super('builder-atree-update'); } + + compute_func(input_map) { + if (input_map.size !== 1) { throw "AbilityTreeUpdateNode accepts exactly one input (build)"; } + const [build] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element + + const atree_raw = atrees[wep_to_class.get(build.weapon.statMap.get('type'))]; + if (!atree_raw) return null; + + let atree_map = new Map(); + let atree_head; + for (const i of atree_raw) { + atree_map.set(i.id, {children: [], node: i}); + if (i.parents.length == 0) { + // Assuming there is only one head. + atree_head = atree_map.get(i.id); + } + } + for (const i of atree_raw) { + let node = atree_map.get(i.id); + let parents = []; + for (const parent_id of node.node.parents) { + let parent_node = atree_map.get(parent_id); + parent_node.children.push(node); + parents.push(parent_node); + } + node.parents = parents; + } + + let atree_topo_sort = []; + topological_sort_tree(atree_head, atree_topo_sort, new Map()); + atree_topo_sort.reverse(); + return atree_topo_sort; + } +})(); + +/** + * Display ability tree from topologically sorted list. + * + * Signature: AbilityTreeRenderNode(atree: ATree) => null + */ +const atree_render = new (class extends ComputeNode { + constructor() { super('builder-atree-render'); this.fail_cb = true; } + + compute_func(input_map) { + if (input_map.size !== 1) { throw "AbilityTreeRenderNode accepts exactly one input (atree)"; } + const [atree] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element + //as of now, we NEED to have the dropdown tab visible/not hidden in order to properly display atree stuff. + // TODO: FIXME! this is a side effect of `px` based rendering. + if (!document.getElementById("toggle-atree").classList.contains("toggleOn")) { + toggle_tab('atree-dropdown'); + toggleButton('toggle-atree'); + } + + //for some reason we have to cast to string + if (atree) { render_AT(document.getElementById("atree-ui"), atree); } + + if (document.getElementById("toggle-atree").classList.contains("toggleOn")) { + toggle_tab('atree-dropdown'); + toggleButton('toggle-atree'); + } + } +})(); + +atree_render.link_to(atree_node); + +/** + * Create a reverse topological sort of the tree in the result list. + * + * https://en.wikipedia.org/wiki/Topological_sorting + * @param tree: Root of tree to sort + * @param res: Result list (reverse topological order) + * @param mark_state: Bookkeeping. Call with empty Map() + */ +function topological_sort_tree(tree, res, mark_state) { + const state = mark_state.get(tree); + if (state === undefined) { + // unmarked. + mark_state.set(tree, false); // temporary mark + for (const child of tree.children) { + topological_sort_tree(child, res, mark_state); + } + mark_state.set(tree, true); // permanent mark + res.push(tree); + } + // these cases are not needed. Case 1 does nothing, case 2 should never happen. + // else if (state === true) { + // // permanent mark. + // return; + // } + // else if (state === false) { + // // temporary mark. + // } +} + +function render_AT(elem, tree) { console.log("constructing ability tree UI"); document.getElementById("atree-active").innerHTML = ""; //reset all atree actives - should be done in a more general way later elem.innerHTML = ""; //reset the atree in the DOM - - if (tree === undefined) {return false;} // add in the "Active" title to atree let active_row = document.createElement("div"); active_row.classList.add("row", "item-title", "mx-auto", "justify-content-center"); - active_row.textContent = "Active:"; + active_row.textContent = "Active: 0/45 AP"; + abil_points_current = 0; document.getElementById("atree-active").appendChild(active_row); - atree_map = new Map(); - atree_connectors_map = new Map() - for (let i of tree) { - atree_map.set(i.id, {display: i.display, parents: i.parents, connectors: new Map(), active: false}); + let atree_map = new Map(); + let atree_connectors_map = new Map() + let max_row = 0; + for (const i of tree) { + atree_map.set(i.node.id, {node: i.node, connectors: new Map(), active: false}); + if (i.node.display.row > max_row) { + max_row = i.node.display.row; + } + } + // Copy graph structure. + for (const i of tree) { + let node_wrapper = atree_map.get(i.node.id); + node_wrapper.parents = []; + node_wrapper.children = []; + for (const parent of i.parents) { + node_wrapper.parents.push(atree_map.get(parent.node.id)); + } + for (const child of i.children) { + node_wrapper.children.push(atree_map.get(child.node.id)); + } } - for (let i = 0; i < tree.length; i++) { - let node = tree[i]; - - // create rows if not exist - let missing_rows = [node.display.row]; + // Setup grid. + for (let j = 0; j <= max_row; j++) { + let row = document.createElement('div'); + row.classList.add("row"); + row.id = "atree-row-" + j; + //was causing atree rows to be 0 height + // TODO: do this more dynamically + row.style.minHeight = elem.scrollWidth / 9 + "px"; + //row.style.minHeight = elem.getBoundingClientRect().width / 9 + "px"; - if (node.parents.length == 0) { - // Assuming there is only one head. - atree_head = node; - } - - for (let parent of node.parents) { - missing_rows.push(tree.find(object => {return object.id === parent;}).display.row); - } - for (let missing_row of missing_rows) { - if (document.getElementById("atree-row-" + missing_row) == null) { - for (let j = 0; j <= missing_row; j++) { - if (document.getElementById("atree-row-" + j) == null) { - let row = document.createElement('div'); - row.classList.add("row"); - row.id = "atree-row-" + j; - //was causing atree rows to be 0 height - row.style.minHeight = elem.scrollWidth / 9 + "px"; - //row.style.minHeight = elem.getBoundingClientRect().width / 9 + "px"; - - for (let k = 0; k < 9; k++) { - col = document.createElement('div'); - col.classList.add('col', 'px-0'); - col.style.minHeight = elem.scrollWidth / 9 + "px"; - row.appendChild(col); - - atree_connectors_map.set(j + "," + k, []) - }; - elem.appendChild(row); - }; - }; - }; + for (let k = 0; k < 9; k++) { + col = document.createElement('div'); + col.classList.add('col', 'px-0'); + col.style.minHeight = elem.scrollWidth / 9 + "px"; + row.appendChild(col); } + elem.appendChild(row); + } + for (const _node of tree) { + let node_wrap = atree_map.get(_node.node.id); + let node = _node.node; // create connectors based on parent location - for (let parent of node.parents) { - atree_map.get(node.id).connectors.set(parent, []); + for (let parent of node_wrap.parents) { + node_wrap.connectors.set(parent, []); - let parent_node = atree_map.get(parent); + let parent_node = parent.node; + const parent_id = parent_node.id; let connect_elem = document.createElement("div"); connect_elem.style = "background-size: cover; width: 100%; height: 100%;"; // connect up for (let i = node.display.row - 1; i > parent_node.display.row; i--) { let connector = connect_elem.cloneNode(); - connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; - atree_map.get(node.id).connectors.get(parent).push(i + "," + node.display.col); - atree_connectors_map.get(i + "," + node.display.col).push({connector: connector, type: "line", owner: [node.id, parent]}); - resolve_connector(i + "," + node.display.col, node); + node_wrap.connectors.get(parent).push(i + "," + node.display.col); + resolve_connector(atree_connectors_map, i + "," + node.display.col, {connector: connector, connections: [0, 0, 1, 1]}); } // connect horizontally let min = Math.min(parent_node.display.col, node.display.col); let max = Math.max(parent_node.display.col, node.display.col); for (let i = min + 1; i < max; i++) { let connector = connect_elem.cloneNode(); - connector.style.backgroundImage = "url('../media/atree/connect_line.png')"; - connector.classList.add("rotate-90"); - atree_map.get(node.id).connectors.get(parent).push(parent_node.display.row + "," + i); - atree_connectors_map.get(parent_node.display.row + "," + i).push({connector: connector, type: "line", owner: [node.id, parent]}); - resolve_connector(parent_node.display.row + "," + i, node); + node_wrap.connectors.get(parent).push(parent_node.display.row + "," + i); + resolve_connector(atree_connectors_map, parent_node.display.row + "," + i, {connector: connector, connections: [1, 1, 0, 0]}); } // connect corners - if (parent_node.display.row != node.display.row && parent_node.display.col != node.display.col) { let connector = connect_elem.cloneNode(); - connector.style.backgroundImage = "url('../media/atree/connect_angle.png')"; - atree_map.get(node.id).connectors.get(parent).push(parent_node.display.row + "," + node.display.col); - atree_connectors_map.get(parent_node.display.row + "," + node.display.col).push({connector: connector, type: "angle", owner: [node.id, parent]}); + node_wrap.connectors.get(parent).push(parent_node.display.row + "," + node.display.col); + let connections = [0, 0, 0, 1]; if (parent_node.display.col > node.display.col) { - connector.classList.add("rotate-180"); + connections[1] = 1; } else {// if (parent_node.display.col < node.display.col && (parent_node.display.row != node.display.row)) { - connector.classList.add("rotate-270"); + connections[0] = 1; } - resolve_connector(parent_node.display.row + "," + node.display.col, node); + resolve_connector(atree_connectors_map, parent_node.display.row + "," + node.display.col, {connector: connector, connections: connections}); } } @@ -167,81 +258,96 @@ function construct_AT(elem, tree) { if (tooltip.style.display == "block") { tooltip.style.display = "none"; this.classList.remove("atree-selected"); + abil_points_current -= node.cost; } else { tooltip.style.display = "block"; this.classList.add("atree-selected"); + abil_points_current += node.cost; }; - atree_toggle_state(node); - atree_update_connector(); + active_row.textContent = "Active: "+abil_points_current+"/45 AP"; + atree_toggle_state(atree_connectors_map, node_wrap); }); document.getElementById("atree-row-" + node.display.row).children[node.display.col].appendChild(node_elem); }; - - atree_render_connection(); + console.log(atree_connectors_map); + atree_render_connection(atree_connectors_map); }; // resolve connector conflict, when they occupy the same cell. -function resolve_connector(pos, node) { - if (atree_connectors_map.get(pos).length < 2) {return false;} - - let line = false; - let angle = false; - let t = false; - let owners = []; - for (let i of atree_connectors_map.get(pos)) { - if (i.type == "line") { - line = true; - } else if (i.type == "angle") { - angle = true; - } else if (i.type == "t") { - t = true; - } - owners = owners.concat(i.owner); +function resolve_connector(atree_connectors_map, pos, new_connector) { + if (!atree_connectors_map.has(pos)) { + atree_connectors_map.set(pos, new_connector); + return; } - - owners = [...new Set(owners)]; - - let connect_elem = document.createElement("div"); - - if ((line && angle)) { - connect_elem.style = "background-image: url('../media/atree/connect_t.png'); background-size: cover; width: 100%; height: 100%;"; - atree_connectors_map.set(pos, [{connector: connect_elem, type: "t", owner: owners, connector_state: {up: 0, left: 0, right: 0, down: 0}}]); + let existing = atree_connectors_map.get(pos).connections; + for (let i = 0; i < 4; ++i) { + existing[i] += new_connector.connections[i]; } - if (node.parents.length == 3 && t && atree_same_row(node)) { - connect_elem.style = "background-image: url('../media/atree/connect_c.png'); background-size: cover; width: 100%; height: 100%;"; - atree_connectors_map.set(pos, [{connector: connect_elem, type: "c", owner: owners, connector_state: {up: 0, left: 0, right: 0, down: 0}}]); - } - // override the conflict with the first children - atree_connectors_map.set(pos, [atree_connectors_map.get(pos)[0]]); - atree_connectors_map.get(pos)[0].owner = owners; } -// check if a node doesn't have same row w/ its parents (used to solve conflict) -function atree_same_row(node) { - for (let i of node.parents) { - if (node.display.row == atree_map.get(i).display.row) { return false; } - }; - return true; -}; +function set_connector_type(connector_info) { // left right up down + const connections = connector_info.connections; + const connector_elem = connector_info.connector; + if (connections[2]) { + if (connections[0]) { + connector_info.type = 'c'; // cross + return; + } + connector_info.type = 'line'; // vert line + return; + } + if (connections[3]) { // if down: + if (connections[0] && connections[1]) { + connector_info.type = 't'; // all 3 t + return; + } + connector_info.type = 'angle'; // elbow + if (connections[1]) { + connector_elem.classList.add("rotate-180"); + } + else { + connector_elem.classList.add("rotate-270"); + } + return; + } + connector_info.type = 'line'; // horiz line + connector_elem.classList.add("rotate-90"); +} // draw the connector onto the screen -function atree_render_connection() { +function atree_render_connection(atree_connectors_map) { for (let i of atree_connectors_map.keys()) { - if (document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].children.length != 0) {continue;} - if (atree_connectors_map.get(i).length != 0) { - document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]].appendChild(atree_connectors_map.get(i)[0].connector); - }; + let connector_info = atree_connectors_map.get(i); + let connector_elem = connector_info.connector; + set_connector_type(connector_info); + connector_elem.style.backgroundImage = "url('../media/atree/connect_"+connector_info.type+".png')"; + connector_info.highlight = [0, 0, 0, 0]; + console.log(i + ", " + connector_info.type); + let target_elem = document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]]; + if (target_elem.children.length != 0) { + // janky special case... + connector_elem.style.display = 'none'; + } + target_elem.appendChild(connector_elem); }; }; // toggle the state of a node. -function atree_toggle_state(node) { - if (atree_map.get(node.id).active) { - atree_map.get(node.id).active = false; - } else { - atree_map.get(node.id).active = true; - }; +function atree_toggle_state(atree_connectors_map, node_wrapper) { + let node = node_wrapper.node; + const new_state = !node_wrapper.active; + node_wrapper.active = new_state + for (const parent of node_wrapper.parents) { + if (parent.active) { + atree_set_edge(atree_connectors_map, parent, node_wrapper, new_state); // self->parent state only changes if parent is on + } + } + for (const child of node_wrapper.children) { + if (child.active) { + atree_set_edge(atree_connectors_map, node_wrapper, child, new_state); // Same logic as above. + } + } }; // refresh all connector to default state, then try to calculate the connector for all node @@ -256,72 +362,61 @@ function atree_update_connector() { }); } -// set the correct connector highlight for an active node, given a node. -function atree_compute_highlight(node) { - node.connectors.forEach((v, k) => { - if (node.active && atree_map.get(k).active) { - for (let i of v) { - connector_data = atree_connectors_map.get(i)[0]; - if (connector_data.type == "c" || connector_data.type == "t") { - connector_data.connector_state = atree_get_state(i); - let connector_img = atree_parse_connector(connector_data.connector_state, connector_data.type); - connector_data.connector.className = ""; - connector_data.connector.classList.add("rotate-" + connector_img.rotate); - connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + connector_img.attrib + ".png')"; - } else { - connector_data.connector.style.backgroundImage = "url('../media/atree/highlight_" + connector_data.type + ".png')"; - }; - }; - }; - }); -}; +function atree_set_edge(atree_connectors_map, parent, child, state) { + const connectors = child.connectors.get(parent); + const parent_row = parent.node.display.row; + const parent_col = parent.node.display.col; + const child_row = child.node.display.row; + const child_col = child.node.display.col; -// get the current active state of different directions, given a connector coordinate. -function atree_get_state(connector) { - let connector_state = [0, 0, 0, 0]; // left, right, up, down + let state_delta = (state ? 1 : -1); + let child_side_idx = (parent_col > child_col ? 0 : 1); + let parent_side_idx = 1 - child_side_idx; + for (const connector_label of connectors) { + let connector_info = atree_connectors_map.get(connector_label); + let connector_elem = connector_info.connector; + let highlight_state = connector_info.highlight; // left right up down + const ctype = connector_info.type; + if (ctype === 't' || ctype === 'c') { + // c, t + const [connector_row, connector_col] = connector_label.split(',').map(x => parseInt(x)); - for (let abil_name of atree_connectors_map.get(connector)[0].owner) { - - state = atree_map.get(abil_name).active; - if (atree_map.get(abil_name).display.col > parseInt(connector.split(",")[1])) { - if (state) { - connector_state[1] = 1; - } else if (!connector_state[1]) { - connector_state[1] = 0; + if (connector_row === parent_row) { + highlight_state[parent_side_idx] += state_delta; } + else { + highlight_state[2] += state_delta; // up connection guaranteed. + } + if (connector_col === child_col) { + highlight_state[3] += state_delta; + } + else { + highlight_state[child_side_idx] += state_delta; + } + + let render_state = highlight_state.map(x => (x > 0 ? 1 : 0)); + + let connector_img = atree_parse_connector(render_state, ctype); + connector_elem.className = ""; + connector_elem.classList.add("rotate-" + connector_img.rotate); + connector_elem.style.backgroundImage = connector_img.img; continue; } - if (atree_map.get(abil_name).display.col < parseInt(connector.split(",")[1])) { - if (state) { - connector_state[0] = 1; - } else if (!connector_state[0]) { - connector_state[0] = 0; - } - continue; + // lol bad overloading, [0] is just the whole state + highlight_state[0] += state_delta; + if (highlight_state[0] > 0) { + connector_elem.style.backgroundImage = "url('../media/atree/highlight_"+ctype+".png')"; } - if (atree_map.get(abil_name).display.row < parseInt(connector.split(",")[0])) { - if (state) { - connector_state[2] = 1; - } else if (!connector_state[2]) { - connector_state[2] = 0; - } - continue; + else { + connector_elem.style.backgroundImage = "url('../media/atree/connect_"+ctype+".png')"; } - if (atree_map.get(abil_name).display.row > parseInt(connector.split(",")[0])) { - if (state) { - connector_state[3] = 1; - } else if (!connector_state[3]) { - connector_state[3] = 0; - }; - continue; - }; - }; - return connector_state; + } } // parse a sequence of left, right, up, down to appropriate connector image function atree_parse_connector(orient, type) { // left, right, up, down + let c_connector_dict = { "1100": {attrib: "_2_l", rotate: 0}, "1010": {attrib: "_2_a", rotate: 0}, @@ -346,11 +441,17 @@ function atree_parse_connector(orient, type) { let res = ""; for (let i of orient) { res += i; - }; + } + if (res === "0000") { + return {img: "url('../media/atree/connect_" + type + ".png')", rotate: 0}; + } + let ret; if (type == "c") { - return c_connector_dict[res]; + ret = c_connector_dict[res]; } else { - return t_connector_dict[res]; + ret = t_connector_dict[res]; }; + ret.img = "url('../media/atree/highlight_" + type + ret.attrib + ".png')"; + return ret; }; diff --git a/js/atree_constants.js b/js/atree_constants.js index 8e9ae98..2f01e7e 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -466,7 +466,7 @@ const atrees = { "display_name": "Windy Feet", "base_abil": "Escape", "desc": "When casting Escape, give speed to yourself and nearby allies.", - "archetype": "Boltslinger", + "archetype": "", "archetype_req": 0, "parents": [ 7 @@ -2193,7 +2193,7 @@ const atrees = { "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, "scaling": [ 35 @@ -2228,7 +2228,7 @@ const atrees = { "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, "scaling": [ 35 @@ -2263,7 +2263,7 @@ const atrees = { "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, "scaling": [ 35 @@ -3805,12 +3805,12 @@ const atrees = { ], "output": { "type": "stat", - "name": "dmgPct" + "name": "damMult" }, "scaling": [ - 2 + 3 ], - "max": 200 + "max": 300 } ], "id": 103 @@ -4964,4 +4964,4 @@ const atrees = { "id": 139 } ] -} \ No newline at end of file +} diff --git a/js/atree_constants_min.js b/js/atree_constants_min.js index f79809c..ac8955c 100644 --- a/js/atree_constants_min.js +++ b/js/atree_constants_min.js @@ -1 +1 @@ -const atrees={"Archer":[{"display_name":"Arrow Shield","desc":"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)","archetype":"","archetype_req":0,"parents":[60,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":6},"properties":{"duration":60},"effects":[{"type":"replace_spell","name":"Arrow Shield","cost":30,"display_text":"Max Damage","base_spell":4,"spell_type":"damage","scaling":"spell","display":"","parts":[{"name":"Shield Damage","type":"damage","multipliers":[90,0,0,0,0,10]},{"name":"Total Damage","type":"total","hits":{"Shield Damage":2}}]}],"id":0},{"display_name":"Escape","desc":"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":7,"col":4},"properties":{"aoe":0,"range":0},"effects":[{"type":"replace_spell","name":"Escape","cost":25,"display_text":"Max Damage","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":1},{"display_name":"Arrow Bomb","desc":"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4},"properties":{"aoe":4.5,"range":26},"effects":[{"type":"replace_spell","name":"Arrow Bomb","cost":50,"display_text":"Average Damage","base_spell":3,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Arrow Bomb","type":"damage","multipliers":[160,0,0,0,20,0]},{"name":"Total Damage","type":"total","hits":{"Arrow Bomb":1}}]}],"id":2},{"display_name":"Heart Shatter","desc":"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[100,0,0,0,0,0]},{}],"id":3},{"display_name":"Fire Creep","desc":"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.","archetype":"","archetype_req":0,"parents":[68,86,5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":16,"col":6},"properties":{"aoe":0.8,"duration":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[30,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fire Creep":15}}],"id":4},{"display_name":"Bryophyte Roots","desc":"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.","archetype":"Trapper","archetype_req":1,"parents":[4,82],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":16,"col":8},"properties":{"aoe":2,"duration":5,"slowness":0.4},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Bryophyte Roots","cost":0,"multipliers":[40,20,0,0,0,0]}],"id":5},{"display_name":"Nimble String","desc":"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.","archetype":"","archetype_req":0,"parents":[83,69],"dependencies":[7],"blockers":[68],"cost":2,"display":{"row":15,"col":2},"properties":{"shootspeed":2},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-15,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":8}}],"id":6},{"display_name":"Arrow Storm","desc":"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.","archetype":"","archetype_req":0,"parents":[58,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":2},"properties":{"aoe":0,"range":16},"effects":[{"type":"replace_spell","name":"Arrow Storm","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,10,0,0,0]},{"name":"Single Stream","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Stream":2}}]}],"id":7},{"display_name":"Guardian Angels","desc":"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)","archetype":"Boltslinger","archetype_req":3,"parents":[59,67],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":19,"col":1},"properties":{"range":4,"duration":60,"shots":8,"count":2},"effects":[{"type":"replace_spell","name":"Guardian Angels","cost":30,"display_text":"Total Damage Average","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[40,0,0,0,0,20]},{"name":"Single Bow","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Bow":2}}]}],"id":8},{"display_name":"Windy Feet","base_abil":"Escape","desc":"When casting Escape, give speed to yourself and nearby allies.","archetype":"Boltslinger","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":1},"properties":{"aoe":8,"duration":120},"type":"stat_bonus","bonuses":[{"type":"stat","name":"spd","value":20}],"id":9},{"display_name":"Basaltic Trap","desc":"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)","archetype":"Trapper","archetype_req":2,"parents":[5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":8},"properties":{"aoe":7,"traps":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[140,30,0,0,30,0]}],"id":10},{"display_name":"Windstorm","desc":"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.","archetype":"","archetype_req":0,"parents":[8,33],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":21,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-11,0,-7,0,0,3]},{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":1}}],"id":11},{"display_name":"Grappling Hook","base_abil":"Escape","desc":"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)","archetype":"Trapper","archetype_req":0,"parents":[61,40,33],"dependencies":[],"blockers":[20],"cost":2,"display":{"row":21,"col":5},"properties":{"range":20},"effects":[],"id":12},{"display_name":"Implosion","desc":"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.","archetype":"Trapper","archetype_req":0,"parents":[12,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":13},{"display_name":"Twain's Arc","desc":"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)","archetype":"Sharpshooter","archetype_req":4,"parents":[62,64],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":25,"col":4},"properties":{"range":64,"focusReq":2},"effects":[{"type":"replace_spell","name":"Twain's Arc","cost":0,"display_text":"Twain's Arc","base_spell":5,"spell_type":"damage","scaling":"melee","display":"Twain's Arc Damage","parts":[{"name":"Twain's Arc Damage","type":"damage","multipliers":[200,0,0,0,0,0]}]}],"id":14},{"display_name":"Fierce Stomp","desc":"When using Escape, hold shift to quickly drop down and deal damage.","archetype":"Boltslinger","archetype_req":0,"parents":[42,64],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":1},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[100,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":2,"target_part":"Total Damage","cost":0,"hits":{"Fierce Stomp":1}}],"id":15},{"display_name":"Scorched Earth","desc":"Fire Creep become much stronger.","archetype":"Sharpshooter","archetype_req":0,"parents":[14],"dependencies":[4],"blockers":[],"cost":1,"display":{"row":26,"col":5},"properties":{"duration":2,"aoe":0.4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[10,0,0,0,5,0]}],"id":16},{"display_name":"Leap","desc":"When you double tap jump, leap foward. (2s Cooldown)","archetype":"Boltslinger","archetype_req":5,"parents":[42,55],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0},"properties":{"cooldown":2},"effects":[],"id":17},{"display_name":"Shocking Bomb","desc":"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.","archetype":"Sharpshooter","archetype_req":5,"parents":[14,44,55],"dependencies":[2],"blockers":[],"cost":2,"display":{"row":28,"col":4},"properties":{"gravity":0},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"}],"id":18},{"display_name":"Mana Trap","desc":"Your Traps will give you 4 Mana per second when you stay close to them.","archetype":"Trapper","archetype_req":5,"parents":[43,44],"dependencies":[4],"blockers":[],"cost":2,"display":{"row":28,"col":8},"properties":{"range":12,"manaRegen":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":10,"multipliers":[0,0,0,0,0,0]}],"id":19},{"display_name":"Escape Artist","desc":"When casting Escape, release 100 arrows towards the ground.","archetype":"Boltslinger","archetype_req":0,"parents":[46,17],"dependencies":[],"blockers":[12],"cost":2,"display":{"row":31,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Escape Artist","cost":0,"multipliers":[30,0,10,0,0,0]}],"id":20},{"display_name":"Initiator","desc":"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.","archetype":"Sharpshooter","archetype_req":5,"parents":[18,44,47],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":31,"col":5},"properties":{"focus":1,"timer":5},"type":"stat_bonus","bonuses":[{"type":"stat","name":"damPct","value":50}],"id":21},{"display_name":"Call of the Hound","desc":"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.","archetype":"Trapper","archetype_req":0,"parents":[21,47],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":32,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Call of the Hound","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":22},{"display_name":"Arrow Hurricane","desc":"Arrow Storm will shoot +2 stream of arrows.","archetype":"Boltslinger","archetype_req":8,"parents":[48,20],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":33,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":2}}],"id":23},{"display_name":"Geyser Stomp","desc":"Fierce Stomp will create geysers, dealing more damage and vertical knockback.","archetype":"","archetype_req":0,"parents":[56],"dependencies":[15],"blockers":[],"cost":2,"display":{"row":37,"col":1},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[0,0,0,50,0,0]}],"id":24},{"display_name":"Crepuscular Ray","desc":"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.","archetype":"Sharpshooter","archetype_req":10,"parents":[49],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":37,"col":4},"properties":{"focusReq":5,"focusRegen":-1},"effects":[{"type":"replace_spell","name":"Crepuscular Ray","base_spell":5,"spell_type":"damage","scaling":"spell","display":"One Focus","cost":0,"parts":[{"name":"Single Arrow","type":"damage","multipliers":[10,0,0,5,0,0]},{"name":"One Focus","type":"total","hits":{"Single Arrow":20}},{"name":"Total Damage","type":"total","hits":{"One Focus":7}}]}],"id":25},{"display_name":"Grape Bomb","desc":"Arrow bomb will throw 3 additional smaller bombs when exploding.","archetype":"","archetype_req":0,"parents":[51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":37,"col":7},"properties":{"miniBombs":3,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Grape Bomb","cost":0,"multipliers":[30,0,0,0,10,0]}],"id":26},{"display_name":"Tangled Traps","desc":"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":38,"col":6},"properties":{"attackSpeed":0.2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Tangled Traps","cost":0,"multipliers":[20,0,0,0,0,20]}],"id":27},{"display_name":"Snow Storm","desc":"Enemies near you will be slowed down.","archetype":"","archetype_req":0,"parents":[24,63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":39,"col":2},"properties":{"range":2.5,"slowness":0.3},"id":28},{"display_name":"All-Seeing Panoptes","desc":"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.","archetype":"Boltslinger","archetype_req":11,"parents":[28],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":40,"col":1},"properties":{"range":10,"shots":5},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Arrow","cost":0,"multipliers":[0,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":5}}],"id":29},{"display_name":"Minefield","desc":"Allow you to place +6 Traps, but with reduced damage and range.","archetype":"Trapper","archetype_req":10,"parents":[26,53],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":40,"col":7},"properties":{"aoe":-2,"traps":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[-80,0,0,0,0,0]}],"id":30},{"display_name":"Bow Proficiency I","desc":"Improve your Main Attack's damage and range when using a bow.","archetype":"","archetype_req":0,"parents":[2],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":31},{"display_name":"Cheaper Arrow Bomb","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-10}],"id":32},{"display_name":"Cheaper Arrow Storm","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[12,11,61],"dependencies":[],"blockers":[],"cost":1,"display":{"row":21,"col":3},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":33},{"display_name":"Cheaper Escape","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[7,0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":34},{"display_name":"Earth Mastery","desc":"Increases your base damage from all Earth attacks","archetype":"Trapper","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":8},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":82},{"display_name":"Thunder Mastery","desc":"Increases your base damage from all Thunder attacks","archetype":"Boltslinger","archetype_req":0,"parents":[7,86,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":2},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":83},{"display_name":"Water Mastery","desc":"Increases your base damage from all Water attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[34,83,86],"dependencies":[],"blockers":[],"cost":1,"display":{"row":14,"col":4},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":84},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":0},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":85},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[83,0,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":6},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":86},{"display_name":"More Shields","desc":"Give +2 charges to Arrow Shield.","archetype":"","archetype_req":0,"parents":[12,10],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":21,"col":7},"properties":{"shieldCharges":2},"id":40},{"display_name":"Stormy Feet","desc":"Windy Feet will last longer and add more speed.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[9],"blockers":[],"cost":1,"display":{"row":23,"col":1},"properties":{"duration":60},"effects":[{"type":"stat_bonus","bonuses":[{"type":"stat","name":"spdPct","value":20}]}],"id":41},{"display_name":"Refined Gunpowder","desc":"Increase the damage of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[50,0,0,0,0,0]}],"id":42},{"display_name":"More Traps","desc":"Increase the maximum amount of active Traps you can have by +2.","archetype":"Trapper","archetype_req":10,"parents":[54],"dependencies":[10],"blockers":[],"cost":1,"display":{"row":26,"col":8},"properties":{"traps":2},"id":43},{"display_name":"Better Arrow Shield","desc":"Arrow Shield will gain additional area of effect, knockback and damage.","archetype":"Sharpshooter","archetype_req":0,"parents":[19,18,14],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":28,"col":6},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Shield","multipliers":[40,0,0,0,0,0]}],"id":44},{"display_name":"Better Leap","desc":"Reduce leap's cooldown by 1s.","archetype":"Boltslinger","archetype_req":0,"parents":[17,55],"dependencies":[17],"blockers":[],"cost":1,"display":{"row":29,"col":1},"properties":{"cooldown":-1},"id":45},{"display_name":"Better Guardian Angels","desc":"Your Guardian Angels can shoot +4 arrows before disappearing.","archetype":"Boltslinger","archetype_req":0,"parents":[20,55],"dependencies":[8],"blockers":[],"cost":1,"display":{"row":31,"col":2},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":4}}],"id":46},{"display_name":"Cheaper Arrow Storm (2)","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[21,19],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":8},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":47},{"display_name":"Precise Shot","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[46,49,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":2},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdCritPct","value":30}]}],"id":48},{"display_name":"Cheaper Arrow Shield","desc":"Reduce the Mana cost of Arrow Shield.","archetype":"","archetype_req":0,"parents":[48,21],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":49},{"display_name":"Rocket Jump","desc":"Arrow Bomb's self-damage will knockback you farther away.","archetype":"","archetype_req":0,"parents":[47,21],"dependencies":[2],"blockers":[],"cost":1,"display":{"row":33,"col":6},"properties":{},"id":50},{"display_name":"Cheaper Escape (2)","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[22,70],"dependencies":[],"blockers":[],"cost":1,"display":{"row":34,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":51},{"display_name":"Stronger Hook","desc":"Increase your Grappling Hook's range, speed and strength.","archetype":"Trapper","archetype_req":5,"parents":[51],"dependencies":[12],"blockers":[],"cost":1,"display":{"row":35,"col":8},"properties":{"range":8},"id":52},{"display_name":"Cheaper Arrow Bomb (2)","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[63,30],"dependencies":[],"blockers":[],"cost":1,"display":{"row":40,"col":5},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":53},{"display_name":"Bouncing Bomb","desc":"Arrow Bomb will bounce once when hitting a block or enemy","archetype":"","archetype_req":0,"parents":[40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":25,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Arrow Bomb":2}}],"id":54},{"display_name":"Homing Shots","desc":"Your Main Attack arrows will follow nearby enemies and not be affected by gravity","archetype":"","archetype_req":0,"parents":[17,18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2},"properties":{},"effects":[],"id":55},{"display_name":"Shrapnel Bomb","desc":"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area","archetype":"Boltslinger","archetype_req":8,"parents":[23,48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Shrapnel Bomb","cost":0,"multipliers":[40,0,0,0,20,0]}],"id":56},{"display_name":"Elusive","desc":"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)","archetype":"Boltslinger","archetype_req":0,"parents":[24],"dependencies":[],"blockers":[],"cost":2,"display":{"row":38,"col":0},"properties":{},"effects":[],"id":57},{"display_name":"Double Shots","desc":"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)","archetype":"Boltslinger","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[60],"cost":1,"display":{"row":7,"col":2},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":58},{"display_name":"Triple Shots","desc":"Triple Main Attack arrows, but they deal -20% damage per arrow","archetype":"Boltslinger","archetype_req":0,"parents":[69,67],"dependencies":[58],"blockers":[],"cost":1,"display":{"row":17,"col":0},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":59},{"display_name":"Power Shots","desc":"Main Attack arrows have increased speed and knockback","archetype":"Sharpshooter","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[58],"cost":1,"display":{"row":7,"col":6},"properties":{},"effects":[],"id":60},{"display_name":"Focus","desc":"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once","archetype":"Sharpshooter","archetype_req":2,"parents":[68],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":3}],"id":61},{"display_name":"More Focus","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[33,12],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":5}],"id":62},{"display_name":"More Focus (2)","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[25,28],"dependencies":[],"blockers":[],"cost":1,"display":{"row":39,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"dmgPct"},"scaling":[35],"max":7}],"id":63},{"display_name":"Traveler","desc":"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)","archetype":"","archetype_req":0,"parents":[42,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"spd"}],"output":{"type":"stat","name":"sdRaw"},"scaling":[1],"max":100}],"id":64},{"display_name":"Patient Hunter","desc":"Your Traps will deal +20% more damage for every second they are active (Max +80%)","archetype":"Trapper","archetype_req":0,"parents":[40],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":8},"properties":{"max":80},"effects":[],"id":65},{"display_name":"Stronger Patient Hunter","desc":"Add +80% Max Damage to Patient Hunter","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[65],"blockers":[],"cost":1,"display":{"row":38,"col":8},"properties":{"max":80},"effects":[],"id":66},{"display_name":"Frenzy","desc":"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second","archetype":"Boltslinger","archetype_req":0,"parents":[59,6],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"spd"},"scaling":[6],"max":200}],"id":67},{"display_name":"Phantom Ray","desc":"Condense Arrow Storm into a single ray that damages enemies 10 times per second","archetype":"Sharpshooter","archetype_req":0,"parents":[84,4],"dependencies":[7],"blockers":[11,6,23],"cost":2,"display":{"row":16,"col":4},"properties":{},"effects":[{"type":"replace_spell","name":"Phantom Ray","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[25,0,5,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Arrow":16}}]}],"id":68},{"display_name":"Arrow Rain","desc":"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies","archetype":"Trapper","archetype_req":0,"parents":[6,85],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":15,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Arrow Rain","cost":0,"multipliers":[120,0,0,0,0,80]}],"id":69},{"display_name":"Decimator","desc":"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)","archetype":"Sharpshooter","archetype_req":0,"parents":[49],"dependencies":[68],"blockers":[],"cost":1,"display":{"row":34,"col":5},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Phantom Ray hits","output":{"type":"stat","name":"PhRayDmg"},"scaling":10,"max":50}],"id":70}],"Warrior":[{"display_name":"Bash","desc":"Violently bash the ground, dealing high damage in a large area","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4,"icon":"node_4"},"properties":{"aoe":4,"range":3},"effects":[{"type":"replace_spell","name":"Bash","cost":45,"display_text":"Total Damage Average","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Hit","type":"damage","multipliers":[130,20,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Hit":1}}]}],"id":71},{"display_name":"Spear Proficiency 1","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[71],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":72},{"display_name":"Cheaper Bash","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[72],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-10}],"id":73},{"display_name":"Double Bash","desc":"Bash will hit a second time at a farther range","archetype":"","archetype_req":0,"parents":[72],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4,"icon":"node_1"},"properties":{"range":3},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"name":"Single Hit","value":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-50,0,0,0,0,0]}],"id":74},{"display_name":"Charge","desc":"Charge forward at high speed (hold shift to cancel)","archetype":"","archetype_req":0,"parents":[74],"dependencies":[],"blockers":[],"cost":1,"display":{"row":6,"col":4,"icon":"node_4"},"properties":{},"effects":[{"type":"replace_spell","name":"Charge","cost":25,"display_text":"Total Damage Average","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":75},{"display_name":"Heavy Impact","desc":"After using Charge, violently crash down into the ground and deal damage","archetype":"","archetype_req":0,"parents":[79],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":1,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Heavy Impact","cost":0,"multipliers":[100,0,0,0,0,0]}],"id":76},{"display_name":"Vehement","desc":"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)","archetype":"Fallen","archetype_req":0,"parents":[75],"dependencies":[],"blockers":[78],"cost":1,"display":{"row":6,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"mdPct"},{"type":"stat","name":"mdRaw"}],"output":{"type":"stat","name":"spd"},"scaling":[1,1],"max":20}],"id":77},{"display_name":"Tougher Skin","desc":"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)","archetype":"Paladin","archetype_req":0,"parents":[75],"dependencies":[],"blockers":[77],"cost":1,"display":{"row":6,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":"5"}]},{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hprRaw"},{"type":"stat","name":"hprPct"}],"output":{"type":"stat","name":"hpBonus"},"scaling":[10,10],"max":100}],"id":78},{"display_name":"Uppercut","desc":"Rocket enemies in the air and deal massive damage","archetype":"","archetype_req":0,"parents":[77],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":2,"icon":"node_4"},"properties":{"aoe":3,"range":5},"effects":[{"type":"replace_spell","name":"Uppercut","cost":45,"display_text":"Total Damage Average","base_spell":3,"spell_type":"damage","scaling":"spell","display":"total","parts":[{"name":"Uppercut","type":"damage","multipliers":[150,50,50,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Uppercut":1}}]}],"id":79},{"display_name":"Cheaper Charge","desc":"Reduce the Mana cost of Charge","archetype":"","archetype_req":0,"parents":[79,81],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":80},{"display_name":"War Scream","desc":"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies","archetype":"","archetype_req":0,"parents":[78],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":6,"icon":"node_4"},"properties":{"duration":30,"aoe":12,"defense_bonus":10},"effects":[{"type":"replace_spell","name":"War Scream","cost":35,"display_text":"War Scream","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage Average","parts":[{"name":"War Scream","type":"damage","multipliers":[50,0,0,0,50,0]}]}],"id":81},{"display_name":"Earth Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Fallen","archetype_req":0,"parents":[79],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":82},{"display_name":"Thunder Mastery","desc":"Increases base damage from all Thunder attacks","archetype":"Fallen","archetype_req":0,"parents":[79,85,80],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":83},{"display_name":"Water Mastery","desc":"Increases base damage from all Water attacks","archetype":"Battle Monk","archetype_req":0,"parents":[80,83,85],"dependencies":[],"blockers":[],"cost":1,"display":{"row":11,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":84},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[81,83,80],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":85},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Paladin","archetype_req":0,"parents":[81],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":86},{"display_name":"Quadruple Bash","desc":"Bash will hit 4 times at an even larger range","archetype":"Fallen","archetype_req":0,"parents":[82,88],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":0,"icon":"node_1"},"properties":{"range":6},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Hit":2}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-20,0,0,0,0,0]}],"id":87},{"display_name":"Fireworks","desc":"Mobs hit by Uppercut will explode mid-air and receive additional damage","archetype":"Fallen","archetype_req":0,"parents":[83,87],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fireworks","cost":0,"multipliers":[80,0,20,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fireworks":1}}],"id":88},{"display_name":"Half-Moon Swipe","desc":"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water","archetype":"Battle Monk","archetype_req":1,"parents":[84],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":13,"col":4,"icon":"node_1"},"properties":{"range":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":-10,"multipliers":[-70,0,0,0,0,0]},{"type":"convert_spell_conv","target_part":"all","conversion":"water"}],"id":89},{"display_name":"Flyby Jab","desc":"Damage enemies in your way when using Charge","archetype":"","archetype_req":0,"parents":[85,91],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":6,"icon":"node_1"},"properties":{"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flyby Jab","cost":0,"multipliers":[20,0,0,0,0,40]}],"id":90},{"display_name":"Flaming Uppercut","desc":"Uppercut will light mobs on fire, dealing damage every 0.6 seconds","archetype":"Paladin","archetype_req":0,"parents":[86,90],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":12,"col":8,"icon":"node_1"},"properties":{"duration":3,"tick":0.6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut","cost":0,"multipliers":[0,0,0,0,50,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut Total Damage","cost":0,"hits":{"Flaming Uppercut":5}},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Flaming Uppercut":5}}],"id":91},{"display_name":"Iron Lungs","desc":"War Scream deals more damage","archetype":"","archetype_req":0,"parents":[90,91],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"War Scream","cost":0,"multipliers":[30,0,0,0,0,30]}],"id":92},{"display_name":"Generalist","desc":"After casting 3 different spells in a row, your next spell will cost 5 mana","archetype":"Battle Monk","archetype_req":3,"parents":[94],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":2,"icon":"node_3"},"properties":{},"effects":[],"id":93},{"display_name":"Counter","desc":"When dodging a nearby enemy attack, get 30% chance to instantly attack back","archetype":"Battle Monk","archetype_req":0,"parents":[89],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":4,"icon":"node_1"},"properties":{"chance":30},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Counter","cost":0,"multipliers":[60,0,20,0,0,20]}],"id":94},{"display_name":"Mantle of the Bovemists","desc":"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)","archetype":"Paladin","archetype_req":3,"parents":[92],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":15,"col":7,"icon":"node_3"},"properties":{"mantle_charge":3},"effects":[],"id":95},{"display_name":"Bak'al's Grasp","desc":"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)","archetype":"Fallen","archetype_req":2,"parents":[87,88],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":16,"col":1,"icon":"node_3"},"properties":{"cooldown":15},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[4],"slider_step":2,"max":120}],"id":96},{"display_name":"Spear Proficiency 2","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[96,98],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":0,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":97},{"display_name":"Cheaper Uppercut","desc":"Reduce the Mana Cost of Uppercut","archetype":"","archetype_req":0,"parents":[97,99,94],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":98},{"display_name":"Aerodynamics","desc":"During Charge, you can steer and change direction","archetype":"Battle Monk","archetype_req":0,"parents":[98,100],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":5,"icon":"node_1"},"properties":{},"effects":[],"id":99},{"display_name":"Provoke","desc":"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream","archetype":"Paladin","archetype_req":0,"parents":[99,95],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":100},{"display_name":"Precise Strikes","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[98,97],"dependencies":[],"blockers":[],"cost":1,"display":{"row":18,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"critDmg","value":30}]}],"id":101},{"display_name":"Air Shout","desc":"War Scream will fire a projectile that can go through walls and deal damage multiple times","archetype":"","archetype_req":0,"parents":[99,100],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":18,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Air Shout","cost":0,"multipliers":[20,0,0,0,0,5]}],"id":102},{"display_name":"Enraged Blow","desc":"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)","archetype":"Fallen","archetype_req":0,"parents":[97],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":20,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"dmgPct"},"scaling":[2],"max":200}],"id":103},{"display_name":"Flying Kick","desc":"When using Charge, mobs hit will halt your momentum and get knocked back","archetype":"Battle Monk","archetype_req":1,"parents":[98,105],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":3,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flying Kick","cost":0,"multipliers":[120,0,0,10,0,20]}],"id":104},{"display_name":"Stronger Mantle","desc":"Add +2 additional charges to Mantle of the Bovemists","archetype":"Paladin","archetype_req":0,"parents":[106,104],"dependencies":[95],"blockers":[],"cost":1,"display":{"row":20,"col":6,"icon":"node_0"},"properties":{"mantle_charge":2},"effects":[],"id":105},{"display_name":"Manachism","desc":"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)","archetype":"Paladin","archetype_req":3,"parents":[105,100],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":8,"icon":"node_2"},"properties":{"cooldown":1},"effects":[],"id":106},{"display_name":"Boiling Blood","desc":"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds","archetype":"","archetype_req":0,"parents":[103,108],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":0,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Boiling Blood","cost":0,"multipliers":[25,0,0,0,5,0]}],"id":107},{"display_name":"Ragnarokkr","desc":"War Scream become deafening, increasing its range and giving damage bonus to players","archetype":"Fallen","archetype_req":0,"parents":[107,104],"dependencies":[81],"blockers":[],"cost":2,"display":{"row":22,"col":2,"icon":"node_2"},"properties":{"damage_bonus":30,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":10}],"id":108},{"display_name":"Ambidextrous","desc":"Increase your chance to attack with Counter by +30%","archetype":"","archetype_req":0,"parents":[104,105,110],"dependencies":[94],"blockers":[],"cost":1,"display":{"row":22,"col":4,"icon":"node_0"},"properties":{"chance":30},"effects":[],"id":109},{"display_name":"Burning Heart","desc":"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)","archetype":"Paladin","archetype_req":0,"parents":[109,111],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"fDamPct"},"scaling":[2],"max":100,"slider_step":100}],"id":110},{"display_name":"Stronger Bash","desc":"Increase the damage of Bash","archetype":"","archetype_req":0,"parents":[110,106],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[30,0,0,0,0,0]}],"id":111},{"display_name":"Intoxicating Blood","desc":"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted","archetype":"Fallen","archetype_req":5,"parents":[108,107],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":23,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":112},{"display_name":"Comet","desc":"After being hit by Fireworks, enemies will crash into the ground and receive more damage","archetype":"Fallen","archetype_req":0,"parents":[108],"dependencies":[88],"blockers":[],"cost":2,"display":{"row":24,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Comet","cost":0,"multipliers":[80,20,0,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Comet":1}}],"id":113},{"display_name":"Collide","desc":"Mobs thrown into walls from Flying Kick will explode and receive additonal damage","archetype":"Battle Monk","archetype_req":4,"parents":[109,110],"dependencies":[104],"blockers":[],"cost":2,"display":{"row":23,"col":5,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Collide","cost":0,"multipliers":[100,0,0,0,50,0]}],"id":114},{"display_name":"Rejuvenating Skin","desc":"Regain back 30% of the damage you take as healing over 30s","archetype":"Paladin","archetype_req":0,"parents":[110,111],"dependencies":[],"blockers":[],"cost":2,"display":{"row":23,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":115},{"display_name":"Uncontainable Corruption","desc":"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1","archetype":"","archetype_req":0,"parents":[107,117],"dependencies":[96],"blockers":[],"cost":1,"display":{"row":26,"col":0,"icon":"node_0"},"properties":{"cooldown":-5},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[1],"slider_step":2,"max":50}],"id":116},{"display_name":"Radiant Devotee","desc":"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)","archetype":"Battle Monk","archetype_req":1,"parents":[118,116],"dependencies":[],"blockers":[],"cost":1,"display":{"row":26,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","inputs":[{"type":"stat","name":"ref"}],"output":{"type":"stat","name":"mr"},"scaling":[1],"max":10,"slider_step":4}],"id":117},{"display_name":"Whirlwind Strike","desc":"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)","archetype":"Battle Monk","archetype_req":5,"parents":[109,117],"dependencies":[79],"blockers":[],"cost":2,"display":{"row":26,"col":4,"icon":"node_1"},"properties":{"range":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":0,"multipliers":[0,0,0,0,0,50]}],"id":118},{"display_name":"Mythril Skin","desc":"Gain +5% Base Resistance and become immune to knockback","archetype":"Paladin","archetype_req":6,"parents":[115],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":5}]}],"id":119},{"display_name":"Armour Breaker","desc":"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage","archetype":"Fallen","archetype_req":0,"parents":[116,117],"dependencies":[96],"blockers":[],"cost":2,"display":{"row":27,"col":1,"icon":"node_2"},"properties":{"duration":5},"effects":[],"id":120},{"display_name":"Shield Strike","desc":"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost","archetype":"Paladin","archetype_req":0,"parents":[119,122],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Shield Strike","cost":0,"multipliers":[60,0,20,0,0,0]}],"id":121},{"display_name":"Sparkling Hope","desc":"Everytime you heal 5% of your max health, deal damage to all nearby enemies","archetype":"Paladin","archetype_req":0,"parents":[119],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":8,"icon":"node_2"},"properties":{"aoe":6},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Sparkling Hope","cost":0,"multipliers":[10,0,5,0,0,0]}],"id":122},{"display_name":"Massive Bash","desc":"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)","archetype":"Fallen","archetype_req":8,"parents":[124,116],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"bashAoE"},"scaling":[1],"max":10,"slider_step":3}],"id":123},{"display_name":"Tempest","desc":"War Scream will ripple the ground and deal damage 3 times in a large area","archetype":"Battle Monk","archetype_req":0,"parents":[123,125],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2,"icon":"node_1"},"properties":{"aoe":16},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest","cost":"0","multipliers":[30,10,0,0,0,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest Total Damage","cost":"0","hits":{"Tempest":3}},{"type":"add_spell_prop","base_spell":4,"target_part":"Total Damage","cost":"0","hits":{"Tempest":3}}],"id":124},{"display_name":"Spirit of the Rabbit","desc":"Reduce the Mana cost of Charge and increase your Walk Speed by +20%","archetype":"Battle Monk","archetype_req":5,"parents":[124,118],"dependencies":[],"blockers":[],"cost":1,"display":{"row":28,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5},{"type":"raw_stat","bonuses":[{"type":"stat","name":"spd","value":20}]}],"id":125},{"display_name":"Massacre","desc":"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar","archetype":"Fallen","archetype_req":5,"parents":[124,123],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":126},{"display_name":"Axe Kick","desc":"Increase the damage of Uppercut, but also increase its mana cost","archetype":"","archetype_req":0,"parents":[124,125],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":10,"multipliers":[100,0,0,0,0,0]}],"id":127},{"display_name":"Radiance","desc":"Bash will buff your allies' positive IDs. (15s Cooldown)","archetype":"Paladin","archetype_req":2,"parents":[125,129],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":5,"icon":"node_2"},"properties":{"cooldown":15},"effects":[],"id":128},{"display_name":"Cheaper Bash 2","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[128,121,122],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":129},{"display_name":"Cheaper War Scream","desc":"Reduce the Mana cost of War Scream","archetype":"","archetype_req":0,"parents":[123],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":130},{"display_name":"Discombobulate","desc":"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second","archetype":"Battle Monk","archetype_req":12,"parents":[133],"dependencies":[],"blockers":[],"cost":2,"display":{"row":31,"col":2,"icon":"node_3"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"rainrawButDifferent"},"scaling":[2],"max":50}],"id":131},{"display_name":"Thunderclap","desc":"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder","archetype":"Battle Monk","archetype_req":8,"parents":[133],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":5,"icon":"node_1"},"properties":{},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"},{"type":"raw_stat","bonuses":[{"type":"prop","abil_name":"Bash","name":"aoe","value":3}]}],"id":132},{"display_name":"Cyclone","desc":"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s","archetype":"Battle Monk","archetype_req":0,"parents":[125],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":4,"icon":"node_1"},"properties":{"aoe":4,"duration":20},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone","cost":0,"multipliers":[10,0,0,0,5,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone Total Damage","cost":0,"hits":{"Cyclone":40}}],"id":133},{"display_name":"Second Chance","desc":"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)","archetype":"Paladin","archetype_req":12,"parents":[129],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":134},{"display_name":"Blood Pact","desc":"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)","archetype":"","archetype_req":10,"parents":[130],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1,"icon":"node_3"},"properties":{},"effects":[],"id":135},{"display_name":"Haemorrhage","desc":"Reduce Blood Pact's health cost. (0.5% health per mana)","archetype":"Fallen","archetype_req":0,"parents":[135],"dependencies":[135],"blockers":[],"cost":1,"display":{"row":35,"col":2,"icon":"node_1"},"properties":{},"effects":[],"id":136},{"display_name":"Brink of Madness","desc":"If your health is 25% full or less, gain +40% Resistance","archetype":"","archetype_req":0,"parents":[135,138],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":4,"icon":"node_2"},"properties":{},"effects":[],"id":137},{"display_name":"Cheaper Uppercut 2","desc":"Reduce the Mana cost of Uppercut","archetype":"","archetype_req":0,"parents":[134,137],"dependencies":[],"blockers":[],"cost":1,"display":{"row":35,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":138},{"display_name":"Martyr","desc":"When you receive a fatal blow, all nearby allies become invincible","archetype":"Paladin","archetype_req":0,"parents":[134],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":8,"icon":"node_1"},"properties":{"duration":3,"aoe":12},"effects":[],"id":139}]} \ No newline at end of file +const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:[60,34],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}],id:0},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:[3],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}],id:1},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}],id:2},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:[31],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}],id:3},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:[68,86,5],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}],id:4},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:[4,82],dependencies:[7],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}],id:5},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:[83,69],dependencies:[7],blockers:[68],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}],id:6},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:[58,34],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}],id:7},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:[59,67],dependencies:[0],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}],id:8},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"",archetype_req:0,parents:[7],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}],id:9},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:[5],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}],id:10},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:[8,33],dependencies:[],blockers:[68],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}],id:11},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:[61,40,33],dependencies:[],blockers:[20],cost:2,display:{row:21,col:5},properties:{range:20},effects:[],id:12},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:[12,40],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}],id:13},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:[62,64],dependencies:[61],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}],id:14},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:[42,64],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}],id:15},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:[14],dependencies:[4],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}],id:16},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:[42,55],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[],id:17},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:[14,44,55],dependencies:[2],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}],id:18},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:[43,44],dependencies:[4],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}],id:19},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:[46,17],dependencies:[],blockers:[12],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}],id:20},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:[18,44,47],dependencies:[61],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}],id:21},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:[21,47],dependencies:[0],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}],id:22},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:[48,20],dependencies:[],blockers:[68],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}],id:23},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:[56],dependencies:[15],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}],id:24},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:[49],dependencies:[7],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}],id:25},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:[51],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}],id:26},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:[26],dependencies:[10],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}],id:27},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:[24,63],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3},id:28},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:[28],dependencies:[8],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}],id:29},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:[26,53],dependencies:[10],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}],id:30},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:[2],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:31},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:[31],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}],id:32},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:[12,11,61],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:33},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:[7,0],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:34},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:[0],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}],id:82},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:[7,86,34],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}],id:83},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:[34,83,86],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}],id:84},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:[7],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}],id:85},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:[83,0,34],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}],id:86},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:[12,10],dependencies:[0],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2},id:40},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:[11],dependencies:[9],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}],id:41},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:[11],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}],id:42},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:[54],dependencies:[10],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2},id:43},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:[19,18,14],dependencies:[0],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}],id:44},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:[17,55],dependencies:[17],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1},id:45},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:[20,55],dependencies:[8],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}],id:46},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:[21,19],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:47},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:[46,49,23],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}],id:48},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:[48,21],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:49},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:[47,21],dependencies:[2],blockers:[],cost:1,display:{row:33,col:6},properties:{},id:50},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:[22,70],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:51},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:[51],dependencies:[12],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8},id:52},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:[63,30],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:53},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:[40],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}],id:54},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:[17,18],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[],id:55},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:[23,48],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}],id:56},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:[24],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[],id:57},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:[1],dependencies:[],blockers:[60],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}],id:58},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:[69,67],dependencies:[58],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}],id:59},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:[1],dependencies:[],blockers:[58],cost:1,display:{row:7,col:6},properties:{},effects:[],id:60},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:[68],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:3}],id:61},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:[33,12],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:5}],id:62},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:[25,28],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:7}],id:63},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:[42,14],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}],id:64},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:[40],dependencies:[10],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[],id:65},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:[26],dependencies:[65],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[],id:66},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:[59,6],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}],id:67},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:[84,4],dependencies:[7],blockers:[11,6,23],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}],id:68},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:[6,85],dependencies:[0],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}],id:69},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:[49],dependencies:[68],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}],id:70}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}],id:71},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:[71],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:72},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:[72],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}],id:73},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:[72],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}],id:74},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:[74],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}],id:75},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:[79],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}],id:76},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:[75],dependencies:[],blockers:[78],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}],id:77},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:[75],dependencies:[],blockers:[77],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}],id:78},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:[77],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}],id:79},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:[79,81],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:80},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:[78],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}],id:81},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:[79],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}],id:82},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:[79,85,80],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}],id:83},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:[80,83,85],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}],id:84},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:[81,83,80],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}],id:85},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:[81],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}],id:86},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:[82,88],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}],id:87},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:[83,87],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}],id:88},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:[84],dependencies:[79],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}],id:89},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:[85,91],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}],id:90},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:[86,90],dependencies:[79],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}],id:91},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:[90,91],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}],id:92},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:[94],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[],id:93},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:[89],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}],id:94},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:[92],dependencies:[81],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[],id:95},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:[87,88],dependencies:[81],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}],id:96},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:[96,98],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:97},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:[97,99,94],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:98},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:[98,100],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[],id:99},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:[99,95],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:100},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:[98,97],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}],id:101},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:[99,100],dependencies:[81],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}],id:102},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:[97],dependencies:[96],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"damMult"},scaling:[3],max:300}],id:103},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:[98,105],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}],id:104},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:[106,104],dependencies:[95],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[],id:105},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:[105,100],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[],id:106},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:[103,108],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}],id:107},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:[107,104],dependencies:[81],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}],id:108},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:[104,105,110],dependencies:[94],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[],id:109},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:[109,111],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}],id:110},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:[110,106],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}],id:111},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:[108,107],dependencies:[96],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[],id:112},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:[108],dependencies:[88],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}],id:113},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:[109,110],dependencies:[104],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}],id:114},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:[110,111],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[],id:115},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:[107,117],dependencies:[96],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}],id:116},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:[118,116],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}],id:117},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:[109,117],dependencies:[79],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}],id:118},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:[115],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}],id:119},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:[116,117],dependencies:[96],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[],id:120},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:[119,122],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}],id:121},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:[119],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}],id:122},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:[124,116],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}],id:123},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:[123,125],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}],id:124},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:[124,118],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}],id:125},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:[124,123],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[],id:126},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:[124,125],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}],id:127},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:[125,129],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[],id:128},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:[128,121,122],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:129},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:[123],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:130},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:[133],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}],id:131},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:[133],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}],id:132},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:[125],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}],id:133},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:[129],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[],id:134},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:[130],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[],id:135},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:[135],dependencies:[135],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[],id:136},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:[135,138],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[],id:137},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:[134,137],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:138},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:[134],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[],id:139}]} \ No newline at end of file diff --git a/js/atree_constants_str_old.js b/js/atree_constants_str_old.js index e0c7bc3..b604ecc 100644 --- a/js/atree_constants_str_old.js +++ b/js/atree_constants_str_old.js @@ -367,7 +367,7 @@ const atrees = "display_name": "Windy Feet", "base_abil": "Escape", "desc": "When casting Escape, give speed to yourself and nearby allies.", - "archetype": "Boltslinger", + "archetype": "", "archetype_req": 0, "parents": ["Arrow Storm"], "dependencies": [], @@ -1745,9 +1745,9 @@ const atrees = "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, - "scaling": [35], + "scaling": [3], "max": 3 } ] @@ -1776,7 +1776,7 @@ const atrees = "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, "scaling": [35], "max": 5 @@ -1807,7 +1807,7 @@ const atrees = "output": { "type": "stat", "abil_name": "Focus", - "name": "dmgPct" + "name": "damMult" }, "scaling": [35], "max": 7 @@ -3104,10 +3104,10 @@ const atrees = ], "output": { "type": "stat", - "name": "dmgPct" + "name": "damMult" }, - "scaling": [2], - "max": 200 + "scaling": [3], + "max": 300 } ] }, @@ -3870,7 +3870,7 @@ const atrees = "display_name": "Discombobulate", "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", "archetype": "Battle Monk", - "archetype_req": 12, + "archetype_req": 11, "parents": ["Cyclone"], "dependencies": [], "blockers": [], diff --git a/js/builder_graph.js b/js/builder_graph.js index 0098c11..4f6ac15 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -326,20 +326,6 @@ class WeaponInputDisplayNode extends ComputeNode { if (isNaN(dps)) dps = 0; } this.dps_field.textContent = Math.round(dps); - - //as of now, we NEED to have the dropdown tab visible/not hidden in order to properly display atree stuff. - if (!document.getElementById("toggle-atree").classList.contains("toggleOn")) { - toggle_tab('atree-dropdown'); - toggleButton('toggle-atree'); - } - - //for some reason we have to cast to string - construct_AT(document.getElementById("atree-ui"), atrees[wep_to_class.get(type)]); - - if (document.getElementById("toggle-atree").classList.contains("toggleOn")) { - toggle_tab('atree-dropdown'); - toggleButton('toggle-atree'); - } } } @@ -1051,6 +1037,7 @@ function builder_graph_init() { } stat_agg_node.link_to(edit_agg_node); build_disp_node.link_to(stat_agg_node, 'stats'); + atree_node.link_to(build_node, 'build'); for (const input_node of item_nodes.concat(powder_nodes)) { input_node.update(); @@ -1092,6 +1079,8 @@ function builder_graph_init() { let skp_output = new SkillPointSetterNode(edit_input_nodes); skp_output.link_to(build_node); + + edit_agg_node.link_to(build_node, 'build').link_to(item_nodes[8], 'weapon'); let build_warnings_node = new DisplayBuildWarningsNode(); build_warnings_node.link_to(build_node, 'build'); From 8007a808897deb02c5b2a005e68fe46fda0ee58b Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 18:11:17 -0700 Subject: [PATCH 42/68] Spell schema comment --- js/damage_calc.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/js/damage_calc.js b/js/damage_calc.js index 495bb55..74619bb 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -173,6 +173,47 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno return [total_dam_norm, total_dam_crit, damages_results]; } +/* +Spell schema: + +spell: { + name: str internal string name for the spell. Unique identifier + cost: Optional[int] ignored for spells that are not id 1-4 + display_text: str short description of the spell, ex. Bash, Meteor, Arrow Shield + base_spell: int spell index. 0-4 are reserved (0 is melee, 1-4 is common 4 spells) + spell_type: str [TODO: DEPRECATED/REMOVE] "healing" or "damage" + scaling: str "melee" or "spell" + display: str "total" to sum all parts. Or, the name of a spell part + parts: List[part] Parts of this spell (different stuff the spell does basically) +} + +NOTE: when using `replace_spell` on an existing spell, all fields become optional. +Specified fields overwrite existing fields; unspecified fields are left unchanged. + + +There are three possible spell "part" types: damage, heal, and total. + +part: spell_damage | spell_heal | spell_total + +spell_damage: { + name: str != "total" Name of the part. + type: "damage" [TODO: DEPRECATED/REMOVE] flag signaling what type of part it is. Can infer from fields + multipliers: array[num, 6] floating point spellmults (though supposedly wynn only supports integer mults) +} +spell_heal: { + name: str != "total" Name of the part. + type: "heal" [TODO: DEPRECATED/REMOVE] flag signaling what type of part it is. Can infer from fields + power: num floating point healing power (1 is 100% of max hp). +} +spell_total: { + name: str != "total" Name of the part. + type: "total" [TODO: DEPRECATED/REMOVE] flag signaling what type of part it is. Can infer from fields + hits: Map[str, num] Keys are other part names, numbers are the multipliers. Undefined behavior if subparts + are not the same type of spell. Can only pull from spells defined before it. +} + +*/ + const spell_table = { "wand": [ { title: "Heal", cost: 6, parts: [ From 913b5a7c85d2a668303cbfc8e64bc2727e7d1fe9 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 18:23:07 -0700 Subject: [PATCH 43/68] Fix guardian angels spell mult --- js/atree_constants.js | 4 ++-- js/atree_constants_str_old.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/atree_constants.js b/js/atree_constants.js index 2f01e7e..b52508c 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -435,12 +435,12 @@ const atrees = { "name": "Single Arrow", "type": "damage", "multipliers": [ - 40, + 30, 0, 0, 0, 0, - 20 + 10 ] }, { diff --git a/js/atree_constants_str_old.js b/js/atree_constants_str_old.js index b604ecc..8c4d906 100644 --- a/js/atree_constants_str_old.js +++ b/js/atree_constants_str_old.js @@ -343,7 +343,7 @@ const atrees = { "name": "Single Arrow", "type": "damage", - "multipliers": [40, 0, 0, 0, 0, 20] + "multipliers": [30, 0, 0, 0, 0, 10] }, { "name": "Single Bow", From 581891116d502209f4af039508587627172b2310 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 20:24:38 -0700 Subject: [PATCH 44/68] Fix a compute graph state update bug (double link), fix powder special display --- js/builder_graph.js | 16 ++++++++-------- js/damage_calc.js | 30 ++++++++++++++++++++++++++++++ js/display.js | 5 +++-- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/js/builder_graph.js b/js/builder_graph.js index 4f6ac15..d1825e2 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -833,14 +833,13 @@ class AggregateEditableIDNode extends ComputeNode { compute_func(input_map) { const build = input_map.get('build'); input_map.delete('build'); - const weapon = input_map.get('weapon'); input_map.delete('weapon'); const output_stats = new Map(build.statMap); for (const [k, v] of input_map.entries()) { output_stats.set(k, v); } - output_stats.set('classDef', classDefenseMultipliers.get(weapon.statMap.get("type"))); + output_stats.set('classDef', classDefenseMultipliers.get(build.weapon.statMap.get("type"))); return output_stats; } } @@ -946,6 +945,9 @@ let powder_nodes = []; let spelldmg_nodes = []; let edit_input_nodes = []; let skp_inputs = []; +let build_node; +let stat_agg_node; +let edit_agg_node; function builder_graph_init() { // Phase 1/2: Set up item input, propagate updates, etc. @@ -980,7 +982,7 @@ function builder_graph_init() { let level_input = new InputNode('level-input', document.getElementById('level-choice')); // "Build" now only refers to equipment and level (no powders). Powders are injected before damage calculation / stat display. - let build_node = new BuildAssembleNode(); + build_node = new BuildAssembleNode(); for (const input of item_nodes) { build_node.link_to(input); } @@ -1011,9 +1013,9 @@ function builder_graph_init() { build_disp_node.link_to(build_node, 'build'); // Create one node that will be the "aggregator node" (listen to all the editable id nodes, as well as the build_node (for non editable stats) and collect them into one statmap) - let stat_agg_node = new AggregateStatsNode(); - let edit_agg_node = new AggregateEditableIDNode(); - edit_agg_node.link_to(build_node, 'build').link_to(item_nodes[8], 'weapon'); + stat_agg_node = new AggregateStatsNode(); + edit_agg_node = new AggregateEditableIDNode(); + edit_agg_node.link_to(build_node, 'build'); for (const field of editable_item_fields) { // Create nodes that listens to each editable id input, the node name should match the "id" const elem = document.getElementById(field); @@ -1079,8 +1081,6 @@ function builder_graph_init() { let skp_output = new SkillPointSetterNode(edit_input_nodes); skp_output.link_to(build_node); - - edit_agg_node.link_to(build_node, 'build').link_to(item_nodes[8], 'weapon'); let build_warnings_node = new DisplayBuildWarningsNode(); build_warnings_node.link_to(build_node, 'build'); diff --git a/js/damage_calc.js b/js/damage_calc.js index 74619bb..2195926 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -214,6 +214,36 @@ spell_total: { */ +const default_spells = { + wand: [{ + name: "Melee", // TODO: name for melee attacks? + display_text: "Mage basic attack", + base_spell: 0, // Spell 0 is special cased to be handled with melee logic. + spell_type: "damage", + scaling: "melee", + display: "total", + parts: { name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] } + }], + spear: [{ + name: "Melee", // TODO: name for melee attacks? + display_text: "Warrior basic attack", + base_spell: 0, // Spell 0 is special cased to be handled with melee logic. + spell_type: "damage", + scaling: "melee", + display: "total", + parts: { name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] } + }], + bow: [ + + ], + dagger: [ + + ], + relik: [ + + ], +} + const spell_table = { "wand": [ { title: "Heal", cost: 6, parts: [ diff --git a/js/display.js b/js/display.js index a3edcf9..a47667d 100644 --- a/js/display.js +++ b/js/display.js @@ -1476,9 +1476,10 @@ function displayPowderSpecials(parent_elem, powderSpecials, stats, weapon, overa let tmp_conv = []; for (let i in part.conversion) { - tmp_conv.push(part.conversion[i] * part.multiplier[power-1]); + tmp_conv.push(part.conversion[i] * part.multiplier[power-1] / 100); } - let _results = calculateSpellDamage(stats, weapon, tmp_conv, false); + console.log(tmp_conv); + let _results = calculateSpellDamage(stats, weapon, tmp_conv, false, true); let critChance = skillPointsToPercentage(skillpoints[1]); let save_damages = []; From c7fd1c53f8ed1d9e33ac70c7fb0894b6b5321156 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 23:42:00 -0700 Subject: [PATCH 45/68] Internal spell representation overhaul Using new (more expressive) schema Somehow made display code cleaner !!! --- js/builder_graph.js | 87 ++++++++++++++++++++++++------ js/computation_graph.js | 23 ++++++++ js/damage_calc.js | 107 ++++++++++++++++++++++++------------ js/display.js | 116 ++++++++++++++++++---------------------- 4 files changed, 218 insertions(+), 115 deletions(-) diff --git a/js/builder_graph.js b/js/builder_graph.js index d1825e2..b8b4833 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -468,6 +468,7 @@ class PowderInputNode extends InputNode { * Signature: SpellSelectNode(build: Build) => [Spell, SpellParts] */ class SpellSelectNode extends ComputeNode { + // TODO: rewrite me entirely... constructor(spell_num) { super("builder-spell"+spell_num+"-select"); this.spell_idx = spell_num; @@ -475,10 +476,18 @@ class SpellSelectNode extends ComputeNode { compute_func(input_map) { const build = input_map.get('build'); + let stats = build.statMap; const i = this.spell_idx; - let spell = spell_table[build.weapon.statMap.get("type")][i]; - let stats = build.statMap; + const spells = default_spells[build.weapon.statMap.get("type")]; + let spell; + for (const _spell of spells) { + if (_spell.base_spell === i) { + spell = _spell; + break; + } + } + if (spell === undefined) { return null; } let spell_parts; if (spell.parts) { @@ -551,6 +560,7 @@ class SpellDamageCalcNode extends ComputeNode { compute_func(input_map) { const weapon = input_map.get('build').weapon.statMap; const spell_info = input_map.get('spell-info'); + const spell = spell_info[0]; const spell_parts = spell_info[1]; const stats = input_map.get('stats'); const damage_mult = stats.get('damageMultiplier'); @@ -562,23 +572,66 @@ class SpellDamageCalcNode extends ComputeNode { stats.get('agi') ]; let spell_results = [] + let spell_result_map = new Map(); + const use_speed = (('use_atkspd' in spell) ? spell.use_atkspd : true); + const use_spell = (('scaling' in spell) ? spell.scaling === 'spell' : true); + // TODO: move preprocessing to separate node/node chain for (const part of spell_parts) { - if (part.type === "damage") { - let tmp_conv = []; - for (let i in part.conversion) { - tmp_conv.push(part.conversion[i] * part.multiplier/100); + let spell_result; + if ('multipliers' in part) { // damage type spell + let results = calculateSpellDamage(stats, weapon, part.multipliers, use_spell, !use_speed); + spell_result = { + type: "damage", + normal_min: results[2].map(x => x[0]), + normal_max: results[2].map(x => x[1]), + normal_total: results[0], + crit_min: results[2].map(x => x[2]), + crit_max: results[2].map(x => x[3]), + crit_total: results[1], } - let results = calculateSpellDamage(stats, weapon, tmp_conv, true); - spell_results.push(results); - } else if (part.type === "heal") { + } else if ('power' in part) { // TODO: wynn2 formula - let heal_amount = (part.strength * getDefenseStats(stats)[0] * Math.max(0.5,Math.min(1.75, 1 + 0.5 * stats.get("wDamPct")/100))).toFixed(2); - spell_results.push(heal_amount); - } else if (part.type === "total") { - // TODO: remove "total" type - spell_results.push(null); + let _heal_amount = (part.strength * getDefenseStats(stats)[0] * Math.max(0.5,Math.min(1.75, 1 + 0.5 * stats.get("wDamPct")/100))).toFixed(2); + spell_result = { + type: "heal", + heal_amount: _heal_amount + } + } else if ('hits' in part) { + spell_result = { + normal_min: [0, 0, 0, 0, 0, 0], + normal_max: [0, 0, 0, 0, 0, 0], + normal_total: [0, 0], + crit_min: [0, 0, 0, 0, 0, 0], + crit_max: [0, 0, 0, 0, 0, 0], + crit_total: [0, 0] + } + const dam_res_keys = ['normal_min', 'normal_max', 'normal_total', 'crit_min', 'crit_max', 'crit_total']; + for (const [subpart_name, hits] of Object.entries(part.hits)) { + const subpart = spell_result_map.get(subpart_name); + if (spell_result.type) { + if (subpart.type !== spell_result.type) { + throw "SpellCalc total subpart type mismatch"; + } + } + else { + spell_result.type = subpart.type; + } + if (spell_result.type === 'damage') { + for (const key of dam_res_keys) { + for (let i in spell_result.normal_min) { + spell_result[key][i] += subpart[key][i] * hits; + } + } + } + else { + spell_result.heal_amount += subpart.heal_amount; + } + } } + spell_result.name = part.name; + spell_results.push(spell_result); + spell_result_map.set(part.name, spell_result); } return spell_results; } @@ -604,12 +657,11 @@ class SpellDisplayNode extends ComputeNode { const spell_info = input_map.get('spell-info'); const damages = input_map.get('spell-damage'); const spell = spell_info[0]; - const spell_parts = spell_info[1]; const i = this.spell_idx; let parent_elem = document.getElementById("spell"+i+"-info"); let overallparent_elem = document.getElementById("spell"+i+"-infoAvg"); - displaySpellDamage(parent_elem, overallparent_elem, stats, spell, i+1, spell_parts, damages); + displaySpellDamage(parent_elem, overallparent_elem, stats, spell, i+1, damages); } } @@ -1059,7 +1111,8 @@ function builder_graph_init() { // Also do something similar for skill points - for (let i = 0; i < 4; ++i) { + //for (let i = 0; i < 4; ++i) { + for (let i = 0; i < 1; ++i) { let spell_node = new SpellSelectNode(i); spell_node.link_to(build_node, 'build'); // TODO: link and rewrite spell_node to the stat agg node diff --git a/js/computation_graph.js b/js/computation_graph.js index 76b1c2d..a3903eb 100644 --- a/js/computation_graph.js +++ b/js/computation_graph.js @@ -89,6 +89,9 @@ class ComputeNode { throw "no compute func specified"; } + /** + * Add link to a parent compute node, optionally with an alias. + */ link_to(parent_node, link_name) { this.inputs.push(parent_node) link_name = (link_name !== undefined) ? link_name : parent_node.name; @@ -100,6 +103,26 @@ class ComputeNode { parent_node.children.push(this); return this; } + + /** + * Delete a link to a parent node. + * TODO: time complexity of list deletion (not super relevant but it hurts my soul) + */ + remove_link(parent_node) { + const idx = this.inputs.indexOf(parent_node); // Get idx + this.inputs.splice(idx, 1); // remove element + + this.input_translations.delete(parent_node.name); + const was_dirty = this.inputs_dirty.get(parent_node.name); + this.inputs_dirty.delete(parent_node.name); + if (was_dirty) { + this.inputs_dirty_count -= 1; + } + + const idx2 = parent_node.children.indexOf(this); + parent_node.children.splice(idx2, 1); + return this; + } } /** diff --git a/js/damage_calc.js b/js/damage_calc.js index 2195926..2710ec4 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -56,11 +56,14 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno // 2.2. Next, apply elemental conversions using damage computed in step 1.1. // Also, track which elements are present. (Add onto those present in the weapon itself.) + let total_convert = 0; //TODO get confirmation that this is how raw works. for (let i = 1; i <= 5; ++i) { if (conversions[i] > 0) { - damages[i][0] += conversions[i]/100 * weapon_min; - damages[i][1] += conversions[i]/100 * weapon_max; + const conv_frac = conversions[i]/100; + damages[i][0] += conv_frac * weapon_min; + damages[i][1] += conf_frac * weapon_max; present[i] = true; + total_convert += conv_frac } } @@ -125,22 +128,22 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno raw_boost += stats.get(damage_prefix+'Raw') + stats.get(damage_elements[i]+'DamRaw'); } // Next, rainraw and propRaw - let new_min = damages_obj[0] + raw_boost; - let new_max = damages_obj[1] + raw_boost; + let min_boost = raw_boost; + let max_boost = raw_boost; if (total_max > 0) { // TODO: what about total negative all raw? if (total_elem_min > 0) { - new_min += (damages_obj[0] / total_min) * prop_raw; + min_boost += (damages_obj[0] / total_min) * prop_raw; } - new_max += (damages_obj[1] / total_max) * prop_raw; + max_boost += (damages_obj[1] / total_max) * prop_raw; } if (i != 0 && total_elem_max > 0) { // rainraw TODO above if (total_elem_min > 0) { - new_min += (damages_obj[0] / total_elem_min) * rainbow_raw; + min_boost += (damages_obj[0] / total_elem_min) * rainbow_raw; } - new_max += (damages_obj[1] / total_elem_max) * rainbow_raw; + max_boost += (damages_obj[1] / total_elem_max) * rainbow_raw; } - damages_obj[0] = new_min; - damages_obj[1] = new_max; + damages_obj[0] += min_boost * total_convert; + damages_obj[1] += max_boost * total_convert; } // 6. Strength boosters @@ -182,8 +185,9 @@ spell: { display_text: str short description of the spell, ex. Bash, Meteor, Arrow Shield base_spell: int spell index. 0-4 are reserved (0 is melee, 1-4 is common 4 spells) spell_type: str [TODO: DEPRECATED/REMOVE] "healing" or "damage" - scaling: str "melee" or "spell" - display: str "total" to sum all parts. Or, the name of a spell part + scaling: Optional[str] [DEFAULT: "spell"] "melee" or "spell" + use_atkspd: Optional[bool] [DEFAULT: true] true to factor attack speed, false otherwise. + display: Optional[str] [DEFAULT: "total"] "total" to sum all parts. Or, the name of a spell part parts: List[part] Parts of this spell (different stuff the spell does basically) } @@ -212,37 +216,74 @@ spell_total: { are not the same type of spell. Can only pull from spells defined before it. } + +Before passing to display, use the following structs. +NOTE: total is collapsed into damage or healing. + +spell_damage: { + type: "damage" Internal use + name: str Display name of part. Should be human readable + normal_min: array[num, 6] floating point damages (no crit, min), can be less than zero. Order: NETWFA + normal_max: array[num, 6] floating point damages (no crit, max) + normal_total: array[num, 2] (min, max) noncrit total damage (not negative) + crit_min: array[num, 6] floating point damages (crit, min), can be less than zero. Order: NETWFA + crit_max: array[num, 6] floating point damages (crit, max) + crit_total: array[num, 2] (min, max) crit total damage (not negative) +} +spell_heal: { + type: "heal" Internal use + name: str Display name of part. Should be human readable + heal_amount: num floating point HP healed (self) +} + */ const default_spells = { wand: [{ - name: "Melee", // TODO: name for melee attacks? + name: "Magic Strike", // TODO: name for melee attacks? display_text: "Mage basic attack", - base_spell: 0, // Spell 0 is special cased to be handled with melee logic. - spell_type: "damage", - scaling: "melee", - display: "total", - parts: { name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] } + base_spell: 0, + scaling: "melee", use_atkspd: false, + display: "Melee", + parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] }], spear: [{ name: "Melee", // TODO: name for melee attacks? display_text: "Warrior basic attack", - base_spell: 0, // Spell 0 is special cased to be handled with melee logic. - spell_type: "damage", - scaling: "melee", - display: "total", - parts: { name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] } + base_spell: 0, + scaling: "melee", use_atkspd: false, + display: "Melee", + parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] }], - bow: [ - - ], - dagger: [ - - ], - relik: [ - - ], -} + bow: [{ + name: "Bow Shot", // TODO: name for melee attacks? + display_text: "Archer basic attack", + base_spell: 0, + scaling: "melee", use_atkspd: false, + display: "Melee", + parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] + }], + dagger: [{ + name: "Melee", // TODO: name for melee attacks? + display_text: "Assassin basic attack", + base_spell: 0, + scaling: "melee", use_atkspd: false, + display: "Melee", + parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] + }], + relik: [{ + name: "Spread Beam", // TODO: name for melee attacks? + display_text: "Shaman basic attack", + base_spell: 0, + spell_type: "damage", + scaling: "melee", use_atkspd: false, + display: "Total", + parts: [ + { name: "Single Beam", multipliers: [33, 0, 0, 0, 0, 0] }, + { name: "Total", hits: { "Single Beam": 3 } } + ] + }] +}; const spell_table = { "wand": [ diff --git a/js/display.js b/js/display.js index a47667d..e4114ed 100644 --- a/js/display.js +++ b/js/display.js @@ -1579,7 +1579,7 @@ function getBaseSpellCost(stats, spellIdx, cost) { } -function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spellIdx, spell_parts, damages) { +function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spellIdx, spell_results) { // TODO: remove spellIdx (just used to flag melee and cost) // TODO: move cost calc out parent_elem.textContent = ""; @@ -1589,7 +1589,7 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell overallparent_elem.textContent = ""; let title_elemavg = document.createElement("b"); - if (spellIdx != 0) { + if ('cost' in spell) { let first = document.createElement("span"); first.textContent = spell.title + " ("; title_elem.appendChild(first.cloneNode(true)); //cloneNode is needed here. @@ -1611,44 +1611,36 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell title_elemavg.appendChild(third_summary); } else { - title_elem.textContent = spell.title; - title_elemavg.textContent = spell.title; + title_elem.textContent = spell.name; + title_elemavg.textContent = spell.name; } parent_elem.append(title_elem); overallparent_elem.append(title_elemavg); - overallparent_elem.append(displayNextCosts(stats, spell, spellIdx)); + if ('cost' in spell) { + overallparent_elem.append(displayNextCosts(stats, spell, spellIdx)); + } let critChance = skillPointsToPercentage(stats.get('dex')); - let save_damages = []; - let part_divavg = document.createElement("p"); overallparent_elem.append(part_divavg); - for (let i = 0; i < spell_parts.length; ++i) { - const part = spell_parts[i]; - const damage = damages[i]; + for (let i = 0; i < spell_results.length; ++i) { + const damage_info = spell_results[i]; let part_div = document.createElement("p"); parent_elem.append(part_div); let subtitle_elem = document.createElement("p"); - subtitle_elem.textContent = part.subtitle; + subtitle_elem.textContent = damage_info.name part_div.append(subtitle_elem); - if (part.type === "damage") { - let _results = damage; - let totalDamNormal = _results[0]; - let totalDamCrit = _results[1]; - let results = _results[2]; - - for (let i = 0; i < 6; ++i) { - for (let j in results[i]) { - results[i][j] = results[i][j].toFixed(2); - } - } + if (damage_info.type === "damage") { + let totalDamNormal = damage_info.normal_total; + let totalDamCrit = damage_info.crit_total; + let nonCritAverage = (totalDamNormal[0]+totalDamNormal[1])/2 || 0; let critAverage = (totalDamCrit[0]+totalDamCrit[1])/2 || 0; let averageDamage = (1-critChance)*nonCritAverage+critChance*critAverage || 0; @@ -1659,11 +1651,11 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell part_div.append(averageLabel); - if (part.summary == true) { + if (damage_info.name === spell.display) { let overallaverageLabel = document.createElement("p"); let first = document.createElement("span"); let second = document.createElement("span"); - first.textContent = part.subtitle + " Average: "; + first.textContent = damage_info.name+ " Average: "; second.textContent = averageDamage.toFixed(2); overallaverageLabel.appendChild(first); overallaverageLabel.appendChild(second); @@ -1671,71 +1663,65 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell part_divavg.append(overallaverageLabel); } - function _damage_display(label_text, average, result_idx) { + function _damage_display(label_text, average, dmg_min, dmg_max) { let label = document.createElement("p"); label.textContent = label_text+average.toFixed(2); part_div.append(label); - let arrmin = []; - let arrmax = []; for (let i = 0; i < 6; i++){ - if (results[i][1] != 0){ + if (dmg_max[i] != 0){ let p = document.createElement("p"); p.classList.add(damageClasses[i]); - p.textContent = results[i][result_idx] + " \u2013 " + results[i][result_idx + 1]; - arrmin.push(results[i][result_idx]); - arrmax.push(results[i][result_idx + 1]); + p.textContent = dmg_min[i].toFixed(2)+" \u2013 "+dmg_max[i].toFixed(2); part_div.append(p); } } } - _damage_display("Non-Crit Average: ", nonCritAverage, 0); - _damage_display("Crit Average: ", critAverage, 2); - - save_damages.push(averageDamage); - } else if (part.type === "heal") { - let heal_amount = damage; + _damage_display("Non-Crit Average: ", nonCritAverage, damage_info.normal_min, damage_info.normal_max); + _damage_display("Crit Average: ", critAverage, damage_info.crit_min, damage_info.crit_max); + } else if (damage_info.type === "heal") { + let heal_amount = damage_info.heal_amount; let healLabel = document.createElement("p"); healLabel.textContent = heal_amount; // healLabel.classList.add("damagep"); part_div.append(healLabel); - if (part.summary == true) { + if (damage_info.name === spell.display) { let overallhealLabel = document.createElement("p"); let first = document.createElement("span"); let second = document.createElement("span"); - first.textContent = part.subtitle + ": "; + first.textContent = damage_info.name+ ": "; second.textContent = heal_amount; overallhealLabel.appendChild(first); second.classList.add("Set"); overallhealLabel.appendChild(second); part_divavg.append(overallhealLabel); } - } else if (part.type === "total") { - let total_damage = 0; - for (let i in part.factors) { - total_damage += save_damages[i] * part.factors[i]; - } - - let dmgarr = part.factors.slice(); - dmgarr = dmgarr.map(x => "(" + x + " * " + save_damages[dmgarr.indexOf(x)].toFixed(2) + ")"); - - - let averageLabel = document.createElement("p"); - averageLabel.textContent = "Average: "+total_damage.toFixed(2); - averageLabel.classList.add("damageSubtitle"); - part_div.append(averageLabel); - - let overallaverageLabel = document.createElement("p"); - let overallaverageLabelFirst = document.createElement("span"); - let overallaverageLabelSecond = document.createElement("span"); - overallaverageLabelFirst.textContent = "Average: "; - overallaverageLabelSecond.textContent = total_damage.toFixed(2); - overallaverageLabelSecond.classList.add("Damage"); - - - overallaverageLabel.appendChild(overallaverageLabelFirst); - overallaverageLabel.appendChild(overallaverageLabelSecond); - part_divavg.append(overallaverageLabel); +// } else if (part.type === "total") { +// let total_damage = 0; +// for (let i in part.factors) { +// total_damage += save_damages[i] * part.factors[i]; +// } +// +// let dmgarr = part.factors.slice(); +// dmgarr = dmgarr.map(x => "(" + x + " * " + save_damages[dmgarr.indexOf(x)].toFixed(2) + ")"); +// +// +// let averageLabel = document.createElement("p"); +// averageLabel.textContent = "Average: "+total_damage.toFixed(2); +// averageLabel.classList.add("damageSubtitle"); +// part_div.append(averageLabel); +// +// let overallaverageLabel = document.createElement("p"); +// let overallaverageLabelFirst = document.createElement("span"); +// let overallaverageLabelSecond = document.createElement("span"); +// overallaverageLabelFirst.textContent = "Average: "; +// overallaverageLabelSecond.textContent = total_damage.toFixed(2); +// overallaverageLabelSecond.classList.add("Damage"); +// +// +// overallaverageLabel.appendChild(overallaverageLabelFirst); +// overallaverageLabel.appendChild(overallaverageLabelSecond); +// part_divavg.append(overallaverageLabel); } } From 3fb59494d9d4d5af6eea7aa38436eec47f232c43 Mon Sep 17 00:00:00 2001 From: hppeng Date: Sun, 26 Jun 2022 23:54:05 -0700 Subject: [PATCH 46/68] Testing healing --- js/builder_graph.js | 7 +++--- js/damage_calc.js | 10 ++++++++ js/display.js | 58 +++++++++++---------------------------------- 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/js/builder_graph.js b/js/builder_graph.js index b8b4833..b371052 100644 --- a/js/builder_graph.js +++ b/js/builder_graph.js @@ -592,7 +592,7 @@ class SpellDamageCalcNode extends ComputeNode { } } else if ('power' in part) { // TODO: wynn2 formula - let _heal_amount = (part.strength * getDefenseStats(stats)[0] * Math.max(0.5,Math.min(1.75, 1 + 0.5 * stats.get("wDamPct")/100))).toFixed(2); + let _heal_amount = (part.power * getDefenseStats(stats)[0] * Math.max(0.5,Math.min(1.75, 1 + 0.5 * stats.get("wDamPct")/100))); spell_result = { type: "heal", heal_amount: _heal_amount @@ -604,7 +604,8 @@ class SpellDamageCalcNode extends ComputeNode { normal_total: [0, 0], crit_min: [0, 0, 0, 0, 0, 0], crit_max: [0, 0, 0, 0, 0, 0], - crit_total: [0, 0] + crit_total: [0, 0], + heal_amount: 0 } const dam_res_keys = ['normal_min', 'normal_max', 'normal_total', 'crit_min', 'crit_max', 'crit_total']; for (const [subpart_name, hits] of Object.entries(part.hits)) { @@ -1111,7 +1112,7 @@ function builder_graph_init() { // Also do something similar for skill points - //for (let i = 0; i < 4; ++i) { + //for (let i = 0; i < 4; ++i) { TODO: testing code for (let i = 0; i < 1; ++i) { let spell_node = new SpellSelectNode(i); spell_node.link_to(build_node, 'build'); diff --git a/js/damage_calc.js b/js/damage_calc.js index 2710ec4..9a18fbd 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -246,6 +246,16 @@ const default_spells = { scaling: "melee", use_atkspd: false, display: "Melee", parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] + }, { + name: "Heal", // TODO: name for melee attacks? + display_text: "Heal spell!", + base_spell: 1, + display: "Total Heal", + parts: [ + { name: "First Pulse", power: 0.12 }, + { name: "Second and Third Pulses", power: 0.06 }, + { name: "Total Heal", hits: { "First Pulse": 1, "Second and Third Pulses": 2 } } + ] }], spear: [{ name: "Melee", // TODO: name for melee attacks? diff --git a/js/display.js b/js/display.js index e4114ed..6f01d41 100644 --- a/js/display.js +++ b/js/display.js @@ -1627,6 +1627,18 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell let part_divavg = document.createElement("p"); overallparent_elem.append(part_divavg); + function _summary(text, val, fmt) { + let overallaverageLabel = document.createElement("p"); + let first = document.createElement("span"); + let second = document.createElement("span"); + first.textContent = text; + second.textContent = val.toFixed(2); + overallaverageLabel.appendChild(first); + overallaverageLabel.appendChild(second); + second.classList.add(fmt); + part_divavg.append(overallaverageLabel); + } + for (let i = 0; i < spell_results.length; ++i) { const damage_info = spell_results[i]; @@ -1652,15 +1664,7 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell if (damage_info.name === spell.display) { - let overallaverageLabel = document.createElement("p"); - let first = document.createElement("span"); - let second = document.createElement("span"); - first.textContent = damage_info.name+ " Average: "; - second.textContent = averageDamage.toFixed(2); - overallaverageLabel.appendChild(first); - overallaverageLabel.appendChild(second); - second.classList.add("Damage"); - part_divavg.append(overallaverageLabel); + _summary(damage_info.name+ " Average: ", averageDamage, "Damage"); } function _damage_display(label_text, average, dmg_min, dmg_max) { @@ -1686,42 +1690,8 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell // healLabel.classList.add("damagep"); part_div.append(healLabel); if (damage_info.name === spell.display) { - let overallhealLabel = document.createElement("p"); - let first = document.createElement("span"); - let second = document.createElement("span"); - first.textContent = damage_info.name+ ": "; - second.textContent = heal_amount; - overallhealLabel.appendChild(first); - second.classList.add("Set"); - overallhealLabel.appendChild(second); - part_divavg.append(overallhealLabel); + _summary(damage_info.name+ ": ", heal_amount, "Set"); } -// } else if (part.type === "total") { -// let total_damage = 0; -// for (let i in part.factors) { -// total_damage += save_damages[i] * part.factors[i]; -// } -// -// let dmgarr = part.factors.slice(); -// dmgarr = dmgarr.map(x => "(" + x + " * " + save_damages[dmgarr.indexOf(x)].toFixed(2) + ")"); -// -// -// let averageLabel = document.createElement("p"); -// averageLabel.textContent = "Average: "+total_damage.toFixed(2); -// averageLabel.classList.add("damageSubtitle"); -// part_div.append(averageLabel); -// -// let overallaverageLabel = document.createElement("p"); -// let overallaverageLabelFirst = document.createElement("span"); -// let overallaverageLabelSecond = document.createElement("span"); -// overallaverageLabelFirst.textContent = "Average: "; -// overallaverageLabelSecond.textContent = total_damage.toFixed(2); -// overallaverageLabelSecond.classList.add("Damage"); -// -// -// overallaverageLabel.appendChild(overallaverageLabelFirst); -// overallaverageLabel.appendChild(overallaverageLabelSecond); -// part_divavg.append(overallaverageLabel); } } From 65c2d397549858ff5cf32c068bda8257dff5c1ad Mon Sep 17 00:00:00 2001 From: ferricles Date: Mon, 27 Jun 2022 00:09:49 -0700 Subject: [PATCH 47/68] atree ID rework started --- js/atree-ids.json | 137 - py_script/atree-generateID.py | 4 +- py_script/atree-ids.json | 146 + py_script/atree-parse.json | 4967 +++++++++++++++++ .../textures}/items/boots/boots--chain.png | Bin .../textures}/items/boots/boots--diamond.png | Bin .../textures}/items/boots/boots--golden.png | Bin .../textures}/items/boots/boots--iron.png | Bin .../textures}/items/boots/boots--leather.png | Bin .../textures}/items/bow/bow--air1.png | Bin .../textures}/items/bow/bow--air2.png | Bin .../textures}/items/bow/bow--air3.png | Bin .../textures}/items/bow/bow--default1.png | Bin .../textures}/items/bow/bow--default2.png | Bin .../textures}/items/bow/bow--earth1.png | Bin .../textures}/items/bow/bow--earth2.png | Bin .../textures}/items/bow/bow--earth3.png | Bin .../textures}/items/bow/bow--fire1.png | Bin .../textures}/items/bow/bow--fire2.png | Bin .../textures}/items/bow/bow--fire3.png | Bin .../textures}/items/bow/bow--generic1.png | Bin .../textures}/items/bow/bow--generic2.png | Bin .../textures}/items/bow/bow--generic3.png | Bin .../textures}/items/bow/bow--thunder1.png | Bin .../textures}/items/bow/bow--thunder2.png | Bin .../textures}/items/bow/bow--thunder3.png | Bin .../textures}/items/bow/bow--water1.png | Bin .../textures}/items/bow/bow--water2.png | Bin .../textures}/items/bow/bow--water3.png | Bin .../items/chestplate/chestplate--chain.png | Bin .../items/chestplate/chestplate--diamond.png | Bin .../items/chestplate/chestplate--golden.png | Bin .../items/chestplate/chestplate--iron.png | Bin .../items/chestplate/chestplate--leather.png | Bin .../textures}/items/dagger/dagger--air1.png | Bin .../textures}/items/dagger/dagger--air2.png | Bin .../textures}/items/dagger/dagger--air3.png | Bin .../items/dagger/dagger--default1.png | Bin .../items/dagger/dagger--default2.png | Bin .../textures}/items/dagger/dagger--earth1.png | Bin .../textures}/items/dagger/dagger--earth2.png | Bin .../textures}/items/dagger/dagger--earth3.png | Bin .../textures}/items/dagger/dagger--fire1.png | Bin .../textures}/items/dagger/dagger--fire2.png | Bin .../textures}/items/dagger/dagger--fire3.png | Bin .../items/dagger/dagger--generic1.png | Bin .../items/dagger/dagger--generic2.png | Bin .../items/dagger/dagger--generic3.png | Bin .../items/dagger/dagger--thunder1.png | Bin .../items/dagger/dagger--thunder2.png | Bin .../items/dagger/dagger--thunder3.png | Bin .../textures}/items/dagger/dagger--water1.png | Bin .../textures}/items/dagger/dagger--water2.png | Bin .../textures}/items/dagger/dagger--water3.png | Bin .../textures}/items/helmet/helmet--chain.png | Bin .../items/helmet/helmet--diamond.png | Bin .../textures}/items/helmet/helmet--golden.png | Bin .../textures}/items/helmet/helmet--iron.png | Bin .../items/helmet/helmet--leather.png | Bin .../items/leggings/leggings--chain.png | Bin .../items/leggings/leggings--diamond.png | Bin .../items/leggings/leggings--golden.png | Bin .../items/leggings/leggings--iron.png | Bin .../items/leggings/leggings--leather.png | Bin .../textures}/items/relik/relik--air1.png | Bin .../textures}/items/relik/relik--air2.png | Bin .../textures}/items/relik/relik--air3.png | Bin .../textures}/items/relik/relik--default1.png | Bin .../textures}/items/relik/relik--default2.png | Bin .../textures}/items/relik/relik--earth1.png | Bin .../textures}/items/relik/relik--earth2.png | Bin .../textures}/items/relik/relik--earth3.png | Bin .../textures}/items/relik/relik--fire1.png | Bin .../textures}/items/relik/relik--fire2.png | Bin .../textures}/items/relik/relik--fire3.png | Bin .../textures}/items/relik/relik--generic1.png | Bin .../textures}/items/relik/relik--generic2.png | Bin .../textures}/items/relik/relik--generic3.png | 2 +- .../textures}/items/relik/relik--thunder1.png | Bin .../textures}/items/relik/relik--thunder2.png | Bin .../textures}/items/relik/relik--thunder3.png | Bin .../textures}/items/relik/relik--water1.png | 2 +- .../textures}/items/relik/relik--water2.png | 2 +- .../textures}/items/relik/relik--water3.png | 2 +- .../textures}/items/spear/spear--air1.png | Bin .../textures}/items/spear/spear--air2.png | Bin .../textures}/items/spear/spear--air3.png | Bin .../textures}/items/spear/spear--default1.png | Bin .../textures}/items/spear/spear--default2.png | Bin .../textures}/items/spear/spear--earth1.png | Bin .../textures}/items/spear/spear--earth2.png | Bin .../textures}/items/spear/spear--earth3.png | Bin .../textures}/items/spear/spear--fire1.png | Bin .../textures}/items/spear/spear--fire2.png | Bin .../textures}/items/spear/spear--fire3.png | Bin .../textures}/items/spear/spear--generic1.png | Bin .../textures}/items/spear/spear--generic2.png | Bin .../textures}/items/spear/spear--generic3.png | Bin .../textures}/items/spear/spear--thunder1.png | Bin .../textures}/items/spear/spear--thunder2.png | Bin .../textures}/items/spear/spear--thunder3.png | Bin .../textures}/items/spear/spear--water1.png | Bin .../textures}/items/spear/spear--water2.png | Bin .../textures}/items/spear/spear--water3.png | Bin .../textures}/items/wand/wand--air1.png | Bin .../textures}/items/wand/wand--air2.png | Bin .../textures}/items/wand/wand--air3.png | Bin .../textures}/items/wand/wand--default1.png | Bin .../textures}/items/wand/wand--default2.png | Bin .../textures}/items/wand/wand--earth1.png | Bin .../textures}/items/wand/wand--earth2.png | Bin .../textures}/items/wand/wand--earth3.png | Bin .../textures}/items/wand/wand--fire1.png | Bin .../textures}/items/wand/wand--fire2.png | Bin .../textures}/items/wand/wand--fire3.png | Bin .../textures}/items/wand/wand--generic1.png | Bin .../textures}/items/wand/wand--generic2.png | Bin .../textures}/items/wand/wand--generic3.png | 2 +- .../textures}/items/wand/wand--thunder1.png | Bin .../textures}/items/wand/wand--thunder2.png | Bin .../textures}/items/wand/wand--thunder3.png | Bin .../textures}/items/wand/wand--water1.png | Bin .../textures}/items/wand/wand--water2.png | Bin .../textures}/items/wand/wand--water3.png | Bin .../textures}/powder/dye_powder_cyan.png | Bin .../textures}/powder/dye_powder_gray.png | Bin .../textures}/powder/dye_powder_green.png | Bin .../powder/dye_powder_light_blue.png | Bin .../textures}/powder/dye_powder_lime.png | Bin .../textures}/powder/dye_powder_orange.png | Bin .../textures}/powder/dye_powder_pink.png | Bin .../textures}/powder/dye_powder_red.png | Bin .../textures}/powder/dye_powder_silver.png | Bin .../textures}/powder/dye_powder_yellow.png | Bin 134 files changed, 5121 insertions(+), 143 deletions(-) delete mode 100644 js/atree-ids.json create mode 100644 py_script/atree-ids.json create mode 100644 py_script/atree-parse.json rename {textures => py_script/textures}/items/boots/boots--chain.png (100%) rename {textures => py_script/textures}/items/boots/boots--diamond.png (100%) rename {textures => py_script/textures}/items/boots/boots--golden.png (100%) rename {textures => py_script/textures}/items/boots/boots--iron.png (100%) rename {textures => py_script/textures}/items/boots/boots--leather.png (100%) rename {textures => py_script/textures}/items/bow/bow--air1.png (100%) rename {textures => py_script/textures}/items/bow/bow--air2.png (100%) rename {textures => py_script/textures}/items/bow/bow--air3.png (100%) rename {textures => py_script/textures}/items/bow/bow--default1.png (100%) rename {textures => py_script/textures}/items/bow/bow--default2.png (100%) rename {textures => py_script/textures}/items/bow/bow--earth1.png (100%) rename {textures => py_script/textures}/items/bow/bow--earth2.png (100%) rename {textures => py_script/textures}/items/bow/bow--earth3.png (100%) rename {textures => py_script/textures}/items/bow/bow--fire1.png (100%) rename {textures => py_script/textures}/items/bow/bow--fire2.png (100%) rename {textures => py_script/textures}/items/bow/bow--fire3.png (100%) rename {textures => py_script/textures}/items/bow/bow--generic1.png (100%) rename {textures => py_script/textures}/items/bow/bow--generic2.png (100%) rename {textures => py_script/textures}/items/bow/bow--generic3.png (100%) rename {textures => py_script/textures}/items/bow/bow--thunder1.png (100%) rename {textures => py_script/textures}/items/bow/bow--thunder2.png (100%) rename {textures => py_script/textures}/items/bow/bow--thunder3.png (100%) rename {textures => py_script/textures}/items/bow/bow--water1.png (100%) rename {textures => py_script/textures}/items/bow/bow--water2.png (100%) rename {textures => py_script/textures}/items/bow/bow--water3.png (100%) rename {textures => py_script/textures}/items/chestplate/chestplate--chain.png (100%) rename {textures => py_script/textures}/items/chestplate/chestplate--diamond.png (100%) rename {textures => py_script/textures}/items/chestplate/chestplate--golden.png (100%) rename {textures => py_script/textures}/items/chestplate/chestplate--iron.png (100%) rename {textures => py_script/textures}/items/chestplate/chestplate--leather.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--air1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--air2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--air3.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--default1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--default2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--earth1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--earth2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--earth3.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--fire1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--fire2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--fire3.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--generic1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--generic2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--generic3.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--thunder1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--thunder2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--thunder3.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--water1.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--water2.png (100%) rename {textures => py_script/textures}/items/dagger/dagger--water3.png (100%) rename {textures => py_script/textures}/items/helmet/helmet--chain.png (100%) rename {textures => py_script/textures}/items/helmet/helmet--diamond.png (100%) rename {textures => py_script/textures}/items/helmet/helmet--golden.png (100%) rename {textures => py_script/textures}/items/helmet/helmet--iron.png (100%) rename {textures => py_script/textures}/items/helmet/helmet--leather.png (100%) rename {textures => py_script/textures}/items/leggings/leggings--chain.png (100%) rename {textures => py_script/textures}/items/leggings/leggings--diamond.png (100%) rename {textures => py_script/textures}/items/leggings/leggings--golden.png (100%) rename {textures => py_script/textures}/items/leggings/leggings--iron.png (100%) rename {textures => py_script/textures}/items/leggings/leggings--leather.png (100%) rename {textures => py_script/textures}/items/relik/relik--air1.png (100%) rename {textures => py_script/textures}/items/relik/relik--air2.png (100%) rename {textures => py_script/textures}/items/relik/relik--air3.png (100%) rename {textures => py_script/textures}/items/relik/relik--default1.png (100%) rename {textures => py_script/textures}/items/relik/relik--default2.png (100%) rename {textures => py_script/textures}/items/relik/relik--earth1.png (100%) rename {textures => py_script/textures}/items/relik/relik--earth2.png (100%) rename {textures => py_script/textures}/items/relik/relik--earth3.png (100%) rename {textures => py_script/textures}/items/relik/relik--fire1.png (100%) rename {textures => py_script/textures}/items/relik/relik--fire2.png (100%) rename {textures => py_script/textures}/items/relik/relik--fire3.png (100%) rename {textures => py_script/textures}/items/relik/relik--generic1.png (100%) rename {textures => py_script/textures}/items/relik/relik--generic2.png (100%) rename {textures => py_script/textures}/items/relik/relik--generic3.png (99%) rename {textures => py_script/textures}/items/relik/relik--thunder1.png (100%) rename {textures => py_script/textures}/items/relik/relik--thunder2.png (100%) rename {textures => py_script/textures}/items/relik/relik--thunder3.png (100%) rename {textures => py_script/textures}/items/relik/relik--water1.png (99%) rename {textures => py_script/textures}/items/relik/relik--water2.png (99%) rename {textures => py_script/textures}/items/relik/relik--water3.png (99%) rename {textures => py_script/textures}/items/spear/spear--air1.png (100%) rename {textures => py_script/textures}/items/spear/spear--air2.png (100%) rename {textures => py_script/textures}/items/spear/spear--air3.png (100%) rename {textures => py_script/textures}/items/spear/spear--default1.png (100%) rename {textures => py_script/textures}/items/spear/spear--default2.png (100%) rename {textures => py_script/textures}/items/spear/spear--earth1.png (100%) rename {textures => py_script/textures}/items/spear/spear--earth2.png (100%) rename {textures => py_script/textures}/items/spear/spear--earth3.png (100%) rename {textures => py_script/textures}/items/spear/spear--fire1.png (100%) rename {textures => py_script/textures}/items/spear/spear--fire2.png (100%) rename {textures => py_script/textures}/items/spear/spear--fire3.png (100%) rename {textures => py_script/textures}/items/spear/spear--generic1.png (100%) rename {textures => py_script/textures}/items/spear/spear--generic2.png (100%) rename {textures => py_script/textures}/items/spear/spear--generic3.png (100%) rename {textures => py_script/textures}/items/spear/spear--thunder1.png (100%) rename {textures => py_script/textures}/items/spear/spear--thunder2.png (100%) rename {textures => py_script/textures}/items/spear/spear--thunder3.png (100%) rename {textures => py_script/textures}/items/spear/spear--water1.png (100%) rename {textures => py_script/textures}/items/spear/spear--water2.png (100%) rename {textures => py_script/textures}/items/spear/spear--water3.png (100%) rename {textures => py_script/textures}/items/wand/wand--air1.png (100%) rename {textures => py_script/textures}/items/wand/wand--air2.png (100%) rename {textures => py_script/textures}/items/wand/wand--air3.png (100%) rename {textures => py_script/textures}/items/wand/wand--default1.png (100%) rename {textures => py_script/textures}/items/wand/wand--default2.png (100%) rename {textures => py_script/textures}/items/wand/wand--earth1.png (100%) rename {textures => py_script/textures}/items/wand/wand--earth2.png (100%) rename {textures => py_script/textures}/items/wand/wand--earth3.png (100%) rename {textures => py_script/textures}/items/wand/wand--fire1.png (100%) rename {textures => py_script/textures}/items/wand/wand--fire2.png (100%) rename {textures => py_script/textures}/items/wand/wand--fire3.png (100%) rename {textures => py_script/textures}/items/wand/wand--generic1.png (100%) rename {textures => py_script/textures}/items/wand/wand--generic2.png (100%) rename {textures => py_script/textures}/items/wand/wand--generic3.png (99%) rename {textures => py_script/textures}/items/wand/wand--thunder1.png (100%) rename {textures => py_script/textures}/items/wand/wand--thunder2.png (100%) rename {textures => py_script/textures}/items/wand/wand--thunder3.png (100%) rename {textures => py_script/textures}/items/wand/wand--water1.png (100%) rename {textures => py_script/textures}/items/wand/wand--water2.png (100%) rename {textures => py_script/textures}/items/wand/wand--water3.png (100%) rename {textures => py_script/textures}/powder/dye_powder_cyan.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_gray.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_green.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_light_blue.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_lime.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_orange.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_pink.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_red.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_silver.png (100%) mode change 100755 => 100644 rename {textures => py_script/textures}/powder/dye_powder_yellow.png (100%) mode change 100755 => 100644 diff --git a/js/atree-ids.json b/js/atree-ids.json deleted file mode 100644 index d04db13..0000000 --- a/js/atree-ids.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "Arrow Shield": 0, - "Escape": 1, - "Arrow Bomb": 2, - "Heart Shatter": 3, - "Fire Creep": 4, - "Bryophyte Roots": 5, - "Nimble String": 6, - "Arrow Storm": 7, - "Guardian Angels": 8, - "Windy Feet": 9, - "Basaltic Trap": 10, - "Windstorm": 11, - "Grappling Hook": 12, - "Implosion": 13, - "Twain's Arc": 14, - "Fierce Stomp": 15, - "Scorched Earth": 16, - "Leap": 17, - "Shocking Bomb": 18, - "Mana Trap": 19, - "Escape Artist": 20, - "Initiator": 21, - "Call of the Hound": 22, - "Arrow Hurricane": 23, - "Geyser Stomp": 24, - "Crepuscular Ray": 25, - "Grape Bomb": 26, - "Tangled Traps": 27, - "Snow Storm": 28, - "All-Seeing Panoptes": 29, - "Minefield": 30, - "Bow Proficiency I": 31, - "Cheaper Arrow Bomb": 32, - "Cheaper Arrow Storm": 33, - "Cheaper Escape": 34, - "Earth Mastery": 82, - "Thunder Mastery": 83, - "Water Mastery": 84, - "Air Mastery": 85, - "Fire Mastery": 86, - "More Shields": 40, - "Stormy Feet": 41, - "Refined Gunpowder": 42, - "More Traps": 43, - "Better Arrow Shield": 44, - "Better Leap": 45, - "Better Guardian Angels": 46, - "Cheaper Arrow Storm (2)": 47, - "Precise Shot": 48, - "Cheaper Arrow Shield": 49, - "Rocket Jump": 50, - "Cheaper Escape (2)": 51, - "Stronger Hook": 52, - "Cheaper Arrow Bomb (2)": 53, - "Bouncing Bomb": 54, - "Homing Shots": 55, - "Shrapnel Bomb": 56, - "Elusive": 57, - "Double Shots": 58, - "Triple Shots": 59, - "Power Shots": 60, - "Focus": 61, - "More Focus": 62, - "More Focus (2)": 63, - "Traveler": 64, - "Patient Hunter": 65, - "Stronger Patient Hunter": 66, - "Frenzy": 67, - "Phantom Ray": 68, - "Arrow Rain": 69, - "Decimator": 70, - "Bash": 71, - "Spear Proficiency 1": 72, - "Cheaper Bash": 73, - "Double Bash": 74, - "Charge": 75, - "Heavy Impact": 76, - "Vehement": 77, - "Tougher Skin": 78, - "Uppercut": 79, - "Cheaper Charge": 80, - "War Scream": 81, - "Quadruple Bash": 87, - "Fireworks": 88, - "Half-Moon Swipe": 89, - "Flyby Jab": 90, - "Flaming Uppercut": 91, - "Iron Lungs": 92, - "Generalist": 93, - "Counter": 94, - "Mantle of the Bovemists": 95, - "Bak'al's Grasp": 96, - "Spear Proficiency 2": 97, - "Cheaper Uppercut": 98, - "Aerodynamics": 99, - "Provoke": 100, - "Precise Strikes": 101, - "Air Shout": 102, - "Enraged Blow": 103, - "Flying Kick": 104, - "Stronger Mantle": 105, - "Manachism": 106, - "Boiling Blood": 107, - "Ragnarokkr": 108, - "Ambidextrous": 109, - "Burning Heart": 110, - "Stronger Bash": 111, - "Intoxicating Blood": 112, - "Comet": 113, - "Collide": 114, - "Rejuvenating Skin": 115, - "Uncontainable Corruption": 116, - "Radiant Devotee": 117, - "Whirlwind Strike": 118, - "Mythril Skin": 119, - "Armour Breaker": 120, - "Shield Strike": 121, - "Sparkling Hope": 122, - "Massive Bash": 123, - "Tempest": 124, - "Spirit of the Rabbit": 125, - "Massacre": 126, - "Axe Kick": 127, - "Radiance": 128, - "Cheaper Bash 2": 129, - "Cheaper War Scream": 130, - "Discombobulate": 131, - "Thunderclap": 132, - "Cyclone": 133, - "Second Chance": 134, - "Blood Pact": 135, - "Haemorrhage": 136, - "Brink of Madness": 137, - "Cheaper Uppercut 2": 138, - "Martyr": 139 -} \ No newline at end of file diff --git a/py_script/atree-generateID.py b/py_script/atree-generateID.py index 4355e72..4657cf1 100644 --- a/py_script/atree-generateID.py +++ b/py_script/atree-generateID.py @@ -11,6 +11,8 @@ abilDict = {} with open("atree-parse.json") as f: data = json.loads(f.read()) for classType, info in data.items(): + #reset IDs for every class and start at 1 + id = 1 for abil in info: abilDict[abil["display_name"]] = id id += 1 @@ -32,4 +34,4 @@ with open("atree-parse.json") as f: data[classType] = info with open('atree-constants-id.json', 'w', encoding='utf-8') as abil_dest: - json.dump(data, abil_dest, ensure_ascii=False, indent=4) + json.dump(data, abil_dest, ensure_ascii=False, indent=4) \ No newline at end of file diff --git a/py_script/atree-ids.json b/py_script/atree-ids.json new file mode 100644 index 0000000..16db827 --- /dev/null +++ b/py_script/atree-ids.json @@ -0,0 +1,146 @@ +{ + "Archer": { + "Arrow Shield": 1, + "Escape": 2, + "Arrow Bomb": 3, + "Heart Shatter": 4, + "Fire Creep": 5, + "Bryophyte Roots": 6, + "Nimble String": 7, + "Arrow Storm": 8, + "Guardian Angels": 9, + "Windy Feet": 10, + "Basaltic Trap": 11, + "Windstorm": 12, + "Grappling Hook": 13, + "Implosion": 14, + "Twain's Arc": 15, + "Fierce Stomp": 16, + "Scorched Earth": 17, + "Leap": 18, + "Shocking Bomb": 19, + "Mana Trap": 20, + "Escape Artist": 21, + "Initiator": 22, + "Call of the Hound": 23, + "Arrow Hurricane": 24, + "Geyser Stomp": 25, + "Crepuscular Ray": 26, + "Grape Bomb": 27, + "Tangled Traps": 28, + "Snow Storm": 29, + "All-Seeing Panoptes": 30, + "Minefield": 31, + "Bow Proficiency I": 32, + "Cheaper Arrow Bomb": 33, + "Cheaper Arrow Storm": 34, + "Cheaper Escape": 35, + "Earth Mastery": 36, + "Thunder Mastery": 37, + "Water Mastery": 38, + "Air Mastery": 39, + "Fire Mastery": 40, + "More Shields": 41, + "Stormy Feet": 42, + "Refined Gunpowder": 43, + "More Traps": 44, + "Better Arrow Shield": 45, + "Better Leap": 46, + "Better Guardian Angels": 47, + "Cheaper Arrow Storm (2)": 48, + "Precise Shot": 49, + "Cheaper Arrow Shield": 50, + "Rocket Jump": 51, + "Cheaper Escape (2)": 52, + "Stronger Hook": 53, + "Cheaper Arrow Bomb (2)": 54, + "Bouncing Bomb": 55, + "Homing Shots": 56, + "Shrapnel Bomb": 57, + "Elusive": 58, + "Double Shots": 59, + "Triple Shots": 60, + "Power Shots": 61, + "Focus": 62, + "More Focus": 63, + "More Focus (2)": 64, + "Traveler": 65, + "Patient Hunter": 66, + "Stronger Patient Hunter": 67, + "Frenzy": 68, + "Phantom Ray": 69, + "Arrow Rain": 70, + "Decimator": 71 + }, + "Warrior": { + "Bash": 1, + "Spear Proficiency 1": 2, + "Cheaper Bash": 3, + "Double Bash": 4, + "Charge": 5, + "Heavy Impact": 6, + "Vehement": 7, + "Tougher Skin": 8, + "Uppercut": 9, + "Cheaper Charge": 10, + "War Scream": 11, + "Earth Mastery": 12, + "Thunder Mastery": 13, + "Water Mastery": 14, + "Air Mastery": 15, + "Fire Mastery": 16, + "Quadruple Bash": 17, + "Fireworks": 18, + "Half-Moon Swipe": 19, + "Flyby Jab": 20, + "Flaming Uppercut": 21, + "Iron Lungs": 22, + "Generalist": 23, + "Counter": 24, + "Mantle of the Bovemists": 25, + "Bak'al's Grasp": 26, + "Spear Proficiency 2": 27, + "Cheaper Uppercut": 28, + "Aerodynamics": 29, + "Provoke": 30, + "Precise Strikes": 31, + "Air Shout": 32, + "Enraged Blow": 33, + "Flying Kick": 34, + "Stronger Mantle": 35, + "Manachism": 36, + "Boiling Blood": 37, + "Ragnarokkr": 38, + "Ambidextrous": 39, + "Burning Heart": 40, + "Stronger Bash": 41, + "Intoxicating Blood": 42, + "Comet": 43, + "Collide": 44, + "Rejuvenating Skin": 45, + "Uncontainable Corruption": 46, + "Radiant Devotee": 47, + "Whirlwind Strike": 48, + "Mythril Skin": 49, + "Armour Breaker": 50, + "Shield Strike": 51, + "Sparkling Hope": 52, + "Massive Bash": 53, + "Tempest": 54, + "Spirit of the Rabbit": 55, + "Massacre": 56, + "Axe Kick": 57, + "Radiance": 58, + "Cheaper Bash 2": 59, + "Cheaper War Scream": 60, + "Discombobulate": 61, + "Thunderclap": 62, + "Cyclone": 63, + "Second Chance": 64, + "Blood Pact": 65, + "Haemorrhage": 66, + "Brink of Madness": 67, + "Cheaper Uppercut 2": 68, + "Martyr": 69 + } +} \ No newline at end of file diff --git a/py_script/atree-parse.json b/py_script/atree-parse.json new file mode 100644 index 0000000..7eabec7 --- /dev/null +++ b/py_script/atree-parse.json @@ -0,0 +1,4967 @@ +{ + "Archer": [ + { + "display_name": "Arrow Shield", + "desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)", + "archetype": "", + "archetype_req": 0, + "parents": [ + 60, + 34 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 6 + }, + "properties": { + "duration": 60 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Shield", + "cost": 30, + "display_text": "Max Damage", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "", + "parts": [ + { + "name": "Shield Damage", + "type": "damage", + "multipliers": [ + 90, + 0, + 0, + 0, + 0, + 10 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Shield Damage": 2 + } + } + ] + } + ], + "id": 0 + }, + { + "display_name": "Escape", + "desc": "Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)", + "archetype": "", + "archetype_req": 0, + "parents": [ + 3 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 7, + "col": 4 + }, + "properties": { + "aoe": 0, + "range": 0 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Escape", + "cost": 25, + "display_text": "Max Damage", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } + } + ] + } + ], + "id": 1 + }, + { + "display_name": "Arrow Bomb", + "desc": "Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)", + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 0, + "col": 4 + }, + "properties": { + "aoe": 4.5, + "range": 26 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Bomb", + "cost": 50, + "display_text": "Average Damage", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Arrow Bomb", + "type": "damage", + "multipliers": [ + 160, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Arrow Bomb": 1 + } + } + ] + } + ], + "id": 2 + }, + { + "display_name": "Heart Shatter", + "desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 31 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 4, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + }, + {} + ], + "id": 3 + }, + { + "display_name": "Fire Creep", + "desc": "Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 68, + 86, + 5 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 6 + }, + "properties": { + "aoe": 0.8, + "duration": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fire Creep": 15 + } + } + ], + "id": 4 + }, + { + "display_name": "Bryophyte Roots", + "desc": "When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.", + "archetype": "Trapper", + "archetype_req": 1, + "parents": [ + 4, + 82 + ], + "dependencies": [ + 7 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 8 + }, + "properties": { + "aoe": 2, + "duration": 5, + "slowness": 0.4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Bryophyte Roots", + "cost": 0, + "multipliers": [ + 40, + 20, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 5 + }, + { + "display_name": "Nimble String", + "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 83, + 69 + ], + "dependencies": [ + 7 + ], + "blockers": [ + 68 + ], + "cost": 2, + "display": { + "row": 15, + "col": 2 + }, + "properties": { + "shootspeed": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + -15, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Stream", + "cost": 0, + "hits": { + "Single Arrow": 8 + } + } + ], + "id": 6 + }, + { + "display_name": "Arrow Storm", + "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 58, + 34 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 2 + }, + "properties": { + "aoe": 0, + "range": 16 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Arrow Storm", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 30, + 0, + 10, + 0, + 0, + 0 + ] + }, + { + "name": "Single Stream", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Stream": 2 + } + } + ] + } + ], + "id": 7 + }, + { + "display_name": "Guardian Angels", + "desc": "Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)", + "archetype": "Boltslinger", + "archetype_req": 3, + "parents": [ + 59, + 67 + ], + "dependencies": [ + 0 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 1 + }, + "properties": { + "range": 4, + "duration": 60, + "shots": 8, + "count": 2 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Guardian Angels", + "cost": 30, + "display_text": "Total Damage Average", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 20 + ] + }, + { + "name": "Single Bow", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Bow": 2 + } + } + ] + } + ], + "id": 8 + }, + { + "display_name": "Windy Feet", + "base_abil": "Escape", + "desc": "When casting Escape, give speed to yourself and nearby allies.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 7 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 1 + }, + "properties": { + "aoe": 8, + "duration": 120 + }, + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spd", + "value": 20 + } + ], + "id": 9 + }, + { + "display_name": "Basaltic Trap", + "desc": "When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)", + "archetype": "Trapper", + "archetype_req": 2, + "parents": [ + 5 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 8 + }, + "properties": { + "aoe": 7, + "traps": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [ + 140, + 30, + 0, + 0, + 30, + 0 + ] + } + ], + "id": 10 + }, + { + "display_name": "Windstorm", + "desc": "Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 8, + 33 + ], + "dependencies": [], + "blockers": [ + 68 + ], + "cost": 2, + "display": { + "row": 21, + "col": 1 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + -11, + 0, + -7, + 0, + 0, + 3 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 1 + } + } + ], + "id": 11 + }, + { + "display_name": "Grappling Hook", + "base_abil": "Escape", + "desc": "When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 61, + 40, + 33 + ], + "dependencies": [], + "blockers": [ + 20 + ], + "cost": 2, + "display": { + "row": 21, + "col": 5 + }, + "properties": { + "range": 20 + }, + "effects": [], + "id": 12 + }, + { + "display_name": "Implosion", + "desc": "Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 12, + 40 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 6 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 13 + }, + { + "display_name": "Twain's Arc", + "desc": "When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)", + "archetype": "Sharpshooter", + "archetype_req": 4, + "parents": [ + 62, + 64 + ], + "dependencies": [ + 61 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 25, + "col": 4 + }, + "properties": { + "range": 64, + "focusReq": 2 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Twain's Arc", + "cost": 0, + "display_text": "Twain's Arc", + "base_spell": 5, + "spell_type": "damage", + "scaling": "melee", + "display": "Twain's Arc Damage", + "parts": [ + { + "name": "Twain's Arc Damage", + "type": "damage", + "multipliers": [ + 200, + 0, + 0, + 0, + 0, + 0 + ] + } + ] + } + ], + "id": 14 + }, + { + "display_name": "Fierce Stomp", + "desc": "When using Escape, hold shift to quickly drop down and deal damage.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 42, + 64 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 1 + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fierce Stomp": 1 + } + } + ], + "id": 15 + }, + { + "display_name": "Scorched Earth", + "desc": "Fire Creep become much stronger.", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 14 + ], + "dependencies": [ + 4 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 5 + }, + "properties": { + "duration": 2, + "aoe": 0.4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [ + 10, + 0, + 0, + 0, + 5, + 0 + ] + } + ], + "id": 16 + }, + { + "display_name": "Leap", + "desc": "When you double tap jump, leap foward. (2s Cooldown)", + "archetype": "Boltslinger", + "archetype_req": 5, + "parents": [ + 42, + 55 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 0 + }, + "properties": { + "cooldown": 2 + }, + "effects": [], + "id": 17 + }, + { + "display_name": "Shocking Bomb", + "desc": "Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.", + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": [ + 14, + 44, + 55 + ], + "dependencies": [ + 2 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 4 + }, + "properties": { + "gravity": 0 + }, + "effects": [ + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + } + ], + "id": 18 + }, + { + "display_name": "Mana Trap", + "desc": "Your Traps will give you 4 Mana per second when you stay close to them.", + "archetype": "Trapper", + "archetype_req": 5, + "parents": [ + 43, + 44 + ], + "dependencies": [ + 4 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 8 + }, + "properties": { + "range": 12, + "manaRegen": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 10, + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 19 + }, + { + "display_name": "Escape Artist", + "desc": "When casting Escape, release 100 arrows towards the ground.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 46, + 17 + ], + "dependencies": [], + "blockers": [ + 12 + ], + "cost": 2, + "display": { + "row": 31, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Escape Artist", + "cost": 0, + "multipliers": [ + 30, + 0, + 10, + 0, + 0, + 0 + ] + } + ], + "id": 20 + }, + { + "display_name": "Initiator", + "desc": "If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.", + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": [ + 18, + 44, + 47 + ], + "dependencies": [ + 61 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 31, + "col": 5 + }, + "properties": { + "focus": 1, + "timer": 5 + }, + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "damPct", + "value": 50 + } + ], + "id": 21 + }, + { + "display_name": "Call of the Hound", + "desc": "Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 21, + 47 + ], + "dependencies": [ + 0 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 7 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Call of the Hound", + "cost": 0, + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 22 + }, + { + "display_name": "Arrow Hurricane", + "desc": "Arrow Storm will shoot +2 stream of arrows.", + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": [ + 48, + 20 + ], + "dependencies": [], + "blockers": [ + 68 + ], + "cost": 2, + "display": { + "row": 33, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 2 + } + } + ], + "id": 23 + }, + { + "display_name": "Geyser Stomp", + "desc": "Fierce Stomp will create geysers, dealing more damage and vertical knockback.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 56 + ], + "dependencies": [ + 15 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 1 + }, + "properties": { + "aoe": 1 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 50, + 0, + 0 + ] + } + ], + "id": 24 + }, + { + "display_name": "Crepuscular Ray", + "desc": "If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.", + "archetype": "Sharpshooter", + "archetype_req": 10, + "parents": [ + 49 + ], + "dependencies": [ + 7 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 4 + }, + "properties": { + "focusReq": 5, + "focusRegen": -1 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Crepuscular Ray", + "base_spell": 5, + "spell_type": "damage", + "scaling": "spell", + "display": "One Focus", + "cost": 0, + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 10, + 0, + 0, + 5, + 0, + 0 + ] + }, + { + "name": "One Focus", + "type": "total", + "hits": { + "Single Arrow": 20 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "One Focus": 7 + } + } + ] + } + ], + "id": 25 + }, + { + "display_name": "Grape Bomb", + "desc": "Arrow bomb will throw 3 additional smaller bombs when exploding.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 51 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 37, + "col": 7 + }, + "properties": { + "miniBombs": 3, + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Grape Bomb", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 10, + 0 + ] + } + ], + "id": 26 + }, + { + "display_name": "Tangled Traps", + "desc": "Your Traps will be connected by a rope that deals damage to enemies every 0.2s.", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 26 + ], + "dependencies": [ + 10 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 38, + "col": 6 + }, + "properties": { + "attackSpeed": 0.2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Tangled Traps", + "cost": 0, + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 20 + ] + } + ], + "id": 27 + }, + { + "display_name": "Snow Storm", + "desc": "Enemies near you will be slowed down.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 24, + 63 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 39, + "col": 2 + }, + "properties": { + "range": 2.5, + "slowness": 0.3 + }, + "id": 28 + }, + { + "display_name": "All-Seeing Panoptes", + "desc": "Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.", + "archetype": "Boltslinger", + "archetype_req": 11, + "parents": [ + 28 + ], + "dependencies": [ + 8 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 40, + "col": 1 + }, + "properties": { + "range": 10, + "shots": 5 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 0, + 20, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 5 + } + } + ], + "id": 29 + }, + { + "display_name": "Minefield", + "desc": "Allow you to place +6 Traps, but with reduced damage and range.", + "archetype": "Trapper", + "archetype_req": 10, + "parents": [ + 26, + 53 + ], + "dependencies": [ + 10 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 40, + "col": 7 + }, + "properties": { + "aoe": -2, + "traps": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [ + -80, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 30 + }, + { + "display_name": "Bow Proficiency I", + "desc": "Improve your Main Attack's damage and range when using a bow.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 2 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 4 + }, + "properties": { + "mainAtk_range": 6 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ], + "id": 31 + }, + { + "display_name": "Cheaper Arrow Bomb", + "desc": "Reduce the Mana cost of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 31 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 6 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -10 + } + ], + "id": 32 + }, + { + "display_name": "Cheaper Arrow Storm", + "desc": "Reduce the Mana cost of Arrow Storm.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 12, + 11, + 61 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 21, + "col": 3 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ], + "id": 33 + }, + { + "display_name": "Cheaper Escape", + "desc": "Reduce the Mana cost of Escape.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 7, + 0 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ], + "id": 34 + }, + { + "display_name": "Earth Mastery", + "desc": "Increases your base damage from all Earth attacks", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 0 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 8 + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "eDamPct", + "value": 20 + }, + { + "type": "stat", + "name": "eDam", + "value": [ + 2, + 4 + ] + } + ] + } + ], + "id": 82 + }, + { + "display_name": "Thunder Mastery", + "desc": "Increases your base damage from all Thunder attacks", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 7, + 86, + 34 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 2 + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "tDamPct", + "value": 10 + }, + { + "type": "stat", + "name": "tDam", + "value": [ + 1, + 8 + ] + } + ] + } + ], + "id": 83 + }, + { + "display_name": "Water Mastery", + "desc": "Increases your base damage from all Water attacks", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 34, + 83, + 86 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 14, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "wDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "wDam", + "value": [ + 2, + 4 + ] + } + ] + } + ], + "id": 84 + }, + { + "display_name": "Air Mastery", + "desc": "Increases base damage from all Air attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 7 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "aDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "aDam", + "value": [ + 3, + 4 + ] + } + ] + } + ], + "id": 85 + }, + { + "display_name": "Fire Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 83, + 0, + 34 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 6 + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "fDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "fDam", + "value": [ + 3, + 5 + ] + } + ] + } + ], + "id": 86 + }, + { + "display_name": "More Shields", + "desc": "Give +2 charges to Arrow Shield.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 12, + 10 + ], + "dependencies": [ + 0 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 21, + "col": 7 + }, + "properties": { + "shieldCharges": 2 + }, + "id": 40 + }, + { + "display_name": "Stormy Feet", + "desc": "Windy Feet will last longer and add more speed.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 11 + ], + "dependencies": [ + 9 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 23, + "col": 1 + }, + "properties": { + "duration": 60 + }, + "effects": [ + { + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spdPct", + "value": 20 + } + ] + } + ], + "id": 41 + }, + { + "display_name": "Refined Gunpowder", + "desc": "Increase the damage of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 11 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 25, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [ + 50, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 42 + }, + { + "display_name": "More Traps", + "desc": "Increase the maximum amount of active Traps you can have by +2.", + "archetype": "Trapper", + "archetype_req": 10, + "parents": [ + 54 + ], + "dependencies": [ + 10 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 8 + }, + "properties": { + "traps": 2 + }, + "id": 43 + }, + { + "display_name": "Better Arrow Shield", + "desc": "Arrow Shield will gain additional area of effect, knockback and damage.", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 19, + 18, + 14 + ], + "dependencies": [ + 0 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 28, + "col": 6 + }, + "properties": { + "aoe": 1 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Shield", + "multipliers": [ + 40, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 44 + }, + { + "display_name": "Better Leap", + "desc": "Reduce leap's cooldown by 1s.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 17, + 55 + ], + "dependencies": [ + 17 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 1 + }, + "properties": { + "cooldown": -1 + }, + "id": 45 + }, + { + "display_name": "Better Guardian Angels", + "desc": "Your Guardian Angels can shoot +4 arrows before disappearing.", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 20, + 55 + ], + "dependencies": [ + 8 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 2 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 4 + } + } + ], + "id": 46 + }, + { + "display_name": "Cheaper Arrow Storm (2)", + "desc": "Reduce the Mana cost of Arrow Storm.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 21, + 19 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 8 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ], + "id": 47 + }, + { + "display_name": "Precise Shot", + "desc": "+30% Critical Hit Damage", + "archetype": "", + "archetype_req": 0, + "parents": [ + 46, + 49, + 23 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 2 + }, + "properties": { + "mainAtk_range": 6 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdCritPct", + "value": 30 + } + ] + } + ], + "id": 48 + }, + { + "display_name": "Cheaper Arrow Shield", + "desc": "Reduce the Mana cost of Arrow Shield.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 48, + 21 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ], + "id": 49 + }, + { + "display_name": "Rocket Jump", + "desc": "Arrow Bomb's self-damage will knockback you farther away.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 47, + 21 + ], + "dependencies": [ + 2 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 33, + "col": 6 + }, + "properties": {}, + "id": 50 + }, + { + "display_name": "Cheaper Escape (2)", + "desc": "Reduce the Mana cost of Escape.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 22, + 70 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 34, + "col": 7 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ], + "id": 51 + }, + { + "display_name": "Stronger Hook", + "desc": "Increase your Grappling Hook's range, speed and strength.", + "archetype": "Trapper", + "archetype_req": 5, + "parents": [ + 51 + ], + "dependencies": [ + 12 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 8 + }, + "properties": { + "range": 8 + }, + "id": 52 + }, + { + "display_name": "Cheaper Arrow Bomb (2)", + "desc": "Reduce the Mana cost of Arrow Bomb.", + "archetype": "", + "archetype_req": 0, + "parents": [ + 63, + 30 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 40, + "col": 5 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ], + "id": 53 + }, + { + "display_name": "Bouncing Bomb", + "desc": "Arrow Bomb will bounce once when hitting a block or enemy", + "archetype": "", + "archetype_req": 0, + "parents": [ + 40 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 25, + "col": 7 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Arrow Bomb": 2 + } + } + ], + "id": 54 + }, + { + "display_name": "Homing Shots", + "desc": "Your Main Attack arrows will follow nearby enemies and not be affected by gravity", + "archetype": "", + "archetype_req": 0, + "parents": [ + 17, + 18 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 2 + }, + "properties": {}, + "effects": [], + "id": 55 + }, + { + "display_name": "Shrapnel Bomb", + "desc": "Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area", + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": [ + 23, + 48 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 34, + "col": 1 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Shrapnel Bomb", + "cost": 0, + "multipliers": [ + 40, + 0, + 0, + 0, + 20, + 0 + ] + } + ], + "id": 56 + }, + { + "display_name": "Elusive", + "desc": "If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 24 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 38, + "col": 0 + }, + "properties": {}, + "effects": [], + "id": 57 + }, + { + "display_name": "Double Shots", + "desc": "Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 1 + ], + "dependencies": [], + "blockers": [ + 60 + ], + "cost": 1, + "display": { + "row": 7, + "col": 2 + }, + "properties": { + "arrow": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 0, + "target_part": "Melee Damage", + "cost": 0, + "multipliers": 0.7 + } + ], + "id": 58 + }, + { + "display_name": "Triple Shots", + "desc": "Triple Main Attack arrows, but they deal -20% damage per arrow", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 69, + 67 + ], + "dependencies": [ + 58 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 0 + }, + "properties": { + "arrow": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 0, + "target_part": "Melee Damage", + "cost": 0, + "multipliers": 0.7 + } + ], + "id": 59 + }, + { + "display_name": "Power Shots", + "desc": "Main Attack arrows have increased speed and knockback", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 1 + ], + "dependencies": [], + "blockers": [ + 58 + ], + "cost": 1, + "display": { + "row": 7, + "col": 6 + }, + "properties": {}, + "effects": [], + "id": 60 + }, + { + "display_name": "Focus", + "desc": "When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once", + "archetype": "Sharpshooter", + "archetype_req": 2, + "parents": [ + 68 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 19, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [ + 35 + ], + "max": 3 + } + ], + "id": 61 + }, + { + "display_name": "More Focus", + "desc": "Add +2 max Focus", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 33, + 12 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [ + 35 + ], + "max": 5 + } + ], + "id": 62 + }, + { + "display_name": "More Focus (2)", + "desc": "Add +2 max Focus", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 25, + 28 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 39, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Focus", + "output": { + "type": "stat", + "abil_name": "Focus", + "name": "dmgPct" + }, + "scaling": [ + 35 + ], + "max": 7 + } + ], + "id": 63 + }, + { + "display_name": "Traveler", + "desc": "For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)", + "archetype": "", + "archetype_req": 0, + "parents": [ + 42, + 14 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 25, + "col": 2 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "spd" + } + ], + "output": { + "type": "stat", + "name": "sdRaw" + }, + "scaling": [ + 1 + ], + "max": 100 + } + ], + "id": 64 + }, + { + "display_name": "Patient Hunter", + "desc": "Your Traps will deal +20% more damage for every second they are active (Max +80%)", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 40 + ], + "dependencies": [ + 10 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 8 + }, + "properties": { + "max": 80 + }, + "effects": [], + "id": 65 + }, + { + "display_name": "Stronger Patient Hunter", + "desc": "Add +80% Max Damage to Patient Hunter", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 26 + ], + "dependencies": [ + 65 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 38, + "col": 8 + }, + "properties": { + "max": 80 + }, + "effects": [], + "id": 66 + }, + { + "display_name": "Frenzy", + "desc": "Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second", + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": [ + 59, + 6 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 17, + "col": 2 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Hits dealt", + "output": { + "type": "stat", + "name": "spd" + }, + "scaling": [ + 6 + ], + "max": 200 + } + ], + "id": 67 + }, + { + "display_name": "Phantom Ray", + "desc": "Condense Arrow Storm into a single ray that damages enemies 10 times per second", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 84, + 4 + ], + "dependencies": [ + 7 + ], + "blockers": [ + 11, + 6, + 23 + ], + "cost": 2, + "display": { + "row": 16, + "col": 4 + }, + "properties": {}, + "effects": [ + { + "type": "replace_spell", + "name": "Phantom Ray", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [ + 25, + 0, + 5, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Arrow": 16 + } + } + ] + } + ], + "id": 68 + }, + { + "display_name": "Arrow Rain", + "desc": "When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies", + "archetype": "Trapper", + "archetype_req": 0, + "parents": [ + 6, + 85 + ], + "dependencies": [ + 0 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 0 + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Arrow Rain", + "cost": 0, + "multipliers": [ + 120, + 0, + 0, + 0, + 0, + 80 + ] + } + ], + "id": 69 + }, + { + "display_name": "Decimator", + "desc": "Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)", + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": [ + 49 + ], + "dependencies": [ + 68 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 34, + "col": 5 + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Phantom Ray hits", + "output": { + "type": "stat", + "name": "PhRayDmg" + }, + "scaling": 10, + "max": 50 + } + ], + "id": 70 + } + ], + "Warrior": [ + { + "display_name": "Bash", + "desc": "Violently bash the ground, dealing high damage in a large area", + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 0, + "col": 4, + "icon": "node_4" + }, + "properties": { + "aoe": 4, + "range": 3 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Bash", + "cost": 45, + "display_text": "Total Damage Average", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Hit", + "type": "damage", + "multipliers": [ + 130, + 20, + 0, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Hit": 1 + } + } + ] + } + ], + "id": 71 + }, + { + "display_name": "Spear Proficiency 1", + "desc": "Improve your Main Attack's damage and range w/ spear", + "archetype": "", + "archetype_req": 0, + "parents": [ + 71 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 4, + "icon": "node_0" + }, + "properties": { + "melee_range": 1 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ], + "id": 72 + }, + { + "display_name": "Cheaper Bash", + "desc": "Reduce the Mana cost of Bash", + "archetype": "", + "archetype_req": 0, + "parents": [ + 72 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 2, + "col": 2, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -10 + } + ], + "id": 73 + }, + { + "display_name": "Double Bash", + "desc": "Bash will hit a second time at a farther range", + "archetype": "", + "archetype_req": 0, + "parents": [ + 72 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 4, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 3 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "name": "Single Hit", + "value": 1 + } + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [ + -50, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 74 + }, + { + "display_name": "Charge", + "desc": "Charge forward at high speed (hold shift to cancel)", + "archetype": "", + "archetype_req": 0, + "parents": [ + 74 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 6, + "col": 4, + "icon": "node_4" + }, + "properties": {}, + "effects": [ + { + "type": "replace_spell", + "name": "Charge", + "cost": 25, + "display_text": "Total Damage Average", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } + } + ] + } + ], + "id": 75 + }, + { + "display_name": "Heavy Impact", + "desc": "After using Charge, violently crash down into the ground and deal damage", + "archetype": "", + "archetype_req": 0, + "parents": [ + 79 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 9, + "col": 1, + "icon": "node_1" + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Heavy Impact", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 76 + }, + { + "display_name": "Vehement", + "desc": "For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 75 + ], + "dependencies": [], + "blockers": [ + 78 + ], + "cost": 1, + "display": { + "row": 6, + "col": 2, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "mdPct" + }, + { + "type": "stat", + "name": "mdRaw" + } + ], + "output": { + "type": "stat", + "name": "spd" + }, + "scaling": [ + 1, + 1 + ], + "max": 20 + } + ], + "id": 77 + }, + { + "display_name": "Tougher Skin", + "desc": "Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 75 + ], + "dependencies": [], + "blockers": [ + 77 + ], + "cost": 1, + "display": { + "row": 6, + "col": 6, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "baseResist", + "value": "5" + } + ] + }, + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hprRaw" + }, + { + "type": "stat", + "name": "hprPct" + } + ], + "output": { + "type": "stat", + "name": "hpBonus" + }, + "scaling": [ + 10, + 10 + ], + "max": 100 + } + ], + "id": 78 + }, + { + "display_name": "Uppercut", + "desc": "Rocket enemies in the air and deal massive damage", + "archetype": "", + "archetype_req": 0, + "parents": [ + 77 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 2, + "icon": "node_4" + }, + "properties": { + "aoe": 3, + "range": 5 + }, + "effects": [ + { + "type": "replace_spell", + "name": "Uppercut", + "cost": 45, + "display_text": "Total Damage Average", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "total", + "parts": [ + { + "name": "Uppercut", + "type": "damage", + "multipliers": [ + 150, + 50, + 50, + 0, + 0, + 0 + ] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Uppercut": 1 + } + } + ] + } + ], + "id": 79 + }, + { + "display_name": "Cheaper Charge", + "desc": "Reduce the Mana cost of Charge", + "archetype": "", + "archetype_req": 0, + "parents": [ + 79, + 81 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 4, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + } + ], + "id": 80 + }, + { + "display_name": "War Scream", + "desc": "Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies", + "archetype": "", + "archetype_req": 0, + "parents": [ + 78 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 8, + "col": 6, + "icon": "node_4" + }, + "properties": { + "duration": 30, + "aoe": 12, + "defense_bonus": 10 + }, + "effects": [ + { + "type": "replace_spell", + "name": "War Scream", + "cost": 35, + "display_text": "War Scream", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage Average", + "parts": [ + { + "name": "War Scream", + "type": "damage", + "multipliers": [ + 50, + 0, + 0, + 0, + 50, + 0 + ] + } + ] + } + ], + "id": 81 + }, + { + "display_name": "Earth Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 79 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 0, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "eDamPct", + "value": 20 + }, + { + "type": "stat", + "name": "eDam", + "value": [ + 2, + 4 + ] + } + ] + } + ], + "id": 82 + }, + { + "display_name": "Thunder Mastery", + "desc": "Increases base damage from all Thunder attacks", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 79, + 85, + 80 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 2, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "tDamPct", + "value": 10 + }, + { + "type": "stat", + "name": "tDam", + "value": [ + 1, + 8 + ] + } + ] + } + ], + "id": 83 + }, + { + "display_name": "Water Mastery", + "desc": "Increases base damage from all Water attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 80, + 83, + 85 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 11, + "col": 4, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "wDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "wDam", + "value": [ + 2, + 4 + ] + } + ] + } + ], + "id": 84 + }, + { + "display_name": "Air Mastery", + "desc": "Increases base damage from all Air attacks", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 81, + 83, + 80 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 6, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "aDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "aDam", + "value": [ + 3, + 4 + ] + } + ] + } + ], + "id": 85 + }, + { + "display_name": "Fire Mastery", + "desc": "Increases base damage from all Earth attacks", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 81 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 10, + "col": 8, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "fDamPct", + "value": 15 + }, + { + "type": "stat", + "name": "fDam", + "value": [ + 3, + 5 + ] + } + ] + } + ], + "id": 86 + }, + { + "display_name": "Quadruple Bash", + "desc": "Bash will hit 4 times at an even larger range", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 82, + 88 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 0, + "icon": "node_1" + }, + "properties": { + "range": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Hit": 2 + } + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [ + -20, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 87 + }, + { + "display_name": "Fireworks", + "desc": "Mobs hit by Uppercut will explode mid-air and receive additional damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 83, + 87 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 2, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fireworks", + "cost": 0, + "multipliers": [ + 80, + 0, + 20, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fireworks": 1 + } + } + ], + "id": 88 + }, + { + "display_name": "Half-Moon Swipe", + "desc": "Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 84 + ], + "dependencies": [ + 79 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 13, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": -10, + "multipliers": [ + -70, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "water" + } + ], + "id": 89 + }, + { + "display_name": "Flyby Jab", + "desc": "Damage enemies in your way when using Charge", + "archetype": "", + "archetype_req": 0, + "parents": [ + 85, + 91 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 6, + "icon": "node_1" + }, + "properties": { + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Flyby Jab", + "cost": 0, + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 40 + ] + } + ], + "id": 90 + }, + { + "display_name": "Flaming Uppercut", + "desc": "Uppercut will light mobs on fire, dealing damage every 0.6 seconds", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 86, + 90 + ], + "dependencies": [ + 79 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 12, + "col": 8, + "icon": "node_1" + }, + "properties": { + "duration": 3, + "tick": 0.6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Flaming Uppercut", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 0, + 50, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Flaming Uppercut Total Damage", + "cost": 0, + "hits": { + "Flaming Uppercut": 5 + } + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Flaming Uppercut": 5 + } + } + ], + "id": 91 + }, + { + "display_name": "Iron Lungs", + "desc": "War Scream deals more damage", + "archetype": "", + "archetype_req": 0, + "parents": [ + 90, + 91 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 13, + "col": 7, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "War Scream", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 0, + 30 + ] + } + ], + "id": 92 + }, + { + "display_name": "Generalist", + "desc": "After casting 3 different spells in a row, your next spell will cost 5 mana", + "archetype": "Battle Monk", + "archetype_req": 3, + "parents": [ + 94 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 2, + "icon": "node_3" + }, + "properties": {}, + "effects": [], + "id": 93 + }, + { + "display_name": "Counter", + "desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 89 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 4, + "icon": "node_1" + }, + "properties": { + "chance": 30 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Counter", + "cost": 0, + "multipliers": [ + 60, + 0, + 20, + 0, + 0, + 20 + ] + } + ], + "id": 94 + }, + { + "display_name": "Mantle of the Bovemists", + "desc": "When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)", + "archetype": "Paladin", + "archetype_req": 3, + "parents": [ + 92 + ], + "dependencies": [ + 81 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 15, + "col": 7, + "icon": "node_3" + }, + "properties": { + "mantle_charge": 3 + }, + "effects": [], + "id": 95 + }, + { + "display_name": "Bak'al's Grasp", + "desc": "After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)", + "archetype": "Fallen", + "archetype_req": 2, + "parents": [ + 87, + 88 + ], + "dependencies": [ + 81 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 16, + "col": 1, + "icon": "node_3" + }, + "properties": { + "cooldown": 15 + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "raw" + }, + "scaling": [ + 4 + ], + "slider_step": 2, + "max": 120 + } + ], + "id": 96 + }, + { + "display_name": "Spear Proficiency 2", + "desc": "Improve your Main Attack's damage and range w/ spear", + "archetype": "", + "archetype_req": 0, + "parents": [ + 96, + 98 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 0, + "icon": "node_0" + }, + "properties": { + "melee_range": 1 + }, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "mdPct", + "value": 5 + } + ] + } + ], + "id": 97 + }, + { + "display_name": "Cheaper Uppercut", + "desc": "Reduce the Mana Cost of Uppercut", + "archetype": "", + "archetype_req": 0, + "parents": [ + 97, + 99, + 94 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 3, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ], + "id": 98 + }, + { + "display_name": "Aerodynamics", + "desc": "During Charge, you can steer and change direction", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 98, + 100 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 17, + "col": 5, + "icon": "node_1" + }, + "properties": {}, + "effects": [], + "id": 99 + }, + { + "display_name": "Provoke", + "desc": "Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 99, + 95 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 17, + "col": 7, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ], + "id": 100 + }, + { + "display_name": "Precise Strikes", + "desc": "+30% Critical Hit Damage", + "archetype": "", + "archetype_req": 0, + "parents": [ + 98, + 97 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 18, + "col": 2, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "critDmg", + "value": 30 + } + ] + } + ], + "id": 101 + }, + { + "display_name": "Air Shout", + "desc": "War Scream will fire a projectile that can go through walls and deal damage multiple times", + "archetype": "", + "archetype_req": 0, + "parents": [ + 99, + 100 + ], + "dependencies": [ + 81 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 18, + "col": 6, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Air Shout", + "cost": 0, + "multipliers": [ + 20, + 0, + 0, + 0, + 0, + 5 + ] + } + ], + "id": 102 + }, + { + "display_name": "Enraged Blow", + "desc": "While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 97 + ], + "dependencies": [ + 96 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 0, + "icon": "node_2" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hpBonus" + } + ], + "output": { + "type": "stat", + "name": "dmgPct" + }, + "scaling": [ + 2 + ], + "max": 200 + } + ], + "id": 103 + }, + { + "display_name": "Flying Kick", + "desc": "When using Charge, mobs hit will halt your momentum and get knocked back", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 98, + 105 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 3, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Flying Kick", + "cost": 0, + "multipliers": [ + 120, + 0, + 0, + 10, + 0, + 20 + ] + } + ], + "id": 104 + }, + { + "display_name": "Stronger Mantle", + "desc": "Add +2 additional charges to Mantle of the Bovemists", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 106, + 104 + ], + "dependencies": [ + 95 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 20, + "col": 6, + "icon": "node_0" + }, + "properties": { + "mantle_charge": 2 + }, + "effects": [], + "id": 105 + }, + { + "display_name": "Manachism", + "desc": "If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)", + "archetype": "Paladin", + "archetype_req": 3, + "parents": [ + 105, + 100 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 20, + "col": 8, + "icon": "node_2" + }, + "properties": { + "cooldown": 1 + }, + "effects": [], + "id": 106 + }, + { + "display_name": "Boiling Blood", + "desc": "Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds", + "archetype": "", + "archetype_req": 0, + "parents": [ + 103, + 108 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 0, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Boiling Blood", + "cost": 0, + "multipliers": [ + 25, + 0, + 0, + 0, + 5, + 0 + ] + } + ], + "id": 107 + }, + { + "display_name": "Ragnarokkr", + "desc": "War Scream become deafening, increasing its range and giving damage bonus to players", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 107, + 104 + ], + "dependencies": [ + 81 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 22, + "col": 2, + "icon": "node_2" + }, + "properties": { + "damage_bonus": 30, + "aoe": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": 10 + } + ], + "id": 108 + }, + { + "display_name": "Ambidextrous", + "desc": "Increase your chance to attack with Counter by +30%", + "archetype": "", + "archetype_req": 0, + "parents": [ + 104, + 105, + 110 + ], + "dependencies": [ + 94 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 4, + "icon": "node_0" + }, + "properties": { + "chance": 30 + }, + "effects": [], + "id": 109 + }, + { + "display_name": "Burning Heart", + "desc": "For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 109, + 111 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 6, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": false, + "inputs": [ + { + "type": "stat", + "name": "hpBonus" + } + ], + "output": { + "type": "stat", + "name": "fDamPct" + }, + "scaling": [ + 2 + ], + "max": 100, + "slider_step": 100 + } + ], + "id": 110 + }, + { + "display_name": "Stronger Bash", + "desc": "Increase the damage of Bash", + "archetype": "", + "archetype_req": 0, + "parents": [ + 110, + 106 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 22, + "col": 8, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Hit", + "cost": 0, + "multipliers": [ + 30, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 111 + }, + { + "display_name": "Intoxicating Blood", + "desc": "After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted", + "archetype": "Fallen", + "archetype_req": 5, + "parents": [ + 108, + 107 + ], + "dependencies": [ + 96 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 1, + "icon": "node_1" + }, + "properties": {}, + "effects": [], + "id": 112 + }, + { + "display_name": "Comet", + "desc": "After being hit by Fireworks, enemies will crash into the ground and receive more damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 108 + ], + "dependencies": [ + 88 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 24, + "col": 2, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Comet", + "cost": 0, + "multipliers": [ + 80, + 20, + 0, + 0, + 0, + 0 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Comet": 1 + } + } + ], + "id": 113 + }, + { + "display_name": "Collide", + "desc": "Mobs thrown into walls from Flying Kick will explode and receive additonal damage", + "archetype": "Battle Monk", + "archetype_req": 4, + "parents": [ + 109, + 110 + ], + "dependencies": [ + 104 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 5, + "icon": "node_1" + }, + "properties": { + "aoe": 4 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Collide", + "cost": 0, + "multipliers": [ + 100, + 0, + 0, + 0, + 50, + 0 + ] + } + ], + "id": 114 + }, + { + "display_name": "Rejuvenating Skin", + "desc": "Regain back 30% of the damage you take as healing over 30s", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 110, + 111 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 23, + "col": 7, + "icon": "node_3" + }, + "properties": {}, + "effects": [], + "id": 115 + }, + { + "display_name": "Uncontainable Corruption", + "desc": "Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1", + "archetype": "", + "archetype_req": 0, + "parents": [ + 107, + 117 + ], + "dependencies": [ + 96 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 0, + "icon": "node_0" + }, + "properties": { + "cooldown": -5 + }, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "raw" + }, + "scaling": [ + 1 + ], + "slider_step": 2, + "max": 50 + } + ], + "id": 116 + }, + { + "display_name": "Radiant Devotee", + "desc": "For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)", + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": [ + 118, + 116 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 26, + "col": 2, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "inputs": [ + { + "type": "stat", + "name": "ref" + } + ], + "output": { + "type": "stat", + "name": "mr" + }, + "scaling": [ + 1 + ], + "max": 10, + "slider_step": 4 + } + ], + "id": 117 + }, + { + "display_name": "Whirlwind Strike", + "desc": "Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)", + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": [ + 109, + 117 + ], + "dependencies": [ + 79 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 4, + "icon": "node_1" + }, + "properties": { + "range": 2 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": 0, + "multipliers": [ + 0, + 0, + 0, + 0, + 0, + 50 + ] + } + ], + "id": 118 + }, + { + "display_name": "Mythril Skin", + "desc": "Gain +5% Base Resistance and become immune to knockback", + "archetype": "Paladin", + "archetype_req": 6, + "parents": [ + 115 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 26, + "col": 7, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "baseResist", + "value": 5 + } + ] + } + ], + "id": 119 + }, + { + "display_name": "Armour Breaker", + "desc": "While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 116, + 117 + ], + "dependencies": [ + 96 + ], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 1, + "icon": "node_2" + }, + "properties": { + "duration": 5 + }, + "effects": [], + "id": 120 + }, + { + "display_name": "Shield Strike", + "desc": "When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 119, + 122 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 6, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Shield Strike", + "cost": 0, + "multipliers": [ + 60, + 0, + 20, + 0, + 0, + 0 + ] + } + ], + "id": 121 + }, + { + "display_name": "Sparkling Hope", + "desc": "Everytime you heal 5% of your max health, deal damage to all nearby enemies", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 119 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 27, + "col": 8, + "icon": "node_2" + }, + "properties": { + "aoe": 6 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 5, + "target_part": "Sparkling Hope", + "cost": 0, + "multipliers": [ + 10, + 0, + 5, + 0, + 0, + 0 + ] + } + ], + "id": 122 + }, + { + "display_name": "Massive Bash", + "desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)", + "archetype": "Fallen", + "archetype_req": 8, + "parents": [ + 124, + 116 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 0, + "icon": "node_2" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Corrupted", + "output": { + "type": "stat", + "name": "bashAoE" + }, + "scaling": [ + 1 + ], + "max": 10, + "slider_step": 3 + } + ], + "id": 123 + }, + { + "display_name": "Tempest", + "desc": "War Scream will ripple the ground and deal damage 3 times in a large area", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 123, + 125 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 28, + "col": 2, + "icon": "node_1" + }, + "properties": { + "aoe": 16 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Tempest", + "cost": "0", + "multipliers": [ + 30, + 10, + 0, + 0, + 0, + 10 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Tempest Total Damage", + "cost": "0", + "hits": { + "Tempest": 3 + } + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Total Damage", + "cost": "0", + "hits": { + "Tempest": 3 + } + } + ], + "id": 124 + }, + { + "display_name": "Spirit of the Rabbit", + "desc": "Reduce the Mana cost of Charge and increase your Walk Speed by +20%", + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": [ + 124, + 118 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 28, + "col": 4, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 2, + "cost": -5 + }, + { + "type": "raw_stat", + "bonuses": [ + { + "type": "stat", + "name": "spd", + "value": 20 + } + ] + } + ], + "id": 125 + }, + { + "display_name": "Massacre", + "desc": "While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar", + "archetype": "Fallen", + "archetype_req": 5, + "parents": [ + 124, + 123 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 29, + "col": 1, + "icon": "node_1" + }, + "properties": {}, + "effects": [], + "id": 126 + }, + { + "display_name": "Axe Kick", + "desc": "Increase the damage of Uppercut, but also increase its mana cost", + "archetype": "", + "archetype_req": 0, + "parents": [ + 124, + 125 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 3, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Uppercut", + "cost": 10, + "multipliers": [ + 100, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "id": 127 + }, + { + "display_name": "Radiance", + "desc": "Bash will buff your allies' positive IDs. (15s Cooldown)", + "archetype": "Paladin", + "archetype_req": 2, + "parents": [ + 125, + 129 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 29, + "col": 5, + "icon": "node_2" + }, + "properties": { + "cooldown": 15 + }, + "effects": [], + "id": 128 + }, + { + "display_name": "Cheaper Bash 2", + "desc": "Reduce the Mana cost of Bash", + "archetype": "", + "archetype_req": 0, + "parents": [ + 128, + 121, + 122 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 29, + "col": 7, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "cost": -5 + } + ], + "id": 129 + }, + { + "display_name": "Cheaper War Scream", + "desc": "Reduce the Mana cost of War Scream", + "archetype": "", + "archetype_req": 0, + "parents": [ + 123 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 0, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "cost": -5 + } + ], + "id": 130 + }, + { + "display_name": "Discombobulate", + "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", + "archetype": "Battle Monk", + "archetype_req": 12, + "parents": [ + 133 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 31, + "col": 2, + "icon": "node_3" + }, + "properties": {}, + "effects": [ + { + "type": "stat_scaling", + "slider": true, + "slider_name": "Hits dealt", + "output": { + "type": "stat", + "name": "rainrawButDifferent" + }, + "scaling": [ + 2 + ], + "max": 50 + } + ], + "id": 131 + }, + { + "display_name": "Thunderclap", + "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", + "archetype": "Battle Monk", + "archetype_req": 8, + "parents": [ + 133 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 5, + "icon": "node_1" + }, + "properties": {}, + "effects": [ + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + }, + { + "type": "raw_stat", + "bonuses": [ + { + "type": "prop", + "abil_name": "Bash", + "name": "aoe", + "value": 3 + } + ] + } + ], + "id": 132 + }, + { + "display_name": "Cyclone", + "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": [ + 125 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 31, + "col": 4, + "icon": "node_1" + }, + "properties": { + "aoe": 4, + "duration": 20 + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Cyclone", + "cost": 0, + "multipliers": [ + 10, + 0, + 0, + 0, + 5, + 10 + ] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Cyclone Total Damage", + "cost": 0, + "hits": { + "Cyclone": 40 + } + } + ], + "id": 133 + }, + { + "display_name": "Second Chance", + "desc": "When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)", + "archetype": "Paladin", + "archetype_req": 12, + "parents": [ + 129 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 32, + "col": 7, + "icon": "node_3" + }, + "properties": {}, + "effects": [], + "id": 134 + }, + { + "display_name": "Blood Pact", + "desc": "If you do not have enough mana to cast a spell, spend health instead (1% health per mana)", + "archetype": "", + "archetype_req": 10, + "parents": [ + 130 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 34, + "col": 1, + "icon": "node_3" + }, + "properties": {}, + "effects": [], + "id": 135 + }, + { + "display_name": "Haemorrhage", + "desc": "Reduce Blood Pact's health cost. (0.5% health per mana)", + "archetype": "Fallen", + "archetype_req": 0, + "parents": [ + 135 + ], + "dependencies": [ + 135 + ], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 2, + "icon": "node_1" + }, + "properties": {}, + "effects": [], + "id": 136 + }, + { + "display_name": "Brink of Madness", + "desc": "If your health is 25% full or less, gain +40% Resistance", + "archetype": "", + "archetype_req": 0, + "parents": [ + 135, + 138 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 35, + "col": 4, + "icon": "node_2" + }, + "properties": {}, + "effects": [], + "id": 137 + }, + { + "display_name": "Cheaper Uppercut 2", + "desc": "Reduce the Mana cost of Uppercut", + "archetype": "", + "archetype_req": 0, + "parents": [ + 134, + 137 + ], + "dependencies": [], + "blockers": [], + "cost": 1, + "display": { + "row": 35, + "col": 6, + "icon": "node_0" + }, + "properties": {}, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "cost": -5 + } + ], + "id": 138 + }, + { + "display_name": "Martyr", + "desc": "When you receive a fatal blow, all nearby allies become invincible", + "archetype": "Paladin", + "archetype_req": 0, + "parents": [ + 134 + ], + "dependencies": [], + "blockers": [], + "cost": 2, + "display": { + "row": 35, + "col": 8, + "icon": "node_1" + }, + "properties": { + "duration": 3, + "aoe": 12 + }, + "effects": [], + "id": 139 + } + ] +} \ No newline at end of file diff --git a/textures/items/boots/boots--chain.png b/py_script/textures/items/boots/boots--chain.png similarity index 100% rename from textures/items/boots/boots--chain.png rename to py_script/textures/items/boots/boots--chain.png diff --git a/textures/items/boots/boots--diamond.png b/py_script/textures/items/boots/boots--diamond.png similarity index 100% rename from textures/items/boots/boots--diamond.png rename to py_script/textures/items/boots/boots--diamond.png diff --git a/textures/items/boots/boots--golden.png b/py_script/textures/items/boots/boots--golden.png similarity index 100% rename from textures/items/boots/boots--golden.png rename to py_script/textures/items/boots/boots--golden.png diff --git a/textures/items/boots/boots--iron.png b/py_script/textures/items/boots/boots--iron.png similarity index 100% rename from textures/items/boots/boots--iron.png rename to py_script/textures/items/boots/boots--iron.png diff --git a/textures/items/boots/boots--leather.png b/py_script/textures/items/boots/boots--leather.png similarity index 100% rename from textures/items/boots/boots--leather.png rename to py_script/textures/items/boots/boots--leather.png diff --git a/textures/items/bow/bow--air1.png b/py_script/textures/items/bow/bow--air1.png similarity index 100% rename from textures/items/bow/bow--air1.png rename to py_script/textures/items/bow/bow--air1.png diff --git a/textures/items/bow/bow--air2.png b/py_script/textures/items/bow/bow--air2.png similarity index 100% rename from textures/items/bow/bow--air2.png rename to py_script/textures/items/bow/bow--air2.png diff --git a/textures/items/bow/bow--air3.png b/py_script/textures/items/bow/bow--air3.png similarity index 100% rename from textures/items/bow/bow--air3.png rename to py_script/textures/items/bow/bow--air3.png diff --git a/textures/items/bow/bow--default1.png b/py_script/textures/items/bow/bow--default1.png similarity index 100% rename from textures/items/bow/bow--default1.png rename to py_script/textures/items/bow/bow--default1.png diff --git a/textures/items/bow/bow--default2.png b/py_script/textures/items/bow/bow--default2.png similarity index 100% rename from textures/items/bow/bow--default2.png rename to py_script/textures/items/bow/bow--default2.png diff --git a/textures/items/bow/bow--earth1.png b/py_script/textures/items/bow/bow--earth1.png similarity index 100% rename from textures/items/bow/bow--earth1.png rename to py_script/textures/items/bow/bow--earth1.png diff --git a/textures/items/bow/bow--earth2.png b/py_script/textures/items/bow/bow--earth2.png similarity index 100% rename from textures/items/bow/bow--earth2.png rename to py_script/textures/items/bow/bow--earth2.png diff --git a/textures/items/bow/bow--earth3.png b/py_script/textures/items/bow/bow--earth3.png similarity index 100% rename from textures/items/bow/bow--earth3.png rename to py_script/textures/items/bow/bow--earth3.png diff --git a/textures/items/bow/bow--fire1.png b/py_script/textures/items/bow/bow--fire1.png similarity index 100% rename from textures/items/bow/bow--fire1.png rename to py_script/textures/items/bow/bow--fire1.png diff --git a/textures/items/bow/bow--fire2.png b/py_script/textures/items/bow/bow--fire2.png similarity index 100% rename from textures/items/bow/bow--fire2.png rename to py_script/textures/items/bow/bow--fire2.png diff --git a/textures/items/bow/bow--fire3.png b/py_script/textures/items/bow/bow--fire3.png similarity index 100% rename from textures/items/bow/bow--fire3.png rename to py_script/textures/items/bow/bow--fire3.png diff --git a/textures/items/bow/bow--generic1.png b/py_script/textures/items/bow/bow--generic1.png similarity index 100% rename from textures/items/bow/bow--generic1.png rename to py_script/textures/items/bow/bow--generic1.png diff --git a/textures/items/bow/bow--generic2.png b/py_script/textures/items/bow/bow--generic2.png similarity index 100% rename from textures/items/bow/bow--generic2.png rename to py_script/textures/items/bow/bow--generic2.png diff --git a/textures/items/bow/bow--generic3.png b/py_script/textures/items/bow/bow--generic3.png similarity index 100% rename from textures/items/bow/bow--generic3.png rename to py_script/textures/items/bow/bow--generic3.png diff --git a/textures/items/bow/bow--thunder1.png b/py_script/textures/items/bow/bow--thunder1.png similarity index 100% rename from textures/items/bow/bow--thunder1.png rename to py_script/textures/items/bow/bow--thunder1.png diff --git a/textures/items/bow/bow--thunder2.png b/py_script/textures/items/bow/bow--thunder2.png similarity index 100% rename from textures/items/bow/bow--thunder2.png rename to py_script/textures/items/bow/bow--thunder2.png diff --git a/textures/items/bow/bow--thunder3.png b/py_script/textures/items/bow/bow--thunder3.png similarity index 100% rename from textures/items/bow/bow--thunder3.png rename to py_script/textures/items/bow/bow--thunder3.png diff --git a/textures/items/bow/bow--water1.png b/py_script/textures/items/bow/bow--water1.png similarity index 100% rename from textures/items/bow/bow--water1.png rename to py_script/textures/items/bow/bow--water1.png diff --git a/textures/items/bow/bow--water2.png b/py_script/textures/items/bow/bow--water2.png similarity index 100% rename from textures/items/bow/bow--water2.png rename to py_script/textures/items/bow/bow--water2.png diff --git a/textures/items/bow/bow--water3.png b/py_script/textures/items/bow/bow--water3.png similarity index 100% rename from textures/items/bow/bow--water3.png rename to py_script/textures/items/bow/bow--water3.png diff --git a/textures/items/chestplate/chestplate--chain.png b/py_script/textures/items/chestplate/chestplate--chain.png similarity index 100% rename from textures/items/chestplate/chestplate--chain.png rename to py_script/textures/items/chestplate/chestplate--chain.png diff --git a/textures/items/chestplate/chestplate--diamond.png b/py_script/textures/items/chestplate/chestplate--diamond.png similarity index 100% rename from textures/items/chestplate/chestplate--diamond.png rename to py_script/textures/items/chestplate/chestplate--diamond.png diff --git a/textures/items/chestplate/chestplate--golden.png b/py_script/textures/items/chestplate/chestplate--golden.png similarity index 100% rename from textures/items/chestplate/chestplate--golden.png rename to py_script/textures/items/chestplate/chestplate--golden.png diff --git a/textures/items/chestplate/chestplate--iron.png b/py_script/textures/items/chestplate/chestplate--iron.png similarity index 100% rename from textures/items/chestplate/chestplate--iron.png rename to py_script/textures/items/chestplate/chestplate--iron.png diff --git a/textures/items/chestplate/chestplate--leather.png b/py_script/textures/items/chestplate/chestplate--leather.png similarity index 100% rename from textures/items/chestplate/chestplate--leather.png rename to py_script/textures/items/chestplate/chestplate--leather.png diff --git a/textures/items/dagger/dagger--air1.png b/py_script/textures/items/dagger/dagger--air1.png similarity index 100% rename from textures/items/dagger/dagger--air1.png rename to py_script/textures/items/dagger/dagger--air1.png diff --git a/textures/items/dagger/dagger--air2.png b/py_script/textures/items/dagger/dagger--air2.png similarity index 100% rename from textures/items/dagger/dagger--air2.png rename to py_script/textures/items/dagger/dagger--air2.png diff --git a/textures/items/dagger/dagger--air3.png b/py_script/textures/items/dagger/dagger--air3.png similarity index 100% rename from textures/items/dagger/dagger--air3.png rename to py_script/textures/items/dagger/dagger--air3.png diff --git a/textures/items/dagger/dagger--default1.png b/py_script/textures/items/dagger/dagger--default1.png similarity index 100% rename from textures/items/dagger/dagger--default1.png rename to py_script/textures/items/dagger/dagger--default1.png diff --git a/textures/items/dagger/dagger--default2.png b/py_script/textures/items/dagger/dagger--default2.png similarity index 100% rename from textures/items/dagger/dagger--default2.png rename to py_script/textures/items/dagger/dagger--default2.png diff --git a/textures/items/dagger/dagger--earth1.png b/py_script/textures/items/dagger/dagger--earth1.png similarity index 100% rename from textures/items/dagger/dagger--earth1.png rename to py_script/textures/items/dagger/dagger--earth1.png diff --git a/textures/items/dagger/dagger--earth2.png b/py_script/textures/items/dagger/dagger--earth2.png similarity index 100% rename from textures/items/dagger/dagger--earth2.png rename to py_script/textures/items/dagger/dagger--earth2.png diff --git a/textures/items/dagger/dagger--earth3.png b/py_script/textures/items/dagger/dagger--earth3.png similarity index 100% rename from textures/items/dagger/dagger--earth3.png rename to py_script/textures/items/dagger/dagger--earth3.png diff --git a/textures/items/dagger/dagger--fire1.png b/py_script/textures/items/dagger/dagger--fire1.png similarity index 100% rename from textures/items/dagger/dagger--fire1.png rename to py_script/textures/items/dagger/dagger--fire1.png diff --git a/textures/items/dagger/dagger--fire2.png b/py_script/textures/items/dagger/dagger--fire2.png similarity index 100% rename from textures/items/dagger/dagger--fire2.png rename to py_script/textures/items/dagger/dagger--fire2.png diff --git a/textures/items/dagger/dagger--fire3.png b/py_script/textures/items/dagger/dagger--fire3.png similarity index 100% rename from textures/items/dagger/dagger--fire3.png rename to py_script/textures/items/dagger/dagger--fire3.png diff --git a/textures/items/dagger/dagger--generic1.png b/py_script/textures/items/dagger/dagger--generic1.png similarity index 100% rename from textures/items/dagger/dagger--generic1.png rename to py_script/textures/items/dagger/dagger--generic1.png diff --git a/textures/items/dagger/dagger--generic2.png b/py_script/textures/items/dagger/dagger--generic2.png similarity index 100% rename from textures/items/dagger/dagger--generic2.png rename to py_script/textures/items/dagger/dagger--generic2.png diff --git a/textures/items/dagger/dagger--generic3.png b/py_script/textures/items/dagger/dagger--generic3.png similarity index 100% rename from textures/items/dagger/dagger--generic3.png rename to py_script/textures/items/dagger/dagger--generic3.png diff --git a/textures/items/dagger/dagger--thunder1.png b/py_script/textures/items/dagger/dagger--thunder1.png similarity index 100% rename from textures/items/dagger/dagger--thunder1.png rename to py_script/textures/items/dagger/dagger--thunder1.png diff --git a/textures/items/dagger/dagger--thunder2.png b/py_script/textures/items/dagger/dagger--thunder2.png similarity index 100% rename from textures/items/dagger/dagger--thunder2.png rename to py_script/textures/items/dagger/dagger--thunder2.png diff --git a/textures/items/dagger/dagger--thunder3.png b/py_script/textures/items/dagger/dagger--thunder3.png similarity index 100% rename from textures/items/dagger/dagger--thunder3.png rename to py_script/textures/items/dagger/dagger--thunder3.png diff --git a/textures/items/dagger/dagger--water1.png b/py_script/textures/items/dagger/dagger--water1.png similarity index 100% rename from textures/items/dagger/dagger--water1.png rename to py_script/textures/items/dagger/dagger--water1.png diff --git a/textures/items/dagger/dagger--water2.png b/py_script/textures/items/dagger/dagger--water2.png similarity index 100% rename from textures/items/dagger/dagger--water2.png rename to py_script/textures/items/dagger/dagger--water2.png diff --git a/textures/items/dagger/dagger--water3.png b/py_script/textures/items/dagger/dagger--water3.png similarity index 100% rename from textures/items/dagger/dagger--water3.png rename to py_script/textures/items/dagger/dagger--water3.png diff --git a/textures/items/helmet/helmet--chain.png b/py_script/textures/items/helmet/helmet--chain.png similarity index 100% rename from textures/items/helmet/helmet--chain.png rename to py_script/textures/items/helmet/helmet--chain.png diff --git a/textures/items/helmet/helmet--diamond.png b/py_script/textures/items/helmet/helmet--diamond.png similarity index 100% rename from textures/items/helmet/helmet--diamond.png rename to py_script/textures/items/helmet/helmet--diamond.png diff --git a/textures/items/helmet/helmet--golden.png b/py_script/textures/items/helmet/helmet--golden.png similarity index 100% rename from textures/items/helmet/helmet--golden.png rename to py_script/textures/items/helmet/helmet--golden.png diff --git a/textures/items/helmet/helmet--iron.png b/py_script/textures/items/helmet/helmet--iron.png similarity index 100% rename from textures/items/helmet/helmet--iron.png rename to py_script/textures/items/helmet/helmet--iron.png diff --git a/textures/items/helmet/helmet--leather.png b/py_script/textures/items/helmet/helmet--leather.png similarity index 100% rename from textures/items/helmet/helmet--leather.png rename to py_script/textures/items/helmet/helmet--leather.png diff --git a/textures/items/leggings/leggings--chain.png b/py_script/textures/items/leggings/leggings--chain.png similarity index 100% rename from textures/items/leggings/leggings--chain.png rename to py_script/textures/items/leggings/leggings--chain.png diff --git a/textures/items/leggings/leggings--diamond.png b/py_script/textures/items/leggings/leggings--diamond.png similarity index 100% rename from textures/items/leggings/leggings--diamond.png rename to py_script/textures/items/leggings/leggings--diamond.png diff --git a/textures/items/leggings/leggings--golden.png b/py_script/textures/items/leggings/leggings--golden.png similarity index 100% rename from textures/items/leggings/leggings--golden.png rename to py_script/textures/items/leggings/leggings--golden.png diff --git a/textures/items/leggings/leggings--iron.png b/py_script/textures/items/leggings/leggings--iron.png similarity index 100% rename from textures/items/leggings/leggings--iron.png rename to py_script/textures/items/leggings/leggings--iron.png diff --git a/textures/items/leggings/leggings--leather.png b/py_script/textures/items/leggings/leggings--leather.png similarity index 100% rename from textures/items/leggings/leggings--leather.png rename to py_script/textures/items/leggings/leggings--leather.png diff --git a/textures/items/relik/relik--air1.png b/py_script/textures/items/relik/relik--air1.png similarity index 100% rename from textures/items/relik/relik--air1.png rename to py_script/textures/items/relik/relik--air1.png diff --git a/textures/items/relik/relik--air2.png b/py_script/textures/items/relik/relik--air2.png similarity index 100% rename from textures/items/relik/relik--air2.png rename to py_script/textures/items/relik/relik--air2.png diff --git a/textures/items/relik/relik--air3.png b/py_script/textures/items/relik/relik--air3.png similarity index 100% rename from textures/items/relik/relik--air3.png rename to py_script/textures/items/relik/relik--air3.png diff --git a/textures/items/relik/relik--default1.png b/py_script/textures/items/relik/relik--default1.png similarity index 100% rename from textures/items/relik/relik--default1.png rename to py_script/textures/items/relik/relik--default1.png diff --git a/textures/items/relik/relik--default2.png b/py_script/textures/items/relik/relik--default2.png similarity index 100% rename from textures/items/relik/relik--default2.png rename to py_script/textures/items/relik/relik--default2.png diff --git a/textures/items/relik/relik--earth1.png b/py_script/textures/items/relik/relik--earth1.png similarity index 100% rename from textures/items/relik/relik--earth1.png rename to py_script/textures/items/relik/relik--earth1.png diff --git a/textures/items/relik/relik--earth2.png b/py_script/textures/items/relik/relik--earth2.png similarity index 100% rename from textures/items/relik/relik--earth2.png rename to py_script/textures/items/relik/relik--earth2.png diff --git a/textures/items/relik/relik--earth3.png b/py_script/textures/items/relik/relik--earth3.png similarity index 100% rename from textures/items/relik/relik--earth3.png rename to py_script/textures/items/relik/relik--earth3.png diff --git a/textures/items/relik/relik--fire1.png b/py_script/textures/items/relik/relik--fire1.png similarity index 100% rename from textures/items/relik/relik--fire1.png rename to py_script/textures/items/relik/relik--fire1.png diff --git a/textures/items/relik/relik--fire2.png b/py_script/textures/items/relik/relik--fire2.png similarity index 100% rename from textures/items/relik/relik--fire2.png rename to py_script/textures/items/relik/relik--fire2.png diff --git a/textures/items/relik/relik--fire3.png b/py_script/textures/items/relik/relik--fire3.png similarity index 100% rename from textures/items/relik/relik--fire3.png rename to py_script/textures/items/relik/relik--fire3.png diff --git a/textures/items/relik/relik--generic1.png b/py_script/textures/items/relik/relik--generic1.png similarity index 100% rename from textures/items/relik/relik--generic1.png rename to py_script/textures/items/relik/relik--generic1.png diff --git a/textures/items/relik/relik--generic2.png b/py_script/textures/items/relik/relik--generic2.png similarity index 100% rename from textures/items/relik/relik--generic2.png rename to py_script/textures/items/relik/relik--generic2.png diff --git a/textures/items/relik/relik--generic3.png b/py_script/textures/items/relik/relik--generic3.png similarity index 99% rename from textures/items/relik/relik--generic3.png rename to py_script/textures/items/relik/relik--generic3.png index fe68d65..a4530e4 100644 --- a/textures/items/relik/relik--generic3.png +++ b/py_script/textures/items/relik/relik--generic3.png @@ -2,7 +2,7 @@ - 404 Not Found +<title> 404 Not Found
diff --git a/textures/items/relik/relik--thunder1.png b/py_script/textures/items/relik/relik--thunder1.png similarity index 100% rename from textures/items/relik/relik--thunder1.png rename to py_script/textures/items/relik/relik--thunder1.png diff --git a/textures/items/relik/relik--thunder2.png b/py_script/textures/items/relik/relik--thunder2.png similarity index 100% rename from textures/items/relik/relik--thunder2.png rename to py_script/textures/items/relik/relik--thunder2.png diff --git a/textures/items/relik/relik--thunder3.png b/py_script/textures/items/relik/relik--thunder3.png similarity index 100% rename from textures/items/relik/relik--thunder3.png rename to py_script/textures/items/relik/relik--thunder3.png diff --git a/textures/items/relik/relik--water1.png b/py_script/textures/items/relik/relik--water1.png similarity index 99% rename from textures/items/relik/relik--water1.png rename to py_script/textures/items/relik/relik--water1.png index fe68d65..a4530e4 100644 --- a/textures/items/relik/relik--water1.png +++ b/py_script/textures/items/relik/relik--water1.png @@ -2,7 +2,7 @@ - 404 Not Found +<title> 404 Not Found
diff --git a/textures/items/relik/relik--water2.png b/py_script/textures/items/relik/relik--water2.png similarity index 99% rename from textures/items/relik/relik--water2.png rename to py_script/textures/items/relik/relik--water2.png index fe68d65..a4530e4 100644 --- a/textures/items/relik/relik--water2.png +++ b/py_script/textures/items/relik/relik--water2.png @@ -2,7 +2,7 @@ - 404 Not Found +<title> 404 Not Found
diff --git a/textures/items/relik/relik--water3.png b/py_script/textures/items/relik/relik--water3.png similarity index 99% rename from textures/items/relik/relik--water3.png rename to py_script/textures/items/relik/relik--water3.png index fe68d65..a4530e4 100644 --- a/textures/items/relik/relik--water3.png +++ b/py_script/textures/items/relik/relik--water3.png @@ -2,7 +2,7 @@ - 404 Not Found +<title> 404 Not Found
diff --git a/textures/items/spear/spear--air1.png b/py_script/textures/items/spear/spear--air1.png similarity index 100% rename from textures/items/spear/spear--air1.png rename to py_script/textures/items/spear/spear--air1.png diff --git a/textures/items/spear/spear--air2.png b/py_script/textures/items/spear/spear--air2.png similarity index 100% rename from textures/items/spear/spear--air2.png rename to py_script/textures/items/spear/spear--air2.png diff --git a/textures/items/spear/spear--air3.png b/py_script/textures/items/spear/spear--air3.png similarity index 100% rename from textures/items/spear/spear--air3.png rename to py_script/textures/items/spear/spear--air3.png diff --git a/textures/items/spear/spear--default1.png b/py_script/textures/items/spear/spear--default1.png similarity index 100% rename from textures/items/spear/spear--default1.png rename to py_script/textures/items/spear/spear--default1.png diff --git a/textures/items/spear/spear--default2.png b/py_script/textures/items/spear/spear--default2.png similarity index 100% rename from textures/items/spear/spear--default2.png rename to py_script/textures/items/spear/spear--default2.png diff --git a/textures/items/spear/spear--earth1.png b/py_script/textures/items/spear/spear--earth1.png similarity index 100% rename from textures/items/spear/spear--earth1.png rename to py_script/textures/items/spear/spear--earth1.png diff --git a/textures/items/spear/spear--earth2.png b/py_script/textures/items/spear/spear--earth2.png similarity index 100% rename from textures/items/spear/spear--earth2.png rename to py_script/textures/items/spear/spear--earth2.png diff --git a/textures/items/spear/spear--earth3.png b/py_script/textures/items/spear/spear--earth3.png similarity index 100% rename from textures/items/spear/spear--earth3.png rename to py_script/textures/items/spear/spear--earth3.png diff --git a/textures/items/spear/spear--fire1.png b/py_script/textures/items/spear/spear--fire1.png similarity index 100% rename from textures/items/spear/spear--fire1.png rename to py_script/textures/items/spear/spear--fire1.png diff --git a/textures/items/spear/spear--fire2.png b/py_script/textures/items/spear/spear--fire2.png similarity index 100% rename from textures/items/spear/spear--fire2.png rename to py_script/textures/items/spear/spear--fire2.png diff --git a/textures/items/spear/spear--fire3.png b/py_script/textures/items/spear/spear--fire3.png similarity index 100% rename from textures/items/spear/spear--fire3.png rename to py_script/textures/items/spear/spear--fire3.png diff --git a/textures/items/spear/spear--generic1.png b/py_script/textures/items/spear/spear--generic1.png similarity index 100% rename from textures/items/spear/spear--generic1.png rename to py_script/textures/items/spear/spear--generic1.png diff --git a/textures/items/spear/spear--generic2.png b/py_script/textures/items/spear/spear--generic2.png similarity index 100% rename from textures/items/spear/spear--generic2.png rename to py_script/textures/items/spear/spear--generic2.png diff --git a/textures/items/spear/spear--generic3.png b/py_script/textures/items/spear/spear--generic3.png similarity index 100% rename from textures/items/spear/spear--generic3.png rename to py_script/textures/items/spear/spear--generic3.png diff --git a/textures/items/spear/spear--thunder1.png b/py_script/textures/items/spear/spear--thunder1.png similarity index 100% rename from textures/items/spear/spear--thunder1.png rename to py_script/textures/items/spear/spear--thunder1.png diff --git a/textures/items/spear/spear--thunder2.png b/py_script/textures/items/spear/spear--thunder2.png similarity index 100% rename from textures/items/spear/spear--thunder2.png rename to py_script/textures/items/spear/spear--thunder2.png diff --git a/textures/items/spear/spear--thunder3.png b/py_script/textures/items/spear/spear--thunder3.png similarity index 100% rename from textures/items/spear/spear--thunder3.png rename to py_script/textures/items/spear/spear--thunder3.png diff --git a/textures/items/spear/spear--water1.png b/py_script/textures/items/spear/spear--water1.png similarity index 100% rename from textures/items/spear/spear--water1.png rename to py_script/textures/items/spear/spear--water1.png diff --git a/textures/items/spear/spear--water2.png b/py_script/textures/items/spear/spear--water2.png similarity index 100% rename from textures/items/spear/spear--water2.png rename to py_script/textures/items/spear/spear--water2.png diff --git a/textures/items/spear/spear--water3.png b/py_script/textures/items/spear/spear--water3.png similarity index 100% rename from textures/items/spear/spear--water3.png rename to py_script/textures/items/spear/spear--water3.png diff --git a/textures/items/wand/wand--air1.png b/py_script/textures/items/wand/wand--air1.png similarity index 100% rename from textures/items/wand/wand--air1.png rename to py_script/textures/items/wand/wand--air1.png diff --git a/textures/items/wand/wand--air2.png b/py_script/textures/items/wand/wand--air2.png similarity index 100% rename from textures/items/wand/wand--air2.png rename to py_script/textures/items/wand/wand--air2.png diff --git a/textures/items/wand/wand--air3.png b/py_script/textures/items/wand/wand--air3.png similarity index 100% rename from textures/items/wand/wand--air3.png rename to py_script/textures/items/wand/wand--air3.png diff --git a/textures/items/wand/wand--default1.png b/py_script/textures/items/wand/wand--default1.png similarity index 100% rename from textures/items/wand/wand--default1.png rename to py_script/textures/items/wand/wand--default1.png diff --git a/textures/items/wand/wand--default2.png b/py_script/textures/items/wand/wand--default2.png similarity index 100% rename from textures/items/wand/wand--default2.png rename to py_script/textures/items/wand/wand--default2.png diff --git a/textures/items/wand/wand--earth1.png b/py_script/textures/items/wand/wand--earth1.png similarity index 100% rename from textures/items/wand/wand--earth1.png rename to py_script/textures/items/wand/wand--earth1.png diff --git a/textures/items/wand/wand--earth2.png b/py_script/textures/items/wand/wand--earth2.png similarity index 100% rename from textures/items/wand/wand--earth2.png rename to py_script/textures/items/wand/wand--earth2.png diff --git a/textures/items/wand/wand--earth3.png b/py_script/textures/items/wand/wand--earth3.png similarity index 100% rename from textures/items/wand/wand--earth3.png rename to py_script/textures/items/wand/wand--earth3.png diff --git a/textures/items/wand/wand--fire1.png b/py_script/textures/items/wand/wand--fire1.png similarity index 100% rename from textures/items/wand/wand--fire1.png rename to py_script/textures/items/wand/wand--fire1.png diff --git a/textures/items/wand/wand--fire2.png b/py_script/textures/items/wand/wand--fire2.png similarity index 100% rename from textures/items/wand/wand--fire2.png rename to py_script/textures/items/wand/wand--fire2.png diff --git a/textures/items/wand/wand--fire3.png b/py_script/textures/items/wand/wand--fire3.png similarity index 100% rename from textures/items/wand/wand--fire3.png rename to py_script/textures/items/wand/wand--fire3.png diff --git a/textures/items/wand/wand--generic1.png b/py_script/textures/items/wand/wand--generic1.png similarity index 100% rename from textures/items/wand/wand--generic1.png rename to py_script/textures/items/wand/wand--generic1.png diff --git a/textures/items/wand/wand--generic2.png b/py_script/textures/items/wand/wand--generic2.png similarity index 100% rename from textures/items/wand/wand--generic2.png rename to py_script/textures/items/wand/wand--generic2.png diff --git a/textures/items/wand/wand--generic3.png b/py_script/textures/items/wand/wand--generic3.png similarity index 99% rename from textures/items/wand/wand--generic3.png rename to py_script/textures/items/wand/wand--generic3.png index fe68d65..a4530e4 100644 --- a/textures/items/wand/wand--generic3.png +++ b/py_script/textures/items/wand/wand--generic3.png @@ -2,7 +2,7 @@ - 404 Not Found +<title> 404 Not Found
diff --git a/textures/items/wand/wand--thunder1.png b/py_script/textures/items/wand/wand--thunder1.png similarity index 100% rename from textures/items/wand/wand--thunder1.png rename to py_script/textures/items/wand/wand--thunder1.png diff --git a/textures/items/wand/wand--thunder2.png b/py_script/textures/items/wand/wand--thunder2.png similarity index 100% rename from textures/items/wand/wand--thunder2.png rename to py_script/textures/items/wand/wand--thunder2.png diff --git a/textures/items/wand/wand--thunder3.png b/py_script/textures/items/wand/wand--thunder3.png similarity index 100% rename from textures/items/wand/wand--thunder3.png rename to py_script/textures/items/wand/wand--thunder3.png diff --git a/textures/items/wand/wand--water1.png b/py_script/textures/items/wand/wand--water1.png similarity index 100% rename from textures/items/wand/wand--water1.png rename to py_script/textures/items/wand/wand--water1.png diff --git a/textures/items/wand/wand--water2.png b/py_script/textures/items/wand/wand--water2.png similarity index 100% rename from textures/items/wand/wand--water2.png rename to py_script/textures/items/wand/wand--water2.png diff --git a/textures/items/wand/wand--water3.png b/py_script/textures/items/wand/wand--water3.png similarity index 100% rename from textures/items/wand/wand--water3.png rename to py_script/textures/items/wand/wand--water3.png diff --git a/textures/powder/dye_powder_cyan.png b/py_script/textures/powder/dye_powder_cyan.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_cyan.png rename to py_script/textures/powder/dye_powder_cyan.png diff --git a/textures/powder/dye_powder_gray.png b/py_script/textures/powder/dye_powder_gray.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_gray.png rename to py_script/textures/powder/dye_powder_gray.png diff --git a/textures/powder/dye_powder_green.png b/py_script/textures/powder/dye_powder_green.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_green.png rename to py_script/textures/powder/dye_powder_green.png diff --git a/textures/powder/dye_powder_light_blue.png b/py_script/textures/powder/dye_powder_light_blue.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_light_blue.png rename to py_script/textures/powder/dye_powder_light_blue.png diff --git a/textures/powder/dye_powder_lime.png b/py_script/textures/powder/dye_powder_lime.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_lime.png rename to py_script/textures/powder/dye_powder_lime.png diff --git a/textures/powder/dye_powder_orange.png b/py_script/textures/powder/dye_powder_orange.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_orange.png rename to py_script/textures/powder/dye_powder_orange.png diff --git a/textures/powder/dye_powder_pink.png b/py_script/textures/powder/dye_powder_pink.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_pink.png rename to py_script/textures/powder/dye_powder_pink.png diff --git a/textures/powder/dye_powder_red.png b/py_script/textures/powder/dye_powder_red.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_red.png rename to py_script/textures/powder/dye_powder_red.png diff --git a/textures/powder/dye_powder_silver.png b/py_script/textures/powder/dye_powder_silver.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_silver.png rename to py_script/textures/powder/dye_powder_silver.png diff --git a/textures/powder/dye_powder_yellow.png b/py_script/textures/powder/dye_powder_yellow.png old mode 100755 new mode 100644 similarity index 100% rename from textures/powder/dye_powder_yellow.png rename to py_script/textures/powder/dye_powder_yellow.png From 5fde5faacbfd653375ab79827a53ef659ae3559c Mon Sep 17 00:00:00 2001 From: hppeng Date: Mon, 27 Jun 2022 01:32:26 -0700 Subject: [PATCH 48/68] really minor code cleanup --- js/atree.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/js/atree.js b/js/atree.js index 47e80b3..099715a 100644 --- a/js/atree.js +++ b/js/atree.js @@ -56,17 +56,14 @@ const atree_render = new (class extends ComputeNode { //as of now, we NEED to have the dropdown tab visible/not hidden in order to properly display atree stuff. // TODO: FIXME! this is a side effect of `px` based rendering. if (!document.getElementById("toggle-atree").classList.contains("toggleOn")) { - toggle_tab('atree-dropdown'); - toggleButton('toggle-atree'); + toggle_tab('atree-dropdown'); toggleButton('toggle-atree'); } //for some reason we have to cast to string if (atree) { render_AT(document.getElementById("atree-ui"), atree); } - if (document.getElementById("toggle-atree").classList.contains("toggleOn")) { - toggle_tab('atree-dropdown'); - toggleButton('toggle-atree'); - } + //Toggle on, previously was toggled off + toggle_tab('atree-dropdown'); toggleButton('toggle-atree'); } })(); From b36b16c49d750d69c18817a68e22e719b773f6b2 Mon Sep 17 00:00:00 2001 From: reschan Date: Mon, 27 Jun 2022 16:23:22 +0700 Subject: [PATCH 49/68] fix: separate atree ids for each class --- js/atree_constants.js | 442 +++++++++++++++++----------------- js/atree_constants_min.js | 2 +- js/atree_ids.json | 146 +++++++++++ py_script/atree-convertID.py | 29 +++ py_script/atree-generateID.py | 32 ++- 5 files changed, 412 insertions(+), 239 deletions(-) create mode 100644 js/atree_ids.json create mode 100644 py_script/atree-convertID.py diff --git a/js/atree_constants.js b/js/atree_constants.js index 2f01e7e..48fd997 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -202,7 +202,7 @@ const atrees = { "archetype_req": 0, "parents": [ 68, - 86, + 39, 5 ], "dependencies": [], @@ -250,7 +250,7 @@ const atrees = { "archetype_req": 1, "parents": [ 4, - 82 + 35 ], "dependencies": [ 7 @@ -290,7 +290,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 83, + 36, 69 ], "dependencies": [ @@ -435,12 +435,12 @@ const atrees = { "name": "Single Arrow", "type": "damage", "multipliers": [ - 40, + 30, 0, 0, 0, 0, - 20 + 10 ] }, { @@ -1434,7 +1434,7 @@ const atrees = { ] } ], - "id": 82 + "id": 35 }, { "display_name": "Thunder Mastery", @@ -1443,7 +1443,7 @@ const atrees = { "archetype_req": 0, "parents": [ 7, - 86, + 39, 34 ], "dependencies": [], @@ -1474,7 +1474,7 @@ const atrees = { ] } ], - "id": 83 + "id": 36 }, { "display_name": "Water Mastery", @@ -1483,8 +1483,8 @@ const atrees = { "archetype_req": 0, "parents": [ 34, - 83, - 86 + 36, + 39 ], "dependencies": [], "blockers": [], @@ -1514,7 +1514,7 @@ const atrees = { ] } ], - "id": 84 + "id": 37 }, { "display_name": "Air Mastery", @@ -1552,7 +1552,7 @@ const atrees = { ] } ], - "id": 85 + "id": 38 }, { "display_name": "Fire Mastery", @@ -1560,7 +1560,7 @@ const atrees = { "archetype": "Sharpshooter", "archetype_req": 0, "parents": [ - 83, + 36, 0, 34 ], @@ -1592,7 +1592,7 @@ const atrees = { ] } ], - "id": 86 + "id": 39 }, { "display_name": "More Shields", @@ -2196,7 +2196,7 @@ const atrees = { "name": "damMult" }, "scaling": [ - 35 + 3 ], "max": 3 } @@ -2398,7 +2398,7 @@ const atrees = { "archetype": "Sharpshooter", "archetype_req": 0, "parents": [ - 84, + 37, 4 ], "dependencies": [ @@ -2457,7 +2457,7 @@ const atrees = { "archetype_req": 0, "parents": [ 6, - 85 + 38 ], "dependencies": [ 0 @@ -2573,7 +2573,7 @@ const atrees = { ] } ], - "id": 71 + "id": 0 }, { "display_name": "Spear Proficiency 1", @@ -2581,7 +2581,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 71 + 0 ], "dependencies": [], "blockers": [], @@ -2606,7 +2606,7 @@ const atrees = { ] } ], - "id": 72 + "id": 1 }, { "display_name": "Cheaper Bash", @@ -2614,7 +2614,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 72 + 1 ], "dependencies": [], "blockers": [], @@ -2632,7 +2632,7 @@ const atrees = { "cost": -10 } ], - "id": 73 + "id": 2 }, { "display_name": "Double Bash", @@ -2640,7 +2640,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 72 + 1 ], "dependencies": [], "blockers": [], @@ -2679,7 +2679,7 @@ const atrees = { ] } ], - "id": 74 + "id": 3 }, { "display_name": "Charge", @@ -2687,7 +2687,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 74 + 3 ], "dependencies": [], "blockers": [], @@ -2731,7 +2731,7 @@ const atrees = { ] } ], - "id": 75 + "id": 4 }, { "display_name": "Heavy Impact", @@ -2739,7 +2739,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 79 + 8 ], "dependencies": [], "blockers": [], @@ -2768,7 +2768,7 @@ const atrees = { ] } ], - "id": 76 + "id": 5 }, { "display_name": "Vehement", @@ -2776,11 +2776,11 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 75 + 4 ], "dependencies": [], "blockers": [ - 78 + 7 ], "cost": 1, "display": { @@ -2814,7 +2814,7 @@ const atrees = { "max": 20 } ], - "id": 77 + "id": 6 }, { "display_name": "Tougher Skin", @@ -2822,11 +2822,11 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 75 + 4 ], "dependencies": [], "blockers": [ - 77 + 6 ], "cost": 1, "display": { @@ -2870,7 +2870,7 @@ const atrees = { "max": 100 } ], - "id": 78 + "id": 7 }, { "display_name": "Uppercut", @@ -2878,7 +2878,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 77 + 6 ], "dependencies": [], "blockers": [], @@ -2925,7 +2925,7 @@ const atrees = { ] } ], - "id": 79 + "id": 8 }, { "display_name": "Cheaper Charge", @@ -2933,8 +2933,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 79, - 81 + 8, + 10 ], "dependencies": [], "blockers": [], @@ -2952,7 +2952,7 @@ const atrees = { "cost": -5 } ], - "id": 80 + "id": 9 }, { "display_name": "War Scream", @@ -2960,7 +2960,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 78 + 7 ], "dependencies": [], "blockers": [], @@ -3001,7 +3001,7 @@ const atrees = { ] } ], - "id": 81 + "id": 10 }, { "display_name": "Earth Mastery", @@ -3009,7 +3009,7 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 79 + 8 ], "dependencies": [], "blockers": [], @@ -3040,7 +3040,7 @@ const atrees = { ] } ], - "id": 82 + "id": 11 }, { "display_name": "Thunder Mastery", @@ -3048,9 +3048,9 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 79, - 85, - 80 + 8, + 14, + 9 ], "dependencies": [], "blockers": [], @@ -3081,7 +3081,7 @@ const atrees = { ] } ], - "id": 83 + "id": 12 }, { "display_name": "Water Mastery", @@ -3089,9 +3089,9 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 80, - 83, - 85 + 9, + 12, + 14 ], "dependencies": [], "blockers": [], @@ -3122,7 +3122,7 @@ const atrees = { ] } ], - "id": 84 + "id": 13 }, { "display_name": "Air Mastery", @@ -3130,9 +3130,9 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 81, - 83, - 80 + 10, + 12, + 9 ], "dependencies": [], "blockers": [], @@ -3163,7 +3163,7 @@ const atrees = { ] } ], - "id": 85 + "id": 14 }, { "display_name": "Fire Mastery", @@ -3171,7 +3171,7 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 81 + 10 ], "dependencies": [], "blockers": [], @@ -3202,7 +3202,7 @@ const atrees = { ] } ], - "id": 86 + "id": 15 }, { "display_name": "Quadruple Bash", @@ -3210,8 +3210,8 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 82, - 88 + 11, + 17 ], "dependencies": [], "blockers": [], @@ -3249,7 +3249,7 @@ const atrees = { ] } ], - "id": 87 + "id": 16 }, { "display_name": "Fireworks", @@ -3257,8 +3257,8 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 83, - 87 + 12, + 16 ], "dependencies": [], "blockers": [], @@ -3294,7 +3294,7 @@ const atrees = { } } ], - "id": 88 + "id": 17 }, { "display_name": "Half-Moon Swipe", @@ -3302,10 +3302,10 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 1, "parents": [ - 84 + 13 ], "dependencies": [ - 79 + 8 ], "blockers": [], "cost": 2, @@ -3338,7 +3338,7 @@ const atrees = { "conversion": "water" } ], - "id": 89 + "id": 18 }, { "display_name": "Flyby Jab", @@ -3346,8 +3346,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 85, - 91 + 14, + 20 ], "dependencies": [], "blockers": [], @@ -3376,7 +3376,7 @@ const atrees = { ] } ], - "id": 90 + "id": 19 }, { "display_name": "Flaming Uppercut", @@ -3384,11 +3384,11 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 86, - 90 + 15, + 19 ], "dependencies": [ - 79 + 8 ], "blockers": [], "cost": 2, @@ -3435,7 +3435,7 @@ const atrees = { } } ], - "id": 91 + "id": 20 }, { "display_name": "Iron Lungs", @@ -3443,8 +3443,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 90, - 91 + 19, + 20 ], "dependencies": [], "blockers": [], @@ -3471,7 +3471,7 @@ const atrees = { ] } ], - "id": 92 + "id": 21 }, { "display_name": "Generalist", @@ -3479,7 +3479,7 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 3, "parents": [ - 94 + 23 ], "dependencies": [], "blockers": [], @@ -3491,7 +3491,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 93 + "id": 22 }, { "display_name": "Counter", @@ -3499,7 +3499,7 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 89 + 18 ], "dependencies": [], "blockers": [], @@ -3528,7 +3528,7 @@ const atrees = { ] } ], - "id": 94 + "id": 23 }, { "display_name": "Mantle of the Bovemists", @@ -3536,10 +3536,10 @@ const atrees = { "archetype": "Paladin", "archetype_req": 3, "parents": [ - 92 + 21 ], "dependencies": [ - 81 + 10 ], "blockers": [], "cost": 2, @@ -3552,7 +3552,7 @@ const atrees = { "mantle_charge": 3 }, "effects": [], - "id": 95 + "id": 24 }, { "display_name": "Bak'al's Grasp", @@ -3560,11 +3560,11 @@ const atrees = { "archetype": "Fallen", "archetype_req": 2, "parents": [ - 87, - 88 + 16, + 17 ], "dependencies": [ - 81 + 10 ], "blockers": [], "cost": 2, @@ -3592,7 +3592,7 @@ const atrees = { "max": 120 } ], - "id": 96 + "id": 25 }, { "display_name": "Spear Proficiency 2", @@ -3600,8 +3600,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 96, - 98 + 25, + 27 ], "dependencies": [], "blockers": [], @@ -3626,7 +3626,7 @@ const atrees = { ] } ], - "id": 97 + "id": 26 }, { "display_name": "Cheaper Uppercut", @@ -3634,9 +3634,9 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 97, - 99, - 94 + 26, + 28, + 23 ], "dependencies": [], "blockers": [], @@ -3654,7 +3654,7 @@ const atrees = { "cost": -5 } ], - "id": 98 + "id": 27 }, { "display_name": "Aerodynamics", @@ -3662,8 +3662,8 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 98, - 100 + 27, + 29 ], "dependencies": [], "blockers": [], @@ -3675,7 +3675,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 99 + "id": 28 }, { "display_name": "Provoke", @@ -3683,8 +3683,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 99, - 95 + 28, + 24 ], "dependencies": [], "blockers": [], @@ -3702,7 +3702,7 @@ const atrees = { "cost": -5 } ], - "id": 100 + "id": 29 }, { "display_name": "Precise Strikes", @@ -3710,8 +3710,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 98, - 97 + 27, + 26 ], "dependencies": [], "blockers": [], @@ -3734,7 +3734,7 @@ const atrees = { ] } ], - "id": 101 + "id": 30 }, { "display_name": "Air Shout", @@ -3742,11 +3742,11 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 99, - 100 + 28, + 29 ], "dependencies": [ - 81 + 10 ], "blockers": [], "cost": 2, @@ -3772,7 +3772,7 @@ const atrees = { ] } ], - "id": 102 + "id": 31 }, { "display_name": "Enraged Blow", @@ -3780,10 +3780,10 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 97 + 26 ], "dependencies": [ - 96 + 25 ], "blockers": [], "cost": 2, @@ -3813,7 +3813,7 @@ const atrees = { "max": 300 } ], - "id": 103 + "id": 32 }, { "display_name": "Flying Kick", @@ -3821,8 +3821,8 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 1, "parents": [ - 98, - 105 + 27, + 34 ], "dependencies": [], "blockers": [], @@ -3849,7 +3849,7 @@ const atrees = { ] } ], - "id": 104 + "id": 33 }, { "display_name": "Stronger Mantle", @@ -3857,11 +3857,11 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 106, - 104 + 35, + 33 ], "dependencies": [ - 95 + 24 ], "blockers": [], "cost": 1, @@ -3874,7 +3874,7 @@ const atrees = { "mantle_charge": 2 }, "effects": [], - "id": 105 + "id": 34 }, { "display_name": "Manachism", @@ -3882,8 +3882,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 3, "parents": [ - 105, - 100 + 34, + 29 ], "dependencies": [], "blockers": [], @@ -3897,7 +3897,7 @@ const atrees = { "cooldown": 1 }, "effects": [], - "id": 106 + "id": 35 }, { "display_name": "Boiling Blood", @@ -3905,8 +3905,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 103, - 108 + 32, + 37 ], "dependencies": [], "blockers": [], @@ -3933,7 +3933,7 @@ const atrees = { ] } ], - "id": 107 + "id": 36 }, { "display_name": "Ragnarokkr", @@ -3941,11 +3941,11 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 107, - 104 + 36, + 33 ], "dependencies": [ - 81 + 10 ], "blockers": [], "cost": 2, @@ -3965,7 +3965,7 @@ const atrees = { "cost": 10 } ], - "id": 108 + "id": 37 }, { "display_name": "Ambidextrous", @@ -3973,12 +3973,12 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 104, - 105, - 110 + 33, + 34, + 39 ], "dependencies": [ - 94 + 23 ], "blockers": [], "cost": 1, @@ -3991,7 +3991,7 @@ const atrees = { "chance": 30 }, "effects": [], - "id": 109 + "id": 38 }, { "display_name": "Burning Heart", @@ -3999,8 +3999,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 109, - 111 + 38, + 40 ], "dependencies": [], "blockers": [], @@ -4032,7 +4032,7 @@ const atrees = { "slider_step": 100 } ], - "id": 110 + "id": 39 }, { "display_name": "Stronger Bash", @@ -4040,8 +4040,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 110, - 106 + 39, + 35 ], "dependencies": [], "blockers": [], @@ -4068,7 +4068,7 @@ const atrees = { ] } ], - "id": 111 + "id": 40 }, { "display_name": "Intoxicating Blood", @@ -4076,11 +4076,11 @@ const atrees = { "archetype": "Fallen", "archetype_req": 5, "parents": [ - 108, - 107 + 37, + 36 ], "dependencies": [ - 96 + 25 ], "blockers": [], "cost": 2, @@ -4091,7 +4091,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 112 + "id": 41 }, { "display_name": "Comet", @@ -4099,10 +4099,10 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 108 + 37 ], "dependencies": [ - 88 + 17 ], "blockers": [], "cost": 2, @@ -4137,7 +4137,7 @@ const atrees = { } } ], - "id": 113 + "id": 42 }, { "display_name": "Collide", @@ -4145,11 +4145,11 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 4, "parents": [ - 109, - 110 + 38, + 39 ], "dependencies": [ - 104 + 33 ], "blockers": [], "cost": 2, @@ -4177,7 +4177,7 @@ const atrees = { ] } ], - "id": 114 + "id": 43 }, { "display_name": "Rejuvenating Skin", @@ -4185,8 +4185,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 110, - 111 + 39, + 40 ], "dependencies": [], "blockers": [], @@ -4198,7 +4198,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 115 + "id": 44 }, { "display_name": "Uncontainable Corruption", @@ -4206,11 +4206,11 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 107, - 117 + 36, + 46 ], "dependencies": [ - 96 + 25 ], "blockers": [], "cost": 1, @@ -4238,7 +4238,7 @@ const atrees = { "max": 50 } ], - "id": 116 + "id": 45 }, { "display_name": "Radiant Devotee", @@ -4246,8 +4246,8 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 1, "parents": [ - 118, - 116 + 47, + 45 ], "dependencies": [], "blockers": [], @@ -4278,7 +4278,7 @@ const atrees = { "slider_step": 4 } ], - "id": 117 + "id": 46 }, { "display_name": "Whirlwind Strike", @@ -4286,11 +4286,11 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 5, "parents": [ - 109, - 117 + 38, + 46 ], "dependencies": [ - 79 + 8 ], "blockers": [], "cost": 2, @@ -4318,7 +4318,7 @@ const atrees = { ] } ], - "id": 118 + "id": 47 }, { "display_name": "Mythril Skin", @@ -4326,7 +4326,7 @@ const atrees = { "archetype": "Paladin", "archetype_req": 6, "parents": [ - 115 + 44 ], "dependencies": [], "blockers": [], @@ -4349,7 +4349,7 @@ const atrees = { ] } ], - "id": 119 + "id": 48 }, { "display_name": "Armour Breaker", @@ -4357,11 +4357,11 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 116, - 117 + 45, + 46 ], "dependencies": [ - 96 + 25 ], "blockers": [], "cost": 2, @@ -4374,7 +4374,7 @@ const atrees = { "duration": 5 }, "effects": [], - "id": 120 + "id": 49 }, { "display_name": "Shield Strike", @@ -4382,8 +4382,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 119, - 122 + 48, + 51 ], "dependencies": [], "blockers": [], @@ -4410,7 +4410,7 @@ const atrees = { ] } ], - "id": 121 + "id": 50 }, { "display_name": "Sparkling Hope", @@ -4418,7 +4418,7 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 119 + 48 ], "dependencies": [], "blockers": [], @@ -4447,7 +4447,7 @@ const atrees = { ] } ], - "id": 122 + "id": 51 }, { "display_name": "Massive Bash", @@ -4455,8 +4455,8 @@ const atrees = { "archetype": "Fallen", "archetype_req": 8, "parents": [ - 124, - 116 + 53, + 45 ], "dependencies": [], "blockers": [], @@ -4483,7 +4483,7 @@ const atrees = { "slider_step": 3 } ], - "id": 123 + "id": 52 }, { "display_name": "Tempest", @@ -4491,8 +4491,8 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 123, - 125 + 52, + 54 ], "dependencies": [], "blockers": [], @@ -4539,7 +4539,7 @@ const atrees = { } } ], - "id": 124 + "id": 53 }, { "display_name": "Spirit of the Rabbit", @@ -4547,8 +4547,8 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 5, "parents": [ - 124, - 118 + 53, + 47 ], "dependencies": [], "blockers": [], @@ -4576,7 +4576,7 @@ const atrees = { ] } ], - "id": 125 + "id": 54 }, { "display_name": "Massacre", @@ -4584,8 +4584,8 @@ const atrees = { "archetype": "Fallen", "archetype_req": 5, "parents": [ - 124, - 123 + 53, + 52 ], "dependencies": [], "blockers": [], @@ -4597,7 +4597,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 126 + "id": 55 }, { "display_name": "Axe Kick", @@ -4605,8 +4605,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 124, - 125 + 53, + 54 ], "dependencies": [], "blockers": [], @@ -4633,7 +4633,7 @@ const atrees = { ] } ], - "id": 127 + "id": 56 }, { "display_name": "Radiance", @@ -4641,8 +4641,8 @@ const atrees = { "archetype": "Paladin", "archetype_req": 2, "parents": [ - 125, - 129 + 54, + 58 ], "dependencies": [], "blockers": [], @@ -4656,7 +4656,7 @@ const atrees = { "cooldown": 15 }, "effects": [], - "id": 128 + "id": 57 }, { "display_name": "Cheaper Bash 2", @@ -4664,9 +4664,9 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 128, - 121, - 122 + 57, + 50, + 51 ], "dependencies": [], "blockers": [], @@ -4684,7 +4684,7 @@ const atrees = { "cost": -5 } ], - "id": 129 + "id": 58 }, { "display_name": "Cheaper War Scream", @@ -4692,7 +4692,7 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 123 + 52 ], "dependencies": [], "blockers": [], @@ -4710,15 +4710,15 @@ const atrees = { "cost": -5 } ], - "id": 130 + "id": 59 }, { "display_name": "Discombobulate", "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", "archetype": "Battle Monk", - "archetype_req": 12, + "archetype_req": 11, "parents": [ - 133 + 62 ], "dependencies": [], "blockers": [], @@ -4744,7 +4744,7 @@ const atrees = { "max": 50 } ], - "id": 131 + "id": 60 }, { "display_name": "Thunderclap", @@ -4752,7 +4752,7 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 8, "parents": [ - 133 + 62 ], "dependencies": [], "blockers": [], @@ -4781,7 +4781,7 @@ const atrees = { ] } ], - "id": 132 + "id": 61 }, { "display_name": "Cyclone", @@ -4789,7 +4789,7 @@ const atrees = { "archetype": "Battle Monk", "archetype_req": 0, "parents": [ - 125 + 54 ], "dependencies": [], "blockers": [], @@ -4828,7 +4828,7 @@ const atrees = { } } ], - "id": 133 + "id": 62 }, { "display_name": "Second Chance", @@ -4836,7 +4836,7 @@ const atrees = { "archetype": "Paladin", "archetype_req": 12, "parents": [ - 129 + 58 ], "dependencies": [], "blockers": [], @@ -4848,7 +4848,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 134 + "id": 63 }, { "display_name": "Blood Pact", @@ -4856,7 +4856,7 @@ const atrees = { "archetype": "", "archetype_req": 10, "parents": [ - 130 + 59 ], "dependencies": [], "blockers": [], @@ -4868,7 +4868,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 135 + "id": 64 }, { "display_name": "Haemorrhage", @@ -4876,10 +4876,10 @@ const atrees = { "archetype": "Fallen", "archetype_req": 0, "parents": [ - 135 + 64 ], "dependencies": [ - 135 + 64 ], "blockers": [], "cost": 1, @@ -4890,7 +4890,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 136 + "id": 65 }, { "display_name": "Brink of Madness", @@ -4898,8 +4898,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 135, - 138 + 64, + 67 ], "dependencies": [], "blockers": [], @@ -4911,7 +4911,7 @@ const atrees = { }, "properties": {}, "effects": [], - "id": 137 + "id": 66 }, { "display_name": "Cheaper Uppercut 2", @@ -4919,8 +4919,8 @@ const atrees = { "archetype": "", "archetype_req": 0, "parents": [ - 134, - 137 + 63, + 66 ], "dependencies": [], "blockers": [], @@ -4938,7 +4938,7 @@ const atrees = { "cost": -5 } ], - "id": 138 + "id": 67 }, { "display_name": "Martyr", @@ -4946,7 +4946,7 @@ const atrees = { "archetype": "Paladin", "archetype_req": 0, "parents": [ - 134 + 63 ], "dependencies": [], "blockers": [], @@ -4961,7 +4961,7 @@ const atrees = { "aoe": 12 }, "effects": [], - "id": 139 + "id": 68 } ] -} +} \ No newline at end of file diff --git a/js/atree_constants_min.js b/js/atree_constants_min.js index ac8955c..52d1082 100644 --- a/js/atree_constants_min.js +++ b/js/atree_constants_min.js @@ -1 +1 @@ -const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:[60,34],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}],id:0},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:[3],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}],id:1},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}],id:2},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:[31],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}],id:3},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:[68,86,5],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}],id:4},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:[4,82],dependencies:[7],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}],id:5},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:[83,69],dependencies:[7],blockers:[68],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}],id:6},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:[58,34],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}],id:7},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:[59,67],dependencies:[0],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}],id:8},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"",archetype_req:0,parents:[7],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}],id:9},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:[5],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}],id:10},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:[8,33],dependencies:[],blockers:[68],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}],id:11},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:[61,40,33],dependencies:[],blockers:[20],cost:2,display:{row:21,col:5},properties:{range:20},effects:[],id:12},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:[12,40],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}],id:13},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:[62,64],dependencies:[61],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}],id:14},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:[42,64],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}],id:15},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:[14],dependencies:[4],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}],id:16},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:[42,55],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[],id:17},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:[14,44,55],dependencies:[2],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}],id:18},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:[43,44],dependencies:[4],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}],id:19},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:[46,17],dependencies:[],blockers:[12],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}],id:20},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:[18,44,47],dependencies:[61],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}],id:21},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:[21,47],dependencies:[0],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}],id:22},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:[48,20],dependencies:[],blockers:[68],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}],id:23},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:[56],dependencies:[15],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}],id:24},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:[49],dependencies:[7],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}],id:25},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:[51],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}],id:26},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:[26],dependencies:[10],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}],id:27},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:[24,63],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3},id:28},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:[28],dependencies:[8],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}],id:29},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:[26,53],dependencies:[10],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}],id:30},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:[2],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:31},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:[31],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}],id:32},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:[12,11,61],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:33},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:[7,0],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:34},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:[0],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}],id:82},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:[7,86,34],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}],id:83},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:[34,83,86],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}],id:84},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:[7],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}],id:85},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:[83,0,34],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}],id:86},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:[12,10],dependencies:[0],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2},id:40},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:[11],dependencies:[9],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}],id:41},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:[11],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}],id:42},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:[54],dependencies:[10],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2},id:43},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:[19,18,14],dependencies:[0],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}],id:44},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:[17,55],dependencies:[17],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1},id:45},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:[20,55],dependencies:[8],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}],id:46},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:[21,19],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:47},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:[46,49,23],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}],id:48},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:[48,21],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:49},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:[47,21],dependencies:[2],blockers:[],cost:1,display:{row:33,col:6},properties:{},id:50},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:[22,70],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:51},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:[51],dependencies:[12],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8},id:52},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:[63,30],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:53},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:[40],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}],id:54},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:[17,18],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[],id:55},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:[23,48],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}],id:56},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:[24],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[],id:57},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:[1],dependencies:[],blockers:[60],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}],id:58},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:[69,67],dependencies:[58],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}],id:59},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:[1],dependencies:[],blockers:[58],cost:1,display:{row:7,col:6},properties:{},effects:[],id:60},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:[68],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:3}],id:61},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:[33,12],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:5}],id:62},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:[25,28],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"damMult"},scaling:[35],max:7}],id:63},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:[42,14],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}],id:64},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:[40],dependencies:[10],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[],id:65},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:[26],dependencies:[65],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[],id:66},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:[59,6],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}],id:67},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:[84,4],dependencies:[7],blockers:[11,6,23],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}],id:68},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:[6,85],dependencies:[0],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}],id:69},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:[49],dependencies:[68],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}],id:70}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}],id:71},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:[71],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:72},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:[72],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}],id:73},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:[72],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}],id:74},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:[74],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}],id:75},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:[79],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}],id:76},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:[75],dependencies:[],blockers:[78],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}],id:77},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:[75],dependencies:[],blockers:[77],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}],id:78},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:[77],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}],id:79},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:[79,81],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}],id:80},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:[78],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}],id:81},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:[79],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}],id:82},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:[79,85,80],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}],id:83},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:[80,83,85],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}],id:84},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:[81,83,80],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}],id:85},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:[81],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}],id:86},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:[82,88],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}],id:87},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:[83,87],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}],id:88},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:[84],dependencies:[79],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}],id:89},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:[85,91],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}],id:90},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:[86,90],dependencies:[79],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}],id:91},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:[90,91],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}],id:92},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:[94],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[],id:93},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:[89],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}],id:94},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:[92],dependencies:[81],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[],id:95},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:[87,88],dependencies:[81],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}],id:96},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:[96,98],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}],id:97},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:[97,99,94],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:98},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:[98,100],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[],id:99},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:[99,95],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:100},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:[98,97],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}],id:101},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:[99,100],dependencies:[81],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}],id:102},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:[97],dependencies:[96],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"damMult"},scaling:[3],max:300}],id:103},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:[98,105],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}],id:104},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:[106,104],dependencies:[95],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[],id:105},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:[105,100],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[],id:106},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:[103,108],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}],id:107},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:[107,104],dependencies:[81],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}],id:108},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:[104,105,110],dependencies:[94],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[],id:109},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:[109,111],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}],id:110},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:[110,106],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}],id:111},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:[108,107],dependencies:[96],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[],id:112},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:[108],dependencies:[88],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}],id:113},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:[109,110],dependencies:[104],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}],id:114},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:[110,111],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[],id:115},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:[107,117],dependencies:[96],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}],id:116},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:[118,116],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}],id:117},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:[109,117],dependencies:[79],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}],id:118},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:[115],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}],id:119},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:[116,117],dependencies:[96],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[],id:120},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:[119,122],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}],id:121},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:[119],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}],id:122},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:[124,116],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}],id:123},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:[123,125],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}],id:124},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:[124,118],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}],id:125},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:[124,123],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[],id:126},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:[124,125],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}],id:127},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:[125,129],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[],id:128},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:[128,121,122],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}],id:129},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:[123],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}],id:130},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:[133],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}],id:131},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:[133],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}],id:132},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:[125],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}],id:133},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:[129],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[],id:134},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:[130],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[],id:135},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:[135],dependencies:[135],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[],id:136},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:[135,138],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[],id:137},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:[134,137],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}],id:138},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:[134],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[],id:139}]} \ No newline at end of file +const atrees={"Archer":[{"display_name":"Arrow Shield","desc":"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)","archetype":"","archetype_req":0,"parents":[60,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":6},"properties":{"duration":60},"effects":[{"type":"replace_spell","name":"Arrow Shield","cost":30,"display_text":"Max Damage","base_spell":4,"spell_type":"damage","scaling":"spell","display":"","parts":[{"name":"Shield Damage","type":"damage","multipliers":[90,0,0,0,0,10]},{"name":"Total Damage","type":"total","hits":{"Shield Damage":2}}]}],"id":0},{"display_name":"Escape","desc":"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":7,"col":4},"properties":{"aoe":0,"range":0},"effects":[{"type":"replace_spell","name":"Escape","cost":25,"display_text":"Max Damage","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":1},{"display_name":"Arrow Bomb","desc":"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4},"properties":{"aoe":4.5,"range":26},"effects":[{"type":"replace_spell","name":"Arrow Bomb","cost":50,"display_text":"Average Damage","base_spell":3,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Arrow Bomb","type":"damage","multipliers":[160,0,0,0,20,0]},{"name":"Total Damage","type":"total","hits":{"Arrow Bomb":1}}]}],"id":2},{"display_name":"Heart Shatter","desc":"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[100,0,0,0,0,0]},{}],"id":3},{"display_name":"Fire Creep","desc":"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.","archetype":"","archetype_req":0,"parents":[68,39,5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":16,"col":6},"properties":{"aoe":0.8,"duration":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[30,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fire Creep":15}}],"id":4},{"display_name":"Bryophyte Roots","desc":"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.","archetype":"Trapper","archetype_req":1,"parents":[4,35],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":16,"col":8},"properties":{"aoe":2,"duration":5,"slowness":0.4},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Bryophyte Roots","cost":0,"multipliers":[40,20,0,0,0,0]}],"id":5},{"display_name":"Nimble String","desc":"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.","archetype":"","archetype_req":0,"parents":[36,69],"dependencies":[7],"blockers":[68],"cost":2,"display":{"row":15,"col":2},"properties":{"shootspeed":2},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-15,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":8}}],"id":6},{"display_name":"Arrow Storm","desc":"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.","archetype":"","archetype_req":0,"parents":[58,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":2},"properties":{"aoe":0,"range":16},"effects":[{"type":"replace_spell","name":"Arrow Storm","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,10,0,0,0]},{"name":"Single Stream","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Stream":2}}]}],"id":7},{"display_name":"Guardian Angels","desc":"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)","archetype":"Boltslinger","archetype_req":3,"parents":[59,67],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":19,"col":1},"properties":{"range":4,"duration":60,"shots":8,"count":2},"effects":[{"type":"replace_spell","name":"Guardian Angels","cost":30,"display_text":"Total Damage Average","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,0,0,0,10]},{"name":"Single Bow","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Bow":2}}]}],"id":8},{"display_name":"Windy Feet","base_abil":"Escape","desc":"When casting Escape, give speed to yourself and nearby allies.","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":1},"properties":{"aoe":8,"duration":120},"type":"stat_bonus","bonuses":[{"type":"stat","name":"spd","value":20}],"id":9},{"display_name":"Basaltic Trap","desc":"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)","archetype":"Trapper","archetype_req":2,"parents":[5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":8},"properties":{"aoe":7,"traps":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[140,30,0,0,30,0]}],"id":10},{"display_name":"Windstorm","desc":"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.","archetype":"","archetype_req":0,"parents":[8,33],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":21,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-11,0,-7,0,0,3]},{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":1}}],"id":11},{"display_name":"Grappling Hook","base_abil":"Escape","desc":"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)","archetype":"Trapper","archetype_req":0,"parents":[61,40,33],"dependencies":[],"blockers":[20],"cost":2,"display":{"row":21,"col":5},"properties":{"range":20},"effects":[],"id":12},{"display_name":"Implosion","desc":"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.","archetype":"Trapper","archetype_req":0,"parents":[12,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":13},{"display_name":"Twain's Arc","desc":"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)","archetype":"Sharpshooter","archetype_req":4,"parents":[62,64],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":25,"col":4},"properties":{"range":64,"focusReq":2},"effects":[{"type":"replace_spell","name":"Twain's Arc","cost":0,"display_text":"Twain's Arc","base_spell":5,"spell_type":"damage","scaling":"melee","display":"Twain's Arc Damage","parts":[{"name":"Twain's Arc Damage","type":"damage","multipliers":[200,0,0,0,0,0]}]}],"id":14},{"display_name":"Fierce Stomp","desc":"When using Escape, hold shift to quickly drop down and deal damage.","archetype":"Boltslinger","archetype_req":0,"parents":[42,64],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":1},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[100,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":2,"target_part":"Total Damage","cost":0,"hits":{"Fierce Stomp":1}}],"id":15},{"display_name":"Scorched Earth","desc":"Fire Creep become much stronger.","archetype":"Sharpshooter","archetype_req":0,"parents":[14],"dependencies":[4],"blockers":[],"cost":1,"display":{"row":26,"col":5},"properties":{"duration":2,"aoe":0.4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[10,0,0,0,5,0]}],"id":16},{"display_name":"Leap","desc":"When you double tap jump, leap foward. (2s Cooldown)","archetype":"Boltslinger","archetype_req":5,"parents":[42,55],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0},"properties":{"cooldown":2},"effects":[],"id":17},{"display_name":"Shocking Bomb","desc":"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.","archetype":"Sharpshooter","archetype_req":5,"parents":[14,44,55],"dependencies":[2],"blockers":[],"cost":2,"display":{"row":28,"col":4},"properties":{"gravity":0},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"}],"id":18},{"display_name":"Mana Trap","desc":"Your Traps will give you 4 Mana per second when you stay close to them.","archetype":"Trapper","archetype_req":5,"parents":[43,44],"dependencies":[4],"blockers":[],"cost":2,"display":{"row":28,"col":8},"properties":{"range":12,"manaRegen":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":10,"multipliers":[0,0,0,0,0,0]}],"id":19},{"display_name":"Escape Artist","desc":"When casting Escape, release 100 arrows towards the ground.","archetype":"Boltslinger","archetype_req":0,"parents":[46,17],"dependencies":[],"blockers":[12],"cost":2,"display":{"row":31,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Escape Artist","cost":0,"multipliers":[30,0,10,0,0,0]}],"id":20},{"display_name":"Initiator","desc":"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.","archetype":"Sharpshooter","archetype_req":5,"parents":[18,44,47],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":31,"col":5},"properties":{"focus":1,"timer":5},"type":"stat_bonus","bonuses":[{"type":"stat","name":"damPct","value":50}],"id":21},{"display_name":"Call of the Hound","desc":"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.","archetype":"Trapper","archetype_req":0,"parents":[21,47],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":32,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Call of the Hound","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":22},{"display_name":"Arrow Hurricane","desc":"Arrow Storm will shoot +2 stream of arrows.","archetype":"Boltslinger","archetype_req":8,"parents":[48,20],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":33,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":2}}],"id":23},{"display_name":"Geyser Stomp","desc":"Fierce Stomp will create geysers, dealing more damage and vertical knockback.","archetype":"","archetype_req":0,"parents":[56],"dependencies":[15],"blockers":[],"cost":2,"display":{"row":37,"col":1},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[0,0,0,50,0,0]}],"id":24},{"display_name":"Crepuscular Ray","desc":"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.","archetype":"Sharpshooter","archetype_req":10,"parents":[49],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":37,"col":4},"properties":{"focusReq":5,"focusRegen":-1},"effects":[{"type":"replace_spell","name":"Crepuscular Ray","base_spell":5,"spell_type":"damage","scaling":"spell","display":"One Focus","cost":0,"parts":[{"name":"Single Arrow","type":"damage","multipliers":[10,0,0,5,0,0]},{"name":"One Focus","type":"total","hits":{"Single Arrow":20}},{"name":"Total Damage","type":"total","hits":{"One Focus":7}}]}],"id":25},{"display_name":"Grape Bomb","desc":"Arrow bomb will throw 3 additional smaller bombs when exploding.","archetype":"","archetype_req":0,"parents":[51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":37,"col":7},"properties":{"miniBombs":3,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Grape Bomb","cost":0,"multipliers":[30,0,0,0,10,0]}],"id":26},{"display_name":"Tangled Traps","desc":"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":38,"col":6},"properties":{"attackSpeed":0.2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Tangled Traps","cost":0,"multipliers":[20,0,0,0,0,20]}],"id":27},{"display_name":"Snow Storm","desc":"Enemies near you will be slowed down.","archetype":"","archetype_req":0,"parents":[24,63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":39,"col":2},"properties":{"range":2.5,"slowness":0.3},"id":28},{"display_name":"All-Seeing Panoptes","desc":"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.","archetype":"Boltslinger","archetype_req":11,"parents":[28],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":40,"col":1},"properties":{"range":10,"shots":5},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Arrow","cost":0,"multipliers":[0,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":5}}],"id":29},{"display_name":"Minefield","desc":"Allow you to place +6 Traps, but with reduced damage and range.","archetype":"Trapper","archetype_req":10,"parents":[26,53],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":40,"col":7},"properties":{"aoe":-2,"traps":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[-80,0,0,0,0,0]}],"id":30},{"display_name":"Bow Proficiency I","desc":"Improve your Main Attack's damage and range when using a bow.","archetype":"","archetype_req":0,"parents":[2],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":31},{"display_name":"Cheaper Arrow Bomb","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-10}],"id":32},{"display_name":"Cheaper Arrow Storm","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[12,11,61],"dependencies":[],"blockers":[],"cost":1,"display":{"row":21,"col":3},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":33},{"display_name":"Cheaper Escape","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[7,0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":34},{"display_name":"Earth Mastery","desc":"Increases your base damage from all Earth attacks","archetype":"Trapper","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":8},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":35},{"display_name":"Thunder Mastery","desc":"Increases your base damage from all Thunder attacks","archetype":"Boltslinger","archetype_req":0,"parents":[7,39,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":2},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":36},{"display_name":"Water Mastery","desc":"Increases your base damage from all Water attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[34,36,39],"dependencies":[],"blockers":[],"cost":1,"display":{"row":14,"col":4},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":37},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":0},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":38},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[36,0,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":6},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":39},{"display_name":"More Shields","desc":"Give +2 charges to Arrow Shield.","archetype":"","archetype_req":0,"parents":[12,10],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":21,"col":7},"properties":{"shieldCharges":2},"id":40},{"display_name":"Stormy Feet","desc":"Windy Feet will last longer and add more speed.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[9],"blockers":[],"cost":1,"display":{"row":23,"col":1},"properties":{"duration":60},"effects":[{"type":"stat_bonus","bonuses":[{"type":"stat","name":"spdPct","value":20}]}],"id":41},{"display_name":"Refined Gunpowder","desc":"Increase the damage of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[50,0,0,0,0,0]}],"id":42},{"display_name":"More Traps","desc":"Increase the maximum amount of active Traps you can have by +2.","archetype":"Trapper","archetype_req":10,"parents":[54],"dependencies":[10],"blockers":[],"cost":1,"display":{"row":26,"col":8},"properties":{"traps":2},"id":43},{"display_name":"Better Arrow Shield","desc":"Arrow Shield will gain additional area of effect, knockback and damage.","archetype":"Sharpshooter","archetype_req":0,"parents":[19,18,14],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":28,"col":6},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Shield","multipliers":[40,0,0,0,0,0]}],"id":44},{"display_name":"Better Leap","desc":"Reduce leap's cooldown by 1s.","archetype":"Boltslinger","archetype_req":0,"parents":[17,55],"dependencies":[17],"blockers":[],"cost":1,"display":{"row":29,"col":1},"properties":{"cooldown":-1},"id":45},{"display_name":"Better Guardian Angels","desc":"Your Guardian Angels can shoot +4 arrows before disappearing.","archetype":"Boltslinger","archetype_req":0,"parents":[20,55],"dependencies":[8],"blockers":[],"cost":1,"display":{"row":31,"col":2},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":4}}],"id":46},{"display_name":"Cheaper Arrow Storm (2)","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[21,19],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":8},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":47},{"display_name":"Precise Shot","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[46,49,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":2},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdCritPct","value":30}]}],"id":48},{"display_name":"Cheaper Arrow Shield","desc":"Reduce the Mana cost of Arrow Shield.","archetype":"","archetype_req":0,"parents":[48,21],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":49},{"display_name":"Rocket Jump","desc":"Arrow Bomb's self-damage will knockback you farther away.","archetype":"","archetype_req":0,"parents":[47,21],"dependencies":[2],"blockers":[],"cost":1,"display":{"row":33,"col":6},"properties":{},"id":50},{"display_name":"Cheaper Escape (2)","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[22,70],"dependencies":[],"blockers":[],"cost":1,"display":{"row":34,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":51},{"display_name":"Stronger Hook","desc":"Increase your Grappling Hook's range, speed and strength.","archetype":"Trapper","archetype_req":5,"parents":[51],"dependencies":[12],"blockers":[],"cost":1,"display":{"row":35,"col":8},"properties":{"range":8},"id":52},{"display_name":"Cheaper Arrow Bomb (2)","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[63,30],"dependencies":[],"blockers":[],"cost":1,"display":{"row":40,"col":5},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":53},{"display_name":"Bouncing Bomb","desc":"Arrow Bomb will bounce once when hitting a block or enemy","archetype":"","archetype_req":0,"parents":[40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":25,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Arrow Bomb":2}}],"id":54},{"display_name":"Homing Shots","desc":"Your Main Attack arrows will follow nearby enemies and not be affected by gravity","archetype":"","archetype_req":0,"parents":[17,18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2},"properties":{},"effects":[],"id":55},{"display_name":"Shrapnel Bomb","desc":"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area","archetype":"Boltslinger","archetype_req":8,"parents":[23,48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Shrapnel Bomb","cost":0,"multipliers":[40,0,0,0,20,0]}],"id":56},{"display_name":"Elusive","desc":"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)","archetype":"Boltslinger","archetype_req":0,"parents":[24],"dependencies":[],"blockers":[],"cost":2,"display":{"row":38,"col":0},"properties":{},"effects":[],"id":57},{"display_name":"Double Shots","desc":"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)","archetype":"Boltslinger","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[60],"cost":1,"display":{"row":7,"col":2},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":58},{"display_name":"Triple Shots","desc":"Triple Main Attack arrows, but they deal -20% damage per arrow","archetype":"Boltslinger","archetype_req":0,"parents":[69,67],"dependencies":[58],"blockers":[],"cost":1,"display":{"row":17,"col":0},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":59},{"display_name":"Power Shots","desc":"Main Attack arrows have increased speed and knockback","archetype":"Sharpshooter","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[58],"cost":1,"display":{"row":7,"col":6},"properties":{},"effects":[],"id":60},{"display_name":"Focus","desc":"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once","archetype":"Sharpshooter","archetype_req":2,"parents":[68],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[3],"max":3}],"id":61},{"display_name":"More Focus","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[33,12],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":5}],"id":62},{"display_name":"More Focus (2)","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[25,28],"dependencies":[],"blockers":[],"cost":1,"display":{"row":39,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":7}],"id":63},{"display_name":"Traveler","desc":"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)","archetype":"","archetype_req":0,"parents":[42,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"spd"}],"output":{"type":"stat","name":"sdRaw"},"scaling":[1],"max":100}],"id":64},{"display_name":"Patient Hunter","desc":"Your Traps will deal +20% more damage for every second they are active (Max +80%)","archetype":"Trapper","archetype_req":0,"parents":[40],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":8},"properties":{"max":80},"effects":[],"id":65},{"display_name":"Stronger Patient Hunter","desc":"Add +80% Max Damage to Patient Hunter","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[65],"blockers":[],"cost":1,"display":{"row":38,"col":8},"properties":{"max":80},"effects":[],"id":66},{"display_name":"Frenzy","desc":"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second","archetype":"Boltslinger","archetype_req":0,"parents":[59,6],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"spd"},"scaling":[6],"max":200}],"id":67},{"display_name":"Phantom Ray","desc":"Condense Arrow Storm into a single ray that damages enemies 10 times per second","archetype":"Sharpshooter","archetype_req":0,"parents":[37,4],"dependencies":[7],"blockers":[11,6,23],"cost":2,"display":{"row":16,"col":4},"properties":{},"effects":[{"type":"replace_spell","name":"Phantom Ray","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[25,0,5,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Arrow":16}}]}],"id":68},{"display_name":"Arrow Rain","desc":"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies","archetype":"Trapper","archetype_req":0,"parents":[6,38],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":15,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Arrow Rain","cost":0,"multipliers":[120,0,0,0,0,80]}],"id":69},{"display_name":"Decimator","desc":"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)","archetype":"Sharpshooter","archetype_req":0,"parents":[49],"dependencies":[68],"blockers":[],"cost":1,"display":{"row":34,"col":5},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Phantom Ray hits","output":{"type":"stat","name":"PhRayDmg"},"scaling":10,"max":50}],"id":70}],"Warrior":[{"display_name":"Bash","desc":"Violently bash the ground, dealing high damage in a large area","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4,"icon":"node_4"},"properties":{"aoe":4,"range":3},"effects":[{"type":"replace_spell","name":"Bash","cost":45,"display_text":"Total Damage Average","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Hit","type":"damage","multipliers":[130,20,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Hit":1}}]}],"id":0},{"display_name":"Spear Proficiency 1","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":1},{"display_name":"Cheaper Bash","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-10}],"id":2},{"display_name":"Double Bash","desc":"Bash will hit a second time at a farther range","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4,"icon":"node_1"},"properties":{"range":3},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"name":"Single Hit","value":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-50,0,0,0,0,0]}],"id":3},{"display_name":"Charge","desc":"Charge forward at high speed (hold shift to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":6,"col":4,"icon":"node_4"},"properties":{},"effects":[{"type":"replace_spell","name":"Charge","cost":25,"display_text":"Total Damage Average","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":4},{"display_name":"Heavy Impact","desc":"After using Charge, violently crash down into the ground and deal damage","archetype":"","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":1,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Heavy Impact","cost":0,"multipliers":[100,0,0,0,0,0]}],"id":5},{"display_name":"Vehement","desc":"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)","archetype":"Fallen","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[7],"cost":1,"display":{"row":6,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"mdPct"},{"type":"stat","name":"mdRaw"}],"output":{"type":"stat","name":"spd"},"scaling":[1,1],"max":20}],"id":6},{"display_name":"Tougher Skin","desc":"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)","archetype":"Paladin","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[6],"cost":1,"display":{"row":6,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":"5"}]},{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hprRaw"},{"type":"stat","name":"hprPct"}],"output":{"type":"stat","name":"hpBonus"},"scaling":[10,10],"max":100}],"id":7},{"display_name":"Uppercut","desc":"Rocket enemies in the air and deal massive damage","archetype":"","archetype_req":0,"parents":[6],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":2,"icon":"node_4"},"properties":{"aoe":3,"range":5},"effects":[{"type":"replace_spell","name":"Uppercut","cost":45,"display_text":"Total Damage Average","base_spell":3,"spell_type":"damage","scaling":"spell","display":"total","parts":[{"name":"Uppercut","type":"damage","multipliers":[150,50,50,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Uppercut":1}}]}],"id":8},{"display_name":"Cheaper Charge","desc":"Reduce the Mana cost of Charge","archetype":"","archetype_req":0,"parents":[8,10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":9},{"display_name":"War Scream","desc":"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":6,"icon":"node_4"},"properties":{"duration":30,"aoe":12,"defense_bonus":10},"effects":[{"type":"replace_spell","name":"War Scream","cost":35,"display_text":"War Scream","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage Average","parts":[{"name":"War Scream","type":"damage","multipliers":[50,0,0,0,50,0]}]}],"id":10},{"display_name":"Earth Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Fallen","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":11},{"display_name":"Thunder Mastery","desc":"Increases base damage from all Thunder attacks","archetype":"Fallen","archetype_req":0,"parents":[8,14,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":12},{"display_name":"Water Mastery","desc":"Increases base damage from all Water attacks","archetype":"Battle Monk","archetype_req":0,"parents":[9,12,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":11,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":13},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[10,12,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":14},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Paladin","archetype_req":0,"parents":[10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":15},{"display_name":"Quadruple Bash","desc":"Bash will hit 4 times at an even larger range","archetype":"Fallen","archetype_req":0,"parents":[11,17],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":0,"icon":"node_1"},"properties":{"range":6},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Hit":2}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-20,0,0,0,0,0]}],"id":16},{"display_name":"Fireworks","desc":"Mobs hit by Uppercut will explode mid-air and receive additional damage","archetype":"Fallen","archetype_req":0,"parents":[12,16],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fireworks","cost":0,"multipliers":[80,0,20,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fireworks":1}}],"id":17},{"display_name":"Half-Moon Swipe","desc":"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water","archetype":"Battle Monk","archetype_req":1,"parents":[13],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":13,"col":4,"icon":"node_1"},"properties":{"range":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":-10,"multipliers":[-70,0,0,0,0,0]},{"type":"convert_spell_conv","target_part":"all","conversion":"water"}],"id":18},{"display_name":"Flyby Jab","desc":"Damage enemies in your way when using Charge","archetype":"","archetype_req":0,"parents":[14,20],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":6,"icon":"node_1"},"properties":{"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flyby Jab","cost":0,"multipliers":[20,0,0,0,0,40]}],"id":19},{"display_name":"Flaming Uppercut","desc":"Uppercut will light mobs on fire, dealing damage every 0.6 seconds","archetype":"Paladin","archetype_req":0,"parents":[15,19],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":12,"col":8,"icon":"node_1"},"properties":{"duration":3,"tick":0.6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut","cost":0,"multipliers":[0,0,0,0,50,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut Total Damage","cost":0,"hits":{"Flaming Uppercut":5}},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Flaming Uppercut":5}}],"id":20},{"display_name":"Iron Lungs","desc":"War Scream deals more damage","archetype":"","archetype_req":0,"parents":[19,20],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"War Scream","cost":0,"multipliers":[30,0,0,0,0,30]}],"id":21},{"display_name":"Generalist","desc":"After casting 3 different spells in a row, your next spell will cost 5 mana","archetype":"Battle Monk","archetype_req":3,"parents":[23],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":2,"icon":"node_3"},"properties":{},"effects":[],"id":22},{"display_name":"Counter","desc":"When dodging a nearby enemy attack, get 30% chance to instantly attack back","archetype":"Battle Monk","archetype_req":0,"parents":[18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":4,"icon":"node_1"},"properties":{"chance":30},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Counter","cost":0,"multipliers":[60,0,20,0,0,20]}],"id":23},{"display_name":"Mantle of the Bovemists","desc":"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)","archetype":"Paladin","archetype_req":3,"parents":[21],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":15,"col":7,"icon":"node_3"},"properties":{"mantle_charge":3},"effects":[],"id":24},{"display_name":"Bak'al's Grasp","desc":"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)","archetype":"Fallen","archetype_req":2,"parents":[16,17],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":16,"col":1,"icon":"node_3"},"properties":{"cooldown":15},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[4],"slider_step":2,"max":120}],"id":25},{"display_name":"Spear Proficiency 2","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[25,27],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":0,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":26},{"display_name":"Cheaper Uppercut","desc":"Reduce the Mana Cost of Uppercut","archetype":"","archetype_req":0,"parents":[26,28,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":27},{"display_name":"Aerodynamics","desc":"During Charge, you can steer and change direction","archetype":"Battle Monk","archetype_req":0,"parents":[27,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":5,"icon":"node_1"},"properties":{},"effects":[],"id":28},{"display_name":"Provoke","desc":"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream","archetype":"Paladin","archetype_req":0,"parents":[28,24],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":29},{"display_name":"Precise Strikes","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[27,26],"dependencies":[],"blockers":[],"cost":1,"display":{"row":18,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"critDmg","value":30}]}],"id":30},{"display_name":"Air Shout","desc":"War Scream will fire a projectile that can go through walls and deal damage multiple times","archetype":"","archetype_req":0,"parents":[28,29],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":18,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Air Shout","cost":0,"multipliers":[20,0,0,0,0,5]}],"id":31},{"display_name":"Enraged Blow","desc":"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)","archetype":"Fallen","archetype_req":0,"parents":[26],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":20,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"damMult"},"scaling":[3],"max":300}],"id":32},{"display_name":"Flying Kick","desc":"When using Charge, mobs hit will halt your momentum and get knocked back","archetype":"Battle Monk","archetype_req":1,"parents":[27,34],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":3,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flying Kick","cost":0,"multipliers":[120,0,0,10,0,20]}],"id":33},{"display_name":"Stronger Mantle","desc":"Add +2 additional charges to Mantle of the Bovemists","archetype":"Paladin","archetype_req":0,"parents":[35,33],"dependencies":[24],"blockers":[],"cost":1,"display":{"row":20,"col":6,"icon":"node_0"},"properties":{"mantle_charge":2},"effects":[],"id":34},{"display_name":"Manachism","desc":"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)","archetype":"Paladin","archetype_req":3,"parents":[34,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":8,"icon":"node_2"},"properties":{"cooldown":1},"effects":[],"id":35},{"display_name":"Boiling Blood","desc":"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds","archetype":"","archetype_req":0,"parents":[32,37],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":0,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Boiling Blood","cost":0,"multipliers":[25,0,0,0,5,0]}],"id":36},{"display_name":"Ragnarokkr","desc":"War Scream become deafening, increasing its range and giving damage bonus to players","archetype":"Fallen","archetype_req":0,"parents":[36,33],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":2,"icon":"node_2"},"properties":{"damage_bonus":30,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":10}],"id":37},{"display_name":"Ambidextrous","desc":"Increase your chance to attack with Counter by +30%","archetype":"","archetype_req":0,"parents":[33,34,39],"dependencies":[23],"blockers":[],"cost":1,"display":{"row":22,"col":4,"icon":"node_0"},"properties":{"chance":30},"effects":[],"id":38},{"display_name":"Burning Heart","desc":"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)","archetype":"Paladin","archetype_req":0,"parents":[38,40],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"fDamPct"},"scaling":[2],"max":100,"slider_step":100}],"id":39},{"display_name":"Stronger Bash","desc":"Increase the damage of Bash","archetype":"","archetype_req":0,"parents":[39,35],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[30,0,0,0,0,0]}],"id":40},{"display_name":"Intoxicating Blood","desc":"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted","archetype":"Fallen","archetype_req":5,"parents":[37,36],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":23,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":41},{"display_name":"Comet","desc":"After being hit by Fireworks, enemies will crash into the ground and receive more damage","archetype":"Fallen","archetype_req":0,"parents":[37],"dependencies":[17],"blockers":[],"cost":2,"display":{"row":24,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Comet","cost":0,"multipliers":[80,20,0,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Comet":1}}],"id":42},{"display_name":"Collide","desc":"Mobs thrown into walls from Flying Kick will explode and receive additonal damage","archetype":"Battle Monk","archetype_req":4,"parents":[38,39],"dependencies":[33],"blockers":[],"cost":2,"display":{"row":23,"col":5,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Collide","cost":0,"multipliers":[100,0,0,0,50,0]}],"id":43},{"display_name":"Rejuvenating Skin","desc":"Regain back 30% of the damage you take as healing over 30s","archetype":"Paladin","archetype_req":0,"parents":[39,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":23,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":44},{"display_name":"Uncontainable Corruption","desc":"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1","archetype":"","archetype_req":0,"parents":[36,46],"dependencies":[25],"blockers":[],"cost":1,"display":{"row":26,"col":0,"icon":"node_0"},"properties":{"cooldown":-5},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[1],"slider_step":2,"max":50}],"id":45},{"display_name":"Radiant Devotee","desc":"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)","archetype":"Battle Monk","archetype_req":1,"parents":[47,45],"dependencies":[],"blockers":[],"cost":1,"display":{"row":26,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","inputs":[{"type":"stat","name":"ref"}],"output":{"type":"stat","name":"mr"},"scaling":[1],"max":10,"slider_step":4}],"id":46},{"display_name":"Whirlwind Strike","desc":"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)","archetype":"Battle Monk","archetype_req":5,"parents":[38,46],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":26,"col":4,"icon":"node_1"},"properties":{"range":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":0,"multipliers":[0,0,0,0,0,50]}],"id":47},{"display_name":"Mythril Skin","desc":"Gain +5% Base Resistance and become immune to knockback","archetype":"Paladin","archetype_req":6,"parents":[44],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":5}]}],"id":48},{"display_name":"Armour Breaker","desc":"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage","archetype":"Fallen","archetype_req":0,"parents":[45,46],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":27,"col":1,"icon":"node_2"},"properties":{"duration":5},"effects":[],"id":49},{"display_name":"Shield Strike","desc":"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost","archetype":"Paladin","archetype_req":0,"parents":[48,51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Shield Strike","cost":0,"multipliers":[60,0,20,0,0,0]}],"id":50},{"display_name":"Sparkling Hope","desc":"Everytime you heal 5% of your max health, deal damage to all nearby enemies","archetype":"Paladin","archetype_req":0,"parents":[48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":8,"icon":"node_2"},"properties":{"aoe":6},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Sparkling Hope","cost":0,"multipliers":[10,0,5,0,0,0]}],"id":51},{"display_name":"Massive Bash","desc":"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)","archetype":"Fallen","archetype_req":8,"parents":[53,45],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"bashAoE"},"scaling":[1],"max":10,"slider_step":3}],"id":52},{"display_name":"Tempest","desc":"War Scream will ripple the ground and deal damage 3 times in a large area","archetype":"Battle Monk","archetype_req":0,"parents":[52,54],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2,"icon":"node_1"},"properties":{"aoe":16},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest","cost":"0","multipliers":[30,10,0,0,0,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest Total Damage","cost":"0","hits":{"Tempest":3}},{"type":"add_spell_prop","base_spell":4,"target_part":"Total Damage","cost":"0","hits":{"Tempest":3}}],"id":53},{"display_name":"Spirit of the Rabbit","desc":"Reduce the Mana cost of Charge and increase your Walk Speed by +20%","archetype":"Battle Monk","archetype_req":5,"parents":[53,47],"dependencies":[],"blockers":[],"cost":1,"display":{"row":28,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5},{"type":"raw_stat","bonuses":[{"type":"stat","name":"spd","value":20}]}],"id":54},{"display_name":"Massacre","desc":"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar","archetype":"Fallen","archetype_req":5,"parents":[53,52],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":55},{"display_name":"Axe Kick","desc":"Increase the damage of Uppercut, but also increase its mana cost","archetype":"","archetype_req":0,"parents":[53,54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":10,"multipliers":[100,0,0,0,0,0]}],"id":56},{"display_name":"Radiance","desc":"Bash will buff your allies' positive IDs. (15s Cooldown)","archetype":"Paladin","archetype_req":2,"parents":[54,58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":5,"icon":"node_2"},"properties":{"cooldown":15},"effects":[],"id":57},{"display_name":"Cheaper Bash 2","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[57,50,51],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":58},{"display_name":"Cheaper War Scream","desc":"Reduce the Mana cost of War Scream","archetype":"","archetype_req":0,"parents":[52],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":59},{"display_name":"Discombobulate","desc":"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second","archetype":"Battle Monk","archetype_req":11,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":31,"col":2,"icon":"node_3"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"rainrawButDifferent"},"scaling":[2],"max":50}],"id":60},{"display_name":"Thunderclap","desc":"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder","archetype":"Battle Monk","archetype_req":8,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":5,"icon":"node_1"},"properties":{},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"},{"type":"raw_stat","bonuses":[{"type":"prop","abil_name":"Bash","name":"aoe","value":3}]}],"id":61},{"display_name":"Cyclone","desc":"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s","archetype":"Battle Monk","archetype_req":0,"parents":[54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":4,"icon":"node_1"},"properties":{"aoe":4,"duration":20},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone","cost":0,"multipliers":[10,0,0,0,5,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone Total Damage","cost":0,"hits":{"Cyclone":40}}],"id":62},{"display_name":"Second Chance","desc":"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)","archetype":"Paladin","archetype_req":12,"parents":[58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":63},{"display_name":"Blood Pact","desc":"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)","archetype":"","archetype_req":10,"parents":[59],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1,"icon":"node_3"},"properties":{},"effects":[],"id":64},{"display_name":"Haemorrhage","desc":"Reduce Blood Pact's health cost. (0.5% health per mana)","archetype":"Fallen","archetype_req":0,"parents":[64],"dependencies":[64],"blockers":[],"cost":1,"display":{"row":35,"col":2,"icon":"node_1"},"properties":{},"effects":[],"id":65},{"display_name":"Brink of Madness","desc":"If your health is 25% full or less, gain +40% Resistance","archetype":"","archetype_req":0,"parents":[64,67],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":4,"icon":"node_2"},"properties":{},"effects":[],"id":66},{"display_name":"Cheaper Uppercut 2","desc":"Reduce the Mana cost of Uppercut","archetype":"","archetype_req":0,"parents":[63,66],"dependencies":[],"blockers":[],"cost":1,"display":{"row":35,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":67},{"display_name":"Martyr","desc":"When you receive a fatal blow, all nearby allies become invincible","archetype":"Paladin","archetype_req":0,"parents":[63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":8,"icon":"node_1"},"properties":{"duration":3,"aoe":12},"effects":[],"id":68}]} \ No newline at end of file diff --git a/js/atree_ids.json b/js/atree_ids.json new file mode 100644 index 0000000..a7cd98e --- /dev/null +++ b/js/atree_ids.json @@ -0,0 +1,146 @@ +{ + "Archer": { + "Arrow Shield": 0, + "Escape": 1, + "Arrow Bomb": 2, + "Heart Shatter": 3, + "Fire Creep": 4, + "Bryophyte Roots": 5, + "Nimble String": 6, + "Arrow Storm": 7, + "Guardian Angels": 8, + "Windy Feet": 9, + "Basaltic Trap": 10, + "Windstorm": 11, + "Grappling Hook": 12, + "Implosion": 13, + "Twain's Arc": 14, + "Fierce Stomp": 15, + "Scorched Earth": 16, + "Leap": 17, + "Shocking Bomb": 18, + "Mana Trap": 19, + "Escape Artist": 20, + "Initiator": 21, + "Call of the Hound": 22, + "Arrow Hurricane": 23, + "Geyser Stomp": 24, + "Crepuscular Ray": 25, + "Grape Bomb": 26, + "Tangled Traps": 27, + "Snow Storm": 28, + "All-Seeing Panoptes": 29, + "Minefield": 30, + "Bow Proficiency I": 31, + "Cheaper Arrow Bomb": 32, + "Cheaper Arrow Storm": 33, + "Cheaper Escape": 34, + "Earth Mastery": 35, + "Thunder Mastery": 36, + "Water Mastery": 37, + "Air Mastery": 38, + "Fire Mastery": 39, + "More Shields": 40, + "Stormy Feet": 41, + "Refined Gunpowder": 42, + "More Traps": 43, + "Better Arrow Shield": 44, + "Better Leap": 45, + "Better Guardian Angels": 46, + "Cheaper Arrow Storm (2)": 47, + "Precise Shot": 48, + "Cheaper Arrow Shield": 49, + "Rocket Jump": 50, + "Cheaper Escape (2)": 51, + "Stronger Hook": 52, + "Cheaper Arrow Bomb (2)": 53, + "Bouncing Bomb": 54, + "Homing Shots": 55, + "Shrapnel Bomb": 56, + "Elusive": 57, + "Double Shots": 58, + "Triple Shots": 59, + "Power Shots": 60, + "Focus": 61, + "More Focus": 62, + "More Focus (2)": 63, + "Traveler": 64, + "Patient Hunter": 65, + "Stronger Patient Hunter": 66, + "Frenzy": 67, + "Phantom Ray": 68, + "Arrow Rain": 69, + "Decimator": 70 + }, + "Warrior": { + "Bash": 0, + "Spear Proficiency 1": 1, + "Cheaper Bash": 2, + "Double Bash": 3, + "Charge": 4, + "Heavy Impact": 5, + "Vehement": 6, + "Tougher Skin": 7, + "Uppercut": 8, + "Cheaper Charge": 9, + "War Scream": 10, + "Earth Mastery": 11, + "Thunder Mastery": 12, + "Water Mastery": 13, + "Air Mastery": 14, + "Fire Mastery": 15, + "Quadruple Bash": 16, + "Fireworks": 17, + "Half-Moon Swipe": 18, + "Flyby Jab": 19, + "Flaming Uppercut": 20, + "Iron Lungs": 21, + "Generalist": 22, + "Counter": 23, + "Mantle of the Bovemists": 24, + "Bak'al's Grasp": 25, + "Spear Proficiency 2": 26, + "Cheaper Uppercut": 27, + "Aerodynamics": 28, + "Provoke": 29, + "Precise Strikes": 30, + "Air Shout": 31, + "Enraged Blow": 32, + "Flying Kick": 33, + "Stronger Mantle": 34, + "Manachism": 35, + "Boiling Blood": 36, + "Ragnarokkr": 37, + "Ambidextrous": 38, + "Burning Heart": 39, + "Stronger Bash": 40, + "Intoxicating Blood": 41, + "Comet": 42, + "Collide": 43, + "Rejuvenating Skin": 44, + "Uncontainable Corruption": 45, + "Radiant Devotee": 46, + "Whirlwind Strike": 47, + "Mythril Skin": 48, + "Armour Breaker": 49, + "Shield Strike": 50, + "Sparkling Hope": 51, + "Massive Bash": 52, + "Tempest": 53, + "Spirit of the Rabbit": 54, + "Massacre": 55, + "Axe Kick": 56, + "Radiance": 57, + "Cheaper Bash 2": 58, + "Cheaper War Scream": 59, + "Discombobulate": 60, + "Thunderclap": 61, + "Cyclone": 62, + "Second Chance": 63, + "Blood Pact": 64, + "Haemorrhage": 65, + "Brink of Madness": 66, + "Cheaper Uppercut 2": 67, + "Martyr": 68 + } +} \ No newline at end of file diff --git a/py_script/atree-convertID.py b/py_script/atree-convertID.py new file mode 100644 index 0000000..74c40dd --- /dev/null +++ b/py_script/atree-convertID.py @@ -0,0 +1,29 @@ +""" +Generate a JSON Ability Tree [atree_constants_idfied.json] with: + - All references replaced by numerical IDs +given a JSON Ability Tree with reference as string AND a JSON Ability Names to IDs. +""" +import json + +# Ability names to IDs data +with open("atree_ids.json") as f: + id_data = json.loads(f.read()) + +# Ability tree data with reference as string +with open("atree_constants.json") as f: + atree_data = json.loads(f.read()) + +for _class, info in atree_data.items(): + for abil in range(len(info)): + info[abil]["id"] = id_data[_class][info[abil]["display_name"]] + for ref in range(len(info[abil]["parents"])): + info[abil]["parents"][ref] = id_data[_class][info[abil]["parents"][ref]] + + for ref in range(len(info[abil]["dependencies"])): + info[abil]["dependencies"][ref] = id_data[_class][info[abil]["dependencies"][ref]] + + for ref in range(len(info[abil]["blockers"])): + info[abil]["blockers"][ref] = id_data[_class][info[abil]["blockers"][ref]] + +with open('atree_constants_idfied.json', 'w', encoding='utf-8') as abil_dest: + json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4) \ No newline at end of file diff --git a/py_script/atree-generateID.py b/py_script/atree-generateID.py index 4657cf1..d8d6419 100644 --- a/py_script/atree-generateID.py +++ b/py_script/atree-generateID.py @@ -1,37 +1,35 @@ """ -Generate a JSON Ability Tree with: +Generate a JSON Ability Tree [atree_constants_id.json] with: - All references replaced by numerical IDs - - Extra JSON File with Original name as key and Assigned IDs as value. -given a JSON Ability Tree. + - Extra JSON File with Class: [Original name as key and Assigned IDs as value]. +given a JSON Ability Tree with reference as string. """ import json -id = 0 abilDict = {} -with open("atree-parse.json") as f: +with open("atree_constants.json") as f: data = json.loads(f.read()) for classType, info in data.items(): - #reset IDs for every class and start at 1 - id = 1 + _id = 0 + abilDict[classType] = {} for abil in info: - abilDict[abil["display_name"]] = id - id += 1 + abilDict[classType][abil["display_name"]] = _id + _id += 1 - with open("atree-ids.json", "w", encoding='utf-8') as id_dest: + with open("atree_ids.json", "w", encoding='utf-8') as id_dest: json.dump(abilDict, id_dest, ensure_ascii=False, indent=4) for classType, info in data.items(): for abil in range(len(info)): - info[abil]["id"] = abilDict[info[abil]["display_name"]] + info[abil]["id"] = abilDict[classType][info[abil]["display_name"]] for ref in range(len(info[abil]["parents"])): - info[abil]["parents"][ref] = abilDict[info[abil]["parents"][ref]] + info[abil]["parents"][ref] = abilDict[classType][info[abil]["parents"][ref]] for ref in range(len(info[abil]["dependencies"])): - info[abil]["dependencies"][ref] = abilDict[info[abil]["dependencies"][ref]] + info[abil]["dependencies"][ref] = abilDict[classType][info[abil]["dependencies"][ref]] for ref in range(len(info[abil]["blockers"])): - info[abil]["blockers"][ref] = abilDict[info[abil]["blockers"][ref]] - data[classType] = info + info[abil]["blockers"][ref] = abilDict[classType][info[abil]["blockers"][ref]] - with open('atree-constants-id.json', 'w', encoding='utf-8') as abil_dest: - json.dump(data, abil_dest, ensure_ascii=False, indent=4) \ No newline at end of file + with open('atree_constants_id.json', 'w', encoding='utf-8') as abil_dest: + json.dump(data, abil_dest, ensure_ascii=False, indent=4) From ebcdbc14fc19c4a70419bf75de7c3fb54219d1b9 Mon Sep 17 00:00:00 2001 From: reschan Date: Mon, 27 Jun 2022 16:53:18 +0700 Subject: [PATCH 50/68] remove redundant atree data files --- js/atree_constants.js | 4063 +++++++++++----------------- js/atree_constants_old.js | 171 -- js/atree_constants_str_old.js | 4160 ----------------------------- js/atree_constants_str_old_min.js | 1 - 4 files changed, 1592 insertions(+), 6803 deletions(-) delete mode 100644 js/atree_constants_old.js delete mode 100644 js/atree_constants_str_old.js delete mode 100644 js/atree_constants_str_old_min.js diff --git a/js/atree_constants.js b/js/atree_constants.js index 48fd997..cbd42b1 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -5,10 +5,7 @@ const atrees = { "desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)", "archetype": "", "archetype_req": 0, - "parents": [ - 60, - 34 - ], + "parents": ["Power Shots", "Cheaper Escape"], "dependencies": [], "blockers": [], "cost": 1, @@ -33,14 +30,7 @@ const atrees = { { "name": "Shield Damage", "type": "damage", - "multipliers": [ - 90, - 0, - 0, - 0, - 0, - 10 - ] + "multipliers": [90, 0, 0, 0, 0, 10] }, { "name": "Total Damage", @@ -51,1258 +41,955 @@ const atrees = { } ] } - ], - "id": 0 + ] }, + { "display_name": "Escape", "desc": "Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": [ - 3 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Heart Shatter"], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 7, - "col": 4 + "row": 7, + "col": 4 }, "properties": { - "aoe": 0, - "range": 0 + "aoe": 0, + "range": 0 }, "effects": [ + { + "type": "replace_spell", + "name": "Escape", + "cost": 25, + "display_text": "Max Damage", + "base_spell": 2, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "None", + "type": "damage", + "multipliers": [0, 0, 0, 0, 0, 0] + }, { - "type": "replace_spell", - "name": "Escape", - "cost": 25, - "display_text": "Max Damage", - "base_spell": 2, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "None", - "type": "damage", - "multipliers": [ - 0, - 0, - 0, - 0, - 0, - 0 - ] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "None": 0 - } - } - ] + "name": "Total Damage", + "type": "total", + "hits": { + "None": 0 + } } - ], - "id": 1 + ] + } + ] }, { "display_name": "Arrow Bomb", "desc": "Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)", - "archetype": "", - "archetype_req": 0, - "parents": [], + "archetype": "", + "archetype_req": 0, + "parents": [], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 0, - "col": 4 + "row": 0, + "col": 4 }, "properties": { - "aoe": 4.5, - "range": 26 + "aoe": 4.5, + "range": 26 }, "effects": [ - { - "type": "replace_spell", + { + "type": "replace_spell", + "name": "Arrow Bomb", + "cost": 50, + "display_text": "Average Damage", + "base_spell": 3, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { "name": "Arrow Bomb", - "cost": 50, - "display_text": "Average Damage", - "base_spell": 3, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Arrow Bomb", - "type": "damage", - "multipliers": [ - 160, - 0, - 0, - 0, - 20, - 0 - ] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Arrow Bomb": 1 - } - } - ] + "type": "damage", + "multipliers": [160, 0, 0, 0, 20, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Arrow Bomb": 1 + } } - ], - "id": 2 + ] + } + ] }, { "display_name": "Heart Shatter", "desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 31 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Bow Proficiency I"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 4, - "col": 4 + "row": 4, + "col": 4 }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [ - 100, - 0, - 0, - 0, - 0, - 0 - ] - }, - {} - ], - "id": 3 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [100, 0, 0, 0, 0, 0] + }, + { + + } + ] }, { "display_name": "Fire Creep", "desc": "Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 68, - 39, - 5 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Phantom Ray", "Fire Mastery", "Bryophyte Roots"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 16, - "col": 6 + "row": 16, + "col": 6 }, - "properties": { - "aoe": 0.8, - "duration": 6 + "properties": { + "aoe": 0.8, + "duration": 6 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [ - 30, - 0, - 0, - 0, - 20, - 0 - ] - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fire Creep": 15 - } + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [30, 0, 0, 0, 20, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fire Creep": 15 } - ], - "id": 4 + } + ] }, { "display_name": "Bryophyte Roots", "desc": "When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.", - "archetype": "Trapper", - "archetype_req": 1, - "parents": [ - 4, - 35 - ], - "dependencies": [ - 7 - ], + "archetype": "Trapper", + "archetype_req": 1, + "parents": ["Fire Creep", "Earth Mastery"], + "dependencies": ["Arrow Storm"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 16, - "col": 8 + "row": 16, + "col": 8 }, "properties": { - "aoe": 2, - "duration": 5, - "slowness": 0.4 - }, + "aoe": 2, + "duration": 5, + "slowness": 0.4 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Bryophyte Roots", - "cost": 0, - "multipliers": [ - 40, - 20, - 0, - 0, - 0, - 0 - ] - } - ], - "id": 5 + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Bryophyte Roots", + "cost": 0, + "multipliers": [40, 20, 0, 0, 0, 0] + } + ] }, { "display_name": "Nimble String", "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 36, - 69 - ], - "dependencies": [ - 7 - ], - "blockers": [ - 68 - ], - "cost": 2, + "archetype": "", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Arrow Rain"], + "dependencies": ["Arrow Storm"], + "blockers": ["Phantom Ray"], + "cost": 2, "display": { - "row": 15, - "col": 2 + "row": 15, + "col": 2 }, "properties": { - "shootspeed": 2 - }, + "shootspeed": 2 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [ - -15, - 0, - 0, - 0, - 0, - 0 - ] - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Stream", - "cost": 0, - "hits": { - "Single Arrow": 8 - } + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [-15, 0, 0, 0, 0, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Stream", + "cost": 0, + "hits": { + "Single Arrow": 8 } - ], - "id": 6 + } + ] }, { "display_name": "Arrow Storm", "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 58, - 34 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Double Shots", "Cheaper Escape"], "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 9, - "col": 2 + "row": 9, + "col": 2 }, "properties": { - "aoe": 0, - "range": 16 + "aoe": 0, + "range": 16 }, "effects": [ - { - "type": "replace_spell", - "name": "Arrow Storm", - "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [ - 30, - 0, - 10, - 0, - 0, - 0 - ] - }, - { - "name": "Single Stream", - "type": "total", - "hits": { - "Single Arrow": 8 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Stream": 2 - } - } - ] + { + "type": "replace_spell", + "name": "Arrow Storm", + "cost": 40, + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [30, 0, 10, 0, 0, 0] + }, + { + "name": "Single Stream", + "type": "total", + "hits": { + "Single Arrow": 8 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Stream": 2 + } } - ], - "id": 7 + ] + } + ] }, { "display_name": "Guardian Angels", "desc": "Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)", "archetype": "Boltslinger", - "archetype_req": 3, - "parents": [ - 59, - 67 - ], - "dependencies": [ - 0 - ], + "archetype_req": 3, + "parents": ["Triple Shots", "Frenzy"], + "dependencies": ["Arrow Shield"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 19, - "col": 1 + "row": 19, + "col": 1 }, "properties": { - "range": 4, - "duration": 60, - "shots": 8, - "count": 2 - }, + "range": 4, + "duration": 60, + "shots": 8, + "count": 2 + }, "effects": [ - { - "type": "replace_spell", - "name": "Guardian Angels", - "cost": 30, - "display_text": "Total Damage Average", - "base_spell": 4, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [ - 30, - 0, - 0, - 0, - 0, - 10 - ] - }, - { - "name": "Single Bow", - "type": "total", - "hits": { - "Single Arrow": 8 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Bow": 2 - } + { + "type": "replace_spell", + "name": "Guardian Angels", + "cost": 30, + "display_text": "Total Damage Average", + "base_spell": 4, + "spell_type": "damage", + "scaling": "spell", + "display": "Total Damage", + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [30, 0, 0, 0, 0, 10] + }, + { + "name": "Single Bow", + "type": "total", + "hits": { + "Single Arrow": 8 } - ] - } - ], - "id": 8 + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Bow": 2 + } + } + ] + } + ] }, { "display_name": "Windy Feet", "base_abil": "Escape", "desc": "When casting Escape, give speed to yourself and nearby allies.", "archetype": "", - "archetype_req": 0, - "parents": [ - 7 - ], - "dependencies": [], + "archetype_req": 0, + "parents": ["Arrow Storm"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 10, - "col": 1 + "row": 10, + "col": 1 }, "properties": { - "aoe": 8, - "duration": 120 - }, + "aoe": 8, + "duration": 120 + }, "type": "stat_bonus", "bonuses": [ - { - "type": "stat", - "name": "spd", - "value": 20 + { + "type": "stat", + "name": "spd", + "value": 20 } - ], - "id": 9 + ] }, { "display_name": "Basaltic Trap", "desc": "When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)", "archetype": "Trapper", - "archetype_req": 2, - "parents": [ - 5 - ], - "dependencies": [], + "archetype_req": 2, + "parents": ["Bryophyte Roots"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 19, - "col": 8 + "row": 19, + "col": 8 }, "properties": { - "aoe": 7, - "traps": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [ - 140, - 30, - 0, - 0, - 30, - 0 - ] - } - ], - "id": 10 + "aoe": 7, + "traps": 2 }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [140, 30, 0, 0, 30, 0] + } + ] + }, { "display_name": "Windstorm", "desc": "Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 8, - 33 - ], - "dependencies": [], - "blockers": [ - 68 - ], - "cost": 2, + "archetype": "", + "archetype_req": 0, + "parents": ["Guardian Angels", "Cheaper Arrow Storm"], + "dependencies": [], + "blockers": ["Phantom Ray"], + "cost": 2, "display": { "row": 21, "col": 1 - }, + }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [ - -11, - 0, - -7, - 0, - 0, - 3 - ] - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 1 - } + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [-11, 0, -7, 0, 0, 3] + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 1 } - ], - "id": 11 - }, + } + ] + }, { "display_name": "Grappling Hook", "base_abil": "Escape", "desc": "When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)", - "archetype": "Trapper", - "archetype_req": 0, - "parents": [ - 61, - 40, - 33 - ], - "dependencies": [], - "blockers": [ - 20 - ], - "cost": 2, + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Focus", "More Shields", "Cheaper Arrow Storm"], + "dependencies": [], + "blockers": ["Escape Artist"], + "cost": 2, "display": { "row": 21, "col": 5 - }, + }, "properties": { "range": 20 }, - "effects": [], - "id": 12 - }, + "effects": [ + ] + }, { "display_name": "Implosion", "desc": "Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": [ - 12, - 40 - ], - "dependencies": [], + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Grappling Hook", "More Shields"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 6 - }, + }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [ - 40, - 0, - 0, - 0, - 0, - 0 - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [40, 0, 0, 0, 0, 0] } - ], - "id": 13 - }, + ] + }, { "display_name": "Twain's Arc", "desc": "When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)", - "archetype": "Sharpshooter", - "archetype_req": 4, - "parents": [ - 62, - 64 - ], - "dependencies": [ - 61 - ], + "archetype": "Sharpshooter", + "archetype_req": 4, + "parents": ["More Focus", "Traveler"], + "dependencies": ["Focus"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 25, "col": 4 - }, + }, "properties": { - "range": 64, - "focusReq": 2 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Twain's Arc", - "cost": 0, - "display_text": "Twain's Arc", - "base_spell": 5, - "spell_type": "damage", - "scaling": "melee", - "display": "Twain's Arc Damage", - "parts": [ - { - "name": "Twain's Arc Damage", - "type": "damage", - "multipliers": [ - 200, - 0, - 0, - 0, - 0, - 0 - ] - } - ] - } - ], - "id": 14 + "range": 64, + "focusReq": 2 }, + "effects": [ + + { + "type": "replace_spell", + "name": "Twain's Arc", + "cost": 0, + "display_text": "Twain's Arc", + "base_spell": 5, + "spell_type": "damage", + "scaling": "melee", + "display": "Twain's Arc Damage", + "parts": [ + { + "name": "Twain's Arc Damage", + "type": "damage", + "multipliers": [200, 0, 0, 0, 0, 0] + } + ] + } + ] + }, { "display_name": "Fierce Stomp", "desc": "When using Escape, hold shift to quickly drop down and deal damage.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": [ - 42, - 64 - ], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Refined Gunpowder", "Traveler"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 26, - "col": 1 + "row": 26, + "col": 1 }, "properties": { - "aoe": 4 + "aoe": 4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [ - 100, - 0, - 0, - 0, - 0, - 0 - ] - }, - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fierce Stomp": 1 - } + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [100, 0, 0, 0, 0, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Fierce Stomp": 1 } - ], - "id": 15 + } + ] }, { "display_name": "Scorched Earth", "desc": "Fire Creep become much stronger.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": [ - 14 - ], - "dependencies": [ - 4 - ], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Twain's Arc"], + "dependencies": ["Fire Creep"], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 26, - "col": 5 + "row": 26 , + "col": 5 }, "properties": { - "duration": 2, - "aoe": 0.4 + "duration": 2, + "aoe": 0.4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [ - 10, - 0, - 0, - 0, - 5, - 0 - ] - } - ], - "id": 16 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Fire Creep", + "cost": 0, + "multipliers": [10, 0, 0, 0, 5, 0] + } + ] }, { "display_name": "Leap", "desc": "When you double tap jump, leap foward. (2s Cooldown)", - "archetype": "Boltslinger", - "archetype_req": 5, - "parents": [ - 42, - 55 - ], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 5, + "parents": ["Refined Gunpowder", "Homing Shots"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 0 + "row": 28, + "col": 0 }, "properties": { - "cooldown": 2 - }, - "effects": [], - "id": 17 + "cooldown": 2 }, + "effects": [ + + ] + }, { "display_name": "Shocking Bomb", "desc": "Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.", - "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": [ - 14, - 44, - 55 - ], - "dependencies": [ - 2 - ], + "archetype": "Sharpshooter", + "archetype_req": 5, + "parents": ["Twain's Arc", "Better Arrow Shield", "Homing Shots"], + "dependencies": ["Arrow Bomb"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 4 + "row": 28, + "col": 4 }, "properties": { - "gravity": 0 + "gravity": 0 }, "effects": [ - { - "type": "convert_spell_conv", - "target_part": "all", - "conversion": "thunder" - } - ], - "id": 18 + { + "type": "convert_spell_conv", + "target_part": "all", + "conversion": "thunder" + } + ] }, { "display_name": "Mana Trap", "desc": "Your Traps will give you 4 Mana per second when you stay close to them.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": [ - 43, - 44 - ], - "dependencies": [ - 4 - ], + "archetype": "Trapper", + "archetype_req": 5, + "parents": ["More Traps", "Better Arrow Shield"], + "dependencies": ["Fire Creep"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 28, - "col": 8 + "row": 28, + "col": 8 }, "properties": { - "range": 12, - "manaRegen": 4 + "range": 12, + "manaRegen": 4 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 10, - "multipliers": [ - 0, - 0, - 0, - 0, - 0, - 0 - ] - } - ], - "id": 19 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 10, + "multipliers": [0, 0, 0, 0, 0, 0] + } + ] }, { "display_name": "Escape Artist", "desc": "When casting Escape, release 100 arrows towards the ground.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": [ - 46, - 17 - ], - "dependencies": [], - "blockers": [ - 12 - ], - "cost": 2, + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Better Guardian Angels", "Leap"], + "dependencies": [], + "blockers": ["Grappling Hook"], + "cost": 2, "display": { - "row": 31, - "col": 0 + "row": 31, + "col": 0 + }, + "properties": { }, - "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Escape Artist", - "cost": 0, - "multipliers": [ - 30, - 0, - 10, - 0, - 0, - 0 - ] - } - ], - "id": 20 + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Escape Artist", + "cost": 0, + "multipliers": [30, 0, 10, 0, 0, 0] + } + ] }, { "display_name": "Initiator", "desc": "If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.", "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": [ - 18, - 44, - 47 - ], - "dependencies": [ - 61 - ], + "archetype_req": 5, + "parents": ["Shocking Bomb", "Better Arrow Shield", "Cheaper Arrow Storm (2)"], + "dependencies": ["Focus"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 31, - "col": 5 + "row": 31, + "col": 5 }, "properties": { - "focus": 1, - "timer": 5 - }, - "type": "stat_bonus", + "focus": 1, + "timer": 5 + }, + "type": "stat_bonus", "bonuses": [ - { - "type": "stat", - "name": "damPct", - "value": 50 + { + "type": "stat", + "name": "damPct", + "value": 50 } - ], - "id": 21 + ] }, { "display_name": "Call of the Hound", "desc": "Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.", "archetype": "Trapper", - "archetype_req": 0, - "parents": [ - 21, - 47 - ], - "dependencies": [ - 0 - ], + "archetype_req": 0, + "parents": ["Initiator", "Cheaper Arrow Storm (2)"], + "dependencies": ["Arrow Shield"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 32, - "col": 7 + "row": 32, + "col": 7 }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Call of the Hound", - "cost": 0, - "multipliers": [ - 40, - 0, - 0, - 0, - 0, - 0 - ] - } - ], - "id": 22 + "properties": { + }, + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Call of the Hound", + "cost": 0, + "multipliers": [40, 0, 0, 0, 0, 0] + } + ] }, { "display_name": "Arrow Hurricane", "desc": "Arrow Storm will shoot +2 stream of arrows.", - "archetype": "Boltslinger", - "archetype_req": 8, - "parents": [ - 48, - 20 - ], - "dependencies": [], - "blockers": [ - 68 - ], - "cost": 2, + "archetype": "Boltslinger", + "archetype_req": 8, + "parents": ["Precise Shot", "Escape Artist"], + "dependencies": [], + "blockers": ["Phantom Ray"], + "cost": 2, "display": { - "row": 33, - "col": 0 + "row": 33, + "col": 0 }, "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 2 - } + "effects": [ + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Total Damage", + "cost": 0, + "hits": { + "Single Stream": 2 } - ], - "id": 23 + } + ] }, { "display_name": "Geyser Stomp", "desc": "Fierce Stomp will create geysers, dealing more damage and vertical knockback.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 56 - ], - "dependencies": [ - 15 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Shrapnel Bomb"], + "dependencies": ["Fierce Stomp"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 1 + "row": 37, + "col": 1 }, "properties": { - "aoe": 1 + "aoe": 1 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [ - 0, - 0, - 0, - 50, - 0, - 0 - ] - } - ], - "id": 24 + { + "type": "add_spell_prop", + "base_spell": 2, + "target_part": "Fierce Stomp", + "cost": 0, + "multipliers": [0, 0, 0, 50, 0, 0] + } + ] }, { "display_name": "Crepuscular Ray", "desc": "If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.", - "archetype": "Sharpshooter", - "archetype_req": 10, - "parents": [ - 49 - ], - "dependencies": [ - 7 - ], + "archetype": "Sharpshooter", + "archetype_req": 10, + "parents": ["Cheaper Arrow Shield"], + "dependencies": ["Arrow Storm"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 4 + "row": 37, + "col": 4 }, "properties": { - "focusReq": 5, - "focusRegen": -1 - }, + "focusReq": 5, + "focusRegen": -1 + }, "effects": [ + { + "type": "replace_spell", + "name": "Crepuscular Ray", + "base_spell": 5, + "spell_type": "damage", + "scaling": "spell", + "display": "One Focus", + "cost": 0, + + "parts": [ + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [10, 0, 0, 5, 0, 0] + }, { - "type": "replace_spell", - "name": "Crepuscular Ray", - "base_spell": 5, - "spell_type": "damage", - "scaling": "spell", - "display": "One Focus", - "cost": 0, - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [ - 10, - 0, - 0, - 5, - 0, - 0 - ] - }, - { - "name": "One Focus", - "type": "total", - "hits": { - "Single Arrow": 20 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "One Focus": 7 - } - } - ] + "name": "One Focus", + "type": "total", + "hits": { + "Single Arrow": 20 + } + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "One Focus": 7 + } } - ], - "id": 25 + ] + } + ] }, { "display_name": "Grape Bomb", "desc": "Arrow bomb will throw 3 additional smaller bombs when exploding.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 51 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Escape (2)"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 37, - "col": 7 + "row": 37, + "col": 7 }, "properties": { - "miniBombs": 3, - "aoe": 2 + "miniBombs": 3, + "aoe": 2 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Grape Bomb", - "cost": 0, - "multipliers": [ - 30, - 0, - 0, - 0, - 10, - 0 - ] - } - ], - "id": 26 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Grape Bomb", + "cost": 0, + "multipliers": [30, 0, 0, 0, 10, 0] + } + ] }, { "display_name": "Tangled Traps", "desc": "Your Traps will be connected by a rope that deals damage to enemies every 0.2s.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": [ - 26 - ], - "dependencies": [ - 10 - ], + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Grape Bomb"], + "dependencies": ["Basaltic Trap"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 38, - "col": 6 + "row": 38, + "col": 6 }, "properties": { - "attackSpeed": 0.2 + "attackSpeed": 0.2 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Tangled Traps", - "cost": 0, - "multipliers": [ - 20, - 0, - 0, - 0, - 0, - 20 - ] - } - ], - "id": 27 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Tangled Traps", + "cost": 0, + "multipliers": [20, 0, 0, 0, 0, 20] + } + ] }, { "display_name": "Snow Storm", "desc": "Enemies near you will be slowed down.", "archetype": "", - "archetype_req": 0, - "parents": [ - 24, - 63 - ], - "dependencies": [], + "archetype_req": 0, + "parents": ["Geyser Stomp", "More Focus (2)"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 39, - "col": 2 + "row": 39, + "col": 2 }, "properties": { - "range": 2.5, - "slowness": 0.3 - }, - "id": 28 + "range": 2.5, + "slowness": 0.3 + } }, { "display_name": "All-Seeing Panoptes", "desc": "Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.", "archetype": "Boltslinger", - "archetype_req": 11, - "parents": [ - 28 - ], - "dependencies": [ - 8 - ], + "archetype_req": 11, + "parents": ["Snow Storm"], + "dependencies": ["Guardian Angels"], "blockers": [], - "cost": 2, + "cost": 2, "display": { - "row": 40, - "col": 1 + "row": 40, + "col": 1 }, "properties": { - "range": 10, - "shots": 5 - }, + "range": 10, + "shots": 5 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [ - 0, - 0, - 0, - 0, - 20, - 0 - ] - }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Bow", - "cost": 0, - "hits": { - "Single Arrow": 5 - } + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Arrow", + "cost": 0, + "multipliers": [0, 0, 0, 0, 20, 0] + }, + { + "type": "add_spell_prop", + "base_spell": 4, + "target_part": "Single Bow", + "cost": 0, + "hits": { + "Single Arrow": 5 } - ], - "id": 29 + } + ] }, { "display_name": "Minefield", "desc": "Allow you to place +6 Traps, but with reduced damage and range.", "archetype": "Trapper", - "archetype_req": 10, - "parents": [ - 26, - 53 - ], - "dependencies": [ - 10 - ], + "archetype_req": 10, + "parents": ["Grape Bomb", "Cheaper Arrow Bomb (2)"], + "dependencies": ["Basaltic Trap"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 40, "col": 7 - }, + }, "properties": { "aoe": -2, "traps": 6 }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [ - -80, - 0, - 0, - 0, - 0, - 0 - ] + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Basaltic Trap", + "cost": 0, + "multipliers": [-80, 0, 0, 0, 0, 0] } - ], - "id": 30 - }, + ] + }, { "display_name": "Bow Proficiency I", "desc": "Improve your Main Attack's damage and range when using a bow.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 2 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Arrow Bomb"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 4 - }, + }, "properties": { "mainAtk_range": 6 }, @@ -1317,103 +1004,94 @@ const atrees = { } ] } - ], - "id": 31 + ] }, { "display_name": "Cheaper Arrow Bomb", "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 31 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Bow Proficiency I"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 6 + }, + "properties": { + }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -10 } - ], - "id": 32 + ] }, { "display_name": "Cheaper Arrow Storm", "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 12, - 11, - 61 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Grappling Hook", "Windstorm", "Focus"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 21, "col": 3 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ], - "id": 33 + ] }, { "display_name": "Cheaper Escape", "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 7, - 0 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Arrow Storm", "Arrow Shield"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 9, "col": 4 + }, + "properties": { + }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ], - "id": 34 + ] }, { "display_name": "Earth Mastery", "desc": "Increases your base damage from all Earth attacks", - "archetype": "Trapper", - "archetype_req": 0, - "parents": [ - 0 - ], - "dependencies": [], + "archetype": "Trapper", + "archetype_req": 0, + "parents": ["Arrow Shield"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 8 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "raw_stat", @@ -1426,34 +1104,27 @@ const atrees = { { "type": "stat", "name": "eDam", - "value": [ - 2, - 4 - ] + "value": [2, 4] } ] } - ], - "id": 35 + ] }, { "display_name": "Thunder Mastery", "desc": "Increases your base damage from all Thunder attacks", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": [ - 7, - 39, - 34 - ], - "dependencies": [], + "archetype": "Boltslinger", + "archetype_req": 0, + "parents": ["Arrow Storm", "Fire Mastery", "Cheaper Escape"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 2 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "raw_stat", @@ -1466,34 +1137,27 @@ const atrees = { { "type": "stat", "name": "tDam", - "value": [ - 1, - 8 - ] + "value": [1, 8] } ] } - ], - "id": 36 + ] }, { "display_name": "Water Mastery", "desc": "Increases your base damage from all Water attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": [ - 34, - 36, - 39 - ], - "dependencies": [], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Cheaper Escape", "Thunder Mastery", "Fire Mastery"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 14, "col": 4 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "raw_stat", @@ -1506,32 +1170,27 @@ const atrees = { { "type": "stat", "name": "wDam", - "value": [ - 2, - 4 - ] + "value": [2, 4] } ] } - ], - "id": 37 + ] }, { "display_name": "Air Mastery", "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 7 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Arrow Storm"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 0 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "raw_stat", @@ -1544,34 +1203,27 @@ const atrees = { { "type": "stat", "name": "aDam", - "value": [ - 3, - 4 - ] + "value": [3, 4] } ] } - ], - "id": 38 + ] }, { "display_name": "Fire Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": [ - 36, - 0, - 34 - ], - "dependencies": [], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Arrow Shield", "Cheaper Escape"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 6 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "raw_stat", @@ -1584,210 +1236,156 @@ const atrees = { { "type": "stat", "name": "fDam", - "value": [ - 3, - 5 - ] + "value": [3, 5] } ] } - ], - "id": 39 + ] }, { "display_name": "More Shields", "desc": "Give +2 charges to Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 12, - 10 - ], - "dependencies": [ - 0 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Grappling Hook", "Basaltic Trap"], + "dependencies": ["Arrow Shield"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 21, "col": 7 - }, + }, "properties": { "shieldCharges": 2 - }, - "id": 40 + } }, { "display_name": "Stormy Feet", "desc": "Windy Feet will last longer and add more speed.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 11 - ], - "dependencies": [ - 9 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Windstorm"], + "dependencies": ["Windy Feet"], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 23, - "col": 1 + "row": 23, + "col": 1 }, "properties": { - "duration": 60 + "duration": 60 }, "effects": [ - { - "type": "stat_bonus", - "bonuses": [ - { - "type": "stat", - "name": "spdPct", - "value": 20 - } - ] + { + "type": "stat_bonus", + "bonuses": [ + { + "type": "stat", + "name": "spdPct", + "value": 20 } - ], - "id": 41 + ] + } + ] }, { "display_name": "Refined Gunpowder", "desc": "Increase the damage of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 11 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Windstorm"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 25, - "col": 0 + "row": 25, + "col": 0 }, "properties": {}, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [ - 50, - 0, - 0, - 0, - 0, - 0 - ] - } - ], - "id": 42 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Bomb", + "cost": 0, + "multipliers": [50, 0, 0, 0, 0, 0] + } + ] }, { "display_name": "More Traps", "desc": "Increase the maximum amount of active Traps you can have by +2.", "archetype": "Trapper", - "archetype_req": 10, - "parents": [ - 54 - ], - "dependencies": [ - 10 - ], + "archetype_req": 10, + "parents": ["Bouncing Bomb"], + "dependencies": ["Basaltic Trap"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 8 - }, + }, "properties": { "traps": 2 - }, - "id": 43 + } }, { "display_name": "Better Arrow Shield", "desc": "Arrow Shield will gain additional area of effect, knockback and damage.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": [ - 19, - 18, - 14 - ], - "dependencies": [ - 0 - ], + "archetype": "Sharpshooter", + "archetype_req": 0, + "parents": ["Mana Trap", "Shocking Bomb", "Twain's Arc"], + "dependencies": ["Arrow Shield"], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 28, - "col": 6 + "row": 28, + "col": 6 }, "properties": { - "aoe": 1 - }, + "aoe": 1 + }, "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Shield", - "multipliers": [ - 40, - 0, - 0, - 0, - 0, - 0 - ] - } - ], - "id": 44 + { + "type": "add_spell_prop", + "base_spell": 3, + "target_part": "Arrow Shield", + "multipliers": [40, 0, 0, 0, 0, 0] + } + ] }, { "display_name": "Better Leap", "desc": "Reduce leap's cooldown by 1s.", "archetype": "Boltslinger", - "archetype_req": 0, - "parents": [ - 17, - 55 - ], - "dependencies": [ - 17 - ], + "archetype_req": 0, + "parents": ["Leap", "Homing Shots"], + "dependencies": ["Leap"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 1 - }, + }, "properties": { "cooldown": -1 - }, - "id": 45 + } }, { "display_name": "Better Guardian Angels", "desc": "Your Guardian Angels can shoot +4 arrows before disappearing.", "archetype": "Boltslinger", - "archetype_req": 0, - "parents": [ - 20, - 55 - ], - "dependencies": [ - 8 - ], + "archetype_req": 0, + "parents": ["Escape Artist", "Homing Shots"], + "dependencies": ["Guardian Angels"], "blockers": [], - "cost": 1, + "cost": 1, "display": { - "row": 31, - "col": 2 + "row": 31, + "col": 2 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "add_spell_prop", @@ -1798,52 +1396,44 @@ const atrees = { "Single Arrow": 4 } } - ], - "id": 46 + ] }, { "display_name": "Cheaper Arrow Storm (2)", "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 21, - 19 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Initiator", "Mana Trap"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 8 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ], - "id": 47 + ] }, { "display_name": "Precise Shot", "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": [ - 46, - 49, - 23 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Better Guardian Angels", "Cheaper Arrow Shield", "Arrow Hurricane"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 2 - }, + }, "properties": { "mainAtk_range": 6 }, @@ -1858,138 +1448,118 @@ const atrees = { } ] } - ], - "id": 48 + ] }, { "display_name": "Cheaper Arrow Shield", "desc": "Reduce the Mana cost of Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 48, - 21 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Precise Shot", "Initiator"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 4 + }, + "properties": { }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ], - "id": 49 + ] }, { "display_name": "Rocket Jump", "desc": "Arrow Bomb's self-damage will knockback you farther away.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 47, - 21 - ], - "dependencies": [ - 2 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Arrow Storm (2)", "Initiator"], + "dependencies": ["Arrow Bomb"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 33, "col": 6 - }, - "properties": {}, - "id": 50 + }, + "properties": { + } }, { "display_name": "Cheaper Escape (2)", "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 22, - 70 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Call of the Hound", "Decimator"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 34, "col": 7 + }, + "properties": { + }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ], - "id": 51 + ] }, { "display_name": "Stronger Hook", "desc": "Increase your Grappling Hook's range, speed and strength.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": [ - 51 - ], - "dependencies": [ - 12 - ], + "archetype": "Trapper", + "archetype_req": 5, + "parents": ["Cheaper Escape (2)"], + "dependencies": ["Grappling Hook"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 8 - }, + }, "properties": { - "range": 8 - }, - "id": 52 + "range": 8 + } }, { "display_name": "Cheaper Arrow Bomb (2)", "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": [ - 63, - 30 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["More Focus (2)", "Minefield"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 40, "col": 5 + }, + "properties": { + }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -5 } - ], - "id": 53 + ] }, { "display_name": "Bouncing Bomb", "desc": "Arrow Bomb will bounce once when hitting a block or enemy", "archetype": "", "archetype_req": 0, - "parents": [ - 40 - ], + "parents": ["More Shields"], "dependencies": [], "blockers": [], "cost": 2, @@ -1997,7 +1567,9 @@ const atrees = { "row": 25, "col": 7 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "add_spell_prop", @@ -2008,18 +1580,14 @@ const atrees = { "Arrow Bomb": 2 } } - ], - "id": 54 + ] }, { "display_name": "Homing Shots", "desc": "Your Main Attack arrows will follow nearby enemies and not be affected by gravity", "archetype": "", "archetype_req": 0, - "parents": [ - 17, - 18 - ], + "parents": ["Leap", "Shocking Bomb"], "dependencies": [], "blockers": [], "cost": 2, @@ -2027,53 +1595,45 @@ const atrees = { "row": 28, "col": 2 }, - "properties": {}, - "effects": [], - "id": 55 + "properties": { + + }, + "effects": [ + + ] }, { "display_name": "Shrapnel Bomb", "desc": "Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area", "archetype": "Boltslinger", "archetype_req": 8, - "parents": [ - 23, - 48 - ], + "parents": ["Arrow Hurricane", "Precise Shot"], "dependencies": [], "blockers": [], "cost": 2, "display": { "row": 34, - "col": 1 + "col": 1 + }, + "properties": { + }, - "properties": {}, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Shrapnel Bomb", "cost": 0, - "multipliers": [ - 40, - 0, - 0, - 0, - 20, - 0 - ] + "multipliers": [40, 0, 0, 0, 20, 0] } - ], - "id": 56 + ] }, { "display_name": "Elusive", "desc": "If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)", "archetype": "Boltslinger", "archetype_req": 0, - "parents": [ - 24 - ], + "parents": ["Geyser Stomp"], "dependencies": [], "blockers": [], "cost": 2, @@ -2081,22 +1641,21 @@ const atrees = { "row": 38, "col": 0 }, - "properties": {}, - "effects": [], - "id": 57 + "properties": { + + }, + "effects": [ + + ] }, { "display_name": "Double Shots", "desc": "Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)", "archetype": "Boltslinger", "archetype_req": 0, - "parents": [ - 1 - ], + "parents": ["Escape"], "dependencies": [], - "blockers": [ - 60 - ], + "blockers": ["Power Shots"], "cost": 1, "display": { "row": 7, @@ -2113,21 +1672,15 @@ const atrees = { "cost": 0, "multipliers": 0.7 } - ], - "id": 58 + ] }, { "display_name": "Triple Shots", "desc": "Triple Main Attack arrows, but they deal -20% damage per arrow", "archetype": "Boltslinger", "archetype_req": 0, - "parents": [ - 69, - 67 - ], - "dependencies": [ - 58 - ], + "parents": ["Arrow Rain", "Frenzy"], + "dependencies": ["Double Shots"], "blockers": [], "cost": 1, "display": { @@ -2145,38 +1698,34 @@ const atrees = { "cost": 0, "multipliers": 0.7 } - ], - "id": 59 + ] }, { "display_name": "Power Shots", "desc": "Main Attack arrows have increased speed and knockback", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": [ - 1 - ], + "parents": ["Escape"], "dependencies": [], - "blockers": [ - 58 - ], + "blockers": ["Double Shots"], "cost": 1, "display": { "row": 7, "col": 6 }, - "properties": {}, - "effects": [], - "id": 60 + "properties": { + + }, + "effects": [ + + ] }, { "display_name": "Focus", "desc": "When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once", "archetype": "Sharpshooter", "archetype_req": 2, - "parents": [ - 68 - ], + "parents": ["Phantom Ray"], "dependencies": [], "blockers": [], "cost": 2, @@ -2184,7 +1733,9 @@ const atrees = { "row": 19, "col": 4 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "stat_scaling", @@ -2195,23 +1746,17 @@ const atrees = { "abil_name": "Focus", "name": "damMult" }, - "scaling": [ - 3 - ], + "scaling": [3], "max": 3 } - ], - "id": 61 + ] }, { "display_name": "More Focus", "desc": "Add +2 max Focus", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": [ - 33, - 12 - ], + "parents": ["Cheaper Arrow Storm", "Grappling Hook"], "dependencies": [], "blockers": [], "cost": 1, @@ -2219,7 +1764,9 @@ const atrees = { "row": 22, "col": 4 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "stat_scaling", @@ -2230,23 +1777,17 @@ const atrees = { "abil_name": "Focus", "name": "damMult" }, - "scaling": [ - 35 - ], + "scaling": [35], "max": 5 } - ], - "id": 62 + ] }, { "display_name": "More Focus (2)", "desc": "Add +2 max Focus", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": [ - 25, - 28 - ], + "parents": ["Crepuscular Ray", "Snow Storm"], "dependencies": [], "blockers": [], "cost": 1, @@ -2254,7 +1795,9 @@ const atrees = { "row": 39, "col": 4 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "stat_scaling", @@ -2265,23 +1808,17 @@ const atrees = { "abil_name": "Focus", "name": "damMult" }, - "scaling": [ - 35 - ], + "scaling": [35], "max": 7 } - ], - "id": 63 + ] }, { "display_name": "Traveler", "desc": "For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)", "archetype": "", "archetype_req": 0, - "parents": [ - 42, - 14 - ], + "parents": ["Refined Gunpowder", "Twain's Arc"], "dependencies": [], "blockers": [], "cost": 1, @@ -2289,7 +1826,9 @@ const atrees = { "row": 25, "col": 2 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "stat_scaling", @@ -2304,25 +1843,18 @@ const atrees = { "type": "stat", "name": "sdRaw" }, - "scaling": [ - 1 - ], + "scaling": [1], "max": 100 } - ], - "id": 64 + ] }, { "display_name": "Patient Hunter", "desc": "Your Traps will deal +20% more damage for every second they are active (Max +80%)", "archetype": "Trapper", "archetype_req": 0, - "parents": [ - 40 - ], - "dependencies": [ - 10 - ], + "parents": ["More Shields"], + "dependencies": ["Basaltic Trap"], "blockers": [], "cost": 2, "display": { @@ -2332,20 +1864,17 @@ const atrees = { "properties": { "max": 80 }, - "effects": [], - "id": 65 + "effects": [ + + ] }, { "display_name": "Stronger Patient Hunter", "desc": "Add +80% Max Damage to Patient Hunter", "archetype": "Trapper", "archetype_req": 0, - "parents": [ - 26 - ], - "dependencies": [ - 65 - ], + "parents": ["Grape Bomb"], + "dependencies": ["Patient Hunter"], "blockers": [], "cost": 1, "display": { @@ -2355,18 +1884,16 @@ const atrees = { "properties": { "max": 80 }, - "effects": [], - "id": 66 + "effects": [ + + ] }, { "display_name": "Frenzy", "desc": "Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second", "archetype": "Boltslinger", "archetype_req": 0, - "parents": [ - 59, - 6 - ], + "parents": ["Triple Shots", "Nimble String"], "dependencies": [], "blockers": [], "cost": 2, @@ -2374,7 +1901,9 @@ const atrees = { "row": 17, "col": 2 }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "stat_scaling", @@ -2384,127 +1913,93 @@ const atrees = { "type": "stat", "name": "spd" }, - "scaling": [ - 6 - ], + "scaling": [6], "max": 200 } - ], - "id": 67 + ] }, { "display_name": "Phantom Ray", "desc": "Condense Arrow Storm into a single ray that damages enemies 10 times per second", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": [ - 37, - 4 - ], - "dependencies": [ - 7 - ], - "blockers": [ - 11, - 6, - 23 - ], + "parents": ["Water Mastery", "Fire Creep"], + "dependencies": ["Arrow Storm"], + "blockers": ["Windstorm", "Nimble String", "Arrow Hurricane"], "cost": 2, "display": { "row": 16, "col": 4 }, - "properties": {}, + "properties": { + }, "effects": [ - { + { "type": "replace_spell", "name": "Phantom Ray", "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", + "display_text": "Max Damage", + "base_spell": 1, + "spell_type": "damage", "scaling": "spell", - "display": "Total Damage", + "display": "Total Damage", "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [ - 25, - 0, - 5, - 0, - 0, - 0 - ] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Arrow": 16 - } + { + "name": "Single Arrow", + "type": "damage", + "multipliers": [25, 0, 5, 0, 0, 0] + }, + { + "name": "Total Damage", + "type": "total", + "hits": { + "Single Arrow": 16 } + } ] } - ], - "id": 68 + ] }, { "display_name": "Arrow Rain", "desc": "When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies", "archetype": "Trapper", "archetype_req": 0, - "parents": [ - 6, - 38 - ], - "dependencies": [ - 0 - ], + "parents": ["Nimble String", "Air Mastery"], + "dependencies": ["Arrow Shield"], "blockers": [], "cost": 2, "display": { "row": 15, "col": 0 }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "Arrow Rain", "cost": 0, - "multipliers": [ - 120, - 0, - 0, - 0, - 0, - 80 - ] + "multipliers": [120, 0, 0, 0, 0, 80] } - ], - "id": 69 + ] }, { "display_name": "Decimator", "desc": "Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)", "archetype": "Sharpshooter", "archetype_req": 0, - "parents": [ - 49 - ], - "dependencies": [ - 68 - ], + "parents": ["Cheaper Arrow Shield"], + "dependencies": ["Phantom Ray"], "blockers": [], "cost": 1, "display": { "row": 34, "col": 5 }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -2517,20 +2012,19 @@ const atrees = { "scaling": 10, "max": 50 } - ], - "id": 70 + ] } ], "Warrior": [ { "display_name": "Bash", "desc": "Violently bash the ground, dealing high damage in a large area", - "archetype": "", - "archetype_req": 0, - "parents": [], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": [], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 0, "col": 4, @@ -2554,14 +2048,7 @@ const atrees = { { "name": "Single Hit", "type": "damage", - "multipliers": [ - 130, - 20, - 0, - 0, - 0, - 0 - ] + "multipliers": [130, 20, 0, 0, 0, 0] }, { "name": "Total Damage", @@ -2572,20 +2059,17 @@ const atrees = { } ] } - ], - "id": 0 + ] }, { "display_name": "Spear Proficiency 1", "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": [ - 0 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Bash"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 4, @@ -2605,46 +2089,43 @@ const atrees = { } ] } - ], - "id": 1 + ] }, + { "display_name": "Cheaper Bash", "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": [ - 1 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 1"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 2, "col": 2, "icon": "node_0" }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -10 } - ], - "id": 2 + ] }, { "display_name": "Double Bash", "desc": "Bash will hit a second time at a farther range", - "archetype": "", - "archetype_req": 0, - "parents": [ - 1 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 1"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 4, "col": 4, @@ -2669,35 +2150,27 @@ const atrees = { "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [ - -50, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [-50, 0, 0, 0, 0, 0] } - ], - "id": 3 + ] }, + { "display_name": "Charge", "desc": "Charge forward at high speed (hold shift to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": [ - 3 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Double Bash"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 6, "col": 4, "icon": "node_4" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "replace_spell", @@ -2712,14 +2185,7 @@ const atrees = { { "name": "None", "type": "damage", - "multipliers": [ - 0, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [0, 0, 0, 0, 0, 0] }, { "name": "Total Damage", @@ -2730,20 +2196,18 @@ const atrees = { } ] } - ], - "id": 4 + ] }, + { "display_name": "Heavy Impact", "desc": "After using Charge, violently crash down into the ground and deal damage", - "archetype": "", - "archetype_req": 0, - "parents": [ - 8 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Uppercut"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 9, "col": 1, @@ -2758,37 +2222,27 @@ const atrees = { "base_spell": 2, "target_part": "Heavy Impact", "cost": 0, - "multipliers": [ - 100, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [100, 0, 0, 0, 0, 0] } - ], - "id": 5 + ] }, + { "display_name": "Vehement", "desc": "For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 4 - ], - "dependencies": [], - "blockers": [ - 7 - ], - "cost": 1, + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Charge"], + "dependencies": [], + "blockers": ["Tougher Skin"], + "cost": 1, "display": { "row": 6, "col": 2, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -2807,34 +2261,28 @@ const atrees = { "type": "stat", "name": "spd" }, - "scaling": [ - 1, - 1 - ], + "scaling": [1, 1], "max": 20 } - ], - "id": 6 + ] }, + { "display_name": "Tougher Skin", "desc": "Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 4 - ], - "dependencies": [], - "blockers": [ - 6 - ], - "cost": 1, + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Charge"], + "dependencies": [], + "blockers": ["Vehement"], + "cost": 1, "display": { "row": 6, "col": 6, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -2863,26 +2311,21 @@ const atrees = { "type": "stat", "name": "hpBonus" }, - "scaling": [ - 10, - 10 - ], + "scaling": [10, 10], "max": 100 } - ], - "id": 7 + ] }, + { "display_name": "Uppercut", "desc": "Rocket enemies in the air and deal massive damage", - "archetype": "", - "archetype_req": 0, - "parents": [ - 6 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Vehement"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 2, @@ -2906,14 +2349,7 @@ const atrees = { { "name": "Uppercut", "type": "damage", - "multipliers": [ - 150, - 50, - 50, - 0, - 0, - 0 - ] + "multipliers": [150, 50, 50, 0, 0, 0] }, { "name": "Total Damage", @@ -2924,47 +2360,43 @@ const atrees = { } ] } - ], - "id": 8 + ] }, + { "display_name": "Cheaper Charge", "desc": "Reduce the Mana cost of Charge", - "archetype": "", - "archetype_req": 0, - "parents": [ - 8, - 10 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Uppercut", "War Scream"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 4, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "cost": -5 } - ], - "id": 9 + ] }, + { "display_name": "War Scream", "desc": "Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies", - "archetype": "", - "archetype_req": 0, - "parents": [ - 7 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Tougher Skin"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 8, "col": 6, @@ -2989,37 +2421,29 @@ const atrees = { { "name": "War Scream", "type": "damage", - "multipliers": [ - 50, - 0, - 0, - 0, - 50, - 0 - ] + "multipliers": [50, 0, 0, 0, 50, 0] } ] } - ], - "id": 10 + ] }, + { "display_name": "Earth Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 8 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uppercut"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 0, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3032,35 +2456,29 @@ const atrees = { { "type": "stat", "name": "eDam", - "value": [ - 2, - 4 - ] + "value": [2, 4] } ] } - ], - "id": 11 + ] }, + { "display_name": "Thunder Mastery", "desc": "Increases base damage from all Thunder attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 8, - 14, - 9 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uppercut", "Air Mastery", "Cheaper Charge"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 2, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3073,35 +2491,29 @@ const atrees = { { "type": "stat", "name": "tDam", - "value": [ - 1, - 8 - ] + "value": [1, 8] } ] } - ], - "id": 12 + ] }, + { "display_name": "Water Mastery", "desc": "Increases base damage from all Water attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 9, - 12, - 14 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Cheaper Charge", "Thunder Mastery", "Air Mastery"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 11, "col": 4, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3114,35 +2526,29 @@ const atrees = { { "type": "stat", "name": "wDam", - "value": [ - 2, - 4 - ] + "value": [2, 4] } ] } - ], - "id": 13 + ] }, + { "display_name": "Air Mastery", "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 10, - 12, - 9 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["War Scream", "Thunder Mastery", "Cheaper Charge"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 6, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3155,33 +2561,29 @@ const atrees = { { "type": "stat", "name": "aDam", - "value": [ - 3, - 4 - ] + "value": [3, 4] } ] } - ], - "id": 14 + ] }, + { "display_name": "Fire Mastery", "desc": "Increases base damage from all Earth attacks", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 10 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["War Scream"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 10, "col": 8, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3194,28 +2596,22 @@ const atrees = { { "type": "stat", "name": "fDam", - "value": [ - 3, - 5 - ] + "value": [3, 5] } ] } - ], - "id": 15 + ] }, + { "display_name": "Quadruple Bash", "desc": "Bash will hit 4 times at an even larger range", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 11, - 17 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Earth Mastery", "Fireworks"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 0, @@ -3232,57 +2628,41 @@ const atrees = { "cost": 0, "hits": { "Single Hit": 2 - } + } }, { "type": "add_spell_prop", "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [ - -20, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [-20, 0, 0, 0, 0, 0] } - ], - "id": 16 + ] }, + { "display_name": "Fireworks", "desc": "Mobs hit by Uppercut will explode mid-air and receive additional damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 12, - 16 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Thunder Mastery", "Quadruple Bash"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 2, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Fireworks", "cost": 0, - "multipliers": [ - 80, - 0, - 20, - 0, - 0, - 0 - ] + "multipliers": [80, 0, 20, 0, 0, 0] }, { "type": "add_spell_prop", @@ -3293,22 +2673,18 @@ const atrees = { "Fireworks": 1 } } - ], - "id": 17 + ] }, + { "display_name": "Half-Moon Swipe", "desc": "Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": [ - 13 - ], - "dependencies": [ - 8 - ], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Water Mastery"], + "dependencies": ["Uppercut"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 13, "col": 4, @@ -3323,35 +2699,25 @@ const atrees = { "base_spell": 3, "target_part": "Uppercut", "cost": -10, - "multipliers": [ - -70, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [-70, 0, 0, 0, 0, 0] }, { "type": "convert_spell_conv", "target_part": "all", "conversion": "water" } - ], - "id": 18 + ] }, + { "display_name": "Flyby Jab", "desc": "Damage enemies in your way when using Charge", - "archetype": "", - "archetype_req": 0, - "parents": [ - 14, - 20 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Air Mastery", "Flaming Uppercut"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 6, @@ -3366,32 +2732,20 @@ const atrees = { "base_spell": 2, "target_part": "Flyby Jab", "cost": 0, - "multipliers": [ - 20, - 0, - 0, - 0, - 0, - 40 - ] + "multipliers": [20, 0, 0, 0, 0, 40] } - ], - "id": 19 + ] }, + { "display_name": "Flaming Uppercut", "desc": "Uppercut will light mobs on fire, dealing damage every 0.6 seconds", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 15, - 19 - ], - "dependencies": [ - 8 - ], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Fire Mastery", "Flyby Jab"], + "dependencies": ["Uppercut"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 12, "col": 8, @@ -3407,14 +2761,7 @@ const atrees = { "base_spell": 3, "target_part": "Flaming Uppercut", "cost": 0, - "multipliers": [ - 0, - 0, - 0, - 0, - 50, - 0 - ] + "multipliers": [0, 0, 0, 0, 50, 0] }, { "type": "add_spell_prop", @@ -3434,76 +2781,66 @@ const atrees = { "Flaming Uppercut": 5 } } - ], - "id": 20 + ] }, + { "display_name": "Iron Lungs", "desc": "War Scream deals more damage", - "archetype": "", - "archetype_req": 0, - "parents": [ - 19, - 20 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Flyby Jab", "Flaming Uppercut"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 13, "col": 7, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "War Scream", "cost": 0, - "multipliers": [ - 30, - 0, - 0, - 0, - 0, - 30 - ] + "multipliers": [30, 0, 0, 0, 0, 30] } - ], - "id": 21 + ] }, + { "display_name": "Generalist", "desc": "After casting 3 different spells in a row, your next spell will cost 5 mana", - "archetype": "Battle Monk", - "archetype_req": 3, - "parents": [ - 23 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 3, + "parents": ["Counter"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 2, "icon": "node_3" }, - "properties": {}, - "effects": [], - "id": 22 + "properties": { + }, + "effects": [ + + ] }, + { "display_name": "Counter", "desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 18 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Half-Moon Swipe"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 4, @@ -3518,31 +2855,20 @@ const atrees = { "base_spell": 5, "target_part": "Counter", "cost": 0, - "multipliers": [ - 60, - 0, - 20, - 0, - 0, - 20 - ] + "multipliers": [60, 0, 20, 0, 0, 20] } - ], - "id": 23 + ] }, + { "display_name": "Mantle of the Bovemists", "desc": "When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": [ - 21 - ], - "dependencies": [ - 10 - ], + "archetype": "Paladin", + "archetype_req": 3, + "parents": ["Iron Lungs"], + "dependencies": ["War Scream"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 15, "col": 7, @@ -3551,23 +2877,20 @@ const atrees = { "properties": { "mantle_charge": 3 }, - "effects": [], - "id": 24 + "effects": [ + + ] }, + { "display_name": "Bak'al's Grasp", "desc": "After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)", - "archetype": "Fallen", - "archetype_req": 2, - "parents": [ - 16, - 17 - ], - "dependencies": [ - 10 - ], + "archetype": "Fallen", + "archetype_req": 2, + "parents": ["Quadruple Bash", "Fireworks"], + "dependencies": ["War Scream"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 16, "col": 1, @@ -3583,29 +2906,24 @@ const atrees = { "slider_name": "Corrupted", "output": { "type": "stat", - "name": "raw" + "name": "raw" }, - "scaling": [ - 4 - ], + "scaling": [4], "slider_step": 2, "max": 120 } - ], - "id": 25 + ] }, + { "display_name": "Spear Proficiency 2", "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": [ - 25, - 27 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Bak'al's Grasp", "Cheaper Uppercut"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 0, @@ -3625,103 +2943,96 @@ const atrees = { } ] } - ], - "id": 26 + ] }, + { "display_name": "Cheaper Uppercut", "desc": "Reduce the Mana Cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": [ - 26, - 28, - 23 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Spear Proficiency 2", "Aerodynamics", "Counter"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 3, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "cost": -5 } - ], - "id": 27 + ] }, + { "display_name": "Aerodynamics", "desc": "During Charge, you can steer and change direction", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 27, - 29 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Cheaper Uppercut", "Provoke"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 17, "col": 5, "icon": "node_1" }, - "properties": {}, - "effects": [], - "id": 28 + "properties": { + }, + "effects": [ + + ] }, + { "display_name": "Provoke", "desc": "Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 28, - 24 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Aerodynamics", "Mantle of the Bovemists"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 17, "col": 7, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ], - "id": 29 + ] }, + { "display_name": "Precise Strikes", "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": [ - 27, - 26 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Cheaper Uppercut", "Spear Proficiency 2"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 18, "col": 2, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -3733,66 +3044,53 @@ const atrees = { } ] } - ], - "id": 30 + ] }, + { "display_name": "Air Shout", "desc": "War Scream will fire a projectile that can go through walls and deal damage multiple times", - "archetype": "", - "archetype_req": 0, - "parents": [ - 28, - 29 - ], - "dependencies": [ - 10 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Aerodynamics", "Provoke"], + "dependencies": ["War Scream"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 18, "col": 6, "icon": "node_1" }, - "properties": {}, + "properties": { + + }, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "target_part": "Air Shout", "cost": 0, - "multipliers": [ - 20, - 0, - 0, - 0, - 0, - 5 - ] + "multipliers": [20, 0, 0, 0, 0, 5] } - ], - "id": 31 + ] }, + { "display_name": "Enraged Blow", "desc": "While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 26 - ], - "dependencies": [ - 25 - ], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Spear Proficiency 2"], + "dependencies": ["Bak'al's Grasp"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 0, "icon": "node_2" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -3805,66 +3103,50 @@ const atrees = { ], "output": { "type": "stat", - "name": "damMult" + "name": "damMult" }, - "scaling": [ - 3 - ], + "scaling": [3], "max": 300 } - ], - "id": 32 + ] }, + { "display_name": "Flying Kick", "desc": "When using Charge, mobs hit will halt your momentum and get knocked back", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": [ - 27, - 34 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Cheaper Uppercut", "Stronger Mantle"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 3, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 2, "target_part": "Flying Kick", "cost": 0, - "multipliers": [ - 120, - 0, - 0, - 10, - 0, - 20 - ] + "multipliers": [120, 0, 0, 10, 0, 20] } - ], - "id": 33 + ] }, + { "display_name": "Stronger Mantle", "desc": "Add +2 additional charges to Mantle of the Bovemists", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 35, - 33 - ], - "dependencies": [ - 24 - ], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Manachism", "Flying Kick"], + "dependencies": ["Mantle of the Bovemists"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 20, "col": 6, @@ -3873,21 +3155,20 @@ const atrees = { "properties": { "mantle_charge": 2 }, - "effects": [], - "id": 34 + "effects": [ + + ] }, + { "display_name": "Manachism", "desc": "If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": [ - 34, - 29 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 3, + "parents": ["Stronger Mantle", "Provoke"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 20, "col": 8, @@ -3896,59 +3177,47 @@ const atrees = { "properties": { "cooldown": 1 }, - "effects": [], - "id": 35 + "effects": [ + + ] }, + { "display_name": "Boiling Blood", "desc": "Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds", - "archetype": "", - "archetype_req": 0, - "parents": [ - 32, - 37 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Enraged Blow", "Ragnarokkr"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 0, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "target_part": "Boiling Blood", "cost": 0, - "multipliers": [ - 25, - 0, - 0, - 0, - 5, - 0 - ] + "multipliers": [25, 0, 0, 0, 5, 0] } - ], - "id": 36 + ] }, + { "display_name": "Ragnarokkr", "desc": "War Scream become deafening, increasing its range and giving damage bonus to players", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 36, - 33 - ], - "dependencies": [ - 10 - ], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Boiling Blood", "Flying Kick"], + "dependencies": ["War Scream"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 22, "col": 2, @@ -3964,24 +3233,18 @@ const atrees = { "base_spell": 4, "cost": 10 } - ], - "id": 37 + ] }, + { "display_name": "Ambidextrous", "desc": "Increase your chance to attack with Counter by +30%", - "archetype": "", - "archetype_req": 0, - "parents": [ - 33, - 34, - 39 - ], - "dependencies": [ - 23 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Flying Kick", "Stronger Mantle", "Burning Heart"], + "dependencies": ["Counter"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 4, @@ -3990,27 +3253,27 @@ const atrees = { "properties": { "chance": 30 }, - "effects": [], - "id": 38 + "effects": [ + + ] }, + { "display_name": "Burning Heart", "desc": "For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 38, - 40 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Ambidextrous", "Stronger Bash"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 6, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -4025,134 +3288,106 @@ const atrees = { "type": "stat", "name": "fDamPct" }, - "scaling": [ - 2 - ], + "scaling": [2], "max": 100, "slider_step": 100 } - ], - "id": 39 + ] }, + { "display_name": "Stronger Bash", "desc": "Increase the damage of Bash", - "archetype": "", - "archetype_req": 0, - "parents": [ - 39, - 35 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Burning Heart", "Manachism"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 22, "col": 8, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "target_part": "Single Hit", "cost": 0, - "multipliers": [ - 30, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [30, 0, 0, 0, 0, 0] } - ], - "id": 40 + ] }, + { "display_name": "Intoxicating Blood", "desc": "After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted", - "archetype": "Fallen", - "archetype_req": 5, - "parents": [ - 37, - 36 - ], - "dependencies": [ - 25 - ], + "archetype": "Fallen", + "archetype_req": 5, + "parents": ["Ragnarokkr", "Boiling Blood"], + "dependencies": ["Bak'al's Grasp"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 1, "icon": "node_1" }, - "properties": {}, - "effects": [], - "id": 41 + "properties": { + }, + "effects": [ + + ] }, + { "display_name": "Comet", "desc": "After being hit by Fireworks, enemies will crash into the ground and receive more damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 37 - ], - "dependencies": [ - 17 - ], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Ragnarokkr"], + "dependencies": ["Fireworks"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 24, "col": 2, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Comet", "cost": 0, - "multipliers": [ - 80, - 20, - 0, - 0, - 0, - 0 - ] + "multipliers": [80, 20, 0, 0, 0, 0] }, { - "type": "add_spell_prop", + "type":"add_spell_prop", "base_spell": 3, "target_part": "Total Damage", - "cost": 0, + "cost": 0, "hits": { "Comet": 1 } } - ], - "id": 42 + ] }, + { "display_name": "Collide", "desc": "Mobs thrown into walls from Flying Kick will explode and receive additonal damage", - "archetype": "Battle Monk", - "archetype_req": 4, - "parents": [ - 38, - 39 - ], - "dependencies": [ - 33 - ], + "archetype": "Battle Monk", + "archetype_req": 4, + "parents": ["Ambidextrous", "Burning Heart"], + "dependencies": ["Flying Kick"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 5, @@ -4167,53 +3402,41 @@ const atrees = { "base_spell": 2, "target_part": "Collide", "cost": 0, - "multipliers": [ - 100, - 0, - 0, - 0, - 50, - 0 - ] + "multipliers": [100, 0, 0, 0, 50, 0] } - ], - "id": 43 + ] }, + { "display_name": "Rejuvenating Skin", "desc": "Regain back 30% of the damage you take as healing over 30s", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 39, - 40 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Burning Heart", "Stronger Bash"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 23, "col": 7, "icon": "node_3" }, - "properties": {}, - "effects": [], - "id": 44 + "properties": { + }, + "effects": [ + + ] }, + { "display_name": "Uncontainable Corruption", "desc": "Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1", - "archetype": "", - "archetype_req": 0, - "parents": [ - 36, - 46 - ], - "dependencies": [ - 25 - ], + "archetype": "", + "archetype_req": 0, + "parents": ["Boiling Blood", "Radiant Devotee"], + "dependencies": ["Bak'al's Grasp"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 0, @@ -4229,35 +3452,31 @@ const atrees = { "slider_name": "Corrupted", "output": { "type": "stat", - "name": "raw" + "name": "raw" }, - "scaling": [ - 1 - ], + "scaling": [1], "slider_step": 2, "max": 50 } - ], - "id": 45 + ] }, + { "display_name": "Radiant Devotee", "desc": "For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": [ - 47, - 45 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 1, + "parents": ["Whirlwind Strike", "Uncontainable Corruption"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 26, "col": 2, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -4271,36 +3490,29 @@ const atrees = { "type": "stat", "name": "mr" }, - "scaling": [ - 1 - ], + "scaling": [1], "max": 10, "slider_step": 4 } - ], - "id": 46 + ] }, + { "display_name": "Whirlwind Strike", "desc": "Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": [ - 38, - 46 - ], - "dependencies": [ - 8 - ], + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": ["Ambidextrous", "Radiant Devotee"], + "dependencies": ["Uppercut"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 26, "col": 4, "icon": "node_1" }, "properties": { - "range": 2 + "range": 2 }, "effects": [ { @@ -4308,35 +3520,27 @@ const atrees = { "base_spell": 3, "target_part": "Uppercut", "cost": 0, - "multipliers": [ - 0, - 0, - 0, - 0, - 0, - 50 - ] + "multipliers": [0, 0, 0, 0, 0, 50] } - ], - "id": 47 + ] }, + { "display_name": "Mythril Skin", "desc": "Gain +5% Base Resistance and become immune to knockback", - "archetype": "Paladin", - "archetype_req": 6, - "parents": [ - 44 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 6, + "parents": ["Rejuvenating Skin"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 26, "col": 7, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "raw_stat", @@ -4348,23 +3552,18 @@ const atrees = { } ] } - ], - "id": 48 + ] }, + { "display_name": "Armour Breaker", "desc": "While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 45, - 46 - ], - "dependencies": [ - 25 - ], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Uncontainable Corruption", "Radiant Devotee"], + "dependencies": ["Bak'al's Grasp"], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 1, @@ -4373,56 +3572,47 @@ const atrees = { "properties": { "duration": 5 }, - "effects": [], - "id": 49 + "effects": [ + + ] }, + { "display_name": "Shield Strike", "desc": "When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 48, - 51 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Mythril Skin", "Sparkling Hope"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 6, "icon": "node_1" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 5, "target_part": "Shield Strike", "cost": 0, - "multipliers": [ - 60, - 0, - 20, - 0, - 0, - 0 - ] + "multipliers": [60, 0, 20, 0, 0, 0] } - ], - "id": 50 + ] }, + { "display_name": "Sparkling Hope", "desc": "Everytime you heal 5% of your max health, deal damage to all nearby enemies", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 48 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Mythril Skin"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 27, "col": 8, @@ -4437,36 +3627,27 @@ const atrees = { "base_spell": 5, "target_part": "Sparkling Hope", "cost": 0, - "multipliers": [ - 10, - 0, - 5, - 0, - 0, - 0 - ] + "multipliers": [10, 0, 5, 0, 0, 0] } - ], - "id": 51 + ] }, + { "display_name": "Massive Bash", "desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)", - "archetype": "Fallen", - "archetype_req": 8, - "parents": [ - 53, - 45 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 8, + "parents": ["Tempest", "Uncontainable Corruption"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 28, "col": 0, "icon": "node_2" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -4474,29 +3655,24 @@ const atrees = { "slider_name": "Corrupted", "output": { "type": "stat", - "name": "bashAoE" + "name": "bashAoE" }, - "scaling": [ - 1 - ], + "scaling": [1], "max": 10, "slider_step": 3 } - ], - "id": 52 + ] }, + { "display_name": "Tempest", "desc": "War Scream will ripple the ground and deal damage 3 times in a large area", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 52, - 54 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Massive Bash", "Spirit of the Rabbit"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 28, "col": 2, @@ -4511,14 +3687,7 @@ const atrees = { "base_spell": 4, "target_part": "Tempest", "cost": "0", - "multipliers": [ - 30, - 10, - 0, - 0, - 0, - 10 - ] + "multipliers": [30, 10, 0, 0, 0, 10] }, { "type": "add_spell_prop", @@ -4538,27 +3707,25 @@ const atrees = { "Tempest": 3 } } - ], - "id": 53 + ] }, + { "display_name": "Spirit of the Rabbit", "desc": "Reduce the Mana cost of Charge and increase your Walk Speed by +20%", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": [ - 53, - 47 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 5, + "parents": ["Tempest", "Whirlwind Strike"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 28, "col": 4, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", @@ -4575,78 +3742,66 @@ const atrees = { } ] } - ], - "id": 54 + ] }, + { "display_name": "Massacre", "desc": "While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar", - "archetype": "Fallen", - "archetype_req": 5, - "parents": [ - 53, - 52 - ], - "dependencies": [], + "archetype": "Fallen", + "archetype_req": 5, + "parents": ["Tempest", "Massive Bash"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 29, "col": 1, "icon": "node_1" }, - "properties": {}, - "effects": [], - "id": 55 + "properties": { + }, + "effects": [ + + ] }, + { "display_name": "Axe Kick", "desc": "Increase the damage of Uppercut, but also increase its mana cost", - "archetype": "", - "archetype_req": 0, - "parents": [ - 53, - 54 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Tempest", "Spirit of the Rabbit"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 3, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 3, "target_part": "Uppercut", "cost": 10, - "multipliers": [ - 100, - 0, - 0, - 0, - 0, - 0 - ] + "multipliers": [100, 0, 0, 0, 0, 0] } - ], - "id": 56 + ] }, + { "display_name": "Radiance", "desc": "Bash will buff your allies' positive IDs. (15s Cooldown)", - "archetype": "Paladin", - "archetype_req": 2, - "parents": [ - 54, - 58 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 2, + "parents": ["Spirit of the Rabbit", "Cheaper Bash 2"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 29, "col": 5, @@ -4655,80 +3810,77 @@ const atrees = { "properties": { "cooldown": 15 }, - "effects": [], - "id": 57 + "effects": [ + + ] }, + { "display_name": "Cheaper Bash 2", "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": [ - 57, - 50, - 51 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Radiance", "Shield Strike", "Sparkling Hope"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 29, "col": 7, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 1, "cost": -5 } - ], - "id": 58 + ] }, + { "display_name": "Cheaper War Scream", "desc": "Reduce the Mana cost of War Scream", - "archetype": "", - "archetype_req": 0, - "parents": [ - 52 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Massive Bash"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 0, "icon": "node_0" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "add_spell_prop", "base_spell": 4, "cost": -5 } - ], - "id": 59 + ] }, + { "display_name": "Discombobulate", "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", - "archetype": "Battle Monk", - "archetype_req": 11, - "parents": [ - 62 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 11, + "parents": ["Cyclone"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 31, "col": 2, "icon": "node_3" }, - "properties": {}, + "properties": { + }, "effects": [ { "type": "stat_scaling", @@ -4736,27 +3888,23 @@ const atrees = { "slider_name": "Hits dealt", "output": { "type": "stat", - "name": "rainrawButDifferent" + "name": "rainrawButDifferent" }, - "scaling": [ - 2 - ], + "scaling": [2], "max": 50 } - ], - "id": 60 + ] }, + { "display_name": "Thunderclap", "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", - "archetype": "Battle Monk", - "archetype_req": 8, - "parents": [ - 62 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 8, + "parents": ["Cyclone"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 32, "col": 5, @@ -4771,29 +3919,25 @@ const atrees = { }, { "type": "raw_stat", - "bonuses": [ - { - "type": "prop", - "abil_name": "Bash", - "name": "aoe", - "value": 3 - } - ] + "bonuses": [{ + "type": "prop", + "abil_name": "Bash", + "name": "aoe", + "value": 3 + }] } - ], - "id": 61 + ] }, + { "display_name": "Cyclone", "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": [ - 54 - ], - "dependencies": [], + "archetype": "Battle Monk", + "archetype_req": 0, + "parents": ["Spirit of the Rabbit"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 31, "col": 4, @@ -4809,14 +3953,7 @@ const atrees = { "base_spell": 4, "target_part": "Cyclone", "cost": 0, - "multipliers": [ - 10, - 0, - 0, - 0, - 5, - 10 - ] + "multipliers": [10, 0, 0, 0, 5, 10] }, { "type": "add_spell_prop", @@ -4826,105 +3963,92 @@ const atrees = { "hits": { "Cyclone": 40 } + } - ], - "id": 62 + ] }, + { "display_name": "Second Chance", "desc": "When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)", - "archetype": "Paladin", - "archetype_req": 12, - "parents": [ - 58 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 12, + "parents": ["Cheaper Bash 2"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 32, "col": 7, "icon": "node_3" }, "properties": {}, - "effects": [], - "id": 63 + "effects": [] }, + { "display_name": "Blood Pact", "desc": "If you do not have enough mana to cast a spell, spend health instead (1% health per mana)", - "archetype": "", - "archetype_req": 10, - "parents": [ - 59 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 10, + "parents": ["Cheaper War Scream"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 34, "col": 1, "icon": "node_3" }, "properties": {}, - "effects": [], - "id": 64 + "effects": [] }, + { "display_name": "Haemorrhage", "desc": "Reduce Blood Pact's health cost. (0.5% health per mana)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": [ - 64 - ], - "dependencies": [ - 64 - ], + "archetype": "Fallen", + "archetype_req": 0, + "parents": ["Blood Pact"], + "dependencies": ["Blood Pact"], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 2, "icon": "node_1" }, "properties": {}, - "effects": [], - "id": 65 + "effects": [] }, + { "display_name": "Brink of Madness", "desc": "If your health is 25% full or less, gain +40% Resistance", - "archetype": "", - "archetype_req": 0, - "parents": [ - 64, - 67 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Blood Pact", "Cheaper Uppercut 2"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 35, "col": 4, "icon": "node_2" }, "properties": {}, - "effects": [], - "id": 66 + "effects": [] }, + { "display_name": "Cheaper Uppercut 2", "desc": "Reduce the Mana cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": [ - 63, - 66 - ], - "dependencies": [], + "archetype": "", + "archetype_req": 0, + "parents": ["Second Chance", "Brink of Madness"], + "dependencies": [], "blockers": [], - "cost": 1, + "cost": 1, "display": { "row": 35, "col": 6, @@ -4937,20 +4061,18 @@ const atrees = { "base_spell": 3, "cost": -5 } - ], - "id": 67 + ] }, + { "display_name": "Martyr", "desc": "When you receive a fatal blow, all nearby allies become invincible", - "archetype": "Paladin", - "archetype_req": 0, - "parents": [ - 63 - ], - "dependencies": [], + "archetype": "Paladin", + "archetype_req": 0, + "parents": ["Second Chance"], + "dependencies": [], "blockers": [], - "cost": 2, + "cost": 2, "display": { "row": 35, "col": 8, @@ -4960,8 +4082,7 @@ const atrees = { "duration": 3, "aoe": 12 }, - "effects": [], - "id": 68 + "effects": [] } ] -} \ No newline at end of file +} diff --git a/js/atree_constants_old.js b/js/atree_constants_old.js deleted file mode 100644 index e325247..0000000 --- a/js/atree_constants_old.js +++ /dev/null @@ -1,171 +0,0 @@ -const atrees_old = { - "Assassin": [ - {"title": "Spin Attack", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 0, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 1, "col": 4}, - {"title": "Dagger Proficiency I", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 2, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 2, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 2, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 3, "col": 4}, - {"title": "Double Spin", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 4, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 5, "col": 4}, - {"title": "Dash", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 6, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 6, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 6, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 6, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 6, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 7, "col": 2}, - {"title": "Smoke Bomb", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 8, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 7, "col": 6}, - {"title": "Multihit", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 8, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 8, "col": 3}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 8, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 8, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 8, "col": 1}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 8, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 9, "col": 0}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 10, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 9, "col": 2}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 10, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 9, "col": 6}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 10, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 8, "col": 7}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 8, "col": 8}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 9, "col": 8}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 10, "col": 8}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 10, "col": 1}, - {"title": "Backstab", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 11, "col": 1}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 9, "col": 4}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 90, "row": 10, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 10, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 11, "col": 4}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 10, "col": 7}, - {"title": "Fatality", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 11, "col": 7}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 11, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 12, "col": 0}, - {"title": "Violent Vortex", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 13, "col": 0}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 11, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 12, "col": 2}, - {"title": "Vanish", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 13, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 12, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 13, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 13, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 13, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 14, "col": 2}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 15, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 14, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 15, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 12, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 13, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 14, "col": 7}, - {"title": "Lacerate", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 15, "col": 7}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 15, "col": 1}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 16, "col": 1}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 15, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 16, "col": 5}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 15, "col": 8}, - {"title": "Wall of Smoke", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 16, "col": 8}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 16, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 17, "col": 0}, - {"title": "Silent Killer", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 18, "col": 0}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 16, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 17, "col": 2}, - {"title": "Shadow Travel", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 18, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 17, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 18, "col": 5}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 17, "col": 8}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 18, "col": 8}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 18, "col": 4}, - {"title": "Exploding Clones", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 19, "col": 4}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 18, "col": 3}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 19, "col": 0}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 20, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 19, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 20, "col": 3}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 18, "col": 6}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 18, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 19, "col": 7}, - {"title": "Weightless", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 20, "col": 7}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 20, "col": 1}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 20, "col": 2}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 21, "col": 1}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 20, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 21, "col": 4}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 20, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 21, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 21, "col": 6}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 20, "col": 8}, - {"title": "Dancing Blade", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 21, "col": 8}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 21, "col": 0}, - {"title": "Spin Attack Damage", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 22, "col": 0}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 21, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 22, "col": 3}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 22, "col": 1}, - {"title": "Marked", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 23, "col": 1}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 22, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 23, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 23, "col": 5}, - {"title": "Shurikens", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 23, "col": 6}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 23, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 22, "col": 8}, - {"title": "Far Reach", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 23, "col": 8}, - {"title": "Stronger Multihit", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 24, "col": 5}, - {"title": "Psithurism", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 24, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 24, "col": 1}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 25, "col": 1}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 25, "col": 3}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 24, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 25, "col": 4}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 25, "col": 5}, - {"title": "Choke Bomb", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 25, "col": 6}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 25, "col": 7}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 25, "col": 8}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 26, "col": 5}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 25, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 26, "col": 0}, - {"title": "Death Magnet", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 27, "col": 0}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 25, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 26, "col": 2}, - {"title": "Cheaper Multihit", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 27, "col": 2}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 26, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 27, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 26, "col": 7}, - {"title": "Parry", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 27, "col": 7}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 27, "col": 1}, - {"title": "Fatal Spin", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 28, "col": 1}, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 27, "col": 3}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 28, "col": 3}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 27, "col": 6}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 28, "col": 6}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 27, "col": 8}, - {"title": "Wall Jump", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 28, "col": 8}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 28, "col": 0}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 29, "col": 0}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 29, "col": 1}, - {"title": "Harvester", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 30, "col": 1}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 28, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 29, "col": 4}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 30, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 28, "col": 7}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 29, "col": 7}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 30, "col": 7 }, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 30, "col": 2}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 31, "col": 2 }, - {"image": "../media/atree/connect_t.png", "connector": true, "rotate": 180, "row": 30, "col": 5}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 90, "row": 30, "col": 6}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 31, "col": 5}, - {"title": "Ricochet", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 31, "col": 8}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 31, "col": 1}, - {"title": "Satsujin", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 32, "col": 1}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 31, "col": 4}, - {"title": "Forbidden Art", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 32, "col": 4}, - {"image": "../media/atree/connect_line.png", "connector": true, "rotate": 0, "row": 31, "col": 7}, - {"title": "Jasmine Bloom", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 32, "col": 7}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 180, "row": 32, "col": 0}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 33, "col": 0}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 32, "col": 2}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 33, "col": 2}, - {"image": "../media/atree/connect_angle.png", "connector": true, "rotate": 270, "row": 32, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 33, "col": 5}, - {"title": "Text", "desc": "desc", "image": "../media/atree/node.png", "connector": false, "row": 33, "col": 8}, - ] -} \ No newline at end of file diff --git a/js/atree_constants_str_old.js b/js/atree_constants_str_old.js deleted file mode 100644 index b604ecc..0000000 --- a/js/atree_constants_str_old.js +++ /dev/null @@ -1,4160 +0,0 @@ -const atrees = -{ - "Archer": [ - { - "display_name": "Arrow Shield", - "desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)", - "archetype": "", - "archetype_req": 0, - "parents": ["Power Shots", "Cheaper Escape"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 9, - "col": 6 - }, - "properties": { - "duration": 60 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Arrow Shield", - "cost": 30, - "display_text": "Max Damage", - "base_spell": 4, - "spell_type": "damage", - "scaling": "spell", - "display": "", - "parts": [ - { - "name": "Shield Damage", - "type": "damage", - "multipliers": [90, 0, 0, 0, 0, 10] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Shield Damage": 2 - } - } - ] - } - ] - }, - - { - "display_name": "Escape", - "desc": "Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": ["Heart Shatter"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 7, - "col": 4 - }, - "properties": { - "aoe": 0, - "range": 0 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Escape", - "cost": 25, - "display_text": "Max Damage", - "base_spell": 2, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "None", - "type": "damage", - "multipliers": [0, 0, 0, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "None": 0 - } - } - ] - } - ] - }, - { - "display_name": "Arrow Bomb", - "desc": "Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)", - "archetype": "", - "archetype_req": 0, - "parents": [], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 0, - "col": 4 - }, - "properties": { - "aoe": 4.5, - "range": 26 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Arrow Bomb", - "cost": 50, - "display_text": "Average Damage", - "base_spell": 3, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Arrow Bomb", - "type": "damage", - "multipliers": [160, 0, 0, 0, 20, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Arrow Bomb": 1 - } - } - ] - } - ] - }, - { - "display_name": "Heart Shatter", - "desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.", - "archetype": "", - "archetype_req": 0, - "parents": ["Bow Proficiency I"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 4, - "col": 4 - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] - }, - { - - } - ] - }, - { - "display_name": "Fire Creep", - "desc": "Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.", - "archetype": "", - "archetype_req": 0, - "parents": ["Phantom Ray", "Fire Mastery", "Bryophyte Roots"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 16, - "col": 6 - }, - "properties": { - "aoe": 0.8, - "duration": 6 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [30, 0, 0, 0, 20, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fire Creep": 15 - } - } - ] - }, - { - "display_name": "Bryophyte Roots", - "desc": "When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.", - "archetype": "Trapper", - "archetype_req": 1, - "parents": ["Fire Creep", "Earth Mastery"], - "dependencies": ["Arrow Storm"], - "blockers": [], - "cost": 2, - "display": { - "row": 16, - "col": 8 - }, - "properties": { - "aoe": 2, - "duration": 5, - "slowness": 0.4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Bryophyte Roots", - "cost": 0, - "multipliers": [40, 20, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Nimble String", - "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", - "archetype": "", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Arrow Rain"], - "dependencies": ["Arrow Storm"], - "blockers": ["Phantom Ray"], - "cost": 2, - "display": { - "row": 15, - "col": 2 - }, - "properties": { - "shootspeed": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [-15, 0, 0, 0, 0, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Stream", - "cost": 0, - "hits": { - "Single Arrow": 8 - } - } - ] - }, - { - "display_name": "Arrow Storm", - "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", - "archetype": "", - "archetype_req": 0, - "parents": ["Double Shots", "Cheaper Escape"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 9, - "col": 2 - }, - "properties": { - "aoe": 0, - "range": 16 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Arrow Storm", - "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [30, 0, 10, 0, 0, 0] - }, - { - "name": "Single Stream", - "type": "total", - "hits": { - "Single Arrow": 8 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Stream": 2 - } - } - ] - } - ] - }, - { - "display_name": "Guardian Angels", - "desc": "Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)", - "archetype": "Boltslinger", - "archetype_req": 3, - "parents": ["Triple Shots", "Frenzy"], - "dependencies": ["Arrow Shield"], - "blockers": [], - "cost": 2, - "display": { - "row": 19, - "col": 1 - }, - "properties": { - "range": 4, - "duration": 60, - "shots": 8, - "count": 2 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Guardian Angels", - "cost": 30, - "display_text": "Total Damage Average", - "base_spell": 4, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [40, 0, 0, 0, 0, 20] - }, - { - "name": "Single Bow", - "type": "total", - "hits": { - "Single Arrow": 8 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Bow": 2 - } - } - ] - } - ] - }, - { - "display_name": "Windy Feet", - "base_abil": "Escape", - "desc": "When casting Escape, give speed to yourself and nearby allies.", - "archetype": "", - "archetype_req": 0, - "parents": ["Arrow Storm"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 10, - "col": 1 - }, - "properties": { - "aoe": 8, - "duration": 120 - }, - "type": "stat_bonus", - "bonuses": [ - { - "type": "stat", - "name": "spd", - "value": 20 - } - ] - }, - { - "display_name": "Basaltic Trap", - "desc": "When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)", - "archetype": "Trapper", - "archetype_req": 2, - "parents": ["Bryophyte Roots"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 19, - "col": 8 - }, - "properties": { - "aoe": 7, - "traps": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [140, 30, 0, 0, 30, 0] - } - ] - }, - { - "display_name": "Windstorm", - "desc": "Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.", - "archetype": "", - "archetype_req": 0, - "parents": ["Guardian Angels", "Cheaper Arrow Storm"], - "dependencies": [], - "blockers": ["Phantom Ray"], - "cost": 2, - "display": { - "row": 21, - "col": 1 - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [-11, 0, -7, 0, 0, 3] - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 1 - } - } - ] - }, - { - "display_name": "Grappling Hook", - "base_abil": "Escape", - "desc": "When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Focus", "More Shields", "Cheaper Arrow Storm"], - "dependencies": [], - "blockers": ["Escape Artist"], - "cost": 2, - "display": { - "row": 21, - "col": 5 - }, - "properties": { - "range": 20 - }, - "effects": [ - ] - }, - { - "display_name": "Implosion", - "desc": "Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Grappling Hook", "More Shields"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 22, - "col": 6 - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [40, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Twain's Arc", - "desc": "When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)", - "archetype": "Sharpshooter", - "archetype_req": 4, - "parents": ["More Focus", "Traveler"], - "dependencies": ["Focus"], - "blockers": [], - "cost": 2, - "display": { - "row": 25, - "col": 4 - }, - "properties": { - "range": 64, - "focusReq": 2 - }, - "effects": [ - - { - "type": "replace_spell", - "name": "Twain's Arc", - "cost": 0, - "display_text": "Twain's Arc", - "base_spell": 5, - "spell_type": "damage", - "scaling": "melee", - "display": "Twain's Arc Damage", - "parts": [ - { - "name": "Twain's Arc Damage", - "type": "damage", - "multipliers": [200, 0, 0, 0, 0, 0] - } - ] - } - ] - }, - { - "display_name": "Fierce Stomp", - "desc": "When using Escape, hold shift to quickly drop down and deal damage.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Refined Gunpowder", "Traveler"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 26, - "col": 1 - }, - "properties": { - "aoe": 4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fierce Stomp": 1 - } - } - ] - }, - { - "display_name": "Scorched Earth", - "desc": "Fire Creep become much stronger.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Twain's Arc"], - "dependencies": ["Fire Creep"], - "blockers": [], - "cost": 1, - "display": { - "row": 26 , - "col": 5 - }, - "properties": { - "duration": 2, - "aoe": 0.4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fire Creep", - "cost": 0, - "multipliers": [10, 0, 0, 0, 5, 0] - } - ] - }, - { - "display_name": "Leap", - "desc": "When you double tap jump, leap foward. (2s Cooldown)", - "archetype": "Boltslinger", - "archetype_req": 5, - "parents": ["Refined Gunpowder", "Homing Shots"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 0 - }, - "properties": { - "cooldown": 2 - }, - "effects": [ - - ] - }, - { - "display_name": "Shocking Bomb", - "desc": "Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.", - "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": ["Twain's Arc", "Better Arrow Shield", "Homing Shots"], - "dependencies": ["Arrow Bomb"], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 4 - }, - "properties": { - "gravity": 0 - }, - "effects": [ - { - "type": "convert_spell_conv", - "target_part": "all", - "conversion": "thunder" - } - ] - }, - { - "display_name": "Mana Trap", - "desc": "Your Traps will give you 4 Mana per second when you stay close to them.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": ["More Traps", "Better Arrow Shield"], - "dependencies": ["Fire Creep"], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 8 - }, - "properties": { - "range": 12, - "manaRegen": 4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 10, - "multipliers": [0, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Escape Artist", - "desc": "When casting Escape, release 100 arrows towards the ground.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Better Guardian Angels", "Leap"], - "dependencies": [], - "blockers": ["Grappling Hook"], - "cost": 2, - "display": { - "row": 31, - "col": 0 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Escape Artist", - "cost": 0, - "multipliers": [30, 0, 10, 0, 0, 0] - } - ] - }, - { - "display_name": "Initiator", - "desc": "If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.", - "archetype": "Sharpshooter", - "archetype_req": 5, - "parents": ["Shocking Bomb", "Better Arrow Shield", "Cheaper Arrow Storm (2)"], - "dependencies": ["Focus"], - "blockers": [], - "cost": 2, - "display": { - "row": 31, - "col": 5 - }, - "properties": { - "focus": 1, - "timer": 5 - }, - "type": "stat_bonus", - "bonuses": [ - { - "type": "stat", - "name": "damPct", - "value": 50 - } - ] - }, - { - "display_name": "Call of the Hound", - "desc": "Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Initiator", "Cheaper Arrow Storm (2)"], - "dependencies": ["Arrow Shield"], - "blockers": [], - "cost": 2, - "display": { - "row": 32, - "col": 7 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Call of the Hound", - "cost": 0, - "multipliers": [40, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Arrow Hurricane", - "desc": "Arrow Storm will shoot +2 stream of arrows.", - "archetype": "Boltslinger", - "archetype_req": 8, - "parents": ["Precise Shot", "Escape Artist"], - "dependencies": [], - "blockers": ["Phantom Ray"], - "cost": 2, - "display": { - "row": 33, - "col": 0 - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Stream": 2 - } - } - ] - }, - { - "display_name": "Geyser Stomp", - "desc": "Fierce Stomp will create geysers, dealing more damage and vertical knockback.", - "archetype": "", - "archetype_req": 0, - "parents": ["Shrapnel Bomb"], - "dependencies": ["Fierce Stomp"], - "blockers": [], - "cost": 2, - "display": { - "row": 37, - "col": 1 - }, - "properties": { - "aoe": 1 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Fierce Stomp", - "cost": 0, - "multipliers": [0, 0, 0, 50, 0, 0] - } - ] - }, - { - "display_name": "Crepuscular Ray", - "desc": "If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.", - "archetype": "Sharpshooter", - "archetype_req": 10, - "parents": ["Cheaper Arrow Shield"], - "dependencies": ["Arrow Storm"], - "blockers": [], - "cost": 2, - "display": { - "row": 37, - "col": 4 - }, - "properties": { - "focusReq": 5, - "focusRegen": -1 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Crepuscular Ray", - "base_spell": 5, - "spell_type": "damage", - "scaling": "spell", - "display": "One Focus", - "cost": 0, - - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [10, 0, 0, 5, 0, 0] - }, - { - "name": "One Focus", - "type": "total", - "hits": { - "Single Arrow": 20 - } - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "One Focus": 7 - } - } - ] - } - ] - }, - { - "display_name": "Grape Bomb", - "desc": "Arrow bomb will throw 3 additional smaller bombs when exploding.", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Escape (2)"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 37, - "col": 7 - }, - "properties": { - "miniBombs": 3, - "aoe": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Grape Bomb", - "cost": 0, - "multipliers": [30, 0, 0, 0, 10, 0] - } - ] - }, - { - "display_name": "Tangled Traps", - "desc": "Your Traps will be connected by a rope that deals damage to enemies every 0.2s.", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Grape Bomb"], - "dependencies": ["Basaltic Trap"], - "blockers": [], - "cost": 2, - "display": { - "row": 38, - "col": 6 - }, - "properties": { - "attackSpeed": 0.2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Tangled Traps", - "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 20] - } - ] - }, - { - "display_name": "Snow Storm", - "desc": "Enemies near you will be slowed down.", - "archetype": "", - "archetype_req": 0, - "parents": ["Geyser Stomp", "More Focus (2)"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 39, - "col": 2 - }, - "properties": { - "range": 2.5, - "slowness": 0.3 - } - }, - { - "display_name": "All-Seeing Panoptes", - "desc": "Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.", - "archetype": "Boltslinger", - "archetype_req": 11, - "parents": ["Snow Storm"], - "dependencies": ["Guardian Angels"], - "blockers": [], - "cost": 2, - "display": { - "row": 40, - "col": 1 - }, - "properties": { - "range": 10, - "shots": 5 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Arrow", - "cost": 0, - "multipliers": [0, 0, 0, 0, 20, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Bow", - "cost": 0, - "hits": { - "Single Arrow": 5 - } - } - ] - }, - { - "display_name": "Minefield", - "desc": "Allow you to place +6 Traps, but with reduced damage and range.", - "archetype": "Trapper", - "archetype_req": 10, - "parents": ["Grape Bomb", "Cheaper Arrow Bomb (2)"], - "dependencies": ["Basaltic Trap"], - "blockers": [], - "cost": 2, - "display": { - "row": 40, - "col": 7 - }, - "properties": { - "aoe": -2, - "traps": 6 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Basaltic Trap", - "cost": 0, - "multipliers": [-80, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Bow Proficiency I", - "desc": "Improve your Main Attack's damage and range when using a bow.", - "archetype": "", - "archetype_req": 0, - "parents": ["Arrow Bomb"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 2, - "col": 4 - }, - "properties": { - "mainAtk_range": 6 - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "mdPct", - "value": 5 - } - ] - } - ] - }, - { - "display_name": "Cheaper Arrow Bomb", - "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["Bow Proficiency I"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 2, - "col": 6 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "cost": -10 - } - ] - }, - { - "display_name": "Cheaper Arrow Storm", - "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": ["Grappling Hook", "Windstorm", "Focus"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 21, - "col": 3 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "cost": -5 - } - ] - }, - { - "display_name": "Cheaper Escape", - "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": ["Arrow Storm", "Arrow Shield"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 9, - "col": 4 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "cost": -5 - } - ] - }, - { - "display_name": "Earth Mastery", - "desc": "Increases your base damage from all Earth attacks", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Arrow Shield"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 13, - "col": 8 - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "eDamPct", - "value": 20 - }, - { - "type": "stat", - "name": "eDam", - "value": [2, 4] - } - ] - } - ] - }, - { - "display_name": "Thunder Mastery", - "desc": "Increases your base damage from all Thunder attacks", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Arrow Storm", "Fire Mastery"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 13, - "col": 2 - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "tDamPct", - "value": 10 - }, - { - "type": "stat", - "name": "tDam", - "value": [1, 8] - } - ] - } - ] - }, - { - "display_name": "Water Mastery", - "desc": "Increases your base damage from all Water attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Cheaper Escape", "Thunder Mastery", "Fire Mastery"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 14, - "col": 4 - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "wDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "wDam", - "value": [2, 4] - } - ] - } - ] - }, - { - "display_name": "Air Mastery", - "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Arrow Storm"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 13, - "col": 0 - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "aDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "aDam", - "value": [3, 4] - } - ] - } - ] - }, - { - "display_name": "Fire Mastery", - "desc": "Increases base damage from all Earth attacks", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Arrow Shield"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 13, - "col": 6 - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "fDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "fDam", - "value": [3, 5] - } - ] - } - ] - }, - { - "display_name": "More Shields", - "desc": "Give +2 charges to Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": ["Grappling Hook", "Basaltic Trap"], - "dependencies": ["Arrow Shield"], - "blockers": [], - "cost": 1, - "display": { - "row": 21, - "col": 7 - }, - "properties": { - "shieldCharges": 2 - } - }, - { - "display_name": "Stormy Feet", - "desc": "Windy Feet will last longer and add more speed.", - "archetype": "", - "archetype_req": 0, - "parents": ["Windstorm"], - "dependencies": ["Windy Feet"], - "blockers": [], - "cost": 1, - "display": { - "row": 23, - "col": 1 - }, - "properties": { - "duration": 60 - }, - "effects": [ - { - "type": "stat_bonus", - "bonuses": [ - { - "type": "stat", - "name": "spdPct", - "value": 20 - } - ] - } - ] - }, - { - "display_name": "Refined Gunpowder", - "desc": "Increase the damage of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["Windstorm"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 25, - "col": 0 - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Bomb", - "cost": 0, - "multipliers": [50, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "More Traps", - "desc": "Increase the maximum amount of active Traps you can have by +2.", - "archetype": "Trapper", - "archetype_req": 10, - "parents": ["Bouncing Bomb"], - "dependencies": ["Basaltic Trap"], - "blockers": [], - "cost": 1, - "display": { - "row": 26, - "col": 8 - }, - "properties": { - "traps": 2 - } - }, - { - "display_name": "Better Arrow Shield", - "desc": "Arrow Shield will gain additional area of effect, knockback and damage.", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Mana Trap", "Shocking Bomb", "Twain's Arc"], - "dependencies": ["Arrow Shield"], - "blockers": [], - "cost": 1, - "display": { - "row": 28, - "col": 6 - }, - "properties": { - "aoe": 1 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Arrow Shield", - "multipliers": [40, 0, 0, 0, 0, 0] - } - ] - }, - { - "display_name": "Better Leap", - "desc": "Reduce leap's cooldown by 1s.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Leap", "Homing Shots"], - "dependencies": ["Leap"], - "blockers": [], - "cost": 1, - "display": { - "row": 29, - "col": 1 - }, - "properties": { - "cooldown": -1 - } - }, - { - "display_name": "Better Guardian Angels", - "desc": "Your Guardian Angels can shoot +4 arrows before disappearing.", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Escape Artist", "Homing Shots"], - "dependencies": ["Guardian Angels"], - "blockers": [], - "cost": 1, - "display": { - "row": 31, - "col": 2 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Single Bow", - "cost": 0, - "hits": { - "Single Arrow": 4 - } - } - ] - }, - { - "display_name": "Cheaper Arrow Storm (2)", - "desc": "Reduce the Mana cost of Arrow Storm.", - "archetype": "", - "archetype_req": 0, - "parents": ["Initiator", "Mana Trap"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 31, - "col": 8 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "cost": -5 - } - ] - }, - { - "display_name": "Precise Shot", - "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Better Guardian Angels", "Cheaper Arrow Shield", "Arrow Hurricane"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 33, - "col": 2 - }, - "properties": { - "mainAtk_range": 6 - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "mdCritPct", - "value": 30 - } - ] - } - ] - }, - { - "display_name": "Cheaper Arrow Shield", - "desc": "Reduce the Mana cost of Arrow Shield.", - "archetype": "", - "archetype_req": 0, - "parents": ["Precise Shot", "Initiator"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 33, - "col": 4 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "cost": -5 - } - ] - }, - { - "display_name": "Rocket Jump", - "desc": "Arrow Bomb's self-damage will knockback you farther away.", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Arrow Storm (2)", "Initiator"], - "dependencies": ["Arrow Bomb"], - "blockers": [], - "cost": 1, - "display": { - "row": 33, - "col": 6 - }, - "properties": { - } - }, - { - "display_name": "Cheaper Escape (2)", - "desc": "Reduce the Mana cost of Escape.", - "archetype": "", - "archetype_req": 0, - "parents": ["Call of the Hound", "Decimator"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 34, - "col": 7 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "cost": -5 - } - ] - }, - { - "display_name": "Stronger Hook", - "desc": "Increase your Grappling Hook's range, speed and strength.", - "archetype": "Trapper", - "archetype_req": 5, - "parents": ["Cheaper Escape (2)"], - "dependencies": ["Grappling Hook"], - "blockers": [], - "cost": 1, - "display": { - "row": 35, - "col": 8 - }, - "properties": { - "range": 8 - } - }, - { - "display_name": "Cheaper Arrow Bomb (2)", - "desc": "Reduce the Mana cost of Arrow Bomb.", - "archetype": "", - "archetype_req": 0, - "parents": ["More Focus (2)", "Minefield"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 40, - "col": 5 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "cost": -5 - } - ] - }, - { - "display_name": "Bouncing Bomb", - "desc": "Arrow Bomb will bounce once when hitting a block or enemy", - "archetype": "", - "archetype_req": 0, - "parents": ["More Shields"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 25, - "col": 7 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Arrow Bomb": 2 - } - } - ] - }, - { - "display_name": "Homing Shots", - "desc": "Your Main Attack arrows will follow nearby enemies and not be affected by gravity", - "archetype": "", - "archetype_req": 0, - "parents": ["Leap", "Shocking Bomb"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 2 - }, - "properties": { - - }, - "effects": [ - - ] - }, - { - "display_name": "Shrapnel Bomb", - "desc": "Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area", - "archetype": "Boltslinger", - "archetype_req": 8, - "parents": ["Arrow Hurricane", "Precise Shot"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 34, - "col": 1 - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Shrapnel Bomb", - "cost": 0, - "multipliers": [40, 0, 0, 0, 20, 0] - } - ] - }, - { - "display_name": "Elusive", - "desc": "If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Geyser Stomp"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 38, - "col": 0 - }, - "properties": { - - }, - "effects": [ - - ] - }, - { - "display_name": "Double Shots", - "desc": "Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Escape"], - "dependencies": [], - "blockers": ["Power Shots"], - "cost": 1, - "display": { - "row": 7, - "col": 2 - }, - "properties": { - "arrow": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 0, - "target_part": "Melee Damage", - "cost": 0, - "multipliers": 0.7 - } - ] - }, - { - "display_name": "Triple Shots", - "desc": "Triple Main Attack arrows, but they deal -20% damage per arrow", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Arrow Rain", "Frenzy"], - "dependencies": ["Double Shots"], - "blockers": [], - "cost": 1, - "display": { - "row": 17, - "col": 0 - }, - "properties": { - "arrow": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 0, - "target_part": "Melee Damage", - "cost": 0, - "multipliers": 0.7 - } - ] - }, - { - "display_name": "Power Shots", - "desc": "Main Attack arrows have increased speed and knockback", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Escape"], - "dependencies": [], - "blockers": ["Double Shots"], - "cost": 1, - "display": { - "row": 7, - "col": 6 - }, - "properties": { - - }, - "effects": [ - - ] - }, - { - "display_name": "Focus", - "desc": "When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once", - "archetype": "Sharpshooter", - "archetype_req": 2, - "parents": ["Phantom Ray"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 19, - "col": 4 - }, - "properties": { - - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Focus", - "output": { - "type": "stat", - "abil_name": "Focus", - "name": "damMult" - }, - "scaling": [3], - "max": 3 - } - ] - }, - { - "display_name": "More Focus", - "desc": "Add +2 max Focus", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Cheaper Arrow Storm", "Grappling Hook"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 22, - "col": 4 - }, - "properties": { - - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Focus", - "output": { - "type": "stat", - "abil_name": "Focus", - "name": "damMult" - }, - "scaling": [35], - "max": 5 - } - ] - }, - { - "display_name": "More Focus (2)", - "desc": "Add +2 max Focus", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Crepuscular Ray", "Snow Storm"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 39, - "col": 4 - }, - "properties": { - - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Focus", - "output": { - "type": "stat", - "abil_name": "Focus", - "name": "damMult" - }, - "scaling": [35], - "max": 7 - } - ] - }, - { - "display_name": "Traveler", - "desc": "For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)", - "archetype": "", - "archetype_req": 0, - "parents": ["Refined Gunpowder", "Twain's Arc"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 25, - "col": 2 - }, - "properties": { - - }, - "effects": [ - { - "type": "stat_scaling", - "slider": false, - "inputs": [ - { - "type": "stat", - "name": "spd" - } - ], - "output": { - "type": "stat", - "name": "sdRaw" - }, - "scaling": [1], - "max": 100 - } - ] - }, - { - "display_name": "Patient Hunter", - "desc": "Your Traps will deal +20% more damage for every second they are active (Max +80%)", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["More Shields"], - "dependencies": ["Basaltic Trap"], - "blockers": [], - "cost": 2, - "display": { - "row": 22, - "col": 8 - }, - "properties": { - "max": 80 - }, - "effects": [ - - ] - }, - { - "display_name": "Stronger Patient Hunter", - "desc": "Add +80% Max Damage to Patient Hunter", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Grape Bomb"], - "dependencies": ["Patient Hunter"], - "blockers": [], - "cost": 1, - "display": { - "row": 38, - "col": 8 - }, - "properties": { - "max": 80 - }, - "effects": [ - - ] - }, - { - "display_name": "Frenzy", - "desc": "Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second", - "archetype": "Boltslinger", - "archetype_req": 0, - "parents": ["Triple Shots", "Nimble String"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 17, - "col": 2 - }, - "properties": { - - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Hits dealt", - "output": { - "type": "stat", - "name": "spd" - }, - "scaling": [6], - "max": 200 - } - ] - }, - { - "display_name": "Phantom Ray", - "desc": "Condense Arrow Storm into a single ray that damages enemies 10 times per second", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Water Mastery", "Fire Creep"], - "dependencies": ["Arrow Storm"], - "blockers": ["Windstorm", "Nimble String", "Arrow Hurricane"], - "cost": 2, - "display": { - "row": 16, - "col": 4 - }, - "properties": { - }, - "effects": [ - { - "type": "replace_spell", - "name": "Phantom Ray", - "cost": 40, - "display_text": "Max Damage", - "base_spell": 1, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Arrow", - "type": "damage", - "multipliers": [25, 0, 5, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Arrow": 16 - } - } - ] - } - ] - }, - { - "display_name": "Arrow Rain", - "desc": "When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies", - "archetype": "Trapper", - "archetype_req": 0, - "parents": ["Nimble String", "Air Mastery"], - "dependencies": ["Arrow Shield"], - "blockers": [], - "cost": 2, - "display": { - "row": 15, - "col": 0 - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Arrow Rain", - "cost": 0, - "multipliers": [120, 0, 0, 0, 0, 80] - } - ] - }, - { - "display_name": "Decimator", - "desc": "Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)", - "archetype": "Sharpshooter", - "archetype_req": 0, - "parents": ["Cheaper Arrow Shield"], - "dependencies": ["Phantom Ray"], - "blockers": [], - "cost": 1, - "display": { - "row": 34, - "col": 5 - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Phantom Ray hits", - "output": { - "type": "stat", - "name": "PhRayDmg" - }, - "scaling": 10, - "max": 50 - } - ] - } - ], - "Warrior": [ - { - "display_name": "Bash", - "desc": "Violently bash the ground, dealing high damage in a large area", - "archetype": "", - "archetype_req": 0, - "parents": [], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 0, - "col": 4, - "icon": "node_4" - }, - "properties": { - "aoe": 4, - "range": 3 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Bash", - "cost": 45, - "display_text": "Total Damage Average", - "base_spell": 1, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "Single Hit", - "type": "damage", - "multipliers": [130, 20, 0, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Single Hit": 1 - } - } - ] - } - ] - }, - { - "display_name": "Spear Proficiency 1", - "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": ["Bash"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 2, - "col": 4, - "icon": "node_0" - }, - "properties": { - "melee_range": 1 - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "mdPct", - "value": 5 - } - ] - } - ] - }, - - { - "display_name": "Cheaper Bash", - "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 1"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 2, - "col": 2, - "icon": "node_0" - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "cost": -10 - } - ] - }, - { - "display_name": "Double Bash", - "desc": "Bash will hit a second time at a farther range", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 1"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 4, - "col": 4, - "icon": "node_1" - }, - "properties": { - "range": 3 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "name": "Single Hit", - "value": 1 - } - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Hit", - "cost": 0, - "multipliers": [-50, 0, 0, 0, 0, 0] - } - ] - }, - - { - "display_name": "Charge", - "desc": "Charge forward at high speed (hold shift to cancel)", - "archetype": "", - "archetype_req": 0, - "parents": ["Double Bash"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 6, - "col": 4, - "icon": "node_4" - }, - "properties": { - }, - "effects": [ - { - "type": "replace_spell", - "name": "Charge", - "cost": 25, - "display_text": "Total Damage Average", - "base_spell": 2, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage", - "parts": [ - { - "name": "None", - "type": "damage", - "multipliers": [0, 0, 0, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "None": 0 - } - } - ] - } - ] - }, - - { - "display_name": "Heavy Impact", - "desc": "After using Charge, violently crash down into the ground and deal damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Uppercut"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 9, - "col": 1, - "icon": "node_1" - }, - "properties": { - "aoe": 4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Heavy Impact", - "cost": 0, - "multipliers": [100, 0, 0, 0, 0, 0] - } - ] - }, - - { - "display_name": "Vehement", - "desc": "For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Charge"], - "dependencies": [], - "blockers": ["Tougher Skin"], - "cost": 1, - "display": { - "row": 6, - "col": 2, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": false, - "inputs": [ - { - "type": "stat", - "name": "mdPct" - }, - { - "type": "stat", - "name": "mdRaw" - } - ], - "output": { - "type": "stat", - "name": "spd" - }, - "scaling": [1, 1], - "max": 20 - } - ] - }, - - { - "display_name": "Tougher Skin", - "desc": "Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Charge"], - "dependencies": [], - "blockers": ["Vehement"], - "cost": 1, - "display": { - "row": 6, - "col": 6, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "baseResist", - "value": "5" - } - ] - }, - { - "type": "stat_scaling", - "slider": false, - "inputs": [ - { - "type": "stat", - "name": "hprRaw" - }, - { - "type": "stat", - "name": "hprPct" - } - ], - "output": { - "type": "stat", - "name": "hpBonus" - }, - "scaling": [10, 10], - "max": 100 - } - ] - }, - - { - "display_name": "Uppercut", - "desc": "Rocket enemies in the air and deal massive damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Vehement"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 8, - "col": 2, - "icon": "node_4" - }, - "properties": { - "aoe": 3, - "range": 5 - }, - "effects": [ - { - "type": "replace_spell", - "name": "Uppercut", - "cost": 45, - "display_text": "Total Damage Average", - "base_spell": 3, - "spell_type": "damage", - "scaling": "spell", - "display": "total", - "parts": [ - { - "name": "Uppercut", - "type": "damage", - "multipliers": [150, 50, 50, 0, 0, 0] - }, - { - "name": "Total Damage", - "type": "total", - "hits": { - "Uppercut": 1 - } - } - ] - } - ] - }, - - { - "display_name": "Cheaper Charge", - "desc": "Reduce the Mana cost of Charge", - "archetype": "", - "archetype_req": 0, - "parents": ["Uppercut", "War Scream"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 8, - "col": 4, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "cost": -5 - } - ] - }, - - { - "display_name": "War Scream", - "desc": "Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies", - "archetype": "", - "archetype_req": 0, - "parents": ["Tougher Skin"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 8, - "col": 6, - "icon": "node_4" - }, - "properties": { - "duration": 30, - "aoe": 12, - "defense_bonus": 10 - }, - "effects": [ - { - "type": "replace_spell", - "name": "War Scream", - "cost": 35, - "display_text": "War Scream", - "base_spell": 4, - "spell_type": "damage", - "scaling": "spell", - "display": "Total Damage Average", - "parts": [ - { - "name": "War Scream", - "type": "damage", - "multipliers": [50, 0, 0, 0, 50, 0] - } - ] - } - ] - }, - - { - "display_name": "Earth Mastery", - "desc": "Increases base damage from all Earth attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uppercut"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 10, - "col": 0, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "eDamPct", - "value": 20 - }, - { - "type": "stat", - "name": "eDam", - "value": [2, 4] - } - ] - } - ] - }, - - { - "display_name": "Thunder Mastery", - "desc": "Increases base damage from all Thunder attacks", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uppercut", "Air Mastery", "Cheaper Charge"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 10, - "col": 2, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "tDamPct", - "value": 10 - }, - { - "type": "stat", - "name": "tDam", - "value": [1, 8] - } - ] - } - ] - }, - - { - "display_name": "Water Mastery", - "desc": "Increases base damage from all Water attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Cheaper Charge", "Thunder Mastery", "Air Mastery"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 11, - "col": 4, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "wDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "wDam", - "value": [2, 4] - } - ] - } - ] - }, - - { - "display_name": "Air Mastery", - "desc": "Increases base damage from all Air attacks", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["War Scream", "Thunder Mastery", "Cheaper Charge"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 10, - "col": 6, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "aDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "aDam", - "value": [3, 4] - } - ] - } - ] - }, - - { - "display_name": "Fire Mastery", - "desc": "Increases base damage from all Earth attacks", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["War Scream"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 10, - "col": 8, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "fDamPct", - "value": 15 - }, - { - "type": "stat", - "name": "fDam", - "value": [3, 5] - } - ] - } - ] - }, - - { - "display_name": "Quadruple Bash", - "desc": "Bash will hit 4 times at an even larger range", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Earth Mastery", "Fireworks"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 12, - "col": 0, - "icon": "node_1" - }, - "properties": { - "range": 6 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Single Hit": 2 - } - }, - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Hit", - "cost": 0, - "multipliers": [-20, 0, 0, 0, 0, 0] - } - ] - }, - - { - "display_name": "Fireworks", - "desc": "Mobs hit by Uppercut will explode mid-air and receive additional damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Thunder Mastery", "Quadruple Bash"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 12, - "col": 2, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Fireworks", - "cost": 0, - "multipliers": [80, 0, 20, 0, 0, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Fireworks": 1 - } - } - ] - }, - - { - "display_name": "Half-Moon Swipe", - "desc": "Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Water Mastery"], - "dependencies": ["Uppercut"], - "blockers": [], - "cost": 2, - "display": { - "row": 13, - "col": 4, - "icon": "node_1" - }, - "properties": { - "range": 4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Uppercut", - "cost": -10, - "multipliers": [-70, 0, 0, 0, 0, 0] - }, - { - "type": "convert_spell_conv", - "target_part": "all", - "conversion": "water" - } - ] - }, - - { - "display_name": "Flyby Jab", - "desc": "Damage enemies in your way when using Charge", - "archetype": "", - "archetype_req": 0, - "parents": ["Air Mastery", "Flaming Uppercut"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 12, - "col": 6, - "icon": "node_1" - }, - "properties": { - "aoe": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Flyby Jab", - "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 40] - } - ] - }, - - { - "display_name": "Flaming Uppercut", - "desc": "Uppercut will light mobs on fire, dealing damage every 0.6 seconds", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Fire Mastery", "Flyby Jab"], - "dependencies": ["Uppercut"], - "blockers": [], - "cost": 2, - "display": { - "row": 12, - "col": 8, - "icon": "node_1" - }, - "properties": { - "duration": 3, - "tick": 0.6 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Flaming Uppercut", - "cost": 0, - "multipliers": [0, 0, 0, 0, 50, 0] - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Flaming Uppercut Total Damage", - "cost": 0, - "hits": { - "Flaming Uppercut": 5 - } - }, - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Flaming Uppercut": 5 - } - } - ] - }, - - { - "display_name": "Iron Lungs", - "desc": "War Scream deals more damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Flyby Jab", "Flaming Uppercut"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 13, - "col": 7, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "War Scream", - "cost": 0, - "multipliers": [30, 0, 0, 0, 0, 30] - } - ] - }, - - { - "display_name": "Generalist", - "desc": "After casting 3 different spells in a row, your next spell will cost 5 mana", - "archetype": "Battle Monk", - "archetype_req": 3, - "parents": ["Counter"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 15, - "col": 2, - "icon": "node_3" - }, - "properties": { - }, - "effects": [ - - ] - }, - - { - "display_name": "Counter", - "desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Half-Moon Swipe"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 15, - "col": 4, - "icon": "node_1" - }, - "properties": { - "chance": 30 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 5, - "target_part": "Counter", - "cost": 0, - "multipliers": [60, 0, 20, 0, 0, 20] - } - ] - }, - - { - "display_name": "Mantle of the Bovemists", - "desc": "When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": ["Iron Lungs"], - "dependencies": ["War Scream"], - "blockers": [], - "cost": 2, - "display": { - "row": 15, - "col": 7, - "icon": "node_3" - }, - "properties": { - "mantle_charge": 3 - }, - "effects": [ - - ] - }, - - { - "display_name": "Bak'al's Grasp", - "desc": "After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)", - "archetype": "Fallen", - "archetype_req": 2, - "parents": ["Quadruple Bash", "Fireworks"], - "dependencies": ["War Scream"], - "blockers": [], - "cost": 2, - "display": { - "row": 16, - "col": 1, - "icon": "node_3" - }, - "properties": { - "cooldown": 15 - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Corrupted", - "output": { - "type": "stat", - "name": "raw" - }, - "scaling": [4], - "slider_step": 2, - "max": 120 - } - ] - }, - - { - "display_name": "Spear Proficiency 2", - "desc": "Improve your Main Attack's damage and range w/ spear", - "archetype": "", - "archetype_req": 0, - "parents": ["Bak'al's Grasp", "Cheaper Uppercut"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 17, - "col": 0, - "icon": "node_0" - }, - "properties": { - "melee_range": 1 - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "mdPct", - "value": 5 - } - ] - } - ] - }, - - { - "display_name": "Cheaper Uppercut", - "desc": "Reduce the Mana Cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": ["Spear Proficiency 2", "Aerodynamics", "Counter"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 17, - "col": 3, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "cost": -5 - } - ] - }, - - { - "display_name": "Aerodynamics", - "desc": "During Charge, you can steer and change direction", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Cheaper Uppercut", "Provoke"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 17, - "col": 5, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - - ] - }, - - { - "display_name": "Provoke", - "desc": "Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Aerodynamics", "Mantle of the Bovemists"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 17, - "col": 7, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "cost": -5 - } - ] - }, - - { - "display_name": "Precise Strikes", - "desc": "+30% Critical Hit Damage", - "archetype": "", - "archetype_req": 0, - "parents": ["Cheaper Uppercut", "Spear Proficiency 2"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 18, - "col": 2, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "critDmg", - "value": 30 - } - ] - } - ] - }, - - { - "display_name": "Air Shout", - "desc": "War Scream will fire a projectile that can go through walls and deal damage multiple times", - "archetype": "", - "archetype_req": 0, - "parents": ["Aerodynamics", "Provoke"], - "dependencies": ["War Scream"], - "blockers": [], - "cost": 2, - "display": { - "row": 18, - "col": 6, - "icon": "node_1" - }, - "properties": { - - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Air Shout", - "cost": 0, - "multipliers": [20, 0, 0, 0, 0, 5] - } - ] - }, - - { - "display_name": "Enraged Blow", - "desc": "While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Spear Proficiency 2"], - "dependencies": ["Bak'al's Grasp"], - "blockers": [], - "cost": 2, - "display": { - "row": 20, - "col": 0, - "icon": "node_2" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": false, - "inputs": [ - { - "type": "stat", - "name": "hpBonus" - } - ], - "output": { - "type": "stat", - "name": "damMult" - }, - "scaling": [3], - "max": 300 - } - ] - }, - - { - "display_name": "Flying Kick", - "desc": "When using Charge, mobs hit will halt your momentum and get knocked back", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Cheaper Uppercut", "Stronger Mantle"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 20, - "col": 3, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Flying Kick", - "cost": 0, - "multipliers": [120, 0, 0, 10, 0, 20] - } - ] - }, - - { - "display_name": "Stronger Mantle", - "desc": "Add +2 additional charges to Mantle of the Bovemists", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Manachism", "Flying Kick"], - "dependencies": ["Mantle of the Bovemists"], - "blockers": [], - "cost": 1, - "display": { - "row": 20, - "col": 6, - "icon": "node_0" - }, - "properties": { - "mantle_charge": 2 - }, - "effects": [ - - ] - }, - - { - "display_name": "Manachism", - "desc": "If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)", - "archetype": "Paladin", - "archetype_req": 3, - "parents": ["Stronger Mantle", "Provoke"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 20, - "col": 8, - "icon": "node_2" - }, - "properties": { - "cooldown": 1 - }, - "effects": [ - - ] - }, - - { - "display_name": "Boiling Blood", - "desc": "Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds", - "archetype": "", - "archetype_req": 0, - "parents": ["Enraged Blow", "Ragnarokkr"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 22, - "col": 0, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Boiling Blood", - "cost": 0, - "multipliers": [25, 0, 0, 0, 5, 0] - } - ] - }, - - { - "display_name": "Ragnarokkr", - "desc": "War Scream become deafening, increasing its range and giving damage bonus to players", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Boiling Blood", "Flying Kick"], - "dependencies": ["War Scream"], - "blockers": [], - "cost": 2, - "display": { - "row": 22, - "col": 2, - "icon": "node_2" - }, - "properties": { - "damage_bonus": 30, - "aoe": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "cost": 10 - } - ] - }, - - { - "display_name": "Ambidextrous", - "desc": "Increase your chance to attack with Counter by +30%", - "archetype": "", - "archetype_req": 0, - "parents": ["Flying Kick", "Stronger Mantle", "Burning Heart"], - "dependencies": ["Counter"], - "blockers": [], - "cost": 1, - "display": { - "row": 22, - "col": 4, - "icon": "node_0" - }, - "properties": { - "chance": 30 - }, - "effects": [ - - ] - }, - - { - "display_name": "Burning Heart", - "desc": "For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Ambidextrous", "Stronger Bash"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 22, - "col": 6, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": false, - "inputs": [ - { - "type": "stat", - "name": "hpBonus" - } - ], - "output": { - "type": "stat", - "name": "fDamPct" - }, - "scaling": [2], - "max": 100, - "slider_step": 100 - } - ] - }, - - { - "display_name": "Stronger Bash", - "desc": "Increase the damage of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Burning Heart", "Manachism"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 22, - "col": 8, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "target_part": "Single Hit", - "cost": 0, - "multipliers": [30, 0, 0, 0, 0, 0] - } - ] - }, - - { - "display_name": "Intoxicating Blood", - "desc": "After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted", - "archetype": "Fallen", - "archetype_req": 5, - "parents": ["Ragnarokkr", "Boiling Blood"], - "dependencies": ["Bak'al's Grasp"], - "blockers": [], - "cost": 2, - "display": { - "row": 23, - "col": 1, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - - ] - }, - - { - "display_name": "Comet", - "desc": "After being hit by Fireworks, enemies will crash into the ground and receive more damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Ragnarokkr"], - "dependencies": ["Fireworks"], - "blockers": [], - "cost": 2, - "display": { - "row": 24, - "col": 2, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Comet", - "cost": 0, - "multipliers": [80, 20, 0, 0, 0, 0] - }, - { - "type":"add_spell_prop", - "base_spell": 3, - "target_part": "Total Damage", - "cost": 0, - "hits": { - "Comet": 1 - } - } - ] - }, - - { - "display_name": "Collide", - "desc": "Mobs thrown into walls from Flying Kick will explode and receive additonal damage", - "archetype": "Battle Monk", - "archetype_req": 4, - "parents": ["Ambidextrous", "Burning Heart"], - "dependencies": ["Flying Kick"], - "blockers": [], - "cost": 2, - "display": { - "row": 23, - "col": 5, - "icon": "node_1" - }, - "properties": { - "aoe": 4 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "target_part": "Collide", - "cost": 0, - "multipliers": [100, 0, 0, 0, 50, 0] - } - ] - }, - - { - "display_name": "Rejuvenating Skin", - "desc": "Regain back 30% of the damage you take as healing over 30s", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Burning Heart", "Stronger Bash"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 23, - "col": 7, - "icon": "node_3" - }, - "properties": { - }, - "effects": [ - - ] - }, - - { - "display_name": "Uncontainable Corruption", - "desc": "Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1", - "archetype": "", - "archetype_req": 0, - "parents": ["Boiling Blood", "Radiant Devotee"], - "dependencies": ["Bak'al's Grasp"], - "blockers": [], - "cost": 1, - "display": { - "row": 26, - "col": 0, - "icon": "node_0" - }, - "properties": { - "cooldown": -5 - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Corrupted", - "output": { - "type": "stat", - "name": "raw" - }, - "scaling": [1], - "slider_step": 2, - "max": 50 - } - ] - }, - - { - "display_name": "Radiant Devotee", - "desc": "For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)", - "archetype": "Battle Monk", - "archetype_req": 1, - "parents": ["Whirlwind Strike", "Uncontainable Corruption"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 26, - "col": 2, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "inputs": [ - { - "type": "stat", - "name": "ref" - } - ], - "output": { - "type": "stat", - "name": "mr" - }, - "scaling": [1], - "max": 10, - "slider_step": 4 - } - ] - }, - - { - "display_name": "Whirlwind Strike", - "desc": "Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": ["Ambidextrous", "Radiant Devotee"], - "dependencies": ["Uppercut"], - "blockers": [], - "cost": 2, - "display": { - "row": 26, - "col": 4, - "icon": "node_1" - }, - "properties": { - "range": 2 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Uppercut", - "cost": 0, - "multipliers": [0, 0, 0, 0, 0, 50] - } - ] - }, - - { - "display_name": "Mythril Skin", - "desc": "Gain +5% Base Resistance and become immune to knockback", - "archetype": "Paladin", - "archetype_req": 6, - "parents": ["Rejuvenating Skin"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 26, - "col": 7, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "baseResist", - "value": 5 - } - ] - } - ] - }, - - { - "display_name": "Armour Breaker", - "desc": "While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Uncontainable Corruption", "Radiant Devotee"], - "dependencies": ["Bak'al's Grasp"], - "blockers": [], - "cost": 2, - "display": { - "row": 27, - "col": 1, - "icon": "node_2" - }, - "properties": { - "duration": 5 - }, - "effects": [ - - ] - }, - - { - "display_name": "Shield Strike", - "desc": "When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Mythril Skin", "Sparkling Hope"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 27, - "col": 6, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 5, - "target_part": "Shield Strike", - "cost": 0, - "multipliers": [60, 0, 20, 0, 0, 0] - } - ] - }, - - { - "display_name": "Sparkling Hope", - "desc": "Everytime you heal 5% of your max health, deal damage to all nearby enemies", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Mythril Skin"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 27, - "col": 8, - "icon": "node_2" - }, - "properties": { - "aoe": 6 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 5, - "target_part": "Sparkling Hope", - "cost": 0, - "multipliers": [10, 0, 5, 0, 0, 0] - } - ] - }, - - { - "display_name": "Massive Bash", - "desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)", - "archetype": "Fallen", - "archetype_req": 8, - "parents": ["Tempest", "Uncontainable Corruption"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 0, - "icon": "node_2" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Corrupted", - "output": { - "type": "stat", - "name": "bashAoE" - }, - "scaling": [1], - "max": 10, - "slider_step": 3 - } - ] - }, - - { - "display_name": "Tempest", - "desc": "War Scream will ripple the ground and deal damage 3 times in a large area", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Massive Bash", "Spirit of the Rabbit"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 28, - "col": 2, - "icon": "node_1" - }, - "properties": { - "aoe": 16 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Tempest", - "cost": "0", - "multipliers": [30, 10, 0, 0, 0, 10] - }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Tempest Total Damage", - "cost": "0", - "hits": { - "Tempest": 3 - } - }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Total Damage", - "cost": "0", - "hits": { - "Tempest": 3 - } - } - ] - }, - - { - "display_name": "Spirit of the Rabbit", - "desc": "Reduce the Mana cost of Charge and increase your Walk Speed by +20%", - "archetype": "Battle Monk", - "archetype_req": 5, - "parents": ["Tempest", "Whirlwind Strike"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 28, - "col": 4, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 2, - "cost": -5 - }, - { - "type": "raw_stat", - "bonuses": [ - { - "type": "stat", - "name": "spd", - "value": 20 - } - ] - } - ] - }, - - { - "display_name": "Massacre", - "desc": "While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar", - "archetype": "Fallen", - "archetype_req": 5, - "parents": ["Tempest", "Massive Bash"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 29, - "col": 1, - "icon": "node_1" - }, - "properties": { - }, - "effects": [ - - ] - }, - - { - "display_name": "Axe Kick", - "desc": "Increase the damage of Uppercut, but also increase its mana cost", - "archetype": "", - "archetype_req": 0, - "parents": ["Tempest", "Spirit of the Rabbit"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 29, - "col": 3, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "target_part": "Uppercut", - "cost": 10, - "multipliers": [100, 0, 0, 0, 0, 0] - } - ] - }, - - { - "display_name": "Radiance", - "desc": "Bash will buff your allies' positive IDs. (15s Cooldown)", - "archetype": "Paladin", - "archetype_req": 2, - "parents": ["Spirit of the Rabbit", "Cheaper Bash 2"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 29, - "col": 5, - "icon": "node_2" - }, - "properties": { - "cooldown": 15 - }, - "effects": [ - - ] - }, - - { - "display_name": "Cheaper Bash 2", - "desc": "Reduce the Mana cost of Bash", - "archetype": "", - "archetype_req": 0, - "parents": ["Radiance", "Shield Strike", "Sparkling Hope"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 29, - "col": 7, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 1, - "cost": -5 - } - ] - }, - - { - "display_name": "Cheaper War Scream", - "desc": "Reduce the Mana cost of War Scream", - "archetype": "", - "archetype_req": 0, - "parents": ["Massive Bash"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 31, - "col": 0, - "icon": "node_0" - }, - "properties": { - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "cost": -5 - } - ] - }, - - { - "display_name": "Discombobulate", - "desc": "Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second", - "archetype": "Battle Monk", - "archetype_req": 11, - "parents": ["Cyclone"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 31, - "col": 2, - "icon": "node_3" - }, - "properties": { - }, - "effects": [ - { - "type": "stat_scaling", - "slider": true, - "slider_name": "Hits dealt", - "output": { - "type": "stat", - "name": "rainrawButDifferent" - }, - "scaling": [2], - "max": 50 - } - ] - }, - - { - "display_name": "Thunderclap", - "desc": "Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder", - "archetype": "Battle Monk", - "archetype_req": 8, - "parents": ["Cyclone"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 32, - "col": 5, - "icon": "node_1" - }, - "properties": {}, - "effects": [ - { - "type": "convert_spell_conv", - "target_part": "all", - "conversion": "thunder" - }, - { - "type": "raw_stat", - "bonuses": [{ - "type": "prop", - "abil_name": "Bash", - "name": "aoe", - "value": 3 - }] - } - ] - }, - - { - "display_name": "Cyclone", - "desc": "After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s", - "archetype": "Battle Monk", - "archetype_req": 0, - "parents": ["Spirit of the Rabbit"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 31, - "col": 4, - "icon": "node_1" - }, - "properties": { - "aoe": 4, - "duration": 20 - }, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Cyclone", - "cost": 0, - "multipliers": [10, 0, 0, 0, 5, 10] - }, - { - "type": "add_spell_prop", - "base_spell": 4, - "target_part": "Cyclone Total Damage", - "cost": 0, - "hits": { - "Cyclone": 40 - } - - } - ] - }, - - { - "display_name": "Second Chance", - "desc": "When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)", - "archetype": "Paladin", - "archetype_req": 12, - "parents": ["Cheaper Bash 2"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 32, - "col": 7, - "icon": "node_3" - }, - "properties": {}, - "effects": [] - }, - - { - "display_name": "Blood Pact", - "desc": "If you do not have enough mana to cast a spell, spend health instead (1% health per mana)", - "archetype": "", - "archetype_req": 10, - "parents": ["Cheaper War Scream"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 34, - "col": 1, - "icon": "node_3" - }, - "properties": {}, - "effects": [] - }, - - { - "display_name": "Haemorrhage", - "desc": "Reduce Blood Pact's health cost. (0.5% health per mana)", - "archetype": "Fallen", - "archetype_req": 0, - "parents": ["Blood Pact"], - "dependencies": ["Blood Pact"], - "blockers": [], - "cost": 1, - "display": { - "row": 35, - "col": 2, - "icon": "node_1" - }, - "properties": {}, - "effects": [] - }, - - { - "display_name": "Brink of Madness", - "desc": "If your health is 25% full or less, gain +40% Resistance", - "archetype": "", - "archetype_req": 0, - "parents": ["Blood Pact", "Cheaper Uppercut 2"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 35, - "col": 4, - "icon": "node_2" - }, - "properties": {}, - "effects": [] - }, - - { - "display_name": "Cheaper Uppercut 2", - "desc": "Reduce the Mana cost of Uppercut", - "archetype": "", - "archetype_req": 0, - "parents": ["Second Chance", "Brink of Madness"], - "dependencies": [], - "blockers": [], - "cost": 1, - "display": { - "row": 35, - "col": 6, - "icon": "node_0" - }, - "properties": {}, - "effects": [ - { - "type": "add_spell_prop", - "base_spell": 3, - "cost": -5 - } - ] - }, - - { - "display_name": "Martyr", - "desc": "When you receive a fatal blow, all nearby allies become invincible", - "archetype": "Paladin", - "archetype_req": 0, - "parents": ["Second Chance"], - "dependencies": [], - "blockers": [], - "cost": 2, - "display": { - "row": 35, - "col": 8, - "icon": "node_1" - }, - "properties": { - "duration": 3, - "aoe": 12 - }, - "effects": [] - } - ], -} - -const atree_example = [ - { - "title": "skill", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 5, - "col": 3, - }, - { - "image": "../media/atree/connect_angle.png", - "connector": true, - "rotate": 270, - "row": 4, - "col": 3, - }, - { - "title": "skill2", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 0, - "col": 2 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 0, - "row": 1, - "col": 2 - }, - { - "title": "skill3", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 2, - "col": 2 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 90, - "row": 2, - "col": 3 - }, - { - "title": "skill4", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 2, - "col": 4 - }, - { - "image": "../media/atree/connect_line.png", - "connector": true, - "rotate": 0, - "row": 3, - "col": 2 - }, - { - "title": "skill5", - "desc": "desc", - "image": "../media/atree/node.png", - "connector": false, - "row": 4, - "col": 2 - }, -]; diff --git a/js/atree_constants_str_old_min.js b/js/atree_constants_str_old_min.js deleted file mode 100644 index 73d3e29..0000000 --- a/js/atree_constants_str_old_min.js +++ /dev/null @@ -1 +0,0 @@ -const atrees={Archer:[{display_name:"Arrow Shield",desc:"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",archetype:"",archetype_req:0,parents:["Power Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:6},properties:{duration:60},effects:[{type:"replace_spell",name:"Arrow Shield",cost:30,display_text:"Max Damage",base_spell:4,spell_type:"damage",scaling:"spell",display:"",parts:[{name:"Shield Damage",type:"damage",multipliers:[90,0,0,0,0,10]},{name:"Total Damage",type:"total",hits:{"Shield Damage":2}}]}]},{display_name:"Escape",desc:"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)",archetype:"",archetype_req:0,parents:["Heart Shatter"],dependencies:[],blockers:[],cost:1,display:{row:7,col:4},properties:{aoe:0,range:0},effects:[{type:"replace_spell",name:"Escape",cost:25,display_text:"Max Damage",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Arrow Bomb",desc:"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4},properties:{aoe:4.5,range:26},effects:[{type:"replace_spell",name:"Arrow Bomb",cost:50,display_text:"Average Damage",base_spell:3,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Arrow Bomb",type:"damage",multipliers:[160,0,0,0,20,0]},{name:"Total Damage",type:"total",hits:{"Arrow Bomb":1}}]}]},{display_name:"Heart Shatter",desc:"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[100,0,0,0,0,0]},{}]},{display_name:"Fire Creep",desc:"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.",archetype:"",archetype_req:0,parents:["Phantom Ray","Fire Mastery","Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:16,col:6},properties:{aoe:.8,duration:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[30,0,0,0,20,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Fire Creep":15}}]},{display_name:"Bryophyte Roots",desc:"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.",archetype:"Trapper",archetype_req:1,parents:["Fire Creep","Earth Mastery"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:16,col:8},properties:{aoe:2,duration:5,slowness:.4},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Bryophyte Roots",cost:0,multipliers:[40,20,0,0,0,0]}]},{display_name:"Nimble String",desc:"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.",archetype:"",archetype_req:0,parents:["Thunder Mastery","Arrow Rain"],dependencies:["Arrow Storm"],blockers:["Phantom Ray"],cost:2,display:{row:15,col:2},properties:{shootspeed:2},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-15,0,0,0,0,0]},{type:"add_spell_prop",base_spell:1,target_part:"Single Stream",cost:0,hits:{"Single Arrow":8}}]},{display_name:"Arrow Storm",desc:"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.",archetype:"",archetype_req:0,parents:["Double Shots","Cheaper Escape"],dependencies:[],blockers:[],cost:1,display:{row:9,col:2},properties:{aoe:0,range:16},effects:[{type:"replace_spell",name:"Arrow Storm",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[30,0,10,0,0,0]},{name:"Single Stream",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Stream":2}}]}]},{display_name:"Guardian Angels",desc:"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)",archetype:"Boltslinger",archetype_req:3,parents:["Triple Shots","Frenzy"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:19,col:1},properties:{range:4,duration:60,shots:8,count:2},effects:[{type:"replace_spell",name:"Guardian Angels",cost:30,display_text:"Total Damage Average",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[40,0,0,0,0,20]},{name:"Single Bow",type:"total",hits:{"Single Arrow":8}},{name:"Total Damage",type:"total",hits:{"Single Bow":2}}]}]},{display_name:"Windy Feet",base_abil:"Escape",desc:"When casting Escape, give speed to yourself and nearby allies.",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:10,col:1},properties:{aoe:8,duration:120},type:"stat_bonus",bonuses:[{type:"stat",name:"spd",value:20}]},{display_name:"Basaltic Trap",desc:"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)",archetype:"Trapper",archetype_req:2,parents:["Bryophyte Roots"],dependencies:[],blockers:[],cost:2,display:{row:19,col:8},properties:{aoe:7,traps:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[140,30,0,0,30,0]}]},{display_name:"Windstorm",desc:"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.",archetype:"",archetype_req:0,parents:["Guardian Angels","Cheaper Arrow Storm"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:21,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Arrow",cost:0,multipliers:[-11,0,-7,0,0,3]},{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":1}}]},{display_name:"Grappling Hook",base_abil:"Escape",desc:"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)",archetype:"Trapper",archetype_req:0,parents:["Focus","More Shields","Cheaper Arrow Storm"],dependencies:[],blockers:["Escape Artist"],cost:2,display:{row:21,col:5},properties:{range:20},effects:[]},{display_name:"Implosion",desc:"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.",archetype:"Trapper",archetype_req:0,parents:["Grappling Hook","More Shields"],dependencies:[],blockers:[],cost:2,display:{row:22,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Twain's Arc",desc:"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)",archetype:"Sharpshooter",archetype_req:4,parents:["More Focus","Traveler"],dependencies:["Focus"],blockers:[],cost:2,display:{row:25,col:4},properties:{range:64,focusReq:2},effects:[{type:"replace_spell",name:"Twain's Arc",cost:0,display_text:"Twain's Arc",base_spell:5,spell_type:"damage",scaling:"melee",display:"Twain's Arc Damage",parts:[{name:"Twain's Arc Damage",type:"damage",multipliers:[200,0,0,0,0,0]}]}]},{display_name:"Fierce Stomp",desc:"When using Escape, hold shift to quickly drop down and deal damage.",archetype:"Boltslinger",archetype_req:0,parents:["Refined Gunpowder","Traveler"],dependencies:[],blockers:[],cost:2,display:{row:26,col:1},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[100,0,0,0,0,0]},{type:"add_spell_prop",base_spell:2,target_part:"Total Damage",cost:0,hits:{"Fierce Stomp":1}}]},{display_name:"Scorched Earth",desc:"Fire Creep become much stronger.",archetype:"Sharpshooter",archetype_req:0,parents:["Twain's Arc"],dependencies:["Fire Creep"],blockers:[],cost:1,display:{row:26,col:5},properties:{duration:2,aoe:.4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fire Creep",cost:0,multipliers:[10,0,0,0,5,0]}]},{display_name:"Leap",desc:"When you double tap jump, leap foward. (2s Cooldown)",archetype:"Boltslinger",archetype_req:5,parents:["Refined Gunpowder","Homing Shots"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0},properties:{cooldown:2},effects:[]},{display_name:"Shocking Bomb",desc:"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.",archetype:"Sharpshooter",archetype_req:5,parents:["Twain's Arc","Better Arrow Shield","Homing Shots"],dependencies:["Arrow Bomb"],blockers:[],cost:2,display:{row:28,col:4},properties:{gravity:0},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"}]},{display_name:"Mana Trap",desc:"Your Traps will give you 4 Mana per second when you stay close to them.",archetype:"Trapper",archetype_req:5,parents:["More Traps","Better Arrow Shield"],dependencies:["Fire Creep"],blockers:[],cost:2,display:{row:28,col:8},properties:{range:12,manaRegen:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:10,multipliers:[0,0,0,0,0,0]}]},{display_name:"Escape Artist",desc:"When casting Escape, release 100 arrows towards the ground.",archetype:"Boltslinger",archetype_req:0,parents:["Better Guardian Angels","Leap"],dependencies:[],blockers:["Grappling Hook"],cost:2,display:{row:31,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Escape Artist",cost:0,multipliers:[30,0,10,0,0,0]}]},{display_name:"Initiator",desc:"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.",archetype:"Sharpshooter",archetype_req:5,parents:["Shocking Bomb","Better Arrow Shield","Cheaper Arrow Storm (2)"],dependencies:["Focus"],blockers:[],cost:2,display:{row:31,col:5},properties:{focus:1,timer:5},type:"stat_bonus",bonuses:[{type:"stat",name:"damPct",value:50}]},{display_name:"Call of the Hound",desc:"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.",archetype:"Trapper",archetype_req:0,parents:["Initiator","Cheaper Arrow Storm (2)"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:32,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Call of the Hound",cost:0,multipliers:[40,0,0,0,0,0]}]},{display_name:"Arrow Hurricane",desc:"Arrow Storm will shoot +2 stream of arrows.",archetype:"Boltslinger",archetype_req:8,parents:["Precise Shot","Escape Artist"],dependencies:[],blockers:["Phantom Ray"],cost:2,display:{row:33,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Stream":2}}]},{display_name:"Geyser Stomp",desc:"Fierce Stomp will create geysers, dealing more damage and vertical knockback.",archetype:"",archetype_req:0,parents:["Shrapnel Bomb"],dependencies:["Fierce Stomp"],blockers:[],cost:2,display:{row:37,col:1},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Fierce Stomp",cost:0,multipliers:[0,0,0,50,0,0]}]},{display_name:"Crepuscular Ray",desc:"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.",archetype:"Sharpshooter",archetype_req:10,parents:["Cheaper Arrow Shield"],dependencies:["Arrow Storm"],blockers:[],cost:2,display:{row:37,col:4},properties:{focusReq:5,focusRegen:-1},effects:[{type:"replace_spell",name:"Crepuscular Ray",base_spell:5,spell_type:"damage",scaling:"spell",display:"One Focus",cost:0,parts:[{name:"Single Arrow",type:"damage",multipliers:[10,0,0,5,0,0]},{name:"One Focus",type:"total",hits:{"Single Arrow":20}},{name:"Total Damage",type:"total",hits:{"One Focus":7}}]}]},{display_name:"Grape Bomb",desc:"Arrow bomb will throw 3 additional smaller bombs when exploding.",archetype:"",archetype_req:0,parents:["Cheaper Escape (2)"],dependencies:[],blockers:[],cost:2,display:{row:37,col:7},properties:{miniBombs:3,aoe:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Grape Bomb",cost:0,multipliers:[30,0,0,0,10,0]}]},{display_name:"Tangled Traps",desc:"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:38,col:6},properties:{attackSpeed:.2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Tangled Traps",cost:0,multipliers:[20,0,0,0,0,20]}]},{display_name:"Snow Storm",desc:"Enemies near you will be slowed down.",archetype:"",archetype_req:0,parents:["Geyser Stomp","More Focus (2)"],dependencies:[],blockers:[],cost:2,display:{row:39,col:2},properties:{range:2.5,slowness:.3}},{display_name:"All-Seeing Panoptes",desc:"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.",archetype:"Boltslinger",archetype_req:11,parents:["Snow Storm"],dependencies:["Guardian Angels"],blockers:[],cost:2,display:{row:40,col:1},properties:{range:10,shots:5},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Arrow",cost:0,multipliers:[0,0,0,0,20,0]},{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":5}}]},{display_name:"Minefield",desc:"Allow you to place +6 Traps, but with reduced damage and range.",archetype:"Trapper",archetype_req:10,parents:["Grape Bomb","Cheaper Arrow Bomb (2)"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:40,col:7},properties:{aoe:-2,traps:6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Basaltic Trap",cost:0,multipliers:[-80,0,0,0,0,0]}]},{display_name:"Bow Proficiency I",desc:"Improve your Main Attack's damage and range when using a bow.",archetype:"",archetype_req:0,parents:["Arrow Bomb"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Arrow Bomb",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Bow Proficiency I"],dependencies:[],blockers:[],cost:1,display:{row:2,col:6},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-10}]},{display_name:"Cheaper Arrow Storm",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Grappling Hook","Windstorm","Focus"],dependencies:[],blockers:[],cost:1,display:{row:21,col:3},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper Escape",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Arrow Storm","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:9,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Earth Mastery",desc:"Increases your base damage from all Earth attacks",archetype:"Trapper",archetype_req:0,parents:["Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:8},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases your base damage from all Thunder attacks",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Storm","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:13,col:2},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases your base damage from all Water attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Escape","Thunder Mastery","Fire Mastery"],dependencies:[],blockers:[],cost:1,display:{row:14,col:4},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["Arrow Storm"],dependencies:[],blockers:[],cost:1,display:{row:13,col:0},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Sharpshooter",archetype_req:0,parents:["Thunder Mastery","Arrow Shield"],dependencies:[],blockers:[],cost:1,display:{row:13,col:6},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"More Shields",desc:"Give +2 charges to Arrow Shield.",archetype:"",archetype_req:0,parents:["Grappling Hook","Basaltic Trap"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:21,col:7},properties:{shieldCharges:2}},{display_name:"Stormy Feet",desc:"Windy Feet will last longer and add more speed.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:["Windy Feet"],blockers:[],cost:1,display:{row:23,col:1},properties:{duration:60},effects:[{type:"stat_bonus",bonuses:[{type:"stat",name:"spdPct",value:20}]}]},{display_name:"Refined Gunpowder",desc:"Increase the damage of Arrow Bomb.",archetype:"",archetype_req:0,parents:["Windstorm"],dependencies:[],blockers:[],cost:1,display:{row:25,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Bomb",cost:0,multipliers:[50,0,0,0,0,0]}]},{display_name:"More Traps",desc:"Increase the maximum amount of active Traps you can have by +2.",archetype:"Trapper",archetype_req:10,parents:["Bouncing Bomb"],dependencies:["Basaltic Trap"],blockers:[],cost:1,display:{row:26,col:8},properties:{traps:2}},{display_name:"Better Arrow Shield",desc:"Arrow Shield will gain additional area of effect, knockback and damage.",archetype:"Sharpshooter",archetype_req:0,parents:["Mana Trap","Shocking Bomb","Twain's Arc"],dependencies:["Arrow Shield"],blockers:[],cost:1,display:{row:28,col:6},properties:{aoe:1},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Arrow Shield",multipliers:[40,0,0,0,0,0]}]},{display_name:"Better Leap",desc:"Reduce leap's cooldown by 1s.",archetype:"Boltslinger",archetype_req:0,parents:["Leap","Homing Shots"],dependencies:["Leap"],blockers:[],cost:1,display:{row:29,col:1},properties:{cooldown:-1}},{display_name:"Better Guardian Angels",desc:"Your Guardian Angels can shoot +4 arrows before disappearing.",archetype:"Boltslinger",archetype_req:0,parents:["Escape Artist","Homing Shots"],dependencies:["Guardian Angels"],blockers:[],cost:1,display:{row:31,col:2},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Single Bow",cost:0,hits:{"Single Arrow":4}}]},{display_name:"Cheaper Arrow Storm (2)",desc:"Reduce the Mana cost of Arrow Storm.",archetype:"",archetype_req:0,parents:["Initiator","Mana Trap"],dependencies:[],blockers:[],cost:1,display:{row:31,col:8},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Precise Shot",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Better Guardian Angels","Cheaper Arrow Shield","Arrow Hurricane"],dependencies:[],blockers:[],cost:1,display:{row:33,col:2},properties:{mainAtk_range:6},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdCritPct",value:30}]}]},{display_name:"Cheaper Arrow Shield",desc:"Reduce the Mana cost of Arrow Shield.",archetype:"",archetype_req:0,parents:["Precise Shot","Initiator"],dependencies:[],blockers:[],cost:1,display:{row:33,col:4},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Rocket Jump",desc:"Arrow Bomb's self-damage will knockback you farther away.",archetype:"",archetype_req:0,parents:["Cheaper Arrow Storm (2)","Initiator"],dependencies:["Arrow Bomb"],blockers:[],cost:1,display:{row:33,col:6},properties:{}},{display_name:"Cheaper Escape (2)",desc:"Reduce the Mana cost of Escape.",archetype:"",archetype_req:0,parents:["Call of the Hound","Decimator"],dependencies:[],blockers:[],cost:1,display:{row:34,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"Stronger Hook",desc:"Increase your Grappling Hook's range, speed and strength.",archetype:"Trapper",archetype_req:5,parents:["Cheaper Escape (2)"],dependencies:["Grappling Hook"],blockers:[],cost:1,display:{row:35,col:8},properties:{range:8}},{display_name:"Cheaper Arrow Bomb (2)",desc:"Reduce the Mana cost of Arrow Bomb.",archetype:"",archetype_req:0,parents:["More Focus (2)","Minefield"],dependencies:[],blockers:[],cost:1,display:{row:40,col:5},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Bouncing Bomb",desc:"Arrow Bomb will bounce once when hitting a block or enemy",archetype:"",archetype_req:0,parents:["More Shields"],dependencies:[],blockers:[],cost:2,display:{row:25,col:7},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Arrow Bomb":2}}]},{display_name:"Homing Shots",desc:"Your Main Attack arrows will follow nearby enemies and not be affected by gravity",archetype:"",archetype_req:0,parents:["Leap","Shocking Bomb"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2},properties:{},effects:[]},{display_name:"Shrapnel Bomb",desc:"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area",archetype:"Boltslinger",archetype_req:8,parents:["Arrow Hurricane","Precise Shot"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Shrapnel Bomb",cost:0,multipliers:[40,0,0,0,20,0]}]},{display_name:"Elusive",desc:"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)",archetype:"Boltslinger",archetype_req:0,parents:["Geyser Stomp"],dependencies:[],blockers:[],cost:2,display:{row:38,col:0},properties:{},effects:[]},{display_name:"Double Shots",desc:"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)",archetype:"Boltslinger",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Power Shots"],cost:1,display:{row:7,col:2},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Triple Shots",desc:"Triple Main Attack arrows, but they deal -20% damage per arrow",archetype:"Boltslinger",archetype_req:0,parents:["Arrow Rain","Frenzy"],dependencies:["Double Shots"],blockers:[],cost:1,display:{row:17,col:0},properties:{arrow:2},effects:[{type:"add_spell_prop",base_spell:0,target_part:"Melee Damage",cost:0,multipliers:.7}]},{display_name:"Power Shots",desc:"Main Attack arrows have increased speed and knockback",archetype:"Sharpshooter",archetype_req:0,parents:["Escape"],dependencies:[],blockers:["Double Shots"],cost:1,display:{row:7,col:6},properties:{},effects:[]},{display_name:"Focus",desc:"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once",archetype:"Sharpshooter",archetype_req:2,parents:["Phantom Ray"],dependencies:[],blockers:[],cost:2,display:{row:19,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:3}]},{display_name:"More Focus",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Storm","Grappling Hook"],dependencies:[],blockers:[],cost:1,display:{row:22,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:5}]},{display_name:"More Focus (2)",desc:"Add +2 max Focus",archetype:"Sharpshooter",archetype_req:0,parents:["Crepuscular Ray","Snow Storm"],dependencies:[],blockers:[],cost:1,display:{row:39,col:4},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Focus",output:{type:"stat",abil_name:"Focus",name:"dmgPct"},scaling:[35],max:7}]},{display_name:"Traveler",desc:"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)",archetype:"",archetype_req:0,parents:["Refined Gunpowder","Twain's Arc"],dependencies:[],blockers:[],cost:1,display:{row:25,col:2},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"spd"}],output:{type:"stat",name:"sdRaw"},scaling:[1],max:100}]},{display_name:"Patient Hunter",desc:"Your Traps will deal +20% more damage for every second they are active (Max +80%)",archetype:"Trapper",archetype_req:0,parents:["More Shields"],dependencies:["Basaltic Trap"],blockers:[],cost:2,display:{row:22,col:8},properties:{max:80},effects:[]},{display_name:"Stronger Patient Hunter",desc:"Add +80% Max Damage to Patient Hunter",archetype:"Trapper",archetype_req:0,parents:["Grape Bomb"],dependencies:["Patient Hunter"],blockers:[],cost:1,display:{row:38,col:8},properties:{max:80},effects:[]},{display_name:"Frenzy",desc:"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second",archetype:"Boltslinger",archetype_req:0,parents:["Triple Shots","Nimble String"],dependencies:[],blockers:[],cost:2,display:{row:17,col:2},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"spd"},scaling:[6],max:200}]},{display_name:"Phantom Ray",desc:"Condense Arrow Storm into a single ray that damages enemies 10 times per second",archetype:"Sharpshooter",archetype_req:0,parents:["Water Mastery","Fire Creep"],dependencies:["Arrow Storm"],blockers:["Windstorm","Nimble String","Arrow Hurricane"],cost:2,display:{row:16,col:4},properties:{},effects:[{type:"replace_spell",name:"Phantom Ray",cost:40,display_text:"Max Damage",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Arrow",type:"damage",multipliers:[25,0,5,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Arrow":16}}]}]},{display_name:"Arrow Rain",desc:"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies",archetype:"Trapper",archetype_req:0,parents:["Nimble String","Air Mastery"],dependencies:["Arrow Shield"],blockers:[],cost:2,display:{row:15,col:0},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Arrow Rain",cost:0,multipliers:[120,0,0,0,0,80]}]},{display_name:"Decimator",desc:"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)",archetype:"Sharpshooter",archetype_req:0,parents:["Cheaper Arrow Shield"],dependencies:["Phantom Ray"],blockers:[],cost:1,display:{row:34,col:5},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Phantom Ray hits",output:{type:"stat",name:"PhRayDmg"},scaling:10,max:50}]}],Warrior:[{display_name:"Bash",desc:"Violently bash the ground, dealing high damage in a large area",archetype:"",archetype_req:0,parents:[],dependencies:[],blockers:[],cost:1,display:{row:0,col:4,icon:"node_4"},properties:{aoe:4,range:3},effects:[{type:"replace_spell",name:"Bash",cost:45,display_text:"Total Damage Average",base_spell:1,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"Single Hit",type:"damage",multipliers:[130,20,0,0,0,0]},{name:"Total Damage",type:"total",hits:{"Single Hit":1}}]}]},{display_name:"Spear Proficiency 1",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bash"],dependencies:[],blockers:[],cost:1,display:{row:2,col:4,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Bash",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:2,col:2,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-10}]},{display_name:"Double Bash",desc:"Bash will hit a second time at a farther range",archetype:"",archetype_req:0,parents:["Spear Proficiency 1"],dependencies:[],blockers:[],cost:1,display:{row:4,col:4,icon:"node_1"},properties:{range:3},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{name:"Single Hit",value:1}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-50,0,0,0,0,0]}]},{display_name:"Charge",desc:"Charge forward at high speed (hold shift to cancel)",archetype:"",archetype_req:0,parents:["Double Bash"],dependencies:[],blockers:[],cost:1,display:{row:6,col:4,icon:"node_4"},properties:{},effects:[{type:"replace_spell",name:"Charge",cost:25,display_text:"Total Damage Average",base_spell:2,spell_type:"damage",scaling:"spell",display:"Total Damage",parts:[{name:"None",type:"damage",multipliers:[0,0,0,0,0,0]},{name:"Total Damage",type:"total",hits:{None:0}}]}]},{display_name:"Heavy Impact",desc:"After using Charge, violently crash down into the ground and deal damage",archetype:"",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:9,col:1,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Heavy Impact",cost:0,multipliers:[100,0,0,0,0,0]}]},{display_name:"Vehement",desc:"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)",archetype:"Fallen",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Tougher Skin"],cost:1,display:{row:6,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"mdPct"},{type:"stat",name:"mdRaw"}],output:{type:"stat",name:"spd"},scaling:[1,1],max:20}]},{display_name:"Tougher Skin",desc:"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)",archetype:"Paladin",archetype_req:0,parents:["Charge"],dependencies:[],blockers:["Vehement"],cost:1,display:{row:6,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:"5"}]},{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hprRaw"},{type:"stat",name:"hprPct"}],output:{type:"stat",name:"hpBonus"},scaling:[10,10],max:100}]},{display_name:"Uppercut",desc:"Rocket enemies in the air and deal massive damage",archetype:"",archetype_req:0,parents:["Vehement"],dependencies:[],blockers:[],cost:1,display:{row:8,col:2,icon:"node_4"},properties:{aoe:3,range:5},effects:[{type:"replace_spell",name:"Uppercut",cost:45,display_text:"Total Damage Average",base_spell:3,spell_type:"damage",scaling:"spell",display:"total",parts:[{name:"Uppercut",type:"damage",multipliers:[150,50,50,0,0,0]},{name:"Total Damage",type:"total",hits:{Uppercut:1}}]}]},{display_name:"Cheaper Charge",desc:"Reduce the Mana cost of Charge",archetype:"",archetype_req:0,parents:["Uppercut","War Scream"],dependencies:[],blockers:[],cost:1,display:{row:8,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5}]},{display_name:"War Scream",desc:"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies",archetype:"",archetype_req:0,parents:["Tougher Skin"],dependencies:[],blockers:[],cost:1,display:{row:8,col:6,icon:"node_4"},properties:{duration:30,aoe:12,defense_bonus:10},effects:[{type:"replace_spell",name:"War Scream",cost:35,display_text:"War Scream",base_spell:4,spell_type:"damage",scaling:"spell",display:"Total Damage Average",parts:[{name:"War Scream",type:"damage",multipliers:[50,0,0,0,50,0]}]}]},{display_name:"Earth Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:10,col:0,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"eDamPct",value:20},{type:"stat",name:"eDam",value:[2,4]}]}]},{display_name:"Thunder Mastery",desc:"Increases base damage from all Thunder attacks",archetype:"Fallen",archetype_req:0,parents:["Uppercut","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"tDamPct",value:10},{type:"stat",name:"tDam",value:[1,8]}]}]},{display_name:"Water Mastery",desc:"Increases base damage from all Water attacks",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Charge","Thunder Mastery","Air Mastery"],dependencies:[],blockers:[],cost:1,display:{row:11,col:4,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"wDamPct",value:15},{type:"stat",name:"wDam",value:[2,4]}]}]},{display_name:"Air Mastery",desc:"Increases base damage from all Air attacks",archetype:"Battle Monk",archetype_req:0,parents:["War Scream","Thunder Mastery"],dependencies:[],blockers:[],cost:1,display:{row:10,col:6,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"aDamPct",value:15},{type:"stat",name:"aDam",value:[3,4]}]}]},{display_name:"Fire Mastery",desc:"Increases base damage from all Earth attacks",archetype:"Paladin",archetype_req:0,parents:["War Scream"],dependencies:[],blockers:[],cost:1,display:{row:10,col:8,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"fDamPct",value:15},{type:"stat",name:"fDam",value:[3,5]}]}]},{display_name:"Quadruple Bash",desc:"Bash will hit 4 times at an even larger range",archetype:"Fallen",archetype_req:0,parents:["Earth Mastery","Fireworks"],dependencies:[],blockers:[],cost:2,display:{row:12,col:0,icon:"node_1"},properties:{range:6},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Total Damage",cost:0,hits:{"Single Hit":2}},{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[-20,0,0,0,0,0]}]},{display_name:"Fireworks",desc:"Mobs hit by Uppercut will explode mid-air and receive additional damage",archetype:"Fallen",archetype_req:0,parents:["Thunder Mastery","Quadruple Bash"],dependencies:[],blockers:[],cost:2,display:{row:12,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Fireworks",cost:0,multipliers:[80,0,20,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Fireworks:1}}]},{display_name:"Half-Moon Swipe",desc:"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water",archetype:"Battle Monk",archetype_req:1,parents:["Water Mastery"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:13,col:4,icon:"node_1"},properties:{range:4},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:-10,multipliers:[-70,0,0,0,0,0]},{type:"convert_spell_conv",target_part:"all",conversion:"water"}]},{display_name:"Flyby Jab",desc:"Damage enemies in your way when using Charge",archetype:"",archetype_req:0,parents:["Air Mastery","Flaming Uppercut"],dependencies:[],blockers:[],cost:2,display:{row:12,col:6,icon:"node_1"},properties:{aoe:2},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flyby Jab",cost:0,multipliers:[20,0,0,0,0,40]}]},{display_name:"Flaming Uppercut",desc:"Uppercut will light mobs on fire, dealing damage every 0.6 seconds",archetype:"Paladin",archetype_req:0,parents:["Fire Mastery","Flyby Jab"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:12,col:8,icon:"node_1"},properties:{duration:3,tick:.6},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut",cost:0,multipliers:[0,0,0,0,50,0]},{type:"add_spell_prop",base_spell:3,target_part:"Flaming Uppercut Total Damage",cost:0,hits:{"Flaming Uppercut":5}},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{"Flaming Uppercut":5}}]},{display_name:"Iron Lungs",desc:"War Scream deals more damage",archetype:"",archetype_req:0,parents:["Flyby Jab","Flaming Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:13,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"War Scream",cost:0,multipliers:[30,0,0,0,0,30]}]},{display_name:"Generalist",desc:"After casting 3 different spells in a row, your next spell will cost 5 mana",archetype:"Battle Monk",archetype_req:3,parents:["Counter"],dependencies:[],blockers:[],cost:2,display:{row:15,col:2,icon:"node_3"},properties:{},effects:[]},{display_name:"Counter",desc:"When dodging a nearby enemy attack, get 30% chance to instantly attack back",archetype:"Battle Monk",archetype_req:0,parents:["Half-Moon Swipe"],dependencies:[],blockers:[],cost:2,display:{row:15,col:4,icon:"node_1"},properties:{chance:30},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Counter",cost:0,multipliers:[60,0,20,0,0,20]}]},{display_name:"Mantle of the Bovemists",desc:"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)",archetype:"Paladin",archetype_req:3,parents:["Iron Lungs"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:15,col:7,icon:"node_3"},properties:{mantle_charge:3},effects:[]},{display_name:"Bak'al's Grasp",desc:"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)",archetype:"Fallen",archetype_req:2,parents:["Quadruple Bash","Fireworks"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:16,col:1,icon:"node_3"},properties:{cooldown:15},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[4],slider_step:2,max:120}]},{display_name:"Spear Proficiency 2",desc:"Improve your Main Attack's damage and range w/ spear",archetype:"",archetype_req:0,parents:["Bak'al's Grasp","Cheaper Uppercut"],dependencies:[],blockers:[],cost:1,display:{row:17,col:0,icon:"node_0"},properties:{melee_range:1},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"mdPct",value:5}]}]},{display_name:"Cheaper Uppercut",desc:"Reduce the Mana Cost of Uppercut",archetype:"",archetype_req:0,parents:["Spear Proficiency 2","Aerodynamics","Counter"],dependencies:[],blockers:[],cost:1,display:{row:17,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Aerodynamics",desc:"During Charge, you can steer and change direction",archetype:"Battle Monk",archetype_req:0,parents:["Cheaper Uppercut","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:17,col:5,icon:"node_1"},properties:{},effects:[]},{display_name:"Provoke",desc:"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream",archetype:"Paladin",archetype_req:0,parents:["Aerodynamics","Mantle of the Bovemists"],dependencies:[],blockers:[],cost:1,display:{row:17,col:7,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Precise Strikes",desc:"+30% Critical Hit Damage",archetype:"",archetype_req:0,parents:["Cheaper Uppercut","Spear Proficiency 2"],dependencies:[],blockers:[],cost:1,display:{row:18,col:2,icon:"node_0"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"critDmg",value:30}]}]},{display_name:"Air Shout",desc:"War Scream will fire a projectile that can go through walls and deal damage multiple times",archetype:"",archetype_req:0,parents:["Aerodynamics","Provoke"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:18,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Air Shout",cost:0,multipliers:[20,0,0,0,0,5]}]},{display_name:"Enraged Blow",desc:"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)",archetype:"Fallen",archetype_req:0,parents:["Spear Proficiency 2"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:20,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"dmgPct"},scaling:[2],max:200}]},{display_name:"Flying Kick",desc:"When using Charge, mobs hit will halt your momentum and get knocked back",archetype:"Battle Monk",archetype_req:1,parents:["Cheaper Uppercut","Stronger Mantle"],dependencies:[],blockers:[],cost:2,display:{row:20,col:3,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Flying Kick",cost:0,multipliers:[120,0,0,10,0,20]}]},{display_name:"Stronger Mantle",desc:"Add +2 additional charges to Mantle of the Bovemists",archetype:"Paladin",archetype_req:0,parents:["Manachism","Flying Kick"],dependencies:["Mantle of the Bovemists"],blockers:[],cost:1,display:{row:20,col:6,icon:"node_0"},properties:{mantle_charge:2},effects:[]},{display_name:"Manachism",desc:"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)",archetype:"Paladin",archetype_req:3,parents:["Stronger Mantle","Provoke"],dependencies:[],blockers:[],cost:2,display:{row:20,col:8,icon:"node_2"},properties:{cooldown:1},effects:[]},{display_name:"Boiling Blood",desc:"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds",archetype:"",archetype_req:0,parents:["Enraged Blow","Ragnarokkr"],dependencies:[],blockers:[],cost:2,display:{row:22,col:0,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Boiling Blood",cost:0,multipliers:[25,0,0,0,5,0]}]},{display_name:"Ragnarokkr",desc:"War Scream become deafening, increasing its range and giving damage bonus to players",archetype:"Fallen",archetype_req:0,parents:["Boiling Blood","Flying Kick"],dependencies:["War Scream"],blockers:[],cost:2,display:{row:22,col:2,icon:"node_2"},properties:{damage_bonus:30,aoe:2},effects:[{type:"add_spell_prop",base_spell:4,cost:10}]},{display_name:"Ambidextrous",desc:"Increase your chance to attack with Counter by +30%",archetype:"",archetype_req:0,parents:["Flying Kick","Stronger Mantle","Burning Heart"],dependencies:["Counter"],blockers:[],cost:1,display:{row:22,col:4,icon:"node_0"},properties:{chance:30},effects:[]},{display_name:"Burning Heart",desc:"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)",archetype:"Paladin",archetype_req:0,parents:["Ambidextrous","Stronger Bash"],dependencies:[],blockers:[],cost:1,display:{row:22,col:6,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",slider:!1,inputs:[{type:"stat",name:"hpBonus"}],output:{type:"stat",name:"fDamPct"},scaling:[2],max:100,slider_step:100}]},{display_name:"Stronger Bash",desc:"Increase the damage of Bash",archetype:"",archetype_req:0,parents:["Burning Heart","Manachism"],dependencies:[],blockers:[],cost:1,display:{row:22,col:8,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,target_part:"Single Hit",cost:0,multipliers:[30,0,0,0,0,0]}]},{display_name:"Intoxicating Blood",desc:"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted",archetype:"Fallen",archetype_req:5,parents:["Ragnarokkr","Boiling Blood"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:23,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Comet",desc:"After being hit by Fireworks, enemies will crash into the ground and receive more damage",archetype:"Fallen",archetype_req:0,parents:["Ragnarokkr"],dependencies:["Fireworks"],blockers:[],cost:2,display:{row:24,col:2,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Comet",cost:0,multipliers:[80,20,0,0,0,0]},{type:"add_spell_prop",base_spell:3,target_part:"Total Damage",cost:0,hits:{Comet:1}}]},{display_name:"Collide",desc:"Mobs thrown into walls from Flying Kick will explode and receive additonal damage",archetype:"Battle Monk",archetype_req:4,parents:["Ambidextrous","Burning Heart"],dependencies:["Flying Kick"],blockers:[],cost:2,display:{row:23,col:5,icon:"node_1"},properties:{aoe:4},effects:[{type:"add_spell_prop",base_spell:2,target_part:"Collide",cost:0,multipliers:[100,0,0,0,50,0]}]},{display_name:"Rejuvenating Skin",desc:"Regain back 30% of the damage you take as healing over 30s",archetype:"Paladin",archetype_req:0,parents:["Burning Heart","Stronger Bash"],dependencies:[],blockers:[],cost:2,display:{row:23,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Uncontainable Corruption",desc:"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1",archetype:"",archetype_req:0,parents:["Boiling Blood","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:1,display:{row:26,col:0,icon:"node_0"},properties:{cooldown:-5},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"raw"},scaling:[1],slider_step:2,max:50}]},{display_name:"Radiant Devotee",desc:"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)",archetype:"Battle Monk",archetype_req:1,parents:["Whirlwind Strike","Uncontainable Corruption"],dependencies:[],blockers:[],cost:1,display:{row:26,col:2,icon:"node_0"},properties:{},effects:[{type:"stat_scaling",inputs:[{type:"stat",name:"ref"}],output:{type:"stat",name:"mr"},scaling:[1],max:10,slider_step:4}]},{display_name:"Whirlwind Strike",desc:"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)",archetype:"Battle Monk",archetype_req:5,parents:["Ambidextrous","Radiant Devotee"],dependencies:["Uppercut"],blockers:[],cost:2,display:{row:26,col:4,icon:"node_1"},properties:{range:2},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:0,multipliers:[0,0,0,0,0,50]}]},{display_name:"Mythril Skin",desc:"Gain +5% Base Resistance and become immune to knockback",archetype:"Paladin",archetype_req:6,parents:["Rejuvenating Skin"],dependencies:[],blockers:[],cost:2,display:{row:26,col:7,icon:"node_1"},properties:{},effects:[{type:"raw_stat",bonuses:[{type:"stat",name:"baseResist",value:5}]}]},{display_name:"Armour Breaker",desc:"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage",archetype:"Fallen",archetype_req:0,parents:["Uncontainable Corruption","Radiant Devotee"],dependencies:["Bak'al's Grasp"],blockers:[],cost:2,display:{row:27,col:1,icon:"node_2"},properties:{duration:5},effects:[]},{display_name:"Shield Strike",desc:"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin","Sparkling Hope"],dependencies:[],blockers:[],cost:2,display:{row:27,col:6,icon:"node_1"},properties:{},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Shield Strike",cost:0,multipliers:[60,0,20,0,0,0]}]},{display_name:"Sparkling Hope",desc:"Everytime you heal 5% of your max health, deal damage to all nearby enemies",archetype:"Paladin",archetype_req:0,parents:["Mythril Skin"],dependencies:[],blockers:[],cost:2,display:{row:27,col:8,icon:"node_2"},properties:{aoe:6},effects:[{type:"add_spell_prop",base_spell:5,target_part:"Sparkling Hope",cost:0,multipliers:[10,0,5,0,0,0]}]},{display_name:"Massive Bash",desc:"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",archetype:"Fallen",archetype_req:8,parents:["Tempest","Uncontainable Corruption"],dependencies:[],blockers:[],cost:2,display:{row:28,col:0,icon:"node_2"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Corrupted",output:{type:"stat",name:"bashAoE"},scaling:[1],max:10,slider_step:3}]},{display_name:"Tempest",desc:"War Scream will ripple the ground and deal damage 3 times in a large area",archetype:"Battle Monk",archetype_req:0,parents:["Massive Bash","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:2,display:{row:28,col:2,icon:"node_1"},properties:{aoe:16},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Tempest",cost:"0",multipliers:[30,10,0,0,0,10]},{type:"add_spell_prop",base_spell:4,target_part:"Tempest Total Damage",cost:"0",hits:{Tempest:3}},{type:"add_spell_prop",base_spell:4,target_part:"Total Damage",cost:"0",hits:{Tempest:3}}]},{display_name:"Spirit of the Rabbit",desc:"Reduce the Mana cost of Charge and increase your Walk Speed by +20%",archetype:"Battle Monk",archetype_req:5,parents:["Tempest","Whirlwind Strike"],dependencies:[],blockers:[],cost:1,display:{row:28,col:4,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:2,cost:-5},{type:"raw_stat",bonuses:[{type:"stat",name:"spd",value:20}]}]},{display_name:"Massacre",desc:"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar",archetype:"Fallen",archetype_req:5,parents:["Tempest","Massive Bash"],dependencies:[],blockers:[],cost:2,display:{row:29,col:1,icon:"node_1"},properties:{},effects:[]},{display_name:"Axe Kick",desc:"Increase the damage of Uppercut, but also increase its mana cost",archetype:"",archetype_req:0,parents:["Tempest","Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:29,col:3,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,target_part:"Uppercut",cost:10,multipliers:[100,0,0,0,0,0]}]},{display_name:"Radiance",desc:"Bash will buff your allies' positive IDs. (15s Cooldown)",archetype:"Paladin",archetype_req:2,parents:["Spirit of the Rabbit","Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:29,col:5,icon:"node_2"},properties:{cooldown:15},effects:[]},{display_name:"Cheaper Bash 2",desc:"Reduce the Mana cost of Bash",archetype:"",archetype_req:0,parents:["Radiance","Shield Strike","Sparkling Hope"],dependencies:[],blockers:[],cost:1,display:{row:29,col:7,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:1,cost:-5}]},{display_name:"Cheaper War Scream",desc:"Reduce the Mana cost of War Scream",archetype:"",archetype_req:0,parents:["Massive Bash"],dependencies:[],blockers:[],cost:1,display:{row:31,col:0,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:4,cost:-5}]},{display_name:"Discombobulate",desc:"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second",archetype:"Battle Monk",archetype_req:12,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:31,col:2,icon:"node_3"},properties:{},effects:[{type:"stat_scaling",slider:!0,slider_name:"Hits dealt",output:{type:"stat",name:"rainrawButDifferent"},scaling:[2],max:50}]},{display_name:"Thunderclap",desc:"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder",archetype:"Battle Monk",archetype_req:8,parents:["Cyclone"],dependencies:[],blockers:[],cost:2,display:{row:32,col:5,icon:"node_1"},properties:{},effects:[{type:"convert_spell_conv",target_part:"all",conversion:"thunder"},{type:"raw_stat",bonuses:[{type:"prop",abil_name:"Bash",name:"aoe",value:3}]}]},{display_name:"Cyclone",desc:"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s",archetype:"Battle Monk",archetype_req:0,parents:["Spirit of the Rabbit"],dependencies:[],blockers:[],cost:1,display:{row:31,col:4,icon:"node_1"},properties:{aoe:4,duration:20},effects:[{type:"add_spell_prop",base_spell:4,target_part:"Cyclone",cost:0,multipliers:[10,0,0,0,5,10]},{type:"add_spell_prop",base_spell:4,target_part:"Cyclone Total Damage",cost:0,hits:{Cyclone:40}}]},{display_name:"Second Chance",desc:"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)",archetype:"Paladin",archetype_req:12,parents:["Cheaper Bash 2"],dependencies:[],blockers:[],cost:2,display:{row:32,col:7,icon:"node_3"},properties:{},effects:[]},{display_name:"Blood Pact",desc:"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)",archetype:"",archetype_req:10,parents:["Cheaper War Scream"],dependencies:[],blockers:[],cost:2,display:{row:34,col:1,icon:"node_3"},properties:{},effects:[]},{display_name:"Haemorrhage",desc:"Reduce Blood Pact's health cost. (0.5% health per mana)",archetype:"Fallen",archetype_req:0,parents:["Blood Pact"],dependencies:["Blood Pact"],blockers:[],cost:1,display:{row:35,col:2,icon:"node_1"},properties:{},effects:[]},{display_name:"Brink of Madness",desc:"If your health is 25% full or less, gain +40% Resistance",archetype:"",archetype_req:0,parents:["Blood Pact","Cheaper Uppercut 2"],dependencies:[],blockers:[],cost:2,display:{row:35,col:4,icon:"node_2"},properties:{},effects:[]},{display_name:"Cheaper Uppercut 2",desc:"Reduce the Mana cost of Uppercut",archetype:"",archetype_req:0,parents:["Second Chance","Brink of Madness"],dependencies:[],blockers:[],cost:1,display:{row:35,col:6,icon:"node_0"},properties:{},effects:[{type:"add_spell_prop",base_spell:3,cost:-5}]},{display_name:"Martyr",desc:"When you receive a fatal blow, all nearby allies become invincible",archetype:"Paladin",archetype_req:0,parents:["Second Chance"],dependencies:[],blockers:[],cost:2,display:{row:35,col:8,icon:"node_1"},properties:{duration:3,aoe:12},effects:[]}]},atree_example=[{title:"skill",desc:"desc",image:"../media/atree/node.png",connector:!1,row:5,col:3},{image:"../media/atree/connect_angle.png",connector:!0,rotate:270,row:4,col:3},{title:"skill2",desc:"desc",image:"../media/atree/node.png",connector:!1,row:0,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:1,col:2},{title:"skill3",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:2},{image:"../media/atree/connect_line.png",connector:!0,rotate:90,row:2,col:3},{title:"skill4",desc:"desc",image:"../media/atree/node.png",connector:!1,row:2,col:4},{image:"../media/atree/connect_line.png",connector:!0,rotate:0,row:3,col:2},{title:"skill5",desc:"desc",image:"../media/atree/node.png",connector:!1,row:4,col:2},] \ No newline at end of file From 2db1a3a336af5bfa6a01fbf8dea149050f9180bd Mon Sep 17 00:00:00 2001 From: ferricles Date: Mon, 27 Jun 2022 16:49:21 -0700 Subject: [PATCH 51/68] quick documentation + refactoring to add new param for render_AT() --- js/atree.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/js/atree.js b/js/atree.js index 47e80b3..63c75be 100644 --- a/js/atree.js +++ b/js/atree.js @@ -61,7 +61,7 @@ const atree_render = new (class extends ComputeNode { } //for some reason we have to cast to string - if (atree) { render_AT(document.getElementById("atree-ui"), atree); } + if (atree) { render_AT(document.getElementById("atree-ui"), document.getElementById("atree-active"), atree); } if (document.getElementById("toggle-atree").classList.contains("toggleOn")) { toggle_tab('atree-dropdown'); @@ -101,10 +101,17 @@ function topological_sort_tree(tree, res, mark_state) { // } } -function render_AT(elem, tree) { + +/** The main function for rendering an ability tree. + * + * @param {Element} UI_elem - the DOM element to draw the atree within. + * @param {Element} list_elem - the DOM element to list selected abilities within. + * @param {*} tree - the ability tree to work with. + */ +function render_AT(UI_elem, list_elem, tree) { console.log("constructing ability tree UI"); - document.getElementById("atree-active").innerHTML = ""; //reset all atree actives - should be done in a more general way later - elem.innerHTML = ""; //reset the atree in the DOM + list_elem.innerHTML = ""; //reset all atree actives - should be done in a more general way later + UI_elem.innerHTML = ""; //reset the atree in the DOM // add in the "Active" title to atree let active_row = document.createElement("div"); @@ -144,7 +151,7 @@ function render_AT(elem, tree) { active_row.appendChild(active_word); active_row.appendChild(active_AP_container); - document.getElementById("atree-active").appendChild(active_row); + list_elem.appendChild(active_row); let atree_map = new Map(); let atree_connectors_map = new Map() @@ -173,18 +180,17 @@ function render_AT(elem, tree) { let row = document.createElement('div'); row.classList.add("row"); row.id = "atree-row-" + j; - //was causing atree rows to be 0 height // TODO: do this more dynamically - row.style.minHeight = elem.scrollWidth / 9 + "px"; - //row.style.minHeight = elem.getBoundingClientRect().width / 9 + "px"; + row.style.minHeight = UI_elem.scrollWidth / 9 + "px"; + //row.style.minHeight = UI_elem.getBoundingClientRect().width / 9 + "px"; for (let k = 0; k < 9; k++) { col = document.createElement('div'); col.classList.add('col', 'px-0'); - col.style.minHeight = elem.scrollWidth / 9 + "px"; + col.style.minHeight = UI_elem.scrollWidth / 9 + "px"; row.appendChild(col); } - elem.appendChild(row); + UI_elem.appendChild(row); } for (const _node of tree) { @@ -258,8 +264,7 @@ function render_AT(elem, tree) { let active_tooltip = document.createElement('div'); active_tooltip.classList.add("rounded-bottom", "dark-4", "border", "p-0", "mx-2", "my-4", "dark-shadow"); - //was causing active element boxes to be 0 width - active_tooltip.style.maxWidth = elem.getBoundingClientRect().width * .80 + "px"; + active_tooltip.style.maxWidth = UI_elem.getBoundingClientRect().width * .80 + "px"; active_tooltip.style.display = "none"; // tooltip text formatting @@ -288,7 +293,7 @@ function render_AT(elem, tree) { node_tooltip.style.zIndex = "100"; node_elem.appendChild(node_tooltip); - document.getElementById("atree-active").appendChild(active_tooltip); + list_elem.appendChild(active_tooltip); node_elem.addEventListener('click', function(e) { if (e.target !== this && e.target!== this.children[0]) {return;} From e427532424e1184c900e2fd4e7d5767c006ac69e Mon Sep 17 00:00:00 2001 From: aspiepuppy Date: Mon, 27 Jun 2022 22:41:56 -0500 Subject: [PATCH 52/68] wa --- js/atree_constants.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/js/atree_constants.js b/js/atree_constants.js index cbd42b1..00f0a5a 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -225,7 +225,7 @@ const atrees = { }, { "display_name": "Nimble String", - "desc": "Arrow Storm throw out +8 arrows per stream and shoot twice as fast.", + "desc": "Arrow Storm throw out +6 arrows per stream and shoot twice as fast.", "archetype": "", "archetype_req": 0, "parents": ["Thunder Mastery", "Arrow Rain"], @@ -253,14 +253,14 @@ const atrees = { "target_part": "Single Stream", "cost": 0, "hits": { - "Single Arrow": 8 + "Single Arrow": 6 } } ] }, { "display_name": "Arrow Storm", - "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", + "desc": "Shoot one stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", "archetype": "", "archetype_req": 0, "parents": ["Double Shots", "Cheaper Escape"], @@ -302,7 +302,7 @@ const atrees = { "name": "Total Damage", "type": "total", "hits": { - "Single Stream": 2 + "Single Stream": 1 } } ] @@ -436,7 +436,7 @@ const atrees = { "base_spell": 1, "target_part": "Single Arrow", "cost": 0, - "multipliers": [-11, 0, -7, 0, 0, 3] + "multipliers": [-10, 0, -2, 0, 0, 2] }, { "type": "add_spell_prop", @@ -444,7 +444,16 @@ const atrees = { "target_part": "Total Damage", "cost": 0, "hits": { - "Single Stream": 1 + "Single Stream": 1 + } + }, + { + "type": "add_spell_prop", + "base_spell": 1, + "target_part": "Single Stream", + "cost": 0, + "hits": { + "Single Arrow": 2 } } ] @@ -928,7 +937,7 @@ const atrees = { "col": 1 }, "properties": { - "range": 10, + "range": 8, "shots": 5 }, "effects": [ @@ -937,7 +946,7 @@ const atrees = { "base_spell": 4, "target_part": "Single Arrow", "cost": 0, - "multipliers": [0, 0, 0, 0, 20, 0] + "multipliers": [0, 0, 0, 0, 10, 0] }, { "type": "add_spell_prop", From 1a14f230f2e5fdbfc9d66bd7d5dea3ffe3e8dd62 Mon Sep 17 00:00:00 2001 From: aspiepuppy Date: Mon, 27 Jun 2022 22:42:19 -0500 Subject: [PATCH 53/68] wawa --- js/atree_constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/atree_constants.js b/js/atree_constants.js index 00f0a5a..dbdc33a 100644 --- a/js/atree_constants.js +++ b/js/atree_constants.js @@ -260,7 +260,7 @@ const atrees = { }, { "display_name": "Arrow Storm", - "desc": "Shoot one stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", + "desc": "Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.", "archetype": "", "archetype_req": 0, "parents": ["Double Shots", "Cheaper Escape"], From f23895ee48cdf4e703d856d5a855ceec7f0db0ab Mon Sep 17 00:00:00 2001 From: hppeng Date: Mon, 27 Jun 2022 22:16:23 -0700 Subject: [PATCH 54/68] Address PR comments --- js/damage_calc.js | 4 ++-- js/display.js | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/js/damage_calc.js b/js/damage_calc.js index 9a18fbd..95d5f92 100644 --- a/js/damage_calc.js +++ b/js/damage_calc.js @@ -240,7 +240,7 @@ spell_heal: { const default_spells = { wand: [{ - name: "Magic Strike", // TODO: name for melee attacks? + name: "Wand Melee", // TODO: name for melee attacks? display_text: "Mage basic attack", base_spell: 0, scaling: "melee", use_atkspd: false, @@ -282,7 +282,7 @@ const default_spells = { parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }] }], relik: [{ - name: "Spread Beam", // TODO: name for melee attacks? + name: "Relik Melee", // TODO: name for melee attacks? display_text: "Shaman basic attack", base_spell: 0, spell_type: "damage", diff --git a/js/display.js b/js/display.js index 6f01d41..c3e52e4 100644 --- a/js/display.js +++ b/js/display.js @@ -1640,18 +1640,18 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell } for (let i = 0; i < spell_results.length; ++i) { - const damage_info = spell_results[i]; + const spell_info = spell_results[i]; let part_div = document.createElement("p"); parent_elem.append(part_div); let subtitle_elem = document.createElement("p"); - subtitle_elem.textContent = damage_info.name + subtitle_elem.textContent = spell_info.name part_div.append(subtitle_elem); - if (damage_info.type === "damage") { - let totalDamNormal = damage_info.normal_total; - let totalDamCrit = damage_info.crit_total; + if (spell_info.type === "damage") { + let totalDamNormal = spell_info.normal_total; + let totalDamCrit = spell_info.crit_total; let nonCritAverage = (totalDamNormal[0]+totalDamNormal[1])/2 || 0; let critAverage = (totalDamCrit[0]+totalDamCrit[1])/2 || 0; @@ -1663,8 +1663,8 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell part_div.append(averageLabel); - if (damage_info.name === spell.display) { - _summary(damage_info.name+ " Average: ", averageDamage, "Damage"); + if (spell_info.name === spell.display) { + _summary(spell_info.name+ " Average: ", averageDamage, "Damage"); } function _damage_display(label_text, average, dmg_min, dmg_max) { @@ -1681,16 +1681,16 @@ function displaySpellDamage(parent_elem, overallparent_elem, stats, spell, spell } } } - _damage_display("Non-Crit Average: ", nonCritAverage, damage_info.normal_min, damage_info.normal_max); - _damage_display("Crit Average: ", critAverage, damage_info.crit_min, damage_info.crit_max); - } else if (damage_info.type === "heal") { - let heal_amount = damage_info.heal_amount; + _damage_display("Non-Crit Average: ", nonCritAverage, spell_info.normal_min, spell_info.normal_max); + _damage_display("Crit Average: ", critAverage, spell_info.crit_min, spell_info.crit_max); + } else if (spell_info.type === "heal") { + let heal_amount = spell_info.heal_amount; let healLabel = document.createElement("p"); healLabel.textContent = heal_amount; // healLabel.classList.add("damagep"); part_div.append(healLabel); - if (damage_info.name === spell.display) { - _summary(damage_info.name+ ": ", heal_amount, "Set"); + if (spell_info.name === spell.display) { + _summary(spell_info.name+ ": ", heal_amount, "Set"); } } } From c5951195fea1501f52fa57aea581bdc023bde9bc Mon Sep 17 00:00:00 2001 From: reschan Date: Tue, 28 Jun 2022 13:01:36 +0700 Subject: [PATCH 55/68] bump latest change --- js/atree_constants_min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/atree_constants_min.js b/js/atree_constants_min.js index 52d1082..f3825a2 100644 --- a/js/atree_constants_min.js +++ b/js/atree_constants_min.js @@ -1 +1 @@ -const atrees={"Archer":[{"display_name":"Arrow Shield","desc":"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)","archetype":"","archetype_req":0,"parents":[60,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":6},"properties":{"duration":60},"effects":[{"type":"replace_spell","name":"Arrow Shield","cost":30,"display_text":"Max Damage","base_spell":4,"spell_type":"damage","scaling":"spell","display":"","parts":[{"name":"Shield Damage","type":"damage","multipliers":[90,0,0,0,0,10]},{"name":"Total Damage","type":"total","hits":{"Shield Damage":2}}]}],"id":0},{"display_name":"Escape","desc":"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":7,"col":4},"properties":{"aoe":0,"range":0},"effects":[{"type":"replace_spell","name":"Escape","cost":25,"display_text":"Max Damage","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":1},{"display_name":"Arrow Bomb","desc":"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4},"properties":{"aoe":4.5,"range":26},"effects":[{"type":"replace_spell","name":"Arrow Bomb","cost":50,"display_text":"Average Damage","base_spell":3,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Arrow Bomb","type":"damage","multipliers":[160,0,0,0,20,0]},{"name":"Total Damage","type":"total","hits":{"Arrow Bomb":1}}]}],"id":2},{"display_name":"Heart Shatter","desc":"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[100,0,0,0,0,0]},{}],"id":3},{"display_name":"Fire Creep","desc":"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.","archetype":"","archetype_req":0,"parents":[68,39,5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":16,"col":6},"properties":{"aoe":0.8,"duration":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[30,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fire Creep":15}}],"id":4},{"display_name":"Bryophyte Roots","desc":"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.","archetype":"Trapper","archetype_req":1,"parents":[4,35],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":16,"col":8},"properties":{"aoe":2,"duration":5,"slowness":0.4},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Bryophyte Roots","cost":0,"multipliers":[40,20,0,0,0,0]}],"id":5},{"display_name":"Nimble String","desc":"Arrow Storm throw out +8 arrows per stream and shoot twice as fast.","archetype":"","archetype_req":0,"parents":[36,69],"dependencies":[7],"blockers":[68],"cost":2,"display":{"row":15,"col":2},"properties":{"shootspeed":2},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-15,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":8}}],"id":6},{"display_name":"Arrow Storm","desc":"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.","archetype":"","archetype_req":0,"parents":[58,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":2},"properties":{"aoe":0,"range":16},"effects":[{"type":"replace_spell","name":"Arrow Storm","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,10,0,0,0]},{"name":"Single Stream","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Stream":2}}]}],"id":7},{"display_name":"Guardian Angels","desc":"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)","archetype":"Boltslinger","archetype_req":3,"parents":[59,67],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":19,"col":1},"properties":{"range":4,"duration":60,"shots":8,"count":2},"effects":[{"type":"replace_spell","name":"Guardian Angels","cost":30,"display_text":"Total Damage Average","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,0,0,0,10]},{"name":"Single Bow","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Bow":2}}]}],"id":8},{"display_name":"Windy Feet","base_abil":"Escape","desc":"When casting Escape, give speed to yourself and nearby allies.","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":1},"properties":{"aoe":8,"duration":120},"type":"stat_bonus","bonuses":[{"type":"stat","name":"spd","value":20}],"id":9},{"display_name":"Basaltic Trap","desc":"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)","archetype":"Trapper","archetype_req":2,"parents":[5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":8},"properties":{"aoe":7,"traps":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[140,30,0,0,30,0]}],"id":10},{"display_name":"Windstorm","desc":"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.","archetype":"","archetype_req":0,"parents":[8,33],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":21,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-11,0,-7,0,0,3]},{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":1}}],"id":11},{"display_name":"Grappling Hook","base_abil":"Escape","desc":"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)","archetype":"Trapper","archetype_req":0,"parents":[61,40,33],"dependencies":[],"blockers":[20],"cost":2,"display":{"row":21,"col":5},"properties":{"range":20},"effects":[],"id":12},{"display_name":"Implosion","desc":"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.","archetype":"Trapper","archetype_req":0,"parents":[12,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":13},{"display_name":"Twain's Arc","desc":"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)","archetype":"Sharpshooter","archetype_req":4,"parents":[62,64],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":25,"col":4},"properties":{"range":64,"focusReq":2},"effects":[{"type":"replace_spell","name":"Twain's Arc","cost":0,"display_text":"Twain's Arc","base_spell":5,"spell_type":"damage","scaling":"melee","display":"Twain's Arc Damage","parts":[{"name":"Twain's Arc Damage","type":"damage","multipliers":[200,0,0,0,0,0]}]}],"id":14},{"display_name":"Fierce Stomp","desc":"When using Escape, hold shift to quickly drop down and deal damage.","archetype":"Boltslinger","archetype_req":0,"parents":[42,64],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":1},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[100,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":2,"target_part":"Total Damage","cost":0,"hits":{"Fierce Stomp":1}}],"id":15},{"display_name":"Scorched Earth","desc":"Fire Creep become much stronger.","archetype":"Sharpshooter","archetype_req":0,"parents":[14],"dependencies":[4],"blockers":[],"cost":1,"display":{"row":26,"col":5},"properties":{"duration":2,"aoe":0.4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[10,0,0,0,5,0]}],"id":16},{"display_name":"Leap","desc":"When you double tap jump, leap foward. (2s Cooldown)","archetype":"Boltslinger","archetype_req":5,"parents":[42,55],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0},"properties":{"cooldown":2},"effects":[],"id":17},{"display_name":"Shocking Bomb","desc":"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.","archetype":"Sharpshooter","archetype_req":5,"parents":[14,44,55],"dependencies":[2],"blockers":[],"cost":2,"display":{"row":28,"col":4},"properties":{"gravity":0},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"}],"id":18},{"display_name":"Mana Trap","desc":"Your Traps will give you 4 Mana per second when you stay close to them.","archetype":"Trapper","archetype_req":5,"parents":[43,44],"dependencies":[4],"blockers":[],"cost":2,"display":{"row":28,"col":8},"properties":{"range":12,"manaRegen":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":10,"multipliers":[0,0,0,0,0,0]}],"id":19},{"display_name":"Escape Artist","desc":"When casting Escape, release 100 arrows towards the ground.","archetype":"Boltslinger","archetype_req":0,"parents":[46,17],"dependencies":[],"blockers":[12],"cost":2,"display":{"row":31,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Escape Artist","cost":0,"multipliers":[30,0,10,0,0,0]}],"id":20},{"display_name":"Initiator","desc":"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.","archetype":"Sharpshooter","archetype_req":5,"parents":[18,44,47],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":31,"col":5},"properties":{"focus":1,"timer":5},"type":"stat_bonus","bonuses":[{"type":"stat","name":"damPct","value":50}],"id":21},{"display_name":"Call of the Hound","desc":"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.","archetype":"Trapper","archetype_req":0,"parents":[21,47],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":32,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Call of the Hound","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":22},{"display_name":"Arrow Hurricane","desc":"Arrow Storm will shoot +2 stream of arrows.","archetype":"Boltslinger","archetype_req":8,"parents":[48,20],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":33,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":2}}],"id":23},{"display_name":"Geyser Stomp","desc":"Fierce Stomp will create geysers, dealing more damage and vertical knockback.","archetype":"","archetype_req":0,"parents":[56],"dependencies":[15],"blockers":[],"cost":2,"display":{"row":37,"col":1},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[0,0,0,50,0,0]}],"id":24},{"display_name":"Crepuscular Ray","desc":"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.","archetype":"Sharpshooter","archetype_req":10,"parents":[49],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":37,"col":4},"properties":{"focusReq":5,"focusRegen":-1},"effects":[{"type":"replace_spell","name":"Crepuscular Ray","base_spell":5,"spell_type":"damage","scaling":"spell","display":"One Focus","cost":0,"parts":[{"name":"Single Arrow","type":"damage","multipliers":[10,0,0,5,0,0]},{"name":"One Focus","type":"total","hits":{"Single Arrow":20}},{"name":"Total Damage","type":"total","hits":{"One Focus":7}}]}],"id":25},{"display_name":"Grape Bomb","desc":"Arrow bomb will throw 3 additional smaller bombs when exploding.","archetype":"","archetype_req":0,"parents":[51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":37,"col":7},"properties":{"miniBombs":3,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Grape Bomb","cost":0,"multipliers":[30,0,0,0,10,0]}],"id":26},{"display_name":"Tangled Traps","desc":"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":38,"col":6},"properties":{"attackSpeed":0.2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Tangled Traps","cost":0,"multipliers":[20,0,0,0,0,20]}],"id":27},{"display_name":"Snow Storm","desc":"Enemies near you will be slowed down.","archetype":"","archetype_req":0,"parents":[24,63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":39,"col":2},"properties":{"range":2.5,"slowness":0.3},"id":28},{"display_name":"All-Seeing Panoptes","desc":"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.","archetype":"Boltslinger","archetype_req":11,"parents":[28],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":40,"col":1},"properties":{"range":10,"shots":5},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Arrow","cost":0,"multipliers":[0,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":5}}],"id":29},{"display_name":"Minefield","desc":"Allow you to place +6 Traps, but with reduced damage and range.","archetype":"Trapper","archetype_req":10,"parents":[26,53],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":40,"col":7},"properties":{"aoe":-2,"traps":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[-80,0,0,0,0,0]}],"id":30},{"display_name":"Bow Proficiency I","desc":"Improve your Main Attack's damage and range when using a bow.","archetype":"","archetype_req":0,"parents":[2],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":31},{"display_name":"Cheaper Arrow Bomb","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-10}],"id":32},{"display_name":"Cheaper Arrow Storm","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[12,11,61],"dependencies":[],"blockers":[],"cost":1,"display":{"row":21,"col":3},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":33},{"display_name":"Cheaper Escape","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[7,0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":34},{"display_name":"Earth Mastery","desc":"Increases your base damage from all Earth attacks","archetype":"Trapper","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":8},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":35},{"display_name":"Thunder Mastery","desc":"Increases your base damage from all Thunder attacks","archetype":"Boltslinger","archetype_req":0,"parents":[7,39,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":2},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":36},{"display_name":"Water Mastery","desc":"Increases your base damage from all Water attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[34,36,39],"dependencies":[],"blockers":[],"cost":1,"display":{"row":14,"col":4},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":37},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":0},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":38},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[36,0,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":6},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":39},{"display_name":"More Shields","desc":"Give +2 charges to Arrow Shield.","archetype":"","archetype_req":0,"parents":[12,10],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":21,"col":7},"properties":{"shieldCharges":2},"id":40},{"display_name":"Stormy Feet","desc":"Windy Feet will last longer and add more speed.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[9],"blockers":[],"cost":1,"display":{"row":23,"col":1},"properties":{"duration":60},"effects":[{"type":"stat_bonus","bonuses":[{"type":"stat","name":"spdPct","value":20}]}],"id":41},{"display_name":"Refined Gunpowder","desc":"Increase the damage of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[50,0,0,0,0,0]}],"id":42},{"display_name":"More Traps","desc":"Increase the maximum amount of active Traps you can have by +2.","archetype":"Trapper","archetype_req":10,"parents":[54],"dependencies":[10],"blockers":[],"cost":1,"display":{"row":26,"col":8},"properties":{"traps":2},"id":43},{"display_name":"Better Arrow Shield","desc":"Arrow Shield will gain additional area of effect, knockback and damage.","archetype":"Sharpshooter","archetype_req":0,"parents":[19,18,14],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":28,"col":6},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Shield","multipliers":[40,0,0,0,0,0]}],"id":44},{"display_name":"Better Leap","desc":"Reduce leap's cooldown by 1s.","archetype":"Boltslinger","archetype_req":0,"parents":[17,55],"dependencies":[17],"blockers":[],"cost":1,"display":{"row":29,"col":1},"properties":{"cooldown":-1},"id":45},{"display_name":"Better Guardian Angels","desc":"Your Guardian Angels can shoot +4 arrows before disappearing.","archetype":"Boltslinger","archetype_req":0,"parents":[20,55],"dependencies":[8],"blockers":[],"cost":1,"display":{"row":31,"col":2},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":4}}],"id":46},{"display_name":"Cheaper Arrow Storm (2)","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[21,19],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":8},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":47},{"display_name":"Precise Shot","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[46,49,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":2},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdCritPct","value":30}]}],"id":48},{"display_name":"Cheaper Arrow Shield","desc":"Reduce the Mana cost of Arrow Shield.","archetype":"","archetype_req":0,"parents":[48,21],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":49},{"display_name":"Rocket Jump","desc":"Arrow Bomb's self-damage will knockback you farther away.","archetype":"","archetype_req":0,"parents":[47,21],"dependencies":[2],"blockers":[],"cost":1,"display":{"row":33,"col":6},"properties":{},"id":50},{"display_name":"Cheaper Escape (2)","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[22,70],"dependencies":[],"blockers":[],"cost":1,"display":{"row":34,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":51},{"display_name":"Stronger Hook","desc":"Increase your Grappling Hook's range, speed and strength.","archetype":"Trapper","archetype_req":5,"parents":[51],"dependencies":[12],"blockers":[],"cost":1,"display":{"row":35,"col":8},"properties":{"range":8},"id":52},{"display_name":"Cheaper Arrow Bomb (2)","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[63,30],"dependencies":[],"blockers":[],"cost":1,"display":{"row":40,"col":5},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":53},{"display_name":"Bouncing Bomb","desc":"Arrow Bomb will bounce once when hitting a block or enemy","archetype":"","archetype_req":0,"parents":[40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":25,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Arrow Bomb":2}}],"id":54},{"display_name":"Homing Shots","desc":"Your Main Attack arrows will follow nearby enemies and not be affected by gravity","archetype":"","archetype_req":0,"parents":[17,18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2},"properties":{},"effects":[],"id":55},{"display_name":"Shrapnel Bomb","desc":"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area","archetype":"Boltslinger","archetype_req":8,"parents":[23,48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Shrapnel Bomb","cost":0,"multipliers":[40,0,0,0,20,0]}],"id":56},{"display_name":"Elusive","desc":"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)","archetype":"Boltslinger","archetype_req":0,"parents":[24],"dependencies":[],"blockers":[],"cost":2,"display":{"row":38,"col":0},"properties":{},"effects":[],"id":57},{"display_name":"Double Shots","desc":"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)","archetype":"Boltslinger","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[60],"cost":1,"display":{"row":7,"col":2},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":58},{"display_name":"Triple Shots","desc":"Triple Main Attack arrows, but they deal -20% damage per arrow","archetype":"Boltslinger","archetype_req":0,"parents":[69,67],"dependencies":[58],"blockers":[],"cost":1,"display":{"row":17,"col":0},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":59},{"display_name":"Power Shots","desc":"Main Attack arrows have increased speed and knockback","archetype":"Sharpshooter","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[58],"cost":1,"display":{"row":7,"col":6},"properties":{},"effects":[],"id":60},{"display_name":"Focus","desc":"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once","archetype":"Sharpshooter","archetype_req":2,"parents":[68],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[3],"max":3}],"id":61},{"display_name":"More Focus","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[33,12],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":5}],"id":62},{"display_name":"More Focus (2)","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[25,28],"dependencies":[],"blockers":[],"cost":1,"display":{"row":39,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":7}],"id":63},{"display_name":"Traveler","desc":"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)","archetype":"","archetype_req":0,"parents":[42,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"spd"}],"output":{"type":"stat","name":"sdRaw"},"scaling":[1],"max":100}],"id":64},{"display_name":"Patient Hunter","desc":"Your Traps will deal +20% more damage for every second they are active (Max +80%)","archetype":"Trapper","archetype_req":0,"parents":[40],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":8},"properties":{"max":80},"effects":[],"id":65},{"display_name":"Stronger Patient Hunter","desc":"Add +80% Max Damage to Patient Hunter","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[65],"blockers":[],"cost":1,"display":{"row":38,"col":8},"properties":{"max":80},"effects":[],"id":66},{"display_name":"Frenzy","desc":"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second","archetype":"Boltslinger","archetype_req":0,"parents":[59,6],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"spd"},"scaling":[6],"max":200}],"id":67},{"display_name":"Phantom Ray","desc":"Condense Arrow Storm into a single ray that damages enemies 10 times per second","archetype":"Sharpshooter","archetype_req":0,"parents":[37,4],"dependencies":[7],"blockers":[11,6,23],"cost":2,"display":{"row":16,"col":4},"properties":{},"effects":[{"type":"replace_spell","name":"Phantom Ray","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[25,0,5,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Arrow":16}}]}],"id":68},{"display_name":"Arrow Rain","desc":"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies","archetype":"Trapper","archetype_req":0,"parents":[6,38],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":15,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Arrow Rain","cost":0,"multipliers":[120,0,0,0,0,80]}],"id":69},{"display_name":"Decimator","desc":"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)","archetype":"Sharpshooter","archetype_req":0,"parents":[49],"dependencies":[68],"blockers":[],"cost":1,"display":{"row":34,"col":5},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Phantom Ray hits","output":{"type":"stat","name":"PhRayDmg"},"scaling":10,"max":50}],"id":70}],"Warrior":[{"display_name":"Bash","desc":"Violently bash the ground, dealing high damage in a large area","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4,"icon":"node_4"},"properties":{"aoe":4,"range":3},"effects":[{"type":"replace_spell","name":"Bash","cost":45,"display_text":"Total Damage Average","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Hit","type":"damage","multipliers":[130,20,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Hit":1}}]}],"id":0},{"display_name":"Spear Proficiency 1","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":1},{"display_name":"Cheaper Bash","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-10}],"id":2},{"display_name":"Double Bash","desc":"Bash will hit a second time at a farther range","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4,"icon":"node_1"},"properties":{"range":3},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"name":"Single Hit","value":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-50,0,0,0,0,0]}],"id":3},{"display_name":"Charge","desc":"Charge forward at high speed (hold shift to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":6,"col":4,"icon":"node_4"},"properties":{},"effects":[{"type":"replace_spell","name":"Charge","cost":25,"display_text":"Total Damage Average","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":4},{"display_name":"Heavy Impact","desc":"After using Charge, violently crash down into the ground and deal damage","archetype":"","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":1,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Heavy Impact","cost":0,"multipliers":[100,0,0,0,0,0]}],"id":5},{"display_name":"Vehement","desc":"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)","archetype":"Fallen","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[7],"cost":1,"display":{"row":6,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"mdPct"},{"type":"stat","name":"mdRaw"}],"output":{"type":"stat","name":"spd"},"scaling":[1,1],"max":20}],"id":6},{"display_name":"Tougher Skin","desc":"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)","archetype":"Paladin","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[6],"cost":1,"display":{"row":6,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":"5"}]},{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hprRaw"},{"type":"stat","name":"hprPct"}],"output":{"type":"stat","name":"hpBonus"},"scaling":[10,10],"max":100}],"id":7},{"display_name":"Uppercut","desc":"Rocket enemies in the air and deal massive damage","archetype":"","archetype_req":0,"parents":[6],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":2,"icon":"node_4"},"properties":{"aoe":3,"range":5},"effects":[{"type":"replace_spell","name":"Uppercut","cost":45,"display_text":"Total Damage Average","base_spell":3,"spell_type":"damage","scaling":"spell","display":"total","parts":[{"name":"Uppercut","type":"damage","multipliers":[150,50,50,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Uppercut":1}}]}],"id":8},{"display_name":"Cheaper Charge","desc":"Reduce the Mana cost of Charge","archetype":"","archetype_req":0,"parents":[8,10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":9},{"display_name":"War Scream","desc":"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":6,"icon":"node_4"},"properties":{"duration":30,"aoe":12,"defense_bonus":10},"effects":[{"type":"replace_spell","name":"War Scream","cost":35,"display_text":"War Scream","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage Average","parts":[{"name":"War Scream","type":"damage","multipliers":[50,0,0,0,50,0]}]}],"id":10},{"display_name":"Earth Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Fallen","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":11},{"display_name":"Thunder Mastery","desc":"Increases base damage from all Thunder attacks","archetype":"Fallen","archetype_req":0,"parents":[8,14,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":12},{"display_name":"Water Mastery","desc":"Increases base damage from all Water attacks","archetype":"Battle Monk","archetype_req":0,"parents":[9,12,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":11,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":13},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[10,12,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":14},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Paladin","archetype_req":0,"parents":[10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":15},{"display_name":"Quadruple Bash","desc":"Bash will hit 4 times at an even larger range","archetype":"Fallen","archetype_req":0,"parents":[11,17],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":0,"icon":"node_1"},"properties":{"range":6},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Hit":2}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-20,0,0,0,0,0]}],"id":16},{"display_name":"Fireworks","desc":"Mobs hit by Uppercut will explode mid-air and receive additional damage","archetype":"Fallen","archetype_req":0,"parents":[12,16],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fireworks","cost":0,"multipliers":[80,0,20,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fireworks":1}}],"id":17},{"display_name":"Half-Moon Swipe","desc":"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water","archetype":"Battle Monk","archetype_req":1,"parents":[13],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":13,"col":4,"icon":"node_1"},"properties":{"range":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":-10,"multipliers":[-70,0,0,0,0,0]},{"type":"convert_spell_conv","target_part":"all","conversion":"water"}],"id":18},{"display_name":"Flyby Jab","desc":"Damage enemies in your way when using Charge","archetype":"","archetype_req":0,"parents":[14,20],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":6,"icon":"node_1"},"properties":{"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flyby Jab","cost":0,"multipliers":[20,0,0,0,0,40]}],"id":19},{"display_name":"Flaming Uppercut","desc":"Uppercut will light mobs on fire, dealing damage every 0.6 seconds","archetype":"Paladin","archetype_req":0,"parents":[15,19],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":12,"col":8,"icon":"node_1"},"properties":{"duration":3,"tick":0.6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut","cost":0,"multipliers":[0,0,0,0,50,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut Total Damage","cost":0,"hits":{"Flaming Uppercut":5}},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Flaming Uppercut":5}}],"id":20},{"display_name":"Iron Lungs","desc":"War Scream deals more damage","archetype":"","archetype_req":0,"parents":[19,20],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"War Scream","cost":0,"multipliers":[30,0,0,0,0,30]}],"id":21},{"display_name":"Generalist","desc":"After casting 3 different spells in a row, your next spell will cost 5 mana","archetype":"Battle Monk","archetype_req":3,"parents":[23],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":2,"icon":"node_3"},"properties":{},"effects":[],"id":22},{"display_name":"Counter","desc":"When dodging a nearby enemy attack, get 30% chance to instantly attack back","archetype":"Battle Monk","archetype_req":0,"parents":[18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":4,"icon":"node_1"},"properties":{"chance":30},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Counter","cost":0,"multipliers":[60,0,20,0,0,20]}],"id":23},{"display_name":"Mantle of the Bovemists","desc":"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)","archetype":"Paladin","archetype_req":3,"parents":[21],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":15,"col":7,"icon":"node_3"},"properties":{"mantle_charge":3},"effects":[],"id":24},{"display_name":"Bak'al's Grasp","desc":"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)","archetype":"Fallen","archetype_req":2,"parents":[16,17],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":16,"col":1,"icon":"node_3"},"properties":{"cooldown":15},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[4],"slider_step":2,"max":120}],"id":25},{"display_name":"Spear Proficiency 2","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[25,27],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":0,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":26},{"display_name":"Cheaper Uppercut","desc":"Reduce the Mana Cost of Uppercut","archetype":"","archetype_req":0,"parents":[26,28,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":27},{"display_name":"Aerodynamics","desc":"During Charge, you can steer and change direction","archetype":"Battle Monk","archetype_req":0,"parents":[27,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":5,"icon":"node_1"},"properties":{},"effects":[],"id":28},{"display_name":"Provoke","desc":"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream","archetype":"Paladin","archetype_req":0,"parents":[28,24],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":29},{"display_name":"Precise Strikes","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[27,26],"dependencies":[],"blockers":[],"cost":1,"display":{"row":18,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"critDmg","value":30}]}],"id":30},{"display_name":"Air Shout","desc":"War Scream will fire a projectile that can go through walls and deal damage multiple times","archetype":"","archetype_req":0,"parents":[28,29],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":18,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Air Shout","cost":0,"multipliers":[20,0,0,0,0,5]}],"id":31},{"display_name":"Enraged Blow","desc":"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)","archetype":"Fallen","archetype_req":0,"parents":[26],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":20,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"damMult"},"scaling":[3],"max":300}],"id":32},{"display_name":"Flying Kick","desc":"When using Charge, mobs hit will halt your momentum and get knocked back","archetype":"Battle Monk","archetype_req":1,"parents":[27,34],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":3,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flying Kick","cost":0,"multipliers":[120,0,0,10,0,20]}],"id":33},{"display_name":"Stronger Mantle","desc":"Add +2 additional charges to Mantle of the Bovemists","archetype":"Paladin","archetype_req":0,"parents":[35,33],"dependencies":[24],"blockers":[],"cost":1,"display":{"row":20,"col":6,"icon":"node_0"},"properties":{"mantle_charge":2},"effects":[],"id":34},{"display_name":"Manachism","desc":"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)","archetype":"Paladin","archetype_req":3,"parents":[34,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":8,"icon":"node_2"},"properties":{"cooldown":1},"effects":[],"id":35},{"display_name":"Boiling Blood","desc":"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds","archetype":"","archetype_req":0,"parents":[32,37],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":0,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Boiling Blood","cost":0,"multipliers":[25,0,0,0,5,0]}],"id":36},{"display_name":"Ragnarokkr","desc":"War Scream become deafening, increasing its range and giving damage bonus to players","archetype":"Fallen","archetype_req":0,"parents":[36,33],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":2,"icon":"node_2"},"properties":{"damage_bonus":30,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":10}],"id":37},{"display_name":"Ambidextrous","desc":"Increase your chance to attack with Counter by +30%","archetype":"","archetype_req":0,"parents":[33,34,39],"dependencies":[23],"blockers":[],"cost":1,"display":{"row":22,"col":4,"icon":"node_0"},"properties":{"chance":30},"effects":[],"id":38},{"display_name":"Burning Heart","desc":"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)","archetype":"Paladin","archetype_req":0,"parents":[38,40],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":!1,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"fDamPct"},"scaling":[2],"max":100,"slider_step":100}],"id":39},{"display_name":"Stronger Bash","desc":"Increase the damage of Bash","archetype":"","archetype_req":0,"parents":[39,35],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[30,0,0,0,0,0]}],"id":40},{"display_name":"Intoxicating Blood","desc":"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted","archetype":"Fallen","archetype_req":5,"parents":[37,36],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":23,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":41},{"display_name":"Comet","desc":"After being hit by Fireworks, enemies will crash into the ground and receive more damage","archetype":"Fallen","archetype_req":0,"parents":[37],"dependencies":[17],"blockers":[],"cost":2,"display":{"row":24,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Comet","cost":0,"multipliers":[80,20,0,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Comet":1}}],"id":42},{"display_name":"Collide","desc":"Mobs thrown into walls from Flying Kick will explode and receive additonal damage","archetype":"Battle Monk","archetype_req":4,"parents":[38,39],"dependencies":[33],"blockers":[],"cost":2,"display":{"row":23,"col":5,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Collide","cost":0,"multipliers":[100,0,0,0,50,0]}],"id":43},{"display_name":"Rejuvenating Skin","desc":"Regain back 30% of the damage you take as healing over 30s","archetype":"Paladin","archetype_req":0,"parents":[39,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":23,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":44},{"display_name":"Uncontainable Corruption","desc":"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1","archetype":"","archetype_req":0,"parents":[36,46],"dependencies":[25],"blockers":[],"cost":1,"display":{"row":26,"col":0,"icon":"node_0"},"properties":{"cooldown":-5},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[1],"slider_step":2,"max":50}],"id":45},{"display_name":"Radiant Devotee","desc":"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)","archetype":"Battle Monk","archetype_req":1,"parents":[47,45],"dependencies":[],"blockers":[],"cost":1,"display":{"row":26,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","inputs":[{"type":"stat","name":"ref"}],"output":{"type":"stat","name":"mr"},"scaling":[1],"max":10,"slider_step":4}],"id":46},{"display_name":"Whirlwind Strike","desc":"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)","archetype":"Battle Monk","archetype_req":5,"parents":[38,46],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":26,"col":4,"icon":"node_1"},"properties":{"range":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":0,"multipliers":[0,0,0,0,0,50]}],"id":47},{"display_name":"Mythril Skin","desc":"Gain +5% Base Resistance and become immune to knockback","archetype":"Paladin","archetype_req":6,"parents":[44],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":5}]}],"id":48},{"display_name":"Armour Breaker","desc":"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage","archetype":"Fallen","archetype_req":0,"parents":[45,46],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":27,"col":1,"icon":"node_2"},"properties":{"duration":5},"effects":[],"id":49},{"display_name":"Shield Strike","desc":"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost","archetype":"Paladin","archetype_req":0,"parents":[48,51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Shield Strike","cost":0,"multipliers":[60,0,20,0,0,0]}],"id":50},{"display_name":"Sparkling Hope","desc":"Everytime you heal 5% of your max health, deal damage to all nearby enemies","archetype":"Paladin","archetype_req":0,"parents":[48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":8,"icon":"node_2"},"properties":{"aoe":6},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Sparkling Hope","cost":0,"multipliers":[10,0,5,0,0,0]}],"id":51},{"display_name":"Massive Bash","desc":"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)","archetype":"Fallen","archetype_req":8,"parents":[53,45],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Corrupted","output":{"type":"stat","name":"bashAoE"},"scaling":[1],"max":10,"slider_step":3}],"id":52},{"display_name":"Tempest","desc":"War Scream will ripple the ground and deal damage 3 times in a large area","archetype":"Battle Monk","archetype_req":0,"parents":[52,54],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2,"icon":"node_1"},"properties":{"aoe":16},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest","cost":"0","multipliers":[30,10,0,0,0,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest Total Damage","cost":"0","hits":{"Tempest":3}},{"type":"add_spell_prop","base_spell":4,"target_part":"Total Damage","cost":"0","hits":{"Tempest":3}}],"id":53},{"display_name":"Spirit of the Rabbit","desc":"Reduce the Mana cost of Charge and increase your Walk Speed by +20%","archetype":"Battle Monk","archetype_req":5,"parents":[53,47],"dependencies":[],"blockers":[],"cost":1,"display":{"row":28,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5},{"type":"raw_stat","bonuses":[{"type":"stat","name":"spd","value":20}]}],"id":54},{"display_name":"Massacre","desc":"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar","archetype":"Fallen","archetype_req":5,"parents":[53,52],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":55},{"display_name":"Axe Kick","desc":"Increase the damage of Uppercut, but also increase its mana cost","archetype":"","archetype_req":0,"parents":[53,54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":10,"multipliers":[100,0,0,0,0,0]}],"id":56},{"display_name":"Radiance","desc":"Bash will buff your allies' positive IDs. (15s Cooldown)","archetype":"Paladin","archetype_req":2,"parents":[54,58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":5,"icon":"node_2"},"properties":{"cooldown":15},"effects":[],"id":57},{"display_name":"Cheaper Bash 2","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[57,50,51],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":58},{"display_name":"Cheaper War Scream","desc":"Reduce the Mana cost of War Scream","archetype":"","archetype_req":0,"parents":[52],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":59},{"display_name":"Discombobulate","desc":"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second","archetype":"Battle Monk","archetype_req":11,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":31,"col":2,"icon":"node_3"},"properties":{},"effects":[{"type":"stat_scaling","slider":!0,"slider_name":"Hits dealt","output":{"type":"stat","name":"rainrawButDifferent"},"scaling":[2],"max":50}],"id":60},{"display_name":"Thunderclap","desc":"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder","archetype":"Battle Monk","archetype_req":8,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":5,"icon":"node_1"},"properties":{},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"},{"type":"raw_stat","bonuses":[{"type":"prop","abil_name":"Bash","name":"aoe","value":3}]}],"id":61},{"display_name":"Cyclone","desc":"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s","archetype":"Battle Monk","archetype_req":0,"parents":[54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":4,"icon":"node_1"},"properties":{"aoe":4,"duration":20},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone","cost":0,"multipliers":[10,0,0,0,5,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone Total Damage","cost":0,"hits":{"Cyclone":40}}],"id":62},{"display_name":"Second Chance","desc":"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)","archetype":"Paladin","archetype_req":12,"parents":[58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":63},{"display_name":"Blood Pact","desc":"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)","archetype":"","archetype_req":10,"parents":[59],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1,"icon":"node_3"},"properties":{},"effects":[],"id":64},{"display_name":"Haemorrhage","desc":"Reduce Blood Pact's health cost. (0.5% health per mana)","archetype":"Fallen","archetype_req":0,"parents":[64],"dependencies":[64],"blockers":[],"cost":1,"display":{"row":35,"col":2,"icon":"node_1"},"properties":{},"effects":[],"id":65},{"display_name":"Brink of Madness","desc":"If your health is 25% full or less, gain +40% Resistance","archetype":"","archetype_req":0,"parents":[64,67],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":4,"icon":"node_2"},"properties":{},"effects":[],"id":66},{"display_name":"Cheaper Uppercut 2","desc":"Reduce the Mana cost of Uppercut","archetype":"","archetype_req":0,"parents":[63,66],"dependencies":[],"blockers":[],"cost":1,"display":{"row":35,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":67},{"display_name":"Martyr","desc":"When you receive a fatal blow, all nearby allies become invincible","archetype":"Paladin","archetype_req":0,"parents":[63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":8,"icon":"node_1"},"properties":{"duration":3,"aoe":12},"effects":[],"id":68}]} \ No newline at end of file +const atrees={"Archer":[{"display_name":"Arrow Shield","desc":"Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)","archetype":"","archetype_req":0,"parents":[60,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":6},"properties":{"duration":60},"effects":[{"type":"replace_spell","name":"Arrow Shield","cost":30,"display_text":"Max Damage","base_spell":4,"spell_type":"damage","scaling":"spell","display":"","parts":[{"name":"Shield Damage","type":"damage","multipliers":[90,0,0,0,0,10]},{"name":"Total Damage","type":"total","hits":{"Shield Damage":2}}]}],"id":0},{"display_name":"Escape","desc":"Throw yourself backward to avoid danger. (Hold shift while escaping to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":7,"col":4},"properties":{"aoe":0,"range":0},"effects":[{"type":"replace_spell","name":"Escape","cost":25,"display_text":"Max Damage","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":1},{"display_name":"Arrow Bomb","desc":"Throw a long-range arrow that explodes and deal high damage in a large area. (Self-damage for 25% of your DPS)","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4},"properties":{"aoe":4.5,"range":26},"effects":[{"type":"replace_spell","name":"Arrow Bomb","cost":50,"display_text":"Average Damage","base_spell":3,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Arrow Bomb","type":"damage","multipliers":[160,0,0,0,20,0]},{"name":"Total Damage","type":"total","hits":{"Arrow Bomb":1}}]}],"id":2},{"display_name":"Heart Shatter","desc":"If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[100,0,0,0,0,0]},{}],"id":3},{"display_name":"Fire Creep","desc":"Arrow Bomb will leak a trail of fire for 6s, Damaging enemies that walk into it every 0.4s.","archetype":"","archetype_req":0,"parents":[68,39,5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":16,"col":6},"properties":{"aoe":0.8,"duration":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[30,0,0,0,20,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fire Creep":15}}],"id":4},{"display_name":"Bryophyte Roots","desc":"When you hit an enemy with Arrow Storm, create an area that slows them down and deals damage every 0.4s.","archetype":"Trapper","archetype_req":1,"parents":[4,35],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":16,"col":8},"properties":{"aoe":2,"duration":5,"slowness":0.4},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Bryophyte Roots","cost":0,"multipliers":[40,20,0,0,0,0]}],"id":5},{"display_name":"Nimble String","desc":"Arrow Storm throw out +6 arrows per stream and shoot twice as fast.","archetype":"","archetype_req":0,"parents":[36,69],"dependencies":[7],"blockers":[68],"cost":2,"display":{"row":15,"col":2},"properties":{"shootspeed":2},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-15,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":6}}],"id":6},{"display_name":"Arrow Storm","desc":"Shoot two stream of 8 arrows, dealing significant damage to close mobs and pushing them back.","archetype":"","archetype_req":0,"parents":[58,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":2},"properties":{"aoe":0,"range":16},"effects":[{"type":"replace_spell","name":"Arrow Storm","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,10,0,0,0]},{"name":"Single Stream","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Stream":1}}]}],"id":7},{"display_name":"Guardian Angels","desc":"Your protective arrows from Arrow Shield will become sentient bows, dealing damage up to 8 times each to nearby enemies. (Arrow Shield will no longer push nearby enemies)","archetype":"Boltslinger","archetype_req":3,"parents":[59,67],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":19,"col":1},"properties":{"range":4,"duration":60,"shots":8,"count":2},"effects":[{"type":"replace_spell","name":"Guardian Angels","cost":30,"display_text":"Total Damage Average","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[30,0,0,0,0,10]},{"name":"Single Bow","type":"total","hits":{"Single Arrow":8}},{"name":"Total Damage","type":"total","hits":{"Single Bow":2}}]}],"id":8},{"display_name":"Windy Feet","base_abil":"Escape","desc":"When casting Escape, give speed to yourself and nearby allies.","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":1},"properties":{"aoe":8,"duration":120},"type":"stat_bonus","bonuses":[{"type":"stat","name":"spd","value":20}],"id":9},{"display_name":"Basaltic Trap","desc":"When you hit the ground with Arrow Bomb, leave a Trap that damages enemies. (Max 2 Traps)","archetype":"Trapper","archetype_req":2,"parents":[5],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":8},"properties":{"aoe":7,"traps":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[140,30,0,0,30,0]}],"id":10},{"display_name":"Windstorm","desc":"Arrow Storm shoot +1 stream of arrows, effectively doubling its damage.","archetype":"","archetype_req":0,"parents":[8,33],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":21,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Arrow","cost":0,"multipliers":[-10,0,-2,0,0,2]},{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Stream","cost":0,"hits":{"Single Arrow":2}}],"id":11},{"display_name":"Grappling Hook","base_abil":"Escape","desc":"When casting Escape, throw a hook that pulls you when hitting a block. If you hit an enemy, pull them towards you instead. (Escape will not throw you backward anymore)","archetype":"Trapper","archetype_req":0,"parents":[61,40,33],"dependencies":[],"blockers":[20],"cost":2,"display":{"row":21,"col":5},"properties":{"range":20},"effects":[],"id":12},{"display_name":"Implosion","desc":"Arrow bomb will pull enemies towards you. If a trap is nearby, it will pull them towards it instead. Increase Heart Shatter's damage.","archetype":"Trapper","archetype_req":0,"parents":[12,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":13},{"display_name":"Twain's Arc","desc":"When you have 2+ Focus, holding shift will summon the Twain's Arc. Charge it up to shoot a destructive long-range beam. (Damage is dealt as Main Attack Damage)","archetype":"Sharpshooter","archetype_req":4,"parents":[62,64],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":25,"col":4},"properties":{"range":64,"focusReq":2},"effects":[{"type":"replace_spell","name":"Twain's Arc","cost":0,"display_text":"Twain's Arc","base_spell":5,"spell_type":"damage","scaling":"melee","display":"Twain's Arc Damage","parts":[{"name":"Twain's Arc Damage","type":"damage","multipliers":[200,0,0,0,0,0]}]}],"id":14},{"display_name":"Fierce Stomp","desc":"When using Escape, hold shift to quickly drop down and deal damage.","archetype":"Boltslinger","archetype_req":0,"parents":[42,64],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":1},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[100,0,0,0,0,0]},{"type":"add_spell_prop","base_spell":2,"target_part":"Total Damage","cost":0,"hits":{"Fierce Stomp":1}}],"id":15},{"display_name":"Scorched Earth","desc":"Fire Creep become much stronger.","archetype":"Sharpshooter","archetype_req":0,"parents":[14],"dependencies":[4],"blockers":[],"cost":1,"display":{"row":26,"col":5},"properties":{"duration":2,"aoe":0.4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fire Creep","cost":0,"multipliers":[10,0,0,0,5,0]}],"id":16},{"display_name":"Leap","desc":"When you double tap jump, leap foward. (2s Cooldown)","archetype":"Boltslinger","archetype_req":5,"parents":[42,55],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0},"properties":{"cooldown":2},"effects":[],"id":17},{"display_name":"Shocking Bomb","desc":"Arrow Bomb will not be affected by gravity, and all damage conversions become Thunder.","archetype":"Sharpshooter","archetype_req":5,"parents":[14,44,55],"dependencies":[2],"blockers":[],"cost":2,"display":{"row":28,"col":4},"properties":{"gravity":0},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"}],"id":18},{"display_name":"Mana Trap","desc":"Your Traps will give you 4 Mana per second when you stay close to them.","archetype":"Trapper","archetype_req":5,"parents":[43,44],"dependencies":[4],"blockers":[],"cost":2,"display":{"row":28,"col":8},"properties":{"range":12,"manaRegen":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":10,"multipliers":[0,0,0,0,0,0]}],"id":19},{"display_name":"Escape Artist","desc":"When casting Escape, release 100 arrows towards the ground.","archetype":"Boltslinger","archetype_req":0,"parents":[46,17],"dependencies":[],"blockers":[12],"cost":2,"display":{"row":31,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Escape Artist","cost":0,"multipliers":[30,0,10,0,0,0]}],"id":20},{"display_name":"Initiator","desc":"If you do not damage an enemy for 5s or more, your next sucessful hit will deal +50% damage and add +1 Focus.","archetype":"Sharpshooter","archetype_req":5,"parents":[18,44,47],"dependencies":[61],"blockers":[],"cost":2,"display":{"row":31,"col":5},"properties":{"focus":1,"timer":5},"type":"stat_bonus","bonuses":[{"type":"stat","name":"damPct","value":50}],"id":21},{"display_name":"Call of the Hound","desc":"Arrow Shield summon a Hound that will attack and drag aggressive enemies towards your traps.","archetype":"Trapper","archetype_req":0,"parents":[21,47],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":32,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Call of the Hound","cost":0,"multipliers":[40,0,0,0,0,0]}],"id":22},{"display_name":"Arrow Hurricane","desc":"Arrow Storm will shoot +2 stream of arrows.","archetype":"Boltslinger","archetype_req":8,"parents":[48,20],"dependencies":[],"blockers":[68],"cost":2,"display":{"row":33,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Stream":2}}],"id":23},{"display_name":"Geyser Stomp","desc":"Fierce Stomp will create geysers, dealing more damage and vertical knockback.","archetype":"","archetype_req":0,"parents":[56],"dependencies":[15],"blockers":[],"cost":2,"display":{"row":37,"col":1},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Fierce Stomp","cost":0,"multipliers":[0,0,0,50,0,0]}],"id":24},{"display_name":"Crepuscular Ray","desc":"If you have 5 Focus, casting Arrow Storm will make you levitate and shoot 20 homing arrows per second until you run out of Focus. While in that state, you will lose 1 Focus per second.","archetype":"Sharpshooter","archetype_req":10,"parents":[49],"dependencies":[7],"blockers":[],"cost":2,"display":{"row":37,"col":4},"properties":{"focusReq":5,"focusRegen":-1},"effects":[{"type":"replace_spell","name":"Crepuscular Ray","base_spell":5,"spell_type":"damage","scaling":"spell","display":"One Focus","cost":0,"parts":[{"name":"Single Arrow","type":"damage","multipliers":[10,0,0,5,0,0]},{"name":"One Focus","type":"total","hits":{"Single Arrow":20}},{"name":"Total Damage","type":"total","hits":{"One Focus":7}}]}],"id":25},{"display_name":"Grape Bomb","desc":"Arrow bomb will throw 3 additional smaller bombs when exploding.","archetype":"","archetype_req":0,"parents":[51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":37,"col":7},"properties":{"miniBombs":3,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Grape Bomb","cost":0,"multipliers":[30,0,0,0,10,0]}],"id":26},{"display_name":"Tangled Traps","desc":"Your Traps will be connected by a rope that deals damage to enemies every 0.2s.","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":38,"col":6},"properties":{"attackSpeed":0.2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Tangled Traps","cost":0,"multipliers":[20,0,0,0,0,20]}],"id":27},{"display_name":"Snow Storm","desc":"Enemies near you will be slowed down.","archetype":"","archetype_req":0,"parents":[24,63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":39,"col":2},"properties":{"range":2.5,"slowness":0.3},"id":28},{"display_name":"All-Seeing Panoptes","desc":"Your bows from Guardian Angels become all-seeing, increasing their range, damage and letting them shoot up to +5 times each.","archetype":"Boltslinger","archetype_req":11,"parents":[28],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":40,"col":1},"properties":{"range":8,"shots":5},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Arrow","cost":0,"multipliers":[0,0,0,0,10,0]},{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":5}}],"id":29},{"display_name":"Minefield","desc":"Allow you to place +6 Traps, but with reduced damage and range.","archetype":"Trapper","archetype_req":10,"parents":[26,53],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":40,"col":7},"properties":{"aoe":-2,"traps":6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Basaltic Trap","cost":0,"multipliers":[-80,0,0,0,0,0]}],"id":30},{"display_name":"Bow Proficiency I","desc":"Improve your Main Attack's damage and range when using a bow.","archetype":"","archetype_req":0,"parents":[2],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":31},{"display_name":"Cheaper Arrow Bomb","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[31],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":6},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-10}],"id":32},{"display_name":"Cheaper Arrow Storm","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[12,11,61],"dependencies":[],"blockers":[],"cost":1,"display":{"row":21,"col":3},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":33},{"display_name":"Cheaper Escape","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[7,0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":34},{"display_name":"Earth Mastery","desc":"Increases your base damage from all Earth attacks","archetype":"Trapper","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":8},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":35},{"display_name":"Thunder Mastery","desc":"Increases your base damage from all Thunder attacks","archetype":"Boltslinger","archetype_req":0,"parents":[7,39,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":2},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":36},{"display_name":"Water Mastery","desc":"Increases your base damage from all Water attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[34,36,39],"dependencies":[],"blockers":[],"cost":1,"display":{"row":14,"col":4},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":37},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":0},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":38},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Sharpshooter","archetype_req":0,"parents":[36,0,34],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":6},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":39},{"display_name":"More Shields","desc":"Give +2 charges to Arrow Shield.","archetype":"","archetype_req":0,"parents":[12,10],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":21,"col":7},"properties":{"shieldCharges":2},"id":40},{"display_name":"Stormy Feet","desc":"Windy Feet will last longer and add more speed.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[9],"blockers":[],"cost":1,"display":{"row":23,"col":1},"properties":{"duration":60},"effects":[{"type":"stat_bonus","bonuses":[{"type":"stat","name":"spdPct","value":20}]}],"id":41},{"display_name":"Refined Gunpowder","desc":"Increase the damage of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[11],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Bomb","cost":0,"multipliers":[50,0,0,0,0,0]}],"id":42},{"display_name":"More Traps","desc":"Increase the maximum amount of active Traps you can have by +2.","archetype":"Trapper","archetype_req":10,"parents":[54],"dependencies":[10],"blockers":[],"cost":1,"display":{"row":26,"col":8},"properties":{"traps":2},"id":43},{"display_name":"Better Arrow Shield","desc":"Arrow Shield will gain additional area of effect, knockback and damage.","archetype":"Sharpshooter","archetype_req":0,"parents":[19,18,14],"dependencies":[0],"blockers":[],"cost":1,"display":{"row":28,"col":6},"properties":{"aoe":1},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Arrow Shield","multipliers":[40,0,0,0,0,0]}],"id":44},{"display_name":"Better Leap","desc":"Reduce leap's cooldown by 1s.","archetype":"Boltslinger","archetype_req":0,"parents":[17,55],"dependencies":[17],"blockers":[],"cost":1,"display":{"row":29,"col":1},"properties":{"cooldown":-1},"id":45},{"display_name":"Better Guardian Angels","desc":"Your Guardian Angels can shoot +4 arrows before disappearing.","archetype":"Boltslinger","archetype_req":0,"parents":[20,55],"dependencies":[8],"blockers":[],"cost":1,"display":{"row":31,"col":2},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Single Bow","cost":0,"hits":{"Single Arrow":4}}],"id":46},{"display_name":"Cheaper Arrow Storm (2)","desc":"Reduce the Mana cost of Arrow Storm.","archetype":"","archetype_req":0,"parents":[21,19],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":8},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":47},{"display_name":"Precise Shot","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[46,49,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":2},"properties":{"mainAtk_range":6},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdCritPct","value":30}]}],"id":48},{"display_name":"Cheaper Arrow Shield","desc":"Reduce the Mana cost of Arrow Shield.","archetype":"","archetype_req":0,"parents":[48,21],"dependencies":[],"blockers":[],"cost":1,"display":{"row":33,"col":4},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":49},{"display_name":"Rocket Jump","desc":"Arrow Bomb's self-damage will knockback you farther away.","archetype":"","archetype_req":0,"parents":[47,21],"dependencies":[2],"blockers":[],"cost":1,"display":{"row":33,"col":6},"properties":{},"id":50},{"display_name":"Cheaper Escape (2)","desc":"Reduce the Mana cost of Escape.","archetype":"","archetype_req":0,"parents":[22,70],"dependencies":[],"blockers":[],"cost":1,"display":{"row":34,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":51},{"display_name":"Stronger Hook","desc":"Increase your Grappling Hook's range, speed and strength.","archetype":"Trapper","archetype_req":5,"parents":[51],"dependencies":[12],"blockers":[],"cost":1,"display":{"row":35,"col":8},"properties":{"range":8},"id":52},{"display_name":"Cheaper Arrow Bomb (2)","desc":"Reduce the Mana cost of Arrow Bomb.","archetype":"","archetype_req":0,"parents":[63,30],"dependencies":[],"blockers":[],"cost":1,"display":{"row":40,"col":5},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":53},{"display_name":"Bouncing Bomb","desc":"Arrow Bomb will bounce once when hitting a block or enemy","archetype":"","archetype_req":0,"parents":[40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":25,"col":7},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Arrow Bomb":2}}],"id":54},{"display_name":"Homing Shots","desc":"Your Main Attack arrows will follow nearby enemies and not be affected by gravity","archetype":"","archetype_req":0,"parents":[17,18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2},"properties":{},"effects":[],"id":55},{"display_name":"Shrapnel Bomb","desc":"Arrow Bomb's explosion will fling 15 shrapnel, dealing damage in a large area","archetype":"Boltslinger","archetype_req":8,"parents":[23,48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Shrapnel Bomb","cost":0,"multipliers":[40,0,0,0,20,0]}],"id":56},{"display_name":"Elusive","desc":"If you do not get hit for 8+ seconds, become immune to self-damage and remove Arrow Storm's recoil. (Dodging counts as not getting hit)","archetype":"Boltslinger","archetype_req":0,"parents":[24],"dependencies":[],"blockers":[],"cost":2,"display":{"row":38,"col":0},"properties":{},"effects":[],"id":57},{"display_name":"Double Shots","desc":"Double Main Attack arrows, but they deal -30% damage per arrow (harder to hit far enemies)","archetype":"Boltslinger","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[60],"cost":1,"display":{"row":7,"col":2},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":58},{"display_name":"Triple Shots","desc":"Triple Main Attack arrows, but they deal -20% damage per arrow","archetype":"Boltslinger","archetype_req":0,"parents":[69,67],"dependencies":[58],"blockers":[],"cost":1,"display":{"row":17,"col":0},"properties":{"arrow":2},"effects":[{"type":"add_spell_prop","base_spell":0,"target_part":"Melee Damage","cost":0,"multipliers":0.7}],"id":59},{"display_name":"Power Shots","desc":"Main Attack arrows have increased speed and knockback","archetype":"Sharpshooter","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[58],"cost":1,"display":{"row":7,"col":6},"properties":{},"effects":[],"id":60},{"display_name":"Focus","desc":"When hitting an aggressive mob 5+ blocks away, gain +1 Focus (Max 3). Resets if you miss once","archetype":"Sharpshooter","archetype_req":2,"parents":[68],"dependencies":[],"blockers":[],"cost":2,"display":{"row":19,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[3],"max":3}],"id":61},{"display_name":"More Focus","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[33,12],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":5}],"id":62},{"display_name":"More Focus (2)","desc":"Add +2 max Focus","archetype":"Sharpshooter","archetype_req":0,"parents":[25,28],"dependencies":[],"blockers":[],"cost":1,"display":{"row":39,"col":4},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Focus","output":{"type":"stat","abil_name":"Focus","name":"damMult"},"scaling":[35],"max":7}],"id":63},{"display_name":"Traveler","desc":"For every 1% Walk Speed you have from items, gain +1 Raw Spell Damage (Max 100)","archetype":"","archetype_req":0,"parents":[42,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":25,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":false,"inputs":[{"type":"stat","name":"spd"}],"output":{"type":"stat","name":"sdRaw"},"scaling":[1],"max":100}],"id":64},{"display_name":"Patient Hunter","desc":"Your Traps will deal +20% more damage for every second they are active (Max +80%)","archetype":"Trapper","archetype_req":0,"parents":[40],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":8},"properties":{"max":80},"effects":[],"id":65},{"display_name":"Stronger Patient Hunter","desc":"Add +80% Max Damage to Patient Hunter","archetype":"Trapper","archetype_req":0,"parents":[26],"dependencies":[65],"blockers":[],"cost":1,"display":{"row":38,"col":8},"properties":{"max":80},"effects":[],"id":66},{"display_name":"Frenzy","desc":"Every time you hit an enemy, briefly gain +6% Walk Speed (Max 200%). Decay -40% of the bonus every second","archetype":"Boltslinger","archetype_req":0,"parents":[59,6],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":2},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Hits dealt","output":{"type":"stat","name":"spd"},"scaling":[6],"max":200}],"id":67},{"display_name":"Phantom Ray","desc":"Condense Arrow Storm into a single ray that damages enemies 10 times per second","archetype":"Sharpshooter","archetype_req":0,"parents":[37,4],"dependencies":[7],"blockers":[11,6,23],"cost":2,"display":{"row":16,"col":4},"properties":{},"effects":[{"type":"replace_spell","name":"Phantom Ray","cost":40,"display_text":"Max Damage","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Arrow","type":"damage","multipliers":[25,0,5,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Arrow":16}}]}],"id":68},{"display_name":"Arrow Rain","desc":"When Arrow Shield loses its last charge, unleash 200 arrows raining down on enemies","archetype":"Trapper","archetype_req":0,"parents":[6,38],"dependencies":[0],"blockers":[],"cost":2,"display":{"row":15,"col":0},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Arrow Rain","cost":0,"multipliers":[120,0,0,0,0,80]}],"id":69},{"display_name":"Decimator","desc":"Phantom Ray will increase its damage by 10% everytime you do not miss with it (Max 50%)","archetype":"Sharpshooter","archetype_req":0,"parents":[49],"dependencies":[68],"blockers":[],"cost":1,"display":{"row":34,"col":5},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Phantom Ray hits","output":{"type":"stat","name":"PhRayDmg"},"scaling":10,"max":50}],"id":70}],"Warrior":[{"display_name":"Bash","desc":"Violently bash the ground, dealing high damage in a large area","archetype":"","archetype_req":0,"parents":[],"dependencies":[],"blockers":[],"cost":1,"display":{"row":0,"col":4,"icon":"node_4"},"properties":{"aoe":4,"range":3},"effects":[{"type":"replace_spell","name":"Bash","cost":45,"display_text":"Total Damage Average","base_spell":1,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"Single Hit","type":"damage","multipliers":[130,20,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Single Hit":1}}]}],"id":0},{"display_name":"Spear Proficiency 1","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[0],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":4,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":1},{"display_name":"Cheaper Bash","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":2,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-10}],"id":2},{"display_name":"Double Bash","desc":"Bash will hit a second time at a farther range","archetype":"","archetype_req":0,"parents":[1],"dependencies":[],"blockers":[],"cost":1,"display":{"row":4,"col":4,"icon":"node_1"},"properties":{"range":3},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"name":"Single Hit","value":1}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-50,0,0,0,0,0]}],"id":3},{"display_name":"Charge","desc":"Charge forward at high speed (hold shift to cancel)","archetype":"","archetype_req":0,"parents":[3],"dependencies":[],"blockers":[],"cost":1,"display":{"row":6,"col":4,"icon":"node_4"},"properties":{},"effects":[{"type":"replace_spell","name":"Charge","cost":25,"display_text":"Total Damage Average","base_spell":2,"spell_type":"damage","scaling":"spell","display":"Total Damage","parts":[{"name":"None","type":"damage","multipliers":[0,0,0,0,0,0]},{"name":"Total Damage","type":"total","hits":{"None":0}}]}],"id":4},{"display_name":"Heavy Impact","desc":"After using Charge, violently crash down into the ground and deal damage","archetype":"","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":9,"col":1,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Heavy Impact","cost":0,"multipliers":[100,0,0,0,0,0]}],"id":5},{"display_name":"Vehement","desc":"For every 1% or 1 Raw Main Attack Damage you have from items, gain +2% Walk Speed (Max 20%)","archetype":"Fallen","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[7],"cost":1,"display":{"row":6,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":false,"inputs":[{"type":"stat","name":"mdPct"},{"type":"stat","name":"mdRaw"}],"output":{"type":"stat","name":"spd"},"scaling":[1,1],"max":20}],"id":6},{"display_name":"Tougher Skin","desc":"Harden your skin and become permanently +5% more resistant\nFor every 1% or 1 Raw Heath Regen you have from items, gain +10 Health (Max 100)","archetype":"Paladin","archetype_req":0,"parents":[4],"dependencies":[],"blockers":[6],"cost":1,"display":{"row":6,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":"5"}]},{"type":"stat_scaling","slider":false,"inputs":[{"type":"stat","name":"hprRaw"},{"type":"stat","name":"hprPct"}],"output":{"type":"stat","name":"hpBonus"},"scaling":[10,10],"max":100}],"id":7},{"display_name":"Uppercut","desc":"Rocket enemies in the air and deal massive damage","archetype":"","archetype_req":0,"parents":[6],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":2,"icon":"node_4"},"properties":{"aoe":3,"range":5},"effects":[{"type":"replace_spell","name":"Uppercut","cost":45,"display_text":"Total Damage Average","base_spell":3,"spell_type":"damage","scaling":"spell","display":"total","parts":[{"name":"Uppercut","type":"damage","multipliers":[150,50,50,0,0,0]},{"name":"Total Damage","type":"total","hits":{"Uppercut":1}}]}],"id":8},{"display_name":"Cheaper Charge","desc":"Reduce the Mana cost of Charge","archetype":"","archetype_req":0,"parents":[8,10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5}],"id":9},{"display_name":"War Scream","desc":"Emit a terrorizing roar that deals damage, pull nearby enemies, and add damage resistance to yourself and allies","archetype":"","archetype_req":0,"parents":[7],"dependencies":[],"blockers":[],"cost":1,"display":{"row":8,"col":6,"icon":"node_4"},"properties":{"duration":30,"aoe":12,"defense_bonus":10},"effects":[{"type":"replace_spell","name":"War Scream","cost":35,"display_text":"War Scream","base_spell":4,"spell_type":"damage","scaling":"spell","display":"Total Damage Average","parts":[{"name":"War Scream","type":"damage","multipliers":[50,0,0,0,50,0]}]}],"id":10},{"display_name":"Earth Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Fallen","archetype_req":0,"parents":[8],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"eDamPct","value":20},{"type":"stat","name":"eDam","value":[2,4]}]}],"id":11},{"display_name":"Thunder Mastery","desc":"Increases base damage from all Thunder attacks","archetype":"Fallen","archetype_req":0,"parents":[8,14,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"tDamPct","value":10},{"type":"stat","name":"tDam","value":[1,8]}]}],"id":12},{"display_name":"Water Mastery","desc":"Increases base damage from all Water attacks","archetype":"Battle Monk","archetype_req":0,"parents":[9,12,14],"dependencies":[],"blockers":[],"cost":1,"display":{"row":11,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"wDamPct","value":15},{"type":"stat","name":"wDam","value":[2,4]}]}],"id":13},{"display_name":"Air Mastery","desc":"Increases base damage from all Air attacks","archetype":"Battle Monk","archetype_req":0,"parents":[10,12,9],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"aDamPct","value":15},{"type":"stat","name":"aDam","value":[3,4]}]}],"id":14},{"display_name":"Fire Mastery","desc":"Increases base damage from all Earth attacks","archetype":"Paladin","archetype_req":0,"parents":[10],"dependencies":[],"blockers":[],"cost":1,"display":{"row":10,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"fDamPct","value":15},{"type":"stat","name":"fDam","value":[3,5]}]}],"id":15},{"display_name":"Quadruple Bash","desc":"Bash will hit 4 times at an even larger range","archetype":"Fallen","archetype_req":0,"parents":[11,17],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":0,"icon":"node_1"},"properties":{"range":6},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Total Damage","cost":0,"hits":{"Single Hit":2}},{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[-20,0,0,0,0,0]}],"id":16},{"display_name":"Fireworks","desc":"Mobs hit by Uppercut will explode mid-air and receive additional damage","archetype":"Fallen","archetype_req":0,"parents":[12,16],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Fireworks","cost":0,"multipliers":[80,0,20,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Fireworks":1}}],"id":17},{"display_name":"Half-Moon Swipe","desc":"Uppercut will deal a footsweep attack at a longer and wider angle. All elemental conversions become Water","archetype":"Battle Monk","archetype_req":1,"parents":[13],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":13,"col":4,"icon":"node_1"},"properties":{"range":4},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":-10,"multipliers":[-70,0,0,0,0,0]},{"type":"convert_spell_conv","target_part":"all","conversion":"water"}],"id":18},{"display_name":"Flyby Jab","desc":"Damage enemies in your way when using Charge","archetype":"","archetype_req":0,"parents":[14,20],"dependencies":[],"blockers":[],"cost":2,"display":{"row":12,"col":6,"icon":"node_1"},"properties":{"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flyby Jab","cost":0,"multipliers":[20,0,0,0,0,40]}],"id":19},{"display_name":"Flaming Uppercut","desc":"Uppercut will light mobs on fire, dealing damage every 0.6 seconds","archetype":"Paladin","archetype_req":0,"parents":[15,19],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":12,"col":8,"icon":"node_1"},"properties":{"duration":3,"tick":0.6},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut","cost":0,"multipliers":[0,0,0,0,50,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Flaming Uppercut Total Damage","cost":0,"hits":{"Flaming Uppercut":5}},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Flaming Uppercut":5}}],"id":20},{"display_name":"Iron Lungs","desc":"War Scream deals more damage","archetype":"","archetype_req":0,"parents":[19,20],"dependencies":[],"blockers":[],"cost":1,"display":{"row":13,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"War Scream","cost":0,"multipliers":[30,0,0,0,0,30]}],"id":21},{"display_name":"Generalist","desc":"After casting 3 different spells in a row, your next spell will cost 5 mana","archetype":"Battle Monk","archetype_req":3,"parents":[23],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":2,"icon":"node_3"},"properties":{},"effects":[],"id":22},{"display_name":"Counter","desc":"When dodging a nearby enemy attack, get 30% chance to instantly attack back","archetype":"Battle Monk","archetype_req":0,"parents":[18],"dependencies":[],"blockers":[],"cost":2,"display":{"row":15,"col":4,"icon":"node_1"},"properties":{"chance":30},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Counter","cost":0,"multipliers":[60,0,20,0,0,20]}],"id":23},{"display_name":"Mantle of the Bovemists","desc":"When casting War Scream, create a holy shield around you that reduces all incoming damage by 70% for 3 hits (20s cooldown)","archetype":"Paladin","archetype_req":3,"parents":[21],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":15,"col":7,"icon":"node_3"},"properties":{"mantle_charge":3},"effects":[],"id":24},{"display_name":"Bak'al's Grasp","desc":"After casting War Scream, become Corrupted (15s Cooldown). You cannot heal while in that state\n\nWhile Corrupted, every 2% of Health you lose will add +4 Raw Damage to your attacks (Max 120)","archetype":"Fallen","archetype_req":2,"parents":[16,17],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":16,"col":1,"icon":"node_3"},"properties":{"cooldown":15},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[4],"slider_step":2,"max":120}],"id":25},{"display_name":"Spear Proficiency 2","desc":"Improve your Main Attack's damage and range w/ spear","archetype":"","archetype_req":0,"parents":[25,27],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":0,"icon":"node_0"},"properties":{"melee_range":1},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"mdPct","value":5}]}],"id":26},{"display_name":"Cheaper Uppercut","desc":"Reduce the Mana Cost of Uppercut","archetype":"","archetype_req":0,"parents":[26,28,23],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":27},{"display_name":"Aerodynamics","desc":"During Charge, you can steer and change direction","archetype":"Battle Monk","archetype_req":0,"parents":[27,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":17,"col":5,"icon":"node_1"},"properties":{},"effects":[],"id":28},{"display_name":"Provoke","desc":"Mobs damaged by War Scream will target only you for at least 5s \n\nReduce the Mana cost of War Scream","archetype":"Paladin","archetype_req":0,"parents":[28,24],"dependencies":[],"blockers":[],"cost":1,"display":{"row":17,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":29},{"display_name":"Precise Strikes","desc":"+30% Critical Hit Damage","archetype":"","archetype_req":0,"parents":[27,26],"dependencies":[],"blockers":[],"cost":1,"display":{"row":18,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"critDmg","value":30}]}],"id":30},{"display_name":"Air Shout","desc":"War Scream will fire a projectile that can go through walls and deal damage multiple times","archetype":"","archetype_req":0,"parents":[28,29],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":18,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Air Shout","cost":0,"multipliers":[20,0,0,0,0,5]}],"id":31},{"display_name":"Enraged Blow","desc":"While Corriupted, every 1% of Health you lose will increase your damage by +2% (Max 200%)","archetype":"Fallen","archetype_req":0,"parents":[26],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":20,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":false,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"damMult"},"scaling":[3],"max":300}],"id":32},{"display_name":"Flying Kick","desc":"When using Charge, mobs hit will halt your momentum and get knocked back","archetype":"Battle Monk","archetype_req":1,"parents":[27,34],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":3,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Flying Kick","cost":0,"multipliers":[120,0,0,10,0,20]}],"id":33},{"display_name":"Stronger Mantle","desc":"Add +2 additional charges to Mantle of the Bovemists","archetype":"Paladin","archetype_req":0,"parents":[35,33],"dependencies":[24],"blockers":[],"cost":1,"display":{"row":20,"col":6,"icon":"node_0"},"properties":{"mantle_charge":2},"effects":[],"id":34},{"display_name":"Manachism","desc":"If you receive a hit that's less than 5% of your max HP, gain 10 Mana (1s Cooldown)","archetype":"Paladin","archetype_req":3,"parents":[34,29],"dependencies":[],"blockers":[],"cost":2,"display":{"row":20,"col":8,"icon":"node_2"},"properties":{"cooldown":1},"effects":[],"id":35},{"display_name":"Boiling Blood","desc":"Bash leaves a trail of boiling blood behind its first explosion, slowing down and damaging enemies above it every 0.4 seconds","archetype":"","archetype_req":0,"parents":[32,37],"dependencies":[],"blockers":[],"cost":2,"display":{"row":22,"col":0,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Boiling Blood","cost":0,"multipliers":[25,0,0,0,5,0]}],"id":36},{"display_name":"Ragnarokkr","desc":"War Scream become deafening, increasing its range and giving damage bonus to players","archetype":"Fallen","archetype_req":0,"parents":[36,33],"dependencies":[10],"blockers":[],"cost":2,"display":{"row":22,"col":2,"icon":"node_2"},"properties":{"damage_bonus":30,"aoe":2},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":10}],"id":37},{"display_name":"Ambidextrous","desc":"Increase your chance to attack with Counter by +30%","archetype":"","archetype_req":0,"parents":[33,34,39],"dependencies":[23],"blockers":[],"cost":1,"display":{"row":22,"col":4,"icon":"node_0"},"properties":{"chance":30},"effects":[],"id":38},{"display_name":"Burning Heart","desc":"For every 100 Health Bonus you have from item IDs, gain +2% Fire Damage (Max 100%)","archetype":"Paladin","archetype_req":0,"parents":[38,40],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","slider":false,"inputs":[{"type":"stat","name":"hpBonus"}],"output":{"type":"stat","name":"fDamPct"},"scaling":[2],"max":100,"slider_step":100}],"id":39},{"display_name":"Stronger Bash","desc":"Increase the damage of Bash","archetype":"","archetype_req":0,"parents":[39,35],"dependencies":[],"blockers":[],"cost":1,"display":{"row":22,"col":8,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"target_part":"Single Hit","cost":0,"multipliers":[30,0,0,0,0,0]}],"id":40},{"display_name":"Intoxicating Blood","desc":"After leaving Corrupted, gain 2% of the health lost back for each enemy killed while Corrupted","archetype":"Fallen","archetype_req":5,"parents":[37,36],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":23,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":41},{"display_name":"Comet","desc":"After being hit by Fireworks, enemies will crash into the ground and receive more damage","archetype":"Fallen","archetype_req":0,"parents":[37],"dependencies":[17],"blockers":[],"cost":2,"display":{"row":24,"col":2,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Comet","cost":0,"multipliers":[80,20,0,0,0,0]},{"type":"add_spell_prop","base_spell":3,"target_part":"Total Damage","cost":0,"hits":{"Comet":1}}],"id":42},{"display_name":"Collide","desc":"Mobs thrown into walls from Flying Kick will explode and receive additonal damage","archetype":"Battle Monk","archetype_req":4,"parents":[38,39],"dependencies":[33],"blockers":[],"cost":2,"display":{"row":23,"col":5,"icon":"node_1"},"properties":{"aoe":4},"effects":[{"type":"add_spell_prop","base_spell":2,"target_part":"Collide","cost":0,"multipliers":[100,0,0,0,50,0]}],"id":43},{"display_name":"Rejuvenating Skin","desc":"Regain back 30% of the damage you take as healing over 30s","archetype":"Paladin","archetype_req":0,"parents":[39,40],"dependencies":[],"blockers":[],"cost":2,"display":{"row":23,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":44},{"display_name":"Uncontainable Corruption","desc":"Reduce the cooldown of Bak'al's Grasp by -5s, and increase the raw damage gained for every 2% of health lost by +1","archetype":"","archetype_req":0,"parents":[36,46],"dependencies":[25],"blockers":[],"cost":1,"display":{"row":26,"col":0,"icon":"node_0"},"properties":{"cooldown":-5},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Corrupted","output":{"type":"stat","name":"raw"},"scaling":[1],"slider_step":2,"max":50}],"id":45},{"display_name":"Radiant Devotee","desc":"For every 4% Reflection you have from items, gain +1/5s Mana Regen (Max 10/5s)","archetype":"Battle Monk","archetype_req":1,"parents":[47,45],"dependencies":[],"blockers":[],"cost":1,"display":{"row":26,"col":2,"icon":"node_0"},"properties":{},"effects":[{"type":"stat_scaling","inputs":[{"type":"stat","name":"ref"}],"output":{"type":"stat","name":"mr"},"scaling":[1],"max":10,"slider_step":4}],"id":46},{"display_name":"Whirlwind Strike","desc":"Uppercut will create a strong gust of air, launching you upward with enemies (Hold shift to stay grounded)","archetype":"Battle Monk","archetype_req":5,"parents":[38,46],"dependencies":[8],"blockers":[],"cost":2,"display":{"row":26,"col":4,"icon":"node_1"},"properties":{"range":2},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":0,"multipliers":[0,0,0,0,0,50]}],"id":47},{"display_name":"Mythril Skin","desc":"Gain +5% Base Resistance and become immune to knockback","archetype":"Paladin","archetype_req":6,"parents":[44],"dependencies":[],"blockers":[],"cost":2,"display":{"row":26,"col":7,"icon":"node_1"},"properties":{},"effects":[{"type":"raw_stat","bonuses":[{"type":"stat","name":"baseResist","value":5}]}],"id":48},{"display_name":"Armour Breaker","desc":"While Corrupted, losing 30% Health will make your next Uppercut destroy enemies' defense, rendering them weaker to damage","archetype":"Fallen","archetype_req":0,"parents":[45,46],"dependencies":[25],"blockers":[],"cost":2,"display":{"row":27,"col":1,"icon":"node_2"},"properties":{"duration":5},"effects":[],"id":49},{"display_name":"Shield Strike","desc":"When your Mantle of the Bovemist loses all charges, deal damage around you for each Mantle individually lost","archetype":"Paladin","archetype_req":0,"parents":[48,51],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":6,"icon":"node_1"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Shield Strike","cost":0,"multipliers":[60,0,20,0,0,0]}],"id":50},{"display_name":"Sparkling Hope","desc":"Everytime you heal 5% of your max health, deal damage to all nearby enemies","archetype":"Paladin","archetype_req":0,"parents":[48],"dependencies":[],"blockers":[],"cost":2,"display":{"row":27,"col":8,"icon":"node_2"},"properties":{"aoe":6},"effects":[{"type":"add_spell_prop","base_spell":5,"target_part":"Sparkling Hope","cost":0,"multipliers":[10,0,5,0,0,0]}],"id":51},{"display_name":"Massive Bash","desc":"While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)","archetype":"Fallen","archetype_req":8,"parents":[53,45],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":0,"icon":"node_2"},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Corrupted","output":{"type":"stat","name":"bashAoE"},"scaling":[1],"max":10,"slider_step":3}],"id":52},{"display_name":"Tempest","desc":"War Scream will ripple the ground and deal damage 3 times in a large area","archetype":"Battle Monk","archetype_req":0,"parents":[52,54],"dependencies":[],"blockers":[],"cost":2,"display":{"row":28,"col":2,"icon":"node_1"},"properties":{"aoe":16},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest","cost":"0","multipliers":[30,10,0,0,0,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Tempest Total Damage","cost":"0","hits":{"Tempest":3}},{"type":"add_spell_prop","base_spell":4,"target_part":"Total Damage","cost":"0","hits":{"Tempest":3}}],"id":53},{"display_name":"Spirit of the Rabbit","desc":"Reduce the Mana cost of Charge and increase your Walk Speed by +20%","archetype":"Battle Monk","archetype_req":5,"parents":[53,47],"dependencies":[],"blockers":[],"cost":1,"display":{"row":28,"col":4,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":2,"cost":-5},{"type":"raw_stat","bonuses":[{"type":"stat","name":"spd","value":20}]}],"id":54},{"display_name":"Massacre","desc":"While Corrupted, if your effective attack speed is Slow or lower, hitting an enemy with your Main Attack will add +1% to your Corrupted bar","archetype":"Fallen","archetype_req":5,"parents":[53,52],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":1,"icon":"node_1"},"properties":{},"effects":[],"id":55},{"display_name":"Axe Kick","desc":"Increase the damage of Uppercut, but also increase its mana cost","archetype":"","archetype_req":0,"parents":[53,54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":3,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"target_part":"Uppercut","cost":10,"multipliers":[100,0,0,0,0,0]}],"id":56},{"display_name":"Radiance","desc":"Bash will buff your allies' positive IDs. (15s Cooldown)","archetype":"Paladin","archetype_req":2,"parents":[54,58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":29,"col":5,"icon":"node_2"},"properties":{"cooldown":15},"effects":[],"id":57},{"display_name":"Cheaper Bash 2","desc":"Reduce the Mana cost of Bash","archetype":"","archetype_req":0,"parents":[57,50,51],"dependencies":[],"blockers":[],"cost":1,"display":{"row":29,"col":7,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":1,"cost":-5}],"id":58},{"display_name":"Cheaper War Scream","desc":"Reduce the Mana cost of War Scream","archetype":"","archetype_req":0,"parents":[52],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":0,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":4,"cost":-5}],"id":59},{"display_name":"Discombobulate","desc":"Every time you hit an enemy, briefly increase your elemental damage dealt to them by +2 (Additive, Max +50). This bonus decays -5 every second","archetype":"Battle Monk","archetype_req":11,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":31,"col":2,"icon":"node_3"},"properties":{},"effects":[{"type":"stat_scaling","slider":true,"slider_name":"Hits dealt","output":{"type":"stat","name":"rainrawButDifferent"},"scaling":[2],"max":50}],"id":60},{"display_name":"Thunderclap","desc":"Bash will cast at the player's position and gain additional AoE.\n\n All elemental conversions become Thunder","archetype":"Battle Monk","archetype_req":8,"parents":[62],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":5,"icon":"node_1"},"properties":{},"effects":[{"type":"convert_spell_conv","target_part":"all","conversion":"thunder"},{"type":"raw_stat","bonuses":[{"type":"prop","abil_name":"Bash","name":"aoe","value":3}]}],"id":61},{"display_name":"Cyclone","desc":"After casting War Scream, envelop yourself with a vortex that damages nearby enemies every 0.5s","archetype":"Battle Monk","archetype_req":0,"parents":[54],"dependencies":[],"blockers":[],"cost":1,"display":{"row":31,"col":4,"icon":"node_1"},"properties":{"aoe":4,"duration":20},"effects":[{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone","cost":0,"multipliers":[10,0,0,0,5,10]},{"type":"add_spell_prop","base_spell":4,"target_part":"Cyclone Total Damage","cost":0,"hits":{"Cyclone":40}}],"id":62},{"display_name":"Second Chance","desc":"When you receive a fatal blow, survive and regain 30% of your Health (10m Cooldown)","archetype":"Paladin","archetype_req":12,"parents":[58],"dependencies":[],"blockers":[],"cost":2,"display":{"row":32,"col":7,"icon":"node_3"},"properties":{},"effects":[],"id":63},{"display_name":"Blood Pact","desc":"If you do not have enough mana to cast a spell, spend health instead (1% health per mana)","archetype":"","archetype_req":10,"parents":[59],"dependencies":[],"blockers":[],"cost":2,"display":{"row":34,"col":1,"icon":"node_3"},"properties":{},"effects":[],"id":64},{"display_name":"Haemorrhage","desc":"Reduce Blood Pact's health cost. (0.5% health per mana)","archetype":"Fallen","archetype_req":0,"parents":[64],"dependencies":[64],"blockers":[],"cost":1,"display":{"row":35,"col":2,"icon":"node_1"},"properties":{},"effects":[],"id":65},{"display_name":"Brink of Madness","desc":"If your health is 25% full or less, gain +40% Resistance","archetype":"","archetype_req":0,"parents":[64,67],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":4,"icon":"node_2"},"properties":{},"effects":[],"id":66},{"display_name":"Cheaper Uppercut 2","desc":"Reduce the Mana cost of Uppercut","archetype":"","archetype_req":0,"parents":[63,66],"dependencies":[],"blockers":[],"cost":1,"display":{"row":35,"col":6,"icon":"node_0"},"properties":{},"effects":[{"type":"add_spell_prop","base_spell":3,"cost":-5}],"id":67},{"display_name":"Martyr","desc":"When you receive a fatal blow, all nearby allies become invincible","archetype":"Paladin","archetype_req":0,"parents":[63],"dependencies":[],"blockers":[],"cost":2,"display":{"row":35,"col":8,"icon":"node_1"},"properties":{"duration":3,"aoe":12},"effects":[],"id":68}]} \ No newline at end of file From 815cbfacd18b46ba96a995d6354dd0349ef90055 Mon Sep 17 00:00:00 2001 From: reschan Date: Tue, 28 Jun 2022 13:04:18 +0700 Subject: [PATCH 56/68] accept js atree directly and output usable js file and json --- py_script/atree-generateID.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/py_script/atree-generateID.py b/py_script/atree-generateID.py index d8d6419..9fcfece 100644 --- a/py_script/atree-generateID.py +++ b/py_script/atree-generateID.py @@ -1,14 +1,16 @@ """ -Generate a JSON Ability Tree [atree_constants_id.json] with: +Generate a minified JSON Ability Tree [atree_constants_min.json] AND a minified .js form [atree_constants_min.js] of the Ability Tree with: - All references replaced by numerical IDs - Extra JSON File with Class: [Original name as key and Assigned IDs as value]. -given a JSON Ability Tree with reference as string. +given [atree_constants.js] .js form of the Ability Tree with reference as string. """ import json abilDict = {} -with open("atree_constants.json") as f: - data = json.loads(f.read()) +with open("atree_constants.js") as f: + data = f.read() + data = data.replace("const atrees = ", "") + data = json.loads(data) for classType, info in data.items(): _id = 0 abilDict[classType] = {} @@ -31,5 +33,10 @@ with open("atree_constants.json") as f: for ref in range(len(info[abil]["blockers"])): info[abil]["blockers"][ref] = abilDict[classType][info[abil]["blockers"][ref]] - with open('atree_constants_id.json', 'w', encoding='utf-8') as abil_dest: - json.dump(data, abil_dest, ensure_ascii=False, indent=4) + data_str = json.dumps(data, ensure_ascii=False, separators=(',', ':')) + data_str = "const atrees=" + data_str + with open('atree_constants_min.js', 'w', encoding='utf-8') as abil_dest: + abil_dest.write(data_str) + + with open('atree_constants_min.json', 'w', encoding='utf-8') as json_dest: + json.dump(data, json_dest, ensure_ascii=False, separators=(',', ':')) From 881467cf0be4de58590946a3b638dba3ad68e9e5 Mon Sep 17 00:00:00 2001 From: reschan Date: Tue, 28 Jun 2022 14:10:25 +0700 Subject: [PATCH 57/68] fix: atree img display relatively to parent --- builder/index.html | 4 ++-- js/atree.js | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/builder/index.html b/builder/index.html index 2c3ceda..101c64d 100644 --- a/builder/index.html +++ b/builder/index.html @@ -618,10 +618,10 @@