UPDATE 21.04.21
Merge with infantry power calculator
Downloadable here.
Contains:
1 .ipynb file with the script for interactive python
1 .csv file (weapon_report export for attribute editor)
1 .xlsx file to define squads
Needed: Interactive Python 3.X + numpy, pandas, math, plotly.express libraries
Changes:
Currently, the only source of DPS for small arms fire is Cruzz’ formula (also see Vipper’s guide), as well as coh2.serealia.ca which is an updated version that apparently uses Cruzz’ formula as well. However, no one knows where this formula came from.
When I tried to re-calculate these values on my own, I was unable to replicate the exact same values. Since this error could become quite large. I did some more digging only to find out that the formula does not match what I saw in-game.
Some time ago when I tested tank cannons, I found another probably game engine-related issue that increased the time between shots by 0.125 per used stat (I will call this 0.125 addition ‘correction time’ from now on), therefore I expected a similar issue with small arms. I then started iteratively modding and things turned out to be more complicated than that, but finally I can present a model that:
1. Matches the in-game time for shot cycles and
2. Based on that calculates the correct DPS of a given weapon.
I’ll spare you the lengthy details, in essence I had to test every stat separately to see how it behaves, changed it in a mod and then measured the time in-game by hand. If some of you wish to see the raw data, I can provide it but warning ahead it is quite convoluted. "Readability” was not an aim since I initially thought it would only be a quick notation sheet.
Additionally, one limitation is that I had to use "fixed" stats, meaning every stat was defined. The game however often uses randomization for some stats. Although I am fairly certain that I checked for all or at least most of this and my new model reflects this randomness, I cannot exclude with 100% certainty that this will lead to minor differences in the game and in my model. However, these differences will be minor, so I am confident to say that the new formula is better than the old one in any case.
The following spoiler defines a couple of “functions” that are necessary to understand the final formula:
Single fire weapons:
Stat overview:
The easiest way to calculate the DPS is to calculate the expected damage done and divide by the time for a complete shot cycle. Therefore, all variables that are randomly picked from an interval need to be taken as the mean between the interval borders. For brevity and visual clarity, I won’t note it down in the formula.
Expected damage:
Note ahead: Chance to hit and chance to penetrate are capped at 1. The braces are only there to group related stats and not needed for calculation
(Accuracy * target_RA) * (penetration / target_armor) * (reload_frequency + 1) * damage
It’s fairly straight forward: chance to hit times chance to pen times bullets in magazine times damage per bullet.
Cycle time:
(fire_aim_time + wind_up + wind_down + cooldown) * (reload_frequency + 1) - mean_CD + reload_duration
This means the model cycles through (fire_aim_time + wind_up + wind_down + cooldown) until the last bullet left in the magazine. For the last bullet, no cooldown is applied and the model directly enters the reload animation.
I have seen that the model also sometimes has intermediary animations (looking left and right, cowering etc. This does NOT affect the timings.
Burst fire weapons:
This is were things get tricky mostly because we get some additional stats.
Stat overview:
The reasoning is the same as before: Expected damage divided by the time needed.
Expected damage:
Chance to hit and chance to penetrate are capped at 1. The braces are only there to group related stats and not needed for calculation. I only have limited data on the ROF*burst_duration, but from what I saw this value is not rounded down. If a “half bullet” is calculated, there is either a random check of the bullet is given or not or it is carried over to the next cycle. I assume the latter, but not sure.
(Accuracy * target_RA) * (penetration / target_armor) * (burst_duration * ROF) * (reload_frequency + 1) * damage
Same as before. But since we have multiple bullets instead of one, we add another factor to calculate how many: ROF times burst_duration.
Cycle time:
(fire_aim_time + wind_up + wind_down + cooldown + burst_duration) * (reload_frequency + 1) - mean_CD + reload_duration
Same as before. We just add the burst_duration.
Further comments:
The old formula adds the ready_aim time. This is false. Ready_aim time defines the time to focus on a new enemy and is applied only ONCE at the beginning of the fight. It also subtracts the fire aim time. This is false too.
Aftermath
(I'll quickly add another paragraph to give some perspective)
So, what about all this. Overall this doesn't sound like a huge change, does it?
Depends on the weapon you look at. Literally all DPS profiles in coh2.serealia.ca are incorrect. Some values are still close to each other, others are not. For example, the Ranger M1A1 carbine is shows as having 10 DPS in serealia at range 0-4. My in-game tests however showed something closer to 8 (39-40 seconds needed to kill 4 Partisans with in total 320 HP at point blank which leads a DPS of 8-8,2. This leads to a difference of 20% in this rather extreme case. My formula calculates 8,207 which seems to be way closer to the in-game situation. In serealia, the Tommy Bren gun starts at 4,1 and ends at 6,9 DPS, my formula calculates 4,5 (+10%) and 6,95 (+0,1%) respectively. Or the Gren K98 goes from 5,99 to 2,26 DPS, while the new formula returns 5,27 (-12%) to 2,16 (-4%). We're currently in a state of the game where things are in general decently balanced, every move we make now can naturally only be a tiny step. If we want to make further changes, we need to get the correct numbers. I checked some few weapons in the game and my model is consistent with timings that I measured in game and some TTK data I gathered. I encourage everyone to do some measurements themselves and also report back what they got.
I’ll leave it at this for now, it is quite a wall of text already. I spent a lot of time on this, if anyone has doubts about my formula I would kindly ask to gather some data yourself. I will be all ears for discussion, but after countless cycles of changing stats and stopping times, I would like to have a break on this.
I hope this helps for the upcoming commander patch. Release version can be found here.
Hannibal out