I'm creating a web app to learn JS that will calculate damage per round but I'm stuck on adding criticals.

I have successfully created variables for: diceNumber, diceSides, bonuses, attacksPerRound, and criticalChance

I am assuming that every attack is a hit.

What is the formula to add all of these together to get the average damage per round?

This is my Formula so far for non-critical hits: averageDamagePerRound = averageTotalDamage * attacksPerRound

For this a critical hit will mean that the roll and all bonuses do double damage. If you are familiar, it is based on the rules the game Baldur's Gate uses and I am unsure if/how they differ from tabletop as I have never played before.

In case anyone here knows Javascript, this is the code if written so far : https://codepen.io/fujisan0388/pen/JjGbLqq


2 Answers 2


You cannot meaningfully include critical hits without factoring in hit probabilities

A brief discussion of random variables: a measurable function defined on a probability space that maps from the sample space to the real numbers.

The damage done on a hit is a random variable - let's call it \$D\$. Its made up of other variables, some random and some not:

$$ D=\sum_{n=1}^\text{diceNumber}U(\text{diceSides})+\text{bonuses} $$

where \$U(n)\$ is the discrete uniform distribution from \$1\$ to \$n\$ a random variable and the other variables are your variables.

This can simulate \$U(n)\$ although note that the rand function is only pseudorandom but that won't matter for your purposes:

Math.floor(Math.random() * n + 1)

Since a critical hit doubles the number of dice and the bonuses, it is represented by the random variable:

$$ C=\sum_{n=1}^{2\times\text{diceNumber}}U(\text{diceSides})+2\times\text{bonuses} $$

For averages, you can calculate all possible outcomes with nested for loops and then work out the average. However, there is a mathematical short-cut - the mean of the sum of independent random variables is the equal to the sum of the means. Similarly, the variance of the sum of independent random variables is equal to the sum of the variances.


$$ \begin{align} \bar D &= \text{diceNumber} \times \left(\bar U(\text{DiceSides})\right) +\text{bonuses}\\ &= \text{diceNumber} \times \left({{\text{DiceSides}+1}\over 2} \right) +\text{bonuses}\\ \bar C &= 2 \times \left( \text{diceNumber} \times \left({{\text{DiceSides}+1}\over 2} \right) +\text{bonuses}\right)\\ \end{align} $$

So, now we circle back to why you need a random variable to represent your hit chance. For any given combination of armour class and to hit bonuses there is a target number \$t\$ that you need to roll on a d20 equal to above which is a hit and below which is a miss and if you roll a 20 you get a critical. I am assuming that a 20 is always a hit and always a critical hit: if you can miss on a 20, you need to adjust what follows.

So the damage from an attack, including the chance to hit, can be represented by another random variable:

$$ H = \begin{cases} 0, &U(20)\lt t\\ D, &20\gt U(20)\ge t\\ C, &U(20)=20\\ \end{cases} $$

If you are only interested in averages, you get:

$$ \bar H = \sum\begin{cases} 0\times Pr(U(20)\lt t)\\ \bar D \times Pr(20\gt U(20)\ge t)\\ \bar C \times Pr(U(20)=20)\\ \end{cases} $$

Where \$Pr(E)\$Pr is the probability that event \$E\$ happens.

For \$20\ge t \ge 1\$, \$Pr(20\gt U(20)\ge t)=0.05\times (20-t)\$, for \$t\gt 20\$, \$Pr(20\gt U(20)\ge t)=0\$ and for \$t\lt 1\$, \$Pr(20\gt U(20)\ge t)=0.95\$. \$Pr(U(20)=20)=0.05\$ always.


The basic formula outside of crit damage is fairly straightforward as you wrote it.

If you have 2 attacks using a mace you are doing:

2 attacks: aPR=2

mace is 1d6: dN=1 and dS=6

bonuses would be dependant on a lot but usually just Str: b=Str

So basic formula is dN*AVG(1,dS)+b

The to-hit formula would be something like:



b=damage modifiers

Then Crits and probability would be if statements. edit: Sorry, let me be clearer here and go a bit more in depth.

For the crit if statement, you'd be looking for something along the lines of:

Combat execution gives you a value for the roll I will call rollValue then

If rollValue=20 then dN=dN+1

This means that if you looking for the overall expected damage output formula (or average damage) then the formula could be modified to be:

hC(dN*AVG(1,dS)+b)+0.05((dN+1)AVG(1,dS)+b) hC is the hitChance less the crit, ex: 0.45 for a 50% hit chance

That's probably a bit convoluted so here is an alternative writing:

expectedDamage= (hitChance*(diceNumber*((1+diceSides)/2)+bonuses)+(0.05*((diceNumber+1)*((1+diceSides)/2)+bonuses)

  • 1
    \$\begingroup\$ I'm having a really hard time following this answer. I'm going to highly recommend you spend more words explaining why the formula is what it is, and complete it and cover the critical chance which - since it is mentioned in the question - I assume varies and is non-obvious how to cover. \$\endgroup\$
    – Someone_Evil
    Jun 17, 2020 at 17:05
  • \$\begingroup\$ I'd also suggest using MathJax to make your equations/math look nicer. \$\endgroup\$
    – V2Blast
    Jun 17, 2020 at 20:13
  • \$\begingroup\$ so to be clear; this should work: averageDamagePerRound = normalHitChance * (numberOfDice * rollAverageDamage) + critHitChance * (1 + numberOfDice * rollAverageDamage) ? The averageDamage includes the average of the roll and modifiers \$\endgroup\$ Jun 17, 2020 at 20:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .