Patch Water Mastery fluid healing interaction
according to zeer, all stat scaling is applied after total stats
This commit is contained in:
parent
f9e783e56e
commit
7919647372
2 changed files with 58 additions and 62 deletions
101
js/atree.js
101
js/atree.js
|
@ -696,7 +696,7 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
let slider_container = gen_slider_labeled(slider_info);
|
||||
document.getElementById("boost-sliders").appendChild(slider_container);
|
||||
slider_info.slider = document.getElementById(slider_info.id);
|
||||
slider_info.slider.addEventListener("change", (e) => atree_stats.mark_dirty().update());
|
||||
slider_info.slider.addEventListener("change", (e) => atree_scaling.mark_dirty().update());
|
||||
}
|
||||
for (const [button_name, button_info] of button_map.entries()) {
|
||||
let button = make_elem('button', ["button-boost", "border-0", "text-white", "dark-8u", "dark-shadow-sm", "m-1"], {
|
||||
|
@ -709,7 +709,7 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
} else {
|
||||
button.classList.add("toggleOn");
|
||||
}
|
||||
atree_stats.mark_dirty().update()
|
||||
atree_scaling.mark_dirty().update()
|
||||
});
|
||||
button_info.button = button;
|
||||
document.getElementById("boost-toggles").appendChild(button);
|
||||
|
@ -718,20 +718,19 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
}
|
||||
})().link_to(atree_node, 'atree-order').link_to(atree_merge, 'atree-merged').link_to(atree_render_active, 'atree-elements');
|
||||
|
||||
|
||||
/**
|
||||
* Collect stats from ability tree.
|
||||
* Return StatMap of added stats (incl. cost modifications as raw cost)
|
||||
* Scaling stats from ability tree.
|
||||
* Return StatMap of added stats,
|
||||
*
|
||||
* Signature: AbilityTreeStatsNode(atree-merged: MergedATree, build: Build,
|
||||
* Signature: AbilityTreeScalingNode(atree-merged: MergedATree, scale-scats: StatMap,
|
||||
* atree-interactive: [Map<str, slider_info>, Map<str, button_info>]) => StatMap
|
||||
*/
|
||||
const atree_stats = new (class extends ComputeNode {
|
||||
constructor() { super('atree-stats-collector'); }
|
||||
const atree_scaling = new (class extends ComputeNode {
|
||||
constructor() { super('atree-scaling-collector'); }
|
||||
|
||||
compute_func(input_map) {
|
||||
const atree_merged = input_map.get('atree-merged');
|
||||
const item_stats = input_map.get('build').statMap;
|
||||
const pre_scale_stats = input_map.get('scale-stats');
|
||||
const [slider_map, button_map] = input_map.get('atree-interactive');
|
||||
|
||||
let ret_effects = new Map();
|
||||
|
@ -741,41 +740,26 @@ const atree_stats = new (class extends ComputeNode {
|
|||
for (const effect of abil.effects) {
|
||||
switch (effect.type) {
|
||||
case 'stat_scaling':
|
||||
if (effect.slider) {
|
||||
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
|
||||
const slider_val = slider_map.get(effect.slider_name).slider.value;
|
||||
const {round = true} = effect;
|
||||
let total = parseInt(slider_val) * effect.scaling[0];
|
||||
if (round) { total = Math.floor(round_near(total)); }
|
||||
if ('max' in effect && total > effect.max) { total = effect.max; }
|
||||
if (Array.isArray(effect.output)) {
|
||||
for (const output of effect.output) {
|
||||
if (output.type === 'stat') { // TODO: prop
|
||||
merge_stat(ret_effects, output.name, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (effect.output.type === 'stat') {
|
||||
merge_stat(ret_effects, effect.output.name, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
let total = 0;
|
||||
const {round = true, slider = false, scaling = [0]} = effect;
|
||||
if (slider) {
|
||||
const slider_val = slider_map.get(effect.slider_name).slider.value;
|
||||
total = parseInt(slider_val) * scaling[0];
|
||||
}
|
||||
else {
|
||||
// TODO: type: prop?
|
||||
let total = 0;
|
||||
const {round = true} = effect;
|
||||
for (const [scaling, input] of zip2(effect.scaling, effect.inputs)) {
|
||||
total += scaling * item_stats.get(input.name);
|
||||
for (const [_scaling, input] of zip2(scaling, effect.inputs)) {
|
||||
total += _scaling * pre_scale_stats.get(input.name);
|
||||
}
|
||||
}
|
||||
|
||||
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
|
||||
if (round) { total = Math.floor(round_near(total)); }
|
||||
if (total < 0) { total = 0; } // Normal stat scaling will not go negative.
|
||||
if ('max' in effect && total > effect.max) { total = effect.max; }
|
||||
// TODO: output (list...)
|
||||
if (Array.isArray(effect.output)) {
|
||||
for (const output of effect.output) {
|
||||
if (output.type === 'stat') {
|
||||
if (output.type === 'stat') { // TODO: prop
|
||||
merge_stat(ret_effects, output.name, total);
|
||||
}
|
||||
}
|
||||
|
@ -787,6 +771,31 @@ const atree_stats = new (class extends ComputeNode {
|
|||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret_effects;
|
||||
}
|
||||
})().link_to(atree_merge, 'atree-merged').link_to(atree_make_interactives, 'atree-interactive');
|
||||
|
||||
/**
|
||||
* Collect stats from ability tree.
|
||||
* Return StatMap of added stats.
|
||||
*
|
||||
* Signature: AbilityTreeStatsNode(atree-merged: MergedATree) => StatMap
|
||||
*/
|
||||
const atree_stats = new (class extends ComputeNode {
|
||||
constructor() { super('atree-stats-collector'); }
|
||||
|
||||
compute_func(input_map) {
|
||||
const atree_merged = input_map.get('atree-merged');
|
||||
|
||||
let ret_effects = new Map();
|
||||
for (const [abil_id, abil] of atree_merged.entries()) {
|
||||
if (abil.effects.length == 0) { continue; }
|
||||
|
||||
for (const effect of abil.effects) {
|
||||
switch (effect.type) {
|
||||
case 'raw_stat':
|
||||
// TODO: toggles...
|
||||
if (effect.toggle) {
|
||||
|
@ -801,27 +810,12 @@ const atree_stats = new (class extends ComputeNode {
|
|||
}
|
||||
}
|
||||
continue;
|
||||
case 'add_spell_prop':
|
||||
continue;
|
||||
// TODO unjankify....
|
||||
// costs are converted to raw cost ID
|
||||
// const { base_spell, cost = 0} = effect;
|
||||
// if (cost) {
|
||||
// const key = "spRaw"+base_spell;
|
||||
// if (ret_effects.has(key)) { ret_effects.set(key, ret_effects.get(key) + cost); }
|
||||
// else { ret_effects.set(key, cost); }
|
||||
// }
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret_effects.has('baseResist')) {
|
||||
merge_stat(ret_effects, "defMult", 1 - (ret_effects.get('baseResist') / 100));
|
||||
}
|
||||
return ret_effects;
|
||||
}
|
||||
})().link_to(atree_merge, 'atree-merged').link_to(atree_make_interactives, 'atree-interactive');
|
||||
|
||||
})().link_to(atree_merge, 'atree-merged');
|
||||
|
||||
/**
|
||||
* Construct compute nodes to link builder items and edit IDs to the appropriate display outputs.
|
||||
|
@ -844,16 +838,15 @@ class AbilityTreeEnsureNodesNode extends ComputeNode {
|
|||
this.build_node = build_node;
|
||||
this.stat_agg_node = stat_agg_node;
|
||||
// Slight amount of wasted compute to keep internal state non-changing.
|
||||
this.passthrough = new PassThroughNode('atree-make-nodes_internal').link_to(this.build_node, 'build').link_to(this.stat_agg_node, 'stats');
|
||||
this.passthrough = new PassThroughNode('spell-calc-buffer').link_to(this.build_node, 'build').link_to(this.stat_agg_node, 'stats');
|
||||
this.spelldmg_nodes = []; // debugging use
|
||||
this.spell_display_elem = document.getElementById("all-spells-display");
|
||||
}
|
||||
|
||||
compute_func(input_map) {
|
||||
console.log('atree make nodes');
|
||||
this.passthrough.remove_link(this.build_node);
|
||||
this.passthrough.remove_link(this.stat_agg_node);
|
||||
this.passthrough = new PassThroughNode('atree-make-nodes_internal').link_to(this.build_node, 'build').link_to(this.stat_agg_node, 'stats');
|
||||
this.passthrough = new PassThroughNode('spell-calc-buffer').link_to(this.build_node, 'build').link_to(this.stat_agg_node, 'stats');
|
||||
this.spell_display_elem.textContent = "";
|
||||
const build_node = this.passthrough.get_node('build'); // aaaaaaaaa performance... savings... help....
|
||||
const stat_agg_node = this.passthrough.get_node('stats');
|
||||
|
|
|
@ -794,7 +794,7 @@ class DisplayBuildWarningsNode extends ComputeNode {
|
|||
* Signature: AggregateStatsNode(*args) => StatMap
|
||||
*/
|
||||
class AggregateStatsNode extends ComputeNode {
|
||||
constructor() { super("builder-aggregate-stats"); }
|
||||
constructor(name) { super(name); }
|
||||
|
||||
compute_func(input_map) {
|
||||
const output_stats = new Map();
|
||||
|
@ -997,7 +997,8 @@ function builder_graph_init() {
|
|||
// Phase 2/3: Set up editable IDs, skill points; use decodeBuild() skill points, calculate damage
|
||||
|
||||
// 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)
|
||||
stat_agg_node = new AggregateStatsNode();
|
||||
pre_scale_agg_node = new AggregateStatsNode('pre-scale-stats');
|
||||
stat_agg_node = new AggregateStatsNode('final-stats');
|
||||
edit_agg_node = new AggregateEditableIDNode();
|
||||
edit_agg_node.link_to(build_node, 'build');
|
||||
for (const field of editable_item_fields) {
|
||||
|
@ -1021,7 +1022,7 @@ function builder_graph_init() {
|
|||
edit_input_nodes.push(node);
|
||||
skp_inputs.push(node);
|
||||
}
|
||||
stat_agg_node.link_to(edit_agg_node);
|
||||
pre_scale_agg_node.link_to(edit_agg_node);
|
||||
|
||||
// Phase 3/3: Set up atree stuff.
|
||||
|
||||
|
@ -1029,8 +1030,10 @@ function builder_graph_init() {
|
|||
// These two are defined in `atree.js`
|
||||
atree_node.link_to(class_node, 'player-class');
|
||||
atree_merge.link_to(class_node, 'player-class');
|
||||
atree_stats.link_to(build_node, 'build');
|
||||
stat_agg_node.link_to(atree_stats, 'atree-stats');
|
||||
pre_scale_agg_node.link_to(atree_stats, 'atree-raw-stats');
|
||||
atree_scaling.link_to(pre_scale_agg_node, 'scale-stats');
|
||||
stat_agg_node.link_to(pre_scale_agg_node, 'pre-scaling');
|
||||
stat_agg_node.link_to(atree_scaling, 'atree-scaling');
|
||||
|
||||
build_encode_node.link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
|
||||
|
||||
|
@ -1062,12 +1065,12 @@ function builder_graph_init() {
|
|||
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(build_node, 'build');
|
||||
stat_agg_node.link_to(powder_special_calc, 'powder-boost');
|
||||
stat_agg_node.link_to(armor_powder_node, 'armor-powder');
|
||||
pre_scale_agg_node.link_to(powder_special_calc, 'powder-boost');
|
||||
pre_scale_agg_node.link_to(armor_powder_node, 'armor-powder');
|
||||
powder_special_input.update();
|
||||
|
||||
// Potion boost.
|
||||
stat_agg_node.link_to(boosts_node, 'potion-boost');
|
||||
pre_scale_agg_node.link_to(boosts_node, 'potion-boost');
|
||||
|
||||
// Also do something similar for skill points
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue