Add files via upload
This commit is contained in:
parent
ad61401ee5
commit
96f4c69c8d
15 changed files with 21157 additions and 292 deletions
10206
1_20_ci.json
Normal file
10206
1_20_ci.json
Normal file
File diff suppressed because it is too large
Load diff
70
build.js
70
build.js
|
@ -1,3 +1,8 @@
|
|||
|
||||
const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ];
|
||||
const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];
|
||||
const classDefenseMultipliers = new Map([ ["relik",0.60], ["bow",0.60], ["wand", 0.80], ["assassin", 1.0], ["spear",1.20] ]);
|
||||
|
||||
/*Turns the input amount of skill points into a float precision percentage.
|
||||
* @param skp - the integer skillpoint count to be converted
|
||||
*/
|
||||
|
@ -39,10 +44,6 @@ function levelToHPBase(level){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ];
|
||||
const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];
|
||||
|
||||
/*Class that represents a wynn player's build.
|
||||
*/
|
||||
class Build{
|
||||
|
@ -133,6 +134,7 @@ class Build{
|
|||
this.base_skillpoints = result[1];
|
||||
this.total_skillpoints = result[2];
|
||||
this.assigned_skillpoints = result[3];
|
||||
this.activeSetCounts = result[4];
|
||||
|
||||
// For strength boosts like warscream, vanish, etc.
|
||||
this.damageMultiplier = 1.0;
|
||||
|
@ -150,14 +152,6 @@ class Build{
|
|||
|
||||
/* Get total health for build.
|
||||
*/
|
||||
getHealth(){
|
||||
let health = this.statMap.get("hp") + this.statMap.get("hpBonus");
|
||||
if(health<5){
|
||||
return 5;
|
||||
}else{
|
||||
return health;
|
||||
}
|
||||
}
|
||||
|
||||
getSpellCost(spellIdx, cost) {
|
||||
cost = Math.ceil(cost * (1 - skillPointsToPercentage(this.total_skillpoints[2])));
|
||||
|
@ -197,6 +191,43 @@ class Build{
|
|||
return damages_results.concat([totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS,adjAtkSpd]);
|
||||
}
|
||||
|
||||
/*
|
||||
Get all defensive stats for this build.
|
||||
*/
|
||||
getDefenseStats(){
|
||||
const stats = this.statMap;
|
||||
let defenseStats = [];
|
||||
let def_pct = skillPointsToPercentage(this.total_skillpoints[3]);
|
||||
let agi_pct = skillPointsToPercentage(this.total_skillpoints[4]);
|
||||
//total hp
|
||||
let totalHp = stats.get("hp") + stats.get("hpBonus");
|
||||
if (totalHp < 5) totalHp = 5;
|
||||
defenseStats.push(totalHp);
|
||||
//EHP
|
||||
let ehp = totalHp;
|
||||
let defMult = classDefenseMultipliers.get(this.weapon.get("type"));
|
||||
ehp /= ((1-def_pct)*(1-agi_pct)*(2-defMult));
|
||||
defenseStats.push(ehp);
|
||||
//HPR
|
||||
let totalHpr = rawToPct(stats.get("hprRaw"), stats.get("hprPct")/100.);
|
||||
defenseStats.push(totalHpr);
|
||||
//EHPR
|
||||
let ehpr = totalHpr;
|
||||
ehp /= ((1-def_pct)*(1-agi_pct)*(2-defMult));
|
||||
defenseStats.push(ehpr);
|
||||
//skp stats
|
||||
defenseStats.push([def_pct*100, agi_pct*100]);
|
||||
//eledefs - TODO POWDERS
|
||||
let eledefs = [0, 0, 0, 0, 0];
|
||||
for(const i in skp_elements){ //kinda jank but ok
|
||||
eledefs[i] = rawToPct(stats.get(skp_elements[i] + "Def"), stats.get(skp_elements[i] + "DefPct")/100.);
|
||||
}
|
||||
defenseStats.push(eledefs);
|
||||
|
||||
//[total hp, ehp, total hpr, ehpr, [def%, agi%], [edef,tdef,wdef,fdef,adef]]
|
||||
return defenseStats;
|
||||
}
|
||||
|
||||
/* Get all stats for this build. Stores in this.statMap.
|
||||
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
||||
*/
|
||||
|
@ -218,7 +249,20 @@ class Build{
|
|||
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.get(staticID)) {
|
||||
statMap.set(staticID, statMap.get(staticID) + item.get(staticID));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const [setName, count] of this.activeSetCounts) {
|
||||
const bonus = sets[setName].bonuses[count-1];
|
||||
for (const id in bonus) {
|
||||
if (skp_order.includes(id)) {
|
||||
// pass. Don't include skillpoints in ids
|
||||
}
|
||||
else {
|
||||
statMap.set(id,(statMap.get(id) || 0)+bonus[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
10204
clean.json
10204
clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -149,6 +149,10 @@ for item in items:
|
|||
if item["name"] in item_set_map:
|
||||
item["set"] = item_set_map[item["name"]]
|
||||
|
||||
with open("1_20_ci.json", "r") as ci_file:
|
||||
ci_items = json.load(ci_file)
|
||||
items.extend(ci_items)
|
||||
|
||||
with open("id_map.json","w") as id_mapfile:
|
||||
json.dump(id_map, id_mapfile, indent=2)
|
||||
with open("clean.json", "w") as outfile:
|
||||
|
|
|
@ -3,3 +3,5 @@ Damage calculator checking: https://its0x7.cf/build/
|
|||
Theme and overall inspiration: Wynndata (Dukio)
|
||||
- https://wynndata.tk
|
||||
|
||||
Additional Contributors:
|
||||
- QuantumNep (Layout code/layout ideas)
|
||||
|
|
|
@ -99,7 +99,7 @@ const spell_table = {
|
|||
] },
|
||||
{ title: "Meteor", cost: 8, parts: [
|
||||
{ subtitle: "Blast Damage", type: "damage", multiplier: 500, conversion: [40, 30, 0, 0, 30, 0] },
|
||||
{ subtitle: "Burn Damage", type: "damage", multiplier: 125, conversion: [40, 30, 0, 0, 30, 0] },
|
||||
{ subtitle: "Burn Damage", type: "damage", multiplier: 125, conversion: [100, 0, 0, 0, 0, 0] },
|
||||
] },
|
||||
{ title: "Ice Snake", cost: 4, parts: [
|
||||
{ subtitle: "", type: "damage", multiplier: 70, conversion: [50, 0, 0, 50, 0, 0] },
|
||||
|
|
293
display.js
293
display.js
|
@ -1,6 +1,6 @@
|
|||
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", "expd", "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"];
|
||||
|
||||
let damageClasses = ["Neutral","Earth","Thunder","Water","Fire","Air"];
|
||||
let reversedIDs = [ "atkTier", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ];
|
||||
|
||||
function expandItem(item, powders){
|
||||
|
@ -10,24 +10,26 @@ function expandItem(item, powders){
|
|||
if(item.fixID){ //The item has fixed IDs.
|
||||
expandedItem.set("fixID",true);
|
||||
for (const id of rolledIDs){ //all rolled IDs are numerical
|
||||
let val = (item[id] || 0);
|
||||
//if(item[id]) {
|
||||
minRolls.set(id,item[id]);
|
||||
maxRolls.set(id,item[id]);
|
||||
minRolls.set(id,val);
|
||||
maxRolls.set(id,val);
|
||||
//}
|
||||
}
|
||||
}else{ //The item does not have fixed IDs.
|
||||
for (const id of rolledIDs){
|
||||
if(item[id] > 0){ // positive rolled IDs
|
||||
minRolls.set(id,idRound(item[id]*0.3));
|
||||
maxRolls.set(id,idRound(item[id]*1.3));
|
||||
}else if(item[id] < 0){ //negative rolled IDs
|
||||
let val = (item[id] || 0);
|
||||
if(val > 0){ // positive rolled IDs
|
||||
minRolls.set(id,idRound(val*0.3));
|
||||
maxRolls.set(id,idRound(val*1.3));
|
||||
}else if(val < 0){ //negative rolled IDs
|
||||
if (reversedIDs.includes(id)) {
|
||||
maxRolls.set(id,idRound(item[id]*1.3));
|
||||
minRolls.set(id,idRound(item[id]*0.7));
|
||||
maxRolls.set(id,idRound(val*1.3));
|
||||
minRolls.set(id,idRound(val*0.7));
|
||||
}
|
||||
else {
|
||||
minRolls.set(id,idRound(item[id]*1.3));
|
||||
maxRolls.set(id,idRound(item[id]*0.7));
|
||||
minRolls.set(id,idRound(val*1.3));
|
||||
maxRolls.set(id,idRound(val*0.7));
|
||||
}
|
||||
}else{//Id = 0
|
||||
minRolls.set(id,0);
|
||||
|
@ -76,6 +78,38 @@ function apply_elemental_format(p_elem, id, suffix) {
|
|||
p_elem.appendChild(i_elem2);
|
||||
}
|
||||
|
||||
function displaySetBonuses(build, parent_id) {
|
||||
setHTML(parent_id, "");
|
||||
let parent_div = document.getElementById(parent_id);
|
||||
|
||||
let set_summary_elem = document.createElement('p');
|
||||
set_summary_elem.classList.add('itemcenter');
|
||||
set_summary_elem.textContent = "Set Bonuses:";
|
||||
parent_div.append(set_summary_elem);
|
||||
|
||||
for (const [setName, count] of build.activeSetCounts) {
|
||||
let set_elem = document.createElement('p');
|
||||
set_elem.id = "set-"+setName;
|
||||
set_summary_elem.append(set_elem);
|
||||
|
||||
const bonus = sets[setName].bonuses[count-1];
|
||||
let mock_item = new Map();
|
||||
mock_item.set("fixID", true);
|
||||
mock_item.set("displayName", setName+" Set: "+count+"/"+sets[setName].items.length);
|
||||
let mock_minRolls = new Map();
|
||||
mock_item.set("minRolls", mock_minRolls);
|
||||
for (const id in bonus) {
|
||||
if (rolledIDs.includes(id)) {
|
||||
mock_minRolls.set(id, bonus[id]);
|
||||
}
|
||||
else {
|
||||
mock_item.set(id, bonus[id]);
|
||||
}
|
||||
}
|
||||
displayExpandedItem(mock_item, set_elem.id);
|
||||
}
|
||||
}
|
||||
|
||||
function displayBuildStats(build, parent_id){
|
||||
// Commands to "script" the creation of nice formatting.
|
||||
// #commands create a new element.
|
||||
|
@ -119,7 +153,21 @@ function displayBuildStats(build, parent_id){
|
|||
setHTML(parent_id, "");
|
||||
let parent_div = document.getElementById(parent_id);
|
||||
|
||||
let set_summary_elem = document.createElement('p');
|
||||
set_summary_elem.classList.add('itemp');
|
||||
set_summary_elem.classList.add('left');
|
||||
set_summary_elem.textContent = "Set Summary:";
|
||||
parent_div.append(set_summary_elem);
|
||||
for (const [setName, count] of build.activeSetCounts) {
|
||||
let set_elem = document.createElement('p');
|
||||
set_elem.classList.add('itemp');
|
||||
set_elem.classList.add('left');
|
||||
set_elem.textContent = " "+setName+" Set: "+count+"/"+sets[setName].items.length;
|
||||
set_summary_elem.append(set_elem);
|
||||
}
|
||||
|
||||
let stats = build.statMap;
|
||||
console.log(build.statMap);
|
||||
|
||||
let active_elem;
|
||||
let elemental_format = false;
|
||||
|
@ -265,11 +313,18 @@ function displayExpandedItem(item, parent_id){
|
|||
let p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
|
||||
if (id === "slots") {
|
||||
// HACK TO MAKE POWDERS DISPLAY NICE!! TODO
|
||||
//let powderMap = new Map([ ["e", "Earth"], ["t", "Thunder"], ["w", "Water"], ["f", "Fire"], ["a", "Air"]]);
|
||||
p_elem.textContent = idPrefixes[id].concat(item.get(id), idSuffixes[id]) +
|
||||
" [ " + item.get("powders").map(x => powderNames.get(x)) + " ]";
|
||||
}else if(id === "displayName"){
|
||||
p_elem.classList.add("title");
|
||||
if(item.get("tier") !== " "){
|
||||
p_elem.classList.add(item.get("tier"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if(rolledIDs.includes(id)&& item.get("minRolls").get(id)){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID
|
||||
else if (rolledIDs.includes(id) && item.get("minRolls").get(id)){ // && item.get("maxRolls").get(id) ){//rolled ID & non-0/non-null/non-und ID
|
||||
let style = "positive";
|
||||
if (item.get("minRolls").get(id) < 0) {
|
||||
style = "negative";
|
||||
|
@ -306,11 +361,14 @@ function displayExpandedItem(item, parent_id){
|
|||
}//Just don't do anything if else
|
||||
}
|
||||
}
|
||||
let item_desc_elem = document.createElement('p');
|
||||
item_desc_elem.classList.add('itemp');
|
||||
item_desc_elem.classList.add('left');
|
||||
item_desc_elem.textContent = item.get("tier")+" "+item.get("type");
|
||||
parent_div.append(item_desc_elem);
|
||||
if (item.get("tier") & item.get("tier") !== " ") {
|
||||
let item_desc_elem = document.createElement('p');
|
||||
item_desc_elem.classList.add('itemp');
|
||||
item_desc_elem.classList.add('left');
|
||||
item_desc_elem.classList.add(item.get("tier"));
|
||||
item_desc_elem.textContent = item.get("tier")+" "+item.get("type");
|
||||
parent_div.append(item_desc_elem);
|
||||
}
|
||||
}
|
||||
|
||||
function displayFixedID(active, id, value, elemental_format, style) {
|
||||
|
@ -351,10 +409,26 @@ function displayFixedID(active, id, value, elemental_format, style) {
|
|||
return p_elem;
|
||||
}
|
||||
}
|
||||
function displayMeleeDamage(parent_elem, meleeStats){
|
||||
let attackSpeeds = ["Super Slow", "Very Slow", "Slow", "Normal", "Fast", "Very Fast", "Super Fast"];
|
||||
let damagePrefixes = ["Neutral Damage: ","Earth Damage: ","Thunder Damage: ","Water Damage: ","Fire Damage: ","Air Damage: "];
|
||||
function displayEquipOrder(parent_elem,buildOrder){
|
||||
parent_elem.textContent = "";
|
||||
const order = buildOrder.slice();
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.textContent = "Equip order ";
|
||||
title_elem.classList.add("title");
|
||||
parent_elem.append(title_elem);
|
||||
for (const item of order) {
|
||||
let p_elem = document.createElement("p");
|
||||
p_elem.classList.add("itemp");
|
||||
p_elem.classList.add("left");
|
||||
p_elem.textContent = item.get("displayName");
|
||||
parent_elem.append(p_elem);
|
||||
}
|
||||
}
|
||||
function displayMeleeDamage(parent_elem, overallparent_elem, meleeStats){
|
||||
let attackSpeeds = ["Super Slow", "Very Slow", "Slow", "Normal", "Fast", "Very Fast", "Super Fast"];
|
||||
//let damagePrefixes = ["Neutral Damage: ","Earth Damage: ","Thunder Damage: ","Water Damage: ","Fire Damage: ","Air Damage: "];
|
||||
parent_elem.textContent = "";
|
||||
overallparent_elem.textContent = "";
|
||||
const stats = meleeStats.slice();
|
||||
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
|
@ -373,44 +447,73 @@ function displayMeleeDamage(parent_elem, meleeStats){
|
|||
|
||||
//title
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.classList.add("center");
|
||||
title_elem.classList.add("title");
|
||||
title_elem.textContent = "Melee Stats";
|
||||
parent_elem.append(title_elem);
|
||||
parent_elem.append(document.createElement("br"));
|
||||
|
||||
|
||||
//overall title
|
||||
let title_elemavg = document.createElement("p");
|
||||
title_elemavg.classList.add("title");
|
||||
title_elemavg.textContent = "Melee Stats";
|
||||
overallparent_elem.append(title_elemavg);
|
||||
|
||||
//average DPS
|
||||
let averageDamage = document.createElement("p");
|
||||
|
||||
averageDamage.classList.add("center");
|
||||
averageDamage.classList.add("itemp");
|
||||
averageDamage.textContent = "Average DPS: " + stats[10];
|
||||
parent_elem.append(averageDamage);
|
||||
|
||||
//overall average DPS
|
||||
let overallaverageDamage = document.createElement("p");
|
||||
overallaverageDamage.classList.add("itemp");
|
||||
overallaverageDamage.textContent = "Average DPS: " + stats[10];
|
||||
overallparent_elem.append(overallaverageDamage);
|
||||
overallparent_elem.append(document.createElement("br"));
|
||||
|
||||
//attack speed
|
||||
let atkSpd = document.createElement("p");
|
||||
atkSpd.classList.add("center");
|
||||
atkSpd.classList.add("itemp");
|
||||
atkSpd.textContent = "Attack Speed: " + attackSpeeds[stats[11]];
|
||||
parent_elem.append(atkSpd);
|
||||
parent_elem.append(document.createElement("br"));
|
||||
|
||||
//overall attack speed
|
||||
let overallatkSpd = document.createElement("p");
|
||||
overallatkSpd.classList.add("center");
|
||||
overallatkSpd.classList.add("itemp");
|
||||
overallatkSpd.textContent = "Attack Speed: " + attackSpeeds[stats[11]];
|
||||
overallparent_elem.append(overallatkSpd);
|
||||
overallparent_elem.append(document.createElement("br"));
|
||||
|
||||
//Non-Crit: n->elem, total dmg, DPS
|
||||
let nonCritStats = document.createElement("p");
|
||||
nonCritStats.classList.add("center");
|
||||
nonCritStats.classList.add("itemp");
|
||||
nonCritStats.textContent = "Non-Crit Stats: ";
|
||||
nonCritStats.append(document.createElement("br"));
|
||||
let dmg = document.createElement("p");
|
||||
for (let i = 0; i < 6; i++){
|
||||
if(stats[i][0] > 0){
|
||||
dmg.textContent = damagePrefixes[i] + stats[i][0] + " - " + stats[i][1];
|
||||
let dmg = document.createElement("p");
|
||||
dmg.textContent = stats[i][0] + "-" + stats[i][1];
|
||||
dmg.classList.add(damageClasses[i]);
|
||||
dmg.classList.add("itemp");
|
||||
nonCritStats.append(dmg);
|
||||
}
|
||||
}
|
||||
let normalDamage = document.createElement("p");
|
||||
normalDamage.textContent = "Total Damage: " + stats[6][0] + " - " + stats[6][1];
|
||||
normalDamage.textContent = "Total: " + stats[6][0] + "-" + stats[6][1];
|
||||
normalDamage.classList.add("itemp");
|
||||
nonCritStats.append(normalDamage);
|
||||
|
||||
let normalDPS = document.createElement("p");
|
||||
normalDPS.textContent = "Normal DPS: " + stats[8];
|
||||
normalDPS.append(document.createElement("br"));
|
||||
normalDPS.append(document.createElement("br"));
|
||||
normalDPS.classList.add("itemp");
|
||||
nonCritStats.append(normalDPS);
|
||||
|
||||
parent_elem.append(nonCritStats);
|
||||
|
@ -419,45 +522,128 @@ function displayMeleeDamage(parent_elem, meleeStats){
|
|||
//Crit: n->elem, total dmg, DPS
|
||||
let critStats = document.createElement("p");
|
||||
critStats.classList.add("center");
|
||||
critStats.classList.add("itemp");
|
||||
critStats.textContent = "Crit Stats: ";
|
||||
critStats.append(document.createElement("br"));
|
||||
dmg = document.createElement("p");
|
||||
for (let i = 0; i < 6; i++){
|
||||
if(stats[i][2] > 0){
|
||||
dmg.textContent = damagePrefixes[i] + stats[i][2] + " - " + stats[i][3];
|
||||
dmg = document.createElement("p");
|
||||
dmg.textContent = stats[i][2] + "-" + stats[i][3];
|
||||
dmg.classList.add(damageClasses[i]);
|
||||
dmg.classList.add("itemp");
|
||||
critStats.append(dmg);
|
||||
}
|
||||
}
|
||||
normalDamage = document.createElement("p");
|
||||
normalDamage.textContent = "Total Damage: " + stats[7][0] + " - " + stats[7][1];
|
||||
critStats.append(normalDamage);
|
||||
let critDamage = document.createElement("p");
|
||||
critDamage.textContent = "Total: " + stats[7][0] + "-" + stats[7][1];
|
||||
critDamage.classList.add("itemp");
|
||||
critStats.append(critDamage);
|
||||
|
||||
normalDPS = document.createElement("p");
|
||||
normalDPS.textContent = "Crit DPS: " + stats[9];
|
||||
normalDPS.append(document.createElement("br"));
|
||||
normalDPS.append(document.createElement("br"));
|
||||
critStats.append(normalDPS);
|
||||
let critDPS = document.createElement("p");
|
||||
critDPS.textContent = "Crit DPS: " + stats[9];
|
||||
critDPS.classList.add("itemp");
|
||||
critDPS.append(document.createElement("br"));
|
||||
critDPS.append(document.createElement("br"));
|
||||
critStats.append(critDPS);
|
||||
|
||||
parent_elem.append(critStats);
|
||||
}
|
||||
function displayDefenseStats(parent_elem,defenseStats){
|
||||
parent_elem.textContent = "";
|
||||
const stats = defenseStats.slice();
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.textContent = "Defense Stats";
|
||||
title_elem.classList.add("title");
|
||||
parent_elem.append(title_elem);
|
||||
parent_elem.append(document.createElement("br"));
|
||||
|
||||
|
||||
//[total hp, ehp, total hpr, ehpr, [def%, agi%], [edef,tdef,wdef,fdef,adef]]
|
||||
for(const i in stats){
|
||||
if(typeof stats[i] === "number"){
|
||||
stats[i] = stats[i].toFixed(2);
|
||||
}else{
|
||||
for(const j in stats[i]){
|
||||
stats[i][j] = stats[i][j].toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
//total HP
|
||||
let hpElem = document.createElement("p");
|
||||
hpElem.textContent = "HP: " + stats[0];
|
||||
hpElem.classList.add("left");
|
||||
hpElem.classList.add("Health");
|
||||
parent_elem.append(hpElem);
|
||||
//EHP
|
||||
let ehpElem = document.createElement("p");
|
||||
ehpElem.textContent = "Effective HP: " + stats[1];
|
||||
ehpElem.classList.add("left");
|
||||
parent_elem.append(ehpElem);
|
||||
//total HPR
|
||||
let hprElem = document.createElement("p");
|
||||
hprElem.textContent = "HP Regen: " + stats[2];
|
||||
hprElem.classList.add("left");
|
||||
hprElem.classList.add("Health");
|
||||
parent_elem.append(hprElem);
|
||||
//EHPR
|
||||
let ehprElem = document.createElement("p");
|
||||
ehprElem.textContent = "Effective HP Regen: " + stats[3];
|
||||
ehprElem.classList.add("left");
|
||||
parent_elem.append(ehprElem);
|
||||
//eledefs
|
||||
let eledefs = stats[5];
|
||||
for (let i = 0; i < eledefs.length; i++){
|
||||
/* TODO: make this comment work
|
||||
let eledefElem = document.createElement("p");
|
||||
let ele = document.createElement("b");
|
||||
ele.classList.add(damageClasses[i+1]);
|
||||
ele.textContent = damageClasses[i+1];
|
||||
eledefElem.textContent = " Defense: " + eledefs[i];
|
||||
//eledefElem.classList.add(damageClasses[i+1]);
|
||||
eledefElem.classList.add("left");
|
||||
parent_elem.append(ele);
|
||||
parent_elem.append(eledefElem);
|
||||
*/
|
||||
let eledefElem = document.createElement("p");
|
||||
eledefElem.textContent = damageClasses[i+1] + " Defense: " + eledefs[i];
|
||||
eledefElem.classList.add(damageClasses[i+1]);
|
||||
eledefElem.classList.add("left");
|
||||
parent_elem.append(eledefElem);
|
||||
}
|
||||
//skp
|
||||
let defElem = document.createElement("p");
|
||||
defElem.textContent = "Damage Absorbed %: " + stats[4][0] + "%";
|
||||
defElem.classList.add("left");
|
||||
parent_elem.append(defElem);
|
||||
let agiElem = document.createElement("p");
|
||||
agiElem.textContent = "Dodge Chance %: " + stats[4][1] + "%";
|
||||
agiElem.classList.add("left");
|
||||
parent_elem.append(agiElem);
|
||||
|
||||
|
||||
}
|
||||
function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
||||
|
||||
function displaySpellDamage(parent_elem, overallparent_elem, build, spell, spellIdx) {
|
||||
parent_elem.textContent = "";
|
||||
|
||||
const stats = build.statMap;
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.classList.add('center');
|
||||
title_elem.classList.add('title');
|
||||
|
||||
overallparent_elem.textContent = "";
|
||||
let title_elemavg = document.createElement("p");
|
||||
title_elemavg.classList.add('title');
|
||||
if (spellIdx != 0) {
|
||||
title_elem.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
|
||||
title_elemavg.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
|
||||
}
|
||||
else {
|
||||
title_elem.textContent = spell.title;
|
||||
title_elemavg.textContent = spell.title;
|
||||
}
|
||||
|
||||
parent_elem.append(title_elem);
|
||||
overallparent_elem.append(title_elemavg);
|
||||
|
||||
let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
|
||||
|
||||
let save_damages = [];
|
||||
|
@ -467,13 +653,21 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
|||
let part_div = document.createElement("p");
|
||||
parent_elem.append(part_div);
|
||||
|
||||
let part_divavg = document.createElement("p");
|
||||
overallparent_elem.append(part_divavg);
|
||||
|
||||
let subtitle_elem = document.createElement("p");
|
||||
subtitle_elem.textContent = part.subtitle;
|
||||
part_div.append(subtitle_elem);
|
||||
|
||||
let subtitle_elemavg = document.createElement("p");
|
||||
subtitle_elemavg.textContent = part.subtitle;
|
||||
part_divavg.append(subtitle_elemavg);
|
||||
|
||||
if (part.type === "damage") {
|
||||
|
||||
let _results = calculateSpellDamage(stats, part.conversion,
|
||||
stats.get("sdRaw"), stats.get("sdPct"),
|
||||
stats.get("sdRaw"), stats.get("sdPct"),
|
||||
part.multiplier / 100, build.weapon, build.total_skillpoints);
|
||||
let totalDamNormal = _results[0];
|
||||
let totalDamCrit = _results[1];
|
||||
|
@ -492,12 +686,17 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
|||
averageLabel.classList.add("damageSubtitle");
|
||||
part_div.append(averageLabel);
|
||||
|
||||
let overallaverageLabel = document.createElement("p");
|
||||
overallaverageLabel.textContent = "Average: "+averageDamage.toFixed(2);
|
||||
overallaverageLabel.classList.add("damageSubtitle");
|
||||
part_divavg.append(overallaverageLabel);
|
||||
|
||||
let nonCritLabel = document.createElement("p");
|
||||
nonCritLabel.textContent = "Non-Crit Average: "+nonCritAverage.toFixed(2);
|
||||
nonCritLabel.classList.add("damageSubtitle");
|
||||
part_div.append(nonCritLabel);
|
||||
|
||||
let damageClasses = ["Neutral","Earth","Thunder","Water","Fire","Air"];
|
||||
|
||||
for (let i = 0; i < 6; i++){
|
||||
if (results[i][1] > 0){
|
||||
let p = document.createElement("p");
|
||||
|
@ -525,11 +724,17 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
|||
save_damages.push(averageDamage);
|
||||
}
|
||||
else if (part.type == "heal") {
|
||||
let heal_amount = part.strength * build.getHealth() * Math.max(0, Math.min(1.5, 1 + 0.05 * stats.get("wDamPct")));
|
||||
let heal_amount = (part.strength * build.getDefenseStats()[0] * Math.max(0, Math.min(1.5, 1 + 0.05 * stats.get("wDamPct")))).toFixed(2);
|
||||
let healLabel = document.createElement("p");
|
||||
healLabel.textContent = heal_amount;
|
||||
healLabel.classList.add("damagep");
|
||||
part_div.append(healLabel);
|
||||
|
||||
|
||||
let overallhealLabel = document.createElement("p");
|
||||
overallhealLabel.textContent = heal_amount;
|
||||
overallhealLabel.classList.add("damagep")
|
||||
part_divavg.append(overallhealLabel);
|
||||
}
|
||||
else if (part.type === "total") {
|
||||
let total_damage = 0;
|
||||
|
@ -540,6 +745,12 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
|||
averageLabel.textContent = "Average: "+total_damage.toFixed(2);
|
||||
averageLabel.classList.add("damageSubtitle");
|
||||
part_div.append(averageLabel);
|
||||
|
||||
|
||||
let overallaverageLabel = document.createElement("p");
|
||||
overallaverageLabel.textContent = "Average: "+total_damage.toFixed(2);
|
||||
overallaverageLabel.classList.add("damageSubtitle");
|
||||
part_divavg.append(averageLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
288
index.html
288
index.html
|
@ -22,118 +22,152 @@
|
|||
<a href="credits.txt" class="link">Additional credits</a>
|
||||
</div>
|
||||
<div class="equipment">
|
||||
<div class="right" style="grid-column:1;grid-row:1">
|
||||
<label>Equipments</label>
|
||||
<br>
|
||||
<br>
|
||||
<div>
|
||||
<label for="helmet-choice">Helmet:</label>
|
||||
<input list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/>
|
||||
<datalist id="helmet-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="chestplate-choice">Chestplate:</label>
|
||||
<input list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate"/>
|
||||
<datalist id="chestplate-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="leggings-choice">Leggings:</label>
|
||||
<input list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings"/>
|
||||
<datalist id="leggings-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div id="boots">
|
||||
<label for="boots-choice">Boots:</label>
|
||||
<input list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots"/>
|
||||
<datalist id="boots-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="ring1-choice">Ring 1:</label>
|
||||
<input list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/>
|
||||
<datalist id="ring1-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="ring2-choice">Ring 2:</label>
|
||||
<input list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2"/>
|
||||
<datalist id="ring2-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="bracelet-choice">Bracelet:</label>
|
||||
<input list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet"/>
|
||||
<datalist id="bracelet-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="necklace-choice">Necklace:</label>
|
||||
<input list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/>
|
||||
<datalist id="necklace-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="weapon-choice">Weapon:</label>
|
||||
<input list="weapon-items" id="weapon-choice" name="weapon-choice" value=""/>
|
||||
<datalist id="weapon-items">
|
||||
</datalist>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<button class = "button" id = "calc-button" onclick = "calculateBuild()">
|
||||
Update Items (Resets stats)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="left" style="grid-column:2;grid-row:1">
|
||||
<label>Powdering:</label>
|
||||
<div id="helmet-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="helmet-powder" name="helmet-powder" />
|
||||
</div>
|
||||
<div id="chestplate-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="chestplate-powder" name="chestplate-powder" />
|
||||
</div>
|
||||
<div id="leggings-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="leggings-powder" name="leggings-powder" />
|
||||
</div>
|
||||
<div id="boots-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="boots-powder" name="boots-powder" />
|
||||
</div>
|
||||
<br/><br/><br/><br/><br/><br/><br/><br/>
|
||||
<div id="weapon-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="weapon-powder" name="weapon-powder" />
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<button class = "reset" id = "reset-button" onclick = "resetFields()">
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
<div class="left" style="grid-column:1/span 2;grid-row:1">
|
||||
<table>
|
||||
<tr>
|
||||
<th class="right">
|
||||
<label>Equipments</label>
|
||||
</th>
|
||||
<th>
|
||||
<label>Powdering</label>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="helmet-choice">Helmet:</label>
|
||||
<input list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/>
|
||||
<datalist id="helmet-items">
|
||||
</datalist>
|
||||
</td>
|
||||
<td>
|
||||
<div id="helmet-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="helmet-powder" name="helmet-powder"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="chestplate-choice">Chestplate:</label>
|
||||
<input list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate" />
|
||||
<datalist id="chestplate-items">
|
||||
</datalist>
|
||||
</td>
|
||||
<td>
|
||||
<div id="chestplate-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="chestplate-powder" name="chestplate-powder" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="leggings-choice">Leggings:</label>
|
||||
<input list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings" />
|
||||
<datalist id="leggings-items">
|
||||
</datalist>
|
||||
</td>
|
||||
<td>
|
||||
<div id="leggings-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="leggings-powder" name="leggings-powder" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="boots-choice">Boots:</label>
|
||||
<input list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots" />
|
||||
<datalist id="boots-items">
|
||||
</datalist>
|
||||
</td>
|
||||
<td>
|
||||
<div id="boots-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div style="grid-column:1;grid-row:4">
|
||||
<input type="text" id="boots-powder" name="boots-powder"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="ring1-choice">Ring 1:</label>
|
||||
<input list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/>
|
||||
<datalist id="ring1-items">
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="ring2-choice">Ring 2:</label>
|
||||
<input list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2" />
|
||||
<datalist id="ring2-items">
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="bracelet-choice">Bracelet:</label>
|
||||
<input list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet" />
|
||||
<datalist id="bracelet-items">
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="necklace-choice">Necklace:</label>
|
||||
<input list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/>
|
||||
<datalist id="necklace-items">
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">
|
||||
<br/>
|
||||
<label for="weapon-choice">Weapon:</label>
|
||||
<input list="weapon-items" id="weapon-choice" name="weapon-choice" placeholder="No Weapon" value=""/>
|
||||
<datalist id="weapon-items">
|
||||
</datalist>
|
||||
</td>
|
||||
<td>
|
||||
<div id="weapon-slots">
|
||||
X slots
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="weapon-powder" name="weapon-powder" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<br/>
|
||||
<button class = "button" id = "calc-button" onclick = "calculateBuild()">
|
||||
Update Items (Resets stats)
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<button class = "reset" id = "reset-button" onclick = "resetFields()">
|
||||
Reset
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="center" style="grid-column:3;grid-row:1">
|
||||
<div class = "center build-overall" id = "build-overall">
|
||||
|
@ -141,6 +175,23 @@
|
|||
<div class = "center" id = "build-overall-stats"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center" style="grid-column:4;">
|
||||
<div class="spell-info" style="grid-row:1;">
|
||||
<div class="center" id="build-melee-statsAvg">melee</div>
|
||||
</div>
|
||||
<div class="spell-info" style="grid-row:1;">
|
||||
<div class="center" id="spell0-infoAvg">spell1</div>
|
||||
</div>
|
||||
<div class="spell-info" style="grid-row:2">
|
||||
<div class="center" id="spell1-infoAvg">spell2</div>
|
||||
</div>
|
||||
<div class="spell-info" style="grid-row:3">
|
||||
<div class="center" id="spell2-infoAvg">spell3</div>
|
||||
</div>
|
||||
<div class="spell-info" style="grid-row:4">
|
||||
<div class="center" id="spell3-infoAvg">spell4</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center" id="summary-box">
|
||||
Summary:
|
||||
|
@ -250,16 +301,12 @@
|
|||
<div class = "center build-weapon" id = "build-weapon" style = "grid-column:1;grid-row:3">
|
||||
<div class = "center" id = "build-weapon-stats"></div>
|
||||
</div>
|
||||
<div class = "center build-overall" id = "build-overall" style = "grid-column:4;grid-row:3">
|
||||
<p class="itemcenter">Overall Build Stats:<p>
|
||||
<div class = "center" id = "build-overall-stats"></div>
|
||||
<div class = "center build-order" id = "build-order" style = "grid-column:2;grid-row:3">
|
||||
</div>
|
||||
<div class = "center build-melee-stats" id = "build-melee-stats" style = "grid-column:3;grid-row:3">
|
||||
</div>
|
||||
<div class = "center build-order" id = "build-order" style = "grid-column:2;grid-row:3">
|
||||
<div class = "center build-defense-stats" id = "build-defense-stats" style = "grid-column:4;grid-row:3">
|
||||
</div>
|
||||
<!--div class = "center" id = "build-defense-stats" style = "grid-column:4;grid-row:3">
|
||||
</div-->
|
||||
</div>
|
||||
<div class = "spells">
|
||||
<div class = "center spell-info" id = "spell0" style = "grid-column:1;grid-row:1">
|
||||
|
@ -279,6 +326,11 @@
|
|||
<div class = "center" id = "spell3-info">Spell 4</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="misc">
|
||||
<div class = "center set-info" id = "set-info-div" style = "grid-column:1;grid-row:1">
|
||||
<div class = "center" id = "set-info">Set info</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="utils.js"></script>
|
||||
<script type="text/javascript" src="skillpoints.js"></script>
|
||||
|
|
2
load.js
2
load.js
|
@ -1,4 +1,4 @@
|
|||
const DB_VERSION = 7;
|
||||
const DB_VERSION = 11;
|
||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
|
||||
|
||||
let db;
|
||||
|
|
|
@ -69,93 +69,153 @@ for item in build_items:
|
|||
setup(item)
|
||||
if all(x == 0 for x in item["reqs"]):
|
||||
fixed.append(item)
|
||||
elif all(x == 0 for x in item["skillpoints"]):
|
||||
elif all(x == 0 for x in item["skillpoints"]) and item["set"] is None:
|
||||
noboost.append(item)
|
||||
else:
|
||||
consider.append(item)
|
||||
setup(build_weapon)
|
||||
fixed = tuple(fixed)
|
||||
noboost = tuple(noboost)
|
||||
consider = tuple(consider)
|
||||
|
||||
"""
|
||||
The way this code expects this to work:
|
||||
sets is a map: setName -> setObject {
|
||||
bonuses: array[bonusObject]
|
||||
}
|
||||
|
||||
where each bonusObject is a mapping from id to boost value.
|
||||
And the bonuses array describes the effect of equipping set items (0 index = 1 item).
|
||||
"""
|
||||
sets = dict()
|
||||
|
||||
# Apply the skillpoints an item gives to the build.
|
||||
def apply_skillpoints(skillpoints, item):
|
||||
"""
|
||||
skillPoints: current skillpoint totals.
|
||||
item: Item in uestion.
|
||||
activeSetCounts: Mapping from setname to number of items currently worn (not including this one).
|
||||
"""
|
||||
def apply_skillpoints(skillpoints, item, activeSetCounts):
|
||||
for i in range(5):
|
||||
skillpoints[i] += item["skillpoints"][i]
|
||||
|
||||
def remove_skillpoints(skillpoints, item):
|
||||
for i in range(5):
|
||||
skillpoints[i] -= item["skillpoints"][i]
|
||||
if item["set"] is not None:
|
||||
setName = item["set"]
|
||||
old_bonus = dict()
|
||||
if setName in activeSetCounts:
|
||||
setCount = activeSetCounts[setName]
|
||||
old_bonus = sets[setName]["bonuses"][setCount-1]
|
||||
activeSetCounts[setName] = setCount + 1
|
||||
else:
|
||||
setCount = 0
|
||||
activeSetCounts[setName] = 1
|
||||
new_bonus = sets[setName]["bonuses"][setCount]
|
||||
skp_order = ["str","dex","int","def","agi"]
|
||||
for i, skp in enumerate(skp_order):
|
||||
delta = new_bonus[skp] - old_bonus[skp]
|
||||
skillpoints[i] += delta
|
||||
|
||||
# Figure out (naively) how many skillpoints need to be applied to get the current item to fit.
|
||||
# Doesn't handle -skp.
|
||||
def apply_to_fit(skillpoints, item):
|
||||
def apply_to_fit(skillpoints, item, skillpoint_filter, activeSetCounts):
|
||||
applied = [0, 0, 0, 0, 0]
|
||||
total = 0
|
||||
for i, req, cur in zip(range(5), item["reqs"], skillpoints):
|
||||
if item["skillpoints"][i] < 0 and skillpoint_filter[i]:
|
||||
applied[i] -= item["skillpoints"][i]
|
||||
total -= item["skillpoints"][i]
|
||||
if (item["reqs"][i] == 0):
|
||||
continue
|
||||
skillpoint_filter[i] = True
|
||||
if req > cur:
|
||||
diff = req - cur
|
||||
applied[i] += diff
|
||||
total += diff
|
||||
|
||||
if item["set"] is not None:
|
||||
setName = item["set"]
|
||||
old_bonus = dict()
|
||||
if setName in activeSetCounts:
|
||||
setCount = activeSetCounts[setName]
|
||||
old_bonus = sets[setName]["bonuses"][setCount-1]
|
||||
activeSetCounts[setName] = setCount + 1
|
||||
else:
|
||||
setCount = 0;
|
||||
activeSetCounts[setName] = 1
|
||||
new_bonus = sets[setName]["bonuses"][setCount]
|
||||
skp_order = ["str","dex","int","def","agi"]
|
||||
for i, skp in enumerate(skp_order):
|
||||
delta = new_bonus[skp] - old_bonus[skp]
|
||||
if delta < 0 and skillpoint_filter[i]:
|
||||
applied[i] -= delta
|
||||
total -= delta
|
||||
return applied, total
|
||||
|
||||
# Permutations in js reference (also cool algorithm):
|
||||
# https://stackoverflow.com/a/41068709
|
||||
|
||||
static_skillpoints_base = [0, 0, 0, 0, 0]
|
||||
static_activeSetCounts = dict()
|
||||
|
||||
# Separate out the no req items and add them to the static skillpoint base.
|
||||
for item in fixed:
|
||||
apply_skillpoints(static_skillpoints_base, item)
|
||||
apply_skillpoints(static_skillpoints_base, item, static_activeSetCounts)
|
||||
|
||||
best = None
|
||||
final_skillpoints = None
|
||||
best = consider + noboost;
|
||||
final_skillpoints = static_skillpoints_base[:]
|
||||
best_skillpoints = [0, 0, 0, 0, 0]
|
||||
best_total = math.inf
|
||||
best_activeSetCounts = dict()
|
||||
|
||||
# Try every combination and pick the best one.
|
||||
import itertools
|
||||
for permutation in itertools.permutations(consider):
|
||||
allFalse = [False] * 5
|
||||
|
||||
permutation += noboost
|
||||
if len(consider) or len(noboost):
|
||||
|
||||
skillpoints_applied = [0, 0, 0, 0, 0]
|
||||
skillpoints = copy.copy(static_skillpoints_base)
|
||||
total_applied = 0
|
||||
for item in permutation:
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item)
|
||||
for i in range(5):
|
||||
skillpoints_applied[i] += needed_skillpoints[i]
|
||||
skillpoints[i] += needed_skillpoints[i]
|
||||
apply_skillpoints(skillpoints, item)
|
||||
total_applied += total_diff
|
||||
if total_applied >= best_total:
|
||||
break
|
||||
if total_applied < best_total:
|
||||
# Try every combination and pick the best one.
|
||||
import itertools
|
||||
for permutation in itertools.permutations(consider):
|
||||
activeSetCounts = dict(best_activeSetCounts)
|
||||
has_skillpoint = allFalse[:]
|
||||
|
||||
permutation += noboost
|
||||
|
||||
skillpoints_applied = [0, 0, 0, 0, 0]
|
||||
skillpoints = static_skillpoints_base[:]
|
||||
total_applied = 0
|
||||
for item in permutation:
|
||||
remove_skillpoints(skillpoints, item)
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item)
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item, has_skillpoint, activeSetCounts)
|
||||
for i in range(5):
|
||||
skillpoints_applied[i] += needed_skillpoints[i]
|
||||
skillpoints[i] += needed_skillpoints[i]
|
||||
apply_skillpoints(skillpoints, item)
|
||||
apply_skillpoints(skillpoints, item, activeSetCounts)
|
||||
total_applied += total_diff
|
||||
if total_applied >= best_total:
|
||||
break
|
||||
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon)
|
||||
for i in range(5):
|
||||
skillpoints_applied[i] += needed_skillpoints[i]
|
||||
skillpoints[i] += needed_skillpoints[i]
|
||||
apply_skillpoints(skillpoints, build_weapon)
|
||||
total_applied += total_diff
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon, has_skillpoint, activeSetCounts)
|
||||
for i in range(5):
|
||||
skillpoints_applied[i] += needed_skillpoints[i]
|
||||
skillpoints[i] += needed_skillpoints[i]
|
||||
apply_skillpoints(skillpoints, build_weapon, activeSetCounts)
|
||||
total_applied += total_diff
|
||||
|
||||
if total_applied < best_total:
|
||||
best = permutation
|
||||
final_skillpoints = skillpoints
|
||||
best_skillpoints = skillpoints_applied
|
||||
best_total = total_applied
|
||||
if total_applied < best_total:
|
||||
best = permutation
|
||||
final_skillpoints = skillpoints
|
||||
best_skillpoints = skillpoints_applied
|
||||
best_total = total_applied
|
||||
best_activeSetCounts = activeSetCounts
|
||||
else:
|
||||
best_total = 0
|
||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon, allFalse, best_activeSetCounts)
|
||||
for i in range(5):
|
||||
best_skillpoints[i] += needed_skillpoints[i]
|
||||
final_skillpoints[i] += needed_skillpoints[i]
|
||||
apply_skillpoints(skillpoints, build_weapon, best_activeSetCounts)
|
||||
best_total += total_diff
|
||||
|
||||
equip_order = fixed + best
|
||||
results = [equip_order, best_skillpoints, final_skillpoints, best_total, best_activeSetCounts];
|
||||
|
||||
print([i["displayName"] for i in fixed + best])
|
||||
print(best_skillpoints)
|
||||
|
|
100
skillpoints.js
100
skillpoints.js
|
@ -10,32 +10,45 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
if (item.get("reqs").every(x => x === 0)) {
|
||||
fixed.push(item);
|
||||
}
|
||||
else if (item.get("skillpoints").every(x => x === 0)) {
|
||||
// TODO hack: We will treat ALL set items as unsafe :(
|
||||
else if (item.get("skillpoints").every(x => x === 0) && item.get("set") === null) {
|
||||
noboost.push(item);
|
||||
}
|
||||
else {
|
||||
consider.push(item);
|
||||
}
|
||||
}
|
||||
function apply_skillpoints(skillpoints, item) {
|
||||
function apply_skillpoints(skillpoints, item, activeSetCounts) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
skillpoints[i] += item.get("skillpoints")[i];
|
||||
}
|
||||
}
|
||||
|
||||
function remove_skillpoints(skillpoints, item) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
skillpoints[i] -= item.get("skillpoints")[i];
|
||||
const setName = item.get("set");
|
||||
if (setName) { // undefined/null means no set.
|
||||
let setCount = activeSetCounts.get(setName);
|
||||
let old_bonus = {};
|
||||
if (setCount) {
|
||||
old_bonus = sets[setName].bonuses[setCount-1];
|
||||
activeSetCounts.set(setName, setCount + 1);
|
||||
}
|
||||
else {
|
||||
setCount = 0;
|
||||
activeSetCounts.set(setName, 1);
|
||||
}
|
||||
const new_bonus = sets[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);
|
||||
skillpoints[i] += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out (naively) how many skillpoints need to be applied to get the current item to fit.
|
||||
// Doesn't handle -skp.
|
||||
function apply_to_fit(skillpoints, item, skillpoint_filter) {
|
||||
function apply_to_fit(skillpoints, item, skillpoint_filter, activeSetCounts) {
|
||||
let applied = [0, 0, 0, 0, 0];
|
||||
let total = 0;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (item.get("skillpoints")[i] < 0 && skillpoint_filter[i] === true) {
|
||||
if (item.get("skillpoints")[i] < 0 && skillpoint_filter[i]) {
|
||||
applied[i] -= item.get("skillpoints")[i];
|
||||
total -= item.get("skillpoints")[i];
|
||||
}
|
||||
|
@ -49,24 +62,46 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
total += diff;
|
||||
}
|
||||
}
|
||||
|
||||
const setName = item.get("set");
|
||||
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];
|
||||
//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);
|
||||
if (delta < 0 && skillpoint_filter[i]) {
|
||||
applied[i] -= delta;
|
||||
total -= delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [applied, total];
|
||||
}
|
||||
|
||||
// Separate out the no req items and add them to the static skillpoint base.
|
||||
let static_skillpoints_base = [0, 0, 0, 0, 0]
|
||||
let static_activeSetCounts = new Map()
|
||||
for (const item of fixed) {
|
||||
apply_skillpoints(static_skillpoints_base, item);
|
||||
apply_skillpoints(static_skillpoints_base, item, static_activeSetCounts);
|
||||
}
|
||||
|
||||
let best = consider.concat(noboost);
|
||||
let final_skillpoints = static_skillpoints_base.slice();
|
||||
let best_skillpoints = [0, 0, 0, 0, 0];
|
||||
let best_total = Infinity;
|
||||
let best_activeSetCounts = static_activeSetCounts;
|
||||
|
||||
let allFalse = [false, false, false, false, false];
|
||||
if (consider.length > 0 || noboost.length > 0) {
|
||||
// Try every combination and pick the best one.
|
||||
for (let permutation of perm(consider)) {
|
||||
let activeSetCounts = new Map(static_activeSetCounts);
|
||||
|
||||
let has_skillpoint = allFalse.slice();
|
||||
|
||||
permutation = permutation.concat(noboost);
|
||||
|
@ -81,7 +116,7 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
let needed_skillpoints;
|
||||
let total_diff;
|
||||
for (const item of permutation) {
|
||||
result = apply_to_fit(skillpoints, item, has_skillpoint);
|
||||
result = apply_to_fit(skillpoints, item, has_skillpoint, activeSetCounts);
|
||||
needed_skillpoints = result[0];
|
||||
total_diff = result[1];
|
||||
|
||||
|
@ -89,40 +124,14 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
skillpoints_applied[i] += needed_skillpoints[i];
|
||||
skillpoints[i] += needed_skillpoints[i];
|
||||
}
|
||||
apply_skillpoints(skillpoints, item);
|
||||
apply_skillpoints(skillpoints, item, activeSetCounts);
|
||||
total_applied += total_diff;
|
||||
if (total_applied >= best_total) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (total_applied < best_total) {
|
||||
// console.log(total_applied);
|
||||
// console.log(skillpoints_applied);
|
||||
// console.log("Iteration 2");
|
||||
// for (const item of permutation) {
|
||||
// console.log(item);
|
||||
//
|
||||
// remove_skillpoints(skillpoints, item);
|
||||
// console.log(skillpoints);
|
||||
// result = apply_to_fit(skillpoints, item, has_skillpoint);
|
||||
// needed_skillpoints = result[0];
|
||||
// total_diff = result[1];
|
||||
// for (let i = 0; i < 5; ++i) {
|
||||
// skillpoints_applied[i] += needed_skillpoints[i];
|
||||
// skillpoints[i] += needed_skillpoints[i];
|
||||
// }
|
||||
//
|
||||
// apply_skillpoints(skillpoints, item);
|
||||
// console.log(skillpoints);
|
||||
// console.log(total_diff);
|
||||
// total_applied += total_diff;
|
||||
// if (total_applied >= best_total) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
let pre = skillpoints.slice();
|
||||
result = apply_to_fit(skillpoints, weapon, allFalse.slice());
|
||||
result = apply_to_fit(skillpoints, weapon, allFalse.slice(), activeSetCounts);
|
||||
needed_skillpoints = result[0];
|
||||
total_diff = result[1];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
|
@ -130,32 +139,31 @@ function calculate_skillpoints(equipment, weapon) {
|
|||
skillpoints[i] += needed_skillpoints[i];
|
||||
}
|
||||
|
||||
apply_skillpoints(skillpoints, weapon);
|
||||
apply_skillpoints(skillpoints, weapon, activeSetCounts);
|
||||
total_applied += total_diff;
|
||||
|
||||
if (total_applied < best_total) {
|
||||
console.log(pre);
|
||||
console.log(skillpoints);
|
||||
best = permutation;
|
||||
final_skillpoints = skillpoints;
|
||||
best_skillpoints = skillpoints_applied;
|
||||
best_total = total_applied;
|
||||
best_activeSetCounts = activeSetCounts;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
best_total = 0;
|
||||
result = apply_to_fit(final_skillpoints, weapon, allFalse.slice());
|
||||
result = apply_to_fit(final_skillpoints, weapon, allFalse.slice(), best_activeSetCounts);
|
||||
needed_skillpoints = result[0];
|
||||
total_diff = result[1];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
best_skillpoints[i] += needed_skillpoints[i];
|
||||
final_skillpoints[i] += needed_skillpoints[i];
|
||||
}
|
||||
apply_skillpoints(final_skillpoints, weapon);
|
||||
apply_skillpoints(final_skillpoints, weapon, best_activeSetCounts);
|
||||
best_total += total_diff;
|
||||
}
|
||||
let equip_order = fixed.concat(best);
|
||||
return [equip_order, best_skillpoints, final_skillpoints, best_total];
|
||||
return [equip_order, best_skillpoints, final_skillpoints, best_total, best_activeSetCounts];
|
||||
}
|
||||
|
|
90
styles.css
90
styles.css
|
@ -8,6 +8,10 @@
|
|||
font-weight: 700;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.equipment {
|
||||
padding: 4%;
|
||||
display: grid;
|
||||
|
@ -24,7 +28,7 @@
|
|||
grid-auto-rows: minmax(60px, auto);
|
||||
}
|
||||
.equipment, .skillpoints, .center, .header, .all{
|
||||
background: #110110;
|
||||
background: #121516;
|
||||
color: #aaa;
|
||||
}
|
||||
.hppeng{
|
||||
|
@ -36,6 +40,10 @@
|
|||
a.link{
|
||||
color: #A5FDFF;
|
||||
}
|
||||
.title{
|
||||
text-align: center;
|
||||
font-size: 150%;
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -45,25 +53,27 @@ a.link{
|
|||
}
|
||||
|
||||
.left {
|
||||
margin: 2px 2%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.build, .spells {
|
||||
.build, .spells, .misc {
|
||||
padding: 2%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 20px;
|
||||
grid-auto-rows: minmax(60px, auto);
|
||||
width: 94%;
|
||||
background: #110110;
|
||||
background: #121516;
|
||||
}
|
||||
|
||||
.build-helmet, .build-chestplate, .build-leggings, .build-boots, .build-ring1, .build-ring2, .build-bracelet, .build-necklace, .build-weapon, .build-order, .build-overall, .build-melee-stats, .spell-info {
|
||||
.build-helmet, .build-chestplate, .build-leggings, .build-boots, .build-ring1, .build-ring2, .build-bracelet, .build-necklace, .build-weapon, .build-order, .build-overall, .build-melee-stats, .build-defense-stats, .spell-info, .set-info {
|
||||
color: #aaa;
|
||||
background: #110110;
|
||||
background: #121516;
|
||||
border: 3px solid #BCBCBC;
|
||||
border-radius: 3px;
|
||||
width: 96%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.itemcenter {
|
||||
|
@ -172,20 +182,68 @@ a.link{
|
|||
width: 10px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 5px #BCBCBC;
|
||||
border: #BCBCBC;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #aaa;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ugly Corner */
|
||||
::-webkit-scrollbar-corner{
|
||||
background: #110110;
|
||||
}
|
||||
/* Ugly Corner */
|
||||
::-webkit-scrollbar-corner{
|
||||
background: #110110;
|
||||
}
|
||||
button {
|
||||
background-color: #666;
|
||||
border: 2px solid #444;
|
||||
border-radius: 5px;
|
||||
color: #ddd;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-family: 'Nunito',sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 120%;
|
||||
display: inline-block;
|
||||
}
|
||||
input {
|
||||
background-color: #666;
|
||||
border: 2px solid #444;
|
||||
border-radius: 5px;
|
||||
color: #ddd;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-family: 'Nunito',sans-serif;
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
}
|
||||
::placeholder{
|
||||
color: #ddd;
|
||||
}
|
||||
/* Tier colors tier colors */
|
||||
.Normal{
|
||||
color: #fff;
|
||||
}
|
||||
.Unique{
|
||||
color:#ff5;
|
||||
}
|
||||
.Rare{
|
||||
color:#f5f;
|
||||
}
|
||||
.Legendary{
|
||||
color:#5ff;
|
||||
}
|
||||
.Fabled{
|
||||
color:#f55;
|
||||
}
|
||||
.Mythic{
|
||||
color:#a0a;
|
||||
}
|
||||
.Set{
|
||||
color:#5f5
|
||||
}
|
||||
|
|
31
test.js
31
test.js
|
@ -11,7 +11,7 @@ console.log(url_tag);
|
|||
* END testing section
|
||||
*/
|
||||
|
||||
const BUILD_VERSION = "3.2";
|
||||
const BUILD_VERSION = "4.6";
|
||||
|
||||
document.getElementById("header").textContent = "Wynn build calculator "+BUILD_VERSION+" (db version "+DB_VERSION+")";
|
||||
|
||||
|
@ -24,6 +24,7 @@ let weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ];
|
|||
let item_fields = [ "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", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "str", "dex", "int", "agi", "def", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "fixID", "category", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd", "id" ];
|
||||
|
||||
let skp_order = ["str","dex","int","def","agi"];
|
||||
let skp_elements = ["e","t","w","f","a"];
|
||||
let skpReqs = skp_order.map(x => x + "Req");
|
||||
|
||||
let equipment_fields = [
|
||||
|
@ -54,7 +55,7 @@ let buildFields = equipment_fields.map(x => "build-"+x);
|
|||
let powderIDs = new Map();
|
||||
let powderNames = new Map();
|
||||
let _powderID = 0;
|
||||
for (const x of ['e', 't', 'w', 'f', 'a']) {
|
||||
for (const x of skp_elements) {
|
||||
for (let i = 1; i <= 6; ++i) {
|
||||
// Support both upper and lowercase, I guess.
|
||||
powderIDs.set(x.toUpperCase()+i, _powderID);
|
||||
|
@ -80,7 +81,7 @@ class Powder {
|
|||
this.defMinus = defMinus;
|
||||
}
|
||||
}
|
||||
function _p(a,b,c,d,e) { return new Powder(a,b,c,d,e); }
|
||||
function _p(a,b,c,d,e) { return new Powder(a,b,c,d,e); } //bruh moment
|
||||
|
||||
let powderStats = [
|
||||
_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),
|
||||
|
@ -96,6 +97,7 @@ for (const it of itemTypes) {
|
|||
itemLists.set(it, []);
|
||||
}
|
||||
let itemMap = new Map();
|
||||
/* Mapping from item names to set names. */
|
||||
let idMap = new Map();
|
||||
|
||||
/*
|
||||
|
@ -124,13 +126,11 @@ function init() {
|
|||
["accessory", "ring", "No Ring 2"],
|
||||
["accessory", "bracelet", "No Bracelet"],
|
||||
["accessory", "necklace", "No Necklace"],
|
||||
["weapon", "wand", "No Weapon"],
|
||||
["weapon", "dagger", "No Weapon"],
|
||||
];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let item = Object();
|
||||
for (const field of item_fields) {
|
||||
item[field] = 0;
|
||||
}
|
||||
item.slots = 0;
|
||||
item.category = noneItems[i][0];
|
||||
item.type = noneItems[i][1];
|
||||
item.name = noneItems[i][2];
|
||||
|
@ -353,12 +353,9 @@ function calculateBuild(save_skp, skp){
|
|||
console.log(equipment);
|
||||
player_build = new Build(106, equipment, powderings);
|
||||
console.log(player_build.toString());
|
||||
displayEquipOrder(document.getElementById("build-order"),player_build.equip_order);
|
||||
|
||||
let equip_order_text = "Equip order: <br>";
|
||||
for (const item of player_build.equip_order) {
|
||||
equip_order_text += item.get("displayName") + "<br>";
|
||||
}
|
||||
setHTML("build-order", equip_order_text);
|
||||
|
||||
|
||||
const assigned = player_build.base_skillpoints;
|
||||
const skillpoints = player_build.total_skillpoints;
|
||||
|
@ -423,10 +420,13 @@ function calculateBuildStats() {
|
|||
}
|
||||
|
||||
displayBuildStats(player_build, "build-overall-stats");
|
||||
displaySetBonuses(player_build, "set-info");
|
||||
|
||||
let parent_elem = document.getElementById("build-melee-stats");
|
||||
let meleeStats = player_build.getMeleeStats();
|
||||
displayMeleeDamage(parent_elem,meleeStats);
|
||||
displayMeleeDamage(document.getElementById("build-melee-stats"), document.getElementById("build-melee-statsAvg"), meleeStats);
|
||||
|
||||
let defenseStats = player_build.getDefenseStats();
|
||||
displayDefenseStats(document.getElementById("build-defense-stats"),defenseStats);
|
||||
|
||||
|
||||
//let defenseStats = "";
|
||||
|
@ -436,7 +436,8 @@ function calculateBuildStats() {
|
|||
let spells = spell_table[player_build.weapon.get("type")];
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
let parent_elem = document.getElementById("spell"+i+"-info");
|
||||
displaySpellDamage(parent_elem, player_build, spells[i], i+1);
|
||||
let overallparent_elem = document.getElementById("spell"+i+"-infoAvg");
|
||||
displaySpellDamage(parent_elem, overallparent_elem, player_build, spells[i], i+1);
|
||||
}
|
||||
|
||||
location.hash = encodeBuild();
|
||||
|
|
15
utils.js
15
utils.js
|
@ -97,3 +97,18 @@ Base64 = (function () {
|
|||
|
||||
// Base64.fromInt(-2147483648); // gives "200000"
|
||||
// Base64.toInt("200000"); // gives -2147483648
|
||||
|
||||
/*
|
||||
Turns a raw stat and a % stat into a final stat on the basis that - raw and >= 100% becomes 0 and + raw and <=-100% becomes 0.
|
||||
Pct would be 0.80 for 80%, -1.20 for 120%, etc
|
||||
*/
|
||||
function rawToPct(raw, pct){
|
||||
final = 0;
|
||||
if (raw < 0){
|
||||
final = (Math.min(0, raw - (raw * pct) ));
|
||||
}else if(raw > 0){
|
||||
final = (Math.max(0, raw + (raw * pct)));
|
||||
}else{ //do nothing - final's already 0
|
||||
}
|
||||
return final;
|
||||
}
|
Loading…
Reference in a new issue