/// <inheritdoc/> override public void Combat() { if (Me.IsCasting && Me.CastingSpellID == (int)WarlockSpellIds.CATACLYSM) { return; } if (DoSharedRotation()) { return; } //Adds if (Adds.Count > 0) { if (CastOnTerrain( "Shadowfury", Target.Position, () => Adds.Count(x => x.DistanceSquaredTo(Target) <= 12 * 12) > 2 )) { return; } if (DoMultitargetRotation(Adds.Count + 1)) { return; } } // Single DPS if (DoDotting(Target)) { return; } if (CastPreventDouble( "Haunt", () => (!Target.HasAura("Haunt") || Me.GetPower(WoWPowerType.WarlockSoulShards) >= 4) && ( // TODO: Trinket Procc Target.HealthFraction <= 0.25f ||// the boss is reaching death Me.GetPower(WoWPowerType.WarlockSoulShards) > 3 ||// We capped it (sadly we don't get it when we reached half a shard) (and yes I know whis will get this equation to true as we check against >= 4 above!) Me.HasAura("Dark Soul: Misery") ) )) { return; } // TODO: MultiDPS with Haunt, maybe? // Okay.. now souldrain :D if (Cast("Drain Soul")) { return; } }
public void Write(AssetsWriter writer) { writer.WriteCString(Version); writer.Write(Platform); writer.Write(HasTypeTrees); writer.Write(Types.Count()); Types.ForEach(x => x.Write(writer)); writer.Write(ObjectInfos.Count()); ObjectInfos.ForEach(x => { writer.AlignTo(4); x.Write(writer); }); writer.Write(Adds.Count()); Adds.ForEach(x => x.Write(writer)); writer.Write(ExternalFiles.Count()); ExternalFiles.ForEach(x => x.Write(writer)); writer.WriteCString(""); }
/// <summary> /// Casts the given spell on the best target. /// If none is found it will always fallback to Target. /// </summary> /// <returns><c>true</c>, if spell on best target was cast, <c>false</c> otherwise.</returns> /// <param name="spellName">Spell name.</param> /// <param name="castWhen">onlyCastWhen condition for Cast()</param> /// <param name="bestTargetCondition">Condition to limit the UnitObjects for a bestTarget</param> /// <param name="preventTime">Milliseconds in which the spell won't be cast again</param> /// <param name="targetOverride">Spell will be cast on this target</param> public bool CastSpellOnBestAoETarget(string spellName, Func <UnitObject, bool> castWhen = null, Func <UnitObject, bool> bestTargetCondition = null, int preventTime = 0, UnitObject targetOverride = null) { if (castWhen == null) { castWhen = (_ => true); } if (bestTargetCondition == null) { bestTargetCondition = (_ => true); } var aoeRange = SpellAoERange(spellName); var bestTarget = targetOverride ?? Adds .Where(u => u.IsInCombatRangeAndLoS && u.DistanceSquared <= SpellMaxRangeSq(spellName) && bestTargetCondition(u)) .OrderByDescending(u => Adds.Count(o => Vector3.DistanceSquared(u.Position, o.Position) <= aoeRange)).FirstOrDefault() ?? Target; if (preventTime == 0) { return(SpellIsCastOnTerrain(spellName) ? CastOnTerrain( spellName, bestTarget.Position, () => castWhen(bestTarget) ) : Cast( spellName, bestTarget, () => castWhen(bestTarget) )); } return(SpellIsCastOnTerrain(spellName) ? CastOnTerrainPreventDouble( spellName, bestTarget.Position, () => castWhen(bestTarget), preventTime ) : CastPreventDouble( spellName, () => castWhen(bestTarget), bestTarget, preventTime )); }
public override void Combat() { // Bear Form!! if (HasAura("Bear Form")) { // Survival, off GCD Cast("Survival Instincts", () => Me.HealthFraction <= 0.2); Cast("Might of Ursoc", () => Me.HealthFraction <= 0.3); Cast("Frenzied Regeneration", () => Me.HealthFraction <= 0.5); Cast("Barkskin", () => Me.HealthFraction <= 0.6); Cast("Savage Defense", () => !HasAura("Savage Defense")); // Survival, on GCD if (CastSelf("Cenarion Ward")) { return; } // Interrupts Cast("Skull Bash", () => Target.IsCastingAndInterruptible()); // Debuffs if (Cast("Faerie Fire", () => !Target.HasAura("Weakened Armor"))) { return; } // 3+ Targets, all off GCD if (Adds.Count >= 3 && Adds.Count(x => x.DistanceSquared <= 8 * 8) >= 3) { Cast("Disorienting Roar"); Cast("Mass Entanglement"); Cast("Berserk"); } // 2+ Targets if (Adds.Count >= 2 && Adds.Count(x => x.DistanceSquared <= 8 * 8) >= 2) { if (Cast("Swipe")) { return; } if (Cast("Thrash")) { return; } } // 1+ Targets if (Cast("Maul", () => HasAura("Tooth and Claw") && HasAura("Savage Defense") && Me.GetPower(WoWPowerType.Rage) > 80 )) { return; } if (Cast("Mangle")) { return; } if (Cast("Lacerate", () => !Target.HasAura("Lacerate", false, 3))) { return; } if (Cast("Thrash", () => !Target.HasAura("Thrash"))) { return; } } else { if (CastSelf("Bear Form", () => !HasAura("Dash") && !Me.InCombat)) { return; } } }
/// <summary> /// Do all the basic stuff which is shared among all specialisations. /// </summary> /// <returns><c>true</c>, if there was an GCD after a cast, <c>false</c> otherwise.</returns> protected bool DoSharedRotation() { if (UseDarkSoul) { //no globalcd bool DarkSoulCondition = (Target.IsInCombatRangeAndLoS && Target.MaxHealth >= Me.MaxHealth && Target.IsElite() && !UseDarkSoulBossOnly) || IsBoss(Target); CastSelfPreventDouble( "Dark Soul: Instability", () => DarkSoulCondition, 20000 ); CastSelfPreventDouble( "Dark Soul: Knowledge", () => DarkSoulCondition, 20000 ); CastSelfPreventDouble( "Dark Soul: Misery", () => DarkSoulCondition, 20000 ); } Cast( "Command Demon", () => !HasSpell("Grimoire of Sacrifice") && (IsPetActive("Summon Felhunter") || SelectedPet == WarlockPet.Felhunter) && Target.IsCastingAndInterruptible() ); Cast( "Command Demon", () => !HasSpell("Grimoire of Sacrifice") && (IsPetActive("Summon Imp") || SelectedPet == WarlockPet.SoulImp) && Me.HealthFraction <= 0.75 ); Cast( "Command Demon", () => !HasSpell("Grimoire of Sacrifice") && (IsPetActive("Summon Voidwalker") || SelectedPet == WarlockPet.Voidwalker) && Me.HealthFraction < 0.5 ); Cast( "Command Demon", () => !HasSpell("Grimoire of Sacrifice") && HasFelguard() && Adds.Count(u => Vector3.DistanceSquared( Me.Pet.Position, u.Position ) <= 8 * 8) >= 2 ); Cast( "Axe Toss", () => !HasSpell("Grimoire of Sacrifice") && HasFelguard() && Target.IsCastingAndInterruptible() ); //Heal CastSelf("Unbound Will", () => !Me.CanParticipateInCombat); CastSelf("Dark Bargain", () => Me.HealthFraction < 0.5); CastSelf("Sacrificial Pact", () => Me.HealthFraction < 0.6); CastSelf("Unending Resolve", () => Me.HealthFraction <= 0.5); CastSelf("Dark Regeneration", () => Me.HealthFraction <= 0.6); if (Me.HasAlivePet) { UnitObject add = Adds.FirstOrDefault(x => x.Target == Me); if (add != null) { Me.PetAttack(add); } } if (Cast("Mortal Coil", () => Me.HealthFraction <= 0.5)) { return(true); } if (SummonPet()) { return(true); } // Disable DPS Pets if they are the "normal" one. if (!HasSpell("Demonic Servitude")) { if (CastOnTerrain( HasSpell("Grimoire of Supremacy") ? "Summon Abyssal" : "Summon Infernal", Target.Position, () => UseAdditionalDPSPet && (((Target.MaxHealth >= Me.MaxHealth && Target.IsElite() && !UseAdditionalDPSPetBossOnly) || IsBoss(Target)) && (Adds.Count >= 3)) ) || Cast( HasSpell("Grimoire of Supremacy") ? "Summon Terrorguard" : "Summon Doomguard", () => UseAdditionalDPSPet && ((Target.MaxHealth >= Me.MaxHealth && Target.IsElite() && !UseAdditionalDPSPetBossOnly) || IsBoss(Target)) )) { return(true); } } if (HasSpell("Grimoire: Imp")) { bool GrimoireCondition = UseAdditionalDPSPet && ((Target.MaxHealth >= Me.MaxHealth && Target.IsElite() && !UseAdditionalDPSPetBossOnly) || IsBoss(Target)); if (GrimoireCondition) { var GrimoirePet = SelectedGrimoirePet; if (GrimoirePet == WarlockGrimoirePet.CurrentMainPet) { switch (SelectedPet) { case WarlockPet.ManualSelect: case WarlockPet.AutoSelect: GrimoirePet = Target.IsCastingAndInterruptible() ? WarlockGrimoirePet.Felhunter : WarlockGrimoirePet.Doomguard; break; case WarlockPet.SoulImp: GrimoirePet = WarlockGrimoirePet.SoulImp; break; case WarlockPet.Voidwalker: GrimoirePet = WarlockGrimoirePet.Voidwalker; break; case WarlockPet.Succubus: GrimoirePet = WarlockGrimoirePet.Succubus; break; case WarlockPet.Felhunter: GrimoirePet = WarlockGrimoirePet.Felhunter; break; case WarlockPet.Doomguard: GrimoirePet = WarlockGrimoirePet.Doomguard; break; case WarlockPet.Infernal: GrimoirePet = WarlockGrimoirePet.Infernal; break; } } switch (GrimoirePet) { case WarlockGrimoirePet.SoulImp: if (Cast("Grimoire: Imp")) { return(true); } break; case WarlockGrimoirePet.Voidwalker: if (Cast("Grimoire: Voidwalker")) { return(true); } break; case WarlockGrimoirePet.Succubus: if (Cast("Grimoire: Succubus")) { return(true); } break; case WarlockGrimoirePet.Felhunter: if (Cast("Grimoire: Felhunter")) { return(true); } break; case WarlockGrimoirePet.Doomguard: if (Cast("Grimoire: Doomguard")) { return(true); } break; case WarlockGrimoirePet.Infernal: if (Cast("Grimoire: Infernal")) { return(true); } break; } } } if (CurrentBotName == "PvP" && CastFearIfFeasible()) { return(true); } if (CastShadowfuryIfFeasible()) { return(true); } if (DoHealingAndManaManagement()) { return(true); } return(HasGlobalCooldown()); }
/// <summary> /// Does the multitarget rotation. /// </summary> /// <returns><c>true</c>, if a spell was cast, <c>false</c> otherwise.</returns> /// <param name="mobsInFrontOfMe">Mobs in front of me.</param> bool DoMultitargetRotation(int mobsInFrontOfMe) { int burningEmbers = Me.GetPower(WoWPowerType.WarlockDestructionBurningEmbers); if (mobsInFrontOfMe >= 3) { CastSelf( "Mannoroth's Fury", () => HasSpell("Mannoroth's Fury") && !Me.HasAura("Mannoroth's Fury") ); } // Priority #1 if (CastSpellOnBestAoETarget( "Rain of Fire", u => !HasAura("Rain of Fire") && (HasAura("Mannoroth's Fury") || mobsInFrontOfMe >= 5) )) { return(true); } // Priority #2 if ( SpellCooldown("Havoc") <= 0.01 && burningEmbers >= 1 && mobsInFrontOfMe < 12) { // Dont waste Havoc apply it to one of the mid-enemies (high max health, low current health) var havocAdd = Me.Focus; if (!UseHavocOnFocus) { havocAdd = Adds .OrderByDescending(x => x.Health) .FirstOrDefault(x => x.HealthFraction <= HavocHealthPercentage / 100f && x.IsInLoS && x.DistanceSquared <= SpellMaxRangeSq("Havoc")) ?? Adds.FirstOrDefault(); } if (havocAdd != null && havocAdd.IsFriendly) { havocAdd = havocAdd.Target; } if (havocAdd != null && Cast("Havoc", havocAdd)) { return(true); } } // cast Chaosbolt or shadowburn on target as soon as possible and if feasible if (Adds.Count(x => x.HasAura("Havoc", true)) > 0 || burningEmbers >= 4) { var shadowBurnTarget = Adds .Where(x => x.HealthFraction <= 0.2 && !x.HasAura("Havoc") && x.IsInLoS && x.DistanceSquared <= SpellMaxRangeSq("Shadowburn")) .OrderBy(x => x.Health) .FirstOrDefault() ?? Target; if (Cast("Shadowburn", () => mobsInFrontOfMe < 12, shadowBurnTarget)) { return(true); } if (Cast("Chaos Bolt", () => mobsInFrontOfMe < 6)) { return(true); } } if (mobsInFrontOfMe >= 3) { // Apply Immolate to all adds through Cataclysm if (CastSpellOnBestAoETarget("Cataclysm")) { return(true); } } // Priority #3 var countAddsInRange = Adds.Count(x => x.DistanceSquaredTo(Target) <= SpellAoERange("Conflagrate")); if ((burningEmbers >= 2 && countAddsInRange > 2) || (burningEmbers >= 1 && countAddsInRange >= 8)) { // Ensure Fire and Brimstone! CastSelf("Fire and Brimstone", () => !HasAura("Fire and Brimstone")); if (CastSpellOnBestAoETarget("Conflagrate")) { return(true); } if (CastSpellOnBestAoETarget( "Immolate", y => !y.HasAura("Immolate") && y.HpLessThanOrElite(0.15) )) { return(true); } if (CastSpellOnBestAoETarget("Incinerate")) { return(true); } } return(false); }
public override void Combat() { CastSelf("Barkskin", () => Me.HealthFraction < 0.6); if (HasSpell("Cat Form") && HasAura("Cat Form")) { if (HasAura("Prowl")) { if (Cast("Savage Roar", () => !Me.HasAura("Savage Roar"))) { return; } if (Cast("Pounce", () => HasAura("Prowl"))) { return; } } else { if (!Target.IsInCombatRangeAndLoS) { if (Cast("Savage Roar", () => !Me.HasAura("Savage Roar"))) { return; } if (CastSelfPreventDouble("Prowl", () => !Me.InCombat && Target.CombatRange <= RotationInfo.DismountRange && !HasAura("Prowl"))) { return; } } Cast("Skull Bash", () => Target.IsCastingAndInterruptible()); if (CastSelf("Nature's Swiftness", () => Me.HealthFraction <= 0.5)) { CastSelf("Healing Touch"); return; } if (Cast("Healing Touch", () => HasAura("Predatory Swiftness"))) { return; } if (CastSelf("Rejuvenation", () => Me.HealthFraction <= 0.5 && !HasAura("Rejuvenation"))) { return; } if (Cast("Faerie Fire", () => !Target.HasAura("Faerie Fire") && !HasAura("Prowl"))) { return; } if (CastSelf("Tiger's Fury", () => !HasAura("Berserk"))) { CastSelf("Berserk", () => Me.HpLessThanOrElite(0.6)); } if (Cast("Typhoon", () => Target.IsInCombatRange && Me.HealthFraction < 0.5)) { return; } if (Cast("Savage Roar", () => Me.GetPower(WoWPowerType.Energy) >= 25 && !HasAura("Savage Roar") && (SpellCost("Savage Roar") == 0 || Me.ComboPoints >= 3))) { return; } if (Cast("Rip", () => Me.GetPower(WoWPowerType.Energy) >= 30 && !Target.HasAura("Rip", true) && Me.ComboPoints >= 3)) { return; } if (Cast("Ferocious Bite", () => Me.GetPower(WoWPowerType.Energy) >= 25 && Me.ComboPoints >= 3)) { return; } if (Cast("Thrash", () => HasAura("Omen of Clarity") && !Target.HasAura("Thrash", true))) { return; } if (Cast("Rake", () => Me.GetPower(WoWPowerType.Energy) >= 35 && !Target.HasAura("Rake", true) && rakeDelay.IsReady)) { return; } if (Adds.Count > 1 && Adds.Count(x => x.DistanceSquared < 8 * 8) > 1) { if (Cast("Swipe", () => Me.GetPower(WoWPowerType.Energy) >= 45 || HasAura("Omen of Clarity"))) { return; } if (Cast("Mangle", () => Me.GetPower(WoWPowerType.Energy) >= 45 || HasAura("Omen of Clarity"))) { return; } } else { //if (Cast("Shred", () => Me.GetPower(WoWPowerType.Energy) >= 40 && VectorTools.GetRotationDiff())) return; //if behind if (Cast("Mangle", () => Me.GetPower(WoWPowerType.Energy) >= 35 || HasAura("Omen of Clarity"))) { return; } } } } else { if (CastSelf("Rejuvenation", () => Me.HealthFraction <= 0.75 && !HasAura("Rejuvenation"))) { return; } //if (Cast("Moonfire", () => Target.HealthFraction <= 0.1 && !Target.IsElite())) return; if (CastSelf("Cat Form", () => Target.IsInCombatRangeAndLoS || Target.CombatRange <= 25)) { return; } } }