예제 #1
0
파일: Spell.cs 프로젝트: aash/Singular
        /// <summary>
        ///   Creates a composite that will return a success, so long as you are currently casting. (Use this to prevent the CC from
        ///   going down to lower branches in the tree, while casting.)
        /// </summary>
        /// <remarks>
        ///   Created 13/5/2011.
        /// </remarks>
        /// <param name = "faceDuring">Whether or not to face during casting</param>
        /// <param name = "allow">Whether or not to allow lag tollerance for spell queueing</param>
        /// <returns></returns>
        public static Composite WaitForChannel(LagTolerance allow = LagTolerance.Yes)
        {
            return new Action(ret =>
                {
                    if (IsChannelling(allow))
                        return RunStatus.Success;

                    return RunStatus.Failure;
                });
        }
예제 #2
0
파일: Spell.cs 프로젝트: aash/Singular
        public static bool IsChannelling(LagTolerance allow = LagTolerance.Yes)
        {
            try
            {
                if (!StyxWoW.Me.IsChanneling)
                    return false;
            }
            catch (Styx.InvalidObjectPointerException ie)
            {
                Logger.WriteDiagnostic("IsChannelling: InvalidObjectPointerException exception encountered - returning true", ie);
                return true;
            }

            uint latency = SingularRoutine.Latency * 2;
            TimeSpan timeLeft = StyxWoW.Me.CurrentChannelTimeLeft;
            if (allow == LagTolerance.Yes && timeLeft.TotalMilliseconds < latency)
                return false;

            return true;
        }
예제 #3
0
파일: Spell.cs 프로젝트: aash/Singular
        public static bool IsGlobalCooldown(LagTolerance allow = LagTolerance.No)
        {
#if NO_LATENCY_ISSUES_WITH_GLOBAL_COOLDOWN
            uint latency = allow == LagTolerance.Yes ? SingularRoutine.Latency : 0;
            TimeSpan gcdTimeLeft = Spell.GcdTimeLeft;
            return gcdTimeLeft.TotalMilliseconds > latency;
#else
            return Spell.FixGlobalCooldown;
#endif
        }
예제 #4
0
파일: Spell.cs 프로젝트: aash/Singular
        public static bool IsCasting(LagTolerance allow = LagTolerance.Yes)
        {
            try
            {
                if (!StyxWoW.Me.IsCasting)
                    return false;
            }
            catch(Styx.InvalidObjectPointerException ie)
            {
                Logger.WriteDiagnostic("IsCasting: InvalidObjectPointerException exception encountered - returning true", ie);
                return true;
            }

            //if (StyxWoW.Me.IsWanding())
            //    return RunStatus.Failure;

            // following logic previously existed to let channels pass thru -- keeping for now
            if (StyxWoW.Me.ChannelObjectGuid.IsValid)
                return false;

            uint latency = SingularRoutine.Latency * 2;
            TimeSpan castTimeLeft = StyxWoW.Me.CurrentCastTimeLeft;
            if (allow == LagTolerance.Yes // && castTimeLeft != TimeSpan.Zero 
                && StyxWoW.Me.CurrentCastTimeLeft.TotalMilliseconds < latency)
                return false;

            /// -- following code does nothing since the behaviors created are not linked to execution tree
            /// 
            // if (faceDuring && StyxWoW.Me.ChanneledSpell == null) // .ChanneledCastingSpellId == 0)
            //    Movement.CreateFaceTargetBehavior();

            // return RunStatus.Running;
            return true;
        }
예제 #5
0
파일: Spell.cs 프로젝트: aash/Singular
        public static Composite Cast(SpellFindDelegate ssd, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
            SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, bool skipWowCheck = false, CanCastDelegate canCast = null, HasGcd gcd = HasGcd.Yes)
        {
            // only need to check these at creation time
            if (ssd == null || checkMovement == null || onUnit == null || requirements == null)
                return new ActionAlwaysFail();

            if (canCast == null)
                canCast = CanCastHack;

            Composite comp =  new PrioritySelector(

                // create a CastContext object to save passed in context and other values
                ctx => new CastContext(ctx, ssd, onUnit, gcd),

                new Sequence(
                    // cast the spell, saving state information including if we queued this cast
                    new Action(ret =>
                    {
                        CastContext cctx = ret.CastContext();

                        if (cctx.spell == null)
                            return RunStatus.Failure;   

                        if (cctx.unit == null)
                            return RunStatus.Failure;

                        if (!requirements(cctx.context))
                            return RunStatus.Failure;

                        if (checkMovement(cctx.context) && Me.IsMoving && !AllowMovingWhileCasting(cctx.spell))
                        {
                            if (SingularSettings.DebugSpellCasting)
                                Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because we are moving", cctx.unit.SafeName(), cctx.spell.Name);
                            return RunStatus.Failure;
                        }

                        // check we can cast it on target without checking for movement
                        // if (!Spell.CanCastHack(_spell, cctx.unit, true, false, allow == LagTolerance.Yes))
                        if (!canCast(cctx.sfr, cctx.unit, skipWowCheck))
                        {
                            if (SingularSettings.DebugSpellCasting)
                                Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because CanCastHack failed", cctx.unit.SafeName(), cctx.spell.Name);
                            return RunStatus.Failure;
                        }

                        // save status of queueing spell (lag tolerance - the prior spell still completing)
                        cctx.IsSpellBeingQueued = allow == LagTolerance.Yes && (Spell.GcdActive || StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling);

                        const int PENANCE = 047540;
                        LogCast(
                            cctx.spell.Name, 
                            cctx.unit, 
                            cctx.health, 
                            cctx.distance,
                            cctx.spell.IsHeal() ? true : (cctx.spell.Id == PENANCE && cctx.unit.IsFriendly)
                            );

                        if (SingularSettings.DebugSpellCasting)
                            Logger.WriteDebug("Cast('{0}'): dist:{1:F3}, need({2}), hitbox:{3:F3}",
                                cctx.spell.Name, 
                                cctx.unit.Distance,
                                cctx.spell.IsMeleeSpell
                                    ? "Melee"
                                    : (!cctx.spell.HasRange ? "None" : string.Format("min={0:F3},max={1:F3}", cctx.spell.MinRange, cctx.spell.MaxRange)),
                                cctx.unit.CombatReach
                                );

                        if (!Spell.CastPrimative(cctx.spell, cctx.unit))
                        {
                            Logger.Write(Color.LightPink, "cast of {0} on {1} failed!", cctx.spell.Name, cctx.unit.SafeName());
                            return RunStatus.Failure;
                        }

                        SingularRoutine.UpdateDiagnosticCastingState();
                        return RunStatus.Success;
                    }),

                    new Action(r =>
                    {
                        if (SingularSettings.DebugSpellCasting)
                        {
                            CastContext cctx = r.CastContext();
                            Logger.WriteFile("Spell.Cast[{0}]: checking to ensure cast in progress", cctx.spell.Name);
                        }
                        return RunStatus.Success;
                    }),

                // for instant spell, wait for GCD to start
                // for non-instant spell, wait for .IsCasting / .IsChanneling to start
                    new PrioritySelector(
                        new Wait(
                            TimeSpan.FromMilliseconds(350),
                            until =>
                            {
                                CastContext cctx = until.CastContext();
                                if (gcd == HasGcd.No)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile("Spell.Cast[{0}]: has no GCD, status GCD={1}, remains={2}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds);
                                    return true;
                                }

                                if (cctx.spell.IsInstantCast() && Spell.GcdTimeLeft.TotalMilliseconds > 650)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile("Spell.Cast[{0}]: is instant, status GCD={1}, remains={2}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds);
                                    return true;
                                }

                                if (Me.CurrentCastTimeLeft.TotalMilliseconds > 750)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile( "Spell.Cast[{0}]: cast time {1} left, iscasting={2}", cctx.spell.Name, (long)Me.CurrentCastTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN());
                                    return true;
                                }

                                if (Me.CurrentChannelTimeLeft.TotalMilliseconds > 750)
                                {
                                    if (SingularSettings.DebugSpellCasting)
                                        Logger.WriteFile( "Spell.Cast[{0}]: channel spell and channel has {1} left, ischanneling={2}", cctx.spell.Name, (long)Me.CurrentChannelTimeLeft.TotalMilliseconds, Spell.IsChannelling(allow).ToYN());
                                    return true;
                                }

                                return false;
                            },
                            new ActionAlwaysSucceed()
                            ),
                        new Action( r => {
                            if (SingularSettings.DebugSpellCasting)
                            {
                                CastContext cctx = r.CastContext();
                                Logger.WriteFile( "Spell.Cast[{0}]: timed out failing to detect spell in progress - gcdleft={1}/{2}, castleft={3}/{4}, chanleft={5}/{6}", cctx.spell.Name, Spell.IsGlobalCooldown(allow).ToYN(), (long)Spell.GcdTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN(), (long)Me.CurrentCastTimeLeft.TotalMilliseconds, Spell.IsCasting(allow).ToYN(), (long)Me.CurrentChannelTimeLeft.TotalMilliseconds);
                            }
                            return RunStatus.Success;
                            })
                        ),

        // now check for one of the possible done casting states
                    new PrioritySelector(

                        // for cast already ended, assume it has no Global Cooldown
                        new Decorator(
                            ret => !Spell.IsGlobalCooldown() && !Spell.IsCastingOrChannelling(),
                            new Action(r =>
                            {
                                CastContext cctx = r.CastContext();
                                if (SingularSettings.DebugSpellCasting)
                                {
                                    if (!Spell.IsGlobalCooldown())
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no gcd active, lag={0} hasgcd={1}", cctx.spell.Name, allow, gcd);
                                    else
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no cast in progress", cctx.spell.Name);
                                }
                                return RunStatus.Success;
                            })
                            ),

                        // for instant or no cancel method given, we are done
                        new Decorator(
                            ret => gcd == HasGcd.No || cancel == null || ret.CastContext().spell.IsInstantCast(),
                            new Action(r =>
                            {
                                CastContext cctx = r.CastContext();
                                if (SingularSettings.DebugSpellCasting)
                                {
                                    if (gcd == HasGcd.No)
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, hasgcd=No", cctx.spell.Name);
                                    else if (r.CastContext().spell.IsInstantCast())
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, is instant cast", cctx.spell.Name);
                                    else
                                        Logger.WriteFile("Spell.Cast(\"{0}\"): complete, no cancel delegate given", cctx.spell.Name);
                                }
                                return RunStatus.Success;
                            })
                            ),

                        // while casting/channeling call the cancel method to see if we should abort
                        new Wait(12,
                            until =>
                            {
                                CastContext cctx = until.CastContext();
                                SingularRoutine.UpdateDiagnosticCastingState();

                                // Interrupted or finished casting. 
                                if (!Spell.IsCastingOrChannelling(allow))
                                {
                                    Logger.WriteDebug("Spell.Cast(\"{0}\"): complete, iscasting=false", cctx.spell.Name);
                                    return true;
                                }

                                // check cancel delegate if we are finished
                                if (cancel(cctx.context))
                                {
                                    SpellManager.StopCasting();
                                    Logger.Write(LogColor.Cancel, "/cancel {0} on {1} @ {2:F1}%", cctx.spell.Name, cctx.unit.SafeName(), cctx.unit.HealthPercent);
                                    return true;
                                }
                                // continue casting/channeling at this point
                                return false;
                            },
                            new ActionAlwaysSucceed()
                            ),

                        // if we are here, we timed out after 12 seconds (very odd)
                        new Action(r =>
                        {
                            CastContext cctx = r.CastContext();
                            Logger.WriteDebug("Spell.Cast(\"{0}\"): aborting, timed out waiting on cast, gcd={1} cast={2} chanl={3}", cctx.spell.Name, Spell.IsGlobalCooldown().ToYN(), Spell.IsCasting().ToYN(), Spell.IsChannelling().ToYN());
                            return RunStatus.Success;
                        })

                        ),

                        // made it this far then we are RunStatus.Success, so reset wowunit reference and return
                        new Action(ret =>
                        {
                            CastContext cctx = ret.CastContext();
                            cctx.unit = null;
                            cctx.spell = null;
                            return RunStatus.Success;
                        })
                    ),

                // cast Sequence failed, so only thing left is to reset cached references and report failure
                new Action(ret =>
                {
                    CastContext cctx = ret.CastContext();
                    cctx.unit = null;
                    cctx.spell = null;
                    return RunStatus.Failure;
                })
                );

            // when no cancel method in place, we will return immediately so.....
            // .. throttle attempts at casting this spell.  note: this only limits this 
            // .. instance of the spell.cast behavior.  in other words, if this is for a cast
            // .. of flame shock, it would only throttle this behavior tree instance, not any 
            // .. other trees which also call Spell.Cast("flame shock")
            if (cancel == null)
                comp = new Throttle( TimeSpan.FromMilliseconds(SingularSettings.Instance.SameSpellThrottle), comp);

            return comp;
        }
예제 #6
0
파일: Spell.cs 프로젝트: aash/Singular
        public static Composite WaitForGlobalCooldown(LagTolerance allow = LagTolerance.Yes)
        {
            return new Action(ret =>
                {
                    if (IsGlobalCooldown(allow))
                        return RunStatus.Success;

                    return RunStatus.Failure;
                });
        }
예제 #7
0
파일: Spell.cs 프로젝트: aash/Singular
 public static Composite Cast(string name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
     SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, HasGcd gcd = HasGcd.Yes)
 {
     return Cast(n => name, checkMovement, onUnit, requirements, cancel, allow, gcd: gcd);
 }
예제 #8
0
        /// <summary>
        ///   Creates a behavior to cast a spell by name, with special requirements, on a specific unit. Will make sure any spell with
        ///   a non-zero cast time (everything not instant) will stay here until passing the latency boundary (point where .IsCasting == false while cast is in progress.)
        ///   Returns RunStatus.Success if successful, RunStatus.Failure otherwise.  Note: will return as soon as spell cast is in progress, unless cancel delegate provided
        /// </summary>
        /// <remarks>
        ///   Created 5/2/2011.
        /// </remarks>
        /// <param name = "name">The name.</param>
        /// <param name="checkMovement"></param>
        /// <param name = "onUnit">The on unit.</param>
        /// <param name = "requirements">The requirements.</param>
        /// <param name="cancel">The cancel cast in progress delegate</param>
        /// <param name="allow">allow next spell to queue before this one completes</param>
        /// <returns>.</returns>
        public static Composite Cast(SimpleStringDelegate name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
            SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, bool skipWowCheck = false)
        {
            return new Decorator(
                ret => name != null && checkMovement != null && onUnit != null && requirements != null && name(ret) != null,
                new Throttle(
                    new PrioritySelector(
                        new Sequence(
                // save flag indicating if currently in a GCD or IsCasting before queueing our cast
                            new Action(ret =>
                            {
                                _castSpell = null;
                                _castOnUnit = onUnit(ret);
                                if (_castOnUnit == null)
                                    return RunStatus.Failure;

                                // health/dist change quickly, so grab these now where
                                // .. we check requirements so the log message we output
                                // .. later reflects what they were when we were testing
                                // .. as opposed to what they may have changed to
                                // .. (since spell lookup, move while casting check, and cancast take time)
                                double health = _castOnUnit.HealthPercent;
                                double dist = _castOnUnit.Distance;

                                if (!requirements(ret))
                                    return RunStatus.Failure;

                                // find spell 
                                SpellFindResults sfr;
                                if (!SpellManager.FindSpell(name(ret), out sfr))
                                    return RunStatus.Failure;

                                _castSpell = sfr.Override ?? sfr.Original;

                                if (checkMovement(ret) && Me.IsMoving && !AllowMovingWhileCasting(_castSpell))
                                {
                                    if (SingularSettings.Instance.EnableDebugLoggingGCD)
                                        Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because we are moving", _castOnUnit.SafeName(), _castSpell.Name);
                                    return RunStatus.Failure;
                                }

                                // check we can cast it on target without checking for movement
                                // if (!Spell.CanCastHack(_spell, _castOnUnit, true, false, allow == LagTolerance.Yes))
                                if (!CanCastHack(name(ret), _castOnUnit, skipWowCheck))
                                {
                                    if (SingularSettings.Instance.EnableDebugLoggingGCD)
                                        Logger.WriteDebug("skipping Spell.Cast({0},[{1}]) because CanCastHack failed", _castOnUnit.SafeName(), _castSpell.Name);
                                    return RunStatus.Failure;
                                }

                                // save status of queueing spell (lag tolerance - the prior spell still completing)
                                _IsSpellBeingQueued = allow == LagTolerance.Yes && (Spell.GcdActive || StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling);

                                LogCast(_castSpell.Name, _castOnUnit, health, dist);
                                if (!SpellManager.Cast(_castSpell, _castOnUnit))
                                {
                                    Logger.WriteDebug(Color.LightPink, "cast of {0} on {1} failed!", _castSpell.Name, _castOnUnit.SafeName());
                                    return RunStatus.Failure;
                                }

                                SingularRoutine.UpdateDiagnosticCastingState();
                                return RunStatus.Success;
                            }),
#if OLD_WAY_OF_ENSURING
                            // when accountForLag = true, wait for in progress spell (if any) to complete
                            new WaitContinue(
                                TimeSpan.FromMilliseconds(500),
                                ret => SingularRoutine.UpdateDiagnosticCastingState(false) || !_IsSpellBeingQueued || !(Spell.GcdActive || StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling),
                                new ActionAlwaysSucceed()
                                ),

                            // new Action(r => Logger.WriteDebug("Spell.Cast(\"{0}\"): waited for queued spell {1}", name(r), _IsSpellBeingQueued )),

                            // failsafe: max time we should be waiting with the prior and latter WaitContinue is latency x 2
                // .. if system is borked, could be 1 second but shouldnt notice.  
                // .. instant spells should be very quick since only prior wait applies

                            // now for non-instant spell, wait for .IsCasting to be true
                            new WaitContinue(
                                TimeSpan.FromMilliseconds(300),
                                ret =>
                                {
                                    SingularRoutine.UpdateDiagnosticCastingState();

                                    SpellFindResults sfr;
                                    if (SpellManager.FindSpell(name(ret), out sfr))
                                    {
                                        WoWSpell spell = sfr.Override ?? sfr.Original;
                                        if (spell.CastTime == 0 && !IsFunnel(spell))
                                        {
                                            return true;
                                        }
                                    }

                                    return StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling;
                                },
                                new ActionAlwaysSucceed()
                                ),

                            /// new Action(r => Logger.WriteDebug("Spell.Cast(\"{0}\"): assume we are casting (actual={1}, gcd={2})", name(r), StyxWoW.Me.IsCasting || StyxWoW.Me.IsChanneling, Spell.GlobalCooldown )),
#else
                            // for instant spell, wait for GCD to start
                            // for non-instant spell, wait for .IsCasting / .IsChanneling to start
                            new WaitContinue(
                                TimeSpan.FromMilliseconds(350),
                                ret =>
                                {
                                    if ((_castSpell.CastTime == 0 && Spell.GcdTimeLeft.TotalMilliseconds > 750) || Me.CurrentCastTimeLeft.TotalMilliseconds > 750 || Me.CurrentChannelTimeLeft.TotalMilliseconds > 750)
                                        return true;

                                    return false;
                                },
                                new ActionAlwaysSucceed()
                                ),
#endif

                            // now check for one of the possible done casting states
                            new PrioritySelector(

                                // for instant or no cancel method given, we are done
                                new Decorator(
                                    ret => cancel == null || _castSpell.CastTime == 0,
                                    new Action(r =>
                                    {
                                        // Logger.WriteDebug("Spell.Cast(\"{0}\"): no cancel delegate", _castSpell.Name);
                                        return RunStatus.Success;
                                    })
                                    ),

                                // while casting/channeling call the cancel method to see if we should abort
                                new Wait(12,
                                    ret => {
                                        SingularRoutine.UpdateDiagnosticCastingState();

                                        // Interrupted or finished casting. 
                                        if (!Spell.IsCastingOrChannelling(allow))
                                        {
                                            Logger.WriteDebug("Spell.Cast(\"{0}\"): cast has ended", _castSpell.Name);
                                            return true;
                                        }

                                        // check cancel delegate if we are finished
                                        if (cancel(ret))
                                        {
                                            SpellManager.StopCasting();
                                            Logger.Write(System.Drawing.Color.Orange, "/cancel {0} on {1} @ {2:F1}%", _castSpell.Name, _castOnUnit.SafeName(), _castOnUnit.HealthPercent);
                                            return true;
                                        }
                                        // continue casting/channeling at this point
                                        return false;
                                        },
                                    new ActionAlwaysSucceed()
                                    ),

                                // if we are here, we timed out after 12 seconds (very odd)
                                new Action(r => {
                                    Logger.WriteDebug("Spell.Cast(\"{0}\"): timed out waiting", _castSpell.Name);
                                    return RunStatus.Success;
                                    })

                                ),

                                // made it this far the we are RunStatus.Success, so reset wowunit reference and return
                                new Action(ret =>
                                {
                                    _castOnUnit = null;
                                    _castSpell = null;
                                    return RunStatus.Success;
                                })
                            ),

                        // cast Sequence failed, so only thing left is to reset cached references and report failure
                        new Action(ret =>
                        {
                            _castOnUnit = null;
                            _castSpell = null;
                            return RunStatus.Failure;
                        })
                        )
                    )
                );
        }
예제 #9
0
 public static Composite WaitForGcdOrCastOrChannel(FaceDuring faceDuring = FaceDuring.No, LagTolerance allow = LagTolerance.Yes)
 {
     return new PrioritySelector(
         WaitForGlobalCooldown(faceDuring,allow),
         WaitForCast(faceDuring, allow),
         WaitForChannel(faceDuring, allow)
         );
 }
예제 #10
0
        private static bool OkToCallBehaviorsWithCurrentCastingStatus(LagTolerance allow = LagTolerance.Yes)
        {
            if (TalentManager.CurrentSpec == WoWSpec.MonkMistweaver)
                return true;

            if (!Spell.IsGlobalCooldown(allow) && !Spell.IsCastingOrChannelling(allow))
                return true;

            return false;
        }
예제 #11
0
        public static bool IsChannelling(LagTolerance allow = LagTolerance.Yes)
        {
            if (!StyxWoW.Me.IsChanneling)
                return false;

            uint latency = StyxWoW.WoWClient.Latency * 2;
            TimeSpan timeLeft = StyxWoW.Me.CurrentChannelTimeLeft;
            if (allow == LagTolerance.Yes && timeLeft.TotalMilliseconds < latency)
                return false;

            return true;
        }
예제 #12
0
        /// <summary>
        ///   Creates a composite that will return a success, so long as you are currently casting. (Use this to prevent the CC from
        ///   going down to lower branches in the tree, while casting.)
        /// </summary>
        /// <remarks>
        ///   Created 13/5/2011.
        /// </remarks>
        /// <param name = "faceDuring">Whether or not to face during casting</param>
        /// <param name = "allow">Whether or not to allow lag tollerance for spell queueing</param>
        /// <returns></returns>
        public static Composite WaitForChannel(FaceDuring faceDuring = FaceDuring.No, LagTolerance allow = LagTolerance.Yes)
        {
            return new PrioritySelector(
                new Decorator(
                    ret => faceDuring == FaceDuring.Yes,
                    Movement.CreateFaceTargetBehavior()
                    ),
                new Action(ret =>
                {
                    if (IsChannelling(allow))
                        return RunStatus.Success;

                    return RunStatus.Failure;
                })
                );
        }
예제 #13
0
        public static bool IsCasting(LagTolerance allow = LagTolerance.Yes)
        {
            if (!StyxWoW.Me.IsCasting)
                return false;

            //if (StyxWoW.Me.IsWanding())
            //    return RunStatus.Failure;

            // following logic previously existed to let channels pass thru -- keeping for now
            if (StyxWoW.Me.ChannelObjectGuid > 0)
                return false;

            uint latency = StyxWoW.WoWClient.Latency * 2;
            TimeSpan castTimeLeft = StyxWoW.Me.CurrentCastTimeLeft;
            if (allow == LagTolerance.Yes // && castTimeLeft != TimeSpan.Zero 
                && StyxWoW.Me.CurrentCastTimeLeft.TotalMilliseconds < latency)
                return false;

            /// -- following code does nothing since the behaviors created are not linked to execution tree
            /// 
            // if (faceDuring && StyxWoW.Me.ChanneledSpell == null) // .ChanneledCastingSpellId == 0)
            //    Movement.CreateFaceTargetBehavior();

            // return RunStatus.Running;
            return true;
        }
예제 #14
0
파일: Spell.cs 프로젝트: aash/Singular
 public static bool IsCastingOrChannelling(LagTolerance allow = LagTolerance.Yes)
 {
     return IsCasting(allow) || IsChannelling();
 }
예제 #15
0
파일: Spell.cs 프로젝트: aash/Singular
        /// <summary>
        ///   Creates a behavior to cast a spell by name, with special requirements, on a specific unit. Will make sure any spell with
        ///   a non-zero cast time (everything not instant) will stay here until passing the latency boundary (point where .IsCasting == false while cast is in progress.)
        ///   Returns RunStatus.Success if successful, RunStatus.Failure otherwise.  Note: will return as soon as spell cast is in progress, unless cancel delegate provided
        /// </summary>
        /// <remarks>
        ///   Created 5/2/2011.
        /// </remarks>
        /// <param name = "name">The name.</param>
        /// <param name="checkMovement"></param>
        /// <param name = "onUnit">The on unit.</param>
        /// <param name = "requirements">The requirements.</param>
        /// <param name="cancel">The cancel cast in progress delegate</param>
        /// <param name="allow">allow next spell to queue before this one completes</param>
        /// <returns>.</returns>
/*        
        public static Composite Cast(SimpleStringDelegate name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
            SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, bool skipWowCheck = false)
        {
            return Cast(name, checkMovement, onUnit, requirements, cancel, allow, skipWowCheck, null);
        }
*/
        /// <summary>
        ///   Creates a behavior to cast a spell by name, with special requirements, on a specific unit. Will make sure any spell with
        ///   a non-zero cast time (everything not instant) will stay here until passing the latency boundary (point where .IsCasting == false while cast is in progress.)
        ///   Returns RunStatus.Success if successful, RunStatus.Failure otherwise.  Note: will return as soon as spell cast is in progress, unless cancel delegate provided
        /// </summary>
        /// <remarks>
        ///   Created 5/2/2011.
        /// </remarks>
        /// <param name = "name">The name.</param>
        /// <param name="checkMovement"></param>
        /// <param name = "onUnit">The on unit.</param>
        /// <param name = "requirements">The requirements.</param>
        /// <param name="cancel">The cancel cast in progress delegate</param>
        /// <param name="allow">allow next spell to queue before this one completes</param>
        /// <param name="allow">check if spell can be cast</param>
        /// <returns>.</returns>
        public static Composite Cast(SimpleStringDelegate name, SimpleBooleanDelegate checkMovement, UnitSelectionDelegate onUnit,
            SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes, bool skipWowCheck = false, CanCastDelegate canCast = null, HasGcd gcd = HasGcd.Yes)
        {
            SpellFindDelegate ssd =
                (object ctx, out SpellFindResults sfr) =>
                {
                    if (name != null)
                    {
                        string spellName = name(ctx);
                        if (spellName != null)
                        {
                            return SpellManager.FindSpell(spellName, out sfr);
                        }
                        else
                        {
                            AddUndefinedSpell(spellName);
                        }
                    }

                    sfr = EmptySFR;
                    return false;
                };

            return Cast(ssd, checkMovement, onUnit, requirements, cancel, allow, skipWowCheck, canCast, gcd);
        }
