Almost working spell damage calculation
This commit is contained in:
parent
62a9a4f0c2
commit
8db34d68a7
10 changed files with 212 additions and 114 deletions
43
js/build.js
43
js/build.js
|
@ -127,7 +127,9 @@ class Build{
|
|||
this.weapon = weapon;
|
||||
this.items = this.equipment.concat([this.weapon]).concat(this.tomes);
|
||||
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
||||
let result = calculate_skillpoints(this.equipment.concat(this.tomes), this.weapon);
|
||||
|
||||
// calc skillpoints requires statmaps only
|
||||
let result = calculate_skillpoints(this.equipment.concat(this.tomes).map((x) => x.statMap), this.weapon.statMap);
|
||||
console.log(result);
|
||||
this.equip_order = result[0];
|
||||
// How many skillpoints the player had to assign (5 number)
|
||||
|
@ -165,8 +167,9 @@ class Build{
|
|||
*/
|
||||
getMeleeStats(){
|
||||
const stats = this.statMap;
|
||||
if (this.weapon.get("tier") === "Crafted") {
|
||||
stats.set("damageBases", [this.weapon.get("nDamBaseHigh"),this.weapon.get("eDamBaseHigh"),this.weapon.get("tDamBaseHigh"),this.weapon.get("wDamBaseHigh"),this.weapon.get("fDamBaseHigh"),this.weapon.get("aDamBaseHigh")]);
|
||||
const weapon_stats = this.weapon.statMap;
|
||||
if (weapon_stats.get("tier") === "Crafted") {
|
||||
stats.set("damageBases", [weapon_stats.get("nDamBaseHigh"),weapon_stats.get("eDamBaseHigh"),weapon_stats.get("tDamBaseHigh"),weapon_stats.get("wDamBaseHigh"),weapon_stats.get("fDamBaseHigh"),weapon_stats.get("aDamBaseHigh")]);
|
||||
}
|
||||
let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier");
|
||||
if(adjAtkSpd > 6){
|
||||
|
@ -176,13 +179,13 @@ class Build{
|
|||
}
|
||||
|
||||
let damage_mult = 1;
|
||||
if (this.weapon.get("type") === "relik") {
|
||||
if (weapon_stats.get("type") === "relik") {
|
||||
damage_mult = 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.
|
||||
}
|
||||
// 0spellmult for melee damage.
|
||||
let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], stats.get("mdRaw"), stats.get("mdPct") + this.externalStats.get("mdPct"), 0, this.weapon, this.total_skillpoints, damage_mult * this.damageMultiplier, this.externalStats);
|
||||
let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], stats.get("mdRaw"), stats.get("mdPct"), 0, this.weapon.statMap, this.total_skillpoints, damage_mult * this.damageMultiplier);
|
||||
|
||||
let dex = this.total_skillpoints[1];
|
||||
|
||||
|
@ -217,7 +220,7 @@ class Build{
|
|||
defenseStats.push(totalHp);
|
||||
//EHP
|
||||
let ehp = [totalHp, totalHp];
|
||||
let defMult = classDefenseMultipliers.get(this.weapon.get("type"));
|
||||
let defMult = classDefenseMultipliers.get(this.weapon.statMap.get("type"));
|
||||
ehp[0] /= ((1-def_pct)*(1-agi_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
ehp[1] /= ((1-def_pct)*(2-defMult)*(2-this.defenseMultiplier));
|
||||
defenseStats.push(ehp);
|
||||
|
@ -259,26 +262,27 @@ class Build{
|
|||
|
||||
let major_ids = new Set();
|
||||
for (const item of this.items){
|
||||
for (let [id, value] of item.get("maxRolls")) {
|
||||
const item_stats = item.statMap;
|
||||
for (let [id, value] of item_stats.get("maxRolls")) {
|
||||
if (staticIDs.includes(id)) {
|
||||
continue;
|
||||
}
|
||||
statMap.set(id,(statMap.get(id) || 0)+value);
|
||||
}
|
||||
for (const staticID of staticIDs) {
|
||||
if (item.get(staticID)) {
|
||||
statMap.set(staticID, statMap.get(staticID) + item.get(staticID));
|
||||
if (item_stats.get(staticID)) {
|
||||
statMap.set(staticID, statMap.get(staticID) + item_stats.get(staticID));
|
||||
}
|
||||
}
|
||||
if (item.get("majorIds")) {
|
||||
for (const major_id of item.get("majorIds")) {
|
||||
if (item_stats.get("majorIds")) {
|
||||
for (const major_id of item_stats.get("majorIds")) {
|
||||
major_ids.add(major_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
statMap.set("activeMajorIDs", major_ids);
|
||||
for (const [setName, count] of this.activeSetCounts) {
|
||||
const bonus = sets[setName].bonuses[count-1];
|
||||
const bonus = sets.get(setName).bonuses[count-1];
|
||||
for (const id in bonus) {
|
||||
if (skp_order.includes(id)) {
|
||||
// pass. Don't include skillpoints in ids
|
||||
|
@ -291,16 +295,8 @@ class Build{
|
|||
statMap.set("poisonPct", 100);
|
||||
|
||||
// The stuff relevant for damage calculation!!! @ferricles
|
||||
statMap.set("atkSpd", this.weapon.get("atkSpd"));
|
||||
statMap.set("atkSpd", this.weapon.statMap.get("atkSpd"));
|
||||
|
||||
for (const x of skp_elements) {
|
||||
this.externalStats.set(x + "DamPct", 0);
|
||||
}
|
||||
this.externalStats.set("mdPct", 0);
|
||||
this.externalStats.set("sdPct", 0);
|
||||
this.externalStats.set("damageBonus", [0, 0, 0, 0, 0]);
|
||||
this.externalStats.set("defBonus",[0, 0, 0, 0, 0]);
|
||||
this.externalStats.set("poisonPct", 0);
|
||||
this.statMap = statMap;
|
||||
|
||||
this.aggregateStats();
|
||||
|
@ -308,10 +304,11 @@ class Build{
|
|||
|
||||
aggregateStats() {
|
||||
let statMap = this.statMap;
|
||||
statMap.set("damageRaw", [this.weapon.get("nDam"), this.weapon.get("eDam"), this.weapon.get("tDam"), this.weapon.get("wDam"), this.weapon.get("fDam"), this.weapon.get("aDam")]);
|
||||
let weapon_stats = this.weapon.statMap;
|
||||
statMap.set("damageRaw", [weapon_stats.get("nDam"), weapon_stats.get("eDam"), weapon_stats.get("tDam"), weapon_stats.get("wDam"), weapon_stats.get("fDam"), weapon_stats.get("aDam")]);
|
||||
statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]);
|
||||
statMap.set("defRaw", [statMap.get("eDef"), statMap.get("tDef"), statMap.get("wDef"), statMap.get("fDef"), statMap.get("aDef")]);
|
||||
statMap.set("defBonus", [statMap.get("eDefPct"), statMap.get("tDefPct"), statMap.get("wDefPct"), statMap.get("fDefPct"), statMap.get("aDefPct")]);
|
||||
statMap.set("defMult", classDefenseMultipliers.get(this.weapon.get("type")));
|
||||
statMap.set("defMult", classDefenseMultipliers.get(weapon_stats.get("type")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ let equipmentInputs = equipment_fields.map(x => x + "-choice");
|
|||
let buildFields = equipment_fields.map(x => x+"-tooltip").concat(tome_fields.map(x => x + "-tooltip"));
|
||||
let tomeInputs = tome_fields.map(x => x + "-choice");
|
||||
|
||||
let powderInputs = [
|
||||
let powder_inputs = [
|
||||
"helmet-powder",
|
||||
"chestplate-powder",
|
||||
"leggings-powder",
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
function parsePowdering(powder_info) {
|
||||
// TODO: Make this run in linear instead of quadratic time... ew
|
||||
let powdering = [];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
let powders = "";
|
||||
let n_blocks = Base64.toInt(powder_info.charAt(0));
|
||||
// console.log(n_blocks + " blocks");
|
||||
powder_info = powder_info.slice(1);
|
||||
for (let j = 0; j < n_blocks; ++j) {
|
||||
let block = powder_info.slice(0,5);
|
||||
console.log(block);
|
||||
let six_powders = Base64.toInt(block);
|
||||
for (let k = 0; k < 6 && six_powders != 0; ++k) {
|
||||
powders += powderNames.get((six_powders & 0x1f) - 1);
|
||||
six_powders >>>= 5;
|
||||
}
|
||||
powder_info = powder_info.slice(5);
|
||||
}
|
||||
powdering[i] = powders;
|
||||
}
|
||||
return [powdering, powder_info];
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate fields based on url, and calculate build.
|
||||
|
@ -107,8 +129,8 @@ function decodeBuild(url_tag) {
|
|||
info[1] = info[1].slice(7);
|
||||
}
|
||||
|
||||
for (let i in powderInputs) {
|
||||
setValue(powderInputs[i], powdering[i]);
|
||||
for (let i in powder_inputs) {
|
||||
setValue(powder_inputs[i], powdering[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,29 +12,6 @@ function getTomeNameFromID(id) {
|
|||
return tomeIDMap.get(id);
|
||||
}
|
||||
|
||||
function parsePowdering(powder_info) {
|
||||
// TODO: Make this run in linear instead of quadratic time... ew
|
||||
let powdering = [];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
let powders = "";
|
||||
let n_blocks = Base64.toInt(powder_info.charAt(0));
|
||||
// console.log(n_blocks + " blocks");
|
||||
powder_info = powder_info.slice(1);
|
||||
for (let j = 0; j < n_blocks; ++j) {
|
||||
let block = powder_info.slice(0,5);
|
||||
console.log(block);
|
||||
let six_powders = Base64.toInt(block);
|
||||
for (let k = 0; k < 6 && six_powders != 0; ++k) {
|
||||
powders += powderNames.get((six_powders & 0x1f) - 1);
|
||||
six_powders >>>= 5;
|
||||
}
|
||||
powder_info = powder_info.slice(5);
|
||||
}
|
||||
powdering[i] = powders;
|
||||
}
|
||||
return [powdering, powder_info];
|
||||
}
|
||||
|
||||
function populateBuildList() {
|
||||
const buildList = document.getElementById("build-choice");
|
||||
const savedBuilds = window.localStorage.getItem("builds") === null ? {} : JSON.parse(window.localStorage.getItem("builds"));
|
||||
|
@ -139,6 +116,21 @@ function toggle_tab(tab) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
let tabs = ['overall-stats', 'offensive-stats', 'defensive-stats'];
|
||||
function show_tab(tab) {
|
||||
//console.log(itemFilters)
|
||||
|
||||
//hide all tabs, then show the tab of the div clicked and highlight the correct button
|
||||
for (const i in tabs) {
|
||||
document.querySelector("#" + tabs[i]).style.display = "none";
|
||||
document.getElementById("tab-" + tabs[i].split("-")[0] + "-btn").classList.remove("selected-btn");
|
||||
}
|
||||
document.querySelector("#" + tab).style.display = "";
|
||||
document.getElementById("tab-" + tab.split("-")[0] + "-btn").classList.add("selected-btn");
|
||||
}
|
||||
|
||||
|
||||
// TODO: Learn and use await
|
||||
function init() {
|
||||
console.log("builder.js init");
|
||||
|
|
|
@ -42,14 +42,71 @@ class BuildAssembleNode extends ComputeNode {
|
|||
];
|
||||
let weapon = input_map.get('weapon-input');
|
||||
let level = input_map.get('level-input');
|
||||
console.log('build node run');
|
||||
|
||||
let all_none = weapon.statMap.has('NONE');
|
||||
for (const item of equipments) {
|
||||
all_none = all_none && item.statMap.has('NONE');
|
||||
}
|
||||
if (all_none) {
|
||||
return null;
|
||||
}
|
||||
return new Build(level, equipments, [], weapon);
|
||||
}
|
||||
}
|
||||
|
||||
class PowderInputNode extends InputNode {
|
||||
|
||||
constructor(name, input_field) {
|
||||
super(name, input_field);
|
||||
}
|
||||
|
||||
compute_func(input_map) {
|
||||
// TODO: haha improve efficiency to O(n) dumb
|
||||
// also, error handling is missing
|
||||
let input = this.input_field.value.trim();
|
||||
let powdering = [];
|
||||
let errorederrors = [];
|
||||
while (input) {
|
||||
let first = input.slice(0, 2);
|
||||
let powder = powderIDs.get(first);
|
||||
if (powder === undefined) {
|
||||
return null;
|
||||
} else {
|
||||
powdering.push(powder);
|
||||
}
|
||||
input = input.slice(2);
|
||||
}
|
||||
//console.log("POWDERING: " + powdering);
|
||||
return powdering;
|
||||
}
|
||||
}
|
||||
|
||||
class SpellDamageCalcNode extends ComputeNode {
|
||||
constructor(spell_num) {
|
||||
super("builder-spell"+spell_num+"-calc");
|
||||
this.spell_idx = spell_num;
|
||||
}
|
||||
|
||||
compute_func(input_map) {
|
||||
// inputs:
|
||||
let weapon = new Map(input_map.get('weapon-input').statMap);
|
||||
let build = input_map.get('build');
|
||||
let weapon_powder = input_map.get('weapon-powder');
|
||||
weapon.set("powders", weapon_powder);
|
||||
const i = this.spell_idx;
|
||||
let spell = spell_table[weapon.get("type")][i];
|
||||
let parent_elem = document.getElementById("spell"+i+"-info");
|
||||
let overallparent_elem = document.getElementById("spell"+i+"-infoAvg");
|
||||
displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, i+1, weapon);
|
||||
}
|
||||
}
|
||||
|
||||
let item_nodes = [];
|
||||
let powder_nodes = [];
|
||||
let spell_nodes = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Bind item input fields to input nodes, and some display stuff (for auto colorizing stuff).
|
||||
for (const [eq, none_item] of zip(equipment_fields, none_items)) {
|
||||
let input_field = document.getElementById(eq+"-choice");
|
||||
let item_image = document.getElementById(eq+"-img");
|
||||
|
@ -57,28 +114,70 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
let item_input = new ItemInputNode(eq+'-input', input_field, none_item);
|
||||
item_nodes.push(item_input);
|
||||
new ItemInputDisplayNode(eq+'-display', input_field, item_image).link_to(item_input);
|
||||
new PrintNode(eq+'-debug').link_to(item_input);
|
||||
//new PrintNode(eq+'-debug').link_to(item_input);
|
||||
//document.querySelector("#"+eq+"-tooltip").setAttribute("onclick", "collapse_element('#"+ eq +"-tooltip');"); //toggle_plus_minus('" + eq + "-pm');
|
||||
|
||||
}
|
||||
|
||||
// weapon image changer node.
|
||||
let weapon_image = document.getElementById("weapon-img");
|
||||
new WeaponDisplayNode('weapon-type', weapon_image).link_to(item_nodes[8]);
|
||||
let level_input = new InputNode('level-input', document.getElementById('level-choice'));
|
||||
new PrintNode('lvl-debug').link_to(level_input);
|
||||
|
||||
// Level input node.
|
||||
let level_input = new InputNode('level-input', document.getElementById('level-choice'));
|
||||
|
||||
// "Build" now only refers to equipment and level (no powders). Powders are injected before damage calculation / stat display.
|
||||
let build_node = new BuildAssembleNode();
|
||||
for (const input of item_nodes) {
|
||||
build_node.link_to(input);
|
||||
}
|
||||
build_node.link_to(level_input);
|
||||
|
||||
|
||||
for (const input of powder_inputs) {
|
||||
powder_nodes.push(new PowderInputNode(input, document.getElementById(input)));
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
let spell_node = new SpellDamageCalcNode(i);
|
||||
spell_node.link_to(item_nodes[8], 'weapon-input');
|
||||
spell_node.link_to(build_node, 'build');
|
||||
spell_node.link_to(powder_nodes[4], 'weapon-powder');
|
||||
spell_nodes.push(spell_node);
|
||||
}
|
||||
|
||||
console.log("Set up graph");
|
||||
|
||||
let masonry = Macy({
|
||||
container: "#masonry-container",
|
||||
columns: 1,
|
||||
mobileFirst: true,
|
||||
breakAt: {
|
||||
1200: 4,
|
||||
},
|
||||
margin: {
|
||||
x: 20,
|
||||
y: 20,
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
let search_masonry = Macy({
|
||||
container: "#search-results",
|
||||
columns: 1,
|
||||
mobileFirst: true,
|
||||
breakAt: {
|
||||
1200: 4,
|
||||
},
|
||||
margin: {
|
||||
x: 20,
|
||||
y: 20,
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// autocomplete initialize
|
||||
function init_autocomplete() {
|
||||
console.log("autocomplete init");
|
||||
console.log(itemLists)
|
||||
let dropdowns = new Map();
|
||||
for (const eq of equipment_keys) {
|
||||
if (tome_keys.includes(eq)) {
|
||||
|
|
|
@ -7,13 +7,14 @@ class ComputeNode {
|
|||
*/
|
||||
constructor(name) {
|
||||
this.inputs = []; // parent nodes
|
||||
this.input_translation = new Map();
|
||||
this.children = [];
|
||||
this.value = 0;
|
||||
this.value = null;
|
||||
this.name = name;
|
||||
this.update_task = null;
|
||||
this.update_time = Date.now();
|
||||
this.fail_cb = false; // Set to true to force updates even if parent failed.
|
||||
this.dirty = false;
|
||||
this.dirty = true;
|
||||
this.inputs_dirty = new Map();
|
||||
this.inputs_dirty_count = 0;
|
||||
}
|
||||
|
@ -32,7 +33,7 @@ class ComputeNode {
|
|||
}
|
||||
let calc_inputs = new Map();
|
||||
for (const input of this.inputs) {
|
||||
calc_inputs.set(input.name, input.value);
|
||||
calc_inputs.set(this.input_translation.get(input.name), input.value);
|
||||
}
|
||||
this.value = this.compute_func(calc_inputs);
|
||||
this.dirty = false;
|
||||
|
@ -41,18 +42,6 @@ class ComputeNode {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this node's value directly. Notifies children.
|
||||
*/
|
||||
set_value(value) {
|
||||
let timestamp = Date.now();
|
||||
this.update_time = timestamp;
|
||||
this.value = value;
|
||||
for (const child of this.children) {
|
||||
child.set_input(this.name, this.value, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark parent as not dirty. Propagates calculation if all inputs are present.
|
||||
*/
|
||||
|
@ -99,8 +88,10 @@ class ComputeNode {
|
|||
throw "no compute func specified";
|
||||
}
|
||||
|
||||
link_to(parent_node) {
|
||||
link_to(parent_node, link_name) {
|
||||
this.inputs.push(parent_node)
|
||||
link_name = (link_name !== undefined) ? link_name : parent_node.name;
|
||||
this.input_translation.set(parent_node.name, link_name);
|
||||
this.inputs_dirty.set(parent_node.name, parent_node.dirty);
|
||||
if (parent_node.dirty) {
|
||||
this.inputs_dirty_count += 1;
|
||||
|
@ -147,6 +138,7 @@ class InputNode extends ComputeNode {
|
|||
super(name);
|
||||
this.input_field = input_field;
|
||||
this.input_field.addEventListener("input", () => calcSchedule(this));
|
||||
calcSchedule(this);
|
||||
}
|
||||
|
||||
compute_func(input_map) {
|
||||
|
@ -168,6 +160,7 @@ class ItemInputNode extends InputNode {
|
|||
constructor(name, item_input_field, none_item) {
|
||||
super(name, item_input_field);
|
||||
this.none_item = new Item(none_item);
|
||||
this.none_item.statMap.set('NONE', true);
|
||||
}
|
||||
|
||||
compute_func(input_map) {
|
||||
|
@ -231,9 +224,13 @@ class ItemInputDisplayNode extends ComputeNode {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (item.statMap.has('NONE')) {
|
||||
return null;
|
||||
}
|
||||
const tier = item.statMap.get('tier');
|
||||
this.input_field.classList.add(tier);
|
||||
this.image.classList.add(tier + "-shadow");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,12 @@
|
|||
const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["vanish", 0.80], ["warscream", 0.10], ["bash", 0.50] ]);
|
||||
// Calculate spell damage given a spell elemental conversion table, and a spell multiplier.
|
||||
// If spell mult is 0, its melee damage and we don't multiply by attack speed.
|
||||
// externalStats should be a map
|
||||
function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier, externalStats) {
|
||||
function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, total_skillpoints, damageMultiplier) {
|
||||
let buildStats = new Map(stats);
|
||||
let tooltipinfo = new Map();
|
||||
//6x for damages, normal min normal max crit min crit max
|
||||
let damageformulas = [["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "],["Min: = ","Max: = ","Min: = ","Max: = "]];
|
||||
|
||||
if(externalStats) { //if nothing is passed in, then this hopefully won't trigger
|
||||
for (const entry of externalStats) {
|
||||
const key = entry[0];
|
||||
const value = entry[1];
|
||||
if (typeof value === "number") {
|
||||
buildStats.set(key, buildStats.get(key) + value);
|
||||
} else if (Array.isArray(value)) {
|
||||
arr = [];
|
||||
for (let j = 0; j < value.length; j++) {
|
||||
arr[j] = buildStats.get(key)[j] + value[j];
|
||||
}
|
||||
buildStats.set(key, arr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let powders = weapon.get("powders").slice();
|
||||
|
||||
// Array of neutral + ewtfa damages. Each entry is a pair (min, max).
|
||||
|
|
17
js/load.js
17
js/load.js
|
@ -6,7 +6,7 @@ let reload = false;
|
|||
let load_complete = false;
|
||||
let load_in_progress = false;
|
||||
let items;
|
||||
let sets;
|
||||
let sets = new Map();
|
||||
let itemMap;
|
||||
let idMap;
|
||||
let redirectMap;
|
||||
|
@ -20,7 +20,6 @@ async function load_local() {
|
|||
let sets_store = get_tx.objectStore('set_db');
|
||||
let get_store = get_tx.objectStore('item_db');
|
||||
let request = get_store.getAll();
|
||||
let request2 = sets_store.getAll();
|
||||
request.onerror = function(event) {
|
||||
reject("Could not read local item db...");
|
||||
}
|
||||
|
@ -28,15 +27,27 @@ async function load_local() {
|
|||
console.log("Successfully read local item db.");
|
||||
}
|
||||
|
||||
// key-value iteration (hpp don't break this again)
|
||||
// https://stackoverflow.com/questions/47931595/indexeddb-getting-all-data-with-keys
|
||||
let request2 = sets_store.openCursor();
|
||||
request2.onerror = function(event) {
|
||||
reject("Could not read local set db...");
|
||||
}
|
||||
request2.onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
let key = cursor.primaryKey;
|
||||
let value = cursor.value;
|
||||
sets.set(key, value);
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
// no more results
|
||||
console.log("Successfully read local set db.");
|
||||
}
|
||||
};
|
||||
get_tx.oncomplete = function(event) {
|
||||
items = request.result;
|
||||
sets = request2.result;
|
||||
init_maps();
|
||||
load_complete = true;
|
||||
db.close();
|
||||
|
|
|
@ -31,14 +31,15 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
let setCount = activeSetCounts.get(setName);
|
||||
let old_bonus = {};
|
||||
if (setCount) {
|
||||
old_bonus = sets[setName].bonuses[setCount-1];
|
||||
old_bonus = sets.get(setName).bonuses[setCount-1];
|
||||
activeSetCounts.set(setName, setCount + 1);
|
||||
}
|
||||
else {
|
||||
setCount = 0;
|
||||
activeSetCounts.set(setName, 1);
|
||||
}
|
||||
const new_bonus = sets[setName].bonuses[setCount];
|
||||
console.log(sets);
|
||||
const new_bonus = sets.get(setName).bonuses[setCount];
|
||||
//let skp_order = ["str","dex","int","def","agi"];
|
||||
for (const i in skp_order) {
|
||||
const delta = (new_bonus[skp_order[i]] || 0) - (old_bonus[skp_order[i]] || 0);
|
||||
|
@ -74,8 +75,8 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
if (setName) { // undefined/null means no set.
|
||||
const setCount = activeSetCounts.get(setName);
|
||||
if (setCount) {
|
||||
const old_bonus = sets[setName].bonuses[setCount-1];
|
||||
const new_bonus = sets[setName].bonuses[setCount];
|
||||
const old_bonus = sets.get(setName).bonuses[setCount-1];
|
||||
const new_bonus = sets.get(setName).bonuses[setCount];
|
||||
//let skp_order = ["str","dex","int","def","agi"];
|
||||
for (const i in skp_order) {
|
||||
const set_delta = (new_bonus[skp_order[i]] || 0) - (old_bonus[skp_order[i]] || 0);
|
||||
|
|
|
@ -41,7 +41,7 @@ function displaysq2BuildStats(parent_id,build,command_group){
|
|||
// id instruction
|
||||
else {
|
||||
let id = command;
|
||||
if (stats.get(id) || build.externalStats.get(id)) {
|
||||
if (stats.get(id)) {
|
||||
let style = null;
|
||||
|
||||
// TODO: add pos and neg style
|
||||
|
@ -54,10 +54,6 @@ function displaysq2BuildStats(parent_id,build,command_group){
|
|||
|
||||
// ignore
|
||||
let id_val = stats.get(id);
|
||||
if (build.externalStats.has(id)) {
|
||||
id_val += build.externalStats.get(id);
|
||||
}
|
||||
|
||||
if (reversedIDs.includes(id)) {
|
||||
style === "positive" ? style = "negative" : style = "positive";
|
||||
}
|
||||
|
@ -650,7 +646,7 @@ function displaysq2PoisonDamage(overallparent_elem, build) {
|
|||
let overallpoisonDamage = document.createElement("p");
|
||||
let overallpoisonDamageFirst = document.createElement("span");
|
||||
let overallpoisonDamageSecond = document.createElement("span");
|
||||
let poison_tick = Math.ceil(build.statMap.get("poison") * (1+skillPointsToPercentage(build.total_skillpoints[0])) * (build.statMap.get("poisonPct") + build.externalStats.get("poisonPct"))/100 /3);
|
||||
let poison_tick = Math.ceil(build.statMap.get("poison") * (1+skillPointsToPercentage(build.total_skillpoints[0])) * (build.statMap.get("poisonPct"))/100 /3);
|
||||
overallpoisonDamageFirst.textContent = "Poison Tick: ";
|
||||
overallpoisonDamageSecond.textContent = Math.max(poison_tick,0);
|
||||
overallpoisonDamageSecond.classList.add("Damage");
|
||||
|
@ -1126,8 +1122,8 @@ function displaysq2PowderSpecials(parent_elem, powderSpecials, build, overall=fa
|
|||
let spell = (powderSpecialStats.indexOf(special[0]) == 3 ? spells[2] : spells[powderSpecialStats.indexOf(special[0])]);
|
||||
let part = spell["parts"][0];
|
||||
let _results = calculateSpellDamage(stats, part.conversion,
|
||||
stats.get("mdRaw"), stats.get("mdPct") + build.externalStats.get("mdPct"),
|
||||
0, build.weapon, build.total_skillpoints, build.damageMultiplier * ((part.multiplier[power-1] / 100)), build.externalStats);//part.multiplier[power] / 100
|
||||
stats.get("mdRaw"), stats.get("mdPct"),
|
||||
0, build.weapon, build.total_skillpoints, build.damageMultiplier * ((part.multiplier[power-1] / 100)));//part.multiplier[power] / 100
|
||||
|
||||
let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
|
||||
let save_damages = [];
|
||||
|
@ -1215,7 +1211,7 @@ function displaysq2PowderSpecials(parent_elem, powderSpecials, build, overall=fa
|
|||
}
|
||||
}
|
||||
|
||||
function displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx) {
|
||||
function displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx, weapon) {
|
||||
parent_elem.textContent = "";
|
||||
|
||||
|
||||
|
@ -1264,7 +1260,7 @@ function displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, sp
|
|||
parent_elem.append(title_elem);
|
||||
overallparent_elem.append(title_elemavg);
|
||||
|
||||
overallparent_elem.append(displaysq2NextCosts(spell, build));
|
||||
overallparent_elem.append(displaysq2NextCosts(spell, build, weapon));
|
||||
|
||||
|
||||
let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
|
||||
|
@ -1300,8 +1296,8 @@ function displaysq2SpellDamage(parent_elem, overallparent_elem, build, spell, sp
|
|||
if (part.type === "damage") {
|
||||
//console.log(build.expandedStats);
|
||||
let _results = calculateSpellDamage(stats, part.conversion,
|
||||
stats.get("sdRaw") + stats.get("rainbowRaw"), stats.get("sdPct") + build.externalStats.get("sdPct"),
|
||||
part.multiplier / 100, build.weapon, build.total_skillpoints, build.damageMultiplier, build.externalStats);
|
||||
stats.get("sdRaw") + stats.get("rainbowRaw"), stats.get("sdPct"),
|
||||
part.multiplier / 100, weapon, build.total_skillpoints, build.damageMultiplier);
|
||||
let totalDamNormal = _results[0];
|
||||
let totalDamCrit = _results[1];
|
||||
let results = _results[2];
|
||||
|
@ -1427,9 +1423,9 @@ function displaysq2EquipOrder(parent_elem, buildOrder){
|
|||
}
|
||||
}
|
||||
|
||||
function displaysq2NextCosts(spell, build) {
|
||||
function displaysq2NextCosts(spell, build, weapon) {
|
||||
let int = build.total_skillpoints[2];
|
||||
let spells = spell_table[build.weapon.get("type")];
|
||||
let spells = spell_table[weapon.get("type")];
|
||||
|
||||
let row = document.createElement("div");
|
||||
row.classList.add("spellcost-tooltip");
|
||||
|
|
Loading…
Add table
Reference in a new issue