Last active
October 15, 2025 11:16
-
-
Save robfrawley/fcc90744e5ea8b76b4904bcc809d40fc to your computer and use it in GitHub Desktop.
Crit Simulator
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
| import sys | |
| import random | |
| # configure simulation parameters | |
| crit_multiplier = float(sys.argv[1]) if len(sys.argv) > 1 else 2.0 # the crit damage multiplier, read from cli args or default to 2.0 (fixed value) | |
| base_damage = 100 # base damage per shot (fixed value) | |
| base_crit_chance = 0.05 # 5% base crit chance (fixed value) | |
| crit_chance = base_crit_chance # current crit chance, starts at base crit chance | |
| shots_per_second = 2 # total shots every second (fixed value) | |
| total_shots = 1000000 # total number of shots to simulate (fixed value) | |
| total_crits = 0 # total number of crits during the simulation | |
| total_damage = 0.0 # total damage dealt during the simulation | |
| total_crit_chance_when_critting = 0.0 # total crit chance value when a crit occurs | |
| crit_cooldown = 0 # number of shots until next crit is allowed, starts at 0 | |
| # simulate the shots | |
| for _ in range(total_shots - 1): | |
| # determine if the shot is a crit, random returns a float between 0.0 and 1.0 | |
| is_crit = random.random() < crit_chance and crit_cooldown == 0 | |
| # calculate damage for the shot, base_damage or base_damage*crit_multiplier for crits | |
| damage = base_damage * crit_multiplier if is_crit else base_damage | |
| # add damage to total damage | |
| total_damage += damage | |
| # adjust crit chance for next shot, if crit: | |
| if is_crit: | |
| crit_cooldown = (shots_per_second * 5) + 1; # set crit cooldown to (shots_per_second (2 shots) * 5 seconds) + 1 = 11 shots, one extra to account for the current shot | |
| total_crits += 1 # track total number of crit shots | |
| total_crit_chance_when_critting += crit_chance # add the crit chance to the total crit chance | |
| crit_chance = base_crit_chance # reset crit chance back to base chance (5%) after a crit | |
| # if not a crit and not on cooldown: | |
| elif not is_crit and crit_cooldown == 0: | |
| crit_chance += base_crit_chance # increase crit chance by base crit chance (5%) when not a crit | |
| crit_cooldown = max(0, crit_cooldown - 1) # decrease crit cooldown by 1, min of 0 | |
| # output simulation results | |
| average_damage_dealt = total_damage / total_shots | |
| print(f"Base Damage: {base_damage}") | |
| print(f"Base Crit Chance: {base_crit_chance * 100}%") | |
| print(f"Total Shots: {total_shots:,}") | |
| print(f"Total Crits: {total_crits:,}") | |
| print(f"Percent of Shots that Critted: {(total_crits / total_shots) * 100:.2f}%") | |
| print(f"Crit Multiplier: {crit_multiplier}x") | |
| print(f"Average Damage Dealt: {average_damage_dealt:.2f}") | |
| print(f"Average Damage Dealt Over Base Damage: {((average_damage_dealt - base_damage) / base_damage) * 100:.2f}%") | |
| print(f"Average Crit Chance Value For Crit Hits: {total_crit_chance_when_critting / total_crits * 100:.2f}%") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment