diff --git a/builder/index.html b/builder/index.html
index 1ad21f5..f719ac6 100644
--- a/builder/index.html
+++ b/builder/index.html
@@ -1275,20 +1275,7 @@
-
-
-
-
spell4
-
Spell 4
+
Input a weapon to see abilities!
diff --git a/js/atree.js b/js/atree.js
index 6295a58..f87e83b 100644
--- a/js/atree.js
+++ b/js/atree.js
@@ -141,7 +141,7 @@ const atree_node = new (class extends ComputeNode {
const [player_class] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element
const atree_raw = atrees[player_class];
- if (!atree_raw) return null;
+ if (!atree_raw) return [];
let atree_map = new Map();
let atree_head;
@@ -308,6 +308,8 @@ const atree_validate = new (class extends ComputeNode {
const atree_state = input_map.get('atree-state');
const atree_order = input_map.get('atree');
+ if (atree_order.length == 0) { return [0, ['no atree data']]; }
+
let errors = [];
let reachable = new Map();
atree_dfs_mark(atree_order[0], atree_state, reachable);
@@ -473,7 +475,7 @@ const atree_collect_spells = new (class extends ComputeNode {
case 'add_spell_prop': {
const { base_spell, target_part = null, cost = 0, behavior = 'merge'} = effect;
if (base_spell !== base_spell_id) { continue; } // TODO: redundant? if we assume abils only affect one spell
- ret_spell.cost += cost;
+ if ('cost' in ret_spell) { ret_spell.cost += cost; }
if (target_part === null) {
continue;
diff --git a/js/build_encode_decode.js b/js/build_encode_decode.js
index bf7be38..686b3fd 100644
--- a/js/build_encode_decode.js
+++ b/js/build_encode_decode.js
@@ -200,7 +200,7 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
}
build_string += tome_string;
- if (atree_state.get(atree[0].ability.id).active) {
+ if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) {
build_version = Math.max(build_version, 7);
const bitvec = encode_atree(atree, atree_state);
build_string += bitvec.toB64();
diff --git a/js/builder_graph.js b/js/builder_graph.js
index 1c0c5f2..5f3077c 100644
--- a/js/builder_graph.js
+++ b/js/builder_graph.js
@@ -502,8 +502,8 @@ class SpellSelectNode extends ComputeNode {
*/
function getDefenseStats(stats) {
let defenseStats = [];
- let def_pct = skillPointsToPercentage(stats.get('def'));
- let agi_pct = skillPointsToPercentage(stats.get('agi'));
+ let def_pct = skillPointsToPercentage(stats.get('def')) * 0.867; // lol
+ let agi_pct = skillPointsToPercentage(stats.get('agi')) * 0.951; // lol2
//total hp
let totalHp = stats.get("hp") + stats.get("hpBonus");
if (totalHp < 5) totalHp = 5;
@@ -511,7 +511,10 @@ function getDefenseStats(stats) {
//EHP
let ehp = [totalHp, totalHp];
let defMult = (2 - stats.get("classDef")) * stats.get("defMultiplier");
- ehp[0] /= (1-def_pct)*(1-agi_pct)*defMult;
+ // newehp = oldehp / [0.1 * A(x) + (1 - A(x)) * (1 - D(x))]
+ ehp[0] = ehp[0] / (0.1*agi_pct + (1-agi_pct) * (1-def_pct));
+ ehp[0] /= defMult;
+ // ehp[0] /= (1-def_pct)*(1-agi_pct)*defMult;
ehp[1] /= (1-def_pct)*defMult;
defenseStats.push(ehp);
//HPR
@@ -763,6 +766,7 @@ class DisplayBuildWarningsNode extends ComputeNode {
];
let skp_effects = ["% more damage dealt.","% chance to crit.","% spell cost reduction.","% less damage taken.","% chance to dodge."];
let total_assigned = 0;
+ const mults = [1, 1, 0.5, 0.867, 0.951];
for (let i in skp_order){ //big bren
const assigned = skillpoints[i] - base_totals[i] + min_assigned[i]
setText(skp_order[i] + "-skp-base", "Original: " + base_totals[i]);
@@ -770,7 +774,7 @@ class DisplayBuildWarningsNode extends ComputeNode {
setValue(skp_order[i] + "-skp", skillpoints[i]);
let linebreak = document.createElement("br");
linebreak.classList.add("itemp");
- setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100).toFixed(1).concat(skp_effects[i]));
+ setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100*mults[i]).toFixed(1).concat(skp_effects[i]));
document.getElementById(skp_order[i]+"-warnings").textContent = ''
if (assigned > 100) {
let skp_warning = document.createElement("p");