Trending
Opinion: How will Project 2025 impact game developers?
The Heritage Foundation's manifesto for the possible next administration could do great harm to many, including large portions of the game development community.
In this reprinted #altdevblogaday-opinion piece, Uber Entertainment software engineer Forrest Smith looks at how critical hits are handled in his team's upcoming game Super Monday Night Combat and in other
[In this reprinted #altdevblogaday-opinion piece, Uber Entertainment software engineer Forrest Smith looks at how critical hits are handled in his team's upcoming game Super Monday Night Combat and in other titles.] Critical hits are common in many games. Today I'm going to discuss the thought process and math behind calculating critical hits in our upcoming shooter Super Monday Night Combat. Following Precedent What are critical hits? How do they work? Typically there is some percent chance to crit which causes an attack to deal some percentage extra damage. Commons values are in the ranges 1-30% chance to crit and 35-300% extra damage. In an RPG, this works as you'd expect. For each swing of the sword, you roll the magic random number generator dice and check for a crit1. Team Fortress 2 has an interesting crit system2. Guns have a 2% base chance to crit, which temporarily increases as the player deals damage. Slow firing guns (shotgun) check for crit with each shot similar to an RPG sword. Rapid fire guns (uzi) check once per second and crit in two second bursts. Remember Your Units The TF2 rapid fire crit system is interesting. Crits are about dealing burst damage. A minigun firing 10% bullets with crit evenly distributed is less burst and more DPS gain. A two-second crit window is perfect for dealing burst damage. However it has a slight issue. With bursts what does a crit chance 10% really mean. How many bullets are fired critically? Is it 50% or some other number? Let's think it through! Assume a two second crit time, massive 50% crit chance, and one second crit check interval. On average, the player will fail the first dice roll when they start firing and pass the second roll after one second. The dice is not rolled while critical firing. After two seconds of critical firing, we roll the dice3. One second later, on average, we'll critical fire again. With a 50% crit chance the pattern is 1-second regular, 2-seconds crit, 1-second, regular, 2-seconds crit. That 50% magically became 66%! The number of critical bullets is not exactly equal to the listed crit chance and varies with the crit duration. Even weapon fire rate potentially matters depending on when your roll the dice. A slow-ish weapon that fires every .9 seconds could fire either two or three times within a two second crit window. That doesn't mean that TF2 is wrong. It just means the true effect of crit chance is both variable and obfuscated. Something Simpler For Super Monday Night Combat, we established a few goals. First and foremost, the crit percent should represent the number of bullets that deal critical damage no matter the weapon. Second, crits should not be extended, so no rolling the dice mid-crit. Third, crits can occur directly after one another. There is no "dead time". Finally, we want one system to rule them all! Easier to understand, easier to maintain. In our previous example a crit chance of 50% had an effective crit rate 66%. This means there is a mystery number that generates an effective crit rate of 50%. We can find that number with math!
1 CritChance = balance_number; // [0,1] percentage
2 FireRate = balance_number; // Bullets per sec
3 CritDuration = balance_number; // In seconds
4
5 critChancePerBullet = CritChance;
6 bulletsPerMinute = (FireRate * 60);
7 critBulletsPerMinute = (critChancePerBullet * bulletsPerMinute);
8 bulletsPerCrit = (1 + int(bulletsPerSecond * CritDuration));
9 critsPerMinute = (critBulletsPerMinute / bulletsPerCrit);
10 nonCritBulletsPerMinute = (bulletsPerMinute - (critsPerMinute*bulletsPerCrit));
11 critChecksPerMinute = nonCritBulletsPerMinutes;
12 realCritChancePerCheck = (critsPerMinute / critChecksPerMinute);
A wall of math, hooray! Let's go over the interesting line numbers. 1-3: Values defined by a designer that vary per weapon. 6: Math is done in "per minute" space here as it's easier to visualize 2 checks per minute rather than .0333 checks per second. Term cancellation is left as an exercise to the reader. 8: The 1 term is because at least one bullet will fire crit even with a CritDuration of 0. The int cast is to truncate as fractional bullets don't exist. 10: This is where the magic happens! We want to check for crit for every bullet except those that are already critical. We know have many bullets we want to be critical so we can calculate the number of non-critical bullets which is also the number of times we'll check for crit. Line 11 is unnecessary but present for blog post clarity. 12: The pieces are in place and the real crit chance for each roll of the dice can be easily calculated4. Huzzah! This will result in a realCritChancePerCheck that will correctly cause a CritChance percent of bullets to be fired critically no matter the crit chance, fire rate, or crit duration. Exactly as desired. Conclusion This is a specific example of work I did this past week. It fixed some bugs, simplified a system, and produced a result that is easy to comprehend which leads to better balance faster. I had fun sitting down with a piece of paper to solve the equation and felt it was interesting enough to share. It's not a magical solution for every game, but it works for ours. As an open question to the readers, how do you calculate critical hits in your game? What methods have you found useful? Footnotes
How you roll that dice is a post in and of itself. There are multiple strategies to avoid extreme streaks which can and will happen. A "one in a million" chance isn't so rare in World of Warcraft which has 10 million players rolling the dices tens of thousands of times per player.
There could be a minimum time after critical firing to not crit, but that just further complicates the equation.
critChecksPerMinute will be zero or negative (which is bad!) if CritChance is >= 1.0. This should be checked for at the start.
[This piece was reprinted from #AltDevBlogADay, a shared blog initiative started by @mike_acton devoted to giving game developers of all disciplines a place to motivate each other to write regularly about their personal game development passions.]
You May Also Like