Begin working on abil merging framework... fix a bunch of mistakes in atree constants
This commit is contained in:
parent
4d3a922bb2
commit
259ffb2395
7 changed files with 353 additions and 172 deletions
267
js/atree.js
267
js/atree.js
|
@ -1,9 +1,129 @@
|
||||||
let abil_points_current;
|
let abil_points_current;
|
||||||
|
|
||||||
|
/**
|
||||||
|
ATreeNode spec:
|
||||||
|
|
||||||
|
ATreeNode: {
|
||||||
|
children: List[ATreeNode] // nodes that this node can link to downstream (or sideways)
|
||||||
|
parents: List[ATreeNode] // nodes that can link to this one from upstream (or sideways)
|
||||||
|
ability: atree_node // raw data from atree json
|
||||||
|
}
|
||||||
|
|
||||||
|
atree_node: {
|
||||||
|
display_name: str
|
||||||
|
id: int
|
||||||
|
desc: str
|
||||||
|
archetype: Optional[str] // not present or empty string = no arch
|
||||||
|
archetype_req: Optional[int] // default: 0
|
||||||
|
base_abil: Optional[int] // Modify another abil? poorly defined...
|
||||||
|
parents: List[int]
|
||||||
|
dependencies: List[int] // Hard reqs
|
||||||
|
blockers: List[int] // If any in here are taken, i am invalid
|
||||||
|
cost: int // cost in AP
|
||||||
|
display: { // stuff for rendering ATree
|
||||||
|
row: int
|
||||||
|
col: int
|
||||||
|
icon: str
|
||||||
|
}
|
||||||
|
properties: Map[str, float] // Dynamic (modifiable) misc. properties; ex. AOE
|
||||||
|
effects: List[effect]
|
||||||
|
}
|
||||||
|
|
||||||
|
effect: replace_spell | add_spell_prop | convert_spell_conv | raw_stat | stat_scaling
|
||||||
|
|
||||||
|
replace_spell: {
|
||||||
|
type: "replace_spell"
|
||||||
|
... rest of fields are same as `spell` type (see: damage_calc.js)
|
||||||
|
}
|
||||||
|
|
||||||
|
add_spell_prop: {
|
||||||
|
type: "add_spell_prop"
|
||||||
|
base_spell: int // spell identifier
|
||||||
|
target_part: Optional[str] // Part of the spell to modify. Can be not present/empty for ex. cost modifier.
|
||||||
|
// If target part does not exist, a new part is created.
|
||||||
|
cost: Optional[int] // change to spellcost
|
||||||
|
multipliers: Optional[array[float, 6]] // Additive changes to spellmult (for damage spell)
|
||||||
|
power: Optional[float] // Additive change to healing power (for heal spell)
|
||||||
|
hits: Optional[Map[str, float]] // Additive changes to hits (for total entry)
|
||||||
|
display: Optional[str] // Optional change to the displayed entry. Replaces old
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_spell_conv: {
|
||||||
|
"type": "convert_spell_conv",
|
||||||
|
"target_part": "all" | str,
|
||||||
|
"conversion": element_str
|
||||||
|
}
|
||||||
|
raw_stat: {
|
||||||
|
"type": "raw_stat",
|
||||||
|
"bonuses": list[stat_bonus]
|
||||||
|
}
|
||||||
|
stat_bonus: {
|
||||||
|
"type": "stat" | "prop",
|
||||||
|
"abil": Optional[int],
|
||||||
|
"name": str,
|
||||||
|
"value": float
|
||||||
|
}
|
||||||
|
stat_scaling: {
|
||||||
|
"type": "stat_scaling",
|
||||||
|
"slider": bool,
|
||||||
|
"slider_name": Optional[str],
|
||||||
|
"slider_step": Optional[float],
|
||||||
|
"inputs": Optional[list[scaling_target]],
|
||||||
|
"output": scaling_target,
|
||||||
|
"scaling": list[float],
|
||||||
|
"max": float
|
||||||
|
}
|
||||||
|
scaling_target: {
|
||||||
|
"type": "stat" | "prop",
|
||||||
|
"abil": Optional[int],
|
||||||
|
"name": str
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Range numbers
|
||||||
|
const default_abils = {
|
||||||
|
wand: [{
|
||||||
|
display_name: "Mage Melee",
|
||||||
|
id: 999,
|
||||||
|
desc: "Mage basic attack.",
|
||||||
|
properties: {range: 5000},
|
||||||
|
effects: [default_spells.wand]
|
||||||
|
}],
|
||||||
|
spear: [{
|
||||||
|
display_name: "Warrior Melee",
|
||||||
|
id: 999,
|
||||||
|
desc: "Warrior basic attack.",
|
||||||
|
properties: {range: 2},
|
||||||
|
effects: [default_spells.spear]
|
||||||
|
}],
|
||||||
|
bow: [{
|
||||||
|
display_name: "Archer Melee",
|
||||||
|
id: 999,
|
||||||
|
desc: "Archer basic attack.",
|
||||||
|
properties: {range: 20},
|
||||||
|
effects: [default_spells.bow]
|
||||||
|
}],
|
||||||
|
dagger: [{
|
||||||
|
display_name: "Assassin Melee",
|
||||||
|
id: 999,
|
||||||
|
desc: "Assassin basic attack.",
|
||||||
|
properties: {range: 2},
|
||||||
|
effects: [default_spells.dagger]
|
||||||
|
}],
|
||||||
|
relik: [{
|
||||||
|
display_name: "Shaman Melee",
|
||||||
|
id: 999,
|
||||||
|
desc: "Shaman basic attack.",
|
||||||
|
properties: {range: 15, speed: 0},
|
||||||
|
effects: [default_spells.relik]
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update ability tree internal representation. (topologically sorted node list)
|
* Update ability tree internal representation. (topologically sorted node list)
|
||||||
*
|
*
|
||||||
* Signature: AbilityTreeUpdateNode(build: Build) => ATree
|
* Signature: AbilityTreeUpdateNode(build: Build) => ATree (List of atree nodes in topological order)
|
||||||
*/
|
*/
|
||||||
const atree_node = new (class extends ComputeNode {
|
const atree_node = new (class extends ComputeNode {
|
||||||
constructor() { super('builder-atree-update'); }
|
constructor() { super('builder-atree-update'); }
|
||||||
|
@ -18,7 +138,7 @@ const atree_node = new (class extends ComputeNode {
|
||||||
let atree_map = new Map();
|
let atree_map = new Map();
|
||||||
let atree_head;
|
let atree_head;
|
||||||
for (const i of atree_raw) {
|
for (const i of atree_raw) {
|
||||||
atree_map.set(i.id, {children: [], node: i});
|
atree_map.set(i.id, {children: [], ability: i});
|
||||||
if (i.parents.length == 0) {
|
if (i.parents.length == 0) {
|
||||||
// Assuming there is only one head.
|
// Assuming there is only one head.
|
||||||
atree_head = atree_map.get(i.id);
|
atree_head = atree_map.get(i.id);
|
||||||
|
@ -27,7 +147,7 @@ const atree_node = new (class extends ComputeNode {
|
||||||
for (const i of atree_raw) {
|
for (const i of atree_raw) {
|
||||||
let node = atree_map.get(i.id);
|
let node = atree_map.get(i.id);
|
||||||
let parents = [];
|
let parents = [];
|
||||||
for (const parent_id of node.node.parents) {
|
for (const parent_id of node.ability.parents) {
|
||||||
let parent_node = atree_map.get(parent_id);
|
let parent_node = atree_map.get(parent_id);
|
||||||
parent_node.children.push(node);
|
parent_node.children.push(node);
|
||||||
parents.push(parent_node);
|
parents.push(parent_node);
|
||||||
|
@ -45,7 +165,7 @@ const atree_node = new (class extends ComputeNode {
|
||||||
/**
|
/**
|
||||||
* Display ability tree from topologically sorted list.
|
* Display ability tree from topologically sorted list.
|
||||||
*
|
*
|
||||||
* Signature: AbilityTreeRenderNode(atree: ATree) => null
|
* Signature: AbilityTreeRenderNode(atree: ATree) => RenderedATree ( Map[id, RenderedATNode] )
|
||||||
*/
|
*/
|
||||||
const atree_render = new (class extends ComputeNode {
|
const atree_render = new (class extends ComputeNode {
|
||||||
constructor() { super('builder-atree-render'); this.fail_cb = true; }
|
constructor() { super('builder-atree-render'); this.fail_cb = true; }
|
||||||
|
@ -60,14 +180,15 @@ const atree_render = new (class extends ComputeNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
//for some reason we have to cast to string
|
//for some reason we have to cast to string
|
||||||
if (atree) { render_AT(document.getElementById("atree-ui"), document.getElementById("atree-active"), atree); }
|
let ret = null;
|
||||||
|
if (atree) { ret = render_AT(document.getElementById("atree-ui"), document.getElementById("atree-active"), atree); }
|
||||||
|
|
||||||
//Toggle on, previously was toggled off
|
//Toggle on, previously was toggled off
|
||||||
toggle_tab('atree-dropdown'); toggleButton('toggle-atree');
|
toggle_tab('atree-dropdown'); toggleButton('toggle-atree');
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
atree_render.link_to(atree_node);
|
return ret;
|
||||||
|
}
|
||||||
|
})().link_to(atree_node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a reverse topological sort of the tree in the result list.
|
* Create a reverse topological sort of the tree in the result list.
|
||||||
|
@ -89,15 +210,46 @@ function topological_sort_tree(tree, res, mark_state) {
|
||||||
res.push(tree);
|
res.push(tree);
|
||||||
}
|
}
|
||||||
// these cases are not needed. Case 1 does nothing, case 2 should never happen.
|
// these cases are not needed. Case 1 does nothing, case 2 should never happen.
|
||||||
// else if (state === true) {
|
// else if (state === true) { return; } // permanent mark.
|
||||||
// // permanent mark.
|
// else if (state === false) { throw "not a DAG"; } // temporary mark.
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// else if (state === false) {
|
|
||||||
// // temporary mark.
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect abilities and condense them into a list of "final abils".
|
||||||
|
*/
|
||||||
|
const atree_merge = new (class extends ComputeNode {
|
||||||
|
constructor() { super('builder-atree-merge'); }
|
||||||
|
|
||||||
|
compute_func(input_map) {
|
||||||
|
const build = input_map.get('build');
|
||||||
|
const atree_state = input_map.get('atree-state');
|
||||||
|
const atree_order = input_map.get('atree');
|
||||||
|
|
||||||
|
let abils_merged = new Map();
|
||||||
|
for (const abil of default_abils[build.weapon.statMap.get('type')]) {
|
||||||
|
abils_merged.set(abil.id, deepcopy(abil));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const node of atree_order) {
|
||||||
|
const abil_id = node.ability.id;
|
||||||
|
if (!atree_state.get(abil_id).active) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const abil = node.ability;
|
||||||
|
|
||||||
|
if (abils_merged.has(abil.base_abil)) {
|
||||||
|
// Merge abilities.
|
||||||
|
// TODO: What if there is more than one base abil?
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
abils_merged.set(abil_id, deepcopy(abil));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return abils_merged;
|
||||||
|
}
|
||||||
|
})().link_to(atree_node, 'atree').link_to(atree_render, 'atree-state'); // TODO: THIS IS WRONG!!!!! Need one "collect" node...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** The main function for rendering an ability tree.
|
/** The main function for rendering an ability tree.
|
||||||
*
|
*
|
||||||
|
@ -154,21 +306,21 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
let atree_connectors_map = new Map()
|
let atree_connectors_map = new Map()
|
||||||
let max_row = 0;
|
let max_row = 0;
|
||||||
for (const i of tree) {
|
for (const i of tree) {
|
||||||
atree_map.set(i.node.id, {node: i.node, connectors: new Map(), active: false});
|
atree_map.set(i.ability.id, {ability: i.ability, connectors: new Map(), active: false});
|
||||||
if (i.node.display.row > max_row) {
|
if (i.ability.display.row > max_row) {
|
||||||
max_row = i.node.display.row;
|
max_row = i.ability.display.row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Copy graph structure.
|
// Copy graph structure.
|
||||||
for (const i of tree) {
|
for (const i of tree) {
|
||||||
let node_wrapper = atree_map.get(i.node.id);
|
let node_wrapper = atree_map.get(i.ability.id);
|
||||||
node_wrapper.parents = [];
|
node_wrapper.parents = [];
|
||||||
node_wrapper.children = [];
|
node_wrapper.children = [];
|
||||||
for (const parent of i.parents) {
|
for (const parent of i.parents) {
|
||||||
node_wrapper.parents.push(atree_map.get(parent.node.id));
|
node_wrapper.parents.push(atree_map.get(parent.ability.id));
|
||||||
}
|
}
|
||||||
for (const child of i.children) {
|
for (const child of i.children) {
|
||||||
node_wrapper.children.push(atree_map.get(child.node.id));
|
node_wrapper.children.push(atree_map.get(child.ability.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,51 +343,54 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const _node of tree) {
|
for (const _node of tree) {
|
||||||
let node_wrap = atree_map.get(_node.node.id);
|
let node_wrap = atree_map.get(_node.ability.id);
|
||||||
let node = _node.node;
|
let ability = _node.ability;
|
||||||
|
|
||||||
// create connectors based on parent location
|
// create connectors based on parent location
|
||||||
for (let parent of node_wrap.parents) {
|
for (let parent of node_wrap.parents) {
|
||||||
node_wrap.connectors.set(parent, []);
|
node_wrap.connectors.set(parent, []);
|
||||||
|
|
||||||
let parent_node = parent.node;
|
let parent_abil = parent.ability;
|
||||||
const parent_id = parent_node.id;
|
const parent_id = parent_abil.id;
|
||||||
|
|
||||||
let connect_elem = document.createElement("div");
|
let connect_elem = document.createElement("div");
|
||||||
connect_elem.style = "background-size: cover; width: 100%; height: 100%;";
|
connect_elem.style = "background-size: cover; width: 100%; height: 100%;";
|
||||||
// connect up
|
// connect up
|
||||||
for (let i = node.display.row - 1; i > parent_node.display.row; i--) {
|
for (let i = ability.display.row - 1; i > parent_abil.display.row; i--) {
|
||||||
|
const coord = i + "," + ability.display.col;
|
||||||
let connector = connect_elem.cloneNode();
|
let connector = connect_elem.cloneNode();
|
||||||
node_wrap.connectors.get(parent).push(i + "," + node.display.col);
|
node_wrap.connectors.get(parent).push(coord);
|
||||||
resolve_connector(atree_connectors_map, i + "," + node.display.col, {connector: connector, connections: [0, 0, 1, 1]});
|
resolve_connector(atree_connectors_map, coord, {connector: connector, connections: [0, 0, 1, 1]});
|
||||||
}
|
}
|
||||||
// connect horizontally
|
// connect horizontally
|
||||||
let min = Math.min(parent_node.display.col, node.display.col);
|
let min = Math.min(parent_abil.display.col, ability.display.col);
|
||||||
let max = Math.max(parent_node.display.col, node.display.col);
|
let max = Math.max(parent_abil.display.col, ability.display.col);
|
||||||
for (let i = min + 1; i < max; i++) {
|
for (let i = min + 1; i < max; i++) {
|
||||||
|
const coord = parent_abil.display.row + "," + i;
|
||||||
let connector = connect_elem.cloneNode();
|
let connector = connect_elem.cloneNode();
|
||||||
node_wrap.connectors.get(parent).push(parent_node.display.row + "," + i);
|
node_wrap.connectors.get(parent).push(coord);
|
||||||
resolve_connector(atree_connectors_map, parent_node.display.row + "," + i, {connector: connector, connections: [1, 1, 0, 0]});
|
resolve_connector(atree_connectors_map, coord, {connector: connector, connections: [1, 1, 0, 0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect corners
|
// connect corners
|
||||||
if (parent_node.display.row != node.display.row && parent_node.display.col != node.display.col) {
|
if (parent_abil.display.row != ability.display.row && parent_abil.display.col != ability.display.col) {
|
||||||
|
const coord = parent_abil.display.row + "," + ability.display.col;
|
||||||
let connector = connect_elem.cloneNode();
|
let connector = connect_elem.cloneNode();
|
||||||
node_wrap.connectors.get(parent).push(parent_node.display.row + "," + node.display.col);
|
node_wrap.connectors.get(parent).push(coord);
|
||||||
let connections = [0, 0, 0, 1];
|
let connections = [0, 0, 0, 1];
|
||||||
if (parent_node.display.col > node.display.col) {
|
if (parent_abil.display.col > ability.display.col) {
|
||||||
connections[1] = 1;
|
connections[1] = 1;
|
||||||
}
|
}
|
||||||
else {// if (parent_node.display.col < node.display.col && (parent_node.display.row != node.display.row)) {
|
else {// if (parent_node.display.col < node.display.col && (parent_node.display.row != node.display.row)) {
|
||||||
connections[0] = 1;
|
connections[0] = 1;
|
||||||
}
|
}
|
||||||
resolve_connector(atree_connectors_map, parent_node.display.row + "," + node.display.col, {connector: connector, connections: connections});
|
resolve_connector(atree_connectors_map, coord, {connector: connector, connections: connections});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create node
|
// create node
|
||||||
let node_elem = document.createElement('div');
|
let node_elem = document.createElement('div');
|
||||||
let icon = node.display.icon;
|
let icon = ability.display.icon;
|
||||||
if (icon === undefined) {
|
if (icon === undefined) {
|
||||||
icon = "node";
|
icon = "node";
|
||||||
}
|
}
|
||||||
|
@ -268,15 +423,15 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
|
|
||||||
let active_tooltip_title = document.createElement('b');
|
let active_tooltip_title = document.createElement('b');
|
||||||
active_tooltip_title.classList.add("scaled-font");
|
active_tooltip_title.classList.add("scaled-font");
|
||||||
active_tooltip_title.innerHTML = node.display_name;
|
active_tooltip_title.innerHTML = ability.display_name;
|
||||||
|
|
||||||
let active_tooltip_desc = document.createElement('p');
|
let active_tooltip_desc = document.createElement('p');
|
||||||
active_tooltip_desc.classList.add("scaled-font-sm", "my-0", "mx-1", "text-wrap");
|
active_tooltip_desc.classList.add("scaled-font-sm", "my-0", "mx-1", "text-wrap");
|
||||||
active_tooltip_desc.textContent = node.desc;
|
active_tooltip_desc.textContent = ability.desc;
|
||||||
|
|
||||||
let active_tooltip_cost = document.createElement('p');
|
let active_tooltip_cost = document.createElement('p');
|
||||||
active_tooltip_cost.classList.add("scaled-font-sm", "my-0", "mx-1", "text-start");
|
active_tooltip_cost.classList.add("scaled-font-sm", "my-0", "mx-1", "text-start");
|
||||||
active_tooltip_cost.textContent = "Cost: " + node.cost + " AP";
|
active_tooltip_cost.textContent = "Cost: " + ability.cost + " AP";
|
||||||
|
|
||||||
active_tooltip.appendChild(active_tooltip_title);
|
active_tooltip.appendChild(active_tooltip_title);
|
||||||
active_tooltip.appendChild(active_tooltip_desc);
|
active_tooltip.appendChild(active_tooltip_desc);
|
||||||
|
@ -284,7 +439,7 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
|
|
||||||
node_tooltip = active_tooltip.cloneNode(true);
|
node_tooltip = active_tooltip.cloneNode(true);
|
||||||
|
|
||||||
active_tooltip.id = "atree-ab-" + node.id;
|
active_tooltip.id = "atree-ab-" + ability.id;
|
||||||
|
|
||||||
node_tooltip.style.position = "absolute";
|
node_tooltip.style.position = "absolute";
|
||||||
node_tooltip.style.zIndex = "100";
|
node_tooltip.style.zIndex = "100";
|
||||||
|
@ -294,17 +449,23 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
|
|
||||||
node_elem.addEventListener('click', function(e) {
|
node_elem.addEventListener('click', function(e) {
|
||||||
if (e.target !== this && e.target!== this.children[0]) {return;}
|
if (e.target !== this && e.target!== this.children[0]) {return;}
|
||||||
let tooltip = document.getElementById("atree-ab-" + node.id);
|
let tooltip = document.getElementById("atree-ab-" + ability.id);
|
||||||
if (tooltip.style.display == "block") {
|
console.log(node_wrap);
|
||||||
|
console.log(node_wrap.active);
|
||||||
|
console.log(tooltip.style.display);
|
||||||
|
if (tooltip.style.display === "block") {
|
||||||
tooltip.style.display = "none";
|
tooltip.style.display = "none";
|
||||||
this.classList.remove("atree-selected");
|
this.classList.remove("atree-selected");
|
||||||
abil_points_current -= node.cost;
|
abil_points_current -= ability.cost;
|
||||||
|
node_wrap.active = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tooltip.style.display = "block";
|
tooltip.style.display = "block";
|
||||||
this.classList.add("atree-selected");
|
this.classList.add("atree-selected");
|
||||||
abil_points_current += node.cost;
|
abil_points_current += ability.cost;
|
||||||
|
node_wrap.active = true;
|
||||||
};
|
};
|
||||||
|
console.log(node_wrap);
|
||||||
document.getElementById("active_AP_cost").textContent = abil_points_current;
|
document.getElementById("active_AP_cost").textContent = abil_points_current;
|
||||||
atree_toggle_state(atree_connectors_map, node_wrap);
|
atree_toggle_state(atree_connectors_map, node_wrap);
|
||||||
});
|
});
|
||||||
|
@ -325,10 +486,12 @@ function render_AT(UI_elem, list_elem, tree) {
|
||||||
tooltip.style.display = "none";
|
tooltip.style.display = "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("atree-row-" + node.display.row).children[node.display.col].appendChild(node_elem);
|
document.getElementById("atree-row-" + ability.display.row).children[ability.display.col].appendChild(node_elem);
|
||||||
};
|
};
|
||||||
console.log(atree_connectors_map);
|
console.log(atree_connectors_map);
|
||||||
atree_render_connection(atree_connectors_map);
|
atree_render_connection(atree_connectors_map);
|
||||||
|
|
||||||
|
return atree_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
// resolve connector conflict, when they occupy the same cell.
|
// resolve connector conflict, when they occupy the same cell.
|
||||||
|
@ -380,7 +543,6 @@ function atree_render_connection(atree_connectors_map) {
|
||||||
set_connector_type(connector_info);
|
set_connector_type(connector_info);
|
||||||
connector_elem.style.backgroundImage = "url('../media/atree/connect_"+connector_info.type+".png')";
|
connector_elem.style.backgroundImage = "url('../media/atree/connect_"+connector_info.type+".png')";
|
||||||
connector_info.highlight = [0, 0, 0, 0];
|
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]];
|
let target_elem = document.getElementById("atree-row-" + i.split(",")[0]).children[i.split(",")[1]];
|
||||||
if (target_elem.children.length != 0) {
|
if (target_elem.children.length != 0) {
|
||||||
// janky special case...
|
// janky special case...
|
||||||
|
@ -392,11 +554,12 @@ function atree_render_connection(atree_connectors_map) {
|
||||||
|
|
||||||
// toggle the state of a node.
|
// toggle the state of a node.
|
||||||
function atree_toggle_state(atree_connectors_map, node_wrapper) {
|
function atree_toggle_state(atree_connectors_map, node_wrapper) {
|
||||||
let node = node_wrapper.node;
|
console.log(node_wrapper);
|
||||||
const new_state = !node_wrapper.active;
|
const new_state = !node_wrapper.active;
|
||||||
node_wrapper.active = new_state
|
node_wrapper.active = new_state
|
||||||
for (const parent of node_wrapper.parents) {
|
for (const parent of node_wrapper.parents) {
|
||||||
if (parent.active) {
|
if (parent.active) {
|
||||||
|
console.log(parent);
|
||||||
atree_set_edge(atree_connectors_map, parent, node_wrapper, new_state); // self->parent state only changes if parent is on
|
atree_set_edge(atree_connectors_map, parent, node_wrapper, new_state); // self->parent state only changes if parent is on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,10 +584,10 @@ function atree_update_connector() {
|
||||||
|
|
||||||
function atree_set_edge(atree_connectors_map, parent, child, state) {
|
function atree_set_edge(atree_connectors_map, parent, child, state) {
|
||||||
const connectors = child.connectors.get(parent);
|
const connectors = child.connectors.get(parent);
|
||||||
const parent_row = parent.node.display.row;
|
const parent_row = parent.ability.display.row;
|
||||||
const parent_col = parent.node.display.col;
|
const parent_col = parent.ability.display.col;
|
||||||
const child_row = child.node.display.row;
|
const child_row = child.ability.display.row;
|
||||||
const child_col = child.node.display.col;
|
const child_col = child.ability.display.col;
|
||||||
|
|
||||||
let state_delta = (state ? 1 : -1);
|
let state_delta = (state ? 1 : -1);
|
||||||
let child_side_idx = (parent_col > child_col ? 0 : 1);
|
let child_side_idx = (parent_col > child_col ? 0 : 1);
|
||||||
|
|
|
@ -3,8 +3,6 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Arrow Shield",
|
"display_name": "Arrow Shield",
|
||||||
"desc": "Create a shield around you that deal damage and knockback mobs when triggered. (2 Charges)",
|
"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": ["Power Shots", "Cheaper Escape"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -61,8 +59,7 @@ const atrees = {
|
||||||
"aoe": 0,
|
"aoe": 0,
|
||||||
"range": 0
|
"range": 0
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [{
|
||||||
{
|
|
||||||
"type": "replace_spell",
|
"type": "replace_spell",
|
||||||
"name": "Escape",
|
"name": "Escape",
|
||||||
"cost": 25,
|
"cost": 25,
|
||||||
|
@ -72,27 +69,17 @@ const atrees = {
|
||||||
"scaling": "spell",
|
"scaling": "spell",
|
||||||
"display": "Total Damage",
|
"display": "Total Damage",
|
||||||
"parts": [
|
"parts": [
|
||||||
{
|
|
||||||
"name": "None",
|
|
||||||
"type": "damage",
|
|
||||||
"multipliers": [0, 0, 0, 0, 0, 0]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Total Damage",
|
"name": "Total Damage",
|
||||||
"type": "total",
|
"type": "total",
|
||||||
"hits": {
|
"hits": {}
|
||||||
"None": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Arrow Bomb",
|
"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)",
|
"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": [],
|
"parents": [],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -105,8 +92,7 @@ const atrees = {
|
||||||
"aoe": 4.5,
|
"aoe": 4.5,
|
||||||
"range": 26
|
"range": 26
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [{
|
||||||
{
|
|
||||||
"type": "replace_spell",
|
"type": "replace_spell",
|
||||||
"name": "Arrow Bomb",
|
"name": "Arrow Bomb",
|
||||||
"cost": 50,
|
"cost": 50,
|
||||||
|
@ -129,14 +115,12 @@ const atrees = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Heart Shatter",
|
"display_name": "Heart Shatter",
|
||||||
"desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",
|
"desc": "If you hit a mob directly with Arrow Bomb, shatter its heart and deal bonus damage.",
|
||||||
"archetype": "",
|
"base_abil": "Arrow Bomb",
|
||||||
"archetype_req": 0,
|
|
||||||
"parents": ["Bow Proficiency I"],
|
"parents": ["Bow Proficiency I"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -146,18 +130,13 @@ const atrees = {
|
||||||
"col": 4
|
"col": 4
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [{
|
||||||
{
|
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Arrow Bomb",
|
"target_part": "Arrow Bomb",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"multipliers": [100, 0, 0, 0, 0, 0]
|
"multipliers": [100, 0, 0, 0, 0, 0]
|
||||||
},
|
}]
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Fire Creep",
|
"display_name": "Fire Creep",
|
||||||
|
@ -380,6 +359,7 @@ const atrees = {
|
||||||
"aoe": 8,
|
"aoe": 8,
|
||||||
"duration": 120
|
"duration": 120
|
||||||
},
|
},
|
||||||
|
"effects": [{
|
||||||
"type": "stat_bonus",
|
"type": "stat_bonus",
|
||||||
"bonuses": [
|
"bonuses": [
|
||||||
{
|
{
|
||||||
|
@ -388,6 +368,7 @@ const atrees = {
|
||||||
"value": 20
|
"value": 20
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Basaltic Trap",
|
"display_name": "Basaltic Trap",
|
||||||
|
@ -715,6 +696,7 @@ const atrees = {
|
||||||
"focus": 1,
|
"focus": 1,
|
||||||
"timer": 5
|
"timer": 5
|
||||||
},
|
},
|
||||||
|
"effects": [{
|
||||||
"type": "stat_bonus",
|
"type": "stat_bonus",
|
||||||
"bonuses": [
|
"bonuses": [
|
||||||
{
|
{
|
||||||
|
@ -723,6 +705,7 @@ const atrees = {
|
||||||
"value": 50
|
"value": 50
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Call of the Hound",
|
"display_name": "Call of the Hound",
|
||||||
|
@ -921,7 +904,8 @@ const atrees = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 2.5,
|
"range": 2.5,
|
||||||
"slowness": 0.3
|
"slowness": 0.3
|
||||||
}
|
},
|
||||||
|
"effects": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "All-Seeing Panoptes",
|
"display_name": "All-Seeing Panoptes",
|
||||||
|
@ -1266,7 +1250,8 @@ const atrees = {
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"shieldCharges": 2
|
"shieldCharges": 2
|
||||||
}
|
},
|
||||||
|
"effects": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Stormy Feet",
|
"display_name": "Stormy Feet",
|
||||||
|
@ -1284,8 +1269,7 @@ const atrees = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"duration": 60
|
"duration": 60
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [{
|
||||||
{
|
|
||||||
"type": "stat_bonus",
|
"type": "stat_bonus",
|
||||||
"bonuses": [
|
"bonuses": [
|
||||||
{
|
{
|
||||||
|
@ -1294,8 +1278,7 @@ const atrees = {
|
||||||
"value": 20
|
"value": 20
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Refined Gunpowder",
|
"display_name": "Refined Gunpowder",
|
||||||
|
@ -2028,8 +2011,6 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Bash",
|
"display_name": "Bash",
|
||||||
"desc": "Violently bash the ground, dealing high damage in a large area",
|
"desc": "Violently bash the ground, dealing high damage in a large area",
|
||||||
"archetype": "",
|
|
||||||
"archetype_req": 0,
|
|
||||||
"parents": [],
|
"parents": [],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -2073,8 +2054,7 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Spear Proficiency 1",
|
"display_name": "Spear Proficiency 1",
|
||||||
"desc": "Improve your Main Attack's damage and range w/ spear",
|
"desc": "Improve your Main Attack's damage and range w/ spear",
|
||||||
"archetype": "",
|
"base_abil": 999,
|
||||||
"archetype_req": 0,
|
|
||||||
"parents": ["Bash"],
|
"parents": ["Bash"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -2104,8 +2084,7 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Cheaper Bash",
|
"display_name": "Cheaper Bash",
|
||||||
"desc": "Reduce the Mana cost of Bash",
|
"desc": "Reduce the Mana cost of Bash",
|
||||||
"archetype": "",
|
"base_abil": "Bash",
|
||||||
"archetype_req": 0,
|
|
||||||
"parents": ["Spear Proficiency 1"],
|
"parents": ["Spear Proficiency 1"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -2129,9 +2108,8 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Double Bash",
|
"display_name": "Double Bash",
|
||||||
"desc": "Bash will hit a second time at a farther range",
|
"desc": "Bash will hit a second time at a farther range",
|
||||||
"archetype": "",
|
|
||||||
"archetype_req": 0,
|
|
||||||
"parents": ["Spear Proficiency 1"],
|
"parents": ["Spear Proficiency 1"],
|
||||||
|
"base_abil": "Bash",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
|
@ -2634,7 +2612,6 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 1,
|
"base_spell": 1,
|
||||||
"target_part": "Total Damage",
|
"target_part": "Total Damage",
|
||||||
"cost": 0,
|
|
||||||
"hits": {
|
"hits": {
|
||||||
"Single Hit": 2
|
"Single Hit": 2
|
||||||
}
|
}
|
||||||
|
@ -2643,7 +2620,6 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 1,
|
"base_spell": 1,
|
||||||
"target_part": "Single Hit",
|
"target_part": "Single Hit",
|
||||||
"cost": 0,
|
|
||||||
"multipliers": [-20, 0, 0, 0, 0, 0]
|
"multipliers": [-20, 0, 0, 0, 0, 0]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2670,14 +2646,12 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Fireworks",
|
"target_part": "Fireworks",
|
||||||
"cost": 0,
|
|
||||||
"multipliers": [80, 0, 20, 0, 0, 0]
|
"multipliers": [80, 0, 20, 0, 0, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Total Damage",
|
"target_part": "Total Damage",
|
||||||
"cost": 0,
|
|
||||||
"hits": {
|
"hits": {
|
||||||
"Fireworks": 1
|
"Fireworks": 1
|
||||||
}
|
}
|
||||||
|
@ -2740,7 +2714,6 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 2,
|
"base_spell": 2,
|
||||||
"target_part": "Flyby Jab",
|
"target_part": "Flyby Jab",
|
||||||
"cost": 0,
|
|
||||||
"multipliers": [20, 0, 0, 0, 0, 40]
|
"multipliers": [20, 0, 0, 0, 0, 40]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2769,14 +2742,12 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Flaming Uppercut",
|
"target_part": "Flaming Uppercut",
|
||||||
"cost": 0,
|
|
||||||
"multipliers": [0, 0, 0, 0, 50, 0]
|
"multipliers": [0, 0, 0, 0, 50, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Flaming Uppercut Total Damage",
|
"target_part": "Flaming Uppercut Total Damage",
|
||||||
"cost": 0,
|
|
||||||
"hits": {
|
"hits": {
|
||||||
"Flaming Uppercut": 5
|
"Flaming Uppercut": 5
|
||||||
}
|
}
|
||||||
|
@ -2785,7 +2756,6 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Total Damage",
|
"target_part": "Total Damage",
|
||||||
"cost": 0,
|
|
||||||
"hits": {
|
"hits": {
|
||||||
"Flaming Uppercut": 5
|
"Flaming Uppercut": 5
|
||||||
}
|
}
|
||||||
|
@ -2807,8 +2777,7 @@ const atrees = {
|
||||||
"col": 7,
|
"col": 7,
|
||||||
"icon": "node_0"
|
"icon": "node_0"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {},
|
||||||
},
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
|
@ -2834,11 +2803,8 @@ const atrees = {
|
||||||
"col": 2,
|
"col": 2,
|
||||||
"icon": "node_3"
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {},
|
||||||
},
|
"effects": []
|
||||||
"effects": [
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -3646,6 +3612,7 @@ const atrees = {
|
||||||
"desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",
|
"desc": "While Corrupted, every 3% Health you lose will add +1 AoE to Bash (Max 10)",
|
||||||
"archetype": "Fallen",
|
"archetype": "Fallen",
|
||||||
"archetype_req": 8,
|
"archetype_req": 8,
|
||||||
|
"base_abil": "Bak'al's Grasp",
|
||||||
"parents": ["Tempest", "Uncontainable Corruption"],
|
"parents": ["Tempest", "Uncontainable Corruption"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -3663,8 +3630,9 @@ const atrees = {
|
||||||
"slider": true,
|
"slider": true,
|
||||||
"slider_name": "Corrupted",
|
"slider_name": "Corrupted",
|
||||||
"output": {
|
"output": {
|
||||||
"type": "stat",
|
"type": "prop",
|
||||||
"name": "bashAoE"
|
"abil": "Bash",
|
||||||
|
"name": "aoe"
|
||||||
},
|
},
|
||||||
"scaling": [1],
|
"scaling": [1],
|
||||||
"max": 10,
|
"max": 10,
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1093,6 +1093,7 @@ function builder_graph_init() {
|
||||||
stat_agg_node.link_to(edit_agg_node);
|
stat_agg_node.link_to(edit_agg_node);
|
||||||
build_disp_node.link_to(stat_agg_node, 'stats');
|
build_disp_node.link_to(stat_agg_node, 'stats');
|
||||||
atree_node.link_to(build_node, 'build');
|
atree_node.link_to(build_node, 'build');
|
||||||
|
atree_merge.link_to(build_node, 'build');
|
||||||
|
|
||||||
for (const input_node of item_nodes.concat(powder_nodes)) {
|
for (const input_node of item_nodes.concat(powder_nodes)) {
|
||||||
input_node.update();
|
input_node.update();
|
||||||
|
|
|
@ -240,6 +240,7 @@ spell_heal: {
|
||||||
|
|
||||||
const default_spells = {
|
const default_spells = {
|
||||||
wand: [{
|
wand: [{
|
||||||
|
type: "replace_spell", // not needed but makes this usable as an "abil part"
|
||||||
name: "Wand Melee", // TODO: name for melee attacks?
|
name: "Wand Melee", // TODO: name for melee attacks?
|
||||||
display_text: "Mage basic attack",
|
display_text: "Mage basic attack",
|
||||||
base_spell: 0,
|
base_spell: 0,
|
||||||
|
@ -247,7 +248,7 @@ const default_spells = {
|
||||||
display: "Melee",
|
display: "Melee",
|
||||||
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
||||||
}, {
|
}, {
|
||||||
name: "Heal", // TODO: name for melee attacks?
|
name: "Heal", // TODO: name for melee attacks? // JUST FOR TESTING...
|
||||||
display_text: "Heal spell!",
|
display_text: "Heal spell!",
|
||||||
base_spell: 1,
|
base_spell: 1,
|
||||||
display: "Total Heal",
|
display: "Total Heal",
|
||||||
|
@ -258,6 +259,7 @@ const default_spells = {
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
spear: [{
|
spear: [{
|
||||||
|
type: "replace_spell", // not needed but makes this usable as an "abil part"
|
||||||
name: "Melee", // TODO: name for melee attacks?
|
name: "Melee", // TODO: name for melee attacks?
|
||||||
display_text: "Warrior basic attack",
|
display_text: "Warrior basic attack",
|
||||||
base_spell: 0,
|
base_spell: 0,
|
||||||
|
@ -266,6 +268,7 @@ const default_spells = {
|
||||||
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
||||||
}],
|
}],
|
||||||
bow: [{
|
bow: [{
|
||||||
|
type: "replace_spell", // not needed but makes this usable as an "abil part"
|
||||||
name: "Bow Shot", // TODO: name for melee attacks?
|
name: "Bow Shot", // TODO: name for melee attacks?
|
||||||
display_text: "Archer basic attack",
|
display_text: "Archer basic attack",
|
||||||
base_spell: 0,
|
base_spell: 0,
|
||||||
|
@ -274,6 +277,7 @@ const default_spells = {
|
||||||
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
||||||
}],
|
}],
|
||||||
dagger: [{
|
dagger: [{
|
||||||
|
type: "replace_spell", // not needed but makes this usable as an "abil part"
|
||||||
name: "Melee", // TODO: name for melee attacks?
|
name: "Melee", // TODO: name for melee attacks?
|
||||||
display_text: "Assassin basic attack",
|
display_text: "Assassin basic attack",
|
||||||
base_spell: 0,
|
base_spell: 0,
|
||||||
|
@ -282,6 +286,7 @@ const default_spells = {
|
||||||
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
parts: [{ name: "Melee", multipliers: [100, 0, 0, 0, 0, 0] }]
|
||||||
}],
|
}],
|
||||||
relik: [{
|
relik: [{
|
||||||
|
type: "replace_spell", // not needed but makes this usable as an "abil part"
|
||||||
name: "Relik Melee", // TODO: name for melee attacks?
|
name: "Relik Melee", // TODO: name for melee attacks?
|
||||||
display_text: "Shaman basic attack",
|
display_text: "Shaman basic attack",
|
||||||
base_spell: 0,
|
base_spell: 0,
|
||||||
|
|
14
js/utils.js
14
js/utils.js
|
@ -499,3 +499,17 @@ function assert_error(func_binding, msg) {
|
||||||
}
|
}
|
||||||
throw new Error(msg ? msg : "Function didn't throw an error.");
|
throw new Error(msg ? msg : "Function didn't throw an error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep copy object/array of basic types.
|
||||||
|
*/
|
||||||
|
function deepcopy(obj) {
|
||||||
|
if (typeof(obj) !== 'object' || obj === null) { // null or value type
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
let ret = Array.isArray(obj) ? [] : {};
|
||||||
|
for (let key in obj) {
|
||||||
|
ret[key] = deepcopy(obj[key]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -14,16 +14,46 @@ with open("atree_constants.json") as f:
|
||||||
atree_data = json.loads(f.read())
|
atree_data = json.loads(f.read())
|
||||||
|
|
||||||
for _class, info in atree_data.items():
|
for _class, info in atree_data.items():
|
||||||
|
def translate(path, ref):
|
||||||
|
ref_dict = info
|
||||||
|
for x in path:
|
||||||
|
ref_dict = ref_dict[x]
|
||||||
|
ref_dict[ref] = id_data[_class][ref_dict[ref]]
|
||||||
|
|
||||||
for abil in range(len(info)):
|
for abil in range(len(info)):
|
||||||
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
|
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
|
||||||
for ref in range(len(info[abil]["parents"])):
|
for ref in range(len(info[abil]["parents"])):
|
||||||
info[abil]["parents"][ref] = id_data[_class][info[abil]["parents"][ref]]
|
translate([abil, "parents"], ref)
|
||||||
|
|
||||||
for ref in range(len(info[abil]["dependencies"])):
|
for ref in range(len(info[abil]["dependencies"])):
|
||||||
info[abil]["dependencies"][ref] = id_data[_class][info[abil]["dependencies"][ref]]
|
translate([abil, "dependencies"], ref)
|
||||||
|
|
||||||
for ref in range(len(info[abil]["blockers"])):
|
for ref in range(len(info[abil]["blockers"])):
|
||||||
info[abil]["blockers"][ref] = id_data[_class][info[abil]["blockers"][ref]]
|
translate([abil, "blockers"], ref)
|
||||||
|
|
||||||
|
if "base_abil" in info[abil]:
|
||||||
|
base_abil_name = info[abil]["base_abil"]
|
||||||
|
if base_abil_name in id_data[_class]:
|
||||||
|
translate([abil], "base_abil")
|
||||||
|
|
||||||
|
if "effects" not in info[abil]:
|
||||||
|
print(info[abil])
|
||||||
|
info[abil]["effects"] = []
|
||||||
|
for effect in info[abil]["effects"]:
|
||||||
|
if effect["type"] == "raw_stat":
|
||||||
|
for bonus in effect["bonuses"]:
|
||||||
|
if "abil" in bonus:
|
||||||
|
bonus["abil"] = id_data[_class][bonus["abil"]]
|
||||||
|
|
||||||
|
elif effect["type"] == "stat_scaling":
|
||||||
|
if "inputs" in effect: # Might not exist for sliders
|
||||||
|
for _input in effect["inputs"]:
|
||||||
|
if "abil" in _input:
|
||||||
|
_input["abil"] = id_data[_class][_input["abil"]]
|
||||||
|
|
||||||
|
if "abil" in effect["output"]:
|
||||||
|
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
|
||||||
|
|
||||||
|
|
||||||
with open('atree_constants_idfied.json', 'w', encoding='utf-8') as abil_dest:
|
with open('atree_constants_idfied.json', 'w', encoding='utf-8') as abil_dest:
|
||||||
json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4)
|
json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4)
|
Loading…
Reference in a new issue