Example #1
0
        public Pet(StatsDK dkstats, DeathKnightTalents t, BossOptions bo, Presence p)
        {
            m_BO = bo;
            m_DKStats = dkstats;
            m_Talents = t;
            m_Presence = p;

            AccumulateStats();
        }
Example #2
0
 /// <summary>
 /// Use the Talent spec to determine which type of rotation we should be looking towards.
 /// </summary>
 /// <param name="t">DeathKnightTalents</param>
 /// <returns>Enum "Type" [Custom, Blood, Frost, Unholy, Unknown]</returns>
 public Type GetRotationType(DeathKnightTalents t)
 {
     curRotationType = Type.Custom;
     if (t.HighestTree == (int)TalentTrees.Blood)
     {
         // Blood
         curRotationType = Rotation.Type.Blood;
     }
     else if (t.HighestTree == (int)TalentTrees.Frost)
     {
         // Frost
         curRotationType = Rotation.Type.Frost;
     }
     if (t.HighestTree == (int)TalentTrees.Unholy)
     {
         // Unholy
         curRotationType = Rotation.Type.Unholy;
     }
     return curRotationType;
 }
Example #3
0
        /// <summary>
        /// Get the type of rotation we should be using based on talents.
        /// </summary>
        /// <param name="t">DeathKnight Talents to evaluate.</param>
        public void GetRotationByTalents(DeathKnightTalents t)
        {
            if (curRotationType == Type.Custom)
            {
                managedRP = false;
                // if talents are all 0, then setup a basic rotation:
                curRotationType = Type.Custom;
                // we're going to just spam a very basic rotation.
                // IT-PS-BS-BS-DS-DS-RP
                // Need to find a way to actually implement this properly.
                numDisease    = 2f;
                diseaseUptime = 100f;
                IcyTouch      = 2f;
                PlagueStrike  = 2f;
                BloodStrike   = 2f;
                Obliterate    = 0f;
                DeathStrike   = 2f;
                RuneStrike    = 3f;
                Pestilence    = 0f;

                DeathCoil           = 2f;
                ScourgeStrike       = 0f;
                FrostStrike         = 0f;
                HowlingBlast        = 0f;
                HeartStrike         = 0f;
                curRotationDuration = 15f;
            }
            const int indexBlood  = 0;               // start index of Blood Talents.
            const int indexFrost  = 28;              // start index of Frost Talents.
            const int indexUnholy = indexFrost + 29; // start index of Unholy Talents.

            int[] TalentCounter = new int[4];
            int   index         = indexBlood;

            foreach (int i in t.Data)
            {
                if (i > 0)
                {
                    // Blood
                    if (index < indexFrost)
                    {
                        TalentCounter[(int)Type.Blood]++;
                    }
                    // Frost
                    else if ((indexFrost <= index) && (index < indexUnholy))
                    {
                        TalentCounter[(int)Type.Frost]++;
                    }
                    // Unholy
                    else if (index >= indexUnholy)
                    {
                        TalentCounter[(int)Type.Unholy]++;
                    }
                }
                index++;
            }
            if ((TalentCounter[(int)Type.Blood] > TalentCounter[(int)Type.Frost]) && (TalentCounter[(int)Type.Blood] > TalentCounter[(int)Type.Unholy]))
            {
                // Blood
                curRotationType = Type.Blood;
            }
            else if ((TalentCounter[(int)Type.Frost] > TalentCounter[(int)Type.Blood]) && (TalentCounter[(int)Type.Frost] > TalentCounter[(int)Type.Unholy]))
            {
                // Frost
                curRotationType = Type.Frost;
            }
            else if ((TalentCounter[(int)Type.Unholy] > TalentCounter[(int)Type.Frost]) && (TalentCounter[(int)Type.Unholy] > TalentCounter[(int)Type.Blood]))
            {
                // Unholy
                curRotationType = Type.Unholy;
            }

            managedRP = true;
            #region Frost Rotations
            if (curRotationType == Type.Frost)
            {
                numDisease    = 2f;
                diseaseUptime = 100f;
                IcyTouch      = 2f;
                PlagueStrike  = 2f;
                ScourgeStrike = 0f;
                FrostStrike   = 0f;
                if (t.FrostStrike > 0)
                {
                    DeathCoil   = 0f;
                    FrostStrike = 2f;
                }
                else
                {
                    DeathCoil   = 2f;
                    FrostStrike = 0f;
                }
                HowlingBlast        = 0f;
                Obliterate          = 3f;
                BloodStrike         = 2f;
                HeartStrike         = 0f;
                DeathStrike         = 0f;
                RuneStrike          = 3f;
                Pestilence          = 0f;
                curRotationDuration = 15f;

                if (t.GlyphofHowlingBlast && t.HowlingBlast > 0)
                {
                    // Single Disease Glyphed HB rotation
                    // Means that we start w/ HB for the FF hit, and factor in PS later, while HB is on CD.
                    numDisease   = 1f;
                    IcyTouch     = 1f;
                    PlagueStrike = 1f;
                    HowlingBlast = 1f;
                }
                if (t.Rime > 0 && t.HowlingBlast > 0)
                {
                    // Additional HB proc based on Rime.
                    HowlingBlast += .5f;
                }
            }
            #endregion
            #region Blood Rotations
            else if (curRotationType == Type.Blood)
            {
                numDisease    = 2f;
                diseaseUptime = 100f;
                DeathCoil     = 2f;
                IcyTouch      = 1f;
                PlagueStrike  = 1f;
                ScourgeStrike = 0f;
                FrostStrike   = 0f;
                HowlingBlast  = 0f;
                Obliterate    = 0f;
                DeathStrike   = 2f;
                if (HeartStrike > 0)
                {
                    HeartStrike = 6f;
                    BloodStrike = 0f;
                }
                else
                {
                    HeartStrike = 0f;
                    BloodStrike = 6f;
                }
                Pestilence          = 0f;
                RuneStrike          = 2f;
                curRotationDuration = 15f;
            }
            #endregion
            #region Unholy Rotations
            else if (curRotationType == Type.Unholy)
            // UnHoly
            {
                numDisease    = 3f;
                diseaseUptime = 100f;
                DeathCoil     = 2f;
                IcyTouch      = 1f;
                PlagueStrike  = 1f;
                ScourgeStrike = 0f;
                if (t.ScourgeStrike > 0)
                {
                    ScourgeStrike = 4f;
                }
                else
                {
                    DeathStrike = 4f;
                }
                FrostStrike         = 0f;
                HowlingBlast        = 0f;
                Obliterate          = 0f;
                BloodStrike         = 2f;
                HeartStrike         = 0f;
                curRotationDuration = 20f;
                RuneStrike          = 2f;
                Pestilence          = 0f;
            }
            #endregion
        }
Example #4
0
        public DRW(CombatTable combatTable, CharacterCalculationsDPSDK calcs, CalculationOptionsDPSDK calcOpts, Stats stats,
                   Character character, DeathKnightTalents talents)
        {
            bool DW = false;

            float dpsWhite              = 0f;
            float dpsBCB                = 0f;
            float dpsNecrosis           = 0f;
            float dpsDeathCoil          = 0f;
            float dpsIcyTouch           = 0f;
            float dpsPlagueStrike       = 0f;
            float dpsFrostFever         = 0f;
            float dpsBloodPlague        = 0f;
            float dpsDeathStrike        = 0f;
            float dpsHeartStrike        = 0f;
            float dpsWPFromFF           = 0f;
            float dpsWPFromBP           = 0f;
            float dpsWhiteMinusGlancing = 0f;
            float dpsWhiteBeforeArmor   = 0f;

            float IcyTouchAPMult    = 0.1f;
            float FrostFeverAPMult  = 0.055f;
            float BloodPlagueAPMult = 0.055f;
            float DeathCoilAPMult   = 0.15f;

            float OHMult = 0.5f;

            int   targetLevel = calcOpts.TargetLevel;
            float arpBuffs    = talents.BloodGorged * 2f / 100;
            float mitigation  = StatConversion.GetArmorDamageReduction(character.Level, calcOpts.BossArmor, stats.ArmorPenetration, arpBuffs, stats.ArmorPenetrationRating);

            mitigation = 1 - mitigation;
            float MHDPS = 0f, OHDPS = 0f;

            #region White Dmg
            {
                #region Main Hand
                {
                    float dpsMHglancing    = (StatConversion.WHITE_GLANCE_CHANCE_CAP[targetLevel - 80] * combatTable.MH.DPS) * 0.7f;
                    float dpsMHBeforeArmor = ((combatTable.MH.DPS * (1f - calcs.AvoidedAttacks - StatConversion.WHITE_GLANCE_CHANCE_CAP[targetLevel - 80])) * (1f + combatTable.physCrits)) + dpsMHglancing;
                    dpsWhiteMinusGlancing = dpsMHBeforeArmor - dpsMHglancing;
                    dpsWhiteBeforeArmor   = dpsMHBeforeArmor;
                    MHDPS = dpsMHBeforeArmor * mitigation;
                }
                #endregion

                #region Off Hand
                if (DW || (character.MainHand == null && character.OffHand != null))
                {
                    float dpsOHglancing    = (StatConversion.WHITE_GLANCE_CHANCE_CAP[targetLevel - 80] * combatTable.OH.DPS) * 0.7f;
                    float dpsOHBeforeArmor = ((combatTable.OH.DPS * (1f - calcs.AvoidedAttacks - StatConversion.WHITE_GLANCE_CHANCE_CAP[targetLevel - 80])) * (1f + combatTable.physCrits)) + dpsOHglancing;
                    dpsOHBeforeArmor      *= OHMult;
                    dpsWhiteMinusGlancing += dpsOHBeforeArmor - dpsOHglancing;
                    dpsWhiteBeforeArmor   += dpsOHBeforeArmor;
                    OHDPS = dpsOHBeforeArmor * mitigation;
                }
                #endregion

                dpsWhite = MHDPS + OHDPS;
            }
            #endregion

            #region Necrosis
            {
                dpsNecrosis = dpsWhiteMinusGlancing * (.04f * (float)talents.Necrosis); // doesn't proc off Glancings
            }
            #endregion

            #region Blood Caked Blade
            {
                float dpsMHBCB = 0f;
                if (combatTable.MH.damage != 0)
                {
                    float MHBCBDmg = (float)(combatTable.MH.damage * (.25f + .125f * calcOpts.rotation.AvgDiseaseMult));
                    dpsMHBCB = MHBCBDmg / combatTable.MH.hastedSpeed;
                }
                dpsBCB  = dpsMHBCB;
                dpsBCB *= .1f * (float)talents.BloodCakedBlade;
            }
            #endregion

            #region Death Coil
            {
                if (calcOpts.rotation.DeathCoil > 0f)
                {
                    float DCCD  = 1;
                    float DCDmg = 443f + (DeathCoilAPMult * stats.AttackPower);
                    dpsDeathCoil = DCDmg / DCCD;
                    float DCCritDmgMult = .5f * (2f + stats.BonusCritMultiplier);
                    float DCCrit        = 1f + ((combatTable.spellCrits + stats.BonusDeathCoilCrit) * DCCritDmgMult);
                    dpsDeathCoil *= DCCrit;

                    dpsDeathCoil *= 1f + (.05f * (float)talents.Morbidity);
                }
            }
            #endregion

            #region Icy Touch
            {
                if (calcOpts.rotation.IcyTouch > 0f)
                {
                    float ITCD  = 1;
                    float ITDmg = 236f + (IcyTouchAPMult * stats.AttackPower) + stats.BonusIcyTouchDamage;
                    ITDmg      *= 1f + .1f * (float)talents.ImprovedIcyTouch;
                    dpsIcyTouch = ITDmg / ITCD;
                    float ITCritDmgMult = .5f * (2f + stats.CritBonusDamage + stats.BonusCritMultiplier);
                    float ITCrit        = 1f + (Math.Min((combatTable.spellCrits + (.05f * (float)talents.Rime)), 1f) * ITCritDmgMult);
                    dpsIcyTouch *= ITCrit;
                }
            }
            #endregion

            #region Plague Strike
            {
                if (calcOpts.rotation.PlagueStrike > 0f)
                {
                    float PSCD  = 1;
                    float PSDmg = (combatTable.MH.baseDamage + ((stats.AttackPower / 14f) *
                                                                combatTable.normalizationFactor)) * 0.5f + 189f;
                    dpsPlagueStrike = PSDmg / PSCD;
                    float PSCritDmgMult = 1f + (.15f * (float)talents.ViciousStrikes) + stats.BonusCritMultiplier;
                    float PSCrit        = 1f + ((combatTable.physCrits + (.03f * (float)talents.ViciousStrikes) +
                                                 stats.BonusPlagueStrikeCrit) * PSCritDmgMult);

                    dpsPlagueStrike *= PSCrit;
                    dpsPlagueStrike *= 1f + (.1f * (float)talents.Outbreak);
                }
            }
            #endregion

            #region Frost Fever
            {
                if (calcOpts.rotation.IcyTouch > 0f ||
                    (talents.GlyphofHowlingBlast && calcOpts.rotation.HowlingBlast > 0f) ||
                    (talents.GlyphofDisease && calcOpts.rotation.Pestilence > 0f))
                {
                    float FFDmg = FrostFeverAPMult * stats.AttackPower + 25.6f;
                    dpsFrostFever  = FFDmg;
                    dpsFrostFever *= 1.15f;     // Patch 3.2: Diseases hit 15% harder.
                    dpsWPFromFF    = dpsFrostFever * combatTable.physCrits;
                }
            }
            #endregion

            #region Blood Plague
            {
                if (calcOpts.rotation.PlagueStrike > 0f || talents.GlyphofDisease)
                {
                    float BPDmg = BloodPlagueAPMult * stats.AttackPower + 31.1f;
                    dpsBloodPlague  = BPDmg;
                    dpsBloodPlague *= 1.15f; // Patch 3.2: Diseases hit 15% harder.
                    dpsWPFromBP     = dpsBloodPlague * combatTable.physCrits;
                }
            }
            #endregion

            #region Death Strike
            {
                if (calcOpts.rotation.DeathStrike > 0f)
                {
                    float DSCD = 1;
                    // TODO: This should be changed to make use of the new glyph stats:
                    float DSDmg = ((combatTable.MH.baseDamage + ((stats.AttackPower / 14f) * combatTable.normalizationFactor)) * 0.75f) + 222.75f;
                    DSDmg         *= 1f + 0.15f * (float)talents.ImprovedDeathStrike;
                    dpsDeathStrike = DSDmg / DSCD;
                    float DSCritDmgMult = 1f + (.15f * (float)talents.MightOfMograine) + stats.BonusCritMultiplier;
                    float DSCrit        = 1f + ((combatTable.physCrits +
                                                 (.03f * (float)talents.ImprovedDeathStrike) +
                                                 stats.BonusDeathStrikeCrit) * DSCritDmgMult);
                    dpsDeathStrike *= DSCrit;
                }
            }
            #endregion

            #region Heart Strike
            {
                if (talents.HeartStrike > 0 && calcOpts.rotation.HeartStrike > 0f)
                {
                    float HSCD  = 1;
                    float HSDmg = ((combatTable.MH.baseDamage + ((stats.AttackPower / 14f) * combatTable.normalizationFactor)) *
                                   0.5f) + 368f;
                    HSDmg         *= 1f + 0.1f * (float)calcOpts.rotation.AvgDiseaseMult * (1f + stats.BonusPerDiseaseHeartStrikeDamage);
                    dpsHeartStrike = HSDmg / HSCD;
                    //float HSCrit = 1f + combatTable.physCrits + ( .03f * (float)talents.Subversion );
                    float HSCritDmgMult = 1f + (.15f * (float)talents.MightOfMograine) + stats.BonusCritMultiplier;
                    float HSCrit        = 1f + ((combatTable.physCrits + (.03f * (float)talents.Subversion)) * HSCritDmgMult);
                    dpsHeartStrike  = (dpsHeartStrike) * HSCrit;
                    dpsHeartStrike *= 1f + (.15f * (float)talents.BloodyStrikes);
                }
            }
            #endregion

            float BCBMult          = 1f;
            float BloodPlagueMult  = 1f;
            float DeathCoilMult    = 1f;
            float FrostFeverMult   = 1f;
            float HeartStrikeMult  = 1f;
            float IcyTouchMult     = 1f;
            float NecrosisMult     = 1f;
            float DeathStrikeMult  = 1f;
            float PlagueStrikeMult = 1f;
            float WhiteMult        = 1f;

            float spellPowerMult      = 1f + stats.BonusSpellPowerMultiplier;
            float frostSpellPowerMult = 1f + stats.BonusSpellPowerMultiplier + Math.Max((stats.BonusFrostDamageMultiplier - stats.BonusShadowDamageMultiplier), 0f);
            float partialResist       = 0.94f;
            float physPowerMult       = 1f;

            #region Apply Physical Mitigation
            {
                float physMit = mitigation;
                physMit *= 1f + (!DW ? .02f * talents.TwoHandedWeaponSpecialization : 0f);

                dpsBCB           *= physMit;
                dpsHeartStrike   *= physMit;
                dpsDeathStrike   *= physMit;
                dpsPlagueStrike  *= physMit;
                WhiteMult        += physPowerMult - 1f;
                BCBMult          += physPowerMult - 1f;
                HeartStrikeMult  += physPowerMult - 1f;
                DeathStrikeMult  += physPowerMult - 1f;
                PlagueStrikeMult += physPowerMult - 1f;
            }
            #endregion

            #region Apply Magical Mitigation
            {
                // some of this applies to necrosis, I wonder if it is ever accounted for
                float magicMit = partialResist /** combatTable.spellResist*/;
                // magicMit = 1f - magicMit;

                dpsNecrosis    *= magicMit;
                dpsBloodPlague *= magicMit;
                dpsDeathCoil   *= magicMit * (1f - combatTable.spellResist);
                dpsFrostFever  *= magicMit;
                dpsIcyTouch    *= magicMit;


                NecrosisMult    += spellPowerMult - 1f;
                BloodPlagueMult += spellPowerMult - 1f;
                DeathCoilMult   += spellPowerMult - 1f;
                FrostFeverMult  += frostSpellPowerMult - 1f;
                IcyTouchMult    += frostSpellPowerMult - 1f;
            }
            #endregion


            #region Apply Multi-Ability Talent Multipliers
            {
                float BloodyVengeanceMult = .03f * (float)talents.BloodyVengeance;
                BCBMult          *= 1 + BloodyVengeanceMult;
                HeartStrikeMult  *= 1 + BloodyVengeanceMult;
                DeathStrikeMult  *= 1 + BloodyVengeanceMult;
                PlagueStrikeMult *= 1 + BloodyVengeanceMult;
                WhiteMult        *= 1 + BloodyVengeanceMult;

                float HysteriaCoeff = .2f / 2f; // current uptime is 50% for now
                float HysteriaMult  = HysteriaCoeff * (float)talents.Hysteria;
                BCBMult          *= 1 + HysteriaMult;
                HeartStrikeMult  *= 1 + HysteriaMult;
                DeathStrikeMult  *= 1 + HysteriaMult;
                PlagueStrikeMult *= 1 + HysteriaMult;
                WhiteMult        *= 1 + HysteriaMult;

                float BlackIceMult = .02f * (float)talents.BlackIce;
                FrostFeverMult  *= 1 + BlackIceMult;
                IcyTouchMult    *= 1 + BlackIceMult;
                DeathCoilMult   *= 1 + BlackIceMult;
                BloodPlagueMult *= 1 + BlackIceMult;

                float CryptFeverMult = .1f * (float)talents.CryptFever;
                float CryptFeverBuff = stats.BonusDiseaseDamageMultiplier;
                CryptFeverMult   = Math.Max(CryptFeverMult, CryptFeverBuff);
                FrostFeverMult  *= 1 + CryptFeverMult;
                BloodPlagueMult *= 1 + CryptFeverMult;
            }
            #endregion



            dpsDancingRuneWeapon = dpsWhite * WhiteMult * 17f +
                                   dpsBCB * BCBMult * 17f +
                                   dpsNecrosis * NecrosisMult * 17f +
                                   dpsDeathCoil * DeathCoilMult +
                                   dpsIcyTouch * IcyTouchMult +
                                   dpsPlagueStrike * PlagueStrikeMult +
                                   dpsFrostFever * (5f + talents.Epidemic) * FrostFeverMult +
                                   dpsBloodPlague * (5f + talents.Epidemic) * BloodPlagueMult +
                                   dpsDeathStrike * DeathStrikeMult * (talents.GlyphofDancingRuneWeapon ? 1f : 0f) +
                                   dpsHeartStrike * HeartStrikeMult * (5f + (talents.GlyphofDancingRuneWeapon ? 2f : 0f));
            dpsDancingRuneWeapon *= 0.5f;
        }
Example #5
0
 public Disease(Character c, Stats s, CalculationOptionsDPSDK Calcopts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = Calcopts; combatTable = table; talents = Talents; GcdType = GCDType.None; Runes = RunesUsed.None; Name = "A Disease";
 }
Example #6
0
 public BloodBoil(Character c, Stats s, CalculationOptionsDPSDK CalcOpts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = CalcOpts; combatTable = table; talents = Talents; GcdType = GCDType.Spell; Runes = RunesUsed.Blood; Name = "Blood Boil";
 }
 private void AccumulateGlyphStats(Stats s, DeathKnightTalents t)
 {
     if (t.GlyphofBoneShield)
         s.MovementSpeed = (float)Math.Max(s.MovementSpeed, 1.15f);
 }
Example #8
0
 public HowlingBlast(Character c, Stats s, CalculationOptionsDPSDK CalcOpts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = CalcOpts; combatTable = table; talents = Talents; GcdType = GCDType.Spell; Runes = RunesUsed.UnholyFrost; Name = "Howling Blast";
 }
Example #9
0
        public RotationGene(int availableBlood, int availableFrost, int availableUnholy, DeathKnightTalents talents)
        {
            Rotation = new Rotation();
            Rotation.curRotationType = Rotation.Type.Custom;
            Rotation.ManagedRP       = true;
            Random rand = new Random((int)(CalculationsDPSDK.hawut + 0.5d));

            CalculationsDPSDK.hawut -= rand.NextDouble() * DateTime.Now.ToOADate() / 1000000;
            double nextRand;

            Rotation.presence = (rand.NextDouble() > .5 ? CalculationOptionsDPSDK.Presence.Blood : CalculationOptionsDPSDK.Presence.Unholy);
            nextRand          = rand.NextDouble();
            #region blood runes
            if (nextRand > 0.5d && availableBlood > 0d)
            {
                Rotation.Pestilence = 1;
                availableBlood--;
            }
            nextRand = rand.NextDouble();
            if (nextRand < 1d / 3d)
            {
                Rotation.BloodStrike = availableBlood;
                Rotation.HeartStrike = 0;
                Rotation.BloodBoil   = 0;
            }
            else if (nextRand < 2d / 3d)
            {
                Rotation.BloodStrike = 0;
                Rotation.HeartStrike = availableBlood;
                Rotation.BloodBoil   = 0;
            }
            else
            {
                Rotation.BloodStrike = 0;
                Rotation.HeartStrike = 0;
                Rotation.BloodBoil   = availableBlood;
            }
            #endregion

            #region frost and unholy runes
            nextRand = rand.NextDouble();
            if (nextRand > 0.5d && availableFrost > 0d)
            {
                Rotation.IcyTouch = 1;
                availableFrost--;
            }
            else
            {
                Rotation.IcyTouch = 0;
            }
            nextRand = rand.NextDouble();
            if (nextRand > 0.5d && availableUnholy > 0d)
            {
                Rotation.PlagueStrike = 1;
                availableUnholy--;
            }
            else
            {
                Rotation.PlagueStrike = 0;
            }
            nextRand = rand.NextDouble();
            if (nextRand < .25d)
            {
                Rotation.DeathStrike   = (availableUnholy + availableFrost) / 2f;
                Rotation.ScourgeStrike = 0;
                Rotation.Obliterate    = 0;
            }
            else if (nextRand < .5d)
            {
                Rotation.DeathStrike   = 0;
                Rotation.ScourgeStrike = (availableFrost + availableUnholy) / 2f;
                Rotation.Obliterate    = 0;
            }
            else if (nextRand < .75d)
            {
                Rotation.DeathStrike   = 0;
                Rotation.ScourgeStrike = 0;
                Rotation.Obliterate    = (availableUnholy + availableFrost) / 2f;
            }
            else
            {
                Rotation.DeathStrike   = 0;
                Rotation.ScourgeStrike = 0;
                Rotation.Obliterate    = 0;
                Rotation.PlagueStrike += availableUnholy;
                Rotation.IcyTouch     += availableFrost;
            }
            #endregion
            Rotation.AvgDiseaseMult = (Rotation.IcyTouch > 0 ? 1 : 0) + (Rotation.PlagueStrike > 0 ? 1 : 0);
            if (talents.CryptFever > 0 && (Rotation.IcyTouch > 0 || Rotation.PlagueStrike > 0))
            {
                Rotation.AvgDiseaseMult++;
            }
            double minDuration = availableBlood + availableFrost + availableUnholy;
            minDuration /= 6;
            minDuration *= 10 - (Rotation.presence == CalculationOptionsDPSDK.Presence.Unholy ? talents.ImprovedUnholyPresence * .5 : 0);
        }
Example #10
0
 public IcyTouch(Character c, Stats s, CalculationOptionsDPSDK CalcOpts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = CalcOpts; combatTable = table; GcdType = GCDType.Spell; Runes = RunesUsed.Frost; talents = Talents; Name = "Icy Touch";
 }
Example #11
0
        public Weapon (Item i, Stats stats, CalculationOptionsDPSDK calcOpts, BossOptions bossOpts, DeathKnightTalents talents, float expertise, CharacterSlot hand) {
            if (stats == null || calcOpts == null || !(hand == CharacterSlot.MainHand || hand == CharacterSlot.OffHand )) { return; }

            if (i == null) {
                i = new Item();
                i.Speed = 2.0f;
                i.MinDamage = 0;
                i.MaxDamage = 0;
            }
            else
            {
                twohander = (i.Slot == ItemSlot.TwoHand);
            }

            effectiveExpertise = expertise;

            if (i == null) { return; }

            baseSpeed = i.Speed;
            baseDamage = (float)(i.MinDamage + i.MaxDamage) / 2f + stats.WeaponDamage;

            #region Attack Speed
            {
                hastedSpeed = baseSpeed / (1 + stats.PhysicalHaste);
            }
            #endregion

            #region Dodge
            {
                float baseDodged = StatConversion.WHITE_DODGE_CHANCE_CAP[bossOpts.Level - 85];
                chanceDodged = baseDodged - StatConversion.GetDodgeParryReducFromExpertise(effectiveExpertise);
                chanceDodged = Math.Min(Math.Max(chanceDodged, 0f), baseDodged);
            }
            #endregion

            #region Parry
            {
                float baseParried = StatConversion.WHITE_PARRY_CHANCE_CAP[bossOpts.Level - 85];
                chanceParried = baseParried - StatConversion.GetDodgeParryReducFromExpertise(effectiveExpertise);
                chanceParried = Math.Min(Math.Max(chanceParried, 0f), baseParried);
            }
            #endregion

            #region Miss
            {
                float baseMissed = StatConversion.WHITE_MISS_CHANCE_CAP[bossOpts.Level - 85];
                if (!twohander)
                    baseMissed = StatConversion.WHITE_MISS_CHANCE_CAP_DW[bossOpts.Level - 85];
                chanceMissed = baseMissed - stats.PhysicalHit;
                chanceMissed = Math.Min(Math.Max(chanceMissed, 0f), baseMissed);
            }
            #endregion

#if DEBUG
            if (chanceDodged < 0
                || chanceParried < 0
                || chanceMissed < 0)
                throw new Exception("Chance to hit out of range.");
#endif
            #region White Damage
            {
                // White damage per hit.  Basic white hits are use elsewhere.
                float baseDPS = baseDamage / baseSpeed;
                damage = (baseDPS + (stats.AttackPower / 14.0f)) * baseSpeed;
                DPS = damage / hastedSpeed;
                if (hand == CharacterSlot.OffHand)
                {
                    damage /= 2;
                    DPS /= 2;
                    if (talents.NervesOfColdSteel > 0)
                    {
                        damage *= 1f + (.25f * (talents.NervesOfColdSteel / 3f));
                        DPS *= 1f + (.25f * (talents.NervesOfColdSteel / 3f)); ;
                    }
                }
            }
            #endregion
        }
