示例#1
0
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null)
     {
         Character.CalculationOptions = new CalculationOptionsDPSDK();
     }
     calcOpts = Character.CalculationOptions as CalculationOptionsDPSDK;
     // Model Specific Code
     //
     // Bad Gear Hiding
     CalculationsDPSDK.HidingBadStuff_Def = calcOpts.HideBadItems_Def;
     CalculationsDPSDK.HidingBadStuff_Spl = calcOpts.HideBadItems_Spl;
     CalculationsDPSDK.HidingBadStuff_PvP = calcOpts.HideBadItems_PvP;
     ItemCache.OnItemsChanged();
     CalculationOptionsPanelDPSDK_PropertyChanged(null, null);
     _loadingCalculationOptions = false;
 }
示例#2
0
        public void DPSDK_Rotation()
        {
            Rawr.DPSDK.CharacterCalculationsDPSDK CalcDPSDK = new Rawr.DPSDK.CharacterCalculationsDPSDK();
            CalculationOptionsDPSDK calcOpts = new CalculationOptionsDPSDK();
            Rawr.DK.StatsDK TotalStats = new Rawr.DK.StatsDK();

            Rawr.DK.DKCombatTable ct = new Rawr.DK.DKCombatTable(m_char, TotalStats, CalcDPSDK, calcOpts, m_char.BossOptions);
            Rawr.DK.Rotation rot = new Rawr.DK.Rotation(ct, false);
            rot.PRE_OneEachRot();
            rot.ReportRotation();
            Assert.IsTrue(rot.m_DPS > 0, "rotation OneEach produces 0 DPS");
            rot.PRE_Frost();
            rot.ReportRotation();
            Assert.IsTrue(rot.m_DPS > 0, "rotation Frost produces 0 DPS");
            rot.PRE_Unholy();
            rot.ReportRotation();
            Assert.IsTrue(rot.m_DPS > 0, "rotation Unholy produces 0 DPS");
            rot.PRE_BloodDiseased();
            rot.ReportRotation();
            Assert.IsTrue(rot.m_DPS > 0, "rotation BloodDiseased produces 0 DPS");
            //rot.Solver();
            //rot.ReportRotation();
            //Assert.IsTrue(rot.m_DPS > 0, "rotation solver produces 0 DPS");
            
        }
示例#3
0
        public void DPSDK_DPSMisMatch()
        {
            Rawr.DPSDK.CalculationsDPSDK CalcDPSDK = new Rawr.DPSDK.CalculationsDPSDK();

            CalculationOptionsDPSDK calcOpts = new CalculationOptionsDPSDK();
            calcOpts.presence = Rawr.DK.Presence.Frost;
            m_char.CalculationOptions = calcOpts;
            CharacterCalculationsDPSDK calcs = CalcDPSDK.GetCharacterCalculations(m_char) as CharacterCalculationsDPSDK;
            calcs.GetCharacterDisplayCalculationValues();
            for (int i = 0; i < EnumHelper.GetCount(typeof(Rawr.DK.DKability)); i++)
            {
                Assert.IsTrue(calcs.dpsSub[i] <= calcs.damSub[i], string.Format("{0} Dam: {1} DPS: {2}",
                    ((Rawr.DK.DKability)i).ToString(), calcs.damSub[i], calcs.dpsSub[i]));
                Assert.IsTrue(calcs.tpsSub[i] <= calcs.threatSub[i], string.Format("{0} Threat: {1} TPS: {2}",
                    ((Rawr.DK.DKability)i).ToString(), calcs.threatSub[i], calcs.tpsSub[i]));
            }
        }
示例#4
0
        public Stats getSpecialEffects(CalculationOptionsDPSDK calcOpts, SpecialEffect effect)
        {
            Stats    statsAverage = new Stats();
            Rotation rotation     = calcOpts.rotation;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return(statsAverage);
        }
示例#5
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;
        }
示例#6
0
 public DKCombatTable(Character c, StatsDK stats, CharacterCalculationsBase calcs, ICalculationOptionBase calcOpts, BossOptions bossOpts)
 {
     m_CState = new CombatState();
     if (c != null) {
         m_CState.m_Char = c;
         m_CState.m_Talents = c.DeathKnightTalents;
         m_CState.m_Spec = CalculationsDPSDK.GetSpec(c.DeathKnightTalents);
     }
     m_CState.m_Stats = stats;
     // TODO: Put in check here for null.
     m_Calcs = calcs as CharacterCalculationsDPSDK;
     m_Opts = calcOpts as CalculationOptionsDPSDK;
     m_CState.m_Presence = Presence.Frost;
     if (calcOpts != null && m_Opts == null) {
         //throw new Exception("Opts not converted properly.");
         m_Opts = new CalculationOptionsDPSDK();
     }
     try { m_CState.m_Presence = m_Opts.presence; } catch { } // pass  stay w/ default
     m_BO = bossOpts;
     if (m_BO == null) { m_BO = new BossOptions(); }
     // JOTHAY TODO: Kind of an Ugly Hack to do this, but it will give them a value
     m_CState.m_NumberOfTargets = m_BO.MultiTargs ? m_BO.DynamicCompiler_MultiTargs.GetAverageTargetGroupSize(m_BO.BerserkTimer) : 1f;
     //
     m_CState.m_bAttackingFromBehind = m_BO.InBack;
     m_CState.fBossArmor = m_BO.Armor;
     SetupExpertise(c);
 }
示例#7
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";
 }
示例#8
0
        private void AccumulateSpecialEffectStats(StatsDK s, Character c, CalculationOptionsDPSDK calcOpts, DKCombatTable t, Rotation rot)
        {
            StatsSpecialEffects se = new StatsSpecialEffects(t, rot, c.BossOptions );
            StatsDK statSE = new StatsDK();

            foreach (SpecialEffect effect in s.SpecialEffects())
            {
                if (HasRelevantStats(effect.Stats))
                {
                    statSE = se.getSpecialEffects(effect);
                    s.Accumulate(statSE);
                }
            }
        }
示例#9
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";
 }
示例#10
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";
 }
示例#11
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";
 }
示例#12
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";
 }
示例#13
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
        }
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null) Character.CalculationOptions = new CalculationOptionsDPSDK();
     calcOpts = Character.CalculationOptions as CalculationOptionsDPSDK;
     // Model Specific Code
     //
     // Bad Gear Hiding
     CalculationsDPSDK.HidingBadStuff_Def = calcOpts.HideBadItems_Def;
     CalculationsDPSDK.HidingBadStuff_Spl = calcOpts.HideBadItems_Spl;
     CalculationsDPSDK.HidingBadStuff_PvP = calcOpts.HideBadItems_PvP;
     ItemCache.OnItemsChanged();
     CalculationOptionsPanelDPSDK_PropertyChanged(null, null);
     _loadingCalculationOptions = false;
 }
示例#15
0
        public void DPSDK_TrinketHang()
        {
            Stats StatTrink = new Stats();
            StatTrink.AddSpecialEffect(new SpecialEffect(Trigger.MainHandHit, new Stats() { Strength = 300 }, 10, 0, .1f, 5));
            StatTrink.MasteryRating = 500;
            Item Trinket = new Item("testTrink", ItemQuality.Epic, ItemType.None, 10102, "icon.bmp", ItemSlot.Trinket, "", false,
                StatTrink, StatTrink, ItemSlot.None, ItemSlot.None, ItemSlot.None, 0, 0, ItemDamageType.Physical, 0, "");
            m_char.Trinket1 = new ItemInstance(Trinket, 0, null, null, null, new Enchant(), new Reforging(), new Tinkering());

            // This bug was due to non-valid swing times.
            m_char.MainHand = null;

            Rawr.DPSDK.CalculationsDPSDK CalcDPSDK = new Rawr.DPSDK.CalculationsDPSDK();

            CalculationOptionsDPSDK calcOpts = new CalculationOptionsDPSDK();
            calcOpts.presence = Rawr.DK.Presence.Frost;
            m_char.CalculationOptions = calcOpts;
            this.testContextInstance.BeginTimer("GetCalc");
            CharacterCalculationsBase calcs = CalcDPSDK.GetCharacterCalculations(m_char);
            calcs.GetCharacterDisplayCalculationValues();
            this.testContextInstance.EndTimer("GetCalc");
        }
示例#16
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";
 }
示例#17
0
        public void DPSDK_BuildAcceptance()
        {
            Rawr.DPSDK.CalculationsDPSDK CalcDPSDK = new Rawr.DPSDK.CalculationsDPSDK();

            CalculationOptionsDPSDK calcOpts = new CalculationOptionsDPSDK();
            calcOpts.presence = Rawr.DK.Presence.Frost;
            m_char.CalculationOptions = calcOpts;
            this.testContextInstance.BeginTimer("GetCalc");
            CharacterCalculationsBase calcs = CalcDPSDK.GetCharacterCalculations(m_char);
            calcs.GetCharacterDisplayCalculationValues();
            this.testContextInstance.EndTimer("GetCalc");
        }
示例#18
0
        /// <summary>
        /// GetCharacterStats is the 2nd-most calculation intensive method in a model. Here the model will
        /// combine all of the information about the character, including race, gear, enchants, buffs,
        /// calculationoptions, etc., to form a single combined Stats object. Three of the methods below
        /// can be called from this method to help total up stats: GetItemStats(character, additionalItem),
        /// GetEnchantsStats(character), and GetBuffsStats(character.ActiveBuffs).
        /// </summary>
        /// <param name="character">The character whose stats should be totaled.</param>
        /// <param name="additionalItem">An additional item to treat the character as wearing.
        /// This is used for gems, which don't have a slot on the character to fit in, so are just
        /// added onto the character, in order to get gem calculations.</param>
        /// <returns>A Stats object containing the final totaled values of all character stats.</returns>
        public override Stats GetCharacterStats(Character character, Item additionalItem) 
        {
            StatsDK statsTotal = new StatsDK();
            if (null == character)
            {
#if DEBUG
                throw new Exception("Character is Null");
#else
                return statsTotal;
#endif
            }
            CalculationOptionsDPSDK calcOpts = character.CalculationOptions as CalculationOptionsDPSDK;
            if (null == calcOpts) { calcOpts = new CalculationOptionsDPSDK(); }
            DeathKnightTalents talents = character.DeathKnightTalents;
            if (null == talents) { return statsTotal; }

            statsTotal.Accumulate(GetRaceStats(character));
            AccumulateItemStats(statsTotal, character, additionalItem);
            statsTotal = GetRelevantStats(statsTotal) as StatsDK; // GetRel removes any stats specific to the StatsDK object.

            statsTotal.bDW = false;
            if (character.MainHand != null && character.OffHand != null) statsTotal.bDW = true;
            RemoveDuplicateRunes(statsTotal, character, statsTotal.bDW);
            AccumulateBuffsStats(statsTotal, character.ActiveBuffs);

            #region Tank
            #region T11
            int tierCount;
            if (character.SetBonusCount.TryGetValue("Magma Plated Battlearmor", out tierCount))
            {
                if (tierCount >= 2) { statsTotal.b2T11_Tank = true; }
                if (tierCount >= 4) { statsTotal.b4T11_Tank = true; }
            }
            if (statsTotal.b4T11_Tank)
                statsTotal.AddSpecialEffect(_SE_IBF[1]);
            else
                statsTotal.AddSpecialEffect(_SE_IBF[0]);
            #endregion
            #region T12
            if (character.SetBonusCount.TryGetValue("Elementium Deathplate Battlearmor", out tierCount))
            {
                if (tierCount >= 2) { statsTotal.b2T12_Tank = true; }
                if (tierCount >= 4) { statsTotal.b4T12_Tank = true; }
            }
            if (statsTotal.b2T12_Tank)
            {
                // Your melee attacks cause Burning Blood on your target, 
                // which deals 800 Fire damage every 2 for 6 sec and 
                // causes your abilities to behave as if you had 2 diseases 
                // present on the target.

                // Implemented in CombatState DiseaseCount
                statsTotal.FireDamage = 800 / 2;
            }
            if (statsTotal.b4T12_Tank)
            {
                // Your Dancing Rune Weapon grants 15% additional parry chance.
                // Implemented in DRW talent Static Special Effect.
            }
            #endregion
            #region T13
            if (character.SetBonusCount.TryGetValue("Necrotic Boneplate Armor", out tierCount))
            {
                if (tierCount >= 2) { statsTotal.b2T13_Tank = true; }
                if (tierCount >= 4) { statsTotal.b4T13_Tank = true; }
            }
            if (statsTotal.b2T13_Tank)
            {
                // When an attack drops your health below 35%, one of your Blood Runes 
                // will immediately activate and convert into a Death Rune for the next 
                // 20 sec. This effect cannot occur more than once every 45 sec.
            }
            if (statsTotal.b4T13_Tank)
            {
                // Your Vampiric Blood ability also affects all party and raid members 
                // for 50% of the effect it has on you.
            }
            #endregion
            #endregion
            #region DPS
            #region T11
            if (character.SetBonusCount.TryGetValue("Magma Plated Battlegear", out tierCount))
            {
                if (tierCount >= 2)
                {
                    statsTotal.b2T11_DPS = true;
                    if (tierCount >= 4) { statsTotal.b4T11_DPS = true; }
                }
                if (statsTotal.b2T11_DPS)
                {
                    // increase the crit chance of your DeathCoil & FS by 5%
                    statsTotal.BonusCritChanceDeathCoil += .05f;
                    statsTotal.BonusCritChanceFrostStrike += .05f;
                }
                if (statsTotal.b4T11_DPS)
                {
                    // Each time you gain a Death Rune or trigger your Killing Machine talent, 
                    // you also gain 1% increased attack power for 30 sec. Stacks up to 3 times.
                    statsTotal.AddSpecialEffect(new SpecialEffect(Trigger.DeathRuneGained,
                        new Stats() { BonusAttackPowerMultiplier = 0.01f, },
                        30, 0, 1f, 3));
                    statsTotal.AddSpecialEffect(new SpecialEffect(Trigger.KillingMachine,
                        new Stats() { BonusAttackPowerMultiplier = 0.01f, },
                        30, 0, 1f, 3));
                }
            }
            #endregion
            #region T12
            if (character.SetBonusCount.TryGetValue("Elementium Deathplate Battlegear", out tierCount))
            {
                if (tierCount >= 2)
                {
                    statsTotal.b2T12_DPS = true;
                    if (tierCount >= 4)
                    {
                        
                        statsTotal.b4T12_DPS = true;
                    }
                }
            }
            if (statsTotal.b2T12_DPS)
            {
                // Horn of Winter also grats 3 RPp5
                statsTotal.RPp5 += 3;
            }
            if (statsTotal.b4T12_DPS)
            {
                // Your Obliterate and Scourge Strike abilities instantly deal 6% additional damage as Fire damage.
                // Implemented in Oblit and SS classes.
            }
            #endregion
            #region T13
            if (character.SetBonusCount.TryGetValue("Necrotic Boneplate Battlegear", out tierCount))
            {
                if (tierCount >= 2) { statsTotal.b2T13_DPS = true; }
                if (tierCount >= 4) { statsTotal.b4T13_DPS = true; }
            }
            if (statsTotal.b2T13_DPS)
            {
                // Sudden Doom has a 30% chance and Rime has a 60% chance 
                // to grant 2 charges when triggered instead of 1.
            }
            if (statsTotal.b4T13_DPS)
            {
                // Runic Empowerment has a 25% chance and Runic Corruption 
                // has a 40% chance to also grant 710 mastery rating for 12 sec when activated.
            }
            #endregion
            #endregion

            AccumulateTalents(statsTotal, character);
            AccumulatePresenceStats(statsTotal, calcOpts.presence, talents);

            return (statsTotal);
        }