Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

I'm writing a small javascript app which calculates damage per second of a variety of heroes and items in a video game. I'm trying to figure out the formula for critical strike items.

For example, there an item (riftshards) that gives a 20% chance to do 2.4x damage.

.2 * 1.4 = 0.28x extra damage or a damage factor of 1.28.

So my function would look like

getCritMultiplier: function(critMultiplier, critChance)
{
        return critChance * (critMultiplier - 1) + 1;
}

This works for when the hero only has 1 chance at a crit. But if the hero has 2 of these items it gets trickier.

I've been told the formula is something like this:

 1 - [(1-x)(1-y)...]

Gives the % chance to get a crit where x is your first crit chance item, and y is your second crit chance item. Plugging in .2 for each gives ~36% which seems correct.

However, this is where I'm stuck. If each item has a different crit modifier, I don't know how to calculate it.

For example if you have items that are:

  • 20% chance to do 2.4x damage
  • 25% chance to do 2.0x damage
  • 15% chance to do 3.0x damage

How can I calculate the result multiplier? The only other info I have is that if 2 crits happen at the same time (20% chance to 2.4x and 15% chance to 3.0x both occur) the higher multiplier will fire (3.0x damage). Any help is greatly appreciated.

My function needs to be:

getCritMultiplier: function(critMultipliers)
{
     // critMultipliers is an array of objects with critChance and critMultiplier properties
     // Returns a single number which is your average DPS increase 
}

Example calls:

var multipliers = [{critChance: .2, critMultiplier: 2.4}];
getCritMultiplier(multipliers); // Returns 1.28

var multipliers = [{critChance: .2, critMultiplier: 2.4},
                   {critChance: .15, critMultiplier: 3.0},
                   {critChance: .25, critMultiplier: 2.0}]
getCritMultiplier(multipliers); // Returns ??? 

Edit: I'll try to explain the problem better in math terms.

Hero does d damage per attack. He is holding n number of items. Each item has value p that is the percent chance that the hero will score a critical strike. Each item may have a distinct value of p. A critical strike makes the damage for that attack be multiplied by m, where m is a distinct value for each item. What is the formula for calculating the average damage per attack?

Example scenario:

  • Hero does 100 damage per attack. d = 100.
  • Hero is carrying 3 items. n = 3.
  • Item 1 gives a 20% chance to do 2.4x damage. p = .2 m = 2.4
  • Item 1 gives a 15% chance to do 3.0x damage. p = .15 m = 3.0
  • Item 1 gives a 30% chance to do 2.0x damage. p = .3 m = 2.0

Edit:

Thanks, got it working, here is the code I used:

 getCritMultiplier: function(critMultipliers)
    {            
        critMultipliers.sort(function(a, b) {return b.CRITICALMODIFIER - a.CRITICALMODIFIER});
        var dpsMultiplier = 1;                   
        var totalCriticalChance = 0;             
        $.each(critMultipliers, function (i, critMultiplier) {                
            var diminishedChance = (1 - totalCriticalChance) * critMultiplier.CRITICALCHANCE;
            dpsMultiplier = dpsMultiplier + (diminishedChance * (critMultiplier.CRITICALMODIFIER - 1));
            totalCriticalChance += diminishedChance; 
        });

        return {dpsMultiplier: dpsMultiplier, totalCriticalChance: totalCriticalChance};

    },
share|improve this question
    
I think it might help if you provided some more explanation of the problem. Remember, most of us are mathematicians but not gamers. –  Robert Israel May 25 '11 at 22:16
    
sure, ill add some more info. –  Shawn May 25 '11 at 22:18
    
I'm not quite sure I understand your damage factor calculation. Since the amount of extra damage is a random variable, wouldn't you want to randomly sample the uniform distribution to get the damage factor? For example: return critChance >= Math.random() ? critMultiplier : 1.0. Then, if you have multiple items, you would just take the maximum damage factor over the items. –  ESultanik May 25 '11 at 22:21
    
i'm sorry, i'm not that great a math so i don't understand all the terminology you used.... –  Shawn May 25 '11 at 22:24
    
I guess what I'm wondering is: Why do you need to calculate the CritMultiplier at all? In your example, this value comes out to be 1.283, right? For what are you going to use that value? Are you really just calculating damage-per-second? Or are you actually implementing the game itself? –  ESultanik May 26 '11 at 12:41

1 Answer 1

up vote 3 down vote accepted

The key here is that you are taking the greatest of the crits that happen. To use your example, there is a $15\%$ chance of getting a 3.0x crit multiplier. If that crit goes off, the others don't matter. However, if it DOESN'T, then either the 2.4x or the 2.0x crit might go off. The probability that the 3.0x crit doesn't go off is $85\%$, and the probability that the 2.4x crit goes off is $20\%$, so the probability that the 3.0x doesn't go off but the 2.4x does is $85\% * 20\% = 17\%$. You can then multiply that by 2.4 to get the average damage. In full, your example would look like this:

$3.0(.15) + 2.4(1-.15)(.2) + 2.0(1-.15)(1-.2)(.3) = 1.283$

Here, I am going from greatest multiplier to lowest. For each multiplier, I am multiplying by the probability that the crit itself goes off and by the probability that none of the higher crits go off. So, write your code such that your function receives a sorted list from highest to lowest. Next, initialize a variable for your total expected multiplier. Then go through each element, do the multiplication, and add to the total. I can post some code later if need be, but I think that should be sufficient for you. That help? :)

share|improve this answer
    
works perfectly, thanks! I'll update my post with the code –  Shawn May 25 '11 at 23:17
    
@Shawn: Fantastic! Glad I could help. :) –  El'endia Starman May 25 '11 at 23:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.