Reworked master modifiers; working sliders
This commit is contained in:
parent
a4eda17f4e
commit
70c117261d
7 changed files with 85 additions and 51 deletions
30
js/atree.js
30
js/atree.js
|
@ -563,7 +563,7 @@ const atree_collect_spells = new (class extends ComputeNode {
|
|||
/**
|
||||
* Make interactive elements (sliders, buttons)
|
||||
*
|
||||
* Signature: AbilityActiveUINode(atree-merged: MergedATree) => List[ElemState]
|
||||
* Signature: AbilityActiveUINode(atree-merged: MergedATree) => Map<str, slider_info>
|
||||
*
|
||||
* ElemState: {
|
||||
* value: int // value for sliders; 0-1 for toggles
|
||||
|
@ -578,12 +578,13 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
const atree_html = input_map.get('atree-elements');
|
||||
|
||||
/**
|
||||
* slider_info {
|
||||
* slider_info
|
||||
* label_name: str,
|
||||
* max: int,
|
||||
* step: int,
|
||||
* id: str,
|
||||
* abil: atree_node
|
||||
* slider: html element
|
||||
* }
|
||||
*/
|
||||
// Map<str, slider_info>
|
||||
|
@ -615,8 +616,10 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
for (const [slider_name, slider_info] of slider_map.entries()) {
|
||||
let slider_container = gen_slider_labeled(slider_info);
|
||||
atree_html.get(slider_info.abil.id).appendChild(slider_container);
|
||||
slider_info.slider = document.getElementById(slider_info.id);
|
||||
slider_info.slider.addEventListener("change", (e) => atree_stats.mark_dirty().update());
|
||||
}
|
||||
//return ret_states;
|
||||
return slider_map;
|
||||
}
|
||||
})().link_to(atree_node, 'atree-order').link_to(atree_merge, 'atree-merged').link_to(atree_render_active, 'atree-elements');
|
||||
|
||||
|
@ -625,7 +628,7 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
* Collect stats from ability tree.
|
||||
* Return StatMap of added stats (incl. cost modifications as raw cost)
|
||||
*
|
||||
* Signature: AbilityTreeStatsNode(atree-merged: MergedATree) => StatMap
|
||||
* Signature: AbilityTreeStatsNode(atree-merged: MergedATree, build: Build, atree-interactive: Map<str, slider_info>) => StatMap
|
||||
*/
|
||||
const atree_stats = new (class extends ComputeNode {
|
||||
constructor() { super('atree-stats-collector'); }
|
||||
|
@ -633,6 +636,7 @@ const atree_stats = new (class extends ComputeNode {
|
|||
compute_func(input_map) {
|
||||
const atree_merged = input_map.get('atree-merged');
|
||||
const item_stats = input_map.get('build').statMap;
|
||||
const interactive_map = input_map.get('atree-interactive');
|
||||
|
||||
let ret_effects = new Map();
|
||||
for (const [abil_id, abil] of atree_merged.entries()) {
|
||||
|
@ -643,6 +647,20 @@ const atree_stats = new (class extends ComputeNode {
|
|||
case 'stat_scaling':
|
||||
if (effect.slider) {
|
||||
// TODO: handle
|
||||
const slider_val = interactive_map.get(effect.slider_name).slider.value;
|
||||
const total = parseInt(slider_val) * effect.scaling[0];
|
||||
if (Array.isArray(effect.output)) {
|
||||
for (const output of effect.output) {
|
||||
if (output.type === 'stat') {
|
||||
merge_stat(ret_effects, output.name, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (effect.output.type === 'stat') {
|
||||
merge_stat(ret_effects, effect.output.name, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const cap = effect.max;
|
||||
|
@ -691,11 +709,11 @@ const atree_stats = new (class extends ComputeNode {
|
|||
}
|
||||
}
|
||||
if (ret_effects.has('baseResist')) {
|
||||
merge_stat(ret_effects, "defMultiplier", 1 - (ret_effects.get('baseResist') / 100));
|
||||
merge_stat(ret_effects, "defMult", 1 - (ret_effects.get('baseResist') / 100));
|
||||
}
|
||||
return ret_effects;
|
||||
}
|
||||
})().link_to(atree_merge, 'atree-merged');
|
||||
})().link_to(atree_merge, 'atree-merged').link_to(atree_make_interactives, 'atree-interactive');
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1688,7 +1688,7 @@ const atrees = {
|
|||
"slider_name": "Focus",
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult"
|
||||
"name": "damMult.Focus"
|
||||
},
|
||||
"scaling": [40],
|
||||
"slider_max": 3
|
||||
|
@ -1717,7 +1717,7 @@ const atrees = {
|
|||
"slider_max": 2,
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult"
|
||||
"name": "damMult.Focus"
|
||||
},
|
||||
"scaling": [-5]
|
||||
}]
|
||||
|
@ -1745,7 +1745,7 @@ const atrees = {
|
|||
"slider_max": 2,
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult"
|
||||
"name": "damMult.Focus"
|
||||
},
|
||||
"scaling": [-5]
|
||||
}]
|
||||
|
@ -1803,7 +1803,7 @@ const atrees = {
|
|||
"slider_max": 4,
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult:Basaltic Trap"
|
||||
"name": "damMult.Basaltic:Basaltic Trap"
|
||||
},
|
||||
"slider_step": 1,
|
||||
"scaling": [20]
|
||||
|
@ -1967,7 +1967,7 @@ const atrees = {
|
|||
"slider_max": 7,
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult:Single Arrow"
|
||||
"name": "damMult.Decimator:Single Arrow"
|
||||
},
|
||||
"scaling": 10
|
||||
}]
|
||||
|
@ -2227,7 +2227,7 @@ const atrees = {
|
|||
"bonuses": [
|
||||
{
|
||||
"type": "stat",
|
||||
"name": "baseResist",
|
||||
"name": "defMult.Base",
|
||||
"value": 5
|
||||
}
|
||||
]
|
||||
|
@ -2775,7 +2775,7 @@ const atrees = {
|
|||
{
|
||||
"type": "raw_stat",
|
||||
"toggle": true,
|
||||
"bonuses": [{ "type": "stat", "name": "defMultiplier", "value": 0.3}]
|
||||
"bonuses": [{ "type": "stat", "name": "defMult.Mantle", "value": 70}]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -2986,7 +2986,7 @@ const atrees = {
|
|||
"slider_name": "Corrupted",
|
||||
"output": {
|
||||
"type": "stat",
|
||||
"name": "damMult"
|
||||
"name": "damMult.Enraged"
|
||||
},
|
||||
"scaling": [3]
|
||||
}
|
||||
|
@ -3130,7 +3130,7 @@ const atrees = {
|
|||
{
|
||||
"type": "raw_stat",
|
||||
"toggle": true,
|
||||
"bonuses": [ {"type": "stat", "name": "damMult", "value": 30} ]
|
||||
"bonuses": [ {"type": "stat", "name": "damMult.Ragnarokkr", "value": 30} ]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -3438,7 +3438,7 @@ const atrees = {
|
|||
"bonuses": [
|
||||
{
|
||||
"type": "stat",
|
||||
"name": "baseResist",
|
||||
"name": "defMult.Base",
|
||||
"value": 5
|
||||
}
|
||||
]
|
||||
|
@ -3468,7 +3468,7 @@ const atrees = {
|
|||
{
|
||||
"type": "raw_stat",
|
||||
"toggle": true,
|
||||
"bonuses": [ {"type": "stat", "name": "damMult", "value": 30} ]
|
||||
"bonuses": [ {"type": "stat", "name": "damMult.ArmorBreaker", "value": 30} ]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -3924,7 +3924,7 @@ const atrees = {
|
|||
{
|
||||
"type": "raw_stat",
|
||||
"toggle": true,
|
||||
"bonuses": [{ "type": "stat", "name": "defMultiplier", "value": 0.6}]
|
||||
"bonuses": [{ "type": "stat", "name": "defMult.Brink", "value": 40}]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -83,7 +83,6 @@ class Build{
|
|||
|
||||
//Create a map of this build's stats
|
||||
let statMap = new Map();
|
||||
statMap.set("defMultiplier", 1);
|
||||
|
||||
for (const staticID of staticIDs) {
|
||||
statMap.set(staticID, 0);
|
||||
|
@ -113,8 +112,10 @@ class Build{
|
|||
}
|
||||
}
|
||||
}
|
||||
statMap.set('damageMultiplier', 1 + (statMap.get('damMobs') / 100));
|
||||
statMap.set('defMultiplier', 1 - (statMap.get('defMobs') / 100));
|
||||
statMap.set('damMult', new Map());
|
||||
statMap.set('defMult', new Map());
|
||||
statMap.get('damMult').set('tome', statMap.get('damMobs'))
|
||||
statMap.get('defMult').set('tome', statMap.get('defMobs'))
|
||||
statMap.set("activeMajorIDs", major_ids);
|
||||
for (const [setName, count] of this.activeSetCounts) {
|
||||
const bonus = sets.get(setName).bonuses[count-1];
|
||||
|
|
|
@ -74,17 +74,17 @@ 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", "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",
|
||||
"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
|
||||
"critDamPct"
|
||||
];
|
||||
// Extra fake IDs (reserved for use in spell damage calculation) : damageMultiplier, defMultiplier, poisonPct, activeMajorIDs
|
||||
// Extra fake IDs (reserved for use in spell damage calculation) : damMult, defMult, 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
|
||||
|
@ -169,11 +169,11 @@ let rolledIDs = [
|
|||
"gXp",
|
||||
"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",
|
||||
"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
|
||||
|
@ -305,11 +305,23 @@ function idRound(id){
|
|||
* stupid stupid multiplicative stats
|
||||
*/
|
||||
function merge_stat(stats, name, value) {
|
||||
if (stats.has(name)) {
|
||||
if (name === 'damageMultiplier' || name === 'defMultiplier') {
|
||||
stats.set(name, stats.get(name) * value);
|
||||
const start = name.slice(0, 7);
|
||||
if (start === 'damMult' || start === 'defMult') {
|
||||
if (!stats.has(start)) {
|
||||
stats.set(start, new Map());
|
||||
}
|
||||
else { stats.set(name, stats.get(name) + value); }
|
||||
const map = stats.get(start);
|
||||
if (value instanceof Map) {
|
||||
for (const [k, v] of value.entries()) {
|
||||
merge_stat(map, k, v);
|
||||
}
|
||||
return;
|
||||
}
|
||||
merge_stat(map, name.slice(8), value);
|
||||
return;
|
||||
}
|
||||
if (stats.has(name)) {
|
||||
stats.set(name, stats.get(name) + value);
|
||||
}
|
||||
else { stats.set(name, value); }
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ let boosts_node = new (class extends ComputeNode {
|
|||
}
|
||||
}
|
||||
let res = new Map();
|
||||
res.set('damageMultiplier', 1+damage_boost);
|
||||
res.set('defMultiplier', 1-def_boost);
|
||||
res.set('damMult.Potion', 100*damage_boost);
|
||||
res.set('defMult.Potion', 100*def_boost);
|
||||
return res;
|
||||
}
|
||||
})().update();
|
||||
|
@ -489,7 +489,10 @@ function getDefenseStats(stats) {
|
|||
defenseStats.push(totalHp);
|
||||
//EHP
|
||||
let ehp = [totalHp, totalHp];
|
||||
let defMult = (2 - stats.get("classDef")) * stats.get("defMultiplier");
|
||||
let defMult = (2 - stats.get("classDef"));
|
||||
for (const [k, v] of stats.get("defMult").entries()) {
|
||||
defMult *= (1 - v/100);
|
||||
}
|
||||
// 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;
|
||||
|
@ -536,7 +539,6 @@ class SpellDamageCalcNode extends ComputeNode {
|
|||
const spell = spell_info[0];
|
||||
const spell_parts = spell_info[1];
|
||||
const stats = input_map.get('stats');
|
||||
const damage_mult = stats.get('damageMultiplier');
|
||||
const skillpoints = [
|
||||
stats.get('str'),
|
||||
stats.get('dex'),
|
||||
|
@ -673,7 +675,7 @@ function getMeleeStats(stats, weapon) {
|
|||
}
|
||||
|
||||
if (weapon_stats.get("type") === "relik") {
|
||||
stats.set('damageMultiplier', 0.99); // CURSE YOU WYNNCRAFT
|
||||
merge_stat(stats, 'damMult.ShamanMelee', 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.
|
||||
}
|
||||
|
@ -841,13 +843,7 @@ class AggregateStatsNode extends ComputeNode {
|
|||
const output_stats = new Map();
|
||||
for (const [k, v] of input_map.entries()) {
|
||||
for (const [k2, v2] of v.entries()) {
|
||||
if (output_stats.has(k2)) {
|
||||
// TODO: ugly AF
|
||||
merge_stat(output_stats, k2, v2);
|
||||
}
|
||||
else {
|
||||
output_stats.set(k2, v2);
|
||||
}
|
||||
merge_stat(output_stats, k2, v2);
|
||||
}
|
||||
}
|
||||
return output_stats;
|
||||
|
|
|
@ -26,7 +26,7 @@ function get_base_dps(item) {
|
|||
}
|
||||
|
||||
|
||||
function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, ignore_speed=false) {
|
||||
function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, ignore_speed=false, part=undefined) {
|
||||
// TODO: Roll all the loops together maybe
|
||||
|
||||
// Array of neutral + ewtfa damages. Each entry is a pair (min, max).
|
||||
|
@ -154,7 +154,14 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
|
|||
let total_dam_norm = [0, 0];
|
||||
let total_dam_crit = [0, 0];
|
||||
let damages_results = [];
|
||||
const damage_mult = stats.get("damageMultiplier");
|
||||
const mult_map = stats.get("damMult");
|
||||
console.log(mult_map);
|
||||
let damage_mult = 1;
|
||||
for (const [k, v] of mult_map.entries()) {
|
||||
damage_mult *= (1 + v/100);
|
||||
}
|
||||
console.log(damage_mult);
|
||||
|
||||
|
||||
for (const damage of damages) {
|
||||
const res = [
|
||||
|
|
Loading…
Reference in a new issue