private float CalculateSpellCriticalChance(Unit victim, SpellInfo spellInfo, SpellSchoolMask schoolMask, Spell spell = null) { if (spellInfo.HasAttribute(SpellAttributes.CantCrit) || spellInfo.DamageClass == SpellDamageClass.None) { return(0.0f); } if (spellInfo.HasAttribute(SpellAttributes.AlwaysCrit)) { return(100.0f); } float critChance = unit.CritPercentage; if (victim == null) { return(Mathf.Max(critChance, 0.0f)); } switch (spellInfo.DamageClass) { case SpellDamageClass.Magic: if (!spellInfo.IsPositive) { critChance += victim.Auras.TotalAuraModifier(AuraEffectType.ModAttackerSpellCritChance); } goto default; case SpellDamageClass.Melee: if (!spellInfo.IsPositive) { critChance += victim.Auras.TotalAuraModifier(AuraEffectType.ModAttackerMeleeCritChance); } goto default; case SpellDamageClass.Ranged: if (!spellInfo.IsPositive) { critChance += victim.Auras.TotalAuraModifier(AuraEffectType.ModAttackerRangedCritChance); } goto default; default: critChance += victim.Auras.TotalAuraModifierForCaster(AuraEffectType.ModAttackerSpellCritChanceForCaster, unit.Id); critChance += victim.Auras.TotalAuraModifier(AuraEffectType.ModAttackerSpellAndWeaponCritChance); break; } IReadOnlyList <AuraEffect> spellCritAuras = unit.GetAuraEffects(AuraEffectType.OverrideSpellCritCalculation); if (spellCritAuras != null) { for (int i = 0; i < spellCritAuras.Count; i++) { if (spellCritAuras[i].EffectInfo is AuraEffectInfoOverrideSpellCritCalculation effectInfo) { effectInfo.ModifySpellCrit(unit, victim, spellInfo, ref critChance, spell); } } } return(Mathf.Max(critChance, 0.0f)); }