Example #12
0
        TalentsBase parse_talents_wowhead(CharacterClass characterclass, string talent_string)
        {
            // wowhead format: [tree_1]Z[tree_2]Z[tree_3] where the trees are character encodings
            // each character expands to a pair of numbers [0-5][0-5]
            // unused deeper talents are simply left blank instead of filling up the string with zero-zero encodings

            bool hasGlyphs = talent_string.Contains(":");

            int[] talent_trees = new int[] { 0, 0, 0 };
            int[] glyph_trees = new int[] { 3, 3, 3 };

            switch (characterclass)
            {
                case CharacterClass.Warrior:     { WarriorTalents talents = new WarriorTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Paladin:     { PaladinTalents talents = new PaladinTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Hunter:      { HunterTalents talents = new HunterTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Rogue:       { RogueTalents talents = new RogueTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Priest:      { PriestTalents talents = new PriestTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.DeathKnight: { DeathKnightTalents talents = new DeathKnightTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Shaman:      { ShamanTalents talents = new ShamanTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Mage:        { MageTalents talents = new MageTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Warlock:     { WarlockTalents talents = new WarlockTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Druid:       { DruidTalents talents = new DruidTalents(); talent_trees = talents.TreeLengths; break; }
            }

            int[] encoding = new int[talent_trees[0] + talent_trees[1] + talent_trees[2]];
            int[][] glyphEncoding = new int[][] {
                new int[3],
                new int[3],
                new int[3],
            };
            int[] tree_count = new int[] { 0, 0, 0 };
            int[] glyph_count = new int[] { 0, 0, 0 };

            int tree = 0;
            int count = 0;

            #region Talents parsing
            for (int i=1; i < talent_string.Length; i++) {
                if (tree >= 3) {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                    return null;
                }

                char c = talent_string[i];

                if (c == ':') break; // glyph encoding follows
 
                if (c == 'Z') {
                    count = 0;
                    for (int j = 0; j <= tree; j++) {
                        count += talent_trees[tree];
                    }
                    tree++;
                    continue;
                }

                decode_t decode = null;
                for (int j=0; decoding[j].key != '\0' && decode==null; j++) {
                    if (decoding[j].key == c) { decode = decoding[j]; }
                }

                if (decode == null) {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                    return null;
                }

                encoding[count++] += decode.first - '0';
                tree_count[tree] += 1;

                if (tree_count[tree] < talent_trees[tree]) {
                    encoding[count++] += decode.second - '0';
                    tree_count[tree] += 1;
                }

                if (tree_count[tree] >= talent_trees[tree]) {
                    tree++;
                }
            }
            #endregion

            #region Glyphs Parsing
            #region Notes
            /* This is totally crappy....
             * Glyphs do not follow the same parsing rules. If you apply what was there for talents directly
             * to glyphs you get 1202032213120011050000000000000000. Which should only have 1's and 0's
             * 
             * 
             * Warriors: As I'm checking glyphs, here's what I get:
             * == PRIMES ==
             *   Link                           decode  id       Name
            * * http://www.wowhead.com/talent#L:0 00 43415 58388 Devastate
            * * http://www.wowhead.com/talent#L:z 01 43416 58367 Bloodthirst
            * * http://www.wowhead.com/talent#L:M 02 43421 58368 Mortal Strike
            * * http://www.wowhead.com/talent#L:c 03 43422 58386 Overpower
            * * http://www.wowhead.com/talent#L:m 04 43423 58385 Slam
            * * http://www.wowhead.com/talent#L:V 05 43424 58364 Revenge
            * * http://www.wowhead.com/talent#L:o 10 43425 58375 Shield Slam
            * * http://www.wowhead.com/talent#L:k 11 43432 58370 Raging Blow
            * * http://www.wowhead.com/talent#L:R 12 45790 63324 Bladestorm
             * == MAJORS ==
             * * http://www.wowhead.com/talent#L:0 00 43397 Long Charge
             * * http://www.wowhead.com/talent#L:z 01 43399 Thunder Clap
             * * http://www.wowhead.com/talent#L:M 02 43413 Rapid Charge
             * * http://www.wowhead.com/talent#L:c 03 43414 Cleaving
             * * http://www.wowhead.com/talent#L:m 04 43417 Piercing Howl
             * * http://www.wowhead.com/talent#L:V 05 43418 Heroic Throw
             * * http://www.wowhead.com/talent#L:o 10 43419 Intervene
             * * http://www.wowhead.com/talent#L:k 11 43427 Sunder Armor
             * * http://www.wowhead.com/talent#L:R 12 43428 Sweeping Strikes
             * * http://www.wowhead.com/talent#L:s 13 43430 Resonating Power
             * * http://www.wowhead.com/talent#L:a 14 43431 Victory Rush
             * * http://www.wowhead.com/talent#L:q 15 45792 Shockwave
             * * http://www.wowhead.com/talent#L:b 20 45795 Spell Reflection
             * * http://www.wowhead.com/talent#L:d 21 45797 Shield Wall
             * * http://www.wowhead.com/talent#L:r 22 63481 Colossus Smash
             * * http://www.wowhead.com/talent#L:f 23 67482 Intercept
             * * http://www.wowhead.com/talent#L:w 24 67483 Death Wish
             * == MINORS ==
             * * http://www.wowhead.com/talent#L:0 00 43395 Battle
             * * http://www.wowhead.com/talent#L:z 01 43396 Berserker Rage
             * * http://www.wowhead.com/talent#L:M 02 43398 Demoralizing Shout
             * * http://www.wowhead.com/talent#L:c 03 43400 Enduring Victory
             * * http://www.wowhead.com/talent#L:m 04 43412 Bloody Healing
             * * http://www.wowhead.com/talent#L:V 05 45793 Furious Sundering
             * * http://www.wowhead.com/talent#L:o 10 45794 Intimidating Shout
             * * http://www.wowhead.com/talent#L:k 11 49084 Command
             * 
             * So http://www.wowhead.com/talent#LubcfRMRurkcrZ0b:RMcrsR0kV would mean:
             *   Prime: Bladestorm, Mortal Strike, Overpower
             *   Major: Colossus Smash, Resonating Power, Sweeping Strikes
             *   Minor: Battle, Command, Furious Sundering
             * Which is correct, that's what we come out to
             */
            #endregion

            tree = 0;
            count = 0;

            if (hasGlyphs) {
                for (int i=talent_string.IndexOf(":")+1; i < talent_string.Length; i++) {
                    if (tree >= 3) {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                        return null;
                    }

                    char c = talent_string[i];

                    if (c == 'Z') {
                        count = 0;
                        /*for (int j = 0; j <= tree; j++) {
                            count += glyph_trees[tree];
                        }*/
                        tree++;
                        continue;
                    }

                    decode_t decode = null;
                    for (int j=0; decoding[j].key != '\0' && decode==null; j++) {
                        if (decoding[j].key == c) { decode = decoding[j]; }
                    }

                    if (decode == null) {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                        return null;
                    }

                    glyphEncoding[tree][count++] += (decode.first - '0') * 10 + decode.second - '0';
                    glyph_count[tree] += 1;

                    if (glyph_count[tree] >= (glyph_trees[tree])) { tree++; count = 0; }
                }
            }
            #endregion

            string newtalentstring = "";
            foreach (int i in encoding) { newtalentstring += i.ToString(); }
            if (hasGlyphs) {
                //newtalentstring += ".";
                //for (int t = 0; t < 3; t++) {
                //    foreach (int i in glyphEncoding[t]) { newtalentstring += i.ToString(); }
                //}
            }

            switch (characterclass)
            {
                case CharacterClass.Warrior: { return new WarriorTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Paladin: { return new PaladinTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Hunter: { return new HunterTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Rogue: { return new RogueTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Priest: { return new PriestTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.DeathKnight: { return new DeathKnightTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Shaman: { return new ShamanTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Mage: { return new MageTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Warlock: { return new WarlockTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Druid: { return new DruidTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
            }
            return null;
        }
Example #13
0
 public static Rotation.Type GetSpec(DeathKnightTalents t)
 {
     return (Rotation.Type)t.HighestTree + 1;
 }
Example #14
0
        public Gargoyle(StatsDK dkstats, DeathKnightTalents t, BossOptions bo, Presence p)
        {
            m_BO = bo;
            m_DKStats = dkstats;
            m_Talents = t;
            m_Presence = p;

            AccumulateStats();
            DamageType = ItemDamageType.Physical;
        }
Example #15
0
 public Obliterate(Character c, Stats s, CalculationOptionsDPSDK CalcOpts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = CalcOpts; combatTable = table; talents = Talents; GcdType = GCDType.Melee; Runes = RunesUsed.UnholyFrost; Name = "Obliterate";
 }
Example #16
0
        public FrostCycle(Character c, CombatTable t, Stats s, CalculationOptionsDPSDK opts, AbilityHandler a)
        {
            BP          = 0;
            FF          = 0;
            currentTime = 0;
            GCDTime     = 0;
            occurence   = new Rotation();
            //occurence.presence = calcOpts.rotation.presence;
            occurence.setRotation(Rotation.Type.Custom);
            occurence.NumDisease        = 0f;
            occurence.DiseaseUptime     = 100f;
            occurence.DeathCoil         = 0f;
            occurence.IcyTouch          = 0f;
            occurence.PlagueStrike      = 0f;
            occurence.ScourgeStrike     = 0f;
            occurence.ManagedRP         = false;
            occurence.FrostStrike       = 0f;
            occurence.HowlingBlast      = 0f;
            occurence.Obliterate        = 0f;
            occurence.BloodStrike       = 0f;
            occurence.HeartStrike       = 0f;
            occurence.DancingRuneWeapon = 0f;
            occurence.Horn                = 0f;
            occurence.GargoyleDuration    = 30f;
            occurence.DeathStrike         = 0f;
            occurence.GhoulFrenzy         = 0f;
            occurence.Pestilence          = 0f;
            occurence.CurRotationDuration = 60f;
            KMApplicationProbability      = 0;

            RP          = 0;
            FrostRune1  = 0;
            FrostRune2  = 0;
            UnholyRune1 = 0;
            UnholyRune2 = 0;
            BloodRune1  = 0;
            BloodRune2  = 0;
            DeathRune1  = 100 * 60 * 1000 + 1;
            DeathRune2  = 100 * 60 * 1000 + 1;
            horn        = 0;
            abilities   = a;
            character   = c;
            combatTable = t;
            stats       = s;
            talents     = c.DeathKnightTalents;
            KMChance    = (1 / (60 / t.MH.baseSpeed)) * talents.KillingMachine * (1 - combatTable.totalMHMiss);
            calcOpts    = opts;
            if (opts.CurrentPresence == CalculationOptionsDPSDK.Presence.Unholy)
            {
                meleeGCD = 1000;
                spellGCD = 1000;
            }
            else
            {
                meleeGCD = 1500;
                spellGCD = (int)(1500 / ((1 + (StatConversion.GetHasteFromRating(stats.HasteRating, CharacterClass.DeathKnight))) * (1d + stats.SpellHaste)));
                spellGCD = Math.Max(spellGCD, 1000);
            }

            PhysicalGCDMultiplier = (1 / (1 - (combatTable.dodgedSpecial + combatTable.missedSpecial)));
            SpellGCDMultiplier    = (1 / (1 - (combatTable.spellResist)));

            MHFrequency = (int)(combatTable.MH.hastedSpeed * 1000);
            RimeChance  = 0.05 * talents.Rime + (combatTable.DW ? (1 - talents.Rime * .05) * (talents.Rime * .05) : 0);
        }
Example #17
0
 public HeartStrike(Character c, Stats s, CalculationOptionsDPSDK CalcOpts, CombatTable table, DeathKnightTalents Talents)
 {
     character = c; stats = s; calcOpts = CalcOpts; combatTable = table; talents = Talents; GcdType = GCDType.Melee; Runes = RunesUsed.Blood; Name = "Heart Strike";
 }
Example #18
0
 public static bool HasTalent(DeathKnightTalents tal)
 {
     return TalentManager.IsSelected((int)tal);
 }
Example #19
0
        public static void AccumulatePresenceStats(StatsDK PresenceStats, Presence p, DeathKnightTalents t)
        {
            switch(p)
            {
                case Presence.Blood:
                {
                    if (t.ImprovedBloodPresence > 0)
                    {
                        PresenceStats.CritChanceReduction += 0.03f * t.ImprovedBloodPresence;
                        PresenceStats.BonusRuneRegeneration += .1f * t.ImprovedBloodPresence;
                    }
                    else if (t.ImprovedFrostPresence > 0)
                        PresenceStats.BonusRPMultiplier += .02f * t.ImprovedFrostPresence;
                    else if (t.ImprovedUnholyPresence == 1)
                        PresenceStats.MovementSpeed += .08f;
                    else if (t.ImprovedUnholyPresence == 2)
                        PresenceStats.MovementSpeed += .15f;
                    PresenceStats.BonusStaminaMultiplier += .08125f; 
                    if (Rawr.Properties.GeneralSettings.Default.PTRMode)
                        PresenceStats.BaseArmorMultiplier += 0.55f;
                    else
                        PresenceStats.BaseArmorMultiplier += 0.3f;

                    PresenceStats.DamageTakenReductionMultiplier = 1f - (1f - PresenceStats.DamageTakenReductionMultiplier) * (1f - 0.08f);
                    // Threat bonus.
                    PresenceStats.ThreatIncreaseMultiplier += 1f; 
                    break;
                }
                case Presence.Frost:
                {
                    if (t.ImprovedBloodPresence > 0)
                        PresenceStats.DamageTakenReductionMultiplier = 1f - (1f - PresenceStats.DamageTakenReductionMultiplier) * (1f - 0.02f * t.ImprovedBloodPresence);
                    else if (t.ImprovedUnholyPresence == 1)
                        PresenceStats.MovementSpeed += .08f;
                    else if (t.ImprovedUnholyPresence == 2)
                        PresenceStats.MovementSpeed += .15f;
                    PresenceStats.BonusDamageMultiplier += 0.1f;
                    PresenceStats.BonusRPMultiplier += 0.1f;  
                    PresenceStats.ThreatReductionMultiplier += .20f; // Wowhead has this as effect #3
                    break;
                }
                case Presence.Unholy:
                {
                    if (t.ImprovedBloodPresence > 0)
                        PresenceStats.DamageTakenReductionMultiplier = 1f - (1f - PresenceStats.DamageTakenReductionMultiplier) * (1f - 0.02f * t.ImprovedBloodPresence);
                    else if (t.ImprovedFrostPresence > 0)
                        PresenceStats.BonusRPMultiplier += .02f * t.ImprovedFrostPresence;
                    else if (t.ImprovedUnholyPresence > 0)
                        PresenceStats.PhysicalHaste = AddStatMultiplierStat(PresenceStats.PhysicalHaste, (.025f * t.ImprovedUnholyPresence));
                    PresenceStats.PhysicalHaste = AddStatMultiplierStat(PresenceStats.PhysicalHaste, .1f);
                    //PresenceStats.BonusRuneRegeneration += .1f;
                    PresenceStats.MovementSpeed += .15f;
                    PresenceStats.ThreatReductionMultiplier += .20f; // Wowhead has this as effect #3
                    break;
                }
            }
        }