Last active
February 11, 2023 15:20
-
-
Save ccjmne/3d9586e936732555df9052703d0110d0 to your computer and use it in GitHub Desktop.
BDO Enhancement Cost Calculator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>PEN: Kzarka Longsword • Enhancement Cost</title> | |
</head> | |
<body> | |
<style type="text/css"> | |
html, | |
body { | |
width: 100%; | |
height: 100%; | |
} | |
body { | |
margin: 0; | |
background-color: #333; | |
color: #ddd; | |
font-family: sans-serif; | |
display: flex; | |
gap: 30px; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
} | |
h1, | |
h2 { | |
margin: 0; | |
} | |
h2 { | |
font-weight: lighter; | |
} | |
main { | |
display: grid; | |
grid-template-columns: 1fr auto 1fr; | |
grid-gap: 10px 20px; | |
align-items: center; | |
} | |
footer { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
} | |
main>div { | |
background-color: #222; | |
} | |
#valks { | |
display: grid; | |
grid-gap: 0 5px; | |
} | |
#valks>:not(button) { | |
padding: 2px; | |
background-color: #222; | |
border-radius: 5px 5px 0 0; | |
text-align: center; | |
} | |
#valks+* { | |
margin-top: -20px; | |
} | |
button { | |
padding: 10px; | |
} | |
.align-right { | |
text-align: right; | |
} | |
.align-center { | |
text-align: center; | |
} | |
.left { | |
border-radius: 5px 0 0 5px; | |
padding-left: 20px; | |
} | |
.left>button { | |
margin-left: 20px; | |
} | |
.right { | |
border-radius: 0 5px 5px 0; | |
padding-right: 20px; | |
} | |
.right>button { | |
margin-right: 20px; | |
} | |
.lighter { | |
color: #888; | |
} | |
</style> | |
<h1>TET: Blackstar Longsword<span class="lighter"> • </span>Enhancement Cost</h1> | |
<div id="valks"></div> | |
<div> | |
<input type="checkbox" id="freeValks" name="freeValks"> | |
<label for="freeValks"><span class="lighter">Consider</span> Advices of Valks <span class="lighter">to be</span> free</label> | |
</div> | |
<main> | |
<div class="left align-right"> | |
<span>failures: </span> | |
<strong id="gY"></strong> | |
<button id="btnGY">👎</button> | |
</div> | |
<strong class="align-center">+1–15 Blackstar Longsword</strong> | |
<div class="right"> | |
<button id="btnGN">👍</button> | |
<span>successes: </span> | |
<strong id="gN"></strong> | |
</div> | |
<div class="left align-right"> | |
<span>failures: </span> | |
<strong id="kzY"></strong> | |
<button id="btnKzY">👎</button> | |
</div> | |
<strong class="align-center">PRI–PEN Blackstar Longsword</strong> | |
<div class="right"> | |
<button id="btnKzN">👍</button> | |
<span>successes: </span> | |
<strong id="kzN"></strong> | |
</div> | |
</main> | |
<footer> | |
<h1><span class="lighter">Total: </span><span id="total"></span></h1> | |
<h2 class="lighter">including 775m for the base Blackstar Longsword</h2> | |
</footer> | |
<script type="text/javascript"> | |
const material = { | |
bsw: { | |
name: 'Black Stone (Weapon)', | |
value: 150_000 | |
}, | |
bsa: { | |
name: 'Black Stone (Armor)', | |
value: 150_000 | |
}, | |
cmbsw: { | |
name: 'Concentrated Magical Black Stone (Weapon)', | |
value: 2_850_000 | |
}, | |
cmbsa: { | |
name: 'Concentrated Magical Black Stone (Armor)', | |
value: 2_200_000 | |
}, | |
hbcs: { | |
name: 'Hard Black Crystal Shard', | |
value: 1_500_000 | |
}, | |
sbcs: { | |
name: 'Sharp Black Crystal Shard', | |
value: 2_100_000 | |
}, | |
meme: { | |
name: 'Memory Fragment', | |
value: 3_000_000 | |
}, | |
flawless: { | |
name: 'Flawless Magical Black Stone', | |
value: 8_000_000 | |
}, | |
} | |
function humanise(value) { | |
if (!value) { | |
return String(0); | |
} | |
let v = value; | |
const b = Math.floor(v / 1_000_000_000); | |
v = v % 1_000_000_000; | |
const m = Math.floor(v / 1_000_000); | |
v = v % 1_000_000; | |
const k = Math.floor(v / 1_000); | |
return `${b ? `${b}b ` : ''}${m ? `${m}m ` : ''}${k ? `${k}k ` : ''}`; | |
} | |
const valks = [ | |
[20, 10_000_000], | |
[30, 25_000_000], | |
[40, 80_000_000], | |
[50, 200_000_000], | |
[60, 400_000_000], | |
[70, 700_000_000], | |
[80, 1_200_000_000], | |
[90, 1_900_000_000], | |
[100, 2_800_000_000], | |
].map(([stack, value]) => { | |
const button = document.createElement('button'); | |
button.textContent = `+${stack}`; | |
const display = document.createElement('strong'); | |
return { | |
name: `Advice of Valks (+${stack})`, | |
value, | |
display, | |
button | |
}; | |
}); | |
document.querySelector('#valks').style.gridTemplateColumns = `repeat(${valks.length}, auto)`; | |
document.querySelector('#valks').append( | |
...valks.map(({ | |
display | |
}) => display), | |
...valks.map(({ | |
button | |
}) => button) | |
); | |
const recipes = [{ | |
name: '+1–15 Longsword Attempt (Fail)', | |
value: material['cmbsw'].value + 10 * material['meme'].value, | |
display: document.querySelector('#gY'), | |
button: document.querySelector('#btnGY'), | |
}, { | |
name: '+1–15 Longsword Attempt (Success)', | |
value: material['cmbsw'].value, | |
display: document.querySelector('#gN'), | |
button: document.querySelector('#btnGN'), | |
}, { | |
name: 'PRI–PEN Longsword Attempt (Fail)', | |
value: material['flawless'].value + 20 * material['meme'].value, | |
display: document.querySelector('#kzY'), | |
button: document.querySelector('#btnKzY'), | |
}, { | |
name: 'PRI–PEN Longsword Attempt (Success)', | |
value: material['flawless'].value, | |
display: document.querySelector('#kzN'), | |
button: document.querySelector('#btnKzN'), | |
}, ...valks]; | |
const recipesCounts = JSON.parse(localStorage.getItem('recipes-used')) || {}; | |
const total = document.querySelector('#total'); | |
const basePrice = 775_000_000; | |
function update() { | |
recipes.forEach(({ | |
name, | |
display | |
}) => display.textContent = String(recipesCounts[name] || 0)); | |
total.textContent = humanise(recipes.reduce((cost, { | |
name, | |
value | |
}) => cost + ((document.querySelector('#freeValks').checked && /Advice of Valks/.test(name)) ? 0 : (recipesCounts[name] || 0) * value), basePrice)); | |
localStorage.setItem('recipes-used', JSON.stringify(recipesCounts)); | |
} | |
document.querySelector('#freeValks').addEventListener('change', update); | |
update(); | |
recipes.forEach(({ | |
name, | |
button | |
}) => { | |
button.addEventListener('click', e => { | |
recipesCounts[name] = (recipesCounts[name] || 0) + 1; | |
update(); | |
}); | |
button.addEventListener('contextmenu', e => { | |
recipesCounts[name] = Math.max(0, (recipesCounts[name] || 0) - 1); | |
e.preventDefault(); | |
update(); | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment