/// <summary> /// This a basic rotation /// </summary> public void PRE_Unholy_dynamic() // Expensive { /* if (_RotCacheType == Type.Unholy && _RotCache.Count > 100 && Math.Abs(_cachedHaste - m_CT.m_CState.m_Stats.PhysicalHaste) <= 0.05f ) // Haste is within 5% of the cached Haste. { ml_Rot = _RotCache; foreach (AbilityDK_Base ab in ml_Rot) { ab.UpdateCombatState(m_CT.m_CState); } BuildCosts(); return; } * */ // Because, really, Unholy should be in Unholy Presence. // m_CT.m_Opts.presence = Presence.Unholy; m_szRotationName = "Unholy Rotation"; ResetRotation(); // Setup an instance of each ability. // No runes: AbilityDK_Outbreak Outbreak = new AbilityDK_Outbreak(m_CT.m_CState); // Single Runes: // AbilityDK_IcyTouch IT = new AbilityDK_IcyTouch(m_CT.m_CState); AbilityDK_FrostFever FF = new AbilityDK_FrostFever(m_CT.m_CState); // AbilityDK_PlagueStrike PS = new AbilityDK_PlagueStrike(m_CT.m_CState); AbilityDK_BloodPlague BP = new AbilityDK_BloodPlague(m_CT.m_CState); // AbilityDK_BloodStrike BS = new AbilityDK_BloodStrike(m_CT.m_CState); // AbilityDK_HeartStrike HS = new AbilityDK_HeartStrike(m_CT.m_CState); // AbilityDK_NecroticStrike NS = new AbilityDK_NecroticStrike(m_CT.m_CState); // AbilityDK_Pestilence Pest = new AbilityDK_Pestilence(m_CT.m_CState); // AbilityDK_BloodBoil BB = new AbilityDK_BloodBoil(m_CT.m_CState); // AbilityDK_HowlingBlast HB = new AbilityDK_HowlingBlast(m_CT.m_CState); // AbilityDK_ScourgeStrike SS = new AbilityDK_ScourgeStrike(m_CT.m_CState); // AbilityDK_DeathNDecay DnD = new AbilityDK_DeathNDecay(m_CT.m_CState); // Multi Runes: // AbilityDK_DeathStrike DS = new AbilityDK_DeathStrike(m_CT.m_CState); AbilityDK_FesteringStrike Fest = new AbilityDK_FesteringStrike(m_CT.m_CState); // AbilityDK_Obliterate OB = new AbilityDK_Obliterate(m_CT.m_CState); // RP: Unlikely to start w/ RP abilities to open. // AbilityDK_RuneStrike RS = new AbilityDK_RuneStrike(m_CT.m_CState); // each RS gives a 45% chance to renew a fully depleted runes. // thus 20 RSs gets us 9 extra runes. // Same is true for DC & FS AbilityDK_DeathCoil DC = new AbilityDK_DeathCoil(m_CT.m_CState); AbilityDK_UnholyBlight UB = null; if (DC.ml_TriggeredAbility.Length > 0) UB = DC.ml_TriggeredAbility[0] as AbilityDK_UnholyBlight; // AbilityDK_FrostStrike FS = new AbilityDK_FrostStrike(m_CT.m_CState); DarkTranformation Dark = new DarkTranformation(m_CT.m_CState); // Simple ITx1, PSx1, BSx1, SSx4 & Festx4. // Initial rotation build. int[] AvailableResources = new int[EnumHelper.GetCount(typeof(DKCostTypes))]; AvailableResources[(int)DKCostTypes.Blood] = 2; AvailableResources[(int)DKCostTypes.Frost] = 2; AvailableResources[(int)DKCostTypes.UnHoly] = 2; if (m_CT.m_CState.m_Talents.DarkTransformation > 0) { // this won't be there if they're not spec'd for it. ml_Rot.Add(Dark); // Dark Transformation. ProcessRunningRunes(AvailableResources, Dark.AbilityCost); } uint subrotDuration = 0; uint GCDdur = MIN_GCD_MS; // Fill the 3 mins duration if (m_CT.m_Opts.presence == Presence.Unholy) GCDdur = MIN_GCD_MS_UH; subrotDuration = Outbreak.Cooldown; uint diseaseGCDs = 0; for (int count = (int)(Dark.Cooldown / subrotDuration); count > 0; count--) { if (m_CT.m_CState.m_Stats.RPp5 > 0) AvailableResources[(int)DKCostTypes.RunicPower] += (int)((subrotDuration / 5000) * m_CT.m_CState.m_Stats.RPp5); // TODO: This still assumes that we're filling every GCD w/ an ability. // We know that's not the case in most situations. ml_Rot.Add(Outbreak); // 60 sec CD. ProcessRunningRunes(AvailableResources, Outbreak.AbilityCost); ml_Rot.Add(FF); ml_Rot.Add(BP); // 1 GCDs // Fill the disease. diseaseGCDs = Outbreak.Cooldown / GCDdur; float MaxRP = 100 + m_CT.m_CState.m_Stats.BonusMaxRunicPower; List<AbilityDK_Base> l_Abilities; for (; diseaseGCDs > 0; ) { bool bEnoughRP = (-1 * AvailableResources[(int)DKCostTypes.RunicPower]) > DC.RunicPower; bool bOverCapRP = (AvailableResources[(int)DKCostTypes.RunicPower] + Fest.RunicPower) > MaxRP; if ( (!bEnoughRP && !bOverCapRP) ) { l_Abilities = GetFilteredListOfAbilities(AvailableResources, m_CT.m_CState); if (l_Abilities.Count > 0) { foreach (AbilityDK_Base ab in l_Abilities) { ab.UpdateCombatState(m_CT.m_CState); } l_Abilities.Sort(AbilityDK_Base.CompareDPSByRunes); if (l_Abilities[0].AbilityIndex == (int)DKability.BloodStrike || l_Abilities[0].AbilityIndex == (int)DKability.IcyTouch) { l_Abilities[0] = GetAbilityOfType(l_Abilities, DKability.FesteringStrike); } ProcessRunningRunes(AvailableResources, l_Abilities[0].AbilityCost); ml_Rot.Add(l_Abilities[0]); } else { // If the list is 0, means all the runes have been used. // Reset runes AvailableResources[(int)DKCostTypes.Blood] = 2; AvailableResources[(int)DKCostTypes.Frost] = 2; AvailableResources[(int)DKCostTypes.UnHoly] = 2; } } else { ml_Rot.Add(DC); ProcessRunningRunes(AvailableResources, DC.AbilityCost); } diseaseGCDs--; } } // How much RP do we have left at this point? foreach (AbilityDK_Base ab in ml_Rot) m_RunicPower += ab.RunicPower; BuildCosts(); // subsequent: #region Unholy Blight if (UB != null) { uint mSecperDC = (uint)m_RotationDuration / Count(DKability.DeathCoil); uint UBCount = (uint)m_RotationDuration / Math.Max(UB.Cooldown, mSecperDC); for (; UBCount > 0; UBCount--) { ml_Rot.Add(UB); } } #endregion /* _cachedHaste = m_CT.m_CState.m_Stats.PhysicalHaste; _RotCacheType = Type.Unholy; _RotCache = ml_Rot; * */ }
/// <summary> /// This a basic preset rotation consuming the full CD of Dark Transformation. /// </summary> public void PRE_Unholy() { ResetRotation(); m_szRotationName = "Unholy Rotation"; // Because, really, Unholy should be in Unholy Presence. if (m_CT.m_Opts.presence != Presence.Unholy) { m_szRotationName += "\nYou should be in Unholy Presence."; } // Setup an instance of each ability. // No runes: AbilityDK_Outbreak Outbreak = new AbilityDK_Outbreak(m_CT.m_CState); // Single Runes: // AbilityDK_IcyTouch IT = new AbilityDK_IcyTouch(m_CT.m_CState); AbilityDK_FrostFever FF = new AbilityDK_FrostFever(m_CT.m_CState); // AbilityDK_PlagueStrike PS = new AbilityDK_PlagueStrike(m_CT.m_CState); AbilityDK_BloodPlague BP = new AbilityDK_BloodPlague(m_CT.m_CState); // AbilityDK_BloodStrike BS = new AbilityDK_BloodStrike(m_CT.m_CState); AbilityDK_ScourgeStrike SS = new AbilityDK_ScourgeStrike(m_CT.m_CState); AbilityDK_FesteringStrike Fest = new AbilityDK_FesteringStrike(m_CT.m_CState); AbilityDK_DeathCoil DC = new AbilityDK_DeathCoil(m_CT.m_CState); AbilityDK_UnholyBlight UB = null; if (DC.ml_TriggeredAbility != null && DC.ml_TriggeredAbility.Length > 0) UB = DC.ml_TriggeredAbility[0] as AbilityDK_UnholyBlight; DarkTranformation Dark = new DarkTranformation(m_CT.m_CState); AbilityDK_DeathNDecay DnD = new AbilityDK_DeathNDecay(m_CT.m_CState); // Simple outbreak, Festx2 SSx6 & Fill w/ DCs int[] AvailableResources = new int[EnumHelper.GetCount(typeof(DKCostTypes))]; if (m_CT.m_CState.m_Talents.DarkTransformation > 0) { // this won't be there if they're not spec'd for it. ml_Rot.Add(Dark); // Dark Transformation. ProcessRunningRunes(AvailableResources, Dark.AbilityCost); } uint subrotDuration = 0; uint GCDdur = MIN_GCD_MS; // Fill the 3 mins duration if (m_CT.m_Opts.presence == Presence.Unholy) GCDdur = MIN_GCD_MS_UH; subrotDuration = Outbreak.Cooldown; uint diseaseGCDs = Outbreak.Cooldown / GCDdur; for (int count = (int)(Dark.Cooldown / subrotDuration); count > 0; count--) { if (m_CT.m_CState.m_Stats.RPp5 > 0) AvailableResources[(int)DKCostTypes.RunicPower] += (int)((subrotDuration / 5000) * m_CT.m_CState.m_Stats.RPp5); // TODO: This still assumes that we're filling every GCD w/ an ability. // We know that's not the case in most situations. ml_Rot.Add(Outbreak); // 60 sec CD. ProcessRunningRunes(AvailableResources, Outbreak.AbilityCost); ml_Rot.Add(FF); ml_Rot.Add(BP); // 1 GCDs // Fill the disease. for (uint i = 3; i > 0; i--) { if (i == 3) { ml_Rot.Add(DnD); diseaseGCDs--; AvailableResources[(int)DKCostTypes.RunicPower] += DnD.RunicPower; } else { ml_Rot.Add(SS); diseaseGCDs--; AvailableResources[(int)DKCostTypes.RunicPower] += SS.RunicPower; } ml_Rot.Add(SS); diseaseGCDs--; ml_Rot.Add(Fest); diseaseGCDs--; ml_Rot.Add(Fest); diseaseGCDs--; ml_Rot.Add(SS); diseaseGCDs--; ml_Rot.Add(SS); diseaseGCDs--; ml_Rot.Add(SS); diseaseGCDs--; ml_Rot.Add(SS); diseaseGCDs--; AvailableResources[(int)DKCostTypes.RunicPower] += SS.RunicPower * 5; AvailableResources[(int)DKCostTypes.RunicPower] += Fest.RunicPower * 2; } } m_RunicPower = -1 * AvailableResources[(int)DKCostTypes.RunicPower]; // Burn All of the RP we can. for (float RSCount = Math.Abs((float)m_RunicPower / (float)DC.RunicPower); RSCount > 0; RSCount--) { if (RSCount >= 1) { ml_Rot.Add(DC); m_RunicPower += DC.RunicPower; } else { AbilityDK_DeathCoil DCPartial = new AbilityDK_DeathCoil(m_CT.m_CState); DCPartial.fPartialValue = RSCount; DCPartial.bPartial = true; DCPartial.szName = "DC (partial)"; DCPartial.RunicPower = (int)((float)DC.RunicPower * DCPartial.fPartialValue); m_RunicPower += DCPartial.RunicPower; ml_Rot.Add(DCPartial); } } BuildCosts(); #region Sudden Doom if (m_CT.m_CState.m_Talents.SuddenDoom > 0) { AbilityDK_Base ability; float fRimeMod = this.Count(DKability.White) * (.05f * (float)m_CT.m_CState.m_Talents.SuddenDoom); // 30% chance to proc 2 SDs rather than 1. if (m_CT.m_CState.m_Stats.b2T13_DPS) fRimeMod *= 1.3f; if (fRimeMod > 1) { for (; fRimeMod > 1; fRimeMod--) { ability = new AbilityDK_DeathCoil(m_CT.m_CState); ability.szName = "DC (SuddenDoom)"; // These are free DCs. ability.AbilityCost[(int)DKCostTypes.Blood] = 0; ability.AbilityCost[(int)DKCostTypes.Frost] = 0; ability.AbilityCost[(int)DKCostTypes.UnHoly] = 0; ability.AbilityCost[(int)DKCostTypes.Death] = 0; ability.AbilityCost[(int)DKCostTypes.RunicPower] = 0; ml_Rot.Add(ability); } } if (fRimeMod > 0 && fRimeMod < 1) { // we want 1 full use, and then any sub values. ability = new AbilityDK_DeathCoil(m_CT.m_CState); ability.szName = "DC (SD_Partial)"; ability.bPartial = true; ability.fPartialValue = fRimeMod; // These are free DCs. ability.AbilityCost[(int)DKCostTypes.Blood] = 0; ability.AbilityCost[(int)DKCostTypes.Frost] = 0; ability.AbilityCost[(int)DKCostTypes.UnHoly] = 0; ability.AbilityCost[(int)DKCostTypes.Death] = 0; ability.AbilityCost[(int)DKCostTypes.RunicPower] = 0; ml_Rot.Add(ability); } } #endregion #region Unholy Blight if (UB != null) { uint mSecperDC = (uint)m_RotationDuration / Count(DKability.DeathCoil); uint UBCount = (uint)m_RotationDuration / Math.Max(UB.uDuration, mSecperDC); for (; UBCount > 0; UBCount--) { ml_Rot.Add(UB); } } #endregion BuildCosts(); }