public Stats getSpecialEffects(SpecialEffect effect)
 {
     Stats statsAverage = new Stats();
     if (effect == mainHandEnchant || effect == offHandEnchant)
     {
         if (mainHandEnchant != null && !mhProcessed)
         {
             statsAverage.Accumulate(mainHandEnchant.Stats, GetMHUptime());
             mhProcessed = true; 
         }
         else if (offHandEnchant != null && !ohProcessed)
         {
             statsAverage.Accumulate(offHandEnchant.Stats, GetOHUptime());
             ohProcessed = true; 
         }
     }
     else if (effect.Trigger == Trigger.Use)
     {
         effect.AccumulateAverageStats(statsAverage);
         foreach (SpecialEffect e in effect.Stats.SpecialEffects())
             statsAverage.Accumulate(this.getSpecialEffects(e) * (effect.Duration / effect.Cooldown));
     }
     else
     {
         SetTriggerChanceAndSpeed(effect);
         foreach (SpecialEffect e in effect.Stats.SpecialEffects())  // deal with secondary effects
         {
             statsAverage.Accumulate(this.getSpecialEffects(e));
         }
         if (effect.MaxStack > 1)
         {
             if (effect.Stats.MoteOfAnger > 0)
             {
                 // When in effect stats, MoteOfAnger is % of melee hits
                 // When in character stats, MoteOfAnger is average procs per second
                 statsAverage.Accumulate(new Stats() { MoteOfAnger = effect.Stats.MoteOfAnger * effect.GetAverageProcsPerSecond(trigger, chance, unhastedAttackSpeed, 0f) / effect.MaxStack });
             }
             else
             {
                 float timeToMax = (float)Math.Min(_cs.FightLength, effect.GetChance(unhastedAttackSpeed) * trigger * effect.MaxStack);
                 float buffDuration = _cs.FightLength;
                 if (effect.Stats.AttackPower == 250f || effect.Stats.AttackPower == 215f || effect.Stats.HasteRating == 57f || effect.Stats.HasteRating == 64f)
                 {
                     buffDuration = 20f;
                 }
                 if (timeToMax * .5f > buffDuration)
                 {
                     timeToMax = 2 * buffDuration;
                 }
                 statsAverage.Accumulate(effect.Stats * (effect.MaxStack * (((buffDuration) - .5f * timeToMax) / (buffDuration))));
             }
         }
         else
         {
             effect.AccumulateAverageStats(statsAverage, trigger, chance, unhastedAttackSpeed);
         }
     }
     return statsAverage;
 }
Exemple #2
0
        /// <summary>
        /// With Triggers already setup, just pass into the Accumulate function and return the values
        /// </summary>
        /// <param name="effect"></param>
        /// <returns></returns>
        public StatsDK getSpecialEffects(SpecialEffect effect)
        {
            StatsDK statsAverage = new StatsDK();

            triggerIntervals[Trigger.Use] = effect.Cooldown;
            if (float.IsInfinity(effect.Cooldown))
            {
                triggerIntervals[Trigger.Use] = m_bo.BerserkTimer;
            }

            effect.AccumulateAverageStats(statsAverage, triggerIntervals, triggerChances, unhastedAttackSpeed, m_bo.BerserkTimer);
            return(statsAverage);
        }
Exemple #3
0
        public Stats getSpecialEffects(CalculationOptionsDPSDK calcOpts, SpecialEffect effect)
        {
            Stats    statsAverage = new Stats();
            Rotation rotation     = calcOpts.rotation;

            if (effect.Trigger == Trigger.Use)
            {
                effect.AccumulateAverageStats(statsAverage);
                foreach (SpecialEffect e in effect.Stats.SpecialEffects())
                {
                    statsAverage.Accumulate(this.getSpecialEffects(calcOpts, e), (effect.Duration / effect.Cooldown));
                }
            }
            else
            {
                double trigger             = 0f;
                float  chance              = 0f;
                float  unhastedAttackSpeed = 2f;
                switch (effect.Trigger)
                {
                case Trigger.MeleeCrit:
                case Trigger.PhysicalCrit:
                    trigger             = (1f / ((rotation.getMeleeSpecialsPerSecond() * (combatTable.DW ? 2f : 1f)) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f)));
                    chance              = combatTable.physCrits;
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.MeleeHit:
                case Trigger.PhysicalHit:
                    trigger             = (1f / ((rotation.getMeleeSpecialsPerSecond() * (combatTable.DW ? 2f : 1f)) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f)));
                    chance              = 1f - (combatTable.missedSpecial + combatTable.dodgedSpecial) * (1f - combatTable.totalMHMiss);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.CurrentHandHit:
                    trigger = (1f / ((rotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f)));
                    chance  = 1f - (combatTable.missedSpecial + combatTable.dodgedSpecial) * (1f - combatTable.totalMHMiss);
                    // TODO: need to know if this is MH or OH.
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.MainHandHit:
                    trigger             = (1f / ((rotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f)));
                    chance              = 1f - (combatTable.missedSpecial + combatTable.dodgedSpecial) * (1f - combatTable.totalMHMiss);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.OffHandHit:
                    trigger             = (1f / ((rotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f)));
                    chance              = 1f - (combatTable.missedSpecial + combatTable.dodgedSpecial) * (1f - combatTable.totalMHMiss);
                    unhastedAttackSpeed = (combatTable.OH != null ? combatTable.OH.baseSpeed : 2.0f);
                    break;

                case Trigger.DamageDone:
                    trigger             = 1f / (((rotation.getMeleeSpecialsPerSecond() * (combatTable.DW ? 2f : 1f)) + rotation.getSpellSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime: 0.5f));
                    chance              = (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial)) * (1f - combatTable.totalMHMiss);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.DamageOrHealingDone:
                    // Need to add Self Healing
                    trigger             = 1f / (((rotation.getMeleeSpecialsPerSecond() * (combatTable.DW ? 2f : 1f)) + rotation.getSpellSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f));
                    chance              = (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial)) * (1f - combatTable.totalMHMiss);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.DamageSpellCast:
                case Trigger.SpellCast:
                case Trigger.DamageSpellHit:
                case Trigger.SpellHit:
                    trigger = 1f / rotation.getSpellSpecialsPerSecond();
                    chance  = 1f - combatTable.spellResist;
                    break;

                case Trigger.DamageSpellCrit:
                case Trigger.SpellCrit:
                    trigger = 1f / rotation.getSpellSpecialsPerSecond();
                    chance  = combatTable.spellCrits;
                    break;

                case Trigger.BloodStrikeHit:
                    trigger = rotation.CurRotationDuration / (rotation.BloodStrike * (combatTable.DW ? 2f : 1f));
                    chance  = 1f;
                    break;

                case Trigger.HeartStrikeHit:
                    trigger = rotation.CurRotationDuration / rotation.HeartStrike;
                    chance  = 1f;
                    break;

                case Trigger.BloodStrikeOrHeartStrikeHit:
                    trigger = rotation.CurRotationDuration / ((rotation.BloodStrike + rotation.HeartStrike) * (combatTable.DW ? 2f : 1f));
                    chance  = 1f;
                    break;

                case Trigger.ObliterateHit:
                    trigger = rotation.CurRotationDuration / (rotation.Obliterate * (combatTable.DW ? 2f : 1f));
                    chance  = 1f;
                    break;

                case Trigger.ScourgeStrikeHit:
                    trigger = rotation.CurRotationDuration / rotation.ScourgeStrike;
                    chance  = 1f;
                    break;

                case Trigger.DeathStrikeHit:
                    trigger = rotation.CurRotationDuration / rotation.DeathStrike;
                    chance  = 1f;
                    break;

                case Trigger.PlagueStrikeHit:
                    trigger = rotation.CurRotationDuration / (rotation.PlagueStrike * (combatTable.DW ? 2f : 1f));
                    chance  = 1f;
                    break;

                case Trigger.DoTTick:
                    trigger = (rotation.BloodPlague + rotation.FrostFever) / 3;
                    chance  = 1f;
                    break;
                }
#if false // Pull out the embedded handling in this situation.
                foreach (SpecialEffect e in effect.Stats.SpecialEffects())
                {
                    statsAverage.Accumulate(this.getSpecialEffects(calcOpts, e));
                }
 #endif
                if (effect.MaxStack > 1)
                {
                    float timeToMax    = (float)Math.Min(calcOpts.FightLength * 60, effect.GetChance(unhastedAttackSpeed) * trigger * effect.MaxStack);
                    float buffDuration = calcOpts.FightLength * 60f;
                    if (effect.Stats.AttackPower == 250f || effect.Stats.AttackPower == 215f || effect.Stats.HasteRating == 57f || effect.Stats.HasteRating == 64f)
                    {
                        buffDuration = 20f;
                    }
                    if (timeToMax * .5f > buffDuration)
                    {
                        timeToMax = 2 * buffDuration;
                    }
                    statsAverage.Accumulate(effect.Stats, effect.GetAverageStackSize((float)trigger, chance, unhastedAttackSpeed, buffDuration));
                }
                else
                {
                    effect.AccumulateAverageStats(statsAverage, (float)trigger, chance, unhastedAttackSpeed, calcOpts.FightLength * 60);
                }
            }

            return(statsAverage);
        }
        /// <summary>
        /// With Triggers already setup, just pass into the Accumulate function and return the values
        /// </summary>
        /// <param name="effect"></param>
        /// <returns></returns>
        public StatsHunter getSpecialEffects(SpecialEffect effect, Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, Character Char)
        {
            StatsHunter statsAverage = new StatsHunter();
            triggerIntervals[Trigger.Use] = effect.Cooldown;
            if (float.IsInfinity(effect.Cooldown)) triggerIntervals[Trigger.Use] = Char.BossOptions.BerserkTimer;

            ItemInstance RangeWeap = Char.Ranged;
            float unhastedAttackSpeed = (RangeWeap != null ? RangeWeap.Speed : 2.4f);

            effect.AccumulateAverageStats(statsAverage, triggerIntervals, triggerChances, unhastedAttackSpeed, Char.BossOptions.BerserkTimer);
            return statsAverage;
        }
        public Stats getSpecialEffects(CalculationOptionsTankDK calcOpts, SpecialEffect effect)
        {
            Stats    statsAverage = new Stats();
            Rotation rRotation    = calcOpts.m_Rotation;

            if (effect.Trigger == Trigger.Use)
            {
                if (calcOpts.bUseOnUseAbilities == true)
                {
                    statsAverage.Accumulate(effect.GetAverageStats());
                }
            }
            else
            {
                float trigger             = 0f;
                float chance              = effect.Chance;
                float duration            = effect.Duration;
                float unhastedAttackSpeed = 2f;
                switch (effect.Trigger)
                {
                case Trigger.MeleeCrit:
                case Trigger.PhysicalCrit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    chance              = combatTable.physCrits * effect.Chance;
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.MeleeHit:
                case Trigger.PhysicalHit:
                    trigger             = (1f / (rRotation.getMeleeSpecialsPerSecond() * (combatTable.m_bDW ? 2 : 1))) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.CurrentHandHit:
                case Trigger.MainHandHit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.MH.hastedSpeed != 0 ? 1f / combatTable.MH.hastedSpeed : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.OffHandHit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.OH.hastedSpeed != 0 ? 1f / combatTable.OH.hastedSpeed : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.DamageDone:
                case Trigger.DamageOrHealingDone:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    chance = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    break;

                case Trigger.DamageSpellCast:
                case Trigger.SpellCast:
                case Trigger.DamageSpellHit:
                case Trigger.SpellHit:
                    trigger = 1f / rRotation.getSpellSpecialsPerSecond();
                    chance  = 1f - combatTable.spellResist;
                    break;

                case Trigger.DamageSpellCrit:
                case Trigger.SpellCrit:
                    trigger = 1f / rRotation.getSpellSpecialsPerSecond();
                    chance  = combatTable.spellCrits * effect.Chance;
                    break;

                case Trigger.DoTTick:
                    trigger = (rRotation.BloodPlague + rRotation.FrostFever) / 3;
                    break;

                case Trigger.DamageTaken:
                case Trigger.DamageTakenPhysical:
                    trigger             = calcOpts.BossAttackSpeed;
                    chance             *= 1f - (stats.Dodge + stats.Parry + stats.Miss);
                    unhastedAttackSpeed = calcOpts.BossAttackSpeed;
                    break;

                case Trigger.DamageTakenMagical:
                    trigger = calcOpts.IncomingFromMagicFrequency;
                    break;

                //////////////////////////////////
                // DK specific triggers:
                case Trigger.BloodStrikeHit:
                case Trigger.HeartStrikeHit:
                    trigger = rRotation.curRotationDuration / (rRotation.BloodStrike + rRotation.HeartStrike);
                    break;

                case Trigger.PlagueStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.PlagueStrike;
                    break;

                case Trigger.RuneStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.RuneStrike;
                    break;

                case Trigger.IcyTouchHit:
                    trigger = rRotation.curRotationDuration / rRotation.IcyTouch;
                    break;

                case Trigger.DeathStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.DeathStrike;
                    break;

                case Trigger.ObliterateHit:
                    trigger = rRotation.curRotationDuration / rRotation.Obliterate;
                    break;

                case Trigger.ScourgeStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.ScourgeStrike;
                    break;

                case Trigger.FrostFeverHit:
                    // Icy Talons triggers off this.
                    trigger = rRotation.curRotationDuration / rRotation.IcyTouch;
                    if (character.DeathKnightTalents.GlyphofHowlingBlast)
                    {
                        trigger += rRotation.curRotationDuration / rRotation.HowlingBlast;
                    }
                    break;
                }
                if (!float.IsInfinity(trigger) && !float.IsNaN(trigger))
                {
                    if (effect.UsesPPM())
                    {
                        // If effect.chance < 0 , then it's using PPM.
                        // Let's get the duration * how many times it procs per min:
                        float UptimePerMin = 0;
                        float fWeight      = 0;
                        if (duration == 0) // Duration of 0 means that it's a 1 time effect that procs every time the proc comes up.
                        {
                            fWeight = Math.Abs(effect.Chance) / 60;
                        }
                        else
                        {
                            UptimePerMin = duration * Math.Abs(effect.Chance);
                            fWeight      = UptimePerMin / 60;
                        }
                        statsAverage.Accumulate(effect.Stats, fWeight);
                    }
                    else
                    {
                        effect.AccumulateAverageStats(statsAverage, trigger, chance, unhastedAttackSpeed, calcOpts.FightLength * 60);
                    }
                }
            }
            return(statsAverage);
        }
        /// <summary>
        /// With Triggers already setup, just pass into the Accumulate function and return the values
        /// </summary>
        /// <param name="effect"></param>
        /// <returns></returns>
        public StatsDK getSpecialEffects(SpecialEffect effect)
        {
            StatsDK statsAverage = new StatsDK();
            triggerIntervals[Trigger.Use] = effect.Cooldown;
            if (float.IsInfinity(effect.Cooldown)) triggerIntervals[Trigger.Use] = m_bo.BerserkTimer;

            effect.AccumulateAverageStats(statsAverage, triggerIntervals, triggerChances, unhastedAttackSpeed, m_bo.BerserkTimer);
            return statsAverage;
        }
Exemple #7
0
        public Stats getSpecialEffects(SpecialEffect effect)
        {
            Stats statsAverage = new Stats();

            if (effect == mainHandEnchant || effect == offHandEnchant)
            {
                if (mainHandEnchant != null && !mhProcessed)
                {
                    statsAverage.Accumulate(mainHandEnchant.Stats, GetMHUptime());
                    mhProcessed = true;
                }
                else if (offHandEnchant != null && !ohProcessed)
                {
                    statsAverage.Accumulate(offHandEnchant.Stats, GetOHUptime());
                    ohProcessed = true;
                }
            }
            else if (effect.Trigger == Trigger.Use)
            {
                effect.AccumulateAverageStats(statsAverage);
                foreach (SpecialEffect e in effect.Stats.SpecialEffects())
                {
                    statsAverage.Accumulate(this.getSpecialEffects(e) * (effect.Duration / effect.Cooldown));
                }
            }
            else
            {
                SetTriggerChanceAndSpeed(effect);
                foreach (SpecialEffect e in effect.Stats.SpecialEffects())  // deal with secondary effects
                {
                    statsAverage.Accumulate(this.getSpecialEffects(e));
                }
                if (effect.MaxStack > 1)
                {
                    if (effect.Stats.MoteOfAnger > 0)
                    {
                        // When in effect stats, MoteOfAnger is % of melee hits
                        // When in character stats, MoteOfAnger is average procs per second
                        statsAverage.Accumulate(new Stats()
                        {
                            MoteOfAnger = effect.Stats.MoteOfAnger * effect.GetAverageProcsPerSecond(trigger, chance, unhastedAttackSpeed, 0f) / effect.MaxStack
                        });
                    }
                    else
                    {
                        float timeToMax    = (float)Math.Min(_cs.FightLength, effect.GetChance(unhastedAttackSpeed) * trigger * effect.MaxStack);
                        float buffDuration = _cs.FightLength;
                        if (effect.Stats.AttackPower == 250f || effect.Stats.AttackPower == 215f || effect.Stats.HasteRating == 57f || effect.Stats.HasteRating == 64f)
                        {
                            buffDuration = 20f;
                        }
                        if (timeToMax * .5f > buffDuration)
                        {
                            timeToMax = 2 * buffDuration;
                        }
                        statsAverage.Accumulate(effect.Stats * (effect.MaxStack * (((buffDuration) - .5f * timeToMax) / (buffDuration))));
                    }
                }
                else
                {
                    effect.AccumulateAverageStats(statsAverage, trigger, chance, unhastedAttackSpeed);
                }
            }
            return(statsAverage);
        }