private void Calculate() { float baseBossAttackSpeed = CalcOpts.BossAttackSpeed * (1f - Stats.BossAttackSpeedMultiplier); float baseWeaponSpeed = Lookup.WeaponSpeed(Character, Stats); float bossAttackHaste = 0.0f; float weaponHaste = 0.0f; BossAttackSpeed = baseBossAttackSpeed; WeaponSpeed = baseWeaponSpeed; if (CalcOpts.UseParryHaste) { // Iterate on this a few times to get a 'stable' result for (int j = 0; j < 4; j++) { bossAttackHaste = AttackTable.Parry * 0.24f * ((BossAttackSpeed / WeaponSpeed) + (BossAttackSpeed / 1.5f)); weaponHaste = DefendTable.Parry * 0.24f * (WeaponSpeed / BossAttackSpeed); BossAttackSpeed = baseBossAttackSpeed / (1.0f + bossAttackHaste); WeaponSpeed = baseWeaponSpeed / (1.0f + weaponHaste); } } else { // Simple adjust to the defender's speed if the attacker isn't parry hasted WeaponSpeed /= (1.0f + (DefendTable.Parry * 0.24f * (WeaponSpeed / BossAttackSpeed))); BossAttackSpeed = baseBossAttackSpeed; } }
private void Calculate() { float bossAttackSpeed = BossOpts.DefaultMeleeAttack.AttackSpeed / (1f - Stats.BossAttackSpeedReductionMultiplier); WeaponSpeed = Lookup.WeaponSpeed(Character, Stats) / (1.0f + (DefendTable.Parry * 0.24f * (WeaponSpeed / bossAttackSpeed))); }
private void CalculateDamage() { float baseDamage = 0.0f; float critMultiplier = 0.0f; float duration = 0.0f; float AP = Stats.AttackPower; float SP = Stats.SpellPower; #if (RAWR3) int targetLevel = BossOpts.Level; #else int targetLevel = CalcOpts.TargetLevel; #endif #region Ability Base Damage switch (Ability) { // White Damage case Ability.None: baseDamage = Stats.WeaponDamage; DamageMultiplier *= (1.0f + Stats.BonusPhysicalDamageMultiplier) * (1.0f - (Lookup.GlancingReduction(Character, targetLevel) * AttackTable.Glance)) * (1.0f - ArmorReduction); critMultiplier = 1.0f; break; case Ability.ShieldOfRighteousness: float blockValue = Stats.BlockValue + Stats.ShieldOfRighteousnessBlockValue + Stats.JudgementBlockValue + Stats.HolyShieldBlockValue; float blockValueDRStart = 30 * Character.Level; if (blockValue < blockValueDRStart) { baseDamage = blockValue; } else if (blockValue < 39.5 * Character.Level) { baseDamage = blockValueDRStart + (0.95f * (blockValue - blockValueDRStart)) - (0.000625f * (float)Math.Pow(blockValue - blockValueDRStart, 2)); } else { baseDamage = blockValueDRStart + (0.95f * 9.5f * Character.Level) - (0.000625f * (float)Math.Pow(9.5 * Character.Level, 2)); } baseDamage += 520f + Stats.BonusShieldOfRighteousnessDamage; DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; case Ability.HammerOfTheRighteous: if (Talents.HammerOfTheRighteous == 0 || Character.MainHand == null) { Damage = 0.0f; return; } baseDamage = (Stats.WeaponDamage / Character.MainHand.Speed) * 4.0f; DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + Stats.BonusHammerOfTheRighteousMultiplier); critMultiplier = 1.0f; break; // Seal of Vengeance is the tiny damage that applies on each swing; Holy Vengeance is the DoT // While trivial threat and damage, it's modeled for compatibility with Seal of Righteousness case Ability.SealOfVengeance: baseDamage = Stats.WeaponDamage * 0.33f; DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + 0.03f * Talents.SealsOfThePure) * (1.0f + Stats.BonusSealOfVengeanceDamageMultiplier); critMultiplier = 1.0f; break; // 5 stacks of Holy Vengeance are assumed // TODO: implement stacking mechanic for beginning-of-fight TPS case Ability.HolyVengeance: baseDamage = 5f * (0.016f * SP + 0.032f * AP); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + 0.03f * Talents.SealsOfThePure) * (1.0f + Stats.BonusSealOfVengeanceDamageMultiplier); critMultiplier = 0.0f; break; // Judgement of Vengeance assumes 5 stacks of Holy Vengeance case Ability.JudgementOfVengeance: float holyVengeanceStacks = 5; baseDamage = (0.22f * SP + 0.14f * AP) * (1.0f + 0.1f * holyVengeanceStacks); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + 0.03f * Talents.SealsOfThePure) * (Talents.GlyphOfJudgement ? 1.1f : 1.0f); critMultiplier = 1.0f; break; case Ability.SealOfRighteousness: baseDamage = Lookup.WeaponSpeed(Character, Stats) * ((0.022f * AP) + (0.044f * SP)); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + 0.03f * Talents.SealsOfThePure) * (1.0f + Stats.BonusSealOfRighteousnessDamageMultiplier) * (Talents.GlyphOfSealOfRighteousness ? 1.1f : 1.0f); critMultiplier = 0.0f; break; case Ability.JudgementOfRighteousness: baseDamage = 1.0f + (0.2f * AP) + (0.32f * SP); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + 0.03f * Talents.SealsOfThePure) * (Talents.GlyphOfJudgement ? 1.1f : 1.0f); critMultiplier = 1.0f; break; case Ability.HolyShield: if (Talents.HolyShield == 0) { Damage = 0.0f; return; } baseDamage = (211f + (0.056f * AP) + (0.09f * SP)) * 1.3f; DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.0f; break; case Ability.Consecration: baseDamage = 113f + (0.04f * (SP + Stats.ConsecrationSpellPower)) + (0.04f * AP); duration = (Talents.GlyphOfConsecration ? 10.0f : 8.0f); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.0f; break; case Ability.Exorcism: baseDamage = 1087f + (0.15f * SP) + (0.15f * AP); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + Talents.SanctityOfBattle * 0.05f) * (Talents.GlyphOfExorcism ? 1.2f : 1.0f); critMultiplier = 0.5f; break; case Ability.AvengersShield: baseDamage = 1222f + (0.07f * SP) + (0.07f * AP); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (Talents.GlyphOfAvengersShield ? 2.0f : 1.0f); critMultiplier = 1.0f; break; case Ability.HolyWrath: baseDamage = 1142f + (AP * 0.07f) + (SP * 0.07f); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.5f; break; case Ability.HammerOfWrath: baseDamage = 1198f + (AP * 0.15f) + (SP * 0.15f); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; case Ability.RetributionAura: baseDamage = 112f + (SP * 0.0666f); DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + Talents.SanctifiedRetribution * 0.5f); critMultiplier = 0.0f; break; } #endregion // All damage multipliers, 1HWS, Armor etc...do we need to split buff/debuff ? baseDamage *= DamageMultiplier; #region Miss Chance, Avoidance Chance if (Lookup.IsSpell(Ability)) { if (Ability == Ability.Consecration) { // Probability calculation, since each tick can be resisted individually. baseDamage = Lookup.GetConsecrationTickChances(duration, baseDamage, AttackTable.Miss); } else { // Missed spell attacks // TODO: expand Ability Model to include a check for damage type, not only spell. baseDamage *= (1.0f - AttackTable.Miss); } } else { // Missed attacks if (Lookup.IsAvoidable(Ability)) { baseDamage *= (1.0f - AttackTable.AnyMiss); } else { baseDamage *= (1.0f - AttackTable.Miss); } } #endregion #region Partial Resists // Partial Resists if (Lookup.HasPartials(Ability)) { // Detailed table of Partial slices. float[] partialChanceTable = StatConversion.GetResistanceTable(Character.Level, targetLevel, 0.0f, Stats.SpellPenetration); // Here goes nothing, Damage averaged over the different partial slices that can happen. float partialDamage = 0.0f; for (int i = 0; i < 11; i++) { partialDamage += partialChanceTable[i] * (1.0f - 0.1f * (float)i) * baseDamage; } baseDamage = partialDamage; } #endregion // Average critical strike bonuses if (Lookup.CanCrit(Ability)) { baseDamage += baseDamage * critMultiplier * AttackTable.Critical; } // Final Damage the Ability deals Damage = baseDamage; }
private void CalculateDamage() { float baseDamage = 0.0f; float critMultiplier = 0.0f; float duration = 0.0f; float AP = Stats.AttackPower; float SP = Stats.SpellPower; int targetLevel = BossOpts.Level; #region Ability Base Damage switch (Ability) { #region Spells case Ability.AvengersShield: if (Character.OffHand == null || Character.OffHand.Type != ItemType.Shield || (Talents.Divinity == 0 && Talents.SealsOfThePure == 0 && Talents.EternalGlory == 0)) { Damage = 0f; return; } baseDamage = 3113.187994f + (0.419f * AP) + (0.21f * SP); baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier) * (Talents.GlyphOfFocusedShield ? 1.3f : 1.0f); critMultiplier = 1.0f; break; case Ability.HammerOfWrath: baseDamage = 4015.02439f + (0.039f * AP) + (0.117f * SP); baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; case Ability.HolyWrath: baseDamage = 2435.781339f + (0.61f * SP); baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.5f; break; #endregion #region Melee case Ability.CrusaderStrike: if (Character.MainHand == null) { Damage = 0f; return; } baseDamage = Lookup.WeaponDamage(Character, Stats.AttackPower, true); baseDamage *= 1.2f + (1.2f * (Talents.Crusade * 0.1f)) + (1.2f * (Talents.WrathOfTheLightbringer * 0.5f)); baseDamage *= (1.0f + Stats.BonusPhysicalDamageMultiplier) * (1.0f + Stats.BonusDamageMultiplierCrusaderStrike) * (1.0f - ArmorReduction); critMultiplier = 1.0f; break; case Ability.HammerOfTheRighteous: if (Character.MainHand == null || (Character.MainHand.Type != ItemType.OneHandAxe && Character.MainHand.Type != ItemType.OneHandMace && Character.MainHand.Type != ItemType.OneHandSword) || Talents.HammerOfTheRighteous == 0) { Damage = 0f; return; } baseDamage = Lookup.WeaponDamage(Character, Stats.AttackPower, true) * 0.3f; baseDamage *= (1f + (Talents.Crusade * 0.1f) + (Talents.GlyphOfHammerOfTheRighteous ? 0.1f : 0f)) * (1.0f + Stats.BonusPhysicalDamageMultiplier) * (1.0f - ArmorReduction); critMultiplier = 1.0f; break; case Ability.HammerOfTheRighteousProc: if (Character.MainHand == null || (Character.MainHand.Type != ItemType.OneHandAxe && Character.MainHand.Type != ItemType.OneHandMace && Character.MainHand.Type != ItemType.OneHandSword) || Talents.HammerOfTheRighteous == 0) { Damage = 0f; return; } baseDamage = 728.8813374f + (0.18f * AP); baseDamage *= (1f + (Talents.Crusade * 0.1f) + (Talents.GlyphOfHammerOfTheRighteous ? 0.1f : 0f)) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; case Ability.JudgementOfRighteousness: baseDamage = 1f + (0.2f * AP) + (0.32f * SP); baseDamage *= (1f + (Talents.WrathOfTheLightbringer * 0.5f) + (Talents.GlyphOfJudgement ? 0.1f : 0f)) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; case Ability.JudgementOfTruth: { float censureStacks = 5; baseDamage = 1 + (0.223f * SP) + (0.142f * AP) * (1.0f + 0.1f * censureStacks); baseDamage *= (1f + (Talents.WrathOfTheLightbringer * 0.5f) + (Talents.GlyphOfJudgement ? 0.1f : 0f)) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; } break; case Ability.MeleeSwing: baseDamage = Stats.WeaponDamage; baseDamage *= (1.0f + Stats.BonusPhysicalDamageMultiplier) * (1.0f - (Lookup.GlancingReduction(Character.Level, targetLevel) * AttackTable.Glance)) * (1.0f - ArmorReduction); baseDamage *= (1f + Stats.BonusWhiteDamageMultiplier); critMultiplier = 1.0f; break; case Ability.SealOfRighteousness: baseDamage = Lookup.WeaponSpeed(Character, Stats) * ((0.022f * SP) + (0.011f * AP)); baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure) * (1.0f + Stats.BonusHolyDamageMultiplier) * (1.0f + Stats.BonusDamageShieldofRighteous); critMultiplier = 0.0f; break; case Ability.SealOfTruth: { float censureStacks = 5; baseDamage = Stats.WeaponDamage * 0.018f * censureStacks; baseDamage += (1f + (0.01f * SP) + (0.0193f * AP)); baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; } case Ability.ShieldOfTheRighteous: if (Character.OffHand == null || Character.OffHand.Type != ItemType.Shield || Talents.ShieldOfTheRighteous == 0) { Damage = 0f; return; } baseDamage = 610.4895857f + (0.6f * AP); baseDamage *= (1.0f + (Talents.GlyphOfShieldOfTheRighteous ? 0.1f : 0f)) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; #endregion #region DoTs case Ability.CensureTick: { float censureStacks = 5; baseDamage = ((0.01f * SP) + (0.0193f * AP)) * censureStacks; baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure) * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 1.0f; break; } case Ability.Consecration: baseDamage = 81.32998299f + (0.027f * SP) + (0.027f * AP); // Per tick duration = Talents.GlyphOfConsecration ? 12f : 10f; //10.0f * (1f + (Talents.GlyphOfConsecration ? 0.2f : 0f)); baseDamage *= duration * (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.0f; break; #endregion #region Defensive case Ability.RetributionAura: baseDamage = 121.4802229f + (SP * 0.033f); baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier); critMultiplier = 0.0f; break; #endregion } baseDamage *= (1.0f + Stats.BonusDamageMultiplier); #endregion #region Miss Chance, Avoidance Chance if (Lookup.IsSpell(Ability)) { if (Ability == Ability.Consecration) { // Probability calculation, since each tick can be resisted individually. baseDamage = Lookup.GetConsecrationTickChances(duration, baseDamage, AttackTable.Miss); } else { // Missed spell attacks baseDamage *= (1.0f - AttackTable.Miss); } } else { // Avoidable attacks if (Lookup.IsAvoidable(Ability)) { baseDamage *= (1.0f - AttackTable.AnyMiss); } } #endregion // Average critical strike bonuses if (Lookup.CanCrit(Ability)) { baseDamage += baseDamage * critMultiplier * AttackTable.Critical; } // Final Damage the Ability deals Damage = baseDamage; }