Beispiel #1
0
 protected void Initialize(Character character, StatsHunter stats, CombatFactors cf, CalculationOptionsHunter co,
     Skills.Ability ability, bool useSpellHit, bool alwaysHit)
 {
     Char = character;
     StatS = stats;
     calcOpts = co;
     combatFactors = cf;
     Abil = ability;
     if (Abil == null)
     {
         isWhite = true;
     }
     else
     {
         Abil.combatFactors = combatFactors;
     }
     PetAbil = PetAttacks.None;
     this.useSpellHit = useSpellHit;
     /*// Defaults
     Miss 
     Dodge
     Parry
     Block
     Glance
     Critical
     Hit*/
     // Start a calc            
     if (alwaysHit) CalculateAlwaysHit();
     else Calculate();            
 }
Beispiel #2
0
        public static StatsHunter operator *(StatsHunter a, float b)
        {
            StatsHunter c = new StatsHunter();

            int i = c._rawAdditiveHunterData.Length;

            while (--i >= 0)
            {
                c._rawAdditiveHunterData[i] = a._rawAdditiveHunterData[i] * b;
            }
            i = c._rawMultiplicativeHunterData.Length;
            while (--i >= 0)
            {
                c._rawMultiplicativeHunterData[i] = a._rawMultiplicativeHunterData[i] * b;
            }
            i = c._rawInverseMultiplicativeHunterData.Length;
            while (--i >= 0)
            {
                c._rawInverseMultiplicativeHunterData[i] = a._rawInverseMultiplicativeHunterData[i] * b;
            }

            i = c._rawNoStackHunterData.Length;
            while (--i >= 0)
            {
                c._rawNoStackHunterData[i] = a._rawNoStackHunterData[i] * b;
            }
            return(c);
        }
Beispiel #3
0
 /// <summary>
 /// <b>Bestial Wrath</b>, Instant, 2 min cooldown
 /// <para>Send your pet into a rage causing 20% additional damage for 10 sec.  The beast does not feel pity or remorse or fear and it cannot be stopped unless killed.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Longevity - Reduces the cooldown of your Bestial Wrath, Intimidation and Pet Special Abilities by 10/20/30%.
 /// The Beast Within - While your pet is under the effects of Bestial Wrath, you also go into a rage causing 10% additional damage and reducing the focus cost of all shots and abilities by 50% for 10 sec.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Bestial Wrath - Decreases the cooldown of Bestial Wrath by 20 sec.</GlyphsAffecting>
 public BestialWrath(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name             = "Bestial Wrath";
     Cd               = ((2f * 60f) * (1f - Talents.Longevity)) - (Talents.GlyphOfBestialWrath ? 20f : 0f); // In Seconds
     Duration         = 10f;
     UseHitTable      = false;
     ReqTalent        = true;
     Talent2ChksValue = Talents.BestialWrath;
     // TODO: Move these to static SEs.
     Effect = new SpecialEffect(Trigger.Use,
                                new Stats()
     {
         BonusPetDamageMultiplier = 0.20f
     }, Duration, Cd);
     if (Talents.TheBeastWithin > 0f)
     {
         Effect = new SpecialEffect(Trigger.Use,
                                    new Stats()
         {
             BonusDamageMultiplier = 0.10f
         }, Duration, Cd);
     }
     Initialize();
 }
Beispiel #4
0
        public CombatFactors(Character character, StatsHunter stats, CalculationOptionsHunter calcOpts, BossOptions bossOpts)
        {
            Char = character;
            if (Char != null)
            {
                if (Char.Ranged != null)
                {
                    RW = Char.Ranged.Item;
                }
                else
                {
                    RW = new Knuckles();
                }
                if (Char.HunterTalents != null)
                {
                    Talents = Char.HunterTalents;
                }
                else
                {
                    Talents = new HunterTalents();
                }
            }
            CalcOpts = (calcOpts == null ? new CalculationOptionsHunter() : calcOpts);
            BossOpts = (bossOpts == null ? new BossOptions() : bossOpts);
            StatS    = stats;
            InvalidateCache();
            // Optimizations

            //Set_c_values();
        }
Beispiel #5
0
        protected void Initialize(Character character, StatsHunter stats, CalculationOptionsHunter co,
                                  float[] avoidChances, PetAttacks ability, bool useSpellHit, bool alwaysHit)
        {
            Char             = character;
            StatS            = stats;
            calcOpts         = co;
            combatFactors    = null;
            Abil             = null;
            PetAbil          = ability;
            isWhite          = (PetAbil == PetAttacks.None);
            this.useSpellHit = useSpellHit;

            /*// Defaults
             * Miss
             * Dodge
             * Parry
             * Block
             * Glance
             * Critical
             * Hit*/
            // Start a calc
            if (alwaysHit)
            {
                CalculateAlwaysHit();
            }
            else
            {
                Calculate(avoidChances);
            }
        }
Beispiel #6
0
 public HunterBase(Character charac, StatsHunter stats, HunterTalents talents, Specialization spec, int targetLvL)
 {
     character   = charac;
     Stats       = stats;
     Talents     = talents;
     Tree        = spec;
     TargetLevel = targetLvL;
 }
Beispiel #7
0
 public HunterBase (Character charac, StatsHunter stats, HunterTalents talents, Specialization spec, int targetLvL)
 {
     character = charac;
     Stats = stats;
     Talents = talents;
     Tree = spec;
     TargetLevel = targetLvL;
 }
Beispiel #8
0
 /// <summary>
 /// <b>Readiness</b>, Instant, 3 min Cd
 /// <para>When activated, this ability immediately finishes the cooldown on all Hunter abilities.</para>
 /// </summary>
 /// <TalentsAffecting></TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public Readiness(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name        = "Readiness";
     Cd          = 3f * 60f; // In Seconds
     Duration    = 0f;
     UseHitTable = false;
     Initialize();
 }
Beispiel #9
0
 /// <summary>
 /// <b>Readiness</b>, Instant, 3 min Cd
 /// <para>When activated, this ability immediately finishes the cooldown on all Hunter abilities.</para>
 /// </summary>
 /// <TalentsAffecting></TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public Readiness(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Readiness";
     Cd = 3f * 60f; // In Seconds
     Duration = 0f;
     UseHitTable = false;
     Initialize();
 }
Beispiel #10
0
 /// <summary>
 /// <b>Rapid Fire</b>, Instant, 5 min Cd
 /// <para>Increases ranged attack speed by 40% for 15 sec.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Posthaste - Reduces the cooldown of your Rapid Fire by 1/2 min, and your movement speed is increased by 15/30% for 4 sec after you use Disengage.
 /// Rapid Recuperation - You gain 6/12 focus every 3 sec while under the effect of Rapid Fire, and you gain 50 focus instantly when you gain Rapid Killing.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Rapid Fire [+10% Haste Bonus]</GlyphsAffecting>
 public RapidFire(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Rapid Fire";
     Cd = (5f - Talents.Posthaste) * 60f; // In Seconds
     Duration = 15f;
     UseHitTable = false;
     Effect = _RAPIDFIRE[Talents.GlyphOfRapidFire ? 1 : 0][Talents.Posthaste];
     Initialize();
 }
Beispiel #11
0
 /// <summary>
 /// <b>Rapid Fire</b>, Instant, 5 min Cd
 /// <para>Increases ranged attack speed by 40% for 15 sec.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Posthaste - Reduces the cooldown of your Rapid Fire by 1/2 min, and your movement speed is increased by 15/30% for 4 sec after you use Disengage.
 /// Rapid Recuperation - You gain 6/12 focus every 3 sec while under the effect of Rapid Fire, and you gain 50 focus instantly when you gain Rapid Killing.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Rapid Fire [+10% Haste Bonus]</GlyphsAffecting>
 public RapidFire(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name        = "Rapid Fire";
     Cd          = (5f - Talents.Posthaste) * 60f; // In Seconds
     Duration    = 15f;
     UseHitTable = false;
     Effect      = _RAPIDFIRE[Talents.GlyphOfRapidFire ? 1 : 0][Talents.Posthaste];
     Initialize();
 }
Beispiel #12
0
        /// <summary>Clones the stats object for duplication with separation</summary>
        public new StatsHunter Clone()
        {
            StatsHunter clone  = (StatsHunter)this.MemberwiseClone();
            StatsHunter retVal = new StatsHunter();

            retVal.Accumulate(base.Clone());
            retVal._rawAdditiveHunterData              = (float[])clone._rawAdditiveHunterData.Clone();
            retVal._rawMultiplicativeHunterData        = (float[])clone._rawMultiplicativeHunterData.Clone();
            retVal._rawInverseMultiplicativeHunterData = (float[])clone._rawInverseMultiplicativeHunterData.Clone();
            retVal._rawNoStackHunterData = (float[])clone._rawNoStackHunterData.Clone();
            return(retVal);
        }
Beispiel #13
0
        public PetCalculations(Character character, CharacterCalculationsHunter calculatedStats, CalculationOptionsHunter calcopts, BossOptions bossOpts,
            StatsHunter hunterStats)
        {
            this.character = character;
            this.calculatedStats = calculatedStats;
            this.CalcOpts = calcopts;
            this.BossOpts = bossOpts;
            this.PetTalents = calcopts.PetTalents;
            this.Talents = character.HunterTalents;
            this.HunterStats = hunterStats;

            PetStats = new StatsHunter();
        }
Beispiel #14
0
 /// <summary>
 /// TODO Zhok: Sniper Training
 /// <b>Kill Shot</b>, 45 Focus, 45yd, Instant, 10 sec Cd
 /// <para>You attempt to finish the wounded target off, firing a long range attack
 /// dealing 150% weapon damage plus RAP*0.30+543. Kill Shot can only be used on
 /// enemies that have 20% or less health.</para>
 /// <para>Kill Shot can only be used on enemies that have 20% or less health.</para>
 /// </summary>
 /// <TalentsAffecting>Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.</TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Kill Shot - If the damage from your Kill Shot fails to kill a target at or below 20% health, your Kill Shot's cooldown is instantly reset. This effect has a 6 sec cooldown.</GlyphsAffecting>
 public KillShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     Name = "Kill Shot";
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     // In terms of modeling, the Glyph of Kill Shot is basically a 4 second cooldown reduction.
     Cd = 10 - (Talents.GlyphOfKillShot ? 4f : 0f);
     FocusCost = 0;
     // 150% weapon dmg + 45% RAP + 543
     DamageBase = (cf.AvgRwWeaponDmgUnhasted * 1.5f) + (StatS.RangedAttackPower * 0.45f) + 543f;
     Initialize();
 }
Beispiel #15
0
 /// <summary>
 /// TODO Zhok: Sniper Training
 /// <b>Kill Shot</b>, 45 Focus, 45yd, Instant, 10 sec Cd
 /// <para>You attempt to finish the wounded target off, firing a long range attack
 /// dealing 150% weapon damage plus RAP*0.30+543. Kill Shot can only be used on
 /// enemies that have 20% or less health.</para>
 /// <para>Kill Shot can only be used on enemies that have 20% or less health.</para>
 /// </summary>
 /// <TalentsAffecting>Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.</TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Kill Shot - If the damage from your Kill Shot fails to kill a target at or below 20% health, your Kill Shot's cooldown is instantly reset. This effect has a 6 sec cooldown.</GlyphsAffecting>
 public KillShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char           = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     Name           = "Kill Shot";
     ReqRangedWeap  = true;
     ReqSkillsRange = true;
     // In terms of modeling, the Glyph of Kill Shot is basically a 4 second cooldown reduction.
     Cd        = 10 - (Talents.GlyphOfKillShot ? 4f : 0f);
     FocusCost = 0;
     // 150% weapon dmg + 45% RAP + 543
     DamageBase = (cf.AvgRwWeaponDmgUnhasted * 1.5f) + (StatS.RangedAttackPower * 0.45f) + 543f;
     Initialize();
 }
Beispiel #16
0
 /// <summary>
 /// TODO Zhok: Bombardment, Serpent Spread
 /// <b>Multi-Shot</b>, 40 Focus, 5-35yd
 /// <para>Fires several missiles, hitting your current target 
 /// and all enemies within 0 yards of that target for 55% of weapon damage.</para>
 /// </summary>
 /// <TalentsAffecting>Bombardment - When you critically hit with your Multi-Shot your next Multi-Shot's focus cost will be reduced by 25/50%.
 /// Concussive Barrage - Your successful Chimera Shot and Multi-Shot attacks have a 50/100% chance to daze the target for 4 sec.
 /// Serpent Spread - Targets hit by your Multi-Shot are also afflicted by your Serpent Sting equal to 6/9 sec of its total duration.
 /// </TalentsAffecting>
 public MultiShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Multi-Shot";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     Targets = 10f; // TODO Zhok: 10?
     FocusCost = 40f;
     DamageBase = cf.AvgRwWeaponDmgUnhasted * 1.20f;
     //
     Initialize();
 }
Beispiel #17
0
 /// <summary>
 /// TODO Zhok: Bombardment, Serpent Spread
 /// <b>Multi-Shot</b>, 40 Focus, 5-35yd
 /// <para>Fires several missiles, hitting your current target
 /// and all enemies within 0 yards of that target for 55% of weapon damage.</para>
 /// </summary>
 /// <TalentsAffecting>Bombardment - When you critically hit with your Multi-Shot your next Multi-Shot's focus cost will be reduced by 25/50%.
 /// Concussive Barrage - Your successful Chimera Shot and Multi-Shot attacks have a 50/100% chance to daze the target for 4 sec.
 /// Serpent Spread - Targets hit by your Multi-Shot are also afflicted by your Serpent Sting equal to 6/9 sec of its total duration.
 /// </TalentsAffecting>
 public MultiShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Multi-Shot";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqRangedWeap  = true;
     ReqSkillsRange = true;
     Targets        = 10f; // TODO Zhok: 10?
     FocusCost      = 40f;
     DamageBase     = cf.AvgRwWeaponDmgUnhasted * 1.20f;
     //
     Initialize();
 }
Beispiel #18
0
 /// <summary>
 /// TODO Zhok: Careful Aim, Sniper Training, Termination
 /// <b>Cobra Shot</b>, 5-40yd, 1.5 sec cast
 /// <para>Deals weapon damage plus (276 + (RAP * 0.017)) in the form of Nature damage
 /// and increases the duration of your Serpent Sting on
 /// the target by 6 sec.</para>
 /// <para>Generates 9 Focus.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Careful Aim - Increases the critical strike chance of your Steady Shot, Cobra Shot and Aimed Shot by 30/60% on targets who are above 90% health.
 /// Rapid Killing - After killing an opponent that yields experience or honor, your next Aimed Shot, Steady Shot or Cobra Shot causes 10/20% additional damage.  Lasts 20 sec.
 /// Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.
 /// Termination - Your Steady Shot and Cobra Shot abilities grant an additional 3/6 Focus when dealt on targets at or below 25% health.
 /// </TalentsAffecting>
 /// <Note>Cobra Shot is a replacement to [Steady Shot] for beastmaster and survival hunters due to its ability
 /// (and beastmaster and survival hunters otherwise lack of ability) to increase the duration of [Serpent Sting] without recasting it. </Note>
 public CobraShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name             = "Cobra Shot";
     ReqTalent        = true;
     Talent2ChksValue = ((Specialization)Talents.HighestTree == Specialization.Marksmanship ? 0 : 1);
     ReqRangedWeap    = true;
     ReqSkillsRange   = true;
     CastTime         = 1.5f;
     FocusCost        = -9;
     //Targets += StatS.BonusTargets;
     DamageBase = combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.017f) + 277.21f;
     Initialize();
 }
Beispiel #19
0
 public MMMAimedShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name                = "MMM Aimed Shot";
     ReqTalent           = true; // Reqiures MM spec.
     Talent2ChksValue    = Talents.MasterMarksman;
     ReqRangedWeap       = true;
     ReqSkillsRange      = true;
     CastTime            = 0;
     FocusCost           = 0;
     DamageBase          = (combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.724f) + 776) * 1.60f + 100;
     Consumes_Tier12_4pc = true;
     Initialize();
 }
Beispiel #20
0
 /// <summary>
 /// TODO Zhok: Careful Aim, Dazzled Prey, Sniper Training, Termination
 /// <b>Steady Shot</b>, 5-40yd, 1.5 sec cast
 /// <para>A steady shot that causes 100% weapon damage 
 /// plus RAP*0.021+280. Generates 9 Focus.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Careful Aim - Increases the critical strike chance of your Steady Shot, Cobra Shot and Aimed Shot by 30/60% on targets who are above 80% health.
 /// Improved Steady Shot - When you Steady Shot twice in a row, your ranged attack speed will be increased by 5/10/15% for 8 sec.
 /// Master Marksman - You have a 20/40/60% chance when you Steady Shot to gain the Master Marksman effect, lasting 30 sec. After reaching 5 stacks, your next Aimed Shot's cast time and focus cost are reduced by 100% for 10 sec.
 /// Rapid Killing - After killing an opponent that yields experience or honor, your next Aimed Shot, Steady Shot or Cobra Shot causes 10/20% additional damage.  Lasts 20 sec.
 /// Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.
 /// Termination - Your Steady Shot and Cobra Shot abilities grant an additional 3/6 Focus when dealt on targets at or below 25% health.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Steady Shot [+10% DMG]
 /// Glyph of Dazzled Prey - Your Steady Shot generates an additional 2 Focus on targets afflicted by a daze effect.</GlyphsAffecting>
 public SteadyShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Steady Shot";
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     UsesGCD = true;
     CastTime = 1.5f;
     DamageBase = combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.021f) + 280f;
     DamageBonus = 1f + (Talents.GlyphOfSteadyShot ? 0.10f : 0f);
     FocusCost = -9;
     //
     Initialize();
 }
Beispiel #21
0
 /// <summary>
 /// TODO Zhok: Careful Aim, Dazzled Prey, Sniper Training, Termination
 /// <b>Steady Shot</b>, 5-40yd, 1.5 sec cast
 /// <para>A steady shot that causes 100% weapon damage
 /// plus RAP*0.021+280. Generates 9 Focus.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Careful Aim - Increases the critical strike chance of your Steady Shot, Cobra Shot and Aimed Shot by 30/60% on targets who are above 80% health.
 /// Improved Steady Shot - When you Steady Shot twice in a row, your ranged attack speed will be increased by 5/10/15% for 8 sec.
 /// Master Marksman - You have a 20/40/60% chance when you Steady Shot to gain the Master Marksman effect, lasting 30 sec. After reaching 5 stacks, your next Aimed Shot's cast time and focus cost are reduced by 100% for 10 sec.
 /// Rapid Killing - After killing an opponent that yields experience or honor, your next Aimed Shot, Steady Shot or Cobra Shot causes 10/20% additional damage.  Lasts 20 sec.
 /// Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.
 /// Termination - Your Steady Shot and Cobra Shot abilities grant an additional 3/6 Focus when dealt on targets at or below 25% health.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Steady Shot [+10% DMG]
 /// Glyph of Dazzled Prey - Your Steady Shot generates an additional 2 Focus on targets afflicted by a daze effect.</GlyphsAffecting>
 public SteadyShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name           = "Steady Shot";
     ReqRangedWeap  = true;
     ReqSkillsRange = true;
     UsesGCD        = true;
     CastTime       = 1.5f;
     DamageBase     = combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.021f) + 280f;
     DamageBonus    = 1f + (Talents.GlyphOfSteadyShot ? 0.10f : 0f);
     FocusCost      = -9;
     //
     Initialize();
 }
Beispiel #22
0
 public MMMAimedShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "MMM Aimed Shot";
     ReqTalent = true; // Reqiures MM spec.
     Talent2ChksValue = Talents.MasterMarksman;
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     CastTime = 0;
     FocusCost = 0;
     DamageBase = (combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.724f) + 776) * 1.60f + 100;
     Consumes_Tier12_4pc = true;
     Initialize();
 }
Beispiel #23
0
 /// <summary>
 /// TODO Zhok: Careful Aim, Sniper Training, Termination
 /// <b>Cobra Shot</b>, 5-40yd, 1.5 sec cast
 /// <para>Deals weapon damage plus (276 + (RAP * 0.017)) in the form of Nature damage 
 /// and increases the duration of your Serpent Sting on 
 /// the target by 6 sec.</para>
 /// <para>Generates 9 Focus.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Careful Aim - Increases the critical strike chance of your Steady Shot, Cobra Shot and Aimed Shot by 30/60% on targets who are above 90% health.
 /// Rapid Killing - After killing an opponent that yields experience or honor, your next Aimed Shot, Steady Shot or Cobra Shot causes 10/20% additional damage.  Lasts 20 sec.
 /// Sniper Training - Increases the critical strike chance of your Kill Shot ability by 5/10/15%, and after remaining stationary for 6 sec, your Steady Shot and Cobra Shot deal 2/4/6% more damage for 15 sec.
 /// Termination - Your Steady Shot and Cobra Shot abilities grant an additional 3/6 Focus when dealt on targets at or below 25% health.
 /// </TalentsAffecting>
 /// <Note>Cobra Shot is a replacement to [Steady Shot] for beastmaster and survival hunters due to its ability 
 /// (and beastmaster and survival hunters otherwise lack of ability) to increase the duration of [Serpent Sting] without recasting it. </Note>
 public CobraShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Cobra Shot";
     ReqTalent = true;
     Talent2ChksValue = ((Specialization)Talents.HighestTree == Specialization.Marksmanship ? 0 : 1);
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     CastTime = 1.5f;
     FocusCost = -9;
     //Targets += StatS.BonusTargets;
     DamageBase = combatFactors.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.017f) + 277.21f;
     Initialize();
 }
Beispiel #24
0
 /// <summary>
 /// TODO Zhok: Thrill of the Hunt, Toxicology, Trap Mastery
 /// <b>Black Arrow</b>, 35 Focus, 5-40yd, Instant, 30 sec Cd
 /// <para>Fires a Black Arrow at the target, dealing 2395 Shadow damage over 15 sec.
 /// Black Arrow shares a cooldown with other Fire Trap spells.</para>
 /// </summary>
 /// <TalentsAffecting>Black Arrow (Requires Talent)</TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public BlackArrowBuff(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Black Arrow";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqTalent        = true;
     Talent2ChksValue = Talents.BlackArrow;
     ReqRangedWeap    = true;
     ReqSkillsRange   = true;
     //Targets += StatS.BonusTargets;
     Cd        = 30f; //TODO Zhok: Resourcefulness ... - (2f * Talents.Resourcefulness;
     FocusCost = 35f;
     //
     Initialize();
 }
Beispiel #25
0
 /// <summary>
 /// TODO Zhok: Thrill of the Hunt, Toxicology, Trap Mastery
 /// <b>Black Arrow</b>, 35 Focus, 5-40yd, Instant, 30 sec Cd
 /// <para>Fires a Black Arrow at the target, dealing 2395 Shadow damage over 15 sec. 
 /// Black Arrow shares a cooldown with other Fire Trap spells.</para>
 /// </summary>
 /// <TalentsAffecting>Black Arrow (Requires Talent)</TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public BlackArrowBuff(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Black Arrow";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqTalent = true;
     Talent2ChksValue = Talents.BlackArrow;
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     //Targets += StatS.BonusTargets;
     Cd = 30f; //TODO Zhok: Resourcefulness ... - (2f * Talents.Resourcefulness;
     FocusCost = 35f;
     //
     Initialize();
 }
Beispiel #26
0
        // Constructors
        public WhiteAttacks(Character character, StatsHunter stats, CombatFactors cf, CalculationOptionsHunter calcOpts, BossOptions bossOpts)
        {
            Char          = character;
            StatS         = stats;
            Talents       = Char.HunterTalents == null ? new HunterTalents() : Char.HunterTalents;
            combatFactors = cf;
            CalcOpts      = calcOpts;
            BossOpts      = bossOpts;
            RWAtkTable    = new AttackTable(Char, StatS, combatFactors, calcOpts, false, false);
            FightDuration = BossOpts.BerserkTimer;

            Targets            = BossOpts.Targets.Count; // Should update to better handle Target objects
            HSOverridesOverDur = 0f;
            CLOverridesOverDur = 0f;
            Steady_Freq        = 0f;
        }
Beispiel #27
0
        // Constructors
        public WhiteAttacks(Character character, StatsHunter stats, CombatFactors cf, CalculationOptionsHunter calcOpts, BossOptions bossOpts)
        {
            Char = character;
            StatS = stats;
            Talents = Char.HunterTalents == null ? new HunterTalents() : Char.HunterTalents;
            combatFactors = cf;
            CalcOpts = calcOpts;
            BossOpts = bossOpts;
            RWAtkTable = new AttackTable(Char, StatS, combatFactors, calcOpts, false, false);
            FightDuration = BossOpts.BerserkTimer;

            Targets = BossOpts.Targets.Count; // Should update to better handle Target objects
            HSOverridesOverDur = 0f;
            CLOverridesOverDur = 0f;
            Steady_Freq = 0f;
        }
Beispiel #28
0
        /// <summary>
        /// TODO Zhok: Add Efficiency, Piercing Shots
        /// <b>Chimera Shot</b>, 50 Focus, 5-40yd, Instant, 10 sec Cd
        /// <para>An instant shot that causes ranged weapon damage
        /// plus RAP*0.732+1620, refreshing the duration of your
        /// Serpent Sting and healing you for 5% of your total health.</para>
        /// </summary>
        /// <TalentsAffecting>Chimera Shot (Requires Talent)
        /// Concussive Barrage - Your successful Chimera Shot and Multi-Shot attacks have a 50/100% chance to daze the target for 4 sec.
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Marked for Death - Your Arcane Shot and Chimera Shot have a 50/100% chance to automatically apply the Marked for Death effect.
        /// Piercing Shots - Your critical Aimed, Steady and Chimera Shots cause the target to bleed for 10/20/30% of the damage dealt over 8 sec.
        /// </TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Chimera Shot [-1 sec Cd]</GlyphsAffecting>
        public ChimeraShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name             = "Chimera Shot";
            ReqTalent        = true;
            Talent2ChksValue = Talents.ChimeraShot;
            ReqRangedWeap    = true;
            ReqSkillsRange   = true;
            //Targets += StatS.BonusTargets;
            Cd          = 10f - (Talents.GlyphOfChimeraShot ? 1f : 0f); // In Seconds
            FocusCost   = 50f - (Talents.Efficiency * 2f);
            DamageBase  = combatFactors.AvgRwWeaponDmgUnhasted + StatS.RangedAttackPower * 0.732f + 1620;
            RefreshesSS = true;
            //
            Initialize();
        }
Beispiel #29
0
        /// <summary>
        /// TODO Zhok: Add Efficiency, Piercing Shots
        /// <b>Chimera Shot</b>, 50 Focus, 5-40yd, Instant, 10 sec Cd
        /// <para>An instant shot that causes ranged weapon damage 
        /// plus RAP*0.732+1620, refreshing the duration of your 
        /// Serpent Sting and healing you for 5% of your total health.</para>
        /// </summary>
        /// <TalentsAffecting>Chimera Shot (Requires Talent)
        /// Concussive Barrage - Your successful Chimera Shot and Multi-Shot attacks have a 50/100% chance to daze the target for 4 sec.
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Marked for Death - Your Arcane Shot and Chimera Shot have a 50/100% chance to automatically apply the Marked for Death effect.
        /// Piercing Shots - Your critical Aimed, Steady and Chimera Shots cause the target to bleed for 10/20/30% of the damage dealt over 8 sec.
        /// </TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Chimera Shot [-1 sec Cd]</GlyphsAffecting>
        public ChimeraShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Chimera Shot";
            ReqTalent = true;
            Talent2ChksValue = Talents.ChimeraShot;
            ReqRangedWeap = true;
            ReqSkillsRange = true;
            //Targets += StatS.BonusTargets;
            Cd = 10f - (Talents.GlyphOfChimeraShot ? 1f : 0f); // In Seconds
            FocusCost = 50f - (Talents.Efficiency * 2f);
            DamageBase = combatFactors.AvgRwWeaponDmgUnhasted + StatS.RangedAttackPower * 0.732f + 1620;
            RefreshesSS = true;
            //
            Initialize();
        }
Beispiel #30
0
        /// <summary>
        /// TODO Zhok: Add Efficiency, Lock and Load, Thrill of the Hunt
        /// <b>Explosive Shot</b>, 50 Focus, 5-40yd, Instant, 6 sec Cd
        /// <para>You fire an explosive charge into the enemy target, dealing
        /// [RAP * 0.232 + 320] - [RAP * 0.232 + 386] Fire Damage. The charge will
        /// blast the target every second for an additional 2 sec.</para>
        /// </summary>
        /// <TalentsAffecting>Explosive Shot (Requires Spec)
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Lock and Load - You have a 50/100% chance when you trap a target with Freezing Trap or Ice Trap to cause your next 2 Arcane Shot or Explosive Shot abilities to cost no focus and trigger no cooldown.
        /// Sic 'Em! - When you critically hit with your Arcane Shot, Aimed Shot or Explosive Shot the focus cost of your Pet's next basic attack is reduced by 50/100% for 12 sec.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.</TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Explosive Shot [+6% crit chance]</GlyphsAffecting>
        public ExplosiveShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name             = "Explosive Shot";
            ReqTalent        = true;
            Talent2ChksValue = ((Specialization)Talents.HighestTree == Specialization.Survival ? 1 : 0);
            ReqRangedWeap    = true;
            ReqSkillsRange   = true;
            Cd            = 6f; // In Seconds
            Duration      = 2f;
            TimeBtwnTicks = 1f;
            FocusCost     = _basefocuscost - (Talents.Efficiency * 2f);
            // 23.2% RAP + (320 + 386)/2 (Per tick) for 2 seconds
            DamageBase      = ((StatS.RangedAttackPower * 0.232f) + (320 + 386) / 2f);
            BonusCritChance = Talents.GlyphOfExplosiveShot ? 0.06f : 0f;
            Initialize();
        }
Beispiel #31
0
        /// <summary>
        /// TODO Zhok: Cobra Strike, Efficiency, Lock and Load, Sic 'Em, Thrill of the Hunt
        ///
        /// <b>Arcane Shot</b>, 25 Focus, 5-40yd, Instant
        /// <para>An instant shot that causes 100% weapon damage
        /// plus (RAP * 0.0483)+289 as Arcane damage.</para>
        /// </summary>
        /// <TalentsAffecting>Cobra Strikes - You have a 5/10/15% chance when you hit with Arcane Shot to cause your pet's next 2 Basic Attacks to critically hit.
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Lock and Load - You have a 50/100% chance when you trap a target with Freezing Trap or Ice Trap to cause your next 2 Arcane Shot or Explosive Shot abilities to cost no focus and trigger no cooldown.
        /// Marked for Death - Your Arcane Shot and Chimera Shot have a 50/100% chance to automatically apply the Marked for Death effect.
        /// Sic 'Em! - When you critically hit with your Arcane Shot, Aimed Shot or Explosive Shot the focus cost of your Pet's next basic attack is reduced by 50/100% for 12 sec.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.</TalentsAffecting>
        /// </TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Arcane Shot [12% More DMG]</GlyphsAffecting>
        public ArcaneShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Arcane Shot";

            ReqRangedWeap  = true;
            ReqSkillsRange = true;

            FocusCost = _basefocuscost - (Talents.Efficiency * 2f);

            DamageBase  = cf.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.0483f) + 289f;
            DamageBonus = 1 + (Talents.GlyphOfArcaneShot ? 0.12f : 0f);

            Consumes_Tier12_4pc = true;

            Initialize();
        }
Beispiel #32
0
 /// <summary>
 /// <b>Piercing Shots</b>
 /// <para>Your critical Aimed, Steady and Chimera Shots cause the
 /// target to bleed for [Pts*10]% of the damage dealt over 8 sec.</para>
 /// </summary>
 /// <TalentsAffecting>Piercing Shots (Requires Talent)</TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public PiercingShots(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Piercing Shots";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqTalent = true;
     Talent2ChksValue = Talents.PiercingShots;
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     //Targets += StatS.BonusTargets;
     //Cd = 30f; // In Seconds
     Duration = 8f;
     TimeBtwnTicks = 1f; // In Seconds
     DamageBase = StatS.RangedAttackPower * 0.10f + 2765f;
     //
     Initialize();
 }
Beispiel #33
0
        /// <summary>
        /// TODO Zhok: Add Efficiency, Lock and Load, Thrill of the Hunt
        /// <b>Explosive Shot</b>, 50 Focus, 5-40yd, Instant, 6 sec Cd
        /// <para>You fire an explosive charge into the enemy target, dealing
        /// [RAP * 0.232 + 320] - [RAP * 0.232 + 386] Fire Damage. The charge will
        /// blast the target every second for an additional 2 sec.</para>
        /// </summary>
        /// <TalentsAffecting>Explosive Shot (Requires Spec)
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Lock and Load - You have a 50/100% chance when you trap a target with Freezing Trap or Ice Trap to cause your next 2 Arcane Shot or Explosive Shot abilities to cost no focus and trigger no cooldown.
        /// Sic 'Em! - When you critically hit with your Arcane Shot, Aimed Shot or Explosive Shot the focus cost of your Pet's next basic attack is reduced by 50/100% for 12 sec.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.</TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Explosive Shot [+6% crit chance]</GlyphsAffecting>
        public ExplosiveShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Explosive Shot";
            ReqTalent = true;
            Talent2ChksValue = ((Specialization)Talents.HighestTree == Specialization.Survival ? 1 : 0);
            ReqRangedWeap = true;
            ReqSkillsRange = true;
            Cd = 6f; // In Seconds
            Duration = 2f;
            TimeBtwnTicks = 1f;
            FocusCost = _basefocuscost - (Talents.Efficiency * 2f);
            // 23.2% RAP + (320 + 386)/2 (Per tick) for 2 seconds
            DamageBase = ((StatS.RangedAttackPower * 0.232f) + (320 + 386) / 2f);
            BonusCritChance = Talents.GlyphOfExplosiveShot ? 0.06f : 0f;
            Initialize();
        }
Beispiel #34
0
 /// <summary>
 /// <b>Piercing Shots</b>
 /// <para>Your critical Aimed, Steady and Chimera Shots cause the
 /// target to bleed for [Pts*10]% of the damage dealt over 8 sec.</para>
 /// </summary>
 /// <TalentsAffecting>Piercing Shots (Requires Talent)</TalentsAffecting>
 /// <GlyphsAffecting></GlyphsAffecting>
 public PiercingShots(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Piercing Shots";
     //AbilIterater = (int)CalculationOptionsHunter.Maintenances.MortalStrike_;
     ReqTalent        = true;
     Talent2ChksValue = Talents.PiercingShots;
     ReqRangedWeap    = true;
     ReqSkillsRange   = true;
     //Targets += StatS.BonusTargets;
     //Cd = 30f; // In Seconds
     Duration      = 8f;
     TimeBtwnTicks = 1f; // In Seconds
     DamageBase    = StatS.RangedAttackPower * 0.10f + 2765f;
     //
     Initialize();
 }
Beispiel #35
0
        /// <summary>
        /// TODO Zhok: Cobra Strike, Efficiency, Lock and Load, Sic 'Em, Thrill of the Hunt
        /// 
        /// <b>Arcane Shot</b>, 25 Focus, 5-40yd, Instant
        /// <para>An instant shot that causes 100% weapon damage 
        /// plus (RAP * 0.0483)+289 as Arcane damage.</para>
        /// </summary>
        /// <TalentsAffecting>Cobra Strikes - You have a 5/10/15% chance when you hit with Arcane Shot to cause your pet's next 2 Basic Attacks to critically hit.
        /// Efficiency - Reduces the focus cost of your Arcane Shot by 1/2/3, and your Explosive Shot and Chimera Shot by 2/4/6.
        /// Lock and Load - You have a 50/100% chance when you trap a target with Freezing Trap or Ice Trap to cause your next 2 Arcane Shot or Explosive Shot abilities to cost no focus and trigger no cooldown.
        /// Marked for Death - Your Arcane Shot and Chimera Shot have a 50/100% chance to automatically apply the Marked for Death effect.
        /// Sic 'Em! - When you critically hit with your Arcane Shot, Aimed Shot or Explosive Shot the focus cost of your Pet's next basic attack is reduced by 50/100% for 12 sec.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.</TalentsAffecting>
        /// </TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Arcane Shot [12% More DMG]</GlyphsAffecting>
        public ArcaneShot(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Arcane Shot";

            ReqRangedWeap = true;
            ReqSkillsRange = true;

            FocusCost = _basefocuscost - (Talents.Efficiency * 2f);

            DamageBase = cf.AvgRwWeaponDmgUnhasted + (StatS.RangedAttackPower * 0.0483f) + 289f;
            DamageBonus = 1 + (Talents.GlyphOfArcaneShot ? 0.12f : 0f);

            Consumes_Tier12_4pc = true;

            Initialize();
        }
Beispiel #36
0
 /// <summary>
 /// <b>Bestial Wrath</b>, Instant, 2 min cooldown
 /// <para>Send your pet into a rage causing 20% additional damage for 10 sec.  The beast does not feel pity or remorse or fear and it cannot be stopped unless killed.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Longevity - Reduces the cooldown of your Bestial Wrath, Intimidation and Pet Special Abilities by 10/20/30%.
 /// The Beast Within - While your pet is under the effects of Bestial Wrath, you also go into a rage causing 10% additional damage and reducing the focus cost of all shots and abilities by 50% for 10 sec.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Bestial Wrath - Decreases the cooldown of Bestial Wrath by 20 sec.</GlyphsAffecting>
 public BestialWrath(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     //
     Name = "Bestial Wrath";
     Cd = ((2f * 60f) * (1f - Talents.Longevity)) - (Talents.GlyphOfBestialWrath ? 20f : 0f); // In Seconds
     Duration = 10f;
     UseHitTable = false;
     ReqTalent = true;
     Talent2ChksValue = Talents.BestialWrath;
     // TODO: Move these to static SEs.
     Effect = new SpecialEffect(Trigger.Use,
         new Stats() { BonusPetDamageMultiplier = 0.20f }, Duration, Cd);
     if (Talents.TheBeastWithin > 0f)
     {
         Effect = new SpecialEffect(Trigger.Use,
             new Stats() { BonusDamageMultiplier = 0.10f }, Duration, Cd);
     }
     Initialize();
 }
Beispiel #37
0
 /// <summary>
 /// <b>Serpent Sting</b>, 25 Focus,5-40yd, Instant, No Cd
 /// <para>Causes (RAP * 0.4 + (460 * 15 sec / 3)) Nature damage over 15 sec.</para>
 /// </summary>
 /// <TalentsAffecting>
 /// Chimera Shot - An instant shot that causes ranged weapon damage plus RAP*0.732+1620, refreshing the duration of  your Serpent Sting and healing you for 5% of your total health.
 /// Noxious Stings - Increases your damage done on targets afflicted by your Serpent Sting by 5/10%.
 /// Serpent Spread - Targets hit by your Multi-Shot are also afflicted by your Serpent Sting equal to 6/9 sec of its total duration.
 /// Toxicology - Increases the periodic critical damage of your Serpent Sting and Black Arrow by 50/100%.
 /// </TalentsAffecting>
 /// <GlyphsAffecting>Glyph of Serpent Sting - Increases the periodic critical strike chance of your Serpent Sting by 6%.</GlyphsAffecting>
 public SerpentSting(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
 {
     Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
     Name = "Serpent Sting";
     ReqRangedWeap = true;
     ReqSkillsRange = true;
     TimeBtwnTicks = 3f; // In Seconds
     Duration = 15f;
     FocusCost = 25f;
     DamageBase = (StatS.RangedAttackPower * 0.4f + (460f * 15f / 3f));
     
     BonusCritChance = 1f + (Talents.GlyphOfSerpentSting ? 0.06f : 0f) + (Talents.ImprovedSerpentSting * 0.05f);
     MinRange = 5f;
     MaxRange = 40f;
     CanCrit = true;
     StatS.BonusDamageMultiplier += (.05f * Talents.NoxiousStings);
     StatS.BonusCritDamageMultiplier += (.5f * Talents.Toxicology);
     // Improved Serpent Sting
     // Noxious Stings
     //
     Initialize();
 }
Beispiel #38
0
 public CombatFactors(Character character, StatsHunter stats, CalculationOptionsHunter calcOpts, BossOptions bossOpts)
 {
     Char = character;
     if (Char != null)
     {
         if (Char.Ranged != null)
             RW = Char.Ranged.Item;
         else
             RW = new Knuckles();
         if (Char.HunterTalents != null)
             Talents = Char.HunterTalents;
         else
             Talents = new HunterTalents();
     }
     CalcOpts = (calcOpts == null ? new CalculationOptionsHunter() : calcOpts);
     BossOpts = (bossOpts == null ? new BossOptions() : bossOpts);
     StatS = stats;
     InvalidateCache();
     // Optimizations
     
     //Set_c_values();
 }
Beispiel #39
0
        /// <summary>
        /// TODO Zhok: Thrill of the Hunt, Toxicology, Trap Mastery
        /// <b>Black Arrow</b>, 35 Focus, 5-40yd, Instant, 30 sec Cd
        /// <para>Fires a Black Arrow at the target, dealing 2035 Shadow damage over 15 sec.
        /// Black Arrow shares a cooldown with other Fire Trap spells.</para>
        /// </summary>
        /// <TalentsAffecting>Black Arrow (Requires Talent)
        /// Resourcefulness - Reduces the cooldown of all traps and Black Arrow by 2/4/6 sec.
        /// T.N.T - When you deal periodic damage with your Immolation Trap, Explosive Trap or Black Arrow you have a 6/12% chance to trigger Lock and Load.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.
        /// Toxicology - Increases the periodic critical damage of your Serpent Sting and Black Arrow by 50/100%.
        /// Trap Mastery - Immolation Trap, Explosive Trap and Black Arrow - Increases the periodic damage done by 10/20/30%.
        /// </TalentsAffecting>
        /// <GlyphsAffecting></GlyphsAffecting>
        public BlackArrow(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Black Arrow";

            ReqTalent        = true;
            Talent2ChksValue = Talents.BlackArrow;
            ReqRangedWeap    = true;
            ReqSkillsRange   = true;

            Cd            = 30f - (Talents.Resourcefulness * 2f);
            Duration      = 15f;
            TimeBtwnTicks = 1f; // TODO Zhok: Haste?
            FocusCost     = _basefocuscost;
            // 47.35% RAP + 2035 (total damage)
            // 4.2 Increased the damage by 40%
            DamageBase  = /*(StatS.RangedAttackPower * 0.4735f) +*/ 2850f;
            DamageBonus = 1f + (Talents.TrapMastery * 0.10f);

            Initialize();
        }
Beispiel #40
0
        /// <summary>
        /// TODO Zhok: Thrill of the Hunt, Toxicology, Trap Mastery
        /// <b>Black Arrow</b>, 35 Focus, 5-40yd, Instant, 30 sec Cd
        /// <para>Fires a Black Arrow at the target, dealing 2035 Shadow damage over 15 sec. 
        /// Black Arrow shares a cooldown with other Fire Trap spells.</para>
        /// </summary>
        /// <TalentsAffecting>Black Arrow (Requires Talent)
        /// Resourcefulness - Reduces the cooldown of all traps and Black Arrow by 2/4/6 sec.
        /// T.N.T - When you deal periodic damage with your Immolation Trap, Explosive Trap or Black Arrow you have a 6/12% chance to trigger Lock and Load.
        /// Thrill of the Hunt - You have a 5/10/15% chance when you use Arcane Shot, Explosive Shot or Black Arrow to instantly regain 40% of the base focus cost of the shot.
        /// Toxicology - Increases the periodic critical damage of your Serpent Sting and Black Arrow by 50/100%.
        /// Trap Mastery - Immolation Trap, Explosive Trap and Black Arrow - Increases the periodic damage done by 10/20/30%.
        /// </TalentsAffecting>
        /// <GlyphsAffecting></GlyphsAffecting>
        public BlackArrow(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;

            Name = "Black Arrow";

            ReqTalent = true;
            Talent2ChksValue = Talents.BlackArrow;
            ReqRangedWeap = true;
            ReqSkillsRange = true;

            Cd = 30f - (Talents.Resourcefulness * 2f);
            Duration = 15f;
            TimeBtwnTicks = 1f; // TODO Zhok: Haste?
            FocusCost = _basefocuscost;
            // 47.35% RAP + 2035 (total damage)
            // 4.2 Increased the damage by 40%
            DamageBase = /*(StatS.RangedAttackPower * 0.4735f) +*/ 2850f;
            DamageBonus = 1f + (Talents.TrapMastery * 0.10f);

            Initialize();
        }
Beispiel #41
0
        /// <summary>
        /// <b>Serpent Sting</b>, 25 Focus,5-40yd, Instant, No Cd
        /// <para>Causes (RAP * 0.4 + (460 * 15 sec / 3)) Nature damage over 15 sec.</para>
        /// </summary>
        /// <TalentsAffecting>
        /// Chimera Shot - An instant shot that causes ranged weapon damage plus RAP*0.732+1620, refreshing the duration of  your Serpent Sting and healing you for 5% of your total health.
        /// Noxious Stings - Increases your damage done on targets afflicted by your Serpent Sting by 5/10%.
        /// Serpent Spread - Targets hit by your Multi-Shot are also afflicted by your Serpent Sting equal to 6/9 sec of its total duration.
        /// Toxicology - Increases the periodic critical damage of your Serpent Sting and Black Arrow by 50/100%.
        /// </TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Serpent Sting - Increases the periodic critical strike chance of your Serpent Sting by 6%.</GlyphsAffecting>
        public SerpentSting(Character c, StatsHunter s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsHunter co)
        {
            Char           = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co;
            Name           = "Serpent Sting";
            ReqRangedWeap  = true;
            ReqSkillsRange = true;
            TimeBtwnTicks  = 3f; // In Seconds
            Duration       = 15f;
            FocusCost      = 25f;
            DamageBase     = (StatS.RangedAttackPower * 0.4f + (460f * 15f / 3f));

            BonusCritChance                  = 1f + (Talents.GlyphOfSerpentSting ? 0.06f : 0f) + (Talents.ImprovedSerpentSting * 0.05f);
            MinRange                         = 5f;
            MaxRange                         = 40f;
            CanCrit                          = true;
            StatS.BonusDamageMultiplier     += (.05f * Talents.NoxiousStings);
            StatS.BonusCritDamageMultiplier += (.5f * Talents.Toxicology);
            // Improved Serpent Sting
            // Noxious Stings
            //
            Initialize();
        }
Beispiel #42
0
        protected void Initialize(Character character, StatsHunter stats, CombatFactors cf, CalculationOptionsHunter co,
                                  Skills.Ability ability, bool useSpellHit, bool alwaysHit)
        {
            Char          = character;
            StatS         = stats;
            calcOpts      = co;
            combatFactors = cf;
            Abil          = ability;
            if (Abil == null)
            {
                isWhite = true;
            }
            else
            {
                Abil.combatFactors = combatFactors;
            }
            PetAbil          = PetAttacks.None;
            this.useSpellHit = useSpellHit;

            /*// Defaults
             * Miss
             * Dodge
             * Parry
             * Block
             * Glance
             * Critical
             * Hit*/
            // Start a calc
            if (alwaysHit)
            {
                CalculateAlwaysHit();
            }
            else
            {
                Calculate();
            }
        }
        private StatsHunter GetTalentStats(HunterTalents talents)
        {
            StatsHunter s = new StatsHunter();
            #region Specializations : Abilities/Bonuses from picking a tree.
            switch ((Specialization)talents.HighestTree)
            {
                // BM
                case Specialization.BeastMastery:
                    {
                        // Initimitation 
                        // TODO: Implemented in Shots/Abilities
                        // Animal Handler
                        s.BonusAttackPowerMultiplier += 0.25f;
                        // Mastery: Master of Beasts
                        // TODO: s.BonusPetDamageMultiplier += .13 + 0.0167 * Mastery
                        break;
                    }
                // MM
                case Specialization.Marksmanship:
                    {
                        // Aimed Shot
                        // TODO: Implemented in Shots/Abilities
                        // Artisan Quiver
                        // TODO: Auto-attack damage + 15%
                        // Mastery: Wild Quiver
                        // TODO: Additional Auto-Shot 16.8% + 2.1% per Mastery
                        break;
                    }
                // SV
                case Specialization.Survival:
                    {
                        // Explosive Shot
                        // TODO: Implemented in Shots/Abilities
                        // Intothe Wilderness
                        s.BonusAgilityMultiplier += .1f;
                        // Mastery: Essence of the Viper
                        // Bonus magic damage 8% + 1% per mastery
                        break;
                    }

            }
            #endregion

            #region Beast Master
            // Talent: Ferocious Inspiration
            s.BonusDamageMultiplier += talents.FerociousInspiration * 0.03f;
            #endregion

            #region Marksman
            // Talent: Trueshot Aura (Always on and part of the paperdoll numbers)
            s.BonusAttackPowerMultiplier += talents.TrueshotAura * 0.1f;
            #endregion
            #region Survival
            s.BonusStaminaMultiplier += talents.HunterVsWild * 0.05f;
            s.BonusHasteMultiplier += talents.Pathing * 0.01f;
            s.BonusAgilityMultiplier += talents.HuntingParty * 0.02f;
            // This conflics w/ IcyTalons and other similar buffs.
            s.PhysicalHaste += talents.HuntingParty * .1f;
            #endregion
            
            return s;
        }
Beispiel #44
0
 public PetAttackTable(Character character, StatsHunter stats, CalculationOptionsHunter co,
                       float[] avoidChances, PetAttacks ability, bool useSpellHit, bool alwaysHit)
 {
     Initialize(character, stats, co, avoidChances, ability, useSpellHit, alwaysHit);
 }
        private StatsHunter GetCharacterStats(Character character, Item additionalItem, bool bGetMaxStats)
        {
            StatsHunter statsTotal = new StatsHunter();
            try
            {
                #region NullChecks
                if (null == character)
                {
#if DEBUG
                    throw new NullReferenceException("Character is Null");
#else
                    return statsTotal;
#endif
                }
                CalculationOptionsHunter calcOpts = character.CalculationOptions as CalculationOptionsHunter;
                if (null == calcOpts) { calcOpts = new CalculationOptionsHunter(); }
                HunterTalents talents = character.HunterTalents;
                if (null == talents) { return statsTotal; }
                Specialization tree = GetSpecialization(talents);
                CharacterCalculationsHunter calculatedStats = new CharacterCalculationsHunter();
                if (null == calculatedStats)
                {
#if DEBUG
                    throw new NullReferenceException("Character Calculations is Null");
#else
                    return statsTotal;
#endif
                }
                BossOptions bossOpts = new BossOptions();
                bossOpts = character.BossOptions;
                if (null == bossOpts)
                {
#if DEBUG
                    throw new NullReferenceException("Boss Options is Null");
#else
                    return statsTotal;
#endif
                }
                #endregion

                statsTotal.Accumulate(BaseStats.GetBaseStats(character.Level, CharacterClass.Hunter, character.Race));
                statsTotal.Accumulate(GetItemStats(character, additionalItem));
                AccumulateBuffsStats(statsTotal, character.ActiveBuffs);
                // DO NOT MOVE GetRelevantStats any lower in this progression of functions.
                // It will erase stats specific to hunters.
                statsTotal = GetRelevantStats(statsTotal) as StatsHunter;
                statsTotal.Accumulate(GetTalentStats(character.HunterTalents));

                statsTotal.Stamina = (float)Math.Floor(statsTotal.Stamina * (1f + statsTotal.BonusStaminaMultiplier));
                statsTotal.Agility = (float)Math.Floor(statsTotal.Agility * (1f + statsTotal.BonusAgilityMultiplier));
                calculatedStats.critFromAgi = statsTotal.Agility;
                // Agi bonus to Survival doesn't affect crit?
                if (tree == Specialization.Survival) calculatedStats.critFromAgi /= 1.1f;
                statsTotal.AttackPower += (statsTotal.Agility * 2f); 
                statsTotal.AttackPower = statsTotal.RangedAttackPower = (float)Math.Floor(statsTotal.AttackPower * (1f + statsTotal.BonusAttackPowerMultiplier));
                statsTotal.Health += (float)Math.Floor((statsTotal.Stamina - 20f) * 14f + 20f);
                statsTotal.Health = (float)Math.Floor(statsTotal.Health * (1f + statsTotal.BonusHealthMultiplier));
                statsTotal.Armor = (float)Math.Floor(statsTotal.Armor * (1f + statsTotal.BonusArmorMultiplier)) + statsTotal.BonusArmor;

                statsTotal.NatureResistance += statsTotal.NatureResistanceBuff;
                statsTotal.FireResistance += statsTotal.FireResistanceBuff;
                statsTotal.FrostResistance += statsTotal.FrostResistanceBuff;
                statsTotal.ShadowResistance += statsTotal.ShadowResistanceBuff;
                statsTotal.ArcaneResistance += statsTotal.ArcaneResistanceBuff;

                int targetLevel = bossOpts.Level;
                float hasteBonus = StatConversion.GetPhysicalHasteFromRating(statsTotal.HasteRating, CharacterClass.Hunter);
                statsTotal.RangedHaste = (1f + hasteBonus) * (1f + statsTotal.BonusHasteMultiplier) * (1f + statsTotal.PhysicalHaste) - 1f;
                float hitBonus = StatConversion.GetPhysicalHitFromRating(statsTotal.HitRating) + statsTotal.PhysicalHit;
                float chanceMiss = Math.Max(0f, StatConversion.WHITE_MISS_CHANCE_CAP[targetLevel - character.Level] - hitBonus);
                float chanceAvoided = chanceMiss;

                float rawChanceCrit = StatConversion.GetPhysicalCritFromRating(statsTotal.CritRating)
                                    + StatConversion.GetCritFromAgility(calculatedStats.critFromAgi, CharacterClass.Hunter)
                                    + statsTotal.PhysicalCrit
                                    + StatConversion.NPC_LEVEL_CRIT_MOD[targetLevel - character.Level];
                calculatedStats.critRateOverall = rawChanceCrit * (1f - chanceAvoided);
                float chanceHit = 1f - chanceAvoided;

                if (bGetMaxStats)
                {
                    #region Special Effects
                    StatsHunter statsProcs = new StatsHunter();

                    Dictionary<Trigger, float> triggerIntervals = new Dictionary<Trigger, float>();
                    Dictionary<Trigger, float> triggerChances = new Dictionary<Trigger, float>();

                    CalculateTriggers(character, calculatedStats, statsTotal, calcOpts, bossOpts, triggerIntervals, triggerChances);

                    /*if (calcOpts.PetFamily == PETFAMILY.Wolf
                        && calculatedStats.pet.priorityRotation.getSkillFrequency(PetAttacks.FuriousHowl) > 0)
                    {
                        statsTotal.AddSpecialEffect(FuriousHowl);
                    }
                    */
                    foreach (SpecialEffect effect in statsTotal.SpecialEffects())
                    {
                        statsProcs.Accumulate(getSpecialEffects(effect, triggerIntervals, triggerChances, character));
                    }
                    #region Handle Results of Special Effects
                    // Base Stats
                    statsProcs.Stamina = (float)Math.Floor(statsProcs.Stamina * (1f + statsTotal.BonusStaminaMultiplier) * (1f + statsProcs.BonusStaminaMultiplier));
                    statsProcs.Agility = statsProcs.Agility * (1f + statsTotal.BonusAgilityMultiplier) * (1f + statsProcs.BonusAgilityMultiplier);
                    statsProcs.Agility += statsProcs.HighestStat * (1f + statsTotal.BonusAgilityMultiplier) * (1f + statsProcs.BonusAgilityMultiplier);
                    statsProcs.Agility += statsProcs.Paragon * (1f + statsTotal.BonusAgilityMultiplier) * (1f + statsProcs.BonusAgilityMultiplier);
                    statsProcs.HighestStat = statsProcs.Paragon = 0f; // we've added them into agi so kill it
                    statsProcs.Health += (float)Math.Floor(statsProcs.Stamina * 10f);

                    float HighestSecondaryStatValue = statsProcs.HighestSecondaryStat; // how much HighestSecondaryStat to add
                    statsProcs.HighestSecondaryStat = 0f; // remove HighestSecondaryStat stat, since it's not needed
                    if (statsTotal.CritRating > statsTotal.HasteRating && statsTotal.CritRating > statsTotal.MasteryRating)
                    {
                        statsTotal.CritRating += HighestSecondaryStatValue;
                    }
                    else if (statsTotal.HasteRating > statsTotal.CritRating && statsTotal.HasteRating > statsTotal.MasteryRating)
                    {
                        statsTotal.HasteRating += HighestSecondaryStatValue;
                    }
                    else /*if (statsTotal.MasteryRating > statsTotal.CritRating && statsTotal.MasteryRating > statsTotal.HasteRating)*/
                    {
                        statsTotal.MasteryRating += HighestSecondaryStatValue;
                    }


                    // Armor
                    statsProcs.Armor = statsProcs.Armor * (1f + statsTotal.BaseArmorMultiplier + statsProcs.BaseArmorMultiplier);
                    //statsProcs.BonusArmor += statsProcs.Agility * 2f;
                    statsProcs.BonusArmor = statsProcs.BonusArmor * (1f + statsTotal.BonusArmorMultiplier + statsProcs.BonusArmorMultiplier);
                    statsProcs.Armor += statsProcs.BonusArmor;
                    statsProcs.BonusArmor = 0; //it's been added to Armor so kill it

                    // Attack Power
                    statsProcs.BonusAttackPowerMultiplier *= (1f + statsProcs.BonusRangedAttackPowerMultiplier);
                    statsProcs.BonusRangedAttackPowerMultiplier = 0; // it's been added to Attack Power so kill it
                    float totalBAPMProcs = (1f + statsTotal.BonusAttackPowerMultiplier) * (1f + statsProcs.BonusAttackPowerMultiplier) - 1f;
                    float apFromAGIProcs = (1f + totalBAPMProcs) * (statsProcs.Agility) * 2f;
                    //float apFromSTRProcs    = (1f + totalBAPMProcs) * (statsProcs.Strength);
                    float apBonusOtherProcs = (1f + totalBAPMProcs) * (statsProcs.AttackPower + statsProcs.RangedAttackPower);
                    statsProcs.AttackPower = Math.Max(0f, apFromAGIProcs + /*apFromSTRProcs +*/ apBonusOtherProcs);
                    statsProcs.RangedAttackPower = statsProcs.AttackPower;
                    statsTotal.AttackPower *= (1f + statsProcs.BonusAttackPowerMultiplier); // Make sure the originals get your AP% procs

                    // Crit
                    statsProcs.PhysicalCrit += StatConversion.GetCritFromAgility(statsProcs.Agility, character.Class);
                    statsProcs.PhysicalCrit += StatConversion.GetCritFromRating(statsProcs.CritRating + statsProcs.RangedCritRating, character.Class);

                    // Haste
                    statsProcs.PhysicalHaste = (1f + statsProcs.PhysicalHaste)
                                             * (1f + statsProcs.RangedHaste)
                                             * (1f + StatConversion.GetPhysicalHasteFromRating(statsProcs.HasteRating, character.Class))
                                             - 1f;
                    #endregion
                    // Add it back into the fold
                    statsTotal.Accumulate(statsProcs);
                    #endregion
                }
                return statsTotal;
            }
            catch (Exception ex)
            {
                new Base.ErrorBox()
                {
                    Title = "Error in getting Character Stats",
                    Function = "GetCharacterStats()",
                    TheException = ex,
                }.Show();
            }
            return new StatsHunter();
        }
Beispiel #46
0
 public AttackTable(Character character, StatsHunter stats, CombatFactors cf, CalculationOptionsHunter co, Skills.Ability ability, bool useSpellHit, bool alwaysHit)
 {
     Initialize(character, stats, cf, co, ability, useSpellHit, alwaysHit);
 }
Beispiel #47
0
        public void Accumulate(StatsHunter data, float weight)
        {
            // Check the root data:

            if (data == null)
            {
                return;
            }
            #region Base
            if (data.sparseIndices != null)
            {
                int i = 0;
                for (int a = 0; a < data.sparseAdditiveCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawAdditiveData[index] += weight * data.rawAdditiveData[index];
                }
                for (int a = 0; a < data.sparseMultiplicativeCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawMultiplicativeData[index] = (1 + rawMultiplicativeData[index]) * (1 + weight * data.rawMultiplicativeData[index]) - 1;
                }
                for (int a = 0; a < data.sparseInverseMultiplicativeCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawInverseMultiplicativeData[index] = 1 - (1 - rawInverseMultiplicativeData[index]) * (1 - weight * data.rawInverseMultiplicativeData[index]);
                }
                for (int a = 0; a < data.sparseNoStackCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    float value = weight * data.rawNoStackData[index];
                    if (value > rawNoStackData[index]) rawNoStackData[index] = value;
                }
            }
            else
            {
                float[] add = data.rawAdditiveData;
                for (int i = 0; i < rawAdditiveData.Length; i++)
                {
                    rawAdditiveData[i] += weight * add[i];
                }
                add = data.rawMultiplicativeData;
                for (int i = 0; i < rawMultiplicativeData.Length; i++)
                {
                    rawMultiplicativeData[i] = (1 + rawMultiplicativeData[i]) * (1 + weight * add[i]) - 1;
                }
                add = data.rawInverseMultiplicativeData;
                for (int i = 0; i < rawInverseMultiplicativeData.Length; i++)
                {
                    rawInverseMultiplicativeData[i] = 1 - (1 - rawInverseMultiplicativeData[i]) * (1 - weight * add[i]);
                }
                add = data.rawNoStackData;
                for (int i = 0; i < rawNoStackData.Length; i++)
                {
                    if (weight * add[i] > rawNoStackData[i]) rawNoStackData[i] = weight * add[i];
                }
            }
            #endregion
            #region Hunter
            if (data._sparseIndicesHunter != null)
            {
                int i = 0;
                for (int a = 0; a < data._sparseAdditiveHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawAdditiveHunterData[index] += weight * data._rawAdditiveHunterData[index];
                }
                for (int a = 0; a < data._sparseMultiplicativeHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawMultiplicativeHunterData[index] = (1 + _rawMultiplicativeHunterData[index]) * (1 + weight * data._rawMultiplicativeHunterData[index]) - 1;
                }
                for (int a = 0; a < data._sparseInverseMultiplicativeHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawInverseMultiplicativeHunterData[index] = 1 - (1 - _rawInverseMultiplicativeHunterData[index]) * (1 - weight * data._rawInverseMultiplicativeHunterData[index]);
                }
                for (int a = 0; a < data._sparseNoStackHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    float value = weight * data._rawNoStackHunterData[index];
                    if (value > _rawNoStackHunterData[index]) _rawNoStackHunterData[index] = value;
                }
            }
            else
            {
                float[] add = data._rawAdditiveHunterData;
                for (int i = 0; i < _rawAdditiveHunterData.Length; i++)
                {
                    _rawAdditiveHunterData[i] += weight * add[i];
                }
                add = data._rawMultiplicativeHunterData;
                for (int i = 0; i < _rawMultiplicativeHunterData.Length; i++)
                {
                    _rawMultiplicativeHunterData[i] = (1 + _rawMultiplicativeHunterData[i]) * (1 + weight * add[i]) - 1;
                }
                add = data._rawInverseMultiplicativeHunterData;
                for (int i = 0; i < _rawInverseMultiplicativeHunterData.Length; i++)
                {
                    _rawInverseMultiplicativeHunterData[i] = 1 - (1 - _rawInverseMultiplicativeHunterData[i]) * (1 - weight * add[i]);
                }
                add = data._rawNoStackHunterData;
                for (int i = 0; i < _rawNoStackHunterData.Length; i++)
                {
                    if (weight * add[i] > _rawNoStackHunterData[i]) _rawNoStackHunterData[i] = weight * add[i];
                }
            }
            #endregion
            if (data._rawSpecialEffectDataSize > 0)
            {
                EnsureSpecialEffectCapacity(_rawSpecialEffectDataSize + data._rawSpecialEffectDataSize);
                Array.Copy(data._rawSpecialEffectData, 0, _rawSpecialEffectData, _rawSpecialEffectDataSize, data._rawSpecialEffectDataSize);
                _rawSpecialEffectDataSize += data._rawSpecialEffectDataSize;
            }
        }
Beispiel #48
0
        public void Accumulate(StatsHunter data, float weight)
        {
            // Check the root data:

            if (data == null)
            {
                return;
            }
            #region Base
            if (data.sparseIndices != null)
            {
                int i = 0;
                for (int a = 0; a < data.sparseAdditiveCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawAdditiveData[index] += weight * data.rawAdditiveData[index];
                }
                for (int a = 0; a < data.sparseMultiplicativeCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawMultiplicativeData[index] = (1 + rawMultiplicativeData[index]) * (1 + weight * data.rawMultiplicativeData[index]) - 1;
                }
                for (int a = 0; a < data.sparseInverseMultiplicativeCount; a++, i++)
                {
                    int index = data.sparseIndices[i];
                    rawInverseMultiplicativeData[index] = 1 - (1 - rawInverseMultiplicativeData[index]) * (1 - weight * data.rawInverseMultiplicativeData[index]);
                }
                for (int a = 0; a < data.sparseNoStackCount; a++, i++)
                {
                    int   index = data.sparseIndices[i];
                    float value = weight * data.rawNoStackData[index];
                    if (value > rawNoStackData[index])
                    {
                        rawNoStackData[index] = value;
                    }
                }
            }
            else
            {
                float[] add = data.rawAdditiveData;
                for (int i = 0; i < rawAdditiveData.Length; i++)
                {
                    rawAdditiveData[i] += weight * add[i];
                }
                add = data.rawMultiplicativeData;
                for (int i = 0; i < rawMultiplicativeData.Length; i++)
                {
                    rawMultiplicativeData[i] = (1 + rawMultiplicativeData[i]) * (1 + weight * add[i]) - 1;
                }
                add = data.rawInverseMultiplicativeData;
                for (int i = 0; i < rawInverseMultiplicativeData.Length; i++)
                {
                    rawInverseMultiplicativeData[i] = 1 - (1 - rawInverseMultiplicativeData[i]) * (1 - weight * add[i]);
                }
                add = data.rawNoStackData;
                for (int i = 0; i < rawNoStackData.Length; i++)
                {
                    if (weight * add[i] > rawNoStackData[i])
                    {
                        rawNoStackData[i] = weight * add[i];
                    }
                }
            }
            #endregion
            #region Hunter
            if (data._sparseIndicesHunter != null)
            {
                int i = 0;
                for (int a = 0; a < data._sparseAdditiveHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawAdditiveHunterData[index] += weight * data._rawAdditiveHunterData[index];
                }
                for (int a = 0; a < data._sparseMultiplicativeHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawMultiplicativeHunterData[index] = (1 + _rawMultiplicativeHunterData[index]) * (1 + weight * data._rawMultiplicativeHunterData[index]) - 1;
                }
                for (int a = 0; a < data._sparseInverseMultiplicativeHunterCount; a++, i++)
                {
                    int index = data._sparseIndicesHunter[i];
                    _rawInverseMultiplicativeHunterData[index] = 1 - (1 - _rawInverseMultiplicativeHunterData[index]) * (1 - weight * data._rawInverseMultiplicativeHunterData[index]);
                }
                for (int a = 0; a < data._sparseNoStackHunterCount; a++, i++)
                {
                    int   index = data._sparseIndicesHunter[i];
                    float value = weight * data._rawNoStackHunterData[index];
                    if (value > _rawNoStackHunterData[index])
                    {
                        _rawNoStackHunterData[index] = value;
                    }
                }
            }
            else
            {
                float[] add = data._rawAdditiveHunterData;
                for (int i = 0; i < _rawAdditiveHunterData.Length; i++)
                {
                    _rawAdditiveHunterData[i] += weight * add[i];
                }
                add = data._rawMultiplicativeHunterData;
                for (int i = 0; i < _rawMultiplicativeHunterData.Length; i++)
                {
                    _rawMultiplicativeHunterData[i] = (1 + _rawMultiplicativeHunterData[i]) * (1 + weight * add[i]) - 1;
                }
                add = data._rawInverseMultiplicativeHunterData;
                for (int i = 0; i < _rawInverseMultiplicativeHunterData.Length; i++)
                {
                    _rawInverseMultiplicativeHunterData[i] = 1 - (1 - _rawInverseMultiplicativeHunterData[i]) * (1 - weight * add[i]);
                }
                add = data._rawNoStackHunterData;
                for (int i = 0; i < _rawNoStackHunterData.Length; i++)
                {
                    if (weight * add[i] > _rawNoStackHunterData[i])
                    {
                        _rawNoStackHunterData[i] = weight * add[i];
                    }
                }
            }
            #endregion
            if (data._rawSpecialEffectDataSize > 0)
            {
                EnsureSpecialEffectCapacity(_rawSpecialEffectDataSize + data._rawSpecialEffectDataSize);
                Array.Copy(data._rawSpecialEffectData, 0, _rawSpecialEffectData, _rawSpecialEffectDataSize, data._rawSpecialEffectDataSize);
                _rawSpecialEffectDataSize += data._rawSpecialEffectDataSize;
            }
        }
Beispiel #49
0
        public StatsHunter GetSpecialEffectsStats(Character Char, Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, float[] attemptedAtkIntervals, float[] hitRates, float[] critRates, float bleedHitInterval, float dmgDoneInterval, StatsHunter statsTotal, StatsHunter statsToProcess)
        {
            StatsHunter statsProcs = new StatsHunter();
            float fightDuration = BossOpts.BerserkTimer;
            float atkspeed = attemptedAtkIntervals[1];
            StatsHunter _stats, _stats2;
            
            foreach (SpecialEffect effect in (statsToProcess != null ? statsToProcess.SpecialEffects() : statsTotal.SpecialEffects()))
            {
                switch (effect.Trigger) {
                    case Trigger.Use:
                        _stats = new StatsHunter();
                        if (effect.Stats._rawSpecialEffectDataSize == 1 && statsToProcess == null) {
                            float uptime = effect.GetAverageUptime(0f, 1f, atkspeed, fightDuration);
                            _stats.AddSpecialEffect(effect.Stats._rawSpecialEffectData[0]);
                            _stats2 = GetSpecialEffectsStats(Char, triggerIntervals, triggerChances, attemptedAtkIntervals, hitRates, critRates, bleedHitInterval, dmgDoneInterval, statsTotal, _stats);
                            _stats = _stats2 * uptime;
                        } else {
                            _stats.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter);
                        }
                        statsProcs.Accumulate(_stats);
                        break;
                    case Trigger.MeleeHit:
                    case Trigger.PhysicalHit:
                    case Trigger.PhysicalAttack:
                        if (attemptedAtkIntervals[0] > 0f) {
                            statsProcs.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter);
                        }
                        break;
                    case Trigger.MeleeCrit:
                    case Trigger.PhysicalCrit:
                        if (attemptedAtkIntervals[0] > 0f) {
                            statsProcs.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter);
                        }
                        break;
                    case Trigger.DoTTick:
                        if (bleedHitInterval > 0f) { statsProcs.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter); } // 1/sec DeepWounds, 1/3sec Rend
                        break;
                    case Trigger.DamageDone: // physical and dots
                        if (dmgDoneInterval > 0f) { statsProcs.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter); }
                        break;
                    case Trigger.PetClawBiteSmackCrit:
                        if (attemptedAtkIntervals[3] > 0f) {
//                            Stats add = effect.GetAverageStats(triggerIntervals[3], critRates[1], atkspeed, fightDuration, 1f); // this needs to be fixed to read steady shot frequencies
                            statsProcs.Accumulate(effect.GetAverageStats(triggerIntervals, triggerChances, atkspeed, fightDuration, 1f) as StatsHunter); ;
                        }
                        break;
                }
            }
            return statsProcs;
        }
        public StatsHunter GetBuffsStats(Character character, CalculationOptionsHunter calcOpts) {
            List<Buff> removedBuffs = new List<Buff>();
            List<Buff> addedBuffs = new List<Buff>();

            List<Buff> buffGroup = new List<Buff>();
            #region Maintenance Auto-Fixing
            /* Removes the Sunder Armor if you are maintaining it yourself
             * Also removes Acid Spit and Expose Armor
             * We are now calculating this internally for better accuracy and to provide value to relevant talents
             * if (calcOpts.Maintenance[(int)CalculationOptionsDPSWarr.Maintenances.SunderArmor_])
             * {
             *   buffGroup.Clear();
             *   buffGroup.Add(Buff.GetBuffByName("Sunder Armor"));
             *   buffGroup.Add(Buff.GetBuffByName("Acid Spit"));
             *   buffGroup.Add(Buff.GetBuffByName("Expose Armor"));
             *   MaintBuffHelper(buffGroup, character, removedBuffs);
             * }
             */
            #endregion

            #region Passive Ability Auto-Fixing
            // Removes the Trueshot Aura Buff and it's equivalents Unleashed Rage and Abomination's Might if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            if (character.HunterTalents.TrueshotAura > 0) {
                buffGroup.Clear();
                buffGroup.Add(Buff.GetBuffByName("Trueshot Aura"));
                buffGroup.Add(Buff.GetBuffByName("Unleashed Rage"));
                buffGroup.Add(Buff.GetBuffByName("Abomination's Might"));
                MaintBuffHelper(buffGroup, character, removedBuffs);
            }

            // Removes the Ferocious Inspiration Buff and it's equivalents Sanctified Retribution and Arcane Tactics if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            if (character.HunterTalents.FerociousInspiration > 0) {
                buffGroup.Clear();
                buffGroup.Add(Buff.GetBuffByName("Ferocious Inspiration"));
                buffGroup.Add(Buff.GetBuffByName("Sanctified Retribution"));
                buffGroup.Add(Buff.GetBuffByName("Arcane Tactics"));
                MaintBuffHelper(buffGroup, character, removedBuffs);
            }


            // Removes the Hunting Party Buff and it's equivalents Improved Icy Talons and Windfury Totem if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            if (character.HunterTalents.HuntingParty > 0)
            {
                buffGroup.Clear();
                buffGroup.Add(Buff.GetBuffByName("Hunting Party"));
                buffGroup.Add(Buff.GetBuffByName("Improved Icy Talons"));
                buffGroup.Add(Buff.GetBuffByName("Windfury Totem"));
                MaintBuffHelper(buffGroup, character, removedBuffs);
            }

            // Removes the Hunter's Mark if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            buffGroup.Clear();
            buffGroup.Add(Buff.GetBuffByName("Hunter's Mark"));
            MaintBuffHelper(buffGroup, character, removedBuffs);
            #endregion

            StatsHunter statsBuffs = new StatsHunter();
            statsBuffs.Accumulate(GetBuffsStats(character.ActiveBuffs));
            AccumulateSetBonusStats(statsBuffs, character.SetBonusCount);

            #region PvP Set Bonus
            int PvPcount;
            character.SetBonusCount.TryGetValue("Gladiator's Pursuit", out PvPcount);
            if (PvPcount >= 2)
            {
                statsBuffs.Resilience += 400f;
                statsBuffs.Agility += 70f;
            }
            if (PvPcount >= 4)
            {
                statsBuffs.BonusFocusRegenMultiplier = 0.05f;
                statsBuffs.Agility += 90f;
            }
            #endregion

            #region Tier 11 Set Bonus
            int T11count;
            character.SetBonusCount.TryGetValue("Lightning-Charged Battlegear", out T11count);
            if (T11count >= 2)
            {
                statsBuffs.BonusSerpentStingCritChance = 0.05f;
            }
            if (T11count >= 4)
            {
                statsBuffs.FourPieceTier11 = 0.2f;
            }
            #endregion

            #region Tier 12 Set Bonus
            int T12count;
            character.SetBonusCount.TryGetValue("Flamewaker's Battlegear", out T12count);
            if (T12count >= 2)
            {
                statsBuffs.AddSpecialEffect(_SE_2T12_cs);
                statsBuffs.AddSpecialEffect(_SE_2T12_ss);
            }
            if (T12count >= 4)
            {
                statsBuffs.AddSpecialEffect(_SE_4T12);
            }
            #endregion

            foreach (Buff b in removedBuffs) { character.ActiveBuffsAdd(b); }
            foreach (Buff b in addedBuffs) { character.ActiveBuffs.Remove(b); }

            return statsBuffs;
        }
Beispiel #51
0
        public void GenPetStats()
        {
            // Initial Variables
            int levelDiff = BossOpts.Level - character.Level;
            StatsHunter petStatsBase = BasePetStats;
            #region From Hunter
            StatsHunter petStatsFromHunter = new StatsHunter() {
                AttackPower = (HunterStats.RangedAttackPower * 0.424f),
                SpellPower = HunterStats.RangedAttackPower * 0.211807381f,
                Stamina = HunterStats.Stamina,
                Agility = HunterStats.Agility,
                CritRating = HunterStats.CritRating,
                Strength = HunterStats.Strength,
                Spirit = HunterStats.PetSpirit,
                PhysicalHaste = HunterStats.PhysicalHaste,
                ArcaneResistance = HunterStats.ArcaneResistance * 0.4f,
                FireResistance   = HunterStats.FireResistance   * 0.4f,
                NatureResistance = HunterStats.NatureResistance * 0.4f,
                ShadowResistance = HunterStats.ShadowResistance * 0.4f,
                FrostResistance  = HunterStats.FrostResistance  * 0.4f,
                Armor = HunterStats.Armor * 0.7f,
                SpellPenetration = HunterStats.SpellPenetration,
                Resilience = HunterStats.Resilience,
                BonusDamageMultiplier = ((HunterStats.BonusDamageMultiplier /* / (1f + Talents.TheBeastWithin * 0.10f)*/))
                                      * ((character.Race == CharacterRace.Orc ? 0.05f : 0f)),
                BonusPetDamageMultiplier = HunterStats.BonusPetDamageMultiplier,
                BonusBleedDamageMultiplier = HunterStats.BonusBleedDamageMultiplier,
                BonusPetAttackPowerMultiplier = HunterStats.BonusPetAttackPowerMultiplier,
//                PetAttackPower = HunterStats.PetAttackPower,
            };
            #endregion
            #region From Talents (Pet or Hunter)
            Stats petStatsTalents = new Stats() {
                BonusStaminaMultiplier = PetTalents.GreatStamina * 0.04f,
                MovementSpeed = PetTalents.BoarsSpeed * 0.30f,
                PhysicalHaste = PetTalents.SerpentSwiftness * 0.05f,
                PhysicalCrit = PetTalents.SpidersBite * 0.03f
                             ,
                BaseArmorMultiplier = (1f + PetTalents.NaturalArmor * 0.05f)
                                    * (1f + PetTalents.PetBarding * 0.05f)
                                    * (1.05f) // Base 5% Armor Bonus
                                    - 1f,
                Dodge = PetTalents.PetBarding * 0.01f,
                CritChanceReduction = PetTalents.GraceOfTheMantis * 0.03f,
                ArcaneResistance = PetTalents.GreatResistance * 0.05f,
                FireResistance = PetTalents.GreatResistance * 0.05f,
                NatureResistance = PetTalents.GreatResistance * 0.05f,
                ShadowResistance = PetTalents.GreatResistance * 0.05f,
                FrostResistance = PetTalents.GreatResistance * 0.05f,
                FearDurReduc = PetTalents.Lionhearted * 0.15f,
                StunDurReduc = PetTalents.Lionhearted * 0.15f,
                BonusDamageMultiplier = (1 + (PetTalents.SharkAttack * 0.03f)) * (1.05f) - 1f, // Base 5% Damage
                //BonusAttackPowerMultiplier = calculatedStats.aspectBonusAPBeast,
                BonusHealthMultiplier = 0.05f, // Base 5% Health
            };
            float LongevityCdAdjust = 1f - Talents.Longevity * 0.10f;
            if (PetTalents.Rabid > 0) {
                float rabidCooldown = 45f * LongevityCdAdjust;
                SpecialEffect primary = new SpecialEffect(Trigger.Use, new Stats() { }, 20f, rabidCooldown);
                SpecialEffect secondary = new SpecialEffect(Trigger.MeleeHit,
                    new Stats() { BonusAttackPowerMultiplier = 0.05f }, 20f, 0f, 0.50f, 5);
                primary.Stats.AddSpecialEffect(secondary);
                petStatsTalents.AddSpecialEffect(primary);
            }
            if (Talents.Frenzy > 0) {
                if (frenzy == null) {
                    frenzy = new SpecialEffect(Trigger.MeleeCrit, new Stats() { PhysicalHaste = 0.30f, }, 8f, 1f, Talents.Frenzy * 0.20f);
                }
                petStatsTalents.AddSpecialEffect(frenzy);
            }
            if (PetTalents.LastStand > 0) {
                SpecialEffect laststand = new SpecialEffect(Trigger.Use, new Stats() { BonusHealthMultiplier = 0.30f, }, 20f, (1f * 60f) * LongevityCdAdjust);
                petStatsTalents.AddSpecialEffect(laststand);
            }
            #endregion
            #region From Options
            Stats petStatsOptionsPanel = new Stats() {
                PhysicalCrit = StatConversion.NPC_LEVEL_CRIT_MOD[levelDiff],
                //BonusStaminaMultiplier = 0.05f,
            };
            CalculateTimings();
            if(priorityRotation.getSkillFrequency(PetAttacks.SerenityDust) > 0){
                // TODO: Need to make sure this freq actually works
                float freq = priorityRotation.getSkillFrequency(PetAttacks.SerenityDust);
                SpecialEffect serenitydust = new SpecialEffect(Trigger.Use,
                    new Stats() { BonusAttackPowerMultiplier = 0.10f, },
                    15f, BossOpts.BerserkTimer / freq);
                petStatsOptionsPanel.AddSpecialEffect(serenitydust);
                petStatsOptionsPanel.HealthRestore += (BossOpts.BerserkTimer / freq) * 825f;
            }
            #endregion

            // Totals
//            Stats petStatsGearEnchantsBuffs = new Stats();
//            petStatsGearEnchantsBuffs.Accumulate(petStatsBuffs);
            StatsHunter petStatsTotal = new StatsHunter();
            petStatsTotal.Accumulate(petStatsBase);
            petStatsTotal.Accumulate(petStatsFromHunter);
//            petStatsTotal.Accumulate(petStatsBuffs);
            petStatsTotal.Accumulate(petStatsTalents);
            petStatsTotal.Accumulate(petStatsOptionsPanel);
            StatsHunter petStatsProcs = new StatsHunter();

            Dictionary<Trigger, float> triggerIntervals = new Dictionary<Trigger, float>();
            Dictionary<Trigger, float> triggerChances = new Dictionary<Trigger, float>();

            #region Stamina & Health
            float totalBSTAM = petStatsTotal.BonusStaminaMultiplier;
            //calculatedStats.petBaseHealth = BasePetStats.Health;
            //calculatedStats.petHealthfromStamina = (petStatsFromHunter.Stamina) * 10.4173919f;
            petStatsTotal.Stamina = (float)Math.Floor((1f + totalBSTAM) * petStatsTotal.Stamina);
            
            // Health | all pets have a 5% Bonus Stam
            petStatsTotal.Health += (petStatsTotal.Stamina) * 10.4173919f;
            petStatsTotal.Health *= 1f + petStatsTotal.BonusHealthMultiplier;
            //calculatedStats.petBonusHealth = petStatsTotal.Health - calculatedStats.petBaseHealth - calculatedStats.petHealthfromStamina;

            if (PetTalents.Bloodthirsty > 0) {
                SpecialEffect bloodthirsty = new SpecialEffect(Trigger.MeleeHit,
                    new Stats() { HealthRestore = petStatsTotal.Health * 0.05f },
                    0f, 0f, PetTalents.Bloodthirsty * 0.10f);
                petStatsTotal.AddSpecialEffect(bloodthirsty);
            }
            #endregion

            #region Strength
            float totalBSTRM = petStatsTotal.BonusStrengthMultiplier;
            petStatsTotal.Strength = /*(float)Math.Floor(*/(1f + totalBSTRM) * petStatsTotal.Strength/*)*/;
            #endregion

            #region Agility
            float totalBAGIM = petStatsTotal.BonusAgilityMultiplier;
            petStatsTotal.Agility = /*(float)Math.Floor(*/(1f + totalBAGIM) * petStatsTotal.Agility/*)*/;
            #endregion

            #region Attack Power
            petStatsTotal.BonusAttackPowerMultiplier *= (1f + petStatsTotal.BonusPetAttackPowerMultiplier);
            float totalBAPM    = petStatsTotal.BonusAttackPowerMultiplier;

            float apFromBase   = (1f + totalBAPM) * BasePetStats.PetAttackPower;
//            float apFromBonus  = (1f + totalBAPM) * (petStatsTotal.PetAttackPower - BasePetStats.PetAttackPower);

            float apFromHunter = ((1f + totalBAPM) * petStatsFromHunter.AttackPower);
//            float apFromSTR    = ((1f + totalBAPM) * (petStatsFromHunter.Strength)) * 0.85f;//(petStatsTotal.Strength - 10f) * 2f;
//            float apFromHvW    = 0f; //(1f + totalBAPM) * (HunterStats.Stamina * 0.10f * Talents.HunterVsWild);

            petStatsTotal.AttackPower = apFromBase /*+ apFromBonus*/ + apFromHunter /*+ apFromSTR + apFromHvW*/;
            #endregion

            #region Haste
            /*if (StatsPetBuffs._rawSpecialEffectData != null && StatsPetBuffs._rawSpecialEffectData.Length > 0) {
                Stats add = StatsPetBuffs._rawSpecialEffectData[0].GetAverageStats();
                StatsPetBuffs.PhysicalHaste *= (1f + add.PhysicalHaste);
            }*/
            #endregion

            #region Armor
            petStatsTotal.Armor = (float)Math.Floor((petStatsTotal.Armor - petStatsFromHunter.Armor) * (1f + petStatsTotal.BaseArmorMultiplier) + petStatsFromHunter.Armor);
//            petStatsTotal.BonusArmor += petStatsTotal.Agility * 2f;
            petStatsTotal.BonusArmor = (float)Math.Floor(petStatsTotal.BonusArmor * (1f + petStatsTotal.BonusArmorMultiplier));
            petStatsTotal.Armor += petStatsTotal.BonusArmor;
            #endregion

            #region Hit/Dodge Chances
            // This is tied directly to the Hunter's chance to miss
            PetChanceToMiss = Math.Max(0f, StatConversion.YELLOW_MISS_CHANCE_CAP[levelDiff] - HunterStats.PhysicalHit);
            PetChanceToSpellMiss = -1f * Math.Min(0f, StatConversion.GetSpellMiss(levelDiff, false) - HunterStats.SpellHit);

            //calculatedStats.petHitTotal = HunterStats.PhysicalHit;
            //calculatedStats.petHitSpellTotal = HunterStats.PhysicalHit * 17f / 8f;

            //petStatsTotal.PhysicalHit = calculatedStats.petHitTotal;
            //petStatsTotal.SpellHit = calculatedStats.petHitSpellTotal;

            // If the Hunter is Hit Capped, the pet is also Exp Capped
            // If not, Pet is proportionately lower based on Hunter's Hit
            // Expertise itself doesn't factor in at all
            PetChanceToBeDodged = StatConversion.YELLOW_DODGE_CHANCE_CAP[levelDiff]
                                * Math.Min(1f, (PetChanceToMiss / StatConversion.YELLOW_MISS_CHANCE_CAP[levelDiff]));
            //calculatedStats.petTargetDodge = PetChanceToBeDodged;

            float[] avoidChances = { PetChanceToMiss, PetChanceToSpellMiss, PetChanceToBeDodged };
            #endregion

            #region Crit Chance
            petStatsTotal.PhysicalCrit += StatConversion.GetCritFromAgility(petStatsTotal.Agility, CharacterClass.Warrior)
                                        + StatConversion.GetCritFromRating(petStatsTotal.CritRating);

            //calculatedStats.petCritTotalMelee = petStatsTotal.PhysicalCrit;

            // Cobra Strikes
            //calculatedStats.petCritFromCobraStrikes = 0;
            float cobraStrikesProc = Talents.CobraStrikes * 0.2f;
            if (cobraStrikesProc > 0)
            {
                #if FALSE
                float cobraStrikesCritFreqSteady = calculatedStats.steadyShot.Freq * (1f / calculatedStats.steadyShot.CritChance);
                float cobraStrikesCritFreqArcane = calculatedStats.arcaneShot.Freq * (1f / calculatedStats.arcaneShot.CritChance);
                float cobraStrikesCritFreqKill = calculatedStats.killShot.Freq * (1f / calculatedStats.killShot.CritChance);

                float cobraStrikesCritFreqSteadyInv = cobraStrikesCritFreqSteady > 0 ? 1f / cobraStrikesCritFreqSteady : 0;
                float cobraStrikesCritFreqArcaneInv = cobraStrikesCritFreqArcane > 0 ? 1f / cobraStrikesCritFreqArcane : 0;
                float cobraStrikesCritFreqKillInv = cobraStrikesCritFreqKill > 0 ? 1f / cobraStrikesCritFreqKill : 0;
                float cobraStrikesCritFreqInv = cobraStrikesCritFreqSteadyInv + cobraStrikesCritFreqArcaneInv + cobraStrikesCritFreqKillInv;
                float cobraStrikesCritFreq = cobraStrikesCritFreqInv > 0 ? 1f / cobraStrikesCritFreqInv : 0;
                float cobraStrikesProcAdjust = cobraStrikesCritFreq / cobraStrikesProc;

                float cobraStrikesFreqSteadyInv = calculatedStats.steadyShot.Freq > 0 ? 1f / calculatedStats.steadyShot.Freq : 0;
                float cobraStrikesFreqArcaneInv = calculatedStats.arcaneShot.Freq > 0 ? 1f / calculatedStats.arcaneShot.Freq : 0;
                float cobraStrikesFreqKillInv = calculatedStats.killShot.Freq > 0 ? 1f / calculatedStats.killShot.Freq : 0;
                float cobraStrikesFreqInv = cobraStrikesFreqSteadyInv + cobraStrikesFreqArcaneInv + cobraStrikesFreqKillInv;

                float cobraStrikesTwoSpecials = 2f * priorityRotation.petSpecialFrequency;
                float cobraStrikesUptime = 1f - (float)Math.Pow(1f - calculatedStats.steadyShot.CritChance * cobraStrikesProc, cobraStrikesFreqInv * cobraStrikesTwoSpecials);

                //calculatedStats.petCritFromCobraStrikes = (cobraStrikesUptime + (1f - cobraStrikesUptime) * calculatedStats.petCritTotalMelee) - calculatedStats.petCritTotalMelee;
                #endif

            }

            //calculatedStats.petCritTotalSpecials = petStatsTotal.PhysicalCrit + calculatedStats.petCritFromCobraStrikes; // PetCritChance
            //critSpecialsAdjust = calculatedStats.petCritTotalSpecials * 1.5f + 1f;
            #endregion

            #region Handle Special Effects
            CalculateTimings();
            WhAtkTable = new PetAttackTable(character, petStatsTotal, CalcOpts, avoidChances, false, false);
            YwAtkTable = new PetAttackTable(character, petStatsTotal, CalcOpts, avoidChances, PetAttacks.Claw, false, false);

            float AllAttemptedAtksInterval = GenPetFullAttackSpeed(petStatsTotal);
            float WhtAttemptedAtksInterval = PetAttackSpeed(petStatsTotal);
            float YlwAttemptedAtksInterval = AllAttemptedAtksInterval - WhtAttemptedAtksInterval;

            float[] hitRates  = { WhAtkTable.AnyLand,   // Whites
                                  YwAtkTable.AnyLand }; // Yellows
            float[] critRates = { WhAtkTable.Crit, // Whites
                                  YwAtkTable.Crit /*+ calculatedStats.petCritFromCobraStrikes*/ }; // Yellows

            float bleedHitInterval = 0f;
            float rakefreq = priorityRotation.getSkillFrequency(PetAttacks.Rake ); if (rakefreq > 0) { bleedHitInterval      += rakefreq; }

            float dmgDoneInterval = 1f; // Need to Fix this

            float clawbitesmackinterval = 0f;
            float clawfreq = priorityRotation.getSkillFrequency(PetAttacks.Claw ); if (clawfreq > 0) { clawbitesmackinterval += clawfreq; }
            float bitefreq = priorityRotation.getSkillFrequency(PetAttacks.Bite ); if (bitefreq > 0) { clawbitesmackinterval += bitefreq; }
            float smakfreq = priorityRotation.getSkillFrequency(PetAttacks.Smack); if (smakfreq > 0) { clawbitesmackinterval += smakfreq; }
            PetClawBiteSmackInterval = clawbitesmackinterval;

            float[] AttemptedAtkIntervals = {
                AllAttemptedAtksInterval, // All
                WhtAttemptedAtksInterval, // Whites
                YlwAttemptedAtksInterval, // Yellows
                PetClawBiteSmackInterval, // ClawBiteSmack
            };

            petStatsProcs.Accumulate(GetSpecialEffectsStats(character, triggerIntervals, triggerChances, AttemptedAtkIntervals, hitRates, critRates,
                                    bleedHitInterval, dmgDoneInterval, petStatsTotal, null) as StatsHunter);

            #region Stat Results of Special Effects
            // Base Stats
            petStatsProcs.Stamina  = (float)Math.Floor(petStatsProcs.Stamina  * (1f + totalBSTAM) * (1f + petStatsProcs.BonusStaminaMultiplier));
            petStatsProcs.Strength = (float)Math.Floor(petStatsProcs.Strength * (1f + totalBSTRM) * (1f + petStatsProcs.BonusStrengthMultiplier));
            petStatsProcs.Agility  = (float)Math.Floor(petStatsProcs.Agility  * (1f + totalBAGIM) * (1f + petStatsProcs.BonusAgilityMultiplier));
            petStatsProcs.Health  += (float)Math.Floor(petStatsProcs.Stamina  * 10f);
            petStatsProcs.Health  += (float)Math.Floor((petStatsProcs.Health + petStatsTotal.Health) * petStatsProcs.BonusHealthMultiplier);

            // Armor
            petStatsProcs.Armor = (float)Math.Floor(petStatsProcs.Armor * (1f + petStatsTotal.BaseArmorMultiplier + petStatsProcs.BaseArmorMultiplier));
            petStatsProcs.BonusArmor += petStatsProcs.Agility * 2f;
            petStatsProcs.BonusArmor = (float)Math.Floor(petStatsProcs.BonusArmor * (1f + petStatsTotal.BonusArmorMultiplier + petStatsProcs.BonusArmorMultiplier));
            petStatsProcs.Armor += petStatsProcs.BonusArmor;
            petStatsProcs.BonusArmor = 0; //it's been added to Armor so kill it

            // Attack Power
            petStatsProcs.BonusAttackPowerMultiplier *= (1f + petStatsProcs.BonusPetAttackPowerMultiplier);
            float totalBAPMProcs    = (1f + totalBAPM) * (1f + petStatsProcs.BonusAttackPowerMultiplier) - 1f;
            float apFromSTRProcs    = (1f + totalBAPMProcs) * (petStatsProcs.Strength * 2f);
            float apBonusOtherProcs = (1f + totalBAPMProcs) * (petStatsProcs.AttackPower + petStatsProcs.PetAttackPower);
            float apBonusFromBasetoNewMulti = (petStatsProcs.BonusAttackPowerMultiplier) * (petStatsTotal.AttackPower);
            petStatsProcs.AttackPower = (float)Math.Floor(apFromSTRProcs + apBonusOtherProcs + apBonusFromBasetoNewMulti);

            // Crit
            petStatsProcs.PhysicalCrit += StatConversion.GetCritFromAgility(petStatsProcs.Agility, CharacterClass.Warrior);
            //petStatsProcs.PhysicalCrit += StatConversion.GetCritFromRating(petStatsProcs.CritRating, CharacterClass.Warrior);

            #endregion
            petStatsTotal.Accumulate(petStatsProcs);

            GenPetFullAttackSpeed(petStatsTotal);
            CalculateTimings();
            clawbitesmackinterval = 0f;
            clawfreq = priorityRotation.getSkillFrequency(PetAttacks.Claw); if (clawfreq > 0) { clawbitesmackinterval += clawfreq; }
            bitefreq = priorityRotation.getSkillFrequency(PetAttacks.Bite); if (bitefreq > 0) { clawbitesmackinterval += bitefreq; }
            smakfreq = priorityRotation.getSkillFrequency(PetAttacks.Smack); if (smakfreq > 0) { clawbitesmackinterval += smakfreq; }
            PetClawBiteSmackInterval = clawbitesmackinterval;
            #endregion

            PetStats = petStatsTotal;

            #region Special Abilities Priority Rotation
            CalculateTimings();
            #endregion
            #region Kill Command MPS
            //calculatedStats.petKillCommandMPS = 0;
            killCommandCooldown = 0;
            if (CalcOpts.useKillCommand) {
                float killCommandManaCost = 40f /* * calculatedStats.baseMana*/;

//                float killCommandReadinessFactor = calculatedStats.priorityRotation.containsShot(Shots.Readiness) ? 1.0f / 180f : 0f;
                float killCommandCooldownBase = 1.0f;

//                killCommandCooldown = 1.0f / (killCommandCooldownBase + killCommandReadinessFactor);

                //calculatedStats.petKillCommandMPS = killCommandCooldown > 0 ? killCommandManaCost / killCommandCooldown : 0;
            }
            #endregion
            #region Target Debuffs
            float armorDebuffSporeCloud = 0;
            float sporeCloudFrequency = priorityRotation.getSkillFrequency(PetAttacks.SporeCloud);
            if (sporeCloudFrequency > 0)
            {
                float sporeCloudDuration = 9f;
                float sporeCloudUptime = sporeCloudDuration > sporeCloudFrequency ? 1f : sporeCloudDuration / sporeCloudFrequency;

                armorDebuffSporeCloud = sporeCloudUptime * 0.03f;
            }

            float armorDebuffAcidSpit = 0;
            float acidSpitFrequency = priorityRotation.getSkillFrequency(PetAttacks.AcidSpit); // AcidSpitEffectiveRate
            if (acidSpitFrequency > 0)
            {
                float acidSpitCalcFreq = priorityRotation.getSkillCooldown(PetAttacks.AcidSpit);
                float acidSpitDuration = 30;

                float acidSpitChanceToApply = 1f - PetChanceToMiss - PetChanceToBeDodged; // V45
                float acidSpitChancesToMaintain = (float)Math.Floor((acidSpitDuration - 1f) / acidSpitFrequency); // V46
                float acidSpitChanceToApplyFirst = acidSpitChancesToMaintain == 0 ? 0 : acidSpitChanceToApply; // V47
                float acidSpitChanceToStop = 1f - acidSpitChanceToApplyFirst; // AcidSpitChanceToStop
                float acidSpitAverageTimeToInc = acidSpitChanceToApplyFirst > 0 ? acidSpitFrequency : 0; // AcidSpitTimeToInc
                float acidSpitTimeSpentAtMax = acidSpitAverageTimeToInc + (acidSpitDuration * acidSpitChanceToStop); // AcidSpitAverageStackTime

                PetSkillStack[] stacks = new PetSkillStack[3];
                stacks[0] = new PetSkillStack();
                stacks[1] = new PetSkillStack();
                stacks[2] = new PetSkillStack();

                stacks[0].time_to_reach = 0;
                stacks[1].time_to_reach = acidSpitAverageTimeToInc * 1;
                stacks[2].time_to_reach = acidSpitAverageTimeToInc * 2;

                stacks[0].chance_to_max = 0;
                stacks[1].chance_to_max = acidSpitChanceToStop == 1 ? 0 : acidSpitChanceToStop;
                stacks[2].chance_to_max = acidSpitChanceToStop == 1 ? 0 : 1 - (stacks[0].chance_to_max + stacks[1].chance_to_max);

                stacks[0].time_spent = stacks[1].time_to_reach;
                stacks[1].time_spent = stacks[1].time_to_reach == 0 ? 0 : acidSpitTimeSpentAtMax * (1 - stacks[0].chance_to_max);
                stacks[2].time_spent = stacks[1].time_to_reach == 0 ? 0 : acidSpitChanceToStop == 0 ? 1 : 1 / acidSpitChanceToStop * acidSpitCalcFreq * (1-(stacks[0].chance_to_max + stacks[1].chance_to_max));

                float acidSpitTotalTime = stacks[0].time_spent + stacks[1].time_spent + stacks[2].time_spent;

                stacks[0].percent_time = acidSpitTotalTime == 0 ? 1 : stacks[0].time_spent / acidSpitTotalTime;
                stacks[1].percent_time = acidSpitTotalTime == 0 ? 1 : stacks[1].time_spent / acidSpitTotalTime;
                stacks[2].percent_time = acidSpitTotalTime == 0 ? 1 : stacks[2].time_spent / acidSpitTotalTime;

                stacks[0].total = stacks[0].percent_time * 0.0f;
                stacks[1].total = stacks[0].percent_time * 0.1f;
                stacks[2].total = stacks[0].percent_time * 0.2f;

                armorDebuffAcidSpit = stacks[0].total + stacks[1].total + stacks[2].total;
            }

            float armorDebuffSting = 0;
            float stingFrequency = priorityRotation.getSkillFrequency(PetAttacks.Sting);
            if (stingFrequency > 0) {
                float stingUseFreq = priorityRotation.getSkillFrequency(PetAttacks.Sting);
                float stingDuration = 20;
                float stingUptime = stingDuration > stingUseFreq ? 1 : stingDuration / stingUseFreq;

                armorDebuffSting = stingUptime * 0.05f;
            }

            // these local buffs can be overridden
            if (character.ActiveBuffsConflictingBuffContains("Sting")) {
                armorDebuffSporeCloud = 0;
                armorDebuffSting = 0;
            }
            if (character.ActiveBuffsConflictingBuffContains("Acid Spit")) {
                armorDebuffAcidSpit = 0;
            }

            //calculatedStats.petArmorDebuffs = 0f - (1f - armorDebuffSporeCloud) * (1f - armorDebuffAcidSpit) * (1f - armorDebuffSting) + 1;

            #endregion
            #region Hunter Effects
            // Ferocious Inspiraion
            // (Same as above)
            //calculatedStats.ferociousInspirationDamageAdjust = 1;
            if (character.HunterTalents.FerociousInspiration > 0) {
                if (CalcOpts.PetFamily != PETFAMILY.None)
                {
                    float ferociousInspirationSpecialsEffect = priorityRotation.petSpecialFrequency == 0 ? 0 : 10f / priorityRotation.petSpecialFrequency;
                    //float ferociousInspirationUptime = 1f - (float)Math.Pow(1f - calculatedStats.petCritTotalSpecials, (10f / attackSpeedEffective) + ferociousInspirationSpecialsEffect);
                    float ferociousInspirationEffect = 0.01f * character.HunterTalents.FerociousInspiration;

                    //calculatedStats.ferociousInspirationDamageAdjust = 1.0f + ferociousInspirationUptime * ferociousInspirationEffect;                    
                }
            }

            // Roar of Recovery
            //calculatedStats.manaRegenRoarOfRecovery = 0;
            float roarOfRecoveryFreq = priorityRotation.getSkillFrequency(PetAttacks.RoarOfRecovery);
            if (roarOfRecoveryFreq > 0) {
                float roarOfRecoveryUseCount = (float)Math.Ceiling(BossOpts.BerserkTimer / roarOfRecoveryFreq);
                float roarOfRecoveryManaRestored = HunterStats.Mana * 0.30f * roarOfRecoveryUseCount; // E129
                //calculatedStats.manaRegenRoarOfRecovery = roarOfRecoveryUseCount > 0 ? roarOfRecoveryManaRestored / BossOpts.BerserkTimer : 0;
            }

            //Invigoration
            //calculatedStats.manaRegenInvigoration = 0;
            float invigorationProcChance = Talents.Invigoration * 0.50f; // C32
            if (invigorationProcChance > 0) {
                float invigorationProcFreq = (priorityRotation.petSpecialFrequency /*/ calculatedStats.petCritTotalSpecials*/) / invigorationProcChance; //C35
                float invigorationEffect = Talents.Invigoration > 0 ? 0.01f : 0;
                float invigorationManaGainedPercent = invigorationProcFreq > 0 ? 60f / invigorationProcFreq * invigorationEffect : 0; // C36
                float invigorationManaPerMinute = invigorationProcFreq > 0 ? 60f / invigorationProcFreq * invigorationEffect * HunterStats.Mana : 0; // C37
                //calculatedStats.manaRegenInvigoration = invigorationManaPerMinute / 60f;
            }
            #endregion

            #region Target Armor Effect
            //31-10-2009 Drizz: added Armor effect
#if RAWR3 || RAWR4 || SILVERLIGHT
            //double petEffectiveArmor = BossOpts.Armor * (1f - calculatedStats.petArmorDebuffs);
            //calculatedStats.petTargetArmorReduction = StatConversion.GetArmorDamageReduction(character.Level, BossOpts.Armor, calculatedStats.petArmorDebuffs, 0, 0);
#else
            double petEffectiveArmor = CalcOpts.TargetArmor * (1f - calculatedStats.petArmorDebuffs);
            calculatedStats.petTargetArmorReduction = StatConversion.GetArmorDamageReduction(character.Level, CalcOpts.TargetArmor, calculatedStats.petArmorDebuffs, 0, 0);
#endif
            //petEffectiveArmor/(petEffectiveArmor - 22167.5f + (467.5f*80f));
            #endregion
        }
        /// <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 override Stats GetRelevantStats(Stats stats)
        {
            StatsHunter relevantStats = new StatsHunter() {
                #region Basic Stats
                Stamina = stats.Stamina,
                Health = stats.Health,
                Agility = stats.Agility,
                Armor = stats.Armor,
                BonusArmor = stats.BonusArmor,
                #endregion

                #region Ratings
                AttackPower = stats.AttackPower,
                RangedAttackPower = stats.RangedAttackPower,
                PhysicalCrit = stats.PhysicalCrit,
                CritRating = stats.CritRating,
                RangedCritRating = stats.RangedCritRating,
                PhysicalHit = stats.PhysicalHit,
                HitRating = stats.HitRating,
                RangedHitRating = stats.RangedHitRating,
                PhysicalHaste = stats.PhysicalHaste,
                HasteRating = stats.HasteRating,
                RangedHasteRating = stats.RangedHasteRating,
                MasteryRating = stats.MasteryRating,

                TargetArmorReduction = stats.TargetArmorReduction,
                Miss = stats.Miss,
                ScopeDamage = stats.ScopeDamage,
                #endregion

                #region Special
                HighestStat = stats.HighestStat,
                HighestSecondaryStat = stats.HighestSecondaryStat,
                Paragon = stats.Paragon,
                MovementSpeed = stats.MovementSpeed,
                StunDurReduc = stats.StunDurReduc,
                SnareRootDurReduc = stats.SnareRootDurReduc,
                FearDurReduc = stats.FearDurReduc,
                DarkmoonCardDeathProc = stats.DarkmoonCardDeathProc,
                #endregion

                #region Survivability
                HealthRestore = stats.HealthRestore,
                HealthRestoreFromMaxHealth = stats.HealthRestoreFromMaxHealth,
                #endregion

                // Set Bonuses

                #region Multipliers
                BonusStaminaMultiplier = stats.BonusStaminaMultiplier,
                BonusAgilityMultiplier = stats.BonusAgilityMultiplier,
                BonusIntellectMultiplier = stats.BonusIntellectMultiplier,
                BonusAttackPowerMultiplier = stats.BonusAttackPowerMultiplier,

                DamageTakenReductionMultiplier = stats.DamageTakenReductionMultiplier,
                BonusDamageMultiplier = stats.BonusDamageMultiplier,
                BaseArmorMultiplier = stats.BaseArmorMultiplier,
                BonusArmorMultiplier = stats.BonusArmorMultiplier,
                BonusCritDamageMultiplier = stats.BonusCritDamageMultiplier,
                //BonusSpiritMultiplier = stats.BonusSpiritMultiplier,
                // BonusManaMultiplier = stats.BonusManaMultiplier,
                BonusBleedDamageMultiplier = stats.BonusBleedDamageMultiplier,
                BonusPhysicalDamageMultiplier = stats.BonusPhysicalDamageMultiplier,
                #endregion

                #region Damage Procs
                ShadowDamage = stats.ShadowDamage,
                ArcaneDamage = stats.ArcaneDamage,
                HolyDamage = stats.HolyDamage,
                NatureDamage = stats.NatureDamage,
                FrostDamage = stats.FrostDamage,
                FireDamage = stats.FireDamage,
                BonusShadowDamageMultiplier = stats.BonusShadowDamageMultiplier,
                BonusArcaneDamageMultiplier = stats.BonusArcaneDamageMultiplier,
                BonusHolyDamageMultiplier = stats.BonusHolyDamageMultiplier,
                BonusNatureDamageMultiplier = stats.BonusNatureDamageMultiplier,
                BonusFrostDamageMultiplier = stats.BonusFrostDamageMultiplier,
                BonusFireDamageMultiplier = stats.BonusFireDamageMultiplier,
                #endregion
            };
           foreach (SpecialEffect effect in stats.SpecialEffects()) {
                if (RelevantTriggers.Contains(effect.Trigger) && (HasRelevantStats(effect.Stats) || HasSurvivabilityStats(effect.Stats)))
                {
                    relevantStats.AddSpecialEffect(effect);
                }
            }
            return relevantStats;
        }
 private StatsHunter GetSpecialEffectsStats(Character Char, Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, StatsHunter statsTotal, StatsHunter statsToProcess)
 {
     CalculationOptionsHunter calcOpts = Char.CalculationOptions as CalculationOptionsHunter;
     //BossOptions bossOpts = Char.BossOptions;
     ItemInstance RangeWeap = Char.MainHand;
     float speed = (RangeWeap != null ? RangeWeap.Speed : 2.4f);
     HunterTalents talents = Char.HunterTalents;
     StatsHunter statsProcs = new StatsHunter();
     float fightDuration_M = 450f;   //bossOpts.BerserkTimer;
     StatsHunter _stats, _stats2;
     try
     {
         foreach (SpecialEffect effect in (statsToProcess != null ? statsToProcess.SpecialEffects() : statsTotal.SpecialEffects()))
         {
             float fightDuration = fightDuration_M;
             /*float oldArp = float.Parse(effect.Stats.ArmorPenetrationRating.ToString());
             float arpToHardCap = StatConversion.RATING_PER_ARMORPENETRATION;
             if (effect.Stats.ArmorPenetrationRating > 0) {
                 float arpenBuffs = 0.0f;
                 float currentArp = arpenBuffs + StatConversion.GetArmorPenetrationFromRating(statsTotal.ArmorPenetrationRating
                     + (statsToProcess != null ? statsToProcess.ArmorPenetrationRating : 0f));
                 arpToHardCap *= (1f - currentArp);
             }*/
             if (triggerIntervals.ContainsKey(effect.Trigger) && (triggerIntervals[effect.Trigger] > 0f || effect.Trigger == Trigger.Use))
             {
                 float weight = 1f;
                 switch (effect.Trigger)
                 {
                     case Trigger.Use:
                         _stats = new StatsHunter();
                         if (effect.Stats._rawSpecialEffectDataSize == 1 && statsToProcess == null)
                         {
                             float uptime = effect.GetAverageUptime(0f, 1f, speed, fightDuration);
                             _stats.AddSpecialEffect(effect.Stats._rawSpecialEffectData[0]);
                             _stats2 = GetSpecialEffectsStats(Char, triggerIntervals, triggerChances, statsTotal, _stats);
                             _stats = _stats2 * uptime;
                         }
                         else
                         {
                             /*if (effect.Stats.ArmorPenetrationRating > 0 && arpToHardCap < effect.Stats.ArmorPenetrationRating) {
                                 float uptime = effect.GetAverageUptime(0f, 1f, speed, fightDuration);
                                 weight = uptime;
                                 _stats.ArmorPenetrationRating = arpToHardCap;
                             } else {*/
                             //    _stats = effect.GetAverageStats(0f, 1f, speed, fightDuration);
                             _stats = effect.GetAverageStats(triggerIntervals, triggerChances, speed, fightDuration, 1f) as StatsHunter;
                             //}
                         }
                         statsProcs.Accumulate(_stats, weight);
                         _stats = null;
                         break;
                     case Trigger.RangedHit:
                     case Trigger.PhysicalHit:
                     case Trigger.PhysicalAttack:
                         _stats = new StatsHunter();
                         weight = 1.0f;
                         {
                             /*if (effect.Stats.ArmorPenetrationRating > 0 && arpToHardCap < effect.Stats.ArmorPenetrationRating) {
                                 float uptime = effect.GetAverageUptime(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], speed, fightDuration);
                                 weight = uptime;
                                 _stats.ArmorPenetrationRating = arpToHardCap;
                             } else {*/
                             _stats = effect.GetAverageStats(triggerIntervals, triggerChances, speed, fightDuration, weight) as StatsHunter;
                             //}
                         }
                         statsProcs.Accumulate(_stats, weight);
                         _stats = null;
                         break;
                     case Trigger.MeleeHit: // Pets Only
                     case Trigger.MeleeCrit: // Pets Only
                     case Trigger.RangedCrit:
                     case Trigger.PhysicalCrit:
                     case Trigger.DoTTick:
                     case Trigger.DamageDone: // physical and dots
                     case Trigger.DamageOrHealingDone: // physical and dots
                     case Trigger.HunterAutoShotHit:
                     case Trigger.SteadyShotHit:
                     case Trigger.CobraShotHit:
                     case Trigger.PetClawBiteSmackCrit:
                         _stats = new StatsHunter();
                         weight = 1.0f;
                         /*if (effect.Stats.ArmorPenetrationRating > 0 && arpToHardCap < effect.Stats.ArmorPenetrationRating) {
                             float uptime = effect.GetAverageUptime(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], speed, fightDuration);
                             weight = uptime;
                             _stats.ArmorPenetrationRating = arpToHardCap;
                         } else {*/
                         _stats = effect.GetAverageStats(triggerIntervals, triggerChances, speed, fightDuration, weight) as StatsHunter;
                         //}
                         statsProcs.Accumulate(_stats, weight);
                         break;
                     case Trigger.SerpentWyvernStingsDoDamage:
                         _stats = new StatsHunter();
                         weight = 1.0f;
                         /*if (effect.Stats.ArmorPenetrationRating > 0 && arpToHardCap < effect.Stats.ArmorPenetrationRating) {
                             float uptime = effect.GetAverageUptime(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], speed, fightDuration);
                             weight = uptime;
                             _stats.ArmorPenetrationRating = arpToHardCap;
                         } else {*/
                         _stats = effect.GetAverageStats(triggerIntervals, triggerChances, speed, fightDuration, weight) as StatsHunter;
                         //}
                         statsProcs.Accumulate(_stats, weight);
                         break;
                 }
             }
             //effect.Stats.ArmorPenetrationRating = oldArp;
         }
     }
     catch (Exception ex)
     {
         new Base.ErrorBox()
         {
             Title = "Error in getting Special Effect information",
             Function = "GetSpecialEffectsStats()",
             TheException = ex,
         }.Show();
     }
     return statsProcs;
 }
        //private static readonly SpecialEffect FuriousHowl = new SpecialEffect(Trigger.Use, new StatsHunter() { AttackPower = 320f, PetAttackPower = 320f, }, 20f, 40f);

        private static void CalculateTriggers(Character character, CharacterCalculationsHunter calculatedStats, StatsHunter statsTotal, CalculationOptionsHunter calcOpts, BossOptions bossOpts, 
            Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances)
        {
            const float GCD = 1f;
            const float GCDpSec = 1f / GCD;
            int levelDif = bossOpts.Level - character.Level;
            float critMOD = StatConversion.NPC_LEVEL_CRIT_MOD[levelDif];
            HunterTalents talents = character.HunterTalents;
            float rangedWeaponSpeed = 2.4f; 
            float rangedWeaponDamage = 1;
            float autoShotSpeed = rangedWeaponSpeed; // Should be the same as rangedWeaponSpeed hasted.
            float autoShotsPerSecond = 1 / autoShotSpeed;
            float specialShotsPerSecond = GCDpSec; // I know it doesn't start w/ a special every GCD, but something to start with more than 0.
            float totalShotsPerSecond = GCDpSec + autoShotsPerSecond; 
            float shotsPerSecondWithoutHawk = 0;
//            RotationTest rotationTest;
            //GenRotation(character, statsTotal, calculatedStats, calcOpts, bossOpts, talents,
            //    out rangedWeaponSpeed, out rangedWeaponDamage, out autoShotSpeed,
            //    out autoShotsPerSecond, out specialShotsPerSecond, out totalShotsPerSecond, out shotsPerSecondWithoutHawk,
            //    out rotationTest);
            float ChanceToMiss = Math.Max(0f, StatConversion.WHITE_MISS_CHANCE_CAP[levelDif] - statsTotal.PhysicalHit);
            float ChanceToSpellMiss = Math.Max(0f, StatConversion.GetSpellMiss(levelDif, false) - statsTotal.SpellHit);

            // TODO: Ensure that we don't have any div by 0 issues here.

            #region Generic
            // Use
            triggerIntervals[Trigger.Use] = 0f; // Should be Effect cooldown.
            triggerChances[Trigger.Use] = 1f;

            // Physical Hit
            triggerIntervals[Trigger.PhysicalAttack] =
            triggerIntervals[Trigger.RangedHit] =
            triggerIntervals[Trigger.PhysicalHit] = 
            triggerIntervals[Trigger.RangedCrit] =
            triggerIntervals[Trigger.PhysicalCrit] = 1f / totalShotsPerSecond; // Note with DOT crits, this may have to be adjusted.

            triggerChances[Trigger.PhysicalAttack] = 
            triggerChances[Trigger.RangedHit] =
            triggerChances[Trigger.PhysicalHit] = (1f - ChanceToMiss);
            triggerChances[Trigger.RangedCrit] =
            triggerChances[Trigger.PhysicalCrit] = Math.Min(1f + critMOD, Math.Max(0f, statsTotal.PhysicalCrit));

            // Dots & damage done.
            triggerIntervals[Trigger.DoTTick] = talents.PiercingShots > 0 ? 1f : 0f; // Also need to add other DOTs into this value. 
            triggerIntervals[Trigger.DamageDone] = Math.Max(0f, 1f / (totalShotsPerSecond + ((talents.PiercingShots > 0 ? 1f : 0f) > 0 ? 1f / (talents.PiercingShots > 0 ? 1f : 0f) : 0f)));
            triggerIntervals[Trigger.DamageOrHealingDone] = Math.Max(0f, 1f / (totalShotsPerSecond + ((talents.PiercingShots > 0 ? 1f : 0f) > 0 ? 1f / (talents.PiercingShots > 0 ? 1f : 0f) : 0f))); // Need to add Self/pet-Heals

            triggerChances[Trigger.DoTTick] = 1f; // This should be up-time on DoTs & PS. 
            triggerChances[Trigger.DamageDone] = 1f;
            triggerChances[Trigger.DamageOrHealingDone] = 1f;

            #endregion 

            #region Pets only
            //triggerIntervals[Trigger.MeleeHit]                              = 
            //triggerIntervals[Trigger.MeleeCrit]                             = Math.Max(0f, calculatedStats.PetCalc.PetCompInterval);
            //triggerIntervals[Trigger.PetClawBiteSmackCrit]                  = Math.Max(0f, calculatedStats.PetCalc.PetClawBiteSmackInterval);

            //triggerChances[Trigger.MeleeHit]                              = calculatedStats.PetCalc.WhAtkTable.AnyLand;
            //triggerChances[Trigger.MeleeCrit]                             = Math.Min(1f + critMOD, Math.Max(0f, calculatedStats.PetCalc.WhAtkTable.Crit));
            //triggerChances[Trigger.PetClawBiteSmackCrit]                  = Math.Min(1f + critMOD, Math.Max(0f, calculatedStats.PetCalc.WhAtkTable.Crit));
            #endregion

            #region Hunter Specific
            triggerIntervals[Trigger.HunterAutoShotHit] = 1f / autoShotsPerSecond;
            triggerIntervals[Trigger.SteadyShotHit] = 0; // calculatedStats.steadyShot.Cd;
            triggerIntervals[Trigger.CobraShotHit] = 0; // calculatedStats.cobraShot.Cd;
            triggerIntervals[Trigger.EnergyOrFocusDropsBelow20PercentOfMax] = 4f; // Approximating as 80% chance every 4 seconds. TODO: Put in some actual method of calculating this

            triggerChances[Trigger.HunterAutoShotHit] = (1f - ChanceToMiss);
            triggerChances[Trigger.SteadyShotHit] = (1f - ChanceToMiss);
            triggerChances[Trigger.CobraShotHit] = (1f - ChanceToMiss);
            triggerChances[Trigger.EnergyOrFocusDropsBelow20PercentOfMax] = 0.80f; // Approximating as 80% chance every 4 seconds. TODO: Put in some actual method of calculating this
            #endregion
        }