예제 #16
0
파일: Spell.cs 프로젝트: aash/Singular
 public static Composite WaitForGcdOrCastOrChannel(LagTolerance allow = LagTolerance.Yes)
 {
     return new PrioritySelector(
         WaitForGlobalCooldown(allow),
         WaitForCast(allow),
         WaitForChannel(allow)
         );
 }
예제 #17
0
 /// <summary>
 ///   Creates a behavior to cast a heal spell by name, with special requirements, on a specific unit. Heal behaviors will make sure
 ///   we don't double cast. Returns RunStatus.Success if successful, RunStatus.Failure otherwise.
 /// </summary>
 /// <remarks>
 ///   Created 5/2/2011.
 /// </remarks>
 /// <param name = "name">The name.</param>
 /// <param name="checkMovement"></param>
 /// <param name = "onUnit">The on unit.</param>
 /// <param name = "requirements">The requirements.</param>
 /// <param name="cancel">The cancel cast in progress delegate</param>
 /// <param name="allow">allow next spell to queue before this one completes</param>
 /// <returns>.</returns>
 public static Composite Cast(string name, UnitSelectionDelegate onUnit,
     SimpleBooleanDelegate requirements, SimpleBooleanDelegate cancel = null, LagTolerance allow = LagTolerance.Yes)
 {
     return Cast(n => name, mov => true, onUnit, requirements, cancel, allow);
 }