예제 #1
0
        private static Composite CreateArmsAoeCombat(SimpleIntDelegate aoeCount)
        {
            return(new PrioritySelector(
                       new Decorator(ret => Spell.UseAOE && aoeCount(ret) >= 3,
                                     new PrioritySelector(
                                         Spell.BuffSelf("Avatar", ret => WarriorSettings.AvatarOnCooldownAOE),
                                         Spell.Cast("Cleave"),
                                         Spell.Cast("Thunder Clap"),

                                         Spell.Cast("Bladestorm", ret => aoeCount(ret) >= 4),
                                         Spell.Cast("Shockwave", ret => Clusters.GetClusterCount(StyxWoW.Me, Unit.NearbyUnfriendlyUnits, ClusterType.Cone, 10f) >= 3),

                                         Spell.Cast("Whirlwind", ret => Me.CurrentTarget.SpellDistance() < Common.DistanceWindAndThunder(8)),
                                         Spell.Cast("Mortal Strike"),
                                         Spell.Cast("Colossus Smash", ret => !StyxWoW.Me.CurrentTarget.HasMyAura("Colossus Smash")),
                                         Spell.Cast("Overpower")
                                         )
                                     )
                       ));
        }
예제 #2
0
        private static Composite CreateArmsAoeCombat(SimpleIntDelegate aoeCount)
        {
            return(new PrioritySelector(
                       new Decorator(ret => aoeCount(ret) >= 3,
                                     new PrioritySelector(
                                         Spell.Cast("Thunder Clap"),

                                         Spell.Cast("Bladestorm", ret => aoeCount(ret) >= 4),
                                         Spell.Cast("Shockwave", ret => Clusters.GetClusterCount(StyxWoW.Me, Unit.NearbyUnfriendlyUnits, ClusterType.Cone, 10f) >= 3),
                                         Spell.Cast("Dragon Roar"),

                                         Spell.Cast("Whirlwind"),
                                         Spell.Cast("Mortal Strike"),
                                         Spell.Cast("Colossus Smash", ret => !StyxWoW.Me.CurrentTarget.HasMyAura("Colossus Smash")),
                                         Spell.Cast("Overpower")
                                         )
                                     ),

                       Spell.BuffSelf("Sweeping Strikes", ret => aoeCount(ret) == 2)
                       ));
        }
예제 #3
0
 private static Composite CreateArmsAoeCombat(SimpleIntDelegate aoeCount)
 {
     return(new PrioritySelector( //cleave
                new Decorator(
                    ret => Spell.UseAOE && aoeCount(ret) >= 2 && Common.HasTalent(WarriorTalents.SweepingStrikes),
                    new PrioritySelector(
                        Spell.Cast("Mortal Strike"),
                        Spell.Cast("Execute", ret => Me.HasAura("Stone Heart")),
                        Spell.Cast("Colossus Smash", ret => !Me.HasAura("Shattered Defenses") && !Target.HasAura("Precise Strikes")),
                        Spell.Cast("Warbreaker", ret => !Me.HasAura("Shattered Defenses")),
                        Spell.Cast("Whirlwind", ret => Common.HasTalent(WarriorTalents.FervorOfBattle) && (DebuffColossusSmashUp || (Me.CurrentRage >= Me.MaxRage - 50)) && Me.HasAura("Cleave")),
                        Spell.Cast("Rend", ret => Target.GetAuraByName("Rend").TimeLeft() < Target.GetAuraByName("Rend").Duration * .3),
                        Spell.Cast("Bladestorm"),
                        Spell.Cast("Cleave"),
                        Spell.Cast("Whirlwind", ret => Me.CurrentRage >= 40 || Me.HasAura("Cleave")),
                        new ActionAlwaysFail()
                        )),
                new Decorator( //aoe
                    ret => Spell.UseAOE && aoeCount(ret) >= 5 && Common.HasTalent(WarriorTalents.SweepingStrikes),
                    new PrioritySelector(
                        Spell.Cast("Warbreaker", ret => Spell.GetSpellCooldown("Bladestorm").TotalSeconds < 1 && Spell.GetSpellCooldown("Battle Cry").TotalSeconds < 1),
                        Spell.Cast("Bladestorm", ret => Me.HasAura("Battle Cry") && (NumTier20Pieces >= 4 || StyxWoW.Me.Inventory.Equipped.Head.ItemInfo.Guid == 151823)),
                        Spell.Cast("Colossus Smash", ret => !Me.HasAura("In For The Kill") && Common.HasTalent(WarriorTalents.InForTheKill)),
                        Spell.Cast("Colossus Smash", ret => !DebuffColossusSmashUp && Unit.UnfriendlyUnits(8).Count() <= 10),
                        Spell.Cast("Cleave"),
                        Spell.Cast("Whirlwind", ret => Me.HasAura("Cleave")),
                        Spell.Cast("Whirlwind", ret => Unit.UnfriendlyUnits(8).Count() >= 7),
                        Spell.Cast("Colossus Smash", ret => !Me.HasAura("Shattered Defenses")),
                        Spell.Cast("Execute", ret => Me.HasAura("Stone Heart")),
                        Spell.Cast("Mortal Strike", ret => Me.HasAura("Shattered Defenses") || Target.GetAuraByName("Executioner's Precision").stackCount == 0),
                        Spell.Cast("Rend", ret => Target.GetAuraByName("Rend").TimeLeft() < Target.GetAuraByName("Rend").Duration * .3 && Unit.UnfriendlyUnits(8).Count() <= 3, RendCycleTarget),
                        Spell.Cast("Whirlwind")
                        )
                    )
                ));
 }
예제 #4
0
파일: Spell.cs 프로젝트: aash/Singular
        /// <summary>
        ///   Creates a behavior to cast a spell by ID, with special requirements, on a specific unit.
        ///   Returns RunStatus.Success if successful, RunStatus.Failure otherwise.
        /// </summary>
        /// <param name = "spellId">Identifier for the spell.</param>
        /// <param name = "onUnit">The on unit.</param>
        /// <param name = "requirements">The requirements.</param>
        /// <returns>.</returns>
        public static Composite Cast(SimpleIntDelegate spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements)
        {
            if (spellId == null || onUnit == null || requirements == null)
            {
                System.Diagnostics.Debug.Assert(spellId != null);
                System.Diagnostics.Debug.Assert(onUnit != null);
                System.Diagnostics.Debug.Assert(requirements != null);
                return new ActionAlwaysFail();
            }

            return new Throttle(
                new Action(ret =>
                {
                    int id = spellId(ret);

                    // exit now if spell search not needed
                    if (id == 0)
                        return RunStatus.Failure;

                    SpellFindResults sfr;
                    if (SpellManager.FindSpell(id, out sfr))
                    {
                        WoWUnit castOnUnit = onUnit(ret);
                        if (castOnUnit != null && requirements(ret))
                        {
                            if (Spell.CanCastHack(sfr, castOnUnit, skipWowCheck: true))
                            {
                                WoWSpell spell = sfr.Override ?? sfr.Original;
                                // LogCast(spell.Name, castOnUnit, spell.IsHealingSpell);
                                LogCast(spell.Name, castOnUnit, spell.IsHeal());
                                if (Spell.CastPrimative(spell, castOnUnit))
                                {
                                    return RunStatus.Success;
                                }
                            }
                        }
                    }

                    return RunStatus.Failure;
                })
            );
        }
예제 #5
0
파일: Spell.cs 프로젝트: aash/Singular
 /// <summary>
 ///   Creates a behavior to cast a buff by ID on yourself with special requirements. Returns RunStatus.Success if
 ///   successful, RunStatus.Failure otherwise.
 /// </summary>
 /// <remarks>
 ///   Created 5/6/2011.
 /// </remarks>
 /// <param name = "spellId">The buff ID.</param>
 /// <param name = "requirements">The requirements.</param>
 /// <returns>.</returns>
 public static Composite BuffSelf(SimpleIntDelegate spellId, SimpleBooleanDelegate requirements)
 {
     System.Diagnostics.Debug.Assert(requirements != null);
     return Buff(spellId, ret => StyxWoW.Me, requirements);
 }
예제 #6
0
파일: Spell.cs 프로젝트: aash/Singular
 /// <summary>
 ///   Creates a behavior to cast a buff by name, with special requirements, on a specific unit. Returns
 ///   RunStatus.Success if successful, RunStatus.Failure otherwise.
 /// </summary>
 /// <remarks>
 ///   Created 5/2/2011.
 /// </remarks>
 /// <param name = "spellId">The ID of the buff</param>
 /// <param name = "onUnit">The on unit</param>
 /// <param name = "requirements">The requirements.</param>
 /// <returns></returns>
 public static Composite Buff(SimpleIntDelegate spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements, HasGcd gcd = HasGcd.Yes)
 {
     return new Decorator(
         req => onUnit(req) != null && onUnit(req).Auras.Values.All(a => a.SpellId != spellId(req)),
         Cast(spellId, onUnit, requirements) 
         );
 }
예제 #7
0
파일: Spell.cs 프로젝트: aash/Singular
 public static Composite BuffSelf(SimpleIntDelegate idd, SimpleBooleanDelegate requirements, HasGcd gcd)
 {
     return Buff(idd, on => Me, requirements, gcd);
 }
예제 #8
0
파일: Common.cs 프로젝트: aash/Singular
        public static Composite CreateMonkCloseDistanceBehavior( SimpleIntDelegate minDist = null, UnitSelectionDelegate onUnit = null, SimpleBooleanDelegate canReq = null)
        {
            /*
            new Decorator(
                unit => (unit as WoWUnit).SpellDistance() > 10
                    && Me.IsSafelyFacing(unit as WoWUnit, 5f),
                Spell.Cast("Roll")
                )
            */

            bool hasFSKGlpyh = TalentManager.HasGlyph("Flying Serpent Kick");
            bool hasTigersLust = HasTalent(MonkTalents.TigersLust);

            if (minDist == null)
                minDist = min => Me.Combat ? 10 : 12;

            if (onUnit == null)
                onUnit = on => Me.CurrentTarget;

            if (canReq == null)
                canReq = req => true;

            return new Throttle( 1,
                new PrioritySelector(
                    ctx => onUnit(ctx),
                    new Decorator(
                        req => {
                            if (!MovementManager.IsClassMovementAllowed)
                                return false;

                            if (!canReq(req))
                                return false;

                            float dist = Me.SpellDistance(req as WoWUnit);
                            if ( dist <= minDist(req))
                                return false;

                            if ((req as WoWUnit).IsAboveTheGround())
                                return false;

                            float facingPrecision = (req as WoWUnit).SpellDistance() < 15 ? 6f : 4f;
                            if (!Me.IsSafelyFacing(req as WoWUnit, facingPrecision))
                                return false;

                            bool isObstructed = Movement.MeshTraceline(Me.Location, (req as WoWUnit).Location);
                            if (isObstructed == true)
                                return false;

                            return true;
                            },
                        new PrioritySelector(
                            Spell.BuffSelf(
                                "Tiger's Lust",
                                req => hasTigersLust
                                    && !Me.HasAuraWithEffect(WoWApplyAuraType.ModIncreaseSpeed)
                                    && Me.HasAuraWithEffect(WoWApplyAuraType.ModRoot, WoWApplyAuraType.ModDecreaseSpeed)
                                ),

                            new Sequence(
                                Spell.Cast(
                                    "Flying Serpent Kick",
                                    on => (WoWUnit) on,
                                    ret => TalentManager.CurrentSpec == WoWSpec.MonkWindwalker
                                        && !Me.Auras.ContainsKey("Flying Serpent Kick")
                                        && ((ret as WoWUnit).SpellDistance() > 25 || Spell.IsSpellOnCooldown("Roll"))
                                    ),
                                /* wait until in progress */
                                new PrioritySelector(
                                    new Wait(
                                        TimeSpan.FromMilliseconds(750),
                                        until => Me.Auras.ContainsKey("Flying Serpent Kick"),
                                        new Action( r => Logger.WriteDebug("CloseDistance: Flying Serpent Kick detected towards {0} @ {1:F1} yds in progress", (r as WoWUnit).SafeName(), (r as WoWUnit).SpellDistance()))
                                        ),
                                    new Action( r => {
                                        Logger.WriteDebug("CloseDistance: failure - did not see Flying Serpent Kick aura appear - lag?");
                                        return RunStatus.Failure;
                                        })
                                    ),

                                /* cancel when in range */
                                new Wait(
                                    TimeSpan.FromMilliseconds(2500),
                                    until => {
                                        if (!Me.Auras.ContainsKey("Flying Serpent Kick"))
                                        {
                                            Logger.WriteDebug("CloseDistance: Flying Serpent Kick completed on {0} @ {1:F1} yds and {2} behind me", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance(), (until as WoWUnit).IsBehind(Me) ? "IS" : "is NOT");
                                            return true;
                                        }

                                        if (!hasFSKGlpyh)
                                        {
                                            SpellFindResults sfr;
                                            SpellManager.FindSpell("Flying Serpent Kick", out sfr);

                                            if (((until as WoWUnit).IsWithinMeleeRange || (until as WoWUnit).SpellDistance() < 8f))
                                            {
                                                Logger.Write(LogColor.Cancel, "/cancel Flying Serpent Kick in melee range of {0} @ {1:F1} yds", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance());
                                                //Spell.CastPrimative("Flying Serprent Kick");
                                                // Lua.DoString("CastSpellByID(" + sfr.Original.Id + ")");
                                                return true;
                                            }
                                            else if ((until as WoWUnit).IsBehind(Me))
                                            {
                                                Logger.Write(LogColor.Cancel, "/cancel Flying Serpent Kick flew past {0} @ {1:F1} yds", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance());
                                                //Spell.CastPrimative("Flying Serprent Kick");
                                                //Lua.DoString("CastSpellByID(" + sfr.Original.Id + ")");
                                                return true;
                                            }
                                        }

                                        return false;
                                        },
                                    new PrioritySelector(
                                        new Decorator(
                                            req => !Me.Auras.ContainsKey("Flying Serpent Kick"),
                                            new ActionAlwaysSucceed()
                                            ),
                                        new Sequence(
                                            new Action( r => {
                                                if (hasFSKGlpyh)
                                                {
                                                    Logger.WriteDebug("CloseDistance: FSK is glyphed, should not be here - notify developer!");
                                                }
                                                else
                                                {
                                                    Logger.WriteDebug("CloseDistance: casting Flying Serpent Kick to cancel");
                                                    Spell.CastPrimative(101545);
                                                }
                                            }),
                                            /* wait until cancel takes effect */
                                            new PrioritySelector(
                                                new Wait(
                                                    TimeSpan.FromMilliseconds(450),
                                                    until => !Me.Auras.ContainsKey("Flying Serpent Kick"),
                                                    new Action( r => Logger.WriteDebug("CloseDistance: Flying Serpent Kick complete, landed {0:F1} yds from {1}", (r as WoWUnit).SpellDistance(), (r as WoWUnit).SafeName()))
                                                    ),
                                                new Action( r => {
                                                    Logger.WriteDebug("CloseDistance: error - Flying Serpent Kick was not removed - lag?");
                                                    })
                                                )
                                            )
                                        )
                                    )
                                ),

                            Spell.BuffSelf("Tiger's Lust", req => hasTigersLust ),

                            new Sequence(
                                Spell.Cast("Roll", on => (WoWUnit)on, req => !MonkSettings.DisableRoll && MovementManager.IsClassMovementAllowed),
                                new PrioritySelector(
                                    new Wait(
                                        TimeSpan.FromMilliseconds(500),
                                        until => Me.Auras.ContainsKey("Roll"),
                                        new Action(r => Logger.WriteDebug("CloseDistance: Roll in progress"))
                                        ),
                                    new Action( r => {
                                        Logger.WriteDebug("CloseDistance: failure - did not detect Roll in progress aura- lag?");
                                        return RunStatus.Failure;
                                        })
                                    ),
                                new Wait(
                                    TimeSpan.FromMilliseconds(950),
                                    until => !Me.Auras.ContainsKey("Roll"),
                                    new Action(r => Logger.WriteDebug("CloseDistance: Roll has ended"))
                                    )
                                )
                            )
                        )
                    )
                );
        }
예제 #9
0
        /// <summary>
        ///   Creates a behavior to cast a spell by ID, with special requirements, on a specific unit.
        ///   Returns RunStatus.Success if successful, RunStatus.Failure otherwise.
        /// </summary>
        /// <param name = "spellId">Identifier for the spell.</param>
        /// <param name = "onUnit">The on unit.</param>
        /// <param name = "requirements">The requirements.</param>
        /// <returns>.</returns>
        public static Composite Cast(SimpleIntDelegate spellId, UnitSelectionDelegate onUnit, SimpleBooleanDelegate requirements)
        {
            return
                new Decorator(ret => requirements != null && onUnit != null,
                    new Throttle(
                        new Action(ret =>
                        {
                            RunStatus runStat = RunStatus.Failure;

                            _castOnUnit = onUnit(ret);
                            // if (_castOnUnit == null || !requirements(ret) || !Spell.CanCastHack(spellId(ret), _castOnUnit, true))
                            if (_castOnUnit != null && requirements(ret))
                            {
                                _castSpell = WoWSpell.FromId(spellId(ret));
                                if (_castSpell != null)
                                {
                                    if (Spell.CanCastHack(_castSpell.Name, onUnit(ret), skipWowCheck: true))
                                    {
                                        string sname = _castSpell != null ? _castSpell.Name : "#" + _castSpell.Id.ToString();
                                        LogCast(sname, _castOnUnit);
                                        if (SpellManager.Cast(_castSpell.Id, _castOnUnit))
                                        {
                                            runStat = RunStatus.Success;
                                        }
                                    }
                                }
                            }

                            _castSpell = null;
                            _castOnUnit = null;
                            return runStat;
                        })
                    )
                );
        }
예제 #10
0
 /// <summary>
 ///   Creates a behavior to cast a buff by ID on yourself with special requirements. Returns RunStatus.Success if
 ///   successful, RunStatus.Failure otherwise.
 /// </summary>
 /// <remarks>
 ///   Created 5/6/2011.
 /// </remarks>
 /// <param name = "spellId">The buff ID.</param>
 /// <param name = "requirements">The requirements.</param>
 /// <returns>.</returns>
 public static Composite BuffSelf(SimpleIntDelegate spellId, SimpleBooleanDelegate requirements)
 {
     return Buff(spellId, ret => StyxWoW.Me, requirements);
 }
예제 #11
0
        private static Composite CreateArmsAoeCombat(SimpleIntDelegate aoeCount)
        {
            return new PrioritySelector(
                new Decorator(ret => aoeCount(ret) >= 3,
                    new PrioritySelector(
                        Spell.Cast( "Thunder Clap" ),

                        Spell.Cast("Bladestorm", ret => aoeCount(ret) >= 4),
                        Spell.Cast("Shockwave", ret => Clusters.GetClusterCount(StyxWoW.Me, Unit.NearbyUnfriendlyUnits, ClusterType.Cone, 10f) >= 3),
                        Spell.Cast("Dragon Roar"),

                        Spell.Cast("Whirlwind"),
                        Spell.Cast("Mortal Strike"),
                        Spell.Cast("Colossus Smash", ret => !StyxWoW.Me.CurrentTarget.HasMyAura("Colossus Smash")),
                        Spell.Cast("Overpower")
                        )
                    ),

                Spell.BuffSelf("Sweeping Strikes", ret => aoeCount(ret) == 2)
                );
        }
예제 #12
0
        public static Composite CreateMonkCloseDistanceBehavior(SimpleIntDelegate minDist = null, UnitSelectionDelegate onUnit = null, SimpleBooleanDelegate canReq = null)
        {
            /*
             * new Decorator(
             *  unit => (unit as WoWUnit).SpellDistance() > 10
             *      && Me.IsSafelyFacing(unit as WoWUnit, 5f),
             *  Spell.Cast("Roll")
             *  )
             */

            bool hasFSKGlpyh   = TalentManager.HasGlyph("Flying Serpent Kick");
            bool hasTigersLust = HasTalent(MonkTalents.TigersLust);

            if (minDist == null)
            {
                minDist = min => Me.Combat ? 10 : 12;
            }

            if (onUnit == null)
            {
                onUnit = on => Me.CurrentTarget;
            }

            if (canReq == null)
            {
                canReq = req => true;
            }

            return(new Throttle(1,
                                new PrioritySelector(
                                    ctx => onUnit(ctx),
                                    new Decorator(
                                        req => {
                if (!MovementManager.IsClassMovementAllowed)
                {
                    return false;
                }

                if (!canReq(req))
                {
                    return false;
                }

                float dist = Me.SpellDistance(req as WoWUnit);
                if (dist <= minDist(req))
                {
                    return false;
                }

                if ((req as WoWUnit).IsAboveTheGround())
                {
                    return false;
                }

                float facingPrecision = (req as WoWUnit).SpellDistance() < 15 ? 6f : 4f;
                if (!Me.IsSafelyFacing(req as WoWUnit, facingPrecision))
                {
                    return false;
                }

                bool isObstructed = Movement.MeshTraceline(Me.Location, (req as WoWUnit).Location);
                if (isObstructed == true)
                {
                    return false;
                }

                return true;
            },
                                        new PrioritySelector(
                                            Spell.BuffSelf(
                                                "Tiger's Lust",
                                                req => hasTigersLust &&
                                                !Me.HasAuraWithEffect(WoWApplyAuraType.ModIncreaseSpeed) &&
                                                Me.HasAuraWithEffect(WoWApplyAuraType.ModRoot, WoWApplyAuraType.ModDecreaseSpeed)
                                                ),

                                            new Sequence(
                                                Spell.Cast(
                                                    "Flying Serpent Kick",
                                                    on => (WoWUnit)on,
                                                    ret => TalentManager.CurrentSpec == WoWSpec.MonkWindwalker &&
                                                    !Me.Auras.ContainsKey("Flying Serpent Kick") &&
                                                    ((ret as WoWUnit).SpellDistance() > 25 || Spell.IsSpellOnCooldown("Roll"))
                                                    ),
                                                /* wait until in progress */
                                                new PrioritySelector(
                                                    new Wait(
                                                        TimeSpan.FromMilliseconds(750),
                                                        until => Me.Auras.ContainsKey("Flying Serpent Kick"),
                                                        new Action(r => Logger.WriteDebug("CloseDistance: Flying Serpent Kick detected towards {0} @ {1:F1} yds in progress", (r as WoWUnit).SafeName(), (r as WoWUnit).SpellDistance()))
                                                        ),
                                                    new Action(r => {
                Logger.WriteDebug("CloseDistance: failure - did not see Flying Serpent Kick aura appear - lag?");
                return RunStatus.Failure;
            })
                                                    ),

                                                /* cancel when in range */
                                                new Wait(
                                                    TimeSpan.FromMilliseconds(2500),
                                                    until => {
                if (!Me.Auras.ContainsKey("Flying Serpent Kick"))
                {
                    Logger.WriteDebug("CloseDistance: Flying Serpent Kick completed on {0} @ {1:F1} yds and {2} behind me", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance(), (until as WoWUnit).IsBehind(Me) ? "IS" : "is NOT");
                    return true;
                }

                if (!hasFSKGlpyh)
                {
                    SpellFindResults sfr;
                    SpellManager.FindSpell("Flying Serpent Kick", out sfr);

                    if (((until as WoWUnit).IsWithinMeleeRange || (until as WoWUnit).SpellDistance() < 8f))
                    {
                        Logger.Write(LogColor.Cancel, "/cancel Flying Serpent Kick in melee range of {0} @ {1:F1} yds", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance());
                        //Spell.CastPrimative("Flying Serprent Kick");
                        // Lua.DoString("CastSpellByID(" + sfr.Original.Id + ")");
                        return true;
                    }
                    else if ((until as WoWUnit).IsBehind(Me))
                    {
                        Logger.Write(LogColor.Cancel, "/cancel Flying Serpent Kick flew past {0} @ {1:F1} yds", (until as WoWUnit).SafeName(), (until as WoWUnit).SpellDistance());
                        //Spell.CastPrimative("Flying Serprent Kick");
                        //Lua.DoString("CastSpellByID(" + sfr.Original.Id + ")");
                        return true;
                    }
                }

                return false;
            },
                                                    new PrioritySelector(
                                                        new Decorator(
                                                            req => !Me.Auras.ContainsKey("Flying Serpent Kick"),
                                                            new ActionAlwaysSucceed()
                                                            ),
                                                        new Sequence(
                                                            new Action(r => {
                if (hasFSKGlpyh)
                {
                    Logger.WriteDebug("CloseDistance: FSK is glyphed, should not be here - notify developer!");
                }
                else
                {
                    Logger.WriteDebug("CloseDistance: casting Flying Serpent Kick to cancel");
                    Spell.CastPrimative(101545);
                }
            }),
                                                            /* wait until cancel takes effect */
                                                            new PrioritySelector(
                                                                new Wait(
                                                                    TimeSpan.FromMilliseconds(450),
                                                                    until => !Me.Auras.ContainsKey("Flying Serpent Kick"),
                                                                    new Action(r => Logger.WriteDebug("CloseDistance: Flying Serpent Kick complete, landed {0:F1} yds from {1}", (r as WoWUnit).SpellDistance(), (r as WoWUnit).SafeName()))
                                                                    ),
                                                                new Action(r => {
                Logger.WriteDebug("CloseDistance: error - Flying Serpent Kick was not removed - lag?");
            })
                                                                )
                                                            )
                                                        )
                                                    )
                                                ),

                                            Spell.BuffSelf("Tiger's Lust", req => hasTigersLust),

                                            new Sequence(
                                                Spell.Cast("Roll", on => (WoWUnit)on, req => !MonkSettings.DisableRoll && MovementManager.IsClassMovementAllowed),
                                                new PrioritySelector(
                                                    new Wait(
                                                        TimeSpan.FromMilliseconds(500),
                                                        until => Me.Auras.ContainsKey("Roll"),
                                                        new Action(r => Logger.WriteDebug("CloseDistance: Roll in progress"))
                                                        ),
                                                    new Action(r => {
                Logger.WriteDebug("CloseDistance: failure - did not detect Roll in progress aura- lag?");
                return RunStatus.Failure;
            })
                                                    ),
                                                new Wait(
                                                    TimeSpan.FromMilliseconds(950),
                                                    until => !Me.Auras.ContainsKey("Roll"),
                                                    new Action(r => Logger.WriteDebug("CloseDistance: Roll has ended"))
                                                    )
                                                )
                                            )
                                        )
                                    )
                                ));
        }