Ejemplo n.º 1
0
        private float CalcDamageProc(
            SpecialEffect effect,
            float damagePerProc,
            Dictionary <int, float> periods,
            Dictionary <int, float> chances,
            SpellModifiers modifiers)
        {
            damagePerProc *=
                modifiers.GetFinalDirectMultiplier()
                * (1
                   + (modifiers.GetFinalCritMultiplier() - 1)
                   * modifiers.CritChance)
                * (1
                   - StatConversion.GetAverageResistance(
                       80, Options.TargetLevel, 0f, 0f));
            float numProcs
                = Options.Duration
                  * effect.GetAverageProcsPerSecond(
                      periods[(int)effect.Trigger],
                      chances[(int)effect.Trigger],
                      CalculationsWarlock.AVG_UNHASTED_CAST_TIME,
                      Options.Duration);

            return(numProcs * damagePerProc);
        }
Ejemplo n.º 2
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;
 }
Ejemplo n.º 3
0
        // Functions
        public float GetActivates(float landedatksoverdur)
        {
            if (AbilIterater != -1 && !CalcOpts.Maintenance[AbilIterater])
            {
                return(0f);
            }
            float acts = Buff.GetAverageProcsPerSecond(landedatksoverdur / FightDuration, 1f /*MHAtkTable.AnyLand*/, combatFactors._c_mhItemSpeed, FightDuration);

            acts *= FightDuration;
            if (StatS.BonusWarrior_T10_4P_BSSDProcChange > 0)
            {
                acts *= 1.20f;
            }

            return(acts * (1f - Whiteattacks.RageSlip(FightDuration / acts, RageCost + UsedExtraRage)));
        }
Ejemplo n.º 4
0
        private float CalculateTotalDamagePerSecond(SpecialEffect effect, float baseDamage, ItemDamageType type)
        {
            float totalDamage         = 0f;
            float totalDamagePerSec   = 0f;
            float totalNumProcs       = 0f;
            float totalNumProcsPerSec = 0f;

            try {
                float triggerInterval = TriggerIntervals[effect.Trigger];
                float triggerChance   = TriggerChances[effect.Trigger];
                if (TriggerChances.ContainsKey(Trigger.MainHandHit) && MainHandEffects.Contains(effect) && (!OffHandEffects.Contains(effect) || !dualWieldProcs))
                {
                    triggerInterval = TriggerIntervals[Trigger.MainHandHit];
                    triggerChance   = TriggerChances[Trigger.MainHandHit];
                    if (OffHandEffects.Contains(effect))
                    {
                        dualWieldProcs = true;
                    }
                }
                else if (TriggerChances.ContainsKey(Trigger.OffHandHit) && OffHandEffects.Contains(effect))
                {
                    triggerInterval = TriggerIntervals[Trigger.OffHandHit];
                    triggerChance   = TriggerChances[Trigger.OffHandHit];
                }
                // Process the Effects
                totalNumProcsPerSec = effect.GetAverageProcsPerSecond(triggerInterval, triggerChance, Char.MainHand.Speed, FightDuration);
                totalNumProcs       = totalNumProcsPerSec * FightDuration;
                totalDamage         = totalNumProcs * CalculateThisDamage(type, baseDamage);
                totalDamagePerSec   = totalDamage / FightDuration;

                // Set our Results into the Dictionaries
                TotalDamage[type]         += totalDamage;
                TotalDamagePerSec[type]   += totalDamagePerSec;
                TotalNumProcs[type]       += totalNumProcs;
                TotalNumProcsPerSec[type] += totalNumProcsPerSec;
            } catch (Exception ex) {
                new Base.ErrorBox()
                {
                    Title        = "Error calculating special proc DPS",
                    Function     = "CalculateTotalDamagePerSecond(...)",
                    TheException = ex,
                }.Show();
            }

            return(totalDamagePerSec);
        }
Ejemplo n.º 5
0
        //private static Dictionary<float, SpecialEffect> _SE_StrikesOfOpportunity = new Dictionary<float,SpecialEffect>();

        public float GetActivates(float meleeAttemptsOverDur, float perc)
        {
            // This attack doesn't consume GCDs and doesn't affect the swing timer
            //float effectActs = _SE_StrikesOfOpportunity[DPSWarrChar.StatS.MasteryRating].GetAverageProcsPerSecond(
            var se = new SpecialEffect(Trigger.MeleeAttack, null, 0f, 0.5f,
                                       (float)Math.Min(Skills.StrikesOfOpportunity.BaseChance
                                                       + (float)Math.Max(0f, Skills.StrikesOfOpportunity.BonusChance
                                                                         * StatConversion.GetMasteryFromRating(DPSWarrChar.StatS.MasteryRating, CharacterClass.Warrior)), 1f)
                                       )
            {
                BypassCache = true
            };
            float effectActs = se.GetAverageProcsPerSecond((FightDuration * perc) / meleeAttemptsOverDur, 1f, DPSWarrChar.CombatFactors.CMHItemSpeed, FightDuration * perc);

            effectActs *= FightDuration * perc;
            return(effectActs);
        }
Ejemplo n.º 6
0
        public ProcEffect(SpecialEffect effect)
        {
            this.Effect = effect;
            // Shadow damage procs - most widely varied at the current moment
            if (effect.Stats.ShadowDamage > 0)
            {
                CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                {
                    SpecialEffect e = Effect;
                    float         specialDamageModifier = (1 + c.BasicStats.BonusSpellPowerMultiplier) * (1 + c.BasicStats.BonusShadowDamageMultiplier) * (1 + c.BasicStats.BonusDamageMultiplier);
                    float         triggerInterval       = 0.0f;
                    switch (e.Trigger)
                    {
                    case Trigger.DoTTick:           // Extract
                        triggerInterval = r.Duration / r.DotTicks;
                        break;

                    case Trigger.SpellHit:          // Pendulum
                        triggerInterval = r.Duration / r.CastCount;
                        break;

                    case Trigger.DamageDone:        // DMC: Death
                        triggerInterval = r.Duration / (r.CastCount + r.DotTicks);
                        break;

                    case Trigger.DamageOrHealingDone:        // DMC: Greatness
                        // Need to add Self-Heals
                        triggerInterval = r.Duration / (r.CastCount + r.DotTicks);
                        break;

                    default:
                        return(0.0f);
                    }
                    float procsPerSecond = e.GetAverageProcsPerSecond(triggerInterval, 1.0f, 3.0f, c.FightLength * 60.0f);
                    return(e.Stats.ShadowDamage * specialDamageModifier * procsPerSecond);
                };
            }
            // Lightning Capacitor, Thunder Capacitor, Reign of the Unliving/Undead, Nibelung
            else if (effect.Stats.NatureDamage > 0 || effect.Stats.FireDamage > 0 || effect.Stats.ValkyrDamage > 0)
            {
                if (effect.Stats.NatureDamage > 0)
                {
                    CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                    {
                        float specialDamageModifier = (1 + c.BasicStats.BonusSpellPowerMultiplier) * (1 + c.BasicStats.BonusNatureDamageMultiplier) * (1 + c.BasicStats.BonusDamageMultiplier);
                        float procsPerSecond        = Effect.GetAverageProcsPerSecond(r.Duration / (r.CastCount * sc), 1.0f, 3.0f, c.FightLength * 60.0f);
                        return(Effect.Stats.NatureDamage * specialDamageModifier * procsPerSecond);
                    };
                }
                else if (effect.Stats.FireDamage > 0)
                {
                    CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                    {
                        float specialDamageModifier = (1 + c.BasicStats.BonusSpellPowerMultiplier) * (1 + c.BasicStats.BonusFireDamageMultiplier) * (1 + c.BasicStats.BonusDamageMultiplier);
                        float procsPerSecond        = Effect.GetAverageProcsPerSecond(r.Duration / (r.CastCount * sc), 1.0f, 3.0f, c.FightLength * 60.0f);
                        return(Effect.Stats.FireDamage * specialDamageModifier * procsPerSecond);
                    };
                }
                else
                {
                    CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                    {
                        float specialDamageModifier = (1 + c.BasicStats.BonusSpellPowerMultiplier) * (1 + c.BasicStats.BonusDamageMultiplier);
                        float procsPerSecond        = Effect.GetAverageProcsPerSecond(r.Duration / (r.CastCount * sc), 1.0f, 3.0f, c.FightLength * 60.0f);
                        return(Effect.Stats.ValkyrDamage * specialDamageModifier * procsPerSecond);
                    };
                }
            }
            else if (effect.Stats.Mp5 > 0)
            {
                CalculateMP5 = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                {
                    SpecialEffect e = Effect;
                    float         procsPerSecond = e.GetAverageProcsPerSecond(r.Duration / r.CastCount, 1.0f, 3.0f, c.FightLength * 60f);
                    return((e.Stats.Mp5 / 5.0f * e.Duration) * procsPerSecond * 5.0f);
                };
            }
            // Moonkin 4T8 set bonus (15% chance on IS tick to proc an instant-cast Starfire)
            else if (effect.Stats.StarfireProc == 1)
            {
                CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float sp, float sHi, float sc, float sHa)
                {
                    if (r.InsectSwarmTicks == 0)
                    {
                        return(0.0f);
                    }
                    Spell newSF = new Spell()
                    {
                        AllDamageModifier      = r.Solver.Starfire.AllDamageModifier,
                        BaseCastTime           = 1.5f,
                        BaseDamage             = r.Solver.Starfire.BaseDamage,
                        BaseManaCost           = r.Solver.Starfire.BaseManaCost,
                        CriticalChanceModifier = r.Solver.Starfire.CriticalChanceModifier,
                        CriticalDamageModifier = r.Solver.Starfire.CriticalDamageModifier,
                        DotEffect           = null,
                        IdolExtraSpellPower = r.Solver.Starfire.IdolExtraSpellPower,
                        Name   = r.Solver.Starfire.Name,
                        School = r.Solver.Starfire.School,
                        SpellDamageModifier = r.Solver.Starfire.SpellDamageModifier
                    };
                    r.DoSpecialStarfire(c, ref newSF, sp, sHi, sc, sHa);
                    float timeBetweenProcs      = r.Solver.InsectSwarm.DotEffect.TickLength / Effect.Chance;
                    float replaceWrathWithSFDPS = (newSF.DamagePerHit / newSF.CastTime) - (r.Solver.Wrath.DamagePerHit / r.Solver.Wrath.CastTime);
                    float replaceSFWithSFDPS    = (newSF.DamagePerHit / newSF.CastTime) - (r.Solver.Starfire.DamagePerHit / r.Solver.Starfire.CastTime);
                    return((replaceWrathWithSFDPS * (r.WrathCount / (r.WrathCount + r.StarfireCount)) +
                            replaceSFWithSFDPS * (r.StarfireCount / (r.WrathCount + r.StarfireCount)))
                           / timeBetweenProcs);
                };
            }
            else if (Effect.Stats._rawSpecialEffectDataSize == 0 &&
                     (Effect.Trigger == Trigger.DamageDone ||
                      Effect.Trigger == Trigger.DamageOrHealingDone ||
                      Effect.Trigger == Trigger.DamageSpellCast ||
                      Effect.Trigger == Trigger.DamageSpellCrit ||
                      Effect.Trigger == Trigger.DamageSpellHit ||
                      Effect.Trigger == Trigger.SpellCast ||
                      Effect.Trigger == Trigger.SpellCrit ||
                      Effect.Trigger == Trigger.SpellHit ||
                      Effect.Trigger == Trigger.SpellMiss ||
                      Effect.Trigger == Trigger.Use ||
                      Effect.Trigger == Trigger.MoonfireCast ||
                      Effect.Trigger == Trigger.InsectSwarmOrMoonfireTick ||
                      Effect.Trigger == Trigger.MoonfireTick ||
                      Effect.Trigger == Trigger.InsectSwarmTick ||
                      Effect.Trigger == Trigger.DoTTick) &&
                     (Effect.Stats.HasteRating > 0 ||
                      Effect.Stats.SpellHaste > 0 ||
                      Effect.Stats.CritRating > 0 ||
                      Effect.Stats.HighestStat > 0))
            {
                Activate = delegate(Character ch, CharacterCalculationsMoonkin c, ref float sp, ref float sHi, ref float sc, ref float sHa)
                {
                    SpecialEffect e           = Effect;
                    int           maxStack    = e.MaxStack;
                    Stats         st          = e.Stats;
                    float         critRating  = st.CritRating;
                    float         spellCrit   = StatConversion.GetSpellCritFromRating(critRating * maxStack);
                    float         hasteRating = st.HasteRating;
                    float         spellHaste  = StatConversion.GetSpellHasteFromRating(hasteRating * maxStack);
                    spellHaste += st.SpellHaste;
                    float highestStat = st.HighestStat;

                    if (critRating > 0)
                    {
                        sc += spellCrit;
                    }
                    if (spellHaste > 0)
                    {
                        sHa += spellHaste;
                    }
                    if (highestStat > 0)
                    {
                        if (c.BasicStats.Spirit > c.BasicStats.Intellect)
                        {
                            Stats s = c.BasicStats.Clone();
                            s.Spirit += highestStat;
                            CharacterCalculationsMoonkin cNew = CalculationsMoonkin.GetInnerCharacterCalculations(ch, s, null);
                            storedStats.SpellPower = cNew.SpellPower - c.SpellPower;
                            sp += storedStats.SpellPower;
                        }
                        else
                        {
                            Stats s = c.BasicStats.Clone();
                            s.Intellect += highestStat;
                            CharacterCalculationsMoonkin cNew = CalculationsMoonkin.GetInnerCharacterCalculations(ch, s, null);
                            storedStats.SpellPower = cNew.SpellPower - c.SpellPower;
                            storedStats.SpellCrit  = cNew.SpellCrit - c.SpellCrit;
                            sp += storedStats.SpellPower;
                            sc += storedStats.SpellCrit;
                        }
                    }
                };
                Deactivate = delegate(Character ch, CharacterCalculationsMoonkin c, ref float sp, ref float sHi, ref float sc, ref float sHa)
                {
                    SpecialEffect e           = Effect;
                    int           maxStack    = e.MaxStack;
                    Stats         st          = e.Stats;
                    float         critRating  = st.CritRating;
                    float         spellCrit   = StatConversion.GetSpellCritFromRating(critRating * maxStack);
                    float         hasteRating = st.HasteRating;
                    float         spellHaste  = StatConversion.GetSpellHasteFromRating(hasteRating * maxStack);
                    spellHaste += st.SpellHaste;
                    float highestStat = st.HighestStat;

                    if (critRating > 0)
                    {
                        sc -= spellCrit;
                    }
                    if (spellHaste > 0)
                    {
                        sHa -= spellHaste;
                    }
                    if (highestStat > 0)
                    {
                        sp -= storedStats.SpellPower;
                        if (c.BasicStats.Intellect >= c.BasicStats.Spirit)
                        {
                            sc -= storedStats.SpellCrit;
                        }
                    }
                };
                UpTime = delegate(SpellRotation r, CharacterCalculationsMoonkin c)
                {
                    float upTime = 0.0f;
                    switch (Effect.Trigger)
                    {
                    case Trigger.Use:
                        upTime = Effect.GetAverageUptime(0f, 1f);
                        break;

                    case Trigger.SpellHit:
                    case Trigger.DamageSpellHit:
                        upTime = Effect.GetAverageUptime(r.Duration / r.CastCount, r.Solver.GetSpellHit(c));
                        break;

                    case Trigger.DamageSpellCrit:
                    case Trigger.SpellCrit:
                        upTime = Effect.GetAverageUptime(r.Duration / (r.CastCount - (r.InsectSwarmTicks / r.Solver.InsectSwarm.DotEffect.NumberOfTicks)), c.SpellCrit);
                        break;

                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                        upTime = Effect.GetAverageUptime(r.Duration / r.CastCount, 1f);
                        break;

                    case Trigger.MoonfireCast:
                        upTime = Effect.GetAverageUptime(r.Duration / r.MoonfireCasts, 1f);
                        break;

                    case Trigger.InsectSwarmOrMoonfireTick:
                        upTime = Effect.GetAverageUptime(r.Duration / (r.InsectSwarmTicks + r.MoonfireTicks), 1f);
                        break;

                    case Trigger.MoonfireTick:
                        upTime = Effect.GetAverageUptime(r.Duration / r.MoonfireTicks, 1f);
                        break;

                    case Trigger.InsectSwarmTick:
                        upTime = Effect.GetAverageUptime(r.Duration / r.InsectSwarmTicks, 1f);
                        break;

                    case Trigger.DoTTick:
                        upTime = Effect.GetAverageUptime(r.Duration / (r.MoonfireTicks + r.InsectSwarmTicks), 1f);
                        break;

                    case Trigger.DamageDone:
                    case Trigger.DamageOrHealingDone:
                        upTime = Effect.GetAverageUptime(((r.Duration / r.CastCount) + (r.Duration / (r.MoonfireTicks + r.InsectSwarmTicks))) / 2.0f, 1f);
                        break;

                    default:
                        break;
                    }
                    return(upTime);
                };
            }
        }
Ejemplo n.º 7
0
        private float CalculateTotalDamagePerSecond(SpecialEffect effect, float baseDamage, ItemDamageType type) {
            float totalDamage = 0f;
            float totalDamagePerSec = 0f;
            float totalNumProcs = 0f;
            float totalNumProcsPerSec = 0f;
            try {
                float triggerInterval = TriggerIntervals[effect.Trigger];
                float triggerChance = TriggerChances[effect.Trigger];
                if (TriggerChances.ContainsKey(Trigger.MainHandHit) && MainHandEffects.Contains(effect) && (!OffHandEffects.Contains(effect) || !dualWieldProcs))
                {
                    triggerInterval = TriggerIntervals[Trigger.MainHandHit];
                    triggerChance = TriggerChances[Trigger.MainHandHit];
                    if (OffHandEffects.Contains(effect)) dualWieldProcs = true;
                }
                else if (TriggerChances.ContainsKey(Trigger.OffHandHit) && OffHandEffects.Contains(effect))
                {
                    triggerInterval = TriggerIntervals[Trigger.OffHandHit];
                    triggerChance = TriggerChances[Trigger.OffHandHit];
                }
                // Process the Effects
                totalNumProcsPerSec = effect.GetAverageProcsPerSecond(triggerInterval, triggerChance, Char.MainHand.Speed, FightDuration);
                totalNumProcs = totalNumProcsPerSec * FightDuration;
                totalDamage = totalNumProcs * CalculateThisDamage(type, baseDamage);
                totalDamagePerSec = totalDamage / FightDuration;

                // Set our Results into the Dictionaries
                TotalDamage[type] += totalDamage;
                TotalDamagePerSec[type] += totalDamagePerSec;
                TotalNumProcs[type] += totalNumProcs;
                TotalNumProcsPerSec[type] += totalNumProcsPerSec;
            } catch (Exception ex) {
                new Base.ErrorBox()
                {
                    Title = "Error calculating special proc DPS",
                    Function = "CalculateTotalDamagePerSecond(...)",
                    TheException = ex,
                }.Show();
            }

            return totalDamagePerSec;
        }
 private float CalcDamageProc(SpecialEffect effect, float damagePerProc, Dictionary<int, float> periods, Dictionary<int, float> chances, SpellModifiers modifiers)
 {
     damagePerProc *=
           modifiers.GetFinalDirectMultiplier()
         * (1 + (modifiers.GetFinalCritMultiplier() - 1) * modifiers.CritChance)
         * (1 - StatConversion.GetAverageResistance(CalcOpts.PlayerLevel, CalcOpts.TargetLevel, 0f, 0f));
     float numProcs
         = BossOpts.BerserkTimer
             * effect.GetAverageProcsPerSecond(
                 periods[(int)effect.Trigger],
                 chances[(int)effect.Trigger],
                 CalculationsWarlock.AVG_UNHASTED_CAST_TIME,
                 BossOpts.BerserkTimer);
     return numProcs * damagePerProc;
 }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
        private float ApplySpecialEffect(SpecialEffect effect, DPSWarrCharacter charStruct, Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, ref Base.StatsWarrior applyTo)
        {
#if DEBUG
            //ConstructionCounts["ApplySpecialEffect"]++;
#endif
            float fightDuration = charStruct.BossOpts.BerserkTimer;
            float fightDuration2Pass = charStruct.CalcOpts.SE_UseDur ? fightDuration : 0;

            Stats effectStats = effect.Stats;

            float upTime = 0f;
            //float avgStack = 1f;
            /*if (effect.Stats.TargetArmorReduction > 0f || effect.Stats.ArmorPenetrationRating > 0f) {
                //int j = 0;
            }*/
            if (effect.Trigger == Trigger.Use) {
                if (effect.Stats._rawSpecialEffectDataSize == 1) {
                    upTime = effect.GetAverageUptime(0f, 1f, charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass);
                    //float uptime =  (effect.Cooldown / fightDuration);
                    List<SpecialEffect> nestedEffect = new List<SpecialEffect>();
                    nestedEffect.Add(effect.Stats._rawSpecialEffectData[0]);
                    Base.StatsWarrior _stats2 = new Base.StatsWarrior();
                    ApplySpecialEffect(effect.Stats._rawSpecialEffectData[0], charStruct, triggerIntervals, triggerChances, ref _stats2);
                    effectStats = _stats2;
                } else {
                    upTime = effect.GetAverageStackSize(0f, 1f, charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass); 
                }
            } else if (effect.Duration == 0f && triggerIntervals.ContainsKey(effect.Trigger) && !float.IsInfinity(triggerIntervals[effect.Trigger])) {
                upTime = effect.GetAverageProcsPerSecond(triggerIntervals[effect.Trigger], 
                                                         triggerChances[effect.Trigger],
                                                         charStruct.CombatFactors.CMHItemSpeed,
                                                         fightDuration2Pass);
            } else if (effect.Trigger == Trigger.ExecuteHit) {
                upTime = effect.GetAverageStackSize(triggerIntervals[effect.Trigger], 
                                                         triggerChances[effect.Trigger],
                                                         charStruct.CombatFactors.CMHItemSpeed,
                                                         fightDuration2Pass * (float)charStruct.BossOpts.Under20Perc);
            } else if (triggerIntervals.ContainsKey(effect.Trigger) && !float.IsInfinity(triggerIntervals[effect.Trigger])) {
                upTime = effect.GetAverageStackSize(triggerIntervals[effect.Trigger], 
                                                         triggerChances[effect.Trigger],
                                                         charStruct.CombatFactors.CMHItemSpeed,
                                                         fightDuration2Pass);
            }

            if (upTime > 0f) {
                if (effect.Duration == 0f) {
                    applyTo.Accumulate(effectStats, upTime * fightDuration);
                } else if (upTime <= effect.MaxStack) {
                    applyTo.Accumulate(effectStats, upTime);
                }
                return upTime;
            }
            return 0f;
        }
Ejemplo n.º 11
0
        private Stats IterativeSpecialEffectsStats(DPSWarrCharacter charStruct, List<SpecialEffect> specialEffects, List<SpecialEffect> critEffects,
            Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, float oldFlurryUptime,
            bool iterate, Base.StatsWarrior iterateOld, Base.StatsWarrior originalStats)
        {
#if DEBUG
            //ConstructionCounts["IterativeSpecialEffectsStats"]++;
#endif
            WarriorTalents talents = charStruct.Char.WarriorTalents;
            float fightDuration = charStruct.BossOpts.BerserkTimer;
            Base.StatsWarrior statsProcs = new Base.StatsWarrior();
            try {
                float dmgTakenInterval = fightDuration / charStruct.BossOpts.AoETargsFreq;

                //float attempted = charStruct.Rot.AttemptedAtksOverDur;
                //float land = charStruct.Rot.LandedAtksOverDur;
                //float crit = charStruct.Rot.CriticalAtksOverDur;

                //int LevelDif = charStruct.bossOpts.Level - charStruct.Char.Level;
                List<Trigger> critTriggers = new List<Trigger>();
                List<float> critWeights = new List<float>();
                bool needsHitTableReset = false;
                foreach (SpecialEffect effect in critEffects) {
                    needsHitTableReset = true;
                    critTriggers.Add(effect.Trigger);
                    critWeights.Add(1f);
                }
                foreach (SpecialEffect effect in specialEffects) {
                    #region old arp code
                    /*if (effect.Stats.ArmorPenetrationRating > 0) {
                        float arpenBuffs =
                            ((combatFactors.CmhItemType == ItemType.TwoHandMace) ? talents.MaceSpecialization * 0.03f : 0.00f) +
                            (!calcOpts.FuryStance ? (0.10f + originalStats.BonusWarrior_T9_2P_ArP) : 0.0f);

                        float OriginalArmorReduction = StatConversion.GetArmorDamageReduction(Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif],
                            originalStats.ArmorPenetration, arpenBuffs, originalStats.ArmorPenetrationRating);
                        float ProccedArmorReduction = StatConversion.GetArmorDamageReduction(Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif],
                            originalStats.ArmorPenetration + effect.Stats.ArmorPenetration, arpenBuffs, originalStats.ArmorPenetrationRating + effect.Stats.ArmorPenetrationRating);

                        Stats dummyStats = new Stats();
                        float procUptime = ApplySpecialEffect(effect, Char, Rot, combatFactors, calcOpts, originalStats.Dodge + originalStats.Parry, ref dummyStats);

                        float targetReduction = ProccedArmorReduction * procUptime + OriginalArmorReduction * (1f - procUptime);
                        //float arpDiff = OriginalArmorReduction - targetReduction;
                        float procArp = StatConversion.GetRatingFromArmorReduction(Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif],
                            originalStats.ArmorPenetration, arpenBuffs, targetReduction);
                        statsProcs.ArmorPenetrationRating += (procArp - originalStats.ArmorPenetrationRating);
                    } 
                    else */
                    #endregion
                    
                    float numProcs = 0;
                    if (effect.Stats.ManaorEquivRestore > 0f && effect.Stats.HealthRestoreFromMaxHealth > 0f) {
                        // effect.Duration = 0, so GetAverageStats won't work
                        float value1 = effect.Stats.ManaorEquivRestore;
                        float value2 = effect.Stats.HealthRestoreFromMaxHealth;
                        SpecialEffect dummy = new SpecialEffect(effect.Trigger, new Stats() { ManaorEquivRestore = value1, HealthRestoreFromMaxHealth = value2 }, effect.Duration, effect.Cooldown, effect.Chance) { BypassCache = true };
                        numProcs = dummy.GetAverageProcsPerSecond(dmgTakenInterval, originalStats.Dodge + originalStats.Parry, 0f, 0f) * fightDuration;
                        statsProcs.ManaorEquivRestore += dummy.Stats.ManaorEquivRestore * numProcs;
                        dummy.Stats.ManaorEquivRestore = 0f;
                        //numProcs = effect.GetAverageProcsPerSecond(triggerIntervals[Trigger.PhysicalCrit], triggerChances[Trigger.PhysicalCrit], 0f, 0f) * fightDuration;
                        //statsProcs.HealthRestoreFromMaxHealth += effect.Stats.HealthRestoreFromMaxHealth * numProcs;
                        ApplySpecialEffect(dummy, charStruct, triggerIntervals, triggerChances, ref statsProcs);
                    } else if (effect.Stats.ManaorEquivRestore > 0f) {
                        // effect.Duration = 0, so GetAverageStats won't work
                        numProcs = effect.GetAverageProcsPerSecond(dmgTakenInterval, originalStats.Dodge + originalStats.Parry, 0f, 0f) * fightDuration;
                        statsProcs.ManaorEquivRestore += effect.Stats.ManaorEquivRestore * numProcs;
                    } else if (effect.Stats.HealthRestoreFromMaxHealth > 0f) {
                        // effect.Duration = 0, so GetAverageStats won't work
                        numProcs = effect.GetAverageProcsPerSecond(dmgTakenInterval, originalStats.Dodge + originalStats.Parry, 0f, 0f) * fightDuration;
                        statsProcs.HealthRestoreFromMaxHealth += effect.Stats.HealthRestoreFromMaxHealth * numProcs;
                    } else {
                        ApplySpecialEffect(effect, charStruct, triggerIntervals, triggerChances, ref statsProcs);
                    }
                }

                WeightedStat[] critProcs;
                if (critEffects.Count == 0) {
                    critProcs = new WeightedStat[] { new WeightedStat() { Value = 0f, Chance = 1f } };
                } else if (critEffects.Count == 1) {
                    float interval = triggerIntervals[critEffects[0].Trigger];
                    float chance = triggerChances[critEffects[0].Trigger];
                    float upTime = critEffects[0].GetAverageStackSize(interval, chance, charStruct.CombatFactors.CMHItemSpeed,
                        (charStruct.CalcOpts.SE_UseDur ? charStruct.BossOpts.BerserkTimer : 0f));
                    upTime *= critWeights[0];
                    critProcs = new WeightedStat[] { new WeightedStat() { Value = critEffects[0].Stats.CritRating, Chance = upTime },
                                                     new WeightedStat() { Value = 0f, Chance = 1f - upTime } };
                } else {
                    float[] intervals = new float[critEffects.Count];
                    float[] chances = new float[critEffects.Count];
                    float[] offset = new float[critEffects.Count];
                    for (int i = 0; i < critEffects.Count; i++) {
                        intervals[i] = triggerIntervals[critEffects[i].Trigger];
                        chances[i] = triggerChances[critEffects[i].Trigger];
                    }

                    critProcs = SpecialEffect.GetAverageCombinedUptimeCombinations(critEffects.ToArray(), intervals, chances, offset, critWeights.ToArray(), charStruct.CombatFactors.CMHItemSpeed,
                        charStruct.BossOpts.BerserkTimer, AdditiveStat.CritRating);
                }
                charStruct.CombatFactors.CritProcs = critProcs;
                float flurryUptime = 0f;
                if (iterate && talents.Flurry > 0f && charStruct.CombatFactors.FuryStance && charStruct.Char.MainHand != null && charStruct.Char.MainHand.Item != null)
                {
                    float numFlurryHits = 3f; // default
                    float mhPerc = 1f; // 100% by default
                    float flurryHaste = 0.25f / 3f * talents.Flurry;
                    bool useOffHand = false;
                    
                    float flurryHitsPerSec = charStruct.CombatFactors.TotalHaste * (1f + flurryHaste) / (1f + flurryHaste * oldFlurryUptime);
                    float temp = 1f / charStruct.Char.MainHand.Item.Speed;
                    if (charStruct.Char.OffHand != null && charStruct.Char.OffHand.Item != null) {
                        useOffHand = true;
                        temp += 1f / charStruct.Char.OffHand.Item.Speed;
                        mhPerc = (charStruct.Char.MainHand.Speed / charStruct.Char.OffHand.Speed) / (1f + charStruct.Char.MainHand.Speed / charStruct.Char.OffHand.Speed);
                        if (charStruct.Char.OffHand.Speed == charStruct.Char.MainHand.Speed) numFlurryHits = 4f;
                    }
                    
                    flurryHitsPerSec *= temp;
                    float flurryDuration = numFlurryHits / flurryHitsPerSec;
                    flurryUptime = 1f;
                    foreach (AbilityWrapper aw in charStruct.Rot.DamagingAbilities) {
                        if (aw.Ability.CanCrit && aw.AllNumActivates > 0f)
                        {
                            float tempFactor = (float) Math.Pow(1f - aw.Ability.MHAtkTable.Crit,
                                                                flurryDuration*
                                                                (aw.AllNumActivates*aw.Ability.SwingsPerActivate*
                                                                 aw.Ability.AvgTargets/fightDuration));
                            flurryUptime *= tempFactor;
                            if (aw.Ability.SwingsOffHand && useOffHand)
                            {
                                flurryUptime *= (float) Math.Pow(1f - aw.Ability.OHAtkTable.Crit,
                                                                 flurryDuration*
                                                                 (aw.AllNumActivates*aw.Ability.SwingsPerActivate*
                                                                  aw.Ability.AvgTargets/fightDuration));
                            }
                        }
                    }
                    flurryUptime *= (float)Math.Pow(1f - charStruct.Rot.DPSWarrChar.Whiteattacks.MHAtkTable.Crit, numFlurryHits * mhPerc);
                    flurryUptime *= (float)Math.Pow(1f - charStruct.Rot.DPSWarrChar.Whiteattacks.OHAtkTable.Crit, numFlurryHits * (1f - mhPerc));
                    flurryUptime = 1f - flurryUptime;
                    statsProcs.PhysicalHaste = (1f + statsProcs.PhysicalHaste) * (1f + flurryHaste * flurryUptime) - 1f;
                }

                charStruct.CombatFactors.StatS = UpdateStatsAndAdd(statsProcs, originalStats, charStruct.Char);
                charStruct.CombatFactors.InvalidateCache();
                //Rot.InvalidateCache();
                if (iterate) {
                    const float precisionWhole = 0.01f;
                    const float precisionDec = 0.0001f;
                    if (statsProcs.Agility - iterateOld.Agility > precisionWhole ||
                        statsProcs.HasteRating - iterateOld.HasteRating > precisionWhole ||
                        statsProcs.HitRating - iterateOld.HitRating > precisionWhole ||
                        statsProcs.CritRating - iterateOld.CritRating > precisionWhole ||
                        statsProcs.PhysicalHaste - iterateOld.PhysicalHaste > precisionDec ||
                        statsProcs.PhysicalCrit - iterateOld.PhysicalCrit > precisionDec ||
                        statsProcs.PhysicalHit - iterateOld.PhysicalHit > precisionDec)
                    {
                        if (needsHitTableReset) charStruct.Rot.ResetHitTables();
                        charStruct.Rot.DoIterations();
                        CalculateTriggers(charStruct, triggerIntervals, triggerChances);
                        return IterativeSpecialEffectsStats(charStruct,
                            specialEffects, critEffects, triggerIntervals, triggerChances, flurryUptime, true, statsProcs, originalStats);
                    } else { /*int j = 0;*/ }
                }

                return statsProcs;
            } catch (Exception ex) {
                new Base.ErrorBox()
                {
                    Title = "Error in creating SpecialEffects Stats",
                    Function = "GetSpecialEffectsStats()",
                    TheException = ex,
                }.Show();
                return new Stats();
            }
        }
Ejemplo n.º 12
0
        public ProcEffect(SpecialEffect effect)
        {
            this.Effect = effect;
            // Damage procs - unified code handler
            if (effect.Stats.ShadowDamage > 0 || effect.Stats.FireDamage > 0 || effect.Stats.FrostDamage > 0 ||
                effect.Stats.NatureDamage > 0 || effect.Stats.HolyDamage > 0 || effect.Stats.ArcaneDamage > 0 ||
                effect.Stats.HolySummonedDamage > 0)
            {
                CalculateDPS = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float fightLength, float sp, float sHi, float sc, float sHa)
                {
                    SpecialEffect e = Effect;
                    float         schoolModifier = 1 +
                                                   (effect.Stats.ShadowDamage > 0 ? c.BasicStats.BonusShadowDamageMultiplier : 0) +
                                                   (effect.Stats.FireDamage > 0 ? c.BasicStats.BonusFireDamageMultiplier : 0) +
                                                   (effect.Stats.FrostDamage > 0 ? c.BasicStats.BonusFrostDamageMultiplier : 0) +
                                                   (effect.Stats.NatureDamage > 0 ? c.BasicStats.BonusNatureDamageMultiplier : 0) +
                                                   (effect.Stats.HolyDamage > 0 ? c.BasicStats.BonusHolyDamageMultiplier : 0) +
                                                   (effect.Stats.ArcaneDamage > 0 ? c.BasicStats.BonusArcaneDamageMultiplier : 0);
                    float specialDamageModifier = schoolModifier;
                    float baseValue = e.Stats.ShadowDamage + e.Stats.FireDamage + e.Stats.FrostDamage + e.Stats.NatureDamage + e.Stats.HolyDamage + e.Stats.ArcaneDamage + e.Stats.HolySummonedDamage;
                    float triggerInterval = 0.0f, triggerChance = 1.0f;
                    switch (e.Trigger)
                    {
                    case Trigger.DoTTick:
                        triggerInterval = r.RotationData.Duration / r.RotationData.DotTicks;
                        break;

                    case Trigger.DamageSpellHit:
                    case Trigger.SpellHit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sHi;
                        break;

                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        break;

                    case Trigger.SpellCrit:
                    case Trigger.DamageSpellCrit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sc * sHi;
                        break;

                    case Trigger.DamageDone:
                    case Trigger.DamageOrHealingDone:
                        triggerInterval = r.RotationData.Duration / (r.RotationData.CastCount + r.RotationData.DotTicks);
                        break;

                    case Trigger.Use:
                        break;

                    default:
                        return(0.0f);
                    }
                    float procsPerSecond = e.GetAverageProcsPerSecond(triggerInterval, triggerChance, 3.0f, fightLength * 60.0f);
                    return(baseValue * (e.Duration == 0 ? 1 : e.Duration) * specialDamageModifier * procsPerSecond);
                };
            }
            if (effect.Stats.Mp5 > 0)
            {
                CalculateMP5 = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float fightLength, float sp, float sHi, float sc, float sHa)
                {
                    SpecialEffect e = Effect;
                    float         triggerInterval = 0.0f, triggerChance = 1.0f;
                    switch (e.Trigger)
                    {
                    case Trigger.DoTTick:
                        triggerInterval = r.RotationData.Duration / r.RotationData.DotTicks;
                        break;

                    case Trigger.DamageSpellHit:
                    case Trigger.SpellHit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sHi;
                        break;

                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        break;

                    case Trigger.SpellCrit:
                    case Trigger.DamageSpellCrit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sc * sHi;
                        break;

                    case Trigger.DamageDone:
                    case Trigger.DamageOrHealingDone:
                        triggerInterval = r.RotationData.Duration / (r.RotationData.CastCount + r.RotationData.DotTicks);
                        break;

                    case Trigger.Use:
                        break;

                    default:
                        return(0.0f);
                    }
                    float procsPerSecond = e.GetAverageProcsPerSecond(triggerInterval, triggerChance, 3.0f, fightLength * 60f);
                    return((e.Stats.Mp5 / 5.0f * e.Duration) * procsPerSecond * 5.0f);
                };
            }
            if (effect.Stats.ManaRestoreFromMaxManaPerSecond > 0)
            {
                CalculateMP5 = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float fightLength, float sp, float sHi, float sc, float sHa)
                {
                    SpecialEffect e = Effect;
                    float         triggerInterval = 0.0f, triggerChance = 1.0f;
                    switch (e.Trigger)
                    {
                    case Trigger.DoTTick:
                        triggerInterval = r.RotationData.Duration / r.RotationData.DotTicks;
                        break;

                    case Trigger.DamageSpellHit:
                    case Trigger.SpellHit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sHi;
                        break;

                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        break;

                    case Trigger.SpellCrit:
                    case Trigger.DamageSpellCrit:
                        triggerInterval = r.RotationData.Duration / r.RotationData.CastCount;
                        triggerChance   = sc * sHi;
                        break;

                    case Trigger.DamageDone:
                    case Trigger.DamageOrHealingDone:
                        triggerInterval = r.RotationData.Duration / (r.RotationData.CastCount + r.RotationData.DotTicks);
                        break;

                    case Trigger.Use:
                        break;

                    default:
                        return(0.0f);
                    }
                    float procsPerSecond = e.GetAverageProcsPerSecond(triggerInterval, triggerChance, 3.0f, fightLength * 60f);
                    return(e.Stats.ManaRestoreFromMaxManaPerSecond * c.BasicStats.Mana * e.Duration * procsPerSecond * 5.0f);
                };
            }
            if (Effect.Stats._rawSpecialEffectDataSize == 0 &&
                (Effect.Trigger == Trigger.DamageDone ||
                 Effect.Trigger == Trigger.DamageOrHealingDone ||
                 Effect.Trigger == Trigger.DamageSpellCast ||
                 Effect.Trigger == Trigger.DamageSpellCrit ||
                 Effect.Trigger == Trigger.DamageSpellHit ||
                 Effect.Trigger == Trigger.SpellCast ||
                 Effect.Trigger == Trigger.SpellCrit ||
                 Effect.Trigger == Trigger.SpellHit ||
                 Effect.Trigger == Trigger.SpellMiss ||
                 Effect.Trigger == Trigger.Use ||
                 Effect.Trigger == Trigger.MoonfireCast ||
                 Effect.Trigger == Trigger.InsectSwarmCast ||
                 Effect.Trigger == Trigger.InsectSwarmOrMoonfireCast ||
                 Effect.Trigger == Trigger.MoonfireTick ||
                 Effect.Trigger == Trigger.InsectSwarmTick ||
                 Effect.Trigger == Trigger.DoTTick) &&
                (Effect.Stats.HasteRating > 0 ||
                 Effect.Stats.SpellHaste > 0))
            {
                Activate = delegate(Character ch, CharacterCalculationsMoonkin c, ref float sp, ref float sHi, ref float sc, ref float sHa, ref float m)
                {
                    SpecialEffect e           = Effect;
                    int           maxStack    = e.MaxStack;
                    Stats         st          = e.Stats;
                    float         hasteRating = st.HasteRating;
                    float         spellHaste  = StatConversion.GetSpellHasteFromRating(hasteRating * maxStack);
                    spellHaste += st.SpellHaste;
                    //float highestStat = st.HighestStat;

                    if (spellHaste > 0)
                    {
                        sHa += spellHaste;
                    }

                    /*if (st.Intellect > 0 || highestStat > 0)
                     * {
                     *  float procIntellect = (float)Math.Floor((1 + c.BasicStats.BonusIntellectMultiplier) * (st.Intellect + st.HighestStat));
                     *  storedStats.SpellPower = (float)Math.Floor((1 + c.BasicStats.BonusSpellPowerMultiplier) * procIntellect);
                     *  storedStats.SpellCrit = StatConversion.GetSpellCritFromIntellect(procIntellect);
                     *  sp += storedStats.SpellPower;
                     *  sc += storedStats.SpellCrit;
                     * }*/
                };
                Deactivate = delegate(Character ch, CharacterCalculationsMoonkin c, ref float sp, ref float sHi, ref float sc, ref float sHa, ref float m)
                {
                    SpecialEffect e           = Effect;
                    int           maxStack    = e.MaxStack;
                    Stats         st          = e.Stats;
                    float         hasteRating = st.HasteRating;
                    float         spellHaste  = StatConversion.GetSpellHasteFromRating(hasteRating * maxStack);
                    spellHaste += st.SpellHaste;
                    //float highestStat = st.HighestStat;

                    if (spellHaste > 0)
                    {
                        sHa -= spellHaste;
                    }

                    /*if (st.Intellect > 0 || highestStat > 0)
                     * {
                     *  sp -= storedStats.SpellPower;
                     *  sc -= storedStats.SpellCrit;
                     * }*/
                };
                UpTime = delegate(SpellRotation r, CharacterCalculationsMoonkin c, float fightLength, float sub35Percent)
                {
                    float upTime   = 0.0f;
                    float procTime = fightLength * 60.0f * (Effect.LimitedToExecutePhase ? sub35Percent : 1f);
                    switch (Effect.Trigger)
                    {
                    case Trigger.Use:
                        upTime = Effect.GetAverageUptime(0f, 1f, 3.0f, procTime);
                        break;

                    case Trigger.SpellHit:
                    case Trigger.DamageSpellHit:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.CastCount, 1 - Math.Max(0, c.SpellHitCap - c.SpellHit), 3.0f, procTime);
                        break;

                    case Trigger.DamageSpellCrit:
                    case Trigger.SpellCrit:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / (r.RotationData.CastCount - r.RotationData.InsectSwarmCasts), c.SpellCrit, 3.0f, procTime);
                        break;

                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.CastCount, 1f, 3.0f, procTime);
                        break;

                    case Trigger.MoonfireCast:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.MoonfireCasts, 1f, 3.0f, procTime);
                        break;

                    case Trigger.InsectSwarmCast:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.InsectSwarmCasts, 1f, 3.0f, procTime);
                        break;

                    case Trigger.InsectSwarmOrMoonfireCast:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / (r.RotationData.MoonfireCasts + r.RotationData.InsectSwarmCasts), 1f, 3.0f, procTime);
                        break;

                    case Trigger.EclipseProc:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / 2f, 1f, 3.0f, procTime);
                        break;

                    case Trigger.MoonfireTick:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.MoonfireTicks, 1f, 3.0f, procTime);
                        break;

                    case Trigger.InsectSwarmTick:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / r.RotationData.InsectSwarmTicks, 1f, 3.0f, procTime);
                        break;

                    case Trigger.DoTTick:
                        upTime = Effect.GetAverageUptime(r.RotationData.Duration / (r.RotationData.MoonfireTicks + r.RotationData.InsectSwarmTicks), 1f, 3.0f, procTime);
                        break;

                    case Trigger.DamageDone:
                    case Trigger.DamageOrHealingDone:
                        upTime = Effect.GetAverageUptime(((r.RotationData.Duration / r.RotationData.CastCount) + (r.RotationData.Duration / (r.RotationData.MoonfireTicks + r.RotationData.InsectSwarmTicks))) / 2.0f, 1f, 3.0f, procTime);
                        break;

                    default:
                        break;
                    }
                    return(upTime * (Effect.LimitedToExecutePhase ? sub35Percent : 1f));
                };
            }
        }
Ejemplo n.º 13
0
 private float GetAverageFactor(SpecialEffect effect)
 {
     float triggerInterval;
     float triggerChance;
     if (GetTriggerData(effect, out triggerInterval, out triggerChance))
     {
         float durationMultiplier = 1;
         if (effect.LimitedToExecutePhase)
         {
             durationMultiplier = CastingState.CalculationOptions.MoltenFuryPercentage;
         }
         if (effect.MaxStack > 1)
         {
             return durationMultiplier * effect.GetAverageStackSize(triggerInterval, triggerChance, 3f, durationMultiplier * CastingState.CalculationOptions.FightDuration);
         }
         else if (effect.Duration > 0)
         {
             return durationMultiplier * effect.GetAverageUptime(triggerInterval, triggerChance, 3f, durationMultiplier * CastingState.CalculationOptions.FightDuration);
         }
         else
         {
             return durationMultiplier * effect.GetAverageProcsPerSecond(triggerInterval, triggerChance, 3f, durationMultiplier * CastingState.CalculationOptions.FightDuration);
         }
     }
     return 0;
 }
Ejemplo n.º 14
0
        //private static Dictionary<float, SpecialEffect> _SE_StrikesOfOpportunity = new Dictionary<float,SpecialEffect>();

        public float GetActivates(float meleeAttemptsOverDur, float perc)
        {
            // This attack doesn't consume GCDs and doesn't affect the swing timer
            //float effectActs = _SE_StrikesOfOpportunity[DPSWarrChar.StatS.MasteryRating].GetAverageProcsPerSecond(
            var se = new SpecialEffect(Trigger.MeleeAttack, null, 0f, 0.5f,
                            (float)Math.Min(Skills.StrikesOfOpportunity.BaseChance
                                + (float)Math.Max(0f, Skills.StrikesOfOpportunity.BonusChance
                                    * StatConversion.GetMasteryFromRating(DPSWarrChar.StatS.MasteryRating, CharacterClass.Warrior)), 1f)
                    ) { BypassCache = true };
            float effectActs = se.GetAverageProcsPerSecond((FightDuration * perc) / meleeAttemptsOverDur, 1f, DPSWarrChar.CombatFactors.CMHItemSpeed, FightDuration * perc);
            effectActs *= FightDuration * perc;
            return effectActs;
        }