Adding powdering and general spell calc framework
This commit is contained in:
parent
d9941fac60
commit
aa29998340
6 changed files with 196 additions and 114 deletions
83
build.js
83
build.js
|
@ -55,50 +55,50 @@ class Build{
|
|||
if(helmet.type.valueOf() != "helmet".valueOf()){
|
||||
throw new TypeError("No such helmet named ", helmet.name);
|
||||
}else{
|
||||
this.helmet = helmet;
|
||||
this.powders[0] = this.powders[0].slice(0,helmet.slots);
|
||||
this.helmet = expandItem(helmet, this.powders[0]);
|
||||
}
|
||||
if(chestplate.type.valueOf() != "chestplate"){
|
||||
throw new TypeError("No such chestplate named ", chestplate.name);
|
||||
}else{
|
||||
this.chestplate = chestplate;
|
||||
this.powders[1] = this.powders[1].slice(0,chestplate.slots);
|
||||
this.chestplate = expandItem(chestplate, this.powders[1]);
|
||||
}
|
||||
if(leggings.type.valueOf() != "leggings"){
|
||||
throw new TypeError("No such leggings named ", leggings.name);
|
||||
}else{
|
||||
this.leggings = leggings;
|
||||
this.powders[2] = this.powders[2].slice(0,leggings.slots);
|
||||
this.leggings = expandItem(leggings, this.powders[2]);
|
||||
}
|
||||
if(boots.type.valueOf() != "boots"){
|
||||
throw new TypeError("No such boots named ", boots.name);
|
||||
}else{
|
||||
this.boots = boots;
|
||||
this.powders[3] = this.powders[3].slice(0,boots.slots);
|
||||
this.boots = expandItem(boots, this.powders[3]);
|
||||
}
|
||||
if(ring1.type.valueOf() != "ring"){
|
||||
throw new TypeError("No such ring named ", ring1.name);
|
||||
}else{
|
||||
this.ring1 = ring1;
|
||||
this.ring1 = expandItem(ring1, []);
|
||||
}
|
||||
if(ring2.type.valueOf() != "ring"){
|
||||
throw new TypeError("No such ring named ", ring2.name);
|
||||
}else{
|
||||
this.ring2 = ring2;
|
||||
this.ring2 = expandItem(ring2, []);
|
||||
}
|
||||
if(bracelet.type.valueOf() != "bracelet"){
|
||||
throw new TypeError("No such bracelet named ", bracelet.name);
|
||||
}else{
|
||||
this.bracelet = bracelet;
|
||||
this.bracelet = expandItem(bracelet, []);
|
||||
}
|
||||
if(necklace.type.valueOf() != "necklace"){
|
||||
throw new TypeError("No such necklace named ", necklace.name);
|
||||
}else{
|
||||
this.necklace = necklace;
|
||||
this.necklace = expandItem(necklace, []);
|
||||
}
|
||||
if(weapon.type.valueOf() == "wand" || weapon.type.valueOf() == "bow" || weapon.type.valueOf() == "dagger" || weapon.type.valueOf() == "spear" || weapon.type.valueOf() == "relik"){
|
||||
this.weapon = weapon;
|
||||
this.powders[4] = this.powders[4].slice(0,weapon.slots);
|
||||
this.weapon = expandItem(weapon, this.powders[4]);
|
||||
}else{
|
||||
throw new TypeError("No such weapon named ", weapon.name);
|
||||
}
|
||||
|
@ -110,17 +110,17 @@ class Build{
|
|||
this.level = level;
|
||||
}
|
||||
this.availableSkillpoints = levelToSkillPoints(this.level);
|
||||
this.equipment = [ helmet, chestplate, leggings, boots, ring1, ring2, bracelet, necklace ];
|
||||
this.items = this.equipment.concat([weapon]);
|
||||
this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ];
|
||||
this.items = this.equipment.concat([this.weapon]);
|
||||
// return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
||||
let result = calculate_skillpoints(this.equipment, weapon);
|
||||
let result = calculate_skillpoints(this.equipment, this.weapon);
|
||||
this.equip_order = result[0];
|
||||
this.base_skillpoints = result[1];
|
||||
this.total_skillpoints = result[2];
|
||||
this.assigned_skillpoints = result[3];
|
||||
|
||||
// For strength boosts like warscream, vanish, etc.
|
||||
this.damage_multiplier = 1.0;
|
||||
this.damageMultiplier = 1.0;
|
||||
|
||||
this.initBuildStats();
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ class Build{
|
|||
/*Returns build in string format
|
||||
*/
|
||||
toString(){
|
||||
return this.helmet.name + ", " + this.chestplate.name + ", " + this.leggings.name + ", " + this.boots.name + ", " + this.ring1.name + ", " + this.ring2.name + ", " + this.bracelet.name + ", " + this.necklace.name + ", " + this.weapon.name;
|
||||
return this.helmet.get("name") + ", " + this.chestplate.get("name") + ", " + this.leggings.get("name") + ", " + this.boots.get("name") + ", " + this.ring1.get("name") + ", " + this.ring2.get("name") + ", " + this.bracelet.get("name") + ", " + this.necklace.get("name") + ", " + this.weapon.get("name");
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
|
@ -147,67 +147,37 @@ class Build{
|
|||
return health;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get melee stats for build.
|
||||
Returns an array in the order:
|
||||
*/
|
||||
getMeleeStats(){
|
||||
const stats = this.statMap;
|
||||
// Array of neutral + ewtfa damages. Each entry is a pair (min, max).
|
||||
let damages = [];
|
||||
for (const damage_string of stats.get("damageRaw")) {
|
||||
const damage_vals = damage_string.split("-").map(Number);
|
||||
damages.push(damage_vals);
|
||||
}
|
||||
let mdRaw = stats.get("mdRaw");
|
||||
|
||||
let mdPct = stats.get("mdPct");
|
||||
|
||||
let adjAtkSpd = attackSpeeds.indexOf(stats.get("atkSpd")) + stats.get("atkTier");
|
||||
if(adjAtkSpd > 6){
|
||||
adjAtkSpd = 6;
|
||||
}else if(adjAtkSpd < 0){
|
||||
adjAtkSpd = 0;
|
||||
}
|
||||
let poison = stats.get("poison");
|
||||
|
||||
let totalDamNorm = [mdRaw, mdRaw];
|
||||
let totalDamCrit = [mdRaw, mdRaw];
|
||||
let damages_results = [];
|
||||
// 0th skillpoint is strength, 1st is dex.
|
||||
let str = this.total_skillpoints[0];
|
||||
// 0 for melee damage.
|
||||
let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], stats.get("mdRaw"), stats.get("mdPct"), 0, this.weapon, this.damageMultiplier, this.total_skillpoints);
|
||||
let totalDamNorm = results[0];
|
||||
let totalDamCrit = results[1];
|
||||
let damages_results = results[2];
|
||||
|
||||
let dex = this.total_skillpoints[1];
|
||||
let staticBoost = (mdPct / 100.) + skillPointsToPercentage(str);
|
||||
let skillBoost = [0];
|
||||
for (let i in this.total_skillpoints) {
|
||||
skillBoost.push(skillPointsToPercentage(this.total_skillpoints[i]) + stats.get("damageBonus")[i] / 100.);
|
||||
}
|
||||
for (let i in damages) {
|
||||
let damageBoost = 1 + skillBoost[i] + staticBoost;
|
||||
damages_results.push([
|
||||
Math.max(damages[i][0] * damageBoost * this.damage_multiplier, 0), // Normal min
|
||||
Math.max(damages[i][1] * damageBoost * this.damage_multiplier, 0), // Normal max
|
||||
Math.max(damages[i][0] * (1 + damageBoost) * this.damage_multiplier, 0), // Crit min
|
||||
Math.max(damages[i][1] * (1 + damageBoost) * this.damage_multiplier, 0), // Crit max
|
||||
]);
|
||||
totalDamNorm[0] += damages_results[i][0];
|
||||
totalDamNorm[1] += damages_results[i][1];
|
||||
totalDamCrit[0] += damages_results[i][2];
|
||||
totalDamCrit[1] += damages_results[i][3];
|
||||
}
|
||||
for (let i in damages_results[0]) {
|
||||
damages_results[0][i] += mdRaw * this.damage_multiplier;
|
||||
}
|
||||
|
||||
//Now do math
|
||||
let normDPS = (totalDamNorm[0]+totalDamNorm[1])/2 * baseDamageMultiplier[adjAtkSpd];
|
||||
let critDPS = (totalDamCrit[0]+totalDamCrit[1])/2 * baseDamageMultiplier[adjAtkSpd];
|
||||
let avgDPS = (normDPS * (1 - skillPointsToPercentage(dex))) + (critDPS * (skillPointsToPercentage(dex))) + (poison / 3.0 * (1 + skillPointsToPercentage(str)));
|
||||
let avgDPS = (normDPS * (1 - skillPointsToPercentage(dex))) + (critDPS * (skillPointsToPercentage(dex)));
|
||||
//console.log([nDamAdj,eDamAdj,tDamAdj,wDamAdj,fDamAdj,aDamAdj,totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS]);
|
||||
return damages_results.concat([totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS,adjAtkSpd]);
|
||||
}
|
||||
|
||||
/* Get all stats for this build. Stores in this.statMap.
|
||||
@dep test.js.expandItem()
|
||||
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
||||
*/
|
||||
initBuildStats(){
|
||||
|
@ -223,8 +193,7 @@ class Build{
|
|||
}
|
||||
statMap.set("hp", levelToHPBase(this.level)); //TODO: Add player base health
|
||||
|
||||
for (const _item of this.items){
|
||||
let item = expandItem(_item);
|
||||
for (const item of this.items){
|
||||
for (let [id, value] of item.get("maxRolls")) {
|
||||
statMap.set(id,(statMap.get(id) || 0)+value);
|
||||
}
|
||||
|
@ -234,8 +203,8 @@ class Build{
|
|||
}
|
||||
|
||||
// The stuff relevant for damage calculation!!! @ferricles
|
||||
statMap.set("atkSpd", this.weapon["atkSpd"]);
|
||||
statMap.set("damageRaw", [this.weapon["nDam"], this.weapon["eDam"], this.weapon["tDam"], this.weapon["wDam"], this.weapon["fDam"], this.weapon["aDam"]]);
|
||||
statMap.set("atkSpd", this.weapon.get("atkSpd"));
|
||||
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")]);
|
||||
statMap.set("damageBonus", [statMap.get("eDamPct"), statMap.get("tDamPct"), statMap.get("wDamPct"), statMap.get("fDamPct"), statMap.get("aDamPct")]);
|
||||
statMap.set("defRaw", [statMap.get("eDam"), statMap.get("tDef"), statMap.get("wDef"), statMap.get("fDef"), statMap.get("aDef")]);
|
||||
statMap.set("defBonus", [statMap.get("eDamPct"), statMap.get("tDefPct"), statMap.get("wDefPct"), statMap.get("fDefPct"), statMap.get("aDefPct")]);
|
||||
|
|
85
damage_calc.js
Normal file
85
damage_calc.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
// 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.
|
||||
function calculateSpellDamage(stats, spellConversions, rawModifier, pctModifier, spellMultiplier, weapon, damageMultiplier, total_skillpoints) {
|
||||
// Array of neutral + ewtfa damages. Each entry is a pair (min, max).
|
||||
let damages = [];
|
||||
for (const damage_string of stats.get("damageRaw")) {
|
||||
const damage_vals = damage_string.split("-").map(Number);
|
||||
damages.push(damage_vals);
|
||||
}
|
||||
|
||||
// Applying powder.
|
||||
let neutralRemaining = spellConversions[0];
|
||||
let neutralBase = damages[0].slice();
|
||||
let neutralRemainingRaw = damages[0];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
let conversionRatio = spellConversions[i+1]/100;
|
||||
let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]);
|
||||
let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]);
|
||||
damages[i+1][0] = Math.floor(damages[i+1][0] + min_diff);
|
||||
damages[i+1][1] = Math.floor(damages[i+1][1] + max_diff);
|
||||
neutralRemainingRaw[0] = Math.floor(neutralRemainingRaw[0] - min_diff);
|
||||
neutralRemainingRaw[1] = Math.floor(neutralRemainingRaw[1] - max_diff);
|
||||
}
|
||||
let rawBoosts = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]];
|
||||
for (const powderID of weapon.get("powders")) {
|
||||
const powder = powderStats[powderID];
|
||||
// Bitwise to force conversion to integer (integer division).
|
||||
const element = (powderID/6) | 0;
|
||||
let conversionRatio = powder.convert/100;
|
||||
if (neutralRemainingRaw[0] > 0) {
|
||||
let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]);
|
||||
let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]);
|
||||
damages[element+1][0] = Math.floor(damages[element+1][0] + min_diff);
|
||||
damages[element+1][1] = Math.floor(damages[element+1][1] + max_diff);
|
||||
neutralRemainingRaw[0] = Math.floor(neutralRemainingRaw[0] - min_diff);
|
||||
neutralRemainingRaw[1] = Math.floor(neutralRemainingRaw[1] - max_diff);
|
||||
}
|
||||
damages[element+1][0] += powder.min;
|
||||
damages[element+1][1] += powder.max;
|
||||
}
|
||||
damages[0][0] *= neutralRemaining / 100;
|
||||
damages[0][1] *= neutralRemaining / 100;
|
||||
console.log(damages);
|
||||
|
||||
let damageMult = damageMultiplier;
|
||||
// If we are doing melee calculations:
|
||||
if (spellMultiplier == 0) {
|
||||
spellMultiplier = 1;
|
||||
}
|
||||
else {
|
||||
damageMult *= spellMultiplier * baseDamageMultiplier[attackSpeeds.indexOf(stats.get("atkSpd"))];
|
||||
}
|
||||
|
||||
rawModifier *= spellMultiplier;
|
||||
|
||||
let totalDamNorm = [rawModifier, rawModifier];
|
||||
let totalDamCrit = [rawModifier, rawModifier];
|
||||
let damages_results = [];
|
||||
// 0th skillpoint is strength, 1st is dex.
|
||||
let str = total_skillpoints[0];
|
||||
let staticBoost = (pctModifier / 100.) + skillPointsToPercentage(str);
|
||||
let skillBoost = [0];
|
||||
for (let i in total_skillpoints) {
|
||||
skillBoost.push(skillPointsToPercentage(total_skillpoints[i]) + stats.get("damageBonus")[i] / 100.);
|
||||
}
|
||||
|
||||
for (let i in damages) {
|
||||
let damageBoost = 1 + skillBoost[i] + staticBoost;
|
||||
damages_results.push([
|
||||
Math.max(damages[i][0] * damageBoost * damageMult, 0), // Normal min
|
||||
Math.max(damages[i][1] * damageBoost * damageMult, 0), // Normal max
|
||||
Math.max(damages[i][0] * (1 + damageBoost) * damageMult, 0), // Crit min
|
||||
Math.max(damages[i][1] * (1 + damageBoost) * damageMult, 0), // Crit max
|
||||
]);
|
||||
totalDamNorm[0] += damages_results[i][0];
|
||||
totalDamNorm[1] += damages_results[i][1];
|
||||
totalDamCrit[0] += damages_results[i][2];
|
||||
totalDamCrit[1] += damages_results[i][3];
|
||||
}
|
||||
for (let i in damages_results[0]) {
|
||||
// Never account for attack speed.
|
||||
damages_results[0][i] += rawModifier * damageMultiplier;
|
||||
}
|
||||
return [totalDamNorm, totalDamCrit, damages_results];
|
||||
}
|
24
display.js
24
display.js
|
@ -1,7 +1,7 @@
|
|||
let nonRolledIDs = ["name", "displayName", "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","str", "dex", "int", "agi", "def", "fixID", "category", "id"];
|
||||
let nonRolledIDs = ["name", "displayName", "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","str", "dex", "int", "agi", "def", "fixID", "category", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_"];
|
||||
let rolledIDs = ["hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "exploding", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd"];
|
||||
|
||||
function expandItem(item){
|
||||
function expandItem(item, powders){
|
||||
let minRolls = new Map();
|
||||
let maxRolls = new Map();
|
||||
let expandedItem = new Map();
|
||||
|
@ -36,6 +36,7 @@ function expandItem(item){
|
|||
}
|
||||
expandedItem.set("minRolls",minRolls);
|
||||
expandedItem.set("maxRolls",maxRolls);
|
||||
expandedItem.set("powders", powders);
|
||||
return expandedItem;
|
||||
}
|
||||
/*An independent helper function that rounds a rolled ID to the nearest integer OR brings the roll away from 0.
|
||||
|
@ -54,6 +55,19 @@ function displayExpandedItem(item, parent_id){
|
|||
// #commands create a new element.
|
||||
// !elemental is some janky hack for elemental damage.
|
||||
// normals just display a thing.
|
||||
if (item.get("category") === "weapon") {
|
||||
let stats = new Map();
|
||||
stats.set("atkSpd", item.get("atkSpd"));
|
||||
stats.set("damageBonus", [0, 0, 0, 0, 0]);
|
||||
stats.set("damageRaw", [item.get("nDam"), item.get("eDam"), item.get("tDam"), item.get("wDam"), item.get("fDam"), item.get("aDam")]);
|
||||
let results = calculateSpellDamage(stats, [100, 0, 0, 0, 0, 0], 0, 0, 0, item, 1, [0, 0, 0, 0, 0]);
|
||||
let damages = results[2];
|
||||
let damage_keys = [ "nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_" ];
|
||||
for (const i in damage_keys) {
|
||||
item.set(damage_keys[i], damages[i][0]+"-"+damages[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
let display_commands = [
|
||||
"#cdiv",
|
||||
"displayName",
|
||||
|
@ -62,7 +76,7 @@ function displayExpandedItem(item, parent_id){
|
|||
"#ldiv",
|
||||
"!elemental",
|
||||
"hp",
|
||||
"nDam", "eDam", "tDam", "wDam", "fDam", "aDam",
|
||||
"nDam_", "eDam_", "tDam_", "wDam_", "fDam_", "aDam_",
|
||||
"eDef", "tDef", "wDef", "fDef", "aDef",
|
||||
"!elemental",
|
||||
"#ldiv",
|
||||
|
@ -101,8 +115,8 @@ function displayExpandedItem(item, parent_id){
|
|||
"quest",
|
||||
"restrict"];
|
||||
|
||||
let idPrefixes = {"displayName": "", "lvl":"Combat Level Min: ", "classReq":"Class Req: ","strReq":"Strength Min: ","dexReq":"Dexterity Min: ","intReq":"Intelligence Min: ","defReq":"Defense Min: ","agiReq":"Agility Min: ", "nDam":"Neutral Damage: ", "eDam":"Earth Damage: ", "tDam":"Thunder Damage: ", "wDam":"Water Damage: ", "fDam":"Fire Damage: ", "aDam":"Air Damage: ", "atkSpd":"Attack Speed: ", "hp":"Health : ", "eDef":"Earth Defense: ", "tDef":"Thunder Defense: ", "wDef":"Water Defense: ", "fDef":"Fire Defense: ", "aDef":"Air Defense: ", "str":"Strength: ", "dex":"Dexterity: ", "int":"Intelligence: ", "def":"Defense: ","agi":"Agility: ", "hpBonus":"Health Bonus: ", "hprRaw":"Health Regen Raw: ", "hprPct":"Health Regen %: ", "sdRaw":"Raw Spell Damage: ", "sdPct":"Spell Damage %: ", "mdRaw":"Main Attack Neutral Damage: ", "mdPct":"Main Attack Damage %: ", "mr":"Mana Regen: ", "ms":"Mana Steal: ", "ref":"Reflection: ", "ls":"Life Steal: ", "poison":"Poison: ", "thorns":"Thorns: ", "exploding":"Expoding: ", "spd":"Walk Speed Bonus: ", "atkTier":"Attack Speed Bonus: ", "eDamPct":"Earth Damage %: ", "tDamPct":"Thunder Damage %: ", "wDamPct":"Water Damage %: ", "fDamPct":"Fire Damage %: ", "aDamPct":"Air Damage %: ", "eDefPct":"Earth Defense %: ", "tDefPct":"Thunder Defense %: ", "wDefPct":"Water Defense %: ", "fDefPct":"Fire Defense %: ", "aDefPct":"Air Defense %: ", "spPct1":"1st Spell Cost %: ", "spRaw1":"1st Spell Cost Raw: ", "spPct2":"2nd Spell Cost %: ", "spRaw2":"2nd Spell Cost Raw: ", "spPct3":"3rd Spell Cost %: ", "spRaw3":"3rd Spell Cost Raw: ", "spPct4":"4th Spell Cost %: ", "spRaw4":"4th Spell Cost Raw: ", "rainbowRaw":"Rainbow Spell Damage Raw: ", "sprint":"Sprint Bonus: ", "sprintReg":"Sprint Regen Bonus: ", "jh":"Jump Height: ", "xpb":"Combat XP Bonus: ", "lb":"Loot Bonus: ", "lq":"Loot Quality: ", "spRegen":"Soul Point Regen: ", "eSteal":"Stealing: ", "gXp":"Gathering XP Bonus: ", "gSpd":"Gathering Speed Bonus: ", "slots":"Powder Slots: ", "set":"Set: ", "quest":"Quest Req: ", "restrict":""};
|
||||
let idSuffixes = {"displayName": "", "lvl":"", "classReq":"","strReq":"","dexReq":"","intReq":"","defReq":"","agiReq":"", "nDam":"", "eDam":"", "tDam":"", "wDam":"", "fDam":"", "aDam":"", "atkSpd":"", "hp":"", "eDef":"", "tDef":"", "wDef":"", "fDef":"", "aDef":"", "str":"", "dex":"", "int":"", "def":"","agi":"", "hpBonus":"", "hprRaw":"", "hprPct":"%", "sdRaw":"", "sdPct":"%", "mdRaw":"", "mdPct":"%", "mr":"/4s", "ms":"/4s", "ref":"%", "ls":"/4s", "poison":"/3s", "thorns":"%", "exploding":"%", "spd":"%", "atkTier":" tier", "eDamPct":"%", "tDamPct":"%", "wDamPct":"%", "fDamPct":"%", "aDamPct":"%", "eDefPct":"%", "tDefPct":"%", "wDefPct":"%", "fDefPct":"%", "aDefPct":"%", "spPct1":"%", "spRaw1":"", "spPct2":"%", "spRaw2":"", "spPct3":"%", "spRaw3":"", "spPct4":"%", "spRaw4":"", "rainbowRaw":"", "sprint":"%", "sprintReg":"%", "jh":"", "xpb":"%", "lb":"%", "lq":"%", "spRegen":"%", "eSteal":"%", "gXp":"%", "gSpd":"%", "slots":"", "set":" set.", "quest":"", "restrict":""};
|
||||
let idPrefixes = {"displayName": "", "lvl":"Combat Level Min: ", "classReq":"Class Req: ","strReq":"Strength Min: ","dexReq":"Dexterity Min: ","intReq":"Intelligence Min: ","defReq":"Defense Min: ","agiReq":"Agility Min: ", "nDam_":"Neutral Damage: ", "eDam_":"Earth Damage: ", "tDam_":"Thunder Damage: ", "wDam_":"Water Damage: ", "fDam_":"Fire Damage: ", "aDam_":"Air Damage: ", "atkSpd":"Attack Speed: ", "hp":"Health : ", "eDef":"Earth Defense: ", "tDef":"Thunder Defense: ", "wDef":"Water Defense: ", "fDef":"Fire Defense: ", "aDef":"Air Defense: ", "str":"Strength: ", "dex":"Dexterity: ", "int":"Intelligence: ", "def":"Defense: ","agi":"Agility: ", "hpBonus":"Health Bonus: ", "hprRaw":"Health Regen Raw: ", "hprPct":"Health Regen %: ", "sdRaw":"Raw Spell Damage: ", "sdPct":"Spell Damage %: ", "mdRaw":"Main Attack Neutral Damage: ", "mdPct":"Main Attack Damage %: ", "mr":"Mana Regen: ", "ms":"Mana Steal: ", "ref":"Reflection: ", "ls":"Life Steal: ", "poison":"Poison: ", "thorns":"Thorns: ", "exploding":"Expoding: ", "spd":"Walk Speed Bonus: ", "atkTier":"Attack Speed Bonus: ", "eDamPct":"Earth Damage %: ", "tDamPct":"Thunder Damage %: ", "wDamPct":"Water Damage %: ", "fDamPct":"Fire Damage %: ", "aDamPct":"Air Damage %: ", "eDefPct":"Earth Defense %: ", "tDefPct":"Thunder Defense %: ", "wDefPct":"Water Defense %: ", "fDefPct":"Fire Defense %: ", "aDefPct":"Air Defense %: ", "spPct1":"1st Spell Cost %: ", "spRaw1":"1st Spell Cost Raw: ", "spPct2":"2nd Spell Cost %: ", "spRaw2":"2nd Spell Cost Raw: ", "spPct3":"3rd Spell Cost %: ", "spRaw3":"3rd Spell Cost Raw: ", "spPct4":"4th Spell Cost %: ", "spRaw4":"4th Spell Cost Raw: ", "rainbowRaw":"Rainbow Spell Damage Raw: ", "sprint":"Sprint Bonus: ", "sprintReg":"Sprint Regen Bonus: ", "jh":"Jump Height: ", "xpb":"Combat XP Bonus: ", "lb":"Loot Bonus: ", "lq":"Loot Quality: ", "spRegen":"Soul Point Regen: ", "eSteal":"Stealing: ", "gXp":"Gathering XP Bonus: ", "gSpd":"Gathering Speed Bonus: ", "slots":"Powder Slots: ", "set":"Set: ", "quest":"Quest Req: ", "restrict":""};
|
||||
let idSuffixes = {"displayName": "", "lvl":"", "classReq":"","strReq":"","dexReq":"","intReq":"","defReq":"","agiReq":"", "nDam_":"", "eDam_":"", "tDam_":"", "wDam_":"", "fDam_":"", "aDam_":"", "atkSpd":"", "hp":"", "eDef":"", "tDef":"", "wDef":"", "fDef":"", "aDef":"", "str":"", "dex":"", "int":"", "def":"","agi":"", "hpBonus":"", "hprRaw":"", "hprPct":"%", "sdRaw":"", "sdPct":"%", "mdRaw":"", "mdPct":"%", "mr":"/4s", "ms":"/4s", "ref":"%", "ls":"/4s", "poison":"/3s", "thorns":"%", "exploding":"%", "spd":"%", "atkTier":" tier", "eDamPct":"%", "tDamPct":"%", "wDamPct":"%", "fDamPct":"%", "aDamPct":"%", "eDefPct":"%", "tDefPct":"%", "wDefPct":"%", "fDefPct":"%", "aDefPct":"%", "spPct1":"%", "spRaw1":"", "spPct2":"%", "spRaw2":"", "spPct3":"%", "spRaw3":"", "spPct4":"%", "spRaw4":"", "rainbowRaw":"", "sprint":"%", "sprintReg":"%", "jh":"", "xpb":"%", "lb":"%", "lq":"%", "spRegen":"%", "eSteal":"%", "gXp":"%", "gSpd":"%", "slots":"", "set":" set.", "quest":"", "restrict":""};
|
||||
|
||||
function apply_elemental_format(p_elem, id, suffix) {
|
||||
suffix = (typeof suffix !== 'undefined') ? suffix : "";
|
||||
|
|
38
index.html
38
index.html
|
@ -14,8 +14,11 @@
|
|||
<div class="header" id="header">
|
||||
Wynn build calculator
|
||||
</div>
|
||||
<div class="center" id="header">
|
||||
<a href="credits.txt">Credits</a>
|
||||
<div class="center" id="header2">
|
||||
Made by: hppeng and ferricles
|
||||
</div>
|
||||
<div class="center" id="credits">
|
||||
<a href="credits.txt">Additional credits</a>
|
||||
</div>
|
||||
<div class="equipment">
|
||||
<div class="center" style="grid-column:1;grid-row:1">
|
||||
|
@ -133,13 +136,13 @@
|
|||
</div>
|
||||
<div class="skillpoints">
|
||||
<div class="center" style="grid-column:1;grid-row:1">
|
||||
<div id="str-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div>
|
||||
<label for="str-skp" class="skpLabel">Strength:</label>
|
||||
<input type="number" id="str-skp" name="str-skp" value="0" class="skpInput"/>
|
||||
</div>
|
||||
<div id="str-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div id="str-skp-base">
|
||||
Original Value: 0
|
||||
</div>
|
||||
|
@ -147,13 +150,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="center" style="grid-column:2;grid-row:1">
|
||||
<div id="dex-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div>
|
||||
<label for="dex-skp" class="skpLabel">Dexterity:</label>
|
||||
<input type="number" id="dex-skp" name="dex-skp" value="0" class="skpInput"/>
|
||||
</div>
|
||||
<div id="dex-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div id="dex-skp-base">
|
||||
Original Value: 0
|
||||
</div>
|
||||
|
@ -161,13 +164,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="center" style="grid-column:3;grid-row:1">
|
||||
<div id="int-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div>
|
||||
<label for="int-skp" class="skpLabel">Intelligence:</label>
|
||||
<input type="number" id="int-skp" name="int-skp" value="0" class="skpInput"/>
|
||||
</div>
|
||||
<div id="int-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div id="int-skp-base">
|
||||
Original Value: 0
|
||||
</div>
|
||||
|
@ -175,13 +178,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="center" style="grid-column:4;grid-row:1">
|
||||
<div id="def-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div>
|
||||
<label for="def-skp" class="skpLabel">Defense:</label>
|
||||
<input type="number" id="def-skp" name="def-skp" value="0" class="skpInput"/>
|
||||
</div>
|
||||
<div id="def-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div id="def-skp-base">
|
||||
Original Value: 0
|
||||
</div>
|
||||
|
@ -189,13 +192,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="center" style="grid-column:5;grid-row:1">
|
||||
<div id="agi-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div>
|
||||
<label for="agi-skp" class="skpLabel">Agility:</label>
|
||||
<input type="number" id="agi-skp" name="agi-skp" value="0" class="skpInput"/>
|
||||
</div>
|
||||
<div id="agi-skp-assign">
|
||||
Before Boosts: 0
|
||||
</div>
|
||||
<div id="agi-skp-base">
|
||||
Original Value: 0
|
||||
</div>
|
||||
|
@ -241,6 +244,7 @@
|
|||
|
||||
<script type="text/javascript" src="utils.js"></script>
|
||||
<script type="text/javascript" src="skillpoints.js"></script>
|
||||
<script type="text/javascript" src="damage_calc.js"></script>
|
||||
<script type="text/javascript" src="display.js"></script>
|
||||
<script type="text/javascript" src="build.js"></script>
|
||||
<script type="text/javascript" src="load.js"></script>
|
||||
|
|
|
@ -7,10 +7,10 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
let noboost = [];
|
||||
console.log(equipment);
|
||||
for (const item of equipment) {
|
||||
if (item.reqs.every(x => x === 0)) {
|
||||
if (item.get("reqs").every(x => x === 0)) {
|
||||
fixed.push(item);
|
||||
}
|
||||
else if (item.skillpoints.every(x => x === 0)) {
|
||||
else if (item.get("skillpoints").every(x => x === 0)) {
|
||||
noboost.push(item);
|
||||
}
|
||||
else {
|
||||
|
@ -19,13 +19,13 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
}
|
||||
function apply_skillpoints(skillpoints, item) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
skillpoints[i] += item.skillpoints[i];
|
||||
skillpoints[i] += item.get("skillpoints")[i];
|
||||
}
|
||||
}
|
||||
|
||||
function remove_skillpoints(skillpoints, item) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
skillpoints[i] -= item.skillpoints[i];
|
||||
skillpoints[i] -= item.get("skillpoints")[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,13 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
let applied = [0, 0, 0, 0, 0];
|
||||
let total = 0;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (item.skillpoints[i] < 0 && skillpoint_filter[i]) {
|
||||
applied[i] -= item.skillpoints[i];
|
||||
total -= item.skillpoints[i];
|
||||
if (item.get("skillpoints")[i] < 0 && skillpoint_filter[i]) {
|
||||
applied[i] -= item.get("skillpoints")[i];
|
||||
total -= item.get("skillpoints")[i];
|
||||
}
|
||||
if (item.reqs[i] == 0) continue;
|
||||
if (item.get("reqs")[i] == 0) continue;
|
||||
if (skillpoint_filter) skillpoint_filter[i] = true;
|
||||
const req = item.reqs[i];
|
||||
const req = item.get("reqs")[i];
|
||||
const cur = skillpoints[i];
|
||||
if (req > cur) {
|
||||
const diff = req - cur;
|
||||
|
|
62
test.js
62
test.js
|
@ -11,7 +11,7 @@ console.log(url_tag);
|
|||
* END testing section
|
||||
*/
|
||||
|
||||
const BUILD_VERSION = "1.3";
|
||||
const BUILD_VERSION = "1.4";
|
||||
|
||||
document.getElementById("header").textContent = "Wynn build calculator "+BUILD_VERSION+" (db version "+DB_VERSION+")";
|
||||
|
||||
|
@ -43,12 +43,23 @@ let powderInputs = [
|
|||
"weapon-powder",
|
||||
];
|
||||
// Ordering: [dmgMin, dmgMax, convert, defPlus, defMinus (+6 mod 5)]
|
||||
class Powder {
|
||||
constructor(min, max, convert, defPlus, defMinus) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.convert = convert;
|
||||
this.defPlus = defPlus;
|
||||
this.defMinus = defMinus;
|
||||
}
|
||||
}
|
||||
function _p(a,b,c,d,e) { return new Powder(a,b,c,d,e); }
|
||||
|
||||
let powderStats = [
|
||||
[3,6,17,2,1], [6,9,21,4,2], [8,14,25,8,3], [11,16,31,14,5], [15,18,38,22,9], [18,22,46,30,13],
|
||||
[1,8,9,3,1], [1,13,11,5,1], [2,18,14,9,2], [3,24,17,14,4], [3,32,22,20,7], [5,40,28,28,10],
|
||||
[3,4,13,3,1], [4,7,15,6,1], [6,10,17,11,2], [8,12,21,18,4], [11,14,26,28,7], [13,17,32,40,10],
|
||||
[2,5,14,3,1], [4,8,16,5,2], [6,10,19,9,3], [9,13,24,16,5], [12,16,30,25,9], [15,19,37,36,13],
|
||||
[2,6,11,3,1], [4,9,14,6,2], [7,10,17,10,3], [9,13,22,16,5], [13,18,28,24,9], [16,18,35,34,13]
|
||||
_p(3,6,17,2,1), _p(6,9,21,4,2), _p(8,14,25,8,3), _p(11,16,31,14,5), _p(15,18,38,22,9), _p(18,22,46,30,13),
|
||||
_p(1,8,9,3,1), _p(1,13,11,5,1), _p(2,18,14,9,2), _p(3,24,17,14,4), _p(3,32,22,20,7), _p(5,40,28,28,10),
|
||||
_p(3,4,13,3,1), _p(4,7,15,6,1), _p(6,10,17,11,2), _p(8,12,21,18,4), _p(11,14,26,28,7), _p(13,17,32,40,10),
|
||||
_p(2,5,14,3,1), _p(4,8,16,5,2), _p(6,10,19,9,3), _p(9,13,24,16,5), _p(12,16,30,25,9), _p(15,19,37,36,13),
|
||||
_p(2,6,11,3,1), _p(4,9,14,6,2), _p(7,10,17,10,3), _p(9,13,22,16,5), _p(13,18,28,24,9), _p(16,18,35,34,13)
|
||||
];
|
||||
|
||||
let itemTypes = armorTypes.concat(accessoryTypes).concat(weaponTypes);
|
||||
|
@ -262,15 +273,15 @@ function encodeBuild() {
|
|||
// Base64.fromIntN(player_build.bracelet.id, 3) +
|
||||
// Base64.fromIntN(player_build.necklace.id, 3) +
|
||||
// Base64.fromIntN(player_build.weapon.id, 3);
|
||||
let build_string = "1_" + Base64.fromIntN(player_build.helmet.id, 3) +
|
||||
Base64.fromIntN(player_build.chestplate.id, 3) +
|
||||
Base64.fromIntN(player_build.leggings.id, 3) +
|
||||
Base64.fromIntN(player_build.boots.id, 3) +
|
||||
Base64.fromIntN(player_build.ring1.id, 3) +
|
||||
Base64.fromIntN(player_build.ring2.id, 3) +
|
||||
Base64.fromIntN(player_build.bracelet.id, 3) +
|
||||
Base64.fromIntN(player_build.necklace.id, 3) +
|
||||
Base64.fromIntN(player_build.weapon.id, 3);
|
||||
let build_string = "1_" + Base64.fromIntN(player_build.helmet.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.chestplate.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.leggings.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.boots.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.ring1.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.ring2.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.bracelet.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.necklace.get("id"), 3) +
|
||||
Base64.fromIntN(player_build.weapon.get("id"), 3);
|
||||
|
||||
for (const _powderset of player_build.powders) {
|
||||
let n_bits = Math.ceil(_powderset.length / 6);
|
||||
|
@ -363,7 +374,7 @@ function calculateBuild(){
|
|||
|
||||
let equip_order_text = "Equip order: <br>";
|
||||
for (const item of player_build.equip_order) {
|
||||
equip_order_text += item.displayName + "<br>";
|
||||
equip_order_text += item.get("displayName") + "<br>";
|
||||
}
|
||||
setHTML("build-order", equip_order_text);
|
||||
|
||||
|
@ -382,22 +393,21 @@ function calculateBuild(){
|
|||
}
|
||||
setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100).toFixed(1).concat(skp_effects[i]));
|
||||
}
|
||||
console.log(skillpoints);
|
||||
if(player_build.assigned_skillpoints > levelToSkillPoints(player_build.level)){
|
||||
setHTML("summary-box", "Summary: Assigned "+player_build.assigned_skillpoints+" skillpoints.<br>" + "WARNING: Too many skillpoints need to be assigned!<br> For level " + player_build.level + ", there are only " + levelToSkillPoints(player_build.level) + " skill points available.");
|
||||
}else{
|
||||
setText("summary-box", "Summary: Assigned "+player_build.assigned_skillpoints+" skillpoints.");
|
||||
}
|
||||
|
||||
displayExpandedItem(expandItem(player_build.helmet), "build-helmet");
|
||||
displayExpandedItem(expandItem(player_build.chestplate), "build-chestplate");
|
||||
displayExpandedItem(expandItem(player_build.leggings), "build-leggings");
|
||||
displayExpandedItem(expandItem(player_build.boots), "build-boots");
|
||||
displayExpandedItem(expandItem(player_build.ring1), "build-ring1");
|
||||
displayExpandedItem(expandItem(player_build.ring2), "build-ring2");
|
||||
displayExpandedItem(expandItem(player_build.bracelet), "build-bracelet");
|
||||
displayExpandedItem(expandItem(player_build.necklace), "build-necklace");
|
||||
displayExpandedItem(expandItem(player_build.weapon), "build-weapon");
|
||||
displayExpandedItem(player_build.helmet, "build-helmet");
|
||||
displayExpandedItem(player_build.chestplate, "build-chestplate");
|
||||
displayExpandedItem(player_build.leggings, "build-leggings");
|
||||
displayExpandedItem(player_build.boots, "build-boots");
|
||||
displayExpandedItem(player_build.ring1, "build-ring1");
|
||||
displayExpandedItem(player_build.ring2, "build-ring2");
|
||||
displayExpandedItem(player_build.bracelet, "build-bracelet");
|
||||
displayExpandedItem(player_build.necklace, "build-necklace");
|
||||
displayExpandedItem(player_build.weapon, "build-weapon");
|
||||
|
||||
calculateBuildStats();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue