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.
|
/*Turns the input amount of skill points into a float precision percentage.
|
||||||
* @param skp - the integer skillpoint count to be converted
|
* @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 that represents a wynn player's build.
|
||||||
*/
|
*/
|
||||||
class Build{
|
class Build{
|
||||||
|
@ -133,6 +134,7 @@ class Build{
|
||||||
this.base_skillpoints = result[1];
|
this.base_skillpoints = result[1];
|
||||||
this.total_skillpoints = result[2];
|
this.total_skillpoints = result[2];
|
||||||
this.assigned_skillpoints = result[3];
|
this.assigned_skillpoints = result[3];
|
||||||
|
this.activeSetCounts = result[4];
|
||||||
|
|
||||||
// For strength boosts like warscream, vanish, etc.
|
// For strength boosts like warscream, vanish, etc.
|
||||||
this.damageMultiplier = 1.0;
|
this.damageMultiplier = 1.0;
|
||||||
|
@ -150,14 +152,6 @@ class Build{
|
||||||
|
|
||||||
/* Get total health for 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) {
|
getSpellCost(spellIdx, cost) {
|
||||||
cost = Math.ceil(cost * (1 - skillPointsToPercentage(this.total_skillpoints[2])));
|
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]);
|
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.
|
/* 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.
|
@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);
|
statMap.set(id,(statMap.get(id) || 0)+value);
|
||||||
}
|
}
|
||||||
for (const staticID of staticIDs) {
|
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:
|
if item["name"] in item_set_map:
|
||||||
item["set"] = item_set_map[item["name"]]
|
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:
|
with open("id_map.json","w") as id_mapfile:
|
||||||
json.dump(id_map, id_mapfile, indent=2)
|
json.dump(id_map, id_mapfile, indent=2)
|
||||||
with open("clean.json", "w") as outfile:
|
with open("clean.json", "w") as outfile:
|
||||||
|
|
|
@ -3,3 +3,5 @@ Damage calculator checking: https://its0x7.cf/build/
|
||||||
Theme and overall inspiration: Wynndata (Dukio)
|
Theme and overall inspiration: Wynndata (Dukio)
|
||||||
- https://wynndata.tk
|
- https://wynndata.tk
|
||||||
|
|
||||||
|
Additional Contributors:
|
||||||
|
- QuantumNep (Layout code/layout ideas)
|
||||||
|
|
|
@ -99,7 +99,7 @@ const spell_table = {
|
||||||
] },
|
] },
|
||||||
{ title: "Meteor", cost: 8, parts: [
|
{ title: "Meteor", cost: 8, parts: [
|
||||||
{ subtitle: "Blast Damage", type: "damage", multiplier: 500, conversion: [40, 30, 0, 0, 30, 0] },
|
{ 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: [
|
{ title: "Ice Snake", cost: 4, parts: [
|
||||||
{ subtitle: "", type: "damage", multiplier: 70, conversion: [50, 0, 0, 50, 0, 0] },
|
{ 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 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 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" ];
|
let reversedIDs = [ "atkTier", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4" ];
|
||||||
|
|
||||||
function expandItem(item, powders){
|
function expandItem(item, powders){
|
||||||
|
@ -10,24 +10,26 @@ function expandItem(item, powders){
|
||||||
if(item.fixID){ //The item has fixed IDs.
|
if(item.fixID){ //The item has fixed IDs.
|
||||||
expandedItem.set("fixID",true);
|
expandedItem.set("fixID",true);
|
||||||
for (const id of rolledIDs){ //all rolled IDs are numerical
|
for (const id of rolledIDs){ //all rolled IDs are numerical
|
||||||
|
let val = (item[id] || 0);
|
||||||
//if(item[id]) {
|
//if(item[id]) {
|
||||||
minRolls.set(id,item[id]);
|
minRolls.set(id,val);
|
||||||
maxRolls.set(id,item[id]);
|
maxRolls.set(id,val);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}else{ //The item does not have fixed IDs.
|
}else{ //The item does not have fixed IDs.
|
||||||
for (const id of rolledIDs){
|
for (const id of rolledIDs){
|
||||||
if(item[id] > 0){ // positive rolled IDs
|
let val = (item[id] || 0);
|
||||||
minRolls.set(id,idRound(item[id]*0.3));
|
if(val > 0){ // positive rolled IDs
|
||||||
maxRolls.set(id,idRound(item[id]*1.3));
|
minRolls.set(id,idRound(val*0.3));
|
||||||
}else if(item[id] < 0){ //negative rolled IDs
|
maxRolls.set(id,idRound(val*1.3));
|
||||||
|
}else if(val < 0){ //negative rolled IDs
|
||||||
if (reversedIDs.includes(id)) {
|
if (reversedIDs.includes(id)) {
|
||||||
maxRolls.set(id,idRound(item[id]*1.3));
|
maxRolls.set(id,idRound(val*1.3));
|
||||||
minRolls.set(id,idRound(item[id]*0.7));
|
minRolls.set(id,idRound(val*0.7));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
minRolls.set(id,idRound(item[id]*1.3));
|
minRolls.set(id,idRound(val*1.3));
|
||||||
maxRolls.set(id,idRound(item[id]*0.7));
|
maxRolls.set(id,idRound(val*0.7));
|
||||||
}
|
}
|
||||||
}else{//Id = 0
|
}else{//Id = 0
|
||||||
minRolls.set(id,0);
|
minRolls.set(id,0);
|
||||||
|
@ -76,6 +78,38 @@ function apply_elemental_format(p_elem, id, suffix) {
|
||||||
p_elem.appendChild(i_elem2);
|
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){
|
function displayBuildStats(build, parent_id){
|
||||||
// Commands to "script" the creation of nice formatting.
|
// Commands to "script" the creation of nice formatting.
|
||||||
// #commands create a new element.
|
// #commands create a new element.
|
||||||
|
@ -119,7 +153,21 @@ function displayBuildStats(build, parent_id){
|
||||||
setHTML(parent_id, "");
|
setHTML(parent_id, "");
|
||||||
let parent_div = document.getElementById(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;
|
let stats = build.statMap;
|
||||||
|
console.log(build.statMap);
|
||||||
|
|
||||||
let active_elem;
|
let active_elem;
|
||||||
let elemental_format = false;
|
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);
|
let p_elem = displayFixedID(active_elem, id, item.get(id), elemental_format);
|
||||||
if (id === "slots") {
|
if (id === "slots") {
|
||||||
// HACK TO MAKE POWDERS DISPLAY NICE!! TODO
|
// 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]) +
|
p_elem.textContent = idPrefixes[id].concat(item.get(id), idSuffixes[id]) +
|
||||||
" [ " + item.get("powders").map(x => powderNames.get(x)) + " ]";
|
" [ " + 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";
|
let style = "positive";
|
||||||
if (item.get("minRolls").get(id) < 0) {
|
if (item.get("minRolls").get(id) < 0) {
|
||||||
style = "negative";
|
style = "negative";
|
||||||
|
@ -306,11 +361,14 @@ function displayExpandedItem(item, parent_id){
|
||||||
}//Just don't do anything if else
|
}//Just don't do anything if else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let item_desc_elem = document.createElement('p');
|
if (item.get("tier") & item.get("tier") !== " ") {
|
||||||
item_desc_elem.classList.add('itemp');
|
let item_desc_elem = document.createElement('p');
|
||||||
item_desc_elem.classList.add('left');
|
item_desc_elem.classList.add('itemp');
|
||||||
item_desc_elem.textContent = item.get("tier")+" "+item.get("type");
|
item_desc_elem.classList.add('left');
|
||||||
parent_div.append(item_desc_elem);
|
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) {
|
function displayFixedID(active, id, value, elemental_format, style) {
|
||||||
|
@ -351,10 +409,26 @@ function displayFixedID(active, id, value, elemental_format, style) {
|
||||||
return p_elem;
|
return p_elem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function displayMeleeDamage(parent_elem, meleeStats){
|
function displayEquipOrder(parent_elem,buildOrder){
|
||||||
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 = "";
|
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();
|
const stats = meleeStats.slice();
|
||||||
|
|
||||||
for (let i = 0; i < 6; ++i) {
|
for (let i = 0; i < 6; ++i) {
|
||||||
|
@ -373,44 +447,73 @@ function displayMeleeDamage(parent_elem, meleeStats){
|
||||||
|
|
||||||
//title
|
//title
|
||||||
let title_elem = document.createElement("p");
|
let title_elem = document.createElement("p");
|
||||||
title_elem.classList.add("center");
|
title_elem.classList.add("title");
|
||||||
title_elem.textContent = "Melee Stats";
|
title_elem.textContent = "Melee Stats";
|
||||||
parent_elem.append(title_elem);
|
parent_elem.append(title_elem);
|
||||||
parent_elem.append(document.createElement("br"));
|
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
|
//average DPS
|
||||||
let averageDamage = document.createElement("p");
|
let averageDamage = document.createElement("p");
|
||||||
|
|
||||||
averageDamage.classList.add("center");
|
averageDamage.classList.add("center");
|
||||||
|
averageDamage.classList.add("itemp");
|
||||||
averageDamage.textContent = "Average DPS: " + stats[10];
|
averageDamage.textContent = "Average DPS: " + stats[10];
|
||||||
parent_elem.append(averageDamage);
|
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
|
//attack speed
|
||||||
let atkSpd = document.createElement("p");
|
let atkSpd = document.createElement("p");
|
||||||
atkSpd.classList.add("center");
|
atkSpd.classList.add("center");
|
||||||
|
atkSpd.classList.add("itemp");
|
||||||
atkSpd.textContent = "Attack Speed: " + attackSpeeds[stats[11]];
|
atkSpd.textContent = "Attack Speed: " + attackSpeeds[stats[11]];
|
||||||
parent_elem.append(atkSpd);
|
parent_elem.append(atkSpd);
|
||||||
parent_elem.append(document.createElement("br"));
|
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
|
//Non-Crit: n->elem, total dmg, DPS
|
||||||
let nonCritStats = document.createElement("p");
|
let nonCritStats = document.createElement("p");
|
||||||
nonCritStats.classList.add("center");
|
nonCritStats.classList.add("center");
|
||||||
|
nonCritStats.classList.add("itemp");
|
||||||
nonCritStats.textContent = "Non-Crit Stats: ";
|
nonCritStats.textContent = "Non-Crit Stats: ";
|
||||||
nonCritStats.append(document.createElement("br"));
|
nonCritStats.append(document.createElement("br"));
|
||||||
let dmg = document.createElement("p");
|
|
||||||
for (let i = 0; i < 6; i++){
|
for (let i = 0; i < 6; i++){
|
||||||
if(stats[i][0] > 0){
|
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);
|
nonCritStats.append(dmg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let normalDamage = document.createElement("p");
|
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);
|
nonCritStats.append(normalDamage);
|
||||||
|
|
||||||
let normalDPS = document.createElement("p");
|
let normalDPS = document.createElement("p");
|
||||||
normalDPS.textContent = "Normal DPS: " + stats[8];
|
normalDPS.textContent = "Normal DPS: " + stats[8];
|
||||||
normalDPS.append(document.createElement("br"));
|
normalDPS.append(document.createElement("br"));
|
||||||
normalDPS.append(document.createElement("br"));
|
normalDPS.append(document.createElement("br"));
|
||||||
|
normalDPS.classList.add("itemp");
|
||||||
nonCritStats.append(normalDPS);
|
nonCritStats.append(normalDPS);
|
||||||
|
|
||||||
parent_elem.append(nonCritStats);
|
parent_elem.append(nonCritStats);
|
||||||
|
@ -419,45 +522,128 @@ function displayMeleeDamage(parent_elem, meleeStats){
|
||||||
//Crit: n->elem, total dmg, DPS
|
//Crit: n->elem, total dmg, DPS
|
||||||
let critStats = document.createElement("p");
|
let critStats = document.createElement("p");
|
||||||
critStats.classList.add("center");
|
critStats.classList.add("center");
|
||||||
|
critStats.classList.add("itemp");
|
||||||
critStats.textContent = "Crit Stats: ";
|
critStats.textContent = "Crit Stats: ";
|
||||||
critStats.append(document.createElement("br"));
|
critStats.append(document.createElement("br"));
|
||||||
dmg = document.createElement("p");
|
|
||||||
for (let i = 0; i < 6; i++){
|
for (let i = 0; i < 6; i++){
|
||||||
if(stats[i][2] > 0){
|
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);
|
critStats.append(dmg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
normalDamage = document.createElement("p");
|
let critDamage = document.createElement("p");
|
||||||
normalDamage.textContent = "Total Damage: " + stats[7][0] + " - " + stats[7][1];
|
critDamage.textContent = "Total: " + stats[7][0] + "-" + stats[7][1];
|
||||||
critStats.append(normalDamage);
|
critDamage.classList.add("itemp");
|
||||||
|
critStats.append(critDamage);
|
||||||
|
|
||||||
normalDPS = document.createElement("p");
|
let critDPS = document.createElement("p");
|
||||||
normalDPS.textContent = "Crit DPS: " + stats[9];
|
critDPS.textContent = "Crit DPS: " + stats[9];
|
||||||
normalDPS.append(document.createElement("br"));
|
critDPS.classList.add("itemp");
|
||||||
normalDPS.append(document.createElement("br"));
|
critDPS.append(document.createElement("br"));
|
||||||
critStats.append(normalDPS);
|
critDPS.append(document.createElement("br"));
|
||||||
|
critStats.append(critDPS);
|
||||||
|
|
||||||
parent_elem.append(critStats);
|
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"));
|
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 = "";
|
parent_elem.textContent = "";
|
||||||
|
|
||||||
const stats = build.statMap;
|
const stats = build.statMap;
|
||||||
let title_elem = document.createElement("p");
|
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) {
|
if (spellIdx != 0) {
|
||||||
title_elem.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
|
title_elem.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
|
||||||
|
title_elemavg.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
title_elem.textContent = spell.title;
|
title_elem.textContent = spell.title;
|
||||||
|
title_elemavg.textContent = spell.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_elem.append(title_elem);
|
parent_elem.append(title_elem);
|
||||||
|
overallparent_elem.append(title_elemavg);
|
||||||
|
|
||||||
let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
|
let critChance = skillPointsToPercentage(build.total_skillpoints[1]);
|
||||||
|
|
||||||
let save_damages = [];
|
let save_damages = [];
|
||||||
|
@ -467,13 +653,21 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
||||||
let part_div = document.createElement("p");
|
let part_div = document.createElement("p");
|
||||||
parent_elem.append(part_div);
|
parent_elem.append(part_div);
|
||||||
|
|
||||||
|
let part_divavg = document.createElement("p");
|
||||||
|
overallparent_elem.append(part_divavg);
|
||||||
|
|
||||||
let subtitle_elem = document.createElement("p");
|
let subtitle_elem = document.createElement("p");
|
||||||
subtitle_elem.textContent = part.subtitle;
|
subtitle_elem.textContent = part.subtitle;
|
||||||
part_div.append(subtitle_elem);
|
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") {
|
if (part.type === "damage") {
|
||||||
|
|
||||||
let _results = calculateSpellDamage(stats, part.conversion,
|
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);
|
part.multiplier / 100, build.weapon, build.total_skillpoints);
|
||||||
let totalDamNormal = _results[0];
|
let totalDamNormal = _results[0];
|
||||||
let totalDamCrit = _results[1];
|
let totalDamCrit = _results[1];
|
||||||
|
@ -492,12 +686,17 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
||||||
averageLabel.classList.add("damageSubtitle");
|
averageLabel.classList.add("damageSubtitle");
|
||||||
part_div.append(averageLabel);
|
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");
|
let nonCritLabel = document.createElement("p");
|
||||||
nonCritLabel.textContent = "Non-Crit Average: "+nonCritAverage.toFixed(2);
|
nonCritLabel.textContent = "Non-Crit Average: "+nonCritAverage.toFixed(2);
|
||||||
nonCritLabel.classList.add("damageSubtitle");
|
nonCritLabel.classList.add("damageSubtitle");
|
||||||
part_div.append(nonCritLabel);
|
part_div.append(nonCritLabel);
|
||||||
|
|
||||||
let damageClasses = ["Neutral","Earth","Thunder","Water","Fire","Air"];
|
|
||||||
for (let i = 0; i < 6; i++){
|
for (let i = 0; i < 6; i++){
|
||||||
if (results[i][1] > 0){
|
if (results[i][1] > 0){
|
||||||
let p = document.createElement("p");
|
let p = document.createElement("p");
|
||||||
|
@ -525,11 +724,17 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
||||||
save_damages.push(averageDamage);
|
save_damages.push(averageDamage);
|
||||||
}
|
}
|
||||||
else if (part.type == "heal") {
|
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");
|
let healLabel = document.createElement("p");
|
||||||
healLabel.textContent = heal_amount;
|
healLabel.textContent = heal_amount;
|
||||||
healLabel.classList.add("damagep");
|
healLabel.classList.add("damagep");
|
||||||
part_div.append(healLabel);
|
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") {
|
else if (part.type === "total") {
|
||||||
let total_damage = 0;
|
let total_damage = 0;
|
||||||
|
@ -540,6 +745,12 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
|
||||||
averageLabel.textContent = "Average: "+total_damage.toFixed(2);
|
averageLabel.textContent = "Average: "+total_damage.toFixed(2);
|
||||||
averageLabel.classList.add("damageSubtitle");
|
averageLabel.classList.add("damageSubtitle");
|
||||||
part_div.append(averageLabel);
|
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>
|
<a href="credits.txt" class="link">Additional credits</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="equipment">
|
<div class="equipment">
|
||||||
<div class="right" style="grid-column:1;grid-row:1">
|
<div class="left" style="grid-column:1/span 2;grid-row:1">
|
||||||
<label>Equipments</label>
|
<table>
|
||||||
<br>
|
<tr>
|
||||||
<br>
|
<th class="right">
|
||||||
<div>
|
<label>Equipments</label>
|
||||||
<label for="helmet-choice">Helmet:</label>
|
</th>
|
||||||
<input list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/>
|
<th>
|
||||||
<datalist id="helmet-items">
|
<label>Powdering</label>
|
||||||
</datalist>
|
</th>
|
||||||
</div>
|
</tr>
|
||||||
<br>
|
<tr>
|
||||||
<div>
|
<td class="right">
|
||||||
<label for="chestplate-choice">Chestplate:</label>
|
<br/>
|
||||||
<input list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate"/>
|
<label for="helmet-choice">Helmet:</label>
|
||||||
<datalist id="chestplate-items">
|
<input list="helmet-items" id="helmet-choice" name="helmet-choice" placeholder="No Helmet"/>
|
||||||
</datalist>
|
<datalist id="helmet-items">
|
||||||
</div>
|
</datalist>
|
||||||
<br>
|
</td>
|
||||||
<div>
|
<td>
|
||||||
<label for="leggings-choice">Leggings:</label>
|
<div id="helmet-slots">
|
||||||
<input list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings"/>
|
X slots
|
||||||
<datalist id="leggings-items">
|
</div>
|
||||||
</datalist>
|
<div>
|
||||||
</div>
|
<input type="text" id="helmet-powder" name="helmet-powder"/>
|
||||||
<br>
|
</div>
|
||||||
<div id="boots">
|
</td>
|
||||||
<label for="boots-choice">Boots:</label>
|
</tr>
|
||||||
<input list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots"/>
|
<tr>
|
||||||
<datalist id="boots-items">
|
<td class="right">
|
||||||
</datalist>
|
<br/>
|
||||||
</div>
|
<label for="chestplate-choice">Chestplate:</label>
|
||||||
<br>
|
<input list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate" />
|
||||||
<div>
|
<datalist id="chestplate-items">
|
||||||
<label for="ring1-choice">Ring 1:</label>
|
</datalist>
|
||||||
<input list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/>
|
</td>
|
||||||
<datalist id="ring1-items">
|
<td>
|
||||||
</datalist>
|
<div id="chestplate-slots">
|
||||||
</div>
|
X slots
|
||||||
<br>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="ring2-choice">Ring 2:</label>
|
<input type="text" id="chestplate-powder" name="chestplate-powder" />
|
||||||
<input list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2"/>
|
</div>
|
||||||
<datalist id="ring2-items">
|
</td>
|
||||||
</datalist>
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
<br>
|
<td class="right">
|
||||||
<div>
|
<br/>
|
||||||
<label for="bracelet-choice">Bracelet:</label>
|
<label for="leggings-choice">Leggings:</label>
|
||||||
<input list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet"/>
|
<input list="leggings-items" id="leggings-choice" name="leggings-choice" placeholder="No Leggings" />
|
||||||
<datalist id="bracelet-items">
|
<datalist id="leggings-items">
|
||||||
</datalist>
|
</datalist>
|
||||||
</div>
|
</td>
|
||||||
<br>
|
<td>
|
||||||
<div>
|
<div id="leggings-slots">
|
||||||
<label for="necklace-choice">Necklace:</label>
|
X slots
|
||||||
<input list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/>
|
</div>
|
||||||
<datalist id="necklace-items">
|
<div>
|
||||||
</datalist>
|
<input type="text" id="leggings-powder" name="leggings-powder" />
|
||||||
</div>
|
</div>
|
||||||
<br>
|
</td>
|
||||||
<div>
|
</tr>
|
||||||
<label for="weapon-choice">Weapon:</label>
|
<tr>
|
||||||
<input list="weapon-items" id="weapon-choice" name="weapon-choice" value=""/>
|
<td class="right">
|
||||||
<datalist id="weapon-items">
|
<br/>
|
||||||
</datalist>
|
<label for="boots-choice">Boots:</label>
|
||||||
</div>
|
<input list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots" />
|
||||||
<br>
|
<datalist id="boots-items">
|
||||||
<div>
|
</datalist>
|
||||||
<button class = "button" id = "calc-button" onclick = "calculateBuild()">
|
</td>
|
||||||
Update Items (Resets stats)
|
<td>
|
||||||
</button>
|
<div id="boots-slots">
|
||||||
</div>
|
X slots
|
||||||
</div>
|
</div>
|
||||||
<div class="left" style="grid-column:2;grid-row:1">
|
<div style="grid-column:1;grid-row:4">
|
||||||
<label>Powdering:</label>
|
<input type="text" id="boots-powder" name="boots-powder"/>
|
||||||
<div id="helmet-slots">
|
</div>
|
||||||
X slots
|
</td>
|
||||||
</div>
|
</tr>
|
||||||
<div>
|
<tr>
|
||||||
<input type="text" id="helmet-powder" name="helmet-powder" />
|
<td class="right">
|
||||||
</div>
|
<br/>
|
||||||
<div id="chestplate-slots">
|
<label for="ring1-choice">Ring 1:</label>
|
||||||
X slots
|
<input list="ring1-items" id="ring1-choice" name="ring1-choice" placeholder="No Ring 1"/>
|
||||||
</div>
|
<datalist id="ring1-items">
|
||||||
<div>
|
</datalist>
|
||||||
<input type="text" id="chestplate-powder" name="chestplate-powder" />
|
</td>
|
||||||
</div>
|
</tr>
|
||||||
<div id="leggings-slots">
|
<tr>
|
||||||
X slots
|
<td class="right">
|
||||||
</div>
|
<br/>
|
||||||
<div>
|
<label for="ring2-choice">Ring 2:</label>
|
||||||
<input type="text" id="leggings-powder" name="leggings-powder" />
|
<input list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2" />
|
||||||
</div>
|
<datalist id="ring2-items">
|
||||||
<div id="boots-slots">
|
</datalist>
|
||||||
X slots
|
</td>
|
||||||
</div>
|
</tr>
|
||||||
<div>
|
<tr>
|
||||||
<input type="text" id="boots-powder" name="boots-powder" />
|
<td class="right">
|
||||||
</div>
|
<br/>
|
||||||
<br/><br/><br/><br/><br/><br/><br/><br/>
|
<label for="bracelet-choice">Bracelet:</label>
|
||||||
<div id="weapon-slots">
|
<input list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet" />
|
||||||
X slots
|
<datalist id="bracelet-items">
|
||||||
</div>
|
</datalist>
|
||||||
<div>
|
</td>
|
||||||
<input type="text" id="weapon-powder" name="weapon-powder" />
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
<br>
|
<td class="right">
|
||||||
<div>
|
<br/>
|
||||||
<button class = "reset" id = "reset-button" onclick = "resetFields()">
|
<label for="necklace-choice">Necklace:</label>
|
||||||
Reset
|
<input list="necklace-items" id="necklace-choice" name="necklace-choice" placeholder="No Necklace"/>
|
||||||
</button>
|
<datalist id="necklace-items">
|
||||||
</div>
|
</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>
|
||||||
<div class="center" style="grid-column:3;grid-row:1">
|
<div class="center" style="grid-column:3;grid-row:1">
|
||||||
<div class = "center build-overall" id = "build-overall">
|
<div class = "center build-overall" id = "build-overall">
|
||||||
|
@ -141,6 +175,23 @@
|
||||||
<div class = "center" id = "build-overall-stats"></div>
|
<div class = "center" id = "build-overall-stats"></div>
|
||||||
</div>
|
</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>
|
||||||
<div class="center" id="summary-box">
|
<div class="center" id="summary-box">
|
||||||
Summary:
|
Summary:
|
||||||
|
@ -250,16 +301,12 @@
|
||||||
<div class = "center build-weapon" id = "build-weapon" style = "grid-column:1;grid-row:3">
|
<div class = "center build-weapon" id = "build-weapon" style = "grid-column:1;grid-row:3">
|
||||||
<div class = "center" id = "build-weapon-stats"></div>
|
<div class = "center" id = "build-weapon-stats"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class = "center build-overall" id = "build-overall" style = "grid-column:4;grid-row:3">
|
<div class = "center build-order" id = "build-order" style = "grid-column:2;grid-row:3">
|
||||||
<p class="itemcenter">Overall Build Stats:<p>
|
|
||||||
<div class = "center" id = "build-overall-stats"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class = "center build-melee-stats" id = "build-melee-stats" style = "grid-column:3;grid-row:3">
|
<div class = "center build-melee-stats" id = "build-melee-stats" style = "grid-column:3;grid-row:3">
|
||||||
</div>
|
</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>
|
||||||
<!--div class = "center" id = "build-defense-stats" style = "grid-column:4;grid-row:3">
|
|
||||||
</div-->
|
|
||||||
</div>
|
</div>
|
||||||
<div class = "spells">
|
<div class = "spells">
|
||||||
<div class = "center spell-info" id = "spell0" style = "grid-column:1;grid-row:1">
|
<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 class = "center" id = "spell3-info">Spell 4</div>
|
||||||
</div>
|
</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="utils.js"></script>
|
||||||
<script type="text/javascript" src="skillpoints.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
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
|
|
|
@ -69,93 +69,153 @@ for item in build_items:
|
||||||
setup(item)
|
setup(item)
|
||||||
if all(x == 0 for x in item["reqs"]):
|
if all(x == 0 for x in item["reqs"]):
|
||||||
fixed.append(item)
|
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)
|
noboost.append(item)
|
||||||
else:
|
else:
|
||||||
consider.append(item)
|
consider.append(item)
|
||||||
setup(build_weapon)
|
setup(build_weapon)
|
||||||
fixed = tuple(fixed)
|
fixed = tuple(fixed)
|
||||||
noboost = tuple(noboost)
|
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.
|
# 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):
|
for i in range(5):
|
||||||
skillpoints[i] += item["skillpoints"][i]
|
skillpoints[i] += item["skillpoints"][i]
|
||||||
|
|
||||||
def remove_skillpoints(skillpoints, item):
|
if item["set"] is not None:
|
||||||
for i in range(5):
|
setName = item["set"]
|
||||||
skillpoints[i] -= item["skillpoints"][i]
|
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.
|
# Figure out (naively) how many skillpoints need to be applied to get the current item to fit.
|
||||||
# Doesn't handle -skp.
|
# 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]
|
applied = [0, 0, 0, 0, 0]
|
||||||
total = 0
|
total = 0
|
||||||
for i, req, cur in zip(range(5), item["reqs"], skillpoints):
|
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):
|
if (item["reqs"][i] == 0):
|
||||||
continue
|
continue
|
||||||
|
skillpoint_filter[i] = True
|
||||||
if req > cur:
|
if req > cur:
|
||||||
diff = req - cur
|
diff = req - cur
|
||||||
applied[i] += diff
|
applied[i] += diff
|
||||||
total += 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
|
return applied, total
|
||||||
|
|
||||||
# Permutations in js reference (also cool algorithm):
|
# Permutations in js reference (also cool algorithm):
|
||||||
# https://stackoverflow.com/a/41068709
|
# https://stackoverflow.com/a/41068709
|
||||||
|
|
||||||
static_skillpoints_base = [0, 0, 0, 0, 0]
|
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.
|
# Separate out the no req items and add them to the static skillpoint base.
|
||||||
for item in fixed:
|
for item in fixed:
|
||||||
apply_skillpoints(static_skillpoints_base, item)
|
apply_skillpoints(static_skillpoints_base, item, static_activeSetCounts)
|
||||||
|
|
||||||
best = None
|
best = consider + noboost;
|
||||||
final_skillpoints = None
|
final_skillpoints = static_skillpoints_base[:]
|
||||||
best_skillpoints = [0, 0, 0, 0, 0]
|
best_skillpoints = [0, 0, 0, 0, 0]
|
||||||
best_total = math.inf
|
best_total = math.inf
|
||||||
|
best_activeSetCounts = dict()
|
||||||
|
|
||||||
# Try every combination and pick the best one.
|
allFalse = [False] * 5
|
||||||
import itertools
|
|
||||||
for permutation in itertools.permutations(consider):
|
|
||||||
|
|
||||||
permutation += noboost
|
if len(consider) or len(noboost):
|
||||||
|
|
||||||
skillpoints_applied = [0, 0, 0, 0, 0]
|
# Try every combination and pick the best one.
|
||||||
skillpoints = copy.copy(static_skillpoints_base)
|
import itertools
|
||||||
total_applied = 0
|
for permutation in itertools.permutations(consider):
|
||||||
for item in permutation:
|
activeSetCounts = dict(best_activeSetCounts)
|
||||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item)
|
has_skillpoint = allFalse[:]
|
||||||
for i in range(5):
|
|
||||||
skillpoints_applied[i] += needed_skillpoints[i]
|
permutation += noboost
|
||||||
skillpoints[i] += needed_skillpoints[i]
|
|
||||||
apply_skillpoints(skillpoints, item)
|
skillpoints_applied = [0, 0, 0, 0, 0]
|
||||||
total_applied += total_diff
|
skillpoints = static_skillpoints_base[:]
|
||||||
if total_applied >= best_total:
|
total_applied = 0
|
||||||
break
|
|
||||||
if total_applied < best_total:
|
|
||||||
for item in permutation:
|
for item in permutation:
|
||||||
remove_skillpoints(skillpoints, item)
|
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item, has_skillpoint, activeSetCounts)
|
||||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, item)
|
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
skillpoints_applied[i] += needed_skillpoints[i]
|
skillpoints_applied[i] += needed_skillpoints[i]
|
||||||
skillpoints[i] += needed_skillpoints[i]
|
skillpoints[i] += needed_skillpoints[i]
|
||||||
apply_skillpoints(skillpoints, item)
|
apply_skillpoints(skillpoints, item, activeSetCounts)
|
||||||
total_applied += total_diff
|
total_applied += total_diff
|
||||||
if total_applied >= best_total:
|
if total_applied >= best_total:
|
||||||
break
|
break
|
||||||
|
|
||||||
needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon)
|
needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon, has_skillpoint, activeSetCounts)
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
skillpoints_applied[i] += needed_skillpoints[i]
|
skillpoints_applied[i] += needed_skillpoints[i]
|
||||||
skillpoints[i] += needed_skillpoints[i]
|
skillpoints[i] += needed_skillpoints[i]
|
||||||
apply_skillpoints(skillpoints, build_weapon)
|
apply_skillpoints(skillpoints, build_weapon, activeSetCounts)
|
||||||
total_applied += total_diff
|
total_applied += total_diff
|
||||||
|
|
||||||
if total_applied < best_total:
|
if total_applied < best_total:
|
||||||
best = permutation
|
best = permutation
|
||||||
final_skillpoints = skillpoints
|
final_skillpoints = skillpoints
|
||||||
best_skillpoints = skillpoints_applied
|
best_skillpoints = skillpoints_applied
|
||||||
best_total = total_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([i["displayName"] for i in fixed + best])
|
||||||
print(best_skillpoints)
|
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)) {
|
if (item.get("reqs").every(x => x === 0)) {
|
||||||
fixed.push(item);
|
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);
|
noboost.push(item);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
consider.push(item);
|
consider.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function apply_skillpoints(skillpoints, item) {
|
function apply_skillpoints(skillpoints, item, activeSetCounts) {
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
skillpoints[i] += item.get("skillpoints")[i];
|
skillpoints[i] += item.get("skillpoints")[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function remove_skillpoints(skillpoints, item) {
|
const setName = item.get("set");
|
||||||
for (let i = 0; i < 5; i++) {
|
if (setName) { // undefined/null means no set.
|
||||||
skillpoints[i] -= item.get("skillpoints")[i];
|
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.
|
function apply_to_fit(skillpoints, item, skillpoint_filter, activeSetCounts) {
|
||||||
// Doesn't handle -skp.
|
|
||||||
function apply_to_fit(skillpoints, item, skillpoint_filter) {
|
|
||||||
let applied = [0, 0, 0, 0, 0];
|
let applied = [0, 0, 0, 0, 0];
|
||||||
let total = 0;
|
let total = 0;
|
||||||
for (let i = 0; i < 5; i++) {
|
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];
|
applied[i] -= item.get("skillpoints")[i];
|
||||||
total -= item.get("skillpoints")[i];
|
total -= item.get("skillpoints")[i];
|
||||||
}
|
}
|
||||||
|
@ -49,24 +62,46 @@ function calculate_skillpoints(equipment, weapon) {
|
||||||
total += diff;
|
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];
|
return [applied, total];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separate out the no req items and add them to the static skillpoint base.
|
// 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_skillpoints_base = [0, 0, 0, 0, 0]
|
||||||
|
let static_activeSetCounts = new Map()
|
||||||
for (const item of fixed) {
|
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 best = consider.concat(noboost);
|
||||||
let final_skillpoints = static_skillpoints_base.slice();
|
let final_skillpoints = static_skillpoints_base.slice();
|
||||||
let best_skillpoints = [0, 0, 0, 0, 0];
|
let best_skillpoints = [0, 0, 0, 0, 0];
|
||||||
let best_total = Infinity;
|
let best_total = Infinity;
|
||||||
|
let best_activeSetCounts = static_activeSetCounts;
|
||||||
|
|
||||||
let allFalse = [false, false, false, false, false];
|
let allFalse = [false, false, false, false, false];
|
||||||
if (consider.length > 0 || noboost.length > 0) {
|
if (consider.length > 0 || noboost.length > 0) {
|
||||||
// Try every combination and pick the best one.
|
// Try every combination and pick the best one.
|
||||||
for (let permutation of perm(consider)) {
|
for (let permutation of perm(consider)) {
|
||||||
|
let activeSetCounts = new Map(static_activeSetCounts);
|
||||||
|
|
||||||
let has_skillpoint = allFalse.slice();
|
let has_skillpoint = allFalse.slice();
|
||||||
|
|
||||||
permutation = permutation.concat(noboost);
|
permutation = permutation.concat(noboost);
|
||||||
|
@ -81,7 +116,7 @@ function calculate_skillpoints(equipment, weapon) {
|
||||||
let needed_skillpoints;
|
let needed_skillpoints;
|
||||||
let total_diff;
|
let total_diff;
|
||||||
for (const item of permutation) {
|
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];
|
needed_skillpoints = result[0];
|
||||||
total_diff = result[1];
|
total_diff = result[1];
|
||||||
|
|
||||||
|
@ -89,40 +124,14 @@ function calculate_skillpoints(equipment, weapon) {
|
||||||
skillpoints_applied[i] += needed_skillpoints[i];
|
skillpoints_applied[i] += needed_skillpoints[i];
|
||||||
skillpoints[i] += needed_skillpoints[i];
|
skillpoints[i] += needed_skillpoints[i];
|
||||||
}
|
}
|
||||||
apply_skillpoints(skillpoints, item);
|
apply_skillpoints(skillpoints, item, activeSetCounts);
|
||||||
total_applied += total_diff;
|
total_applied += total_diff;
|
||||||
if (total_applied >= best_total) {
|
if (total_applied >= best_total) {
|
||||||
break;
|
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();
|
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];
|
needed_skillpoints = result[0];
|
||||||
total_diff = result[1];
|
total_diff = result[1];
|
||||||
for (let i = 0; i < 5; ++i) {
|
for (let i = 0; i < 5; ++i) {
|
||||||
|
@ -130,32 +139,31 @@ function calculate_skillpoints(equipment, weapon) {
|
||||||
skillpoints[i] += needed_skillpoints[i];
|
skillpoints[i] += needed_skillpoints[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_skillpoints(skillpoints, weapon);
|
apply_skillpoints(skillpoints, weapon, activeSetCounts);
|
||||||
total_applied += total_diff;
|
total_applied += total_diff;
|
||||||
|
|
||||||
if (total_applied < best_total) {
|
if (total_applied < best_total) {
|
||||||
console.log(pre);
|
|
||||||
console.log(skillpoints);
|
|
||||||
best = permutation;
|
best = permutation;
|
||||||
final_skillpoints = skillpoints;
|
final_skillpoints = skillpoints;
|
||||||
best_skillpoints = skillpoints_applied;
|
best_skillpoints = skillpoints_applied;
|
||||||
best_total = total_applied;
|
best_total = total_applied;
|
||||||
|
best_activeSetCounts = activeSetCounts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
best_total = 0;
|
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];
|
needed_skillpoints = result[0];
|
||||||
total_diff = result[1];
|
total_diff = result[1];
|
||||||
for (let i = 0; i < 5; ++i) {
|
for (let i = 0; i < 5; ++i) {
|
||||||
best_skillpoints[i] += needed_skillpoints[i];
|
best_skillpoints[i] += needed_skillpoints[i];
|
||||||
final_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;
|
best_total += total_diff;
|
||||||
}
|
}
|
||||||
let equip_order = fixed.concat(best);
|
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;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.equipment {
|
.equipment {
|
||||||
padding: 4%;
|
padding: 4%;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -24,7 +28,7 @@
|
||||||
grid-auto-rows: minmax(60px, auto);
|
grid-auto-rows: minmax(60px, auto);
|
||||||
}
|
}
|
||||||
.equipment, .skillpoints, .center, .header, .all{
|
.equipment, .skillpoints, .center, .header, .all{
|
||||||
background: #110110;
|
background: #121516;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
.hppeng{
|
.hppeng{
|
||||||
|
@ -36,6 +40,10 @@
|
||||||
a.link{
|
a.link{
|
||||||
color: #A5FDFF;
|
color: #A5FDFF;
|
||||||
}
|
}
|
||||||
|
.title{
|
||||||
|
text-align: center;
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
.center {
|
.center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -45,25 +53,27 @@ a.link{
|
||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
|
margin: 2px 2%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.build, .spells {
|
.build, .spells, .misc {
|
||||||
padding: 2%;
|
padding: 2%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
grid-auto-rows: minmax(60px, auto);
|
grid-auto-rows: minmax(60px, auto);
|
||||||
width: 94%;
|
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;
|
color: #aaa;
|
||||||
background: #110110;
|
background: #121516;
|
||||||
border: 3px solid #BCBCBC;
|
border: 3px solid #BCBCBC;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
width: 96%;
|
width: 96%;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemcenter {
|
.itemcenter {
|
||||||
|
@ -172,20 +182,68 @@ a.link{
|
||||||
width: 10px;
|
width: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Track */
|
/* Track */
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
box-shadow: inset 0 0 5px #BCBCBC;
|
box-shadow: inset 0 0 5px #BCBCBC;
|
||||||
border: #BCBCBC;
|
border: #BCBCBC;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle */
|
/* Handle */
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ugly Corner */
|
/* Ugly Corner */
|
||||||
::-webkit-scrollbar-corner{
|
::-webkit-scrollbar-corner{
|
||||||
background: #110110;
|
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
|
* 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+")";
|
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 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_order = ["str","dex","int","def","agi"];
|
||||||
|
let skp_elements = ["e","t","w","f","a"];
|
||||||
let skpReqs = skp_order.map(x => x + "Req");
|
let skpReqs = skp_order.map(x => x + "Req");
|
||||||
|
|
||||||
let equipment_fields = [
|
let equipment_fields = [
|
||||||
|
@ -54,7 +55,7 @@ let buildFields = equipment_fields.map(x => "build-"+x);
|
||||||
let powderIDs = new Map();
|
let powderIDs = new Map();
|
||||||
let powderNames = new Map();
|
let powderNames = new Map();
|
||||||
let _powderID = 0;
|
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) {
|
for (let i = 1; i <= 6; ++i) {
|
||||||
// Support both upper and lowercase, I guess.
|
// Support both upper and lowercase, I guess.
|
||||||
powderIDs.set(x.toUpperCase()+i, _powderID);
|
powderIDs.set(x.toUpperCase()+i, _powderID);
|
||||||
|
@ -80,7 +81,7 @@ class Powder {
|
||||||
this.defMinus = defMinus;
|
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 = [
|
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),
|
_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, []);
|
itemLists.set(it, []);
|
||||||
}
|
}
|
||||||
let itemMap = new Map();
|
let itemMap = new Map();
|
||||||
|
/* Mapping from item names to set names. */
|
||||||
let idMap = new Map();
|
let idMap = new Map();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -124,13 +126,11 @@ function init() {
|
||||||
["accessory", "ring", "No Ring 2"],
|
["accessory", "ring", "No Ring 2"],
|
||||||
["accessory", "bracelet", "No Bracelet"],
|
["accessory", "bracelet", "No Bracelet"],
|
||||||
["accessory", "necklace", "No Necklace"],
|
["accessory", "necklace", "No Necklace"],
|
||||||
["weapon", "wand", "No Weapon"],
|
["weapon", "dagger", "No Weapon"],
|
||||||
];
|
];
|
||||||
for (let i = 0; i < 9; i++) {
|
for (let i = 0; i < 9; i++) {
|
||||||
let item = Object();
|
let item = Object();
|
||||||
for (const field of item_fields) {
|
item.slots = 0;
|
||||||
item[field] = 0;
|
|
||||||
}
|
|
||||||
item.category = noneItems[i][0];
|
item.category = noneItems[i][0];
|
||||||
item.type = noneItems[i][1];
|
item.type = noneItems[i][1];
|
||||||
item.name = noneItems[i][2];
|
item.name = noneItems[i][2];
|
||||||
|
@ -353,12 +353,9 @@ function calculateBuild(save_skp, skp){
|
||||||
console.log(equipment);
|
console.log(equipment);
|
||||||
player_build = new Build(106, equipment, powderings);
|
player_build = new Build(106, equipment, powderings);
|
||||||
console.log(player_build.toString());
|
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 assigned = player_build.base_skillpoints;
|
||||||
const skillpoints = player_build.total_skillpoints;
|
const skillpoints = player_build.total_skillpoints;
|
||||||
|
@ -423,10 +420,13 @@ function calculateBuildStats() {
|
||||||
}
|
}
|
||||||
|
|
||||||
displayBuildStats(player_build, "build-overall-stats");
|
displayBuildStats(player_build, "build-overall-stats");
|
||||||
|
displaySetBonuses(player_build, "set-info");
|
||||||
|
|
||||||
let parent_elem = document.getElementById("build-melee-stats");
|
|
||||||
let meleeStats = player_build.getMeleeStats();
|
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 = "";
|
//let defenseStats = "";
|
||||||
|
@ -436,7 +436,8 @@ function calculateBuildStats() {
|
||||||
let spells = spell_table[player_build.weapon.get("type")];
|
let spells = spell_table[player_build.weapon.get("type")];
|
||||||
for (let i = 0; i < 4; ++i) {
|
for (let i = 0; i < 4; ++i) {
|
||||||
let parent_elem = document.getElementById("spell"+i+"-info");
|
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();
|
location.hash = encodeBuild();
|
||||||
|
|
15
utils.js
15
utils.js
|
@ -97,3 +97,18 @@ Base64 = (function () {
|
||||||
|
|
||||||
// Base64.fromInt(-2147483648); // gives "200000"
|
// Base64.fromInt(-2147483648); // gives "200000"
|
||||||
// Base64.toInt("200000"); // gives -2147483648
|
// 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