private static void PrintInfo() { Console.WriteLine($"Crit Chance: {RatingConversions.GetCritChance(CurrentStats.CritRating) * 100:0.0}%"); Console.WriteLine($"Crit Mult: {RatingConversions.GetCritDamageMultiplier(CurrentStats.CritRating) * 100:0.0}%"); Console.WriteLine($"DH Chance: {RatingConversions.GetDirectHitChance(CurrentStats.DirectHitRating) * 100:0.0}%"); Console.WriteLine($"GCD: {2.5 / RatingConversions.GetSpeedFactor(CurrentStats.SpeedRating):0.00}"); Console.WriteLine($"Ten/Det Mult: {RatingConversions.GetDeterminationFactor(CurrentStats.Determination) * RatingConversions.GetTenacityFactor(CurrentStats.Tenacity):0.00}"); Console.WriteLine(); Console.ReadKey(true); }
public static double CalculateDamageFromGCD(StatsGroup stats) { double critRate = RatingConversions.GetCritChance(stats.CritRating); double critMult = RatingConversions.GetCritDamageMultiplier(stats.CritRating); double speedFactor = RatingConversions.GetSpeedFactor(stats.SpeedRating); double directHitRate = RatingConversions.GetDirectHitChance(stats.DirectHitRating); double determinationFactor = RatingConversions.GetDeterminationFactor(stats.Determination); double tenacityFactor = RatingConversions.GetTenacityFactor(stats.Tenacity); return(CalculateDamageFromGCD(critRate, critMult, speedFactor, directHitRate, determinationFactor, tenacityFactor)); }
public double SimulateTotalPotencyOver(double duration) { Dictionary <AttackPattern.DamageAbility, double> lastAbilityTimes = new Dictionary <AttackPattern.DamageAbility, double>(); Dictionary <AttackPattern.DamageOverTimeSkill, double> lastDoTTimes = new Dictionary <AttackPattern.DamageOverTimeSkill, double>(); foreach (var dot in ToSimulate.DoTSkills) { lastDoTTimes[dot] = double.MinValue; } foreach (var ability in ToSimulate.DamageAbilities) { lastAbilityTimes[ability] = double.MinValue; } double currentTime = 0; double totalPotency = 0; int hits = 0; int directHits = 0; int crits = 0; while (currentTime < duration) { double timeUsed = 0; double attackPotency = 0; // Use all our oGCDs foreach (var ability in ToSimulate.DamageAbilities) { if (lastAbilityTimes[ability] + ability.Recast < currentTime) { lastAbilityTimes[ability] = currentTime; attackPotency += ability.Potency; // Fudge here - most abilities have a cast time of 0, but RDM melee combo is an "ability" with a cast time // Abilities need to ignore speed stat for that to work. timeUsed = ability.CastTime * RatingConversions.GetSpeedFactor(Stats.SpeedRating); } } // Refresh our DoTs in priority order foreach (var dot in ToSimulate.DoTSkills) { if (timeUsed == 0 && lastDoTTimes[dot] + dot.Duration < currentTime) { lastDoTTimes[dot] = currentTime; attackPotency += dot.TotalPotency * Sim.GetDamageOfDoT(Stats, dot.TickCount); timeUsed += dot.CastTime; } } // If we didn't need to refresh a DoT, use the GCD for damage. if (timeUsed == 0) { bool isCrit, isDirect; timeUsed += 2.5; attackPotency += ToSimulate.GcdPotency * Sim.GetDamageOfGCDAttack(Stats, out isCrit, out isDirect); hits++; if (isCrit) { crits++; } if (isDirect) { directHits++; } } totalPotency += attackPotency; currentTime += timeUsed / RatingConversions.GetSpeedFactor(Stats.SpeedRating); } //Console.WriteLine($"{(double)(crits) / hits * 100:0.00}% Observed Crit Rate"); //Console.WriteLine($"{(double)(directHits) / hits * 100:0.00}% Observed DH Rate"); return(totalPotency); }