Merge branch 'atree' into weapon-powder-optimization

This commit is contained in:
hppeng 2022-07-11 19:57:24 -07:00
commit 7d2626d1dc
11 changed files with 535 additions and 217 deletions

View file

@ -76,6 +76,7 @@
"spRaw1-base": -5,
"category": "armor",
"displayName": "Anaerobic",
"slots": 4,
"hp": 3850,
"wDef": -150,
"aDef": 100,
@ -118,10 +119,10 @@
"classReq": "Shaman",
"dexReq": 55,
"defReq": 50,
"hprPct": -204,
"ms": 13,
"atkTier": 1,
"hpBonus": -1150,
"hprRaw": -204,
"sdRaw": 184,
"spRaw1": -7,
"id": 3614
@ -336,7 +337,7 @@
"poison": 600,
"thorns": 25,
"slots": 3,
"hp": 3450,
"hp": 4350,
"fDef": 120,
"wDef": 120,
"aDef": 200,
@ -393,8 +394,8 @@
"fDef": 50,
"wDef": 50,
"lvl": 101,
"dexReq": 45,
"intReq": 45,
"defReq": 45,
"hprPct": 17,
"sdPct": 5,
"str": -3,
@ -1027,13 +1028,13 @@
"mdPct": 40,
"sdRaw": -40000,
"spPct1": -40,
"spRaw1": -40,
"spRaw1": -400,
"spPct2": -40,
"spRaw2": -40,
"spRaw2": -400,
"spPct3": -40,
"spRaw3": -40,
"spRaw3": -400,
"spPct4": -40,
"spRaw4": -40,
"spRaw4": -400,
"id": 3021
},
{
@ -1971,7 +1972,7 @@
"type": "wand",
"tier": "Mythic",
"majorIds": [],
"mr-base": -49,
"mr-base": -45,
"spRaw1-base": 4,
"spRaw2-base": -299,
"category": "weapon",
@ -1988,7 +1989,7 @@
"lvl": 99,
"agiReq": 130,
"hprPct": -200,
"mr": -49,
"mr": -45,
"ref": 90,
"agi": 20,
"expd": 50,
@ -2074,11 +2075,11 @@
"basedps": 1350,
"slots": 3,
"nDam": "0-0",
"fDam": "215-325",
"wDam": "230-310",
"aDam": "245-295",
"tDam": "260-280",
"eDam": "200-340",
"fDam": "185-295",
"wDam": "200-280",
"aDam": "215-265",
"tDam": "230-250",
"eDam": "170-310",
"atkSpd": "VERY_SLOW",
"lvl": 96,
"strReq": 45,
@ -2086,9 +2087,9 @@
"intReq": 45,
"agiReq": 45,
"defReq": 45,
"mr": -4,
"mr": -20,
"sdPct": 30,
"ms": -4,
"ms": -20,
"int": 50,
"spPct1": -27,
"spPct2": -27,
@ -2177,6 +2178,62 @@
"sprintReg": 43,
"id": 3643
},
{
"name": "Panic Zealot",
"tier": "Fabled",
"type": "relik",
"material": "273:7",
"majorIds": [
"FURIOUS_EFFIGY"
],
"category": "weapon",
"slots": 3,
"lore": "They must know what you went through. They must suffer the same as you did.",
"drop": "never",
"restrict": "Untradable",
"nDam": "46-60",
"fDam": "0-0",
"wDam": "0-0",
"aDam": "43-63",
"tDam": "0-0",
"eDam": "0-0",
"atkSpd": "SUPER_FAST",
"lvl": 101,
"agiReq": 85,
"spd": 30,
"atkTier": 3,
"hpBonus": -5000,
"tDamPct": -30,
"spPct1": -100,
"spPct2": -100,
"spPct3": -100,
"id": 3600
},
{
"name": "Ambivalence",
"tier": "Legendary",
"material": "259:29",
"category": "accessory",
"drop": "never",
"restrict": "Untradable",
"fDef": 70,
"aDef": 70,
"tDef": 70,
"lvl": 100,
"dexReq": 40,
"agiReq": 40,
"defReq": 40,
"sdPct": 250,
"int": -100,
"wDamPct": 50,
"type": "necklace",
"fixID": true,
"spPct1": 130,
"spPct2": 85,
"spPct3": 130,
"spPct4": 100,
"id": 3618
},
{
"name": "Dondasch",
"tier": "Legendary",
@ -2714,35 +2771,6 @@
"dex": 30,
"id": 19
},
{
"name": "Panic Zealot",
"tier": "Fabled",
"type": "relik",
"majorIds": [
"FURIOUS_EFFIGY"
],
"category": "weapon",
"slots": 3,
"drop": "never",
"restrict": "Untradable",
"nDam": "46-60",
"fDam": "0-0",
"wDam": "0-0",
"aDam": "43-63",
"tDam": "0-0",
"eDam": "0-0",
"atkSpd": "SUPER_FAST",
"lvl": 101,
"agiReq": 85,
"spd": 30,
"atkTier": 3,
"hpBonus": -5000,
"tDamPct": -30,
"spPct1": -70,
"spPct2": -70,
"spPct3": -70,
"id": 3600
},
{
"name": "Redrock Bandanna",
"tier": "Rare",
@ -8836,7 +8864,7 @@
"def": 11,
"hpBonus": -300,
"spPct2": 25,
"spPct4": -23,
"spPct4": -24,
"id": 359
},
{
@ -11449,9 +11477,9 @@
"def": -20,
"atkTier": -1,
"hprRaw": -200,
"spPct2": -31,
"spPct2": -32,
"spPct3": -21,
"spPct4": -23,
"spPct4": -24,
"id": 482
},
{
@ -11521,7 +11549,7 @@
"spd": -8,
"hpBonus": 1750,
"hprRaw": 125,
"spPct1": -47,
"spPct1": -48,
"id": 490
},
{
@ -14682,7 +14710,7 @@
"aDamPct": 12,
"tDamPct": 15,
"fixID": true,
"spPct3": -9,
"spPct3": -10,
"id": 629
},
{
@ -16771,7 +16799,7 @@
"aDamPct": 21,
"fixID": true,
"spPct2": -54,
"spPct3": -33,
"spPct3": -34,
"id": 726
},
{
@ -17184,7 +17212,7 @@
"wDefPct": -45,
"eDefPct": -55,
"spPct2": -14,
"spPct3": -9,
"spPct3": -10,
"id": 2264
},
{
@ -17898,30 +17926,6 @@
"fixID": true,
"id": 776
},
{
"name": "Ambivalence",
"tier": "Legendary",
"category": "accessory",
"drop": "never",
"restrict": "Untradable",
"fDef": 70,
"aDef": 70,
"tDef": 70,
"lvl": 100,
"dexReq": 40,
"agiReq": 40,
"defReq": 40,
"sdPct": 250,
"int": -100,
"wDamPct": 50,
"type": "necklace",
"fixID": true,
"spPct1": 91,
"spPct2": 61,
"spPct3": 91,
"spPct4": 70,
"id": 3618
},
{
"name": "The Evolved",
"tier": "Legendary",
@ -18180,7 +18184,7 @@
"mdRaw": 1997,
"fixID": true,
"spPct1": 23,
"spPct2": 16,
"spPct2": 15,
"spPct3": 32,
"spPct4": 23,
"id": 782
@ -20686,7 +20690,7 @@
"spd": 10,
"hpBonus": -300,
"spPct1": 25,
"spPct3": -23,
"spPct3": -24,
"jh": 1,
"id": 898
},
@ -24363,9 +24367,9 @@
"int": -40,
"spd": 8,
"spPct1": -17,
"spPct2": -9,
"spPct2": -10,
"spPct3": -17,
"spPct4": -9,
"spPct4": -10,
"id": 1070
},
{
@ -25537,7 +25541,7 @@
"aDamPct": -33,
"tDamPct": -33,
"eDamPct": -33,
"spPct3": -22,
"spPct3": -23,
"id": 1143
},
{
@ -28186,7 +28190,7 @@
"str": 4,
"dex": 4,
"mdRaw": 52,
"spPct1": 19,
"spPct1": 18,
"id": 1261
},
{
@ -36455,7 +36459,7 @@
"dex": 4,
"sdRaw": 13,
"mdRaw": 13,
"spPct1": 19,
"spPct1": 18,
"id": 1658
},
{
@ -37209,7 +37213,7 @@
"def": 15,
"fDamPct": 40,
"wDamPct": 40,
"spPct1": -22,
"spPct1": -23,
"id": 1689
},
{
@ -44564,7 +44568,7 @@
"fDamPct": 45,
"wDamPct": -25,
"eDamPct": -25,
"spPct3": -22,
"spPct3": -23,
"id": 2063
},
{
@ -47311,7 +47315,7 @@
"ms": 5,
"lb": 10,
"str": -5,
"spPct1": -24,
"spPct1": -25,
"id": 2182
},
{
@ -50036,8 +50040,8 @@
"agi": 7,
"def": 7,
"wDamPct": -15,
"spPct1": -9,
"spPct3": -9,
"spPct1": -10,
"spPct3": -10,
"id": 2327
},
{
@ -62443,7 +62447,7 @@
"hprRaw": -40,
"sdRaw": 95,
"fixID": true,
"spPct3": -9,
"spPct3": -10,
"id": 2915
},
{
@ -66515,7 +66519,7 @@
"hprRaw": 150,
"spPct1": -7,
"spPct2": -14,
"spPct3": -9,
"spPct3": -10,
"id": 3094
},
{
@ -70196,7 +70200,7 @@
"lb": 25,
"hprRaw": -101,
"spPct2": -31,
"spPct4": -9,
"spPct4": -10,
"jh": 2,
"id": 3621
},
@ -70933,7 +70937,7 @@
"fDamPct": -30,
"wDamPct": 20,
"tDefPct": -25,
"spPct3": -23,
"spPct3": -24,
"id": 3309
},
{
@ -71361,9 +71365,9 @@
"spd": 10,
"fDamPct": 10,
"wDamPct": -15,
"spPct1": -9,
"spPct1": -10,
"spPct3": -7,
"spPct4": -9,
"spPct4": -10,
"id": 3327
},
{
@ -72629,7 +72633,7 @@
"int": -24,
"agi": 12,
"spd": 15,
"spPct1": -9,
"spPct1": -10,
"spPct3": -7,
"spPct4": -17,
"id": 3385
@ -73244,7 +73248,7 @@
"ms": 5,
"def": -12,
"spd": 12,
"spPct1": -22,
"spPct1": -23,
"id": 3413
},
{

File diff suppressed because one or more lines are too long

View file

@ -310,6 +310,56 @@ const atree_merge = new (class extends ComputeNode {
}
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
/**
* Check if an atree node can be activated.
*
* Return: [yes/no, hard error, reason]
*/
function abil_can_activate(atree_node, atree_state, reachable, archetype_count, points_remain) {
const {parents, ability} = atree_node;
if (parents.length === 0) {
return [true, false, ""];
}
let failed_deps = [];
for (const dep_id of ability.dependencies) {
if (!atree_state.get(dep_id).active) { failed_deps.push(dep_id) }
}
if (failed_deps.length > 0) {
const dep_strings = failed_deps.map(i => '"' + atree_state.get(i).ability.display_name + '"');
return [false, true, 'missing dep: ' + dep_strings.join(", ")];
}
let blocking_ids = [];
for (const blocker_id of ability.blockers) {
if (atree_state.get(blocker_id).active) { blocking_ids.push(blocker_id); }
}
if (blocking_ids.length > 0) {
const blockers_strings = blocking_ids.map(i => '"' + atree_state.get(i).ability.display_name + '"');
return [false, true, 'blocked by: '+blockers_strings.join(", ")];
}
let node_reachable = false;
for (const parent of parents) {
if (reachable.has(parent.ability.id)) {
node_reachable = true;
break;
}
}
if (!node_reachable) {
return [false, false, 'not reachable'];
}
if ('archetype' in ability && ability.archetype !== "") {
if ('archetype_req' in ability && ability.archetype_req !== 0) {
const others = (archetype_count.get(ability.archetype) || 0);
if (others < ability.archetype_req) {
return [false, false, ability.archetype+': '+others+' < '+ability.archetype_req];
}
}
}
if (ability.cost > points_remain) {
return [false, false, "not enough ability points left"];
}
return [true, false, ""];
}
/**
* Validate ability tree.
* Return list of errors for rendering.
@ -322,13 +372,24 @@ const atree_validate = new (class extends ComputeNode {
compute_func(input_map) {
const atree_state = input_map.get('atree-state');
const atree_order = input_map.get('atree');
const level = parseInt(input_map.get('level'));
if (atree_order.length == 0) { return [0, false, ['no atree data']]; }
let atree_to_add = [];
let atree_not_present = [];
// mark all selected nodes as bright, and mark all other nodes as dark.
// also initialize the "to check" list, and the "not present" list.
for (const node of atree_order) {
const abil = node.ability;
if (atree_state.get(abil.id).active) { atree_to_add.push([node, 'not reachable', false]); }
if (atree_state.get(abil.id).active) {
atree_to_add.push([node, 'not reachable', false]);
atree_state.get(abil.id).img.src = '../media/atree/'+abil.display.icon+'.png';
}
else {
atree_not_present.push(abil.id);
atree_state.get(abil.id).img.src = '../media/atree/'+abil.display.icon+'_blocked.png';
}
}
let reachable = new Set();
@ -337,50 +398,12 @@ const atree_validate = new (class extends ComputeNode {
while (true) {
let _add = [];
for (const [node, fail_reason, fail_hardness] of atree_to_add) {
const {parents, ability} = node;
if (parents.length === 0) {
reachable.add(ability.id);
// root abil has no archetype.
abil_points_total += ability.cost;
continue;
}
let failed_deps = [];
for (const dep_id of ability.dependencies) {
if (!atree_state.get(dep_id).active) { failed_deps.push(dep_id) }
}
if (failed_deps.length > 0) {
const dep_strings = failed_deps.map(i => '"' + atree_state.get(i).ability.display_name + '"');
_add.push([node, 'missing dep: ' + dep_strings.join(", "), true]);
continue;
}
let blocking_ids = [];
for (const blocker_id of ability.blockers) {
if (atree_state.get(blocker_id).active) { blocking_ids.push(blocker_id); }
}
if (blocking_ids.length > 0) {
const blockers_strings = blocking_ids.map(i => '"' + atree_state.get(i).ability.display_name + '"');
_add.push([node, 'blocked by: '+blockers_strings.join(", "), true]);
continue;
}
let node_reachable = false;
for (const parent of parents) {
if (reachable.has(parent.ability.id)) {
node_reachable = true;
break;
}
}
if (!node_reachable) {
_add.push([node, 'not reachable', false])
continue;
const {ability} = node;
const [success, hard_error, reason] = abil_can_activate(node, atree_state, reachable, archetype_count, 9999);
if (!success) {
_add.push([node, reason, hard_error]);
}
if ('archetype' in ability && ability.archetype !== "") {
if ('archetype_req' in ability && ability.archetype_req !== 0) {
const others = archetype_count.get(ability.archetype);
if (others < ability.archetype_req) {
_add.push([node, ability.archetype+': '+others+' < '+ability.archetype_req, false])
continue;
}
}
let val = 1;
if (archetype_count.has(ability.archetype)) {
val = archetype_count.get(ability.archetype) + 1;
@ -395,13 +418,38 @@ const atree_validate = new (class extends ComputeNode {
}
atree_to_add = _add;
}
const atree_level_table = ['lvl0wtf',1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,9,10,11,11,12,12,13,14,14,15,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,34,35,35,35,36,36,36,37,37,37,38,38,38,38,39,39,39,39,40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,44,44,44,44,45,45,45];
let AP_cap;
if (isNaN(level)) {
AP_cap = 45;
}
else {
AP_cap = atree_level_table[level];
}
document.getElementById('active_AP_cap').textContent = AP_cap;
document.getElementById("active_AP_cost").textContent = abil_points_total;
const ap_left = AP_cap - abil_points_total;
// using the "not present" list, highlight one-step reachable nodes.
for (const node_id of atree_not_present) {
const node = atree_state.get(node_id);
const [success, hard_error, reason] = abil_can_activate(node, atree_state, reachable, archetype_count, ap_left);
if (success) {
node.img.src = '../media/atree/'+node.ability.display.icon+'.png';
}
}
let hard_error = false;
let errors = [];
if (abil_points_total > AP_cap) {
errors.push('too many ability points assigned! ('+abil_points_total+' > '+AP_cap+')');
}
for (const [node, fail_reason, fail_hardness] of atree_to_add) {
if (fail_hardness) { hard_error = true; }
errors.push(node.ability.display_name + ": " + fail_reason);
}
return [abil_points_total, hard_error, errors];
return [hard_error, errors];
}
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
@ -420,23 +468,11 @@ const atree_render_active = new (class extends ComputeNode {
compute_func(input_map) {
const merged_abils = input_map.get('atree-merged');
const atree_order = input_map.get('atree-order');
const [abil_points_total, hard_error, errors] = input_map.get('atree-errors');
const atree_level_table = ['lvl0wtf',1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,9,10,11,11,12,12,13,14,14,15,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,34,35,35,35,36,36,36,37,37,37,38,38,38,38,39,39,39,39,40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,44,44,44,44,45,45,45];
const level = parseInt(input_map.get('level'));
const active_AP_cap = document.getElementById('active_AP_cap');
let AP_cap;
if (isNaN(level)) {
AP_cap = 45;
}
else {
AP_cap = atree_level_table[level];
}
active_AP_cap.textContent = AP_cap;
const [hard_error, _errors] = input_map.get('atree-errors');
const errors = deepcopy(_errors);
this.list_elem.innerHTML = ""; //reset all atree actives - should be done in a more general way later
// TODO: move to display?
document.getElementById("active_AP_cost").textContent = abil_points_total;
if (errors.length > 0) {
let errorbox = document.createElement('div');
errorbox.classList.add("rounded-bottom", "dark-4", "border", "p-0", "mx-2", "my-4", "dark-shadow");
@ -457,11 +493,6 @@ const atree_render_active = new (class extends ComputeNode {
const atree_warning = make_elem("p", ["warning", "small-text"], {textContent: error});
errorbox.appendChild(atree_warning);
}
if (abil_points_total > AP_cap) {
const error = 'too many ability points assigned! ('+abil_points_total+' > '+AP_cap+')';
const atree_warning = make_elem("p", ["warning", "small-text"], {textContent: error});
errorbox.appendChild(atree_warning);
}
}
const ret_map = new Map();
const to_render_id = [999, 998];
@ -506,7 +537,7 @@ const atree_collect_spells = new (class extends ComputeNode {
compute_func(input_map) {
const atree_merged = input_map.get('atree-merged');
const [abil_points_total, hard_error, errors] = input_map.get('atree-errors');
const [hard_error, errors] = input_map.get('atree-errors');
if (hard_error) { return []; }
let ret_spells = new Map();
@ -538,7 +569,8 @@ const atree_collect_spells = new (class extends ComputeNode {
case 'add_spell_prop': {
const { base_spell, target_part = null, cost = 0, behavior = 'merge'} = effect;
const ret_spell = ret_spells.get(base_spell);
// TODO: unjankify this... if ('cost' in ret_spell) { ret_spell.cost += cost; }
// TODO: unjankify this...
if ('cost' in ret_spell) { ret_spell.cost += cost; }
if (target_part === null) {
continue;
@ -641,9 +673,11 @@ const atree_make_interactives = new (class extends ComputeNode {
if (effect['type'] === "stat_scaling" && effect['slider'] === true) {
const { slider_name, slider_behavior = 'merge', slider_max, slider_step } = effect;
if (slider_map.has(slider_name)) {
if (slider_max !== undefined) {
const slider_info = slider_map.get(slider_name);
slider_info.max += slider_max;
}
}
else if (slider_behavior === 'merge') {
slider_map.set(slider_name, {
label_name: slider_name,
@ -742,15 +776,16 @@ 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;
// 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;
}
}
}
@ -1016,6 +1051,7 @@ function render_AT(UI_elem, list_elem, tree) {
//list_elem.appendChild(active_tooltip); NOTE: moved to `atree_render_active`
node_wrap.elem = node_elem;
node_wrap.img = node_img;
node_wrap.all_connectors_ref = atree_connectors_map;
node_elem.addEventListener('click', function(e) {

View file

@ -88,7 +88,6 @@ const atrees = {
"cost": 50,
"base_spell": 3,
"spell_type": "damage",
"scaling": "spell",
"display": "Total Damage",
"parts": [
{
@ -237,7 +236,6 @@ const atrees = {
"cost": 40,
"base_spell": 1,
"spell_type": "damage",
"scaling": "spell",
"display": "Total Damage",
"parts": [
{
@ -4586,17 +4584,39 @@ const atrees = {
"archetype": "Riftwalker",
"archetype_req": 3,
"parents": ["Wind Slash", "Thunderstorm"],
"dependencies": [],
"dependencies": ["Ice Snake"],
"blockers": [],
"cost": 2,
"display": {
"row": 15,
"col": 1,
"icon": "node_3",
"__TODO": "hppeng please fix"
"icon": "node_3"
},
"properties": { "max": 5 },
"effects": []
"effects": [
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": {
"type": "stat",
"name": "nConvBase:4.Ice Snake Damage"
},
"scaling": [20],
"slider_step": 1,
"slider_max": 5
},
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": {
"type": "stat",
"name": "wConvBase:4.Ice Snake Damage"
},
"scaling": [10]
}
]
},
{
"display_name": "Ophanim",
@ -4715,7 +4735,7 @@ const atrees = {
{
"display_name": "Eye Piercer",
"desc": "Teleport will blind enemies, confusing them for a short amount of time.",
"base_abil": "Heal",
"base_abil": "Teleport",
"parents": ["Cheaper Heal"],
"dependencies": ["Teleport"],
"blockers": [],
@ -4734,7 +4754,7 @@ const atrees = {
"base_abil": "Windsweeper",
"archetype": "Riftwalker",
"archetype_req": 0,
"parents": ["Cheaper Heal"],
"parents": ["Cheaper Heal", "Purification"],
"dependencies": ["Windsweeper"],
"blockers": [],
"cost": 2,
@ -4744,8 +4764,32 @@ const atrees = {
"icon": "node_1"
},
"properties": {},
"effects": [],
"__TODO": "I still don't really know how to do this, for the record though the ratio is 20% neutral 20% earth per stack"
"effects": [
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": [
{
"type": "stat",
"name": "nConvBase:3.Meteor Damage"
},
{
"type": "stat",
"name": "eConvBase:3.Meteor Damage"
},
{
"type": "stat",
"name": "nConvBase:3.Per Orb"
},
{
"type": "stat",
"name": "eConvBase:3.Per Orb"
}
],
"scaling": [15]
}
]
},
{
"display_name": "Larger Heal",
@ -5028,7 +5072,38 @@ const atrees = {
"icon": "node_2"
},
"properties": {},
"effects": []
"effects": [
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": {
"type": "stat",
"name": "nConvBase:2.Wind Slash"
},
"scaling": [30]
},
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": {
"type": "stat",
"name": "tConvBase:2.Wind Slash"
},
"scaling": [10]
},
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"output": {
"type": "stat",
"name": "aConvBase:2.Wind Slash"
},
"scaling": [5]
}
]
},
{
"display_name": "Healthier Ophanim I",
@ -5204,15 +5279,25 @@ const atrees = {
"icon": "node_0"
},
"properties": {},
"effects": [{
"effects": [
{
"type": "raw_stat",
"bonuses": [{
"bonuses": [
{
"type": "prop",
"abil": "Windsweeper",
"name": "max",
"value": 5
}]
}]
}
]
},
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"slider_max": 5
}
]
},
{
"display_name": "Cheaper Ice Snake II",
@ -5348,8 +5433,8 @@ const atrees = {
"desc": "When sprinting, create an area that increases the speed of all allies the longer they run in it. (Step out or stop running to cancel)",
"archetype": "Riftwalker",
"archetype_req": 7,
"parents": ["Cheaper Ice Snake II", "Explosive Entrance"],
"dependencies": ["Ice Snake"],
"parents": ["Cheaper Ice Snake II"],
"dependencies": [],
"blockers": [],
"cost": 2,
"display": {
@ -5366,7 +5451,8 @@ const atrees = {
"archetype": "Light Bender",
"archetype_req": 0,
"base_abil": "Ophanim",
"parents": ["Explosive Entrance", "Cheaper Meteor II"],
"parents": ["Cheaper Meteor II"],
"_parents": ["Explosive Entrance", "Cheaper Meteor II"],
"dependencies": ["Ophanim"],
"blockers": [],
"cost": 1,
@ -5420,6 +5506,7 @@ const atrees = {
"archetype": "Riftwalker",
"archetype_req": 0,
"parents": ["Time Dilation"],
"_parents": ["Time Dilation", "Dynamic Faith"],
"dependencies": ["Windsweeper"],
"blockers": [],
"cost": 1,
@ -5429,7 +5516,25 @@ const atrees = {
"icon": "node_0"
},
"properties": {},
"effects": []
"effects": [
{
"type": "raw_stat",
"bonuses": [
{
"type": "prop",
"abil": "Windsweeper",
"name": "max",
"value": 5
}
]
},
{
"type": "stat_scaling",
"slider": true,
"slider_name": "Winded",
"slider_max": 5
}
]
},
{
"display_name": "Dynamic Faith",

File diff suppressed because one or more lines are too long

View file

@ -1009,7 +1009,7 @@ function builder_graph_init() {
let level_input = new InputNode('level-input', document.getElementById('level-choice'));
// linking to atree verification
atree_render_active.link_to(level_input, 'level');
atree_validate.link_to(level_input, 'level');
// "Build" now only refers to equipment and level (no powders). Powders are injected before damage calculation / stat display.
build_node = new BuildAssembleNode();

View file

@ -26,7 +26,7 @@ function get_base_dps(item) {
}
function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, ignore_speed=false, part_filter=undefined) {
function calculateSpellDamage(stats, weapon, _conversions, use_spell_damage, ignore_speed=false, part_filter=undefined) {
// TODO: Roll all the loops together maybe
// Array of neutral + ewtfa damages. Each entry is a pair (min, max).
@ -40,7 +40,28 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
}
let present = deepcopy(weapon.get(damage_present_key));
// Also theres prop and rainbow!!
const damage_elements = ['n'].concat(skp_elements); // netwfa
// 2. Conversions.
// 2.0: First, modify conversions.
let conversions = deepcopy(_conversions);
if (part_filter !== undefined) {
const conv_postfix = ':'+part_filter;
for (let i in damage_elements) {
const stat_name = damage_elements[i]+'ConvBase'+conv_postfix;
if (stats.has(stat_name)) {
conversions[i] += stats.get(stat_name);
}
}
}
for (let i in damage_elements) {
const stat_name = damage_elements[i]+'ConvBase';
if (stats.has(stat_name)) {
conversions[i] += stats.get(stat_name);
}
}
// 2.1. First, apply neutral conversion (scale weapon damage). Keep track of total weapon damage here.
let damages = [];
const neutral_convert = conversions[0] / 100;
@ -68,9 +89,6 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
}
total_convert += conversions[0]/100;
// 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"))];
@ -81,7 +99,7 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
}
// 4. Add additive damage. TODO: Is there separate additive damage?
for (let i = 0; i < 6; ++i) {
for (let i in damage_elements) {
if (present[i]) {
damages[i][0] += stats.get(damage_elements[i]+'DamAddMin');
damages[i][1] += stats.get(damage_elements[i]+'DamAddMax');
@ -104,10 +122,10 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
// 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 damage_prefix = damage_elements[i] + specific_boost_str;
for (let i in damage_elements) {
let damage_specific = damage_elements[i] + specific_boost_str + 'Pct';
let damageBoost = 1 + skill_boost[i] + static_boost
+ ((stats.get(damage_prefix+'Pct') + stats.get(damage_elements[i]+'DamPct')) /100);
+ ((stats.get(damage_specific) + 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

View file

@ -1,4 +1,4 @@
const DB_VERSION = 94;
const DB_VERSION = 95;
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
let db;

View file

@ -60,6 +60,7 @@ elif req.lower() == "maploc":
else:
response = requests.get(req)
response['version'] = CURR_WYNN_VERS
data = response.json()
data['version'] = CURR_WYNN_VERS
json.dump(response, open(outfile, "w+"))
json.dump(data, open(outfile, "w+"))

View file

@ -1,17 +1,17 @@
{"items": [
{"name":"Keratoconus","type":"helmet","level":101,"tier":"Legendary","sockets":3,"majorIds":[],"intelligence":65,"agility":65,"intelligencePoints":15,"defensePoints":-10,"health":3900,"thunderDefense":-150,"fireDefense":-150,"airDefense":250,"tDamPct-base":-40,"wDamPct-base":30,"aDamPct-base":35,"hprPct-base":-50,"mr-base":8,"spRaw4-base":-4,"category":"armor","displayName":"Keratoconus","bonusThunderDamage":-40,"bonusWaterDamage":30,"bonusAirDamage":35,"healthRegen":-50,"manaRegen":8,"spellCostRaw4":-4,"identified":false},
{"name":"Wanderlust","type":"chestplate","level":103,"tier":"Legendary","sockets":2,"majorIds":[],"dexterity":45,"agility":55,"health":3500,"thunderDefense":75,"waterDefense":100,"fireDefense":-75,"airDefense":100,"wDamPct-base":20,"aDamPct-base":30,"sdRaw-base":208,"hprPct-base":-15,"ms-base":-11,"ls-base":230,"spd-base":25,"category":"armor","displayName":"Wanderlust","bonusWaterDamage":20,"bonusAirDamage":30,"spellDamageRaw":208,"healthRegen":-15,"manaSteal":-12,"lifeSteal":230,"speed":25,"identified":false},
{"name":"Anaerobic","type":"leggings","level":104,"tier":"Legendary","majorIds":[],"strength":60,"agility":60,"strengthPoints":12,"health":3850,"earthDefense":100,"waterDefense":-150,"airDefense":100,"eDamPct-base":24,"aDamPct-base":32,"atkTier-base":-1,"mr-base":8,"ref-base":48,"spRaw1-base":-5,"category":"armor","displayName":"Anaerobic","bonusEarthDamage":24,"bonusAirDamage":32,"attackSpeedBonus":-1,"manaRegen":8,"reflection":48,"spellCostRaw1":-8,"identified":false},
{"name":"Danse Macabre","type":"relik","level":102,"tier":"Rare","sockets":1,"majorIds":[],"classRequirement":"Shaman","dexterity":55,"defense":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"24-214","waterDamage":"0-0","fireDamage":"97-141","airDamage":"0-0","attackSpeed":"VERY_FAST","sdRaw-base":184,"atkTier-base":1,"hpBonus-base":-1150,"hprPct-base":-204,"ms-base":13,"spRaw1-base":-7,"category":"weapon","displayName":"Danse Macabre","basedps":238,"spellDamageRaw":184,"attackSpeedBonus":1,"healthBonus":-1150,"healthRegen":-204,"manaSteal":13,"spellCostRaw1":-7,"identified":false},
{"name":"Anaerobic","type":"leggings","level":104,"tier":"Legendary","majorIds":[],"strength":60,"agility":60,"strengthPoints":12,"health":3850,"earthDefense":100,"waterDefense":-150,"airDefense":100,"eDamPct-base":24,"aDamPct-base":32,"atkTier-base":-1,"mr-base":8,"ref-base":48,"spRaw1-base":-5,"category":"armor","displayName":"Anaerobic","bonusEarthDamage":24,"bonusAirDamage":32,"attackSpeedBonus":-1,"manaRegen":8,"reflection":48,"spellCostRaw1":-8,"identified":false,"sockets":4},
{"name":"Danse Macabre","type":"relik","level":102,"tier":"Rare","sockets":1,"majorIds":[],"classRequirement":"Shaman","dexterity":55,"defense":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"24-214","waterDamage":"0-0","fireDamage":"97-141","airDamage":"0-0","attackSpeed":"VERY_FAST","sdRaw-base":184,"atkTier-base":1,"hpBonus-base":-1150,"hprPct-base":-204,"ms-base":13,"spRaw1-base":-7,"category":"weapon","displayName":"Danse Macabre","basedps":238,"spellDamageRaw":184,"attackSpeedBonus":1,"healthBonus":-1150,"healthRegenRaw":-204,"manaSteal":13,"spellCostRaw1":-7,"identified":false},
{"name":"Darkness's Dogma","type":"bow","level":103,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Archer","intelligence":60,"defense":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"600-650","fireDamage":"550-700","airDamage":"0-0","attackSpeed":"SUPER_SLOW","hpBonus-base":1500,"wDefPct-base":-50,"fDefPct-base":-50,"ms-base":13,"ls-base":-700,"ref-base":25,"category":"weapon","displayName":"Darkness's Dogma","basedps":1250,"healthBonus":1500,"bonusWaterDefense":-50,"bonusFireDefense":-50,"manaSteal":13,"lifeSteal":-700,"reflection":25,"identified":false},
{"name":"Frameshift","type":"wand","level":104,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Mage","strength":40,"defense":60,"defensePoints":20,"damage":"0-0","earthDamage":"150-210","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"160-200","airDamage":"0-0","attackSpeed":"VERY_SLOW","wDamPct-base":-30,"mdPct-base":25,"mr-base":7,"ls-base":380,"spRaw1-base":-4,"category":"weapon","displayName":"Frameshift","basedps":360,"bonusWaterDamage":-30,"damageBonus":25,"manaRegen":7,"lifeSteal":380,"spellCostRaw1":-4,"identified":false},
{"name":"Helminth","type":"spear","level":102,"tier":"Rare","sockets":2,"majorIds":[],"classRequirement":"Warrior","dexterity":65,"damage":"0-0","earthDamage":"0-0","thunderDamage":"1-199","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"SUPER_FAST","tDamPct-base":20,"atkTier-base":1,"hpBonus-base":-1250,"wDefPct-base":-35,"aDefPct-base":-35,"ls-base":500,"category":"weapon","displayName":"Helminth","basedps":100,"bonusThunderDamage":20,"attackSpeedBonus":1,"healthBonus":-1250,"bonusWaterDefense":-35,"bonusAirDefense":-35,"lifeSteal":500,"identified":false},
{"name":"Lanternfly Leg","type":"dagger","level":101,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Assassin","defense":50,"agility":50,"damage":"150-210","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"FAST","fDamPct-base":23,"aDamPct-base":23,"hpBonus-base":1000,"jh-base":1,"spd-base":30,"spRaw2-base":-2,"category":"weapon","displayName":"Lanternfly Leg","basedps":180,"bonusFireDamage":23,"bonusAirDamage":23,"healthBonus":1000,"jumpHeight":1,"speed":30,"spellCostRaw2":-4,"identified":false},
{"name":"Dissonance","type":"helmet","level":103,"tier":"Unique","sockets":2,"majorIds":[],"dexterity":50,"intelligence":50,"health":3050,"thunderDefense":100,"waterDefense":100,"airDefense":-175,"tDamPct-base":12,"wDamPct-base":20,"sdPct-base":20,"ls-base":-275,"spd-base":-20,"sprint-base":20,"lb-base":20,"category":"armor","displayName":"Dissonance","bonusThunderDamage":12,"bonusWaterDamage":20,"spellDamage":20,"lifeSteal":-275,"speed":-20,"sprint":20,"lootBonus":20,"identified":false},
{"name":"Roridula","type":"chestplate","level":104,"tier":"Unique","sockets":2,"majorIds":[],"strength":55,"intelligence":55,"strengthPoints":10,"health":3675,"earthDefense":150,"fireDefense":-150,"tDamPct-base":-30,"wDamPct-base":25,"ms-base":8,"spd-base":15,"spPct4-base":14,"xpb-base":25,"category":"armor","displayName":"Roridula","bonusThunderDamage":-30,"bonusWaterDamage":25,"manaSteal":8,"speed":15,"spellCostPct4":14,"xpBonus":25,"identified":false},
{"name":"Atomizer","type":"leggings","level":102,"tier":"Unique","sockets":3,"majorIds":[],"agility":75,"agilityPoints":8,"health":3450,"waterDefense":120,"fireDefense":120,"airDefense":200,"poison-base":600,"wDefPct-base":31,"fDefPct-base":31,"hprPct-base":37,"thorns-base":25,"jh-base":1,"category":"armor","displayName":"Atomizer","poison":600,"bonusWaterDefense":31,"bonusFireDefense":31,"healthRegen":37,"thorns":25,"jumpHeight":1,"identified":false},
{"name":"Atomizer","type":"leggings","level":102,"tier":"Unique","sockets":3,"majorIds":[],"agility":75,"agilityPoints":8,"health":4350,"waterDefense":120,"fireDefense":120,"airDefense":200,"poison-base":600,"wDefPct-base":31,"fDefPct-base":31,"hprPct-base":37,"thorns-base":25,"jh-base":1,"category":"armor","displayName":"Atomizer","poison":600,"bonusWaterDefense":31,"bonusFireDefense":31,"healthRegen":37,"thorns":25,"jumpHeight":1,"identified":false},
{"name":"Wasteland Azalea","type":"boots","level":101,"tier":"Unique","sockets":3,"majorIds":[],"strength":45,"agility":50,"health":2750,"earthDefense":75,"fireDefense":-75,"eDamPct-base":25,"aDamPct-base":25,"sdRaw-base":140,"atkTier-base":-1,"poison-base":500,"sprint-base":-15,"spRaw3-base":-6,"category":"armor","displayName":"Wasteland Azalea","bonusEarthDamage":25,"bonusAirDamage":25,"spellDamageRaw":140,"attackSpeedBonus":-1,"poison":500,"sprint":-15,"spellCostRaw3":-6,"identified":false},
{"name":"Tranquility","type":"ring","level":101,"tier":"Unique","majorIds":[],"dexterity":45,"intelligence":45,"strengthPoints":-3,"dexterityPoints":-3,"health":550,"waterDefense":50,"fireDefense":50,"sdPct-base":5,"hprPct-base":17,"spd-base":-7,"category":"accessory","displayName":"Tranquility","spellDamage":5,"healthRegen":17,"speed":-7,"identified":false},
{"name":"Tranquility","type":"ring","level":101,"tier":"Unique","majorIds":[],"defense":45,"intelligence":45,"strengthPoints":-3,"dexterityPoints":-3,"health":550,"waterDefense":50,"fireDefense":50,"sdPct-base":5,"hprPct-base":17,"spd-base":-7,"category":"accessory","displayName":"Tranquility","spellDamage":5,"healthRegen":17,"speed":-7,"identified":false},
{"name":"Misalignment","type":"bracelet","level":101,"tier":"Unique","majorIds":[],"strength":35,"dexterity":45,"dexterityPoints":3,"intelligencePoints":3,"eDamPct-base":6,"tDamPct-base":6,"wDamPct-base":10,"mr-base":3,"category":"accessory","displayName":"Misalignment","bonusEarthDamage":6,"bonusThunderDamage":6,"bonusWaterDamage":10,"manaRegen":3,"identified":false},
{"name":"Grafted Eyestalk","type":"necklace","level":101,"tier":"Unique","majorIds":[],"defense":40,"agility":40,"defensePoints":5,"agilityPoints":5,"health":-600,"earthDefense":-40,"thunderDefense":-40,"sdPct-base":8,"hprPct-base":-11,"spRaw1-base":-1,"category":"accessory","displayName":"Grafted Eyestalk","spellDamage":8,"healthRegen":-12,"spellCostRaw1":-1,"identified":false},
{"name":"Forbearance","type":"ring","level":105,"tier":"Fabled","majorIds":[],"dexterity":60,"intelligence":60,"dexterityPoints":6,"intelligencePoints":6,"tDamPct-base":-15,"wDamPct-base":-15,"mr-base":4,"ls-base":120,"category":"accessory","displayName":"Forbearance","bonusThunderDamage":-15,"bonusWaterDamage":-15,"manaRegen":4,"lifeSteal":120,"identified":false},
@ -36,7 +36,7 @@
{"name":"Scaldsteppers","type":"boots","level":90,"tier":"Unique","sockets":2,"majorIds":[],"intelligence":40,"defense":30,"intelligencePoints":7,"health":2325,"thunderDefense":-100,"waterDefense":110,"fireDefense":80,"airDefense":-90,"spRaw3-base":-4,"category":"armor","displayName":"Scaldsteppers","bonusWaterDamage":10,"bonusFireDamage":10,"bonusAirDamage":-12,"spellDamage":20,"exploding":10,"spellCostRaw3":-4,"identified":false},
{"name":"Charging Flame","type":"spear","level":94,"tier":"Rare","sockets":2,"majorIds":[],"intelligence":40,"defense":40,"damage":"20-40","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"40-120","fireDamage":"20-140","airDamage":"0-0","attackSpeed":"NORMAL","mr-base":5,"spRaw2-base":-12,"category":"weapon","displayName":"Charging Flame","basedps":190,"bonusWaterDamage":12,"bonusFireDamage":12,"damageBonus":12,"spellDamage":12,"healthBonus":-1200,"bonusThunderDefense":-25,"manaRegen":5,"exploding":24,"spellCostRaw2":-12,"identified":false},
{"name":"Aphotic","type":"helmet","level":98,"tier":"Legendary","sockets":2,"majorIds":[],"intelligence":100,"dexterityPoints":-80,"intelligencePoints":5,"health":3200,"thunderDefense":-150,"waterDefense":150,"spRaw3-base":-7,"category":"armor","displayName":"Aphotic","spellDamage":50,"attackSpeedBonus":-6,"spellCostRaw3":-7,"identified":false},
{"name":"Silent Ballet","type":"relik","level":83,"tier":"Unique","majorIds":[],"strength":40,"agility":40,"damage":"0-0","earthDamage":"110-121","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"110-121","attackSpeed":"FAST","category":"weapon","displayName":"Silent Ballet","basedps":231,"damageBonus":40,"spellDamage":-40000,"spellDamageRaw":-40000,"spellCostPct1":-40,"spellCostPct2":-40,"spellCostPct3":-40,"spellCostPct4":-40,"spellCostRaw1":-40,"spellCostRaw2":-40,"spellCostRaw3":-40,"spellCostRaw4":-40,"identified":false},
{"name":"Silent Ballet","type":"relik","level":83,"tier":"Unique","majorIds":[],"strength":40,"agility":40,"damage":"0-0","earthDamage":"110-121","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"110-121","attackSpeed":"FAST","category":"weapon","displayName":"Silent Ballet","basedps":231,"damageBonus":40,"spellDamage":-40000,"spellDamageRaw":-40000,"spellCostPct1":-40,"spellCostPct2":-40,"spellCostPct3":-40,"spellCostPct4":-40,"spellCostRaw1":-400,"spellCostRaw2":-400,"spellCostRaw3":-400,"spellCostRaw4":-400,"identified":false},
{"name":"Rhythm of the Seasons","type":"spear","level":100,"tier":"Fabled","sockets":2,"majorIds":["RALLY"],"strength":80,"defense":60,"defensePoints":12,"damage":"40-50","earthDamage":"100-140","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"VERY_FAST","mr-base":15,"category":"weapon","displayName":"Rhythm of the Seasons","basedps":165,"bonusWaterDamage":25,"healthBonus":1800,"healthRegenRaw":-660,"manaRegen":15,"identified":false},
{"name":"Sorrow","type":"chestplate","level":72,"tier":"Rare","sockets":1,"intelligence":95,"health":1400,"thunderDefense":-150,"waterDefense":150,"identified":true,"category":"armor","displayName":"Sorrow","bonusWaterDamage":42,"spellDamage":8,"manaRegen":5,"manaSteal":-20,"spellCostRaw1":-8,"soulPoints":20},
{"name":"Condensation","type":"boots","level":87,"tier":"Unique","majorIds":[],"intelligence":75,"intelligencePoints":10,"health":2000,"thunderDefense":-120,"waterDefense":100,"spRaw3-base":-6,"category":"armor","displayName":"Condensation","damageBonus":-30,"spellDamage":30,"bonusThunderDefense":-20,"spellCostRaw3":-6,"identified":false},
@ -70,11 +70,165 @@
{"name":"Monster","type":"wand","level":98,"tier":"Mythic","sockets":3,"majorIds":[],"defense":110,"defensePoints":40,"damage":"110-140","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"160-220","airDamage":"0-0","attackSpeed":"SLOW","ms-base":10,"spRaw1-base":4,"category":"weapon","displayName":"Monster","basedps":315,"bonusFireDamage":25,"damageBonus":40,"healthBonus":3000,"manaSteal":10,"lifeSteal":500,"spellCostRaw1":4,"identified":false},
{"name":"Revenant","type":"boots","level":99,"tier":"Mythic","sockets":3,"majorIds":[],"strength":70,"agility":70,"health":7000,"earthDefense":70,"airDefense":70,"ms-base":10,"spPct4-base":-28,"category":"armor","displayName":"Revenant","bonusEarthDamage":40,"bonusAirDamage":40,"damageBonus":-70,"damageBonusRaw":520,"healthBonus":-2500,"manaSteal":10,"reflection":120,"speed":40,"spellCostPct4":-28,"identified":false},
{"name":"Fatal","type":"wand","level":99,"tier":"Mythic","sockets":3,"majorIds":[],"dexterity":110,"dexterityPoints":25,"damage":"0-0","earthDamage":"0-0","thunderDamage":"1-360","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"VERY_FAST","spPct1-base":28,"spPct2-base":-49,"category":"weapon","displayName":"Fatal","basedps":180.5,"spellDamage":25,"manaSteal":1,"speed":15,"spellCostPct1":28,"spellCostPct2":-49,"identified":false},
{"name":"Warp","type":"wand","level":99,"tier":"Mythic","sockets":3,"majorIds":[],"agility":130,"agilityPoints":20,"damage":"40-70","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"190-220","attackSpeed":"VERY_FAST","mr-base":-49,"spRaw1-base":4,"spRaw2-base":-299,"category":"weapon","displayName":"Warp","basedps":260,"bonusAirDamage":15,"healthRegen":-200,"healthRegenRaw":-600,"manaRegen":-49,"reflection":90,"exploding":50,"speed":180,"spellCostRaw1":4,"spellCostRaw2":-299,"identified":false},
{"name":"Warp","type":"wand","level":99,"tier":"Mythic","sockets":3,"majorIds":[],"agility":130,"agilityPoints":20,"damage":"40-70","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"190-220","attackSpeed":"VERY_FAST","mr-base":-45,"spRaw1-base":4,"spRaw2-base":-299,"category":"weapon","displayName":"Warp","basedps":260,"bonusAirDamage":15,"healthRegen":-200,"healthRegenRaw":-600,"manaRegen":-45,"reflection":90,"exploding":50,"speed":180,"spellCostRaw1":4,"spellCostRaw2":-299,"identified":false},
{"name":"Oblivion","type":"dagger","level":101,"tier":"Mythic","sockets":4,"majorIds":[],"dexterity":75,"intelligence":65,"dexterityPoints":15,"damage":"1-200","earthDamage":"0-0","thunderDamage":"600-999","waterDamage":"600-999","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"SUPER_SLOW","mr-base":-30,"ms-base":15,"spRaw2-base":-20,"category":"weapon","displayName":"Oblivion","basedps":1699.5,"spellDamageRaw":265,"manaRegen":-30,"manaSteal":15,"exploding":40,"spellCostRaw2":-20,"soulPoints":40,"identified":false},
{"name":"Epoch","type":"bow","level":102,"tier":"Mythic","sockets":3,"majorIds":[],"dexterity":70,"agility":70,"damage":"500-620","earthDamage":"0-0","thunderDamage":"480-640","waterDamage":"0-0","fireDamage":"0-0","airDamage":"520-600","attackSpeed":"SUPER_SLOW","sdPct-base":40,"category":"weapon","displayName":"Epoch","basedps":1680,"damageBonusRaw":769,"spellDamage":40,"manaSteal":-1,"lifeSteal":825,"speed":-20,"sprint":70,"spellCostRaw1":-1,"spellCostRaw4":-1,"identified":false},
{"name":"Fantasia","type":"relik","level":96,"tier":"Mythic","sockets":3,"majorIds":[],"strength":45,"dexterity":45,"intelligence":45,"defense":45,"agility":45,"intelligencePoints":50,"damage":"0-0","earthDamage":"200-340","thunderDamage":"260-280","waterDamage":"230-310","fireDamage":"215-325","airDamage":"245-295","attackSpeed":"VERY_SLOW","spPct1-base":-27,"spPct2-base":-27,"spPct3-base":-27,"spPct4-base":-27,"category":"weapon","displayName":"Fantasia","basedps":1350,"spellDamage":30,"manaRegen":-4,"manaSteal":-4,"spellCostPct1":-27,"spellCostPct2":-27,"spellCostPct3":-27,"spellCostPct4":-27,"identified":false},
{"name":"Fantasia","type":"relik","level":96,"tier":"Mythic","sockets":3,"majorIds":[],"strength":45,"dexterity":45,"intelligence":45,"defense":45,"agility":45,"intelligencePoints":50,"damage":"0-0","earthDamage":"170-310","thunderDamage":"230-250","waterDamage":"200-280","fireDamage":"185-295","airDamage":"215-265","attackSpeed":"VERY_SLOW","spPct1-base":-27,"spPct2-base":-27,"spPct3-base":-27,"spPct4-base":-27,"category":"weapon","displayName":"Fantasia","basedps":1350,"spellDamage":30,"manaRegen":-20,"manaSteal":-20,"spellCostPct1":-27,"spellCostPct2":-27,"spellCostPct3":-27,"spellCostPct4":-27,"identified":false},
{"name":"Slayer","type":"boots","level":94,"tier":"Mythic","sockets":2,"majorIds":[],"dexterity":75,"agility":60,"dexterityPoints":20,"health":3775,"waterDefense":-100,"spPct3-base":-30,"category":"armor","displayName":"Slayer","damageBonusRaw":285,"attackSpeedBonus":1,"healthRegenRaw":-270,"speed":27,"spellCostPct3":-30,"emeraldStealing":10,"identified":false},
{"name":"Immolation","type":"relik","level":101,"tier":"Mythic","sockets":3,"majorIds":[],"defense":80,"agility":80,"defensePoints":50,"agilityPoints":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"200-440","airDamage":"310-330","attackSpeed":"SLOW","spPct3-base":-14,"category":"weapon","displayName":"Immolation","basedps":640,"bonusWaterDamage":-1000,"bonusFireDamage":45,"bonusAirDamage":45,"healthBonus":-2750,"healthRegen":-180,"spellCostPct3":-14,"identified":false},
{"name":"Convergence","type":"spear","level":104,"tier":"Mythic","sockets":3,"majorIds":[],"intelligence":65,"defense":75,"damage":"70-90","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"100-120","fireDamage":"105-115","airDamage":"0-0","attackSpeed":"NORMAL","spPct3-base":-45,"category":"weapon","displayName":"Convergence","basedps":300,"bonusEarthDamage":55,"bonusThunderDamage":55,"bonusAirDefense":35,"healthRegen":43,"sprintRegen":43,"spellCostPct3":-45,"identified":false}
{"name":"Convergence","type":"spear","level":104,"tier":"Mythic","sockets":3,"majorIds":[],"intelligence":65,"defense":75,"damage":"70-90","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"100-120","fireDamage":"105-115","airDamage":"0-0","attackSpeed":"NORMAL","spPct3-base":-45,"category":"weapon","displayName":"Convergence","basedps":300,"bonusEarthDamage":55,"bonusThunderDamage":55,"bonusAirDefense":35,"healthRegen":43,"sprintRegen":43,"spellCostPct3":-45,"identified":false},
{
"name": "Panic Zealot",
"tier": "Fabled",
"type": "Relik",
"restrictions": "Untradable",
"material": "273:7",
"dropType": "never",
"addedLore": "They must know what you went through. They must suffer the same as you did.",
"sockets": 3,
"damage": "46-60",
"earthDamage": "0-0",
"thunderDamage": "0-0",
"waterDamage": "0-0",
"fireDamage": "0-0",
"airDamage": "43-63",
"attackSpeed": "SUPER_FAST",
"level": 101,
"strength": 0,
"dexterity": 0,
"intelligence": 0,
"defense": 0,
"agility": 85,
"strengthPoints": 0,
"dexterityPoints": 0,
"intelligencePoints": 0,
"defensePoints": 0,
"agilityPoints": 0,
"majorIds": [
"FURIOUS_EFFIGY"
],
"damageBonus": 0,
"damageBonusRaw": 0,
"spellDamage": 0,
"spellDamageRaw": 0,
"rainbowSpellDamageRaw": 0,
"healthRegen": 0,
"healthRegenRaw": 0,
"healthBonus": -5000,
"poison": 0,
"lifeSteal": 0,
"manaRegen": 0,
"manaSteal": 0,
"spellCostPct1": -100,
"spellCostRaw1": 0,
"spellCostPct2": -100,
"spellCostRaw2": 0,
"spellCostPct3": -100,
"spellCostRaw3": 0,
"spellCostPct4": 0,
"spellCostRaw4": 0,
"thorns": 0,
"reflection": 0,
"attackSpeedBonus": 3,
"speed": 30,
"exploding": 0,
"soulPoints": 0,
"sprint": 0,
"sprintRegen": 0,
"jumpHeight": 0,
"xpBonus": 0,
"lootBonus": 0,
"lootQuality": 0,
"emeraldStealing": 0,
"gatherXpBonus": 0,
"gatherSpeed": 0,
"bonusEarthDamage": 0,
"bonusThunderDamage": -30,
"bonusWaterDamage": 0,
"bonusFireDamage": 0,
"bonusAirDamage": 0,
"bonusEarthDefense": 0,
"bonusThunderDefense": 0,
"bonusWaterDefense": 0,
"bonusFireDefense": 0,
"bonusAirDefense": 0,
"category": "weapon"
},
{
"name": "Ambivalence",
"tier": "Legendary",
"accessoryType": "Necklace",
"set": null,
"identified": true,
"restrictions": "Untradable",
"material": "259:29",
"dropType": "never",
"addedLore": null,
"sockets": 0,
"health": 0,
"earthDefense": 0,
"thunderDefense": 70,
"waterDefense": 0,
"fireDefense": 70,
"airDefense": 70,
"level": 100,
"quest": null,
"classRequirement": null,
"strength": 0,
"dexterity": 40,
"intelligence": 0,
"defense": 40,
"agility": 40,
"strengthPoints": 0,
"dexterityPoints": 0,
"intelligencePoints": -100,
"defensePoints": 0,
"agilityPoints": 0,
"damageBonus": 0,
"damageBonusRaw": 0,
"spellDamage": 250,
"spellDamageRaw": 0,
"rainbowSpellDamageRaw": 0,
"healthRegen": 0,
"healthRegenRaw": 0,
"healthBonus": 0,
"poison": 0,
"lifeSteal": 0,
"manaRegen": 0,
"manaSteal": 0,
"spellCostPct1": 130,
"spellCostRaw1": 0,
"spellCostPct2": 85,
"spellCostRaw2": 0,
"spellCostPct3": 130,
"spellCostRaw3": 0,
"spellCostPct4": 100,
"spellCostRaw4": 0,
"thorns": 0,
"reflection": 0,
"attackSpeedBonus": 0,
"speed": 0,
"exploding": 0,
"soulPoints": 0,
"sprint": 0,
"sprintRegen": 0,
"jumpHeight": 0,
"xpBonus": 0,
"lootBonus": 0,
"lootQuality": 0,
"emeraldStealing": 0,
"gatherXpBonus": 0,
"gatherSpeed": 0,
"bonusEarthDamage": 0,
"bonusThunderDamage": 0,
"bonusWaterDamage": 50,
"bonusFireDamage": 0,
"bonusAirDamage": 0,
"bonusEarthDefense": 0,
"bonusThunderDefense": 0,
"bonusWaterDefense": 0,
"bonusFireDefense": 0,
"bonusAirDefense": 0,
"category": "accessory"
}
]}

View file

@ -59,7 +59,7 @@ mul_keys = {
}
def round_near(x, eps=1e-5):
if x - round(x) < eps:
if abs(x - round(x)) < eps:
return round(x)
return x