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; }
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"); }
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])); } }
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); }
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; }
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); }
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"; }
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); } } }
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"; }
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"; }
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"; }
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"; }
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; }
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"); }
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"; }
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"); }
/// <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); }