visual things + defense Stats

This commit is contained in:
ferricles 2021-01-10 02:02:23 -08:00
parent 50afcc753a
commit 7ebcbaaf91
6 changed files with 252 additions and 60 deletions

View file

@ -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{
@ -151,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])));
@ -195,10 +188,45 @@ class Build{
let critDPS = (totalDamCrit[0]+totalDamCrit[1])/2 * baseDamageMultiplier[adjAtkSpd];
let avgDPS = (normDPS * (1 - skillPointsToPercentage(dex))) + (critDPS * (skillPointsToPercentage(dex)));
//console.log([nDamAdj,eDamAdj,tDamAdj,wDamAdj,fDamAdj,aDamAdj,totalDamNorm,totalDamCrit,normDPS,critDPS,avgDPS]);
console.log(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");
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.
*/

View file

@ -310,8 +310,12 @@ 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");
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
@ -355,6 +359,7 @@ function displayExpandedItem(item, parent_id){
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);
}
@ -398,6 +403,21 @@ function displayFixedID(active, id, value, elemental_format, style) {
return p_elem;
}
}
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, 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: "];
@ -420,7 +440,7 @@ 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"));
@ -428,12 +448,14 @@ function displayMeleeDamage(parent_elem, meleeStats){
//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);
//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"));
@ -441,6 +463,7 @@ function displayMeleeDamage(parent_elem, meleeStats){
//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"));
for (let i = 0; i < 6; i++){
@ -448,17 +471,20 @@ function displayMeleeDamage(parent_elem, meleeStats){
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);
@ -467,6 +493,7 @@ 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"));
for (let i = 0; i < 6; i++){
@ -474,22 +501,94 @@ function displayMeleeDamage(parent_elem, meleeStats){
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);
}
@ -498,7 +597,7 @@ function displaySpellDamage(parent_elem, build, spell, spellIdx) {
const stats = build.statMap;
let title_elem = document.createElement("p");
title_elem.classList.add('center');
title_elem.classList.add('title');
if (spellIdx != 0) {
title_elem.textContent = spell.title + " (" + build.getSpellCost(spellIdx, spell.cost) + ")";
}

View file

@ -35,21 +35,21 @@
<br>
<div>
<label for="chestplate-choice">Chestplate:</label>
<input list="chestplate-items" id="chestplate-choice" name="chestplate-choice" placeholder="No Chestplate"/>
<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"/>
<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"/>
<input list="boots-items" id="boots-choice" name="boots-choice" placeholder="No Boots" />
<datalist id="boots-items">
</datalist>
</div>
@ -63,14 +63,14 @@
<br>
<div>
<label for="ring2-choice">Ring 2:</label>
<input list="ring2-items" id="ring2-choice" name="ring2-choice" placeholder="No Ring 2"/>
<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"/>
<input list="bracelet-items" id="bracelet-choice" name="bracelet-choice" placeholder="No Bracelet" />
<datalist id="bracelet-items">
</datalist>
</div>
@ -101,7 +101,7 @@
X slots
</div>
<div>
<input type="text" id="helmet-powder" name="helmet-powder" />
<input type="text" id="helmet-powder" name="helmet-powder"/>
</div>
<div id="chestplate-slots">
X slots
@ -118,8 +118,8 @@
<div id="boots-slots">
X slots
</div>
<div>
<input type="text" id="boots-powder" name="boots-powder" />
<div style="grid-column:1;grid-row:4">
<input type="text" id="boots-powder" name="boots-powder"/>
</div>
<br/><br/><br/><br/><br/><br/><br/><br/>
<div id="weapon-slots">
@ -250,11 +250,11 @@
<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-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>
<div class = "center" id = "build-defense-stats" style = "grid-column:4;grid-row:3">
<div class = "center build-melee-stats" id = "build-melee-stats" style = "grid-column:3;grid-row:3">
</div>
<div class = "center build-defense-stats" id = "build-defense-stats" style = "grid-column:4;grid-row:3">
</div>
</div>
<div class = "spells">

View file

@ -24,7 +24,7 @@
grid-auto-rows: minmax(60px, auto);
}
.equipment, .skillpoints, .center, .header, .all{
background: #110110;
background: #121516;
color: #aaa;
}
.hppeng{
@ -36,6 +36,10 @@
a.link{
color: #A5FDFF;
}
.title{
text-align: center;
font-size: 150%;
}
.center {
text-align: center;
}
@ -45,6 +49,7 @@ a.link{
}
.left {
margin: 2px 2%;
text-align: left;
}
@ -55,12 +60,12 @@ a.link{
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, .set-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%;
@ -172,20 +177,65 @@ 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;
}
/* 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
}

18
test.js
View file

@ -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);
@ -125,7 +126,7 @@ 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();
@ -354,12 +355,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;
@ -426,9 +424,11 @@ 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") ,meleeStats);
let defenseStats = player_build.getDefenseStats();
displayDefenseStats(document.getElementById("build-defense-stats"),defenseStats);
//let defenseStats = "";

View file

@ -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;
}