Example #1
0
        public ObjectBase CreateOrGetObject(WoWGuid guid, TypeID typeid)
        {
            var key = guid.Full;
            ObjectBase obj = null;


            if (Objects[CurrentPlayerMapID].TryGetValue(key, out obj))
                return obj;
            else
            {
                switch (typeid)
                {
                    case TypeID.TYPEID_CORPSE: obj = new Corpse(this, guid, typeid); break;
                    case TypeID.TYPEID_OBJECT: obj = new GenericObject(this, guid, typeid); break;
                    case TypeID.TYPEID_ITEM: obj = new Item(this, guid, typeid); break;
                    case TypeID.TYPEID_CONTAINER: obj = new Container(this, guid, typeid); break;
                    case TypeID.TYPEID_UNIT: obj = new Unit(this, guid, typeid); break;
                    case TypeID.TYPEID_PLAYER: obj = new Player(this, guid, typeid); break;
                    case TypeID.TYPEID_GAMEOBJECT: obj = new GameObject(this, guid, typeid); break;
                    case TypeID.TYPEID_DYNAMICOBJECT: obj = new DynamicObject(this, guid, typeid); break;
                    case TypeID.TYPEID_AIGROUP: obj = new AIGroup(this, guid, typeid); break;
                    case TypeID.TYPEID_AREATRIGGER: obj = new Areatrigger(this, guid, typeid); break;
                }

                Objects[CurrentPlayerMapID].Add(key, obj);
                return obj;
            }
        }
 public TargetAuraMaxTimeLeftCondition(TargetType target, int auraId, WoWGuid creatorGuid, TimeSpan maxTimeLeft)
 {
     Target = target;
     AuraId = auraId;
     CreatorGuid = creatorGuid;
     MaxTimeLeft = maxTimeLeft;
 }
 public TargetHasAuraMinStacksCondition(TargetType target, int auraId, int minStackCount, WoWGuid creatorGuid)
 {
     Target        = target;
     AuraId        = auraId;
     MinStackCount = minStackCount;
     CreatorGuid   = creatorGuid;
 }
Example #4
0
        public void RemoveObjectByWoWGuid(WoWGuid guid)
        {
            var key = guid.Full;

            if (Objects[CurrentPlayerMapID].ContainsKey(key))
                Objects[CurrentPlayerMapID].Remove(key);
        }
 public TargetHasAuraMinStacksCondition(TargetType target, int auraId, int minStackCount, WoWGuid creatorGuid)
 {
     Target = target;
     AuraId = auraId;
     MinStackCount = minStackCount;
     CreatorGuid = creatorGuid;
 }
Example #6
0
    public static void HandleNameQueryResponse(ref PacketReader packet, ref World manager)
    {
        WoWGuid guid = new WoWGuid(packet.ReadUInt64());
        string  name = packet.ReadString();

        packet.ReadByte();
        Race      Race   = (Race)packet.ReadUInt32();
        Gender    Gender = (Gender)packet.ReadUInt32();
        Classname Class  = (Classname)packet.ReadUInt32();


        if (manager.objectMgr.objectExists(guid))    // Update existing Object
        {
            Assets.Scripts.World.Object obj = manager.objectMgr.getObject(guid);
            obj.Name = name;
            manager.objectMgr.updateObject(obj);
        }
        else                // Create new Object        -- FIXME: Add to new 'names only' list?
        {
            Assets.Scripts.World.Object obj = new Assets.Scripts.World.Object(guid);
            obj.Name = name;
            manager.objectMgr.addObject(obj);

            for (int i = 0; i < ChatHandler.ChatQueued.Count; i++)
            {
                ChatHandler.ChatQueue message = (ChatHandler.ChatQueue)ChatHandler.ChatQueued[i];
                if (message.GUID.GetOldGuid() == guid.GetOldGuid())
                {
                    //MainWorld.ChatHeads.Add("[" + obj.Name + "] " + MainWorld.ChatTag + message.Message + "\n");
                    ChatHandler.ChatQueued.Remove(message);
                }
            }
        }
    }
        public void QueryName(WoWGuid guid)
        {
            WoWWriter wr = new WoWWriter(OpCode.CMSG_NAME_QUERY);

            wr.Write(guid.GetOldGuid());
            Send(wr.ToArray());
        }
        public MovementInfo ReadMovementInfo(WoWGuid guid)
        {
            var info = new MovementInfo();

            info.MoveFlag = ReadUInt32_MoveFlag("MoveFlag");
            info.MoveFlagExtra = ReadUInt16_MoveFlagExtra("MoveFlagExtra");
            info.TimeStamp = ReadUInt32("TimeStamp");
            info.PositionInfo = ReadVector4("PositionInfo");

            if (info.MoveFlag.Value.HasFlag(MoveFlag.OnTransport))
            {
                info.TransportInfo = ReadMovementTransport("OnTransport", info.MoveFlagExtra.Value.HasFlag(MoveFlagExtra.InterpolatedPlayerMovement));
            }

            if (info.MoveFlag.Value.HasAnyFlag(MoveFlag.Swimming | MoveFlag.Flying) ||
                info.MoveFlagExtra.Value.HasFlag(MoveFlagExtra.AlwaysAllowPitching))
            {
                info.SwimPitch = ReadSingle("SwimPitch");
            }

            info.FallTime = ReadUInt32("FallTime");

            if (info.MoveFlag.Value.HasFlag(MoveFlag.Falling))
            {
                info.FallInfo = ReadMovementFall("FallInfo");
            }

            if (info.MoveFlag.Value.HasFlag(MoveFlag.SplineElevation))
            {
                info.SplineElevation = ReadFloat("SplineElevation");
            }

            return info;
        }
Example #9
0
        public static async Task <bool> FaceTarget(WoWUnit target)
        {
            if (target == null || Me.IsSafelyFacing(target) || !target.IsValidCombatUnit() || HK.RotationOnlyOn || !GeneralSettings.Instance.GeneralFacing)
            {
                return(false);
            }

            if (!lastTimeFaced.IsRunning || (target.Guid == lastUnitGuid && lastTimeFaced.ElapsedMilliseconds > 500))
            {
                L.infoLog("Not facing target; will attempt to", InfoColor);
            }

            target.Face();



            lastUnitGuid = target.Guid;
            if (Me.IsWithinMeleeRangeOf(target) && Me.IsMoving && GeneralSettings.Instance.GeneralMovement && !Managers.Hotkeys.RotationOnlyOn)
            {
                return(await CommonCoroutines.StopMoving());
            }
            if (!lastTimeFaced.IsRunning)
            {
                lastTimeFaced.Start();
            }
            else
            {
                lastTimeFaced.Restart();
            }
            await Coroutine.Yield();

            return(true);
        }
Example #10
0
        public void Query_GetMailList(WoWGuid mailbox_guid)
        {
            WoWWriter wr = new WoWWriter(OpCode.CMSG_GET_MAIL_LIST);

            wr.Write(mailbox_guid.GetOldGuid());
            Send(wr.ToArray());
        }
Example #11
0
 public ObjectBase(Core core, WoWGuid guid, TypeID typeid)
 {
     Core = core;
     Guid = guid;
     TypeID = typeid;
     UpdateFields = new Dictionary<int, UpdateField>();
 }
Example #12
0
        private void CheckCurrentPet()
        {
            if (!SingularSettings.Debug)
            {
                return;
            }

            if (Me.Pet == null)
            {
                if (_lastPetGuid.IsValid)
                {
                    _lastPetGuid = WoWGuid.Empty;
                    if (SingularSettings.Debug)
                    {
                        Logger.WriteDebug("YourCurrentPet: (none)");
                    }
                }
            }
            else
            {
                // check for change in current pet
                if (Me.Pet.Guid != _lastPetGuid || Me.Pet.IsAlive != _lastPetAlive)
                {
                    _lastPetGuid  = Me.Pet.Guid;
                    _lastPetAlive = Me.Pet.IsAlive;
                    Logger.WriteDebug("YourCurrentPet: #{0}, Name={1}, Level={2}, Type={3}, Talents={4}", Me.PetNumber, Me.Pet.SafeName(), Me.Pet.Level, Me.Pet.CreatureType, PetManager.GetPetTalentTree());
                }

                // now check pets target
                CheckTarget(Me.Pet.CurrentTarget, ref _lastCheckPetsTargetGuid, "PetsCurrentTarget", (x) => { });
            }
        }
Example #13
0
 public TargetAuraMaxTimeLeftCondition(TargetType target, int auraId, WoWGuid creatorGuid, TimeSpan maxTimeLeft)
 {
     Target      = target;
     AuraId      = auraId;
     CreatorGuid = creatorGuid;
     MaxTimeLeft = maxTimeLeft;
 }
Example #14
0
        private void TeleportHandler(WoWReader wr)
        {
            float x, y, z, orient;
            byte  mask = wr.ReadByte();

            WoWGuid guid = new WoWGuid(mask, wr.ReadBytes(WoWGuid.BitCount8(mask)));

            wr.ReadUInt32(); // flags

            wr.ReadUInt32(); // time?
            wr.ReadByte();   // unk 2.3.0

            wr.ReadSingle(); // unk2
            x      = wr.ReadSingle();
            y      = wr.ReadSingle();
            z      = wr.ReadSingle();
            orient = wr.ReadSingle();
            wr.ReadUInt16(); // unk3
            wr.ReadByte();   // unk4
            BoogieCore.Log(LogType.SystemDebug, "Got teleport to: {0} {1} {2} {3}", x, y, z, orient);

            BoogieCore.world.getPlayerObject().SetCoordinates(new Coordinate(x, y, z, orient));

            WoWWriter ww = new WoWWriter(OpCode.MSG_MOVE_TELEPORT_ACK);

            ww.Write(BoogieCore.world.getPlayerObject().GUID.GetOldGuid());
            Send(ww.ToArray());
            SendMoveHeartBeat(BoogieCore.world.getPlayerObject().GetCoordinates());
        }
Example #15
0
        private async static Task <bool> PoolSafetyChecks(WoWGameObject pool)
        {
            if (pool == null || !pool.IsValid)
            {
                BotPoi.Clear();
                return(true);
            }

            if (pool.Guid != _lastVisitedPoolGuid)
            {
                _lastVisitedPoolGuid = pool.Guid;
                TimeAtPoolTimer.Restart();
            }

            // safety check. if spending more than 5 mins at pool than black list it.
            if (TimeAtPoolTimer.ElapsedMilliseconds >= AutoAnglerSettings.Instance.MaxTimeAtPool * 60000)
            {
                Utility.BlacklistPool(pool, TimeSpan.FromMinutes(10), "Spend too much time at pool");
                return(true);
            }

            // move to another spot if we have too many failed casts
            if (_castCounter >= AutoAnglerSettings.Instance.MaxFailedCasts)
            {
                AutoAnglerBot.Log("Moving to a new fishing location since we have {0} failed casts",
                                  _castCounter);
                _castCounter = 0;
                RemovePointAtTop(pool);
                return(true);
            }
            return(false);
        }
Example #16
0
        private WoWUnit FindTarget(Vector3 location)
        {
            WoWUnit target = null;

            if (_targetGuid.IsValid)
            {
                target = ObjectManager.GetObjectByGuid <WoWUnit>(_targetGuid);
            }

            if (target != null && target.IsAlive
                // if rescuing NPCs then we don't want to include those rescued by other players.
                && (DropPassengerButton == 0 || !IsRescuedByOtherPlayer(target)) &&
                !Blacklist.Contains(target, BlacklistFlags.Combat | BlacklistFlags.Interact))
            {
                return(target);
            }

            target = ObjectManager.GetObjectsOfType <WoWUnit>()
                     .Where(u => !u.IsDead && NpcList.Contains((int)u.Entry) &&
                            !Blacklist.Contains(u, BlacklistFlags.Combat | BlacklistFlags.Interact)
                            // if rescuing NPCs then we don't want to include those rescued by other players.
                            && (DropPassengerButton == 0 || !IsRescuedByOtherPlayer(target)) &&
                            u.Location.Distance2D(location) < NpcScanRange)
                     .OrderBy(u => location.Distance2DSquared(u.Location))
                     .FirstOrDefault();

            if (target != null)
            {
                _targetGuid = target.Guid;
            }

            return(target);
        }
        public void Handle_NameQuery(PacketIn packet)
        {
            WoWGuid guid = new WoWGuid(packet.ReadUInt64());
            string  name = packet.ReadString();

            packet.ReadByte();
            Race      Race   = (Race)packet.ReadUInt32();
            Gender    Gender = (Gender)packet.ReadUInt32();
            Classname Class  = (Classname)packet.ReadUInt32();


            if (objectMgr.objectExists(guid))        // Update existing Object
            {
                Object obj = objectMgr.getObject(guid);
                obj.Name = name;
                objectMgr.updateObject(obj);
            }
            else                    // Create new Object        -- FIXME: Add to new 'names only' list?
            {
                Object obj = new Object(guid);
                obj.Name = name;
                objectMgr.addObject(obj);

                /* Process chat message if we looked them up now */
                for (int i = 0; i < ChatQueued.Count; i++)
                {
                    ChatQueue message = (ChatQueue)ChatQueued[i];
                    if (message.GUID.GetOldGuid() == guid.GetOldGuid())
                    {
                        Log.WriteLine(LogType.Chat, "[{1}] {0}", message.Message, name);
                        ChatQueued.Remove(message);
                    }
                }
            }
        }
        public void QueryName(WoWGuid guid)
        {
            PacketOut packet = new PacketOut(WorldServerOpCode.CMSG_NAME_QUERY);

            packet.Write(guid.GetNewGuid());
            Send(packet);
        }
Example #19
0
    public void QueryName(WoWGuid guid, ref World manager)
    {
        PacketWriter packet = new PacketWriter(WorldServerOpCode.CMSG_NAME_QUERY);

        packet.Write(guid.GetNewGuid());
        //login.wClient.Send(packet);
    }
 private static void RemoveIfExpired(WoWGuid id)
 {
     if (s_spellBlacklistDict.ContainsKey(id) &&
         s_spellBlacklistDict[id].TimeStamp + s_spellBlacklistDict[id].Duration <= DateTime.Now)
     {
         s_spellBlacklistDict.Remove(id);
     }
 }
        public void ObjectQuery(WoWGuid guid, UInt32 entry)
        {
            PacketOut packet = new PacketOut(WorldServerOpCode.CMSG_Object_QUERY);

            packet.Write(entry);
            packet.Write(guid.GetNewGuid());
            Send(packet);
        }
Example #22
0
    public void ObjectQuery(WoWGuid guid, UInt32 entry, ref World manager)
    {
        PacketWriter packet = new PacketWriter(WorldServerOpCode.CMSG_GAMEOBJECT_QUERY);

        packet.Write(entry);
        packet.Write(guid.GetNewGuid());
        //login.wClient.Send(packet);
    }
Example #23
0
    public void CreatureQuery(WoWGuid guid, UInt32 entry, ref World manager)
    {
        PacketWriter packet = new PacketWriter(WorldServerOpCode.CMSG_CREATURE_QUERY);

        packet.Write(entry);
        packet.Write(guid.GetNewGuid());
        //login.wClient.Send(packet);
    }
        public void CreatureQuery(WoWGuid guid, UInt32 entry)
        {
            PacketOut packet = new PacketOut(WorldServerOpCode.CMSG_CREATURE_QUERY);

            packet.Write(entry);
            packet.Write(guid.GetNewGuid());
            Send(packet);
        }
Example #25
0
        public static WoWUnit FindStatue()
        {
            const uint BLACK_OX_STATUE = 61146;
            WoWGuid    guidMe          = Me.Guid;

            return(ObjectManager.GetObjectsOfType <WoWUnit>()
                   .FirstOrDefault(u => u.Entry == BLACK_OX_STATUE && u.CreatedByUnitGuid == guidMe));
        }
        public WoWWriter GameObjectQuery(WoWGuid guid, UInt32 entry)
        {
            WoWWriter wr = new WoWWriter(OpCode.CMSG_GAMEOBJECT_QUERY);

            wr.Write(entry);
            wr.Write(guid.GetOldGuid());
            return(wr);
        }
        public WoWWriter CreatureQuery(WoWGuid guid, UInt32 entry)
        {
            WoWWriter wr = new WoWWriter(OpCode.CMSG_CREATURE_QUERY);

            wr.Write(entry);
            wr.Write(guid.GetOldGuid());
            return(wr);
        }
Example #28
0
        public static WoWUnit FindStatue()
        {
            const uint JADE_SERPENT_STATUE = 60849;
            WoWGuid    guidMe = Me.Guid;

            return(ObjectManager.GetObjectsOfType <WoWUnit>()
                   .FirstOrDefault(u => u.Entry == JADE_SERPENT_STATUE && u.CreatedByUnitGuid == guidMe));
        }
Example #29
0
        /// <summary>Removes an Object from the World.</summary>
        /// <param name="guid">Guid of the objects to delete.</param>
        public void delObject(WoWGuid guid)
        {
            int i = getObjectIndex(guid);

            if (i >= 0)
            {
                mObjects.RemoveAt(i);
            }
        }
Example #30
0
 public ObjectBase GetObjectByWoWGuid(WoWGuid guid)
 {
     var key = guid.Full;
     ObjectBase obj = null;
     if (Objects[CurrentPlayerMapID].TryGetValue(key, out obj))
         return obj;
     else
         return null;
 }
Example #31
0
        public void Add(WoWGuid guid, TimeSpan timeSpan)
        {
            if (_stopWatchForSweeping.Elapsed > _maxSweepTime)
            {
                RemoveExpired();
            }

            _blackList[guid] = DateTime.Now.Add(timeSpan);
        }
Example #32
0
        public bool Contains(WoWGuid guid)
        {
            if (_stopWatchForSweeping.Elapsed > _maxSweepTime)
            {
                RemoveExpired();
            }

            return(_blackList.ContainsKey(guid));
        }
Example #33
0
 /// <summary>Returns whether a certain Object already exists in the World.</summary>
 /// <param name="o">Objects guid to check for.</param>
 public Boolean objectExists(WoWGuid guid)
 {
     if (getObjectIndex(guid) >= 0)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Example #34
0
        public bool Contains(WoWGuid guid)
        {
            DateTime expiry;

            if (_blackList.TryGetValue(guid, out expiry))
            {
                return(expiry > DateTime.Now);
            }

            return(false);
        }
        private static WoWGuid ArgToGuid(object o)
        {
            string  s = o.ToString();
            WoWGuid guid;

            if (!WoWGuid.TryParseFriendly(s, out guid))
            {
                guid = WoWGuid.Empty;
            }

            return(guid);
        }
Example #36
0
 // Find Object on list by GUID
 private int getObjectIndex(WoWGuid guid)
 {
     for (int i = 0; i < mObjects.Count; i++)
     {
         Object obj = mObjects[i];
         if (obj.GUID.GetOldGuid() == guid.GetOldGuid())
         {
             return(i);
         }
     }
     return(-1);
 }
Example #37
0
        public void HandleMonsterMove(PacketIn packet)
        {
            byte mask = packet.ReadByte();

            WoWGuid guid = new WoWGuid(mask, packet.ReadBytes(WoWGuid.BitCount8(mask)));

            Object obj = objectMgr.getObject(guid);

            if (obj != null)
            {
                obj.Position = new Coordinate(packet.ReadFloat(), packet.ReadFloat(), packet.ReadFloat());
            }
        }
Example #38
0
        protected override void DefaultIncludeTargetsFilter(List<WoWObject> incomingUnits, HashSet<WoWObject> outgoingUnits)
        {
            bool foundMe = false;
            bool isHorde = StyxWoW.Me.IsHorde;
            WoWGuid focusGuid = Me.FocusedUnitGuid;
            bool foundFocus = false;

            foreach (WoWObject incomingUnit in incomingUnits)
            {
                try
                {
                    if (incomingUnit.IsMe)
                        foundMe = true;
                    else if (incomingUnit.Guid == focusGuid)
                        foundFocus = true;
                    else if (SingularSettings.Debug && incomingUnit.Guid != lastCompanion && SingularSettings.Instance.IncludeCompanionssAsHealTargets && incomingUnit is WoWUnit && incomingUnit.ToUnit().SummonedByUnitGuid == Me.Guid)
                    {
                        // temporary code only used to verify a companion found!
                        lastCompanion = incomingUnit.Guid;
                        Logger.WriteDebug( Color.White, "HealTargets: including found companion {0}#{1}", incomingUnit.Name, incomingUnit.Entry);
                    }

                    outgoingUnits.Add(incomingUnit);

                    var unit = incomingUnit as WoWUnit;
                    if (SingularSettings.Instance.IncludePetsAsHealTargets && unit != null && unit.GotAlivePet)
                        outgoingUnits.Add(unit.Pet);
                }
                catch (System.AccessViolationException)
                {
                }
                catch (Styx.InvalidObjectPointerException)
                {
                }
            }

            if (!foundMe)
            {
                outgoingUnits.Add(Me);
                if (SingularSettings.Instance.IncludePetsAsHealTargets && Me.GotAlivePet)
                    outgoingUnits.Add(Me.Pet);
            }

            /*
            if (StyxWoW.Me.GotTarget() && StyxWoW.Me.CurrentTarget.IsFriendly && !StyxWoW.Me.CurrentTarget.IsPlayer)
                outgoingUnits.Add(StyxWoW.Me.CurrentTarget);
            */
            try
            {
                if (Me.FocusedUnit != null && Me.FocusedUnit.IsFriendly )
                {
                    if (!foundFocus)
                    {
                        outgoingUnits.Add(StyxWoW.Me.FocusedUnit);
                        if (Me.FocusedUnit.GotAlivePet)
                            outgoingUnits.Add(Me.FocusedUnit.Pet);
                    }

                    if (SingularSettings.Debug && Me.FocusedUnit.Guid != lastFocus)
                    {
                        lastFocus = Me.FocusedUnit.Guid;
                        Logger.WriteDebug(Color.White, "HealTargets: including focused unit {0}#{1}", Me.FocusedUnit.Name, Me.FocusedUnit.Entry);
                    }
                }
            }
            catch
            {
            }
        }
 public TargetDoesNotHaveAuraCondition(TargetType target, int auraId, WoWGuid creatorGuid)
 {
     Target = target;
     AuraId = auraId;
     CreatorGuid = creatorGuid;
 }
Example #40
0
 public void SetCurrentPlayerWoWGuid(WoWGuid currentplayerwowguid)
 {
     CurrentPlayerWoWGuid = currentplayerwowguid;
     CurrentPlayer = new PlayerMe(this, currentplayerwowguid, TypeID.TYPEID_PLAYER);
 }
 private void UpdateFieldValues(int index, WoWGuid guid)
 {
     var obj = Core.GetObjectByWoWGuid(guid);
     UpdateFieldValues(index, obj);
 }
Example #42
0
        private void CheckCurrentPet()
        {
            if (!SingularSettings.Debug)
                return;

            if (Me.Pet == null)
            {
                if (_lastPetGuid.IsValid)
                {
                    _lastPetGuid = WoWGuid.Empty;
                    if (SingularSettings.Debug)
                        Logger.WriteDebug("YourCurrentPet: (none)");
                }
            }
            else
            {
                // check for change in current pet
                if ( Me.Pet.Guid != _lastPetGuid || Me.Pet.IsAlive != _lastPetAlive)
                {
                    _lastPetGuid = Me.Pet.Guid;
                    _lastPetAlive = Me.Pet.IsAlive;
                    Logger.WriteDebug("YourCurrentPet: #{0}, Name={1}, Level={2}, Type={3}, Talents={4}", Me.PetNumber, Me.Pet.SafeName(), Me.Pet.Level, Me.Pet.CreatureType, PetManager.GetPetTalentTree());
                }

                // now check pets target
                CheckTarget(Me.Pet.CurrentTarget, ref _lastCheckPetsTargetGuid, "PetsCurrentTarget", (x) => { });

            }
        }
Example #43
0
 public Item(Core core, WoWGuid guid, TypeID typeid)
     : base(core, guid, typeid)
 {
 }
Example #44
0
        public static bool Passive()
        {
            if (lastPetAttack != WoWGuid.Empty)
                lastPetAttack = WoWGuid.Empty;

            if (StyxWoW.Me.Pet == null || StyxWoW.Me.Pet.CurrentTargetGuid == WoWGuid.Empty)
                return false;

            if (StyxWoW.Me.Pet.CurrentTarget == null)
                Logger.Write(LogColor.Hilite, "/petpassive");
            else
                Logger.Write(LogColor.Hilite, "/petpassive (stop attacking {0})", StyxWoW.Me.Pet.CurrentTarget.SafeName());

            PetManager.CastPetAction("Passive");
            return true;
        }
Example #45
0
        public Player(Core core, WoWGuid guid, TypeID typeid)
            : base(core, guid, typeid)
        {

        }
Example #46
0
 public DynamicObject(Core core, WoWGuid guid, TypeID typeid)
     : base(core, guid, typeid)
 {
 }
        private static Composite CreateLogTargetChanges(BehaviorType behav, string sType)
        {
            return new Action(r =>
                {
                    // there are moments where CurrentTargetGuid != 0 but CurrentTarget == null. following
                    // .. tries to handle by only checking CurrentTarget reference and treating null as guid = 0
                    if (Me.CurrentTargetGuid != _guidLastTarget)
                    {
                        if (!Me.GotTarget())
                        {
                            if (_guidLastTarget.IsValid)
                            {
                                if (SingularSettings.Debug)
                                    Logger.WriteDebug(sType + " CurrentTarget now: (null)");
                                _guidLastTarget = WoWGuid.Empty;
                            }
                        }
                        else
                        {
                            _guidLastTarget = Me.CurrentTargetGuid;
                            TargetTimeoutTimerReset();
                            LogTargetChanges(behav, sType);
                        }
                    }
                    // testing for Me.GotTarget() also to address objmgr not resolving guid yet to avoid NullRef
                    else if (Me.GotTarget() && Me.CurrentTarget.IsValid && !MovementManager.IsMovementDisabled && SingularRoutine.CurrentWoWContext == WoWContext.Normal)
                    {
                        // make sure we get into attack range within reasonable time
                        if (((!Me.IsMelee() && Me.CurrentTarget.SpellDistance() < 40) || Me.CurrentTarget.IsWithinMeleeRange) && Movement.InLineOfSpellSight(Me.CurrentTarget, 5000))
                        {
                            TargetTimeoutTimerReset();
                        }
                        // otherwise blacklist and move on
                        else if (TargetTimeoutTimer.IsFinished && SingularSettings.Instance.MoveToTargetTimeout > 0)
                        {
                            bool haveAggro = Me.CurrentTarget.Aggro || (Me.GotAlivePet && Me.CurrentTarget.PetAggro);
                            BlacklistFlags blf = !haveAggro ? BlacklistFlags.Pull : BlacklistFlags.Pull | BlacklistFlags.Combat;
                            if (!Blacklist.Contains(_guidLastTarget, blf))
                            {
                                TimeSpan bltime = haveAggro
                                    ? TimeSpan.FromSeconds(20)
                                    : TimeSpan.FromSeconds(240);

                                string fragment = string.Format(
                                    "{0} out of range/line of sight for {1:F1} seconds",
                                    Me.CurrentTarget.SafeName(),
                                    TargetTimeoutTimer.WaitTime.TotalSeconds
                                    );
                                Logger.Write(Color.HotPink, "{0} Target {1}, blacklisting for {2:c} and clearing {3}",
                                    blf,
                                    fragment,
                                    bltime,
                                    _guidLastTarget == BotPoi.Current.Guid ? "BotPoi" : "Current Target");

                                Blacklist.Add(_guidLastTarget, blf, bltime, "Singular - " + fragment);
                                if (_guidLastTarget == BotPoi.Current.Guid)
                                    BotPoi.Clear("Clearing Blacklisted BotPoi");
                                Me.ClearTarget();
                            }
                        }
                    }

                    return RunStatus.Failure;
                });
        }
 public static void ResetCurrentTarget()
 {
     _guidLastTarget = WoWGuid.Empty;
 }
Example #49
0
        internal static void Pulse()
        {
            if (!NeedsPetSupport)
                return;

            if (StyxWoW.Me.Mounted)
            {
                _wasMounted = true;
            }

            if (_wasMounted && !StyxWoW.Me.Mounted)
            {
                _wasMounted = false;
                PetSummonAfterDismountTimer.Reset();
            }

            if (StyxWoW.Me.GotAlivePet && StyxWoW.Me.Pet != null)
            {
                if (_petGuid != StyxWoW.Me.Pet.Guid)
                {
                    // clear any existing spells
                    PetSpells.Clear();

                    // only load spells if we have one that is non-null
                    // .. as initial load happens before Me.PetSpells is initialized and we were saving 'null' spells
                    if (StyxWoW.Me.PetSpells.Any(s => s.Spell != null || s.Action != WoWPetSpell.PetAction.None))
                    {
                        // save Pet's Guid so we don't have to repeat
                        _petGuid = StyxWoW.Me.Pet.Guid;

                        NeedToCheckPetTauntAutoCast = SingularSettings.Instance.PetAutoControlTaunt;

                        // Cache the list. yea yea, we should just copy it, but I'd rather have shallow copies of each object, rather than a copy of the list.
                        PetSpells.AddRange(StyxWoW.Me.PetSpells);
                        PetSummonAfterDismountTimer.Reset();
                        Logger.WriteDiagnostic("---PetSpells Loaded for: {0} Pet ---", PetManager.GetPetTalentTree());
                        foreach (var sp in PetSpells)
                        {
                            if (sp.Spell == null)
                                Logger.WriteDebug("   {0} spell={1}  Action={0}", sp.ActionBarIndex, sp.ToString(), sp.Action.ToString());
                            else
                                Logger.WriteDebug("   {0} spell={1} #{2}", sp.ActionBarIndex, sp.ToString(), sp.Spell.Id);
                        }
                        Logger.WriteDebug(" ");
                    }
                }

                HandleAutoCast();
            }
            else if (_petGuid != WoWGuid.Empty)
            {
                PetSpells.Clear();
                _petGuid = WoWGuid.Empty;
            }
        }
Example #50
0
        private static Composite ShowHealTarget(UnitSelectionDelegate onUnit)
        {
            return
                new Sequence(
                    new DecoratorContinue(
                        ret => onUnit(ret) == null && guidLastHealTarget.IsValid,
                        new Action(ret =>
                        {
                            guidLastHealTarget = WoWGuid.Empty;
                            Logger.WriteDebug(Color.LightGreen, "Heal Target - none");
                            return RunStatus.Failure;
                        })
                        ),

                    new DecoratorContinue(
                        ret => onUnit(ret) != null && guidLastHealTarget != onUnit(ret).Guid,
                        new Action(ret =>
                        {
                            guidLastHealTarget = onUnit(ret).Guid;
                            Logger.WriteDebug(Color.LightGreen, "Heal Target - {0} {1:F1}% @ {2:F1} yds", onUnit(ret).SafeName(), onUnit(ret).HealthPercent, onUnit(ret).Distance);
                            return RunStatus.Failure;
                        })),

                    new Action(ret => { return RunStatus.Failure; })
                    );
        }
Example #51
0
        /// <summary>
        /// selects best Earth Shield target
        /// </summary>
        /// <returns></returns>
        private static WoWUnit GetBestEarthShieldTargetBattlegrounds()
        {
            #if SUPPORT_MOST_IN_NEED_EARTHSHIELD_LOGIC
            var target = Unit.NearbyGroupMembers
                .Where(u => IsValidEarthShieldTarget(u.ToUnit()))
                .Select(u => new { Unit = u, Health = u.HealthPercent, EnemyCount = Unit.NearbyUnfriendlyUnits.Count(e => e.CurrentTargetGuid == u.Guid)})
                .OrderByDescending(v => v.EnemyCount)
                .ThenBy(v => v.Health )
                .FirstOrDefault();

            if (target == null)
            {
                guidLastEarthShield = Me.Guid;
            }
            else if (guidLastEarthShield != target.Unit.Guid)
            {
                guidLastEarthShield = target.Unit.Guid;
                Logger.WriteDebug("Best Earth Shield Target appears to be: {0} @ {1:F0}% with {2} attackers", target.Unit.SafeName(), target.Health, target.EnemyCount);
            }

            return target == null ? Me : target.Unit;
            #else
            return Me;
            #endif
        }
Example #52
0
        /// <summary>
        /// selects best Earth Shield target
        /// </summary>
        /// <returns></returns>
        private static WoWUnit GetBestEarthShieldTargetInstance()
        {
            WoWUnit target = null;

            if ( HealerManager.Instance.TargetList.Any(m => m.HasMyAura("Earth Shield")))
                return null;

            if (IsValidEarthShieldTarget(RaFHelper.Leader))
                target = RaFHelper.Leader;
            else
            {
                target = Group.Tanks.FirstOrDefault(t => IsValidEarthShieldTarget(t));
                if (Me.Combat && target == null)
                {
                    target = HealerManager.Instance.TargetList.Where(u => u.Combat && IsValidEarthShieldTarget(u))
                        .OrderByDescending(u => u.MaxHealth )
                        .FirstOrDefault();
                }
            }

            guidLastEarthShield = target != null ? target.Guid : WoWGuid.Empty;
            return target;
        }
Example #53
0
        private void CheckTarget(WoWUnit unit, ref WoWGuid prevGuid, string description, OnTargetChange onchg)
        {
            // there are moments where CurrentTargetGuid != 0 but CurrentTarget == null. following
            // .. tries to handle by only checking CurrentTarget reference and treating null as guid = 0
            if (unit == null)
            {
                if (prevGuid.IsValid)
                {
                    prevGuid = WoWGuid.Empty;
                    onchg(unit);
                    if (SingularSettings.Debug)
                        Logger.WriteDebug(description + ": changed to: (null)");
                }
            }
            else if (unit.Guid != prevGuid)
            {
                prevGuid = unit.Guid;
                onchg(unit);
                if (SingularSettings.Debug)
                {
                    //Logger.WriteDebug( "GuidInfo: {0}", unit.Guid.ToString());
                    //Logger.WriteDebug("GuidInfo: {0:X4} {1:X4} {2:X4} {3:X4}", unit.Guid.Highest, unit.Guid.Higher, unit.Guid.Lower, unit.Guid.Lowest);
                    string info = "";
                    if (Styx.CommonBot.POI.BotPoi.Current.Guid == Me.CurrentTargetGuid)
                        info += string.Format(", IsBotPoi={0}", Styx.CommonBot.POI.BotPoi.Current.Type);

                    if (Styx.CommonBot.Targeting.Instance.TargetList.Contains(Me.CurrentTarget))
                        info += string.Format(", TargetIndex={0}", Styx.CommonBot.Targeting.Instance.TargetList.IndexOf(Me.CurrentTarget) + 1);

                    string playerInfo = "N";
                    if (unit.IsPlayer)
                    {
                        WoWPlayer p = unit.ToPlayer();
                        playerInfo = string.Format("Y, Friend={0}, IsPvp={1}, CtstPvp={2}, FfaPvp={3}", Me.IsHorde == p.IsHorde, p.IsPvPFlagged, p.ContestedPvPFlagged, p.IsFFAPvPFlagged);
                    }
                    else
                    {
                        info += string.Format(", creature={0}, tagme={1}, tagother={2}, tapall={3}",
                            unit.CreatureType,
                            unit.TaggedByMe.ToYN(),
                            unit.TaggedByOther.ToYN(),
                            unit.TappedByAllThreatLists.ToYN()
                            );
                    }

                    Logger.WriteDebug(description + ": changed to: {0} lvl={1} h={2:F1}%, maxh={3}, d={4:F1} yds, box={5:F1}, boss={6}, trivial={7}, player={8}, attackable={9}, neutral={10}, hostile={11}, entry={12}, faction={13}, loss={14}, facing={15}, blacklist={16}, combat={17}, flying={18}, abovgrnd={19}" + info,
                        unit.SafeName(),
                        unit.Level,
                        unit.HealthPercent,
                        unit.MaxHealth,
                        unit.Distance,
                        unit.CombatReach,
                        unit.IsBoss().ToYN(),
                        unit.IsTrivial().ToYN(),
                        playerInfo,

                        unit.Attackable.ToYN(),
                        unit.IsNeutral().ToYN(),
                        unit.IsHostile.ToYN(),
                        unit.Entry,
                        unit.FactionId,
                        unit.InLineOfSpellSight.ToYN(),
                        Me.IsSafelyFacing(unit).ToYN(),
                        Blacklist.Contains(unit.Guid, BlacklistFlags.Combat).ToYN(),
                        unit.Combat.ToYN(),
                        unit.IsFlying.ToYN(),
                        unit.IsAboveTheGround().ToYN()
                        );
                }
            }
        }
Example #54
0
 private static string DoubleCastKey(WoWGuid guid, string spellName)
 {
     return guid + "-" + spellName;
 }
Example #55
0
 public Areatrigger(Core core, WoWGuid guid, TypeID typeid)
     : base(core, guid, typeid)
 {
 }
Example #56
0
 public Unit(Core core, WoWGuid guid, TypeID typeid)
     : base(core, guid, typeid)
 {
     PhaseMask = core.CurrentPlayerPhaseMask;
     FactionInfos = new Dictionary<int, CacheObjects.FactionInfo>();
 }
 private void UpdateMovement(int index, TypeID typeid, WoWGuid guid)
 {
     var obj = Core.GetObjectByWoWGuid(guid);
     UpdateMovement(index, obj, typeid);
 }
Example #58
0
        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            // Since we hooked this in ctor, make sure we are the selected CC
            if (RoutineManager.Current.Name != SingularRoutine.Instance.Name)
                return;

            // convert args to usable form
            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);
            bool itWasDamage = false;

            if (TrackDamage || SingularRoutine.CurrentWoWContext == WoWContext.Normal)
            {
                if (e.DestGuid == StyxWoW.Me.Guid && e.SourceGuid != StyxWoW.Me.Guid)
                {
                    long damageAmount = 0;
                    switch (e.EventName)
                    {
                        case "SWING_DAMAGE":
                            itWasDamage = true;
                            damageAmount = (long)e.Args[11];
                            Logger.WriteDebug("HandleCombatLog(Damage): {0} = {1}", e.EventName, damageAmount);
                            break;

                        case "SPELL_DAMAGE":
                        case "SPELL_PERIODIC_DAMAGE":
                        case "RANGE_DAMAGE":
                            itWasDamage = true;
                            damageAmount = (long)e.Args[14];
                            break;
                    }

                    if (TrackDamage)
                    {
                        if (itWasDamage)
                            Logger.WriteDebug("HandleCombatLog(Damage): {0} = {1}", e.EventName, damageAmount);
                        else
                            LogUndesirableEvent("On Character", e);

                        if (damageAmount > 0)
                        {
                            DamageHistory.Enqueue(new Damage(DateTime.UtcNow, damageAmount));
                        }
                    }

                    if (itWasDamage && SingularRoutine.CurrentWoWContext == WoWContext.Normal)
                    {
                        WoWUnit enemy = e.SourceUnit;
                        if (Unit.ValidUnit(enemy) && enemy.IsPlayer)
                        {
                            Logger.WriteDiagnostic("GankDetect: received {0} src={1} dst={2}", args.EventName, e.SourceGuid, e.DestGuid);

                            // if (guidLastEnemy != enemy.Guid || (TimeLastAttackedByEnemyPlayer - DateTime.UtcNow).TotalSeconds > 30)
                            {
                                guidLastEnemy = enemy.Guid;
                                string extra = "";
                                if (e.Args.GetUpperBound(0) >= 12)
                                    extra = string.Format(" using {0}", e.SpellName);

                                AttackedWithSpellSchool = WoWSpellSchool.None;
                                if (e.Args.GetUpperBound(0) >= 12)
                                    AttackedWithSpellSchool = e.SpellSchool;

                                Logger.WriteDiagnostic("GankDetect: attacked by Level {0} {1}{2}", enemy.Level, enemy.SafeName(), extra);
                                if (SingularSettings.Instance.TargetWorldPvpRegardless && (BotPoi.Current == null || BotPoi.Current.Guid != enemy.Guid))
                                {
                                    Logger.Write(LogColor.Hilite, "GankDetect: setting {0} as BotPoi Kill Target", enemy.SafeName());
                                    BotPoi.Current = new BotPoi(enemy, PoiType.Kill);
                                }
                            }

                            AttackingEnemyPlayer = enemy;
                            TimeLastAttackedByEnemyPlayer = DateTime.UtcNow;
                        }
                    }
                }

                return;
            }

            // Logger.WriteDebug("[CombatLog] " + e.Event + " - " + e.SourceName + " - " + e.SpellName);

            switch (e.Event)
            {
                default:
                    LogUndesirableEvent( "From Character", e );
                    break;

                // spell_cast_failed only passes filter in Singular debug mode
                case "SPELL_CAST_FAILED":
                    Logger.WriteDiagnostic("[CombatLog] {0} {1}#{2} failure: '{3}'", e.Event, e.Spell.Name, e.SpellId, e.Args[14] );
                    if ( e.Args[14].ToString() == LocalizedLineOfSightFailure )
                    {
                        WoWGuid guid = WoWGuid.Empty;
                        try
                        {
                            LastLineOfSightTarget = e.DestUnit;
                            guid = LastLineOfSightTarget == null ? WoWGuid.Empty : LastLineOfSightTarget.Guid;
                        }
                        catch
                        {
                        }

                        if (!guid.IsValid)
                        {
                            Logger.WriteFile("[CombatLog] no valid destunit so using CurrentTarget");
                            LastLineOfSightTarget = StyxWoW.Me.CurrentTarget;
                            guid = StyxWoW.Me.CurrentTargetGuid;
                        }

                        LastLineOfSightFailure = DateTime.UtcNow;
                        Logger.WriteFile("[CombatLog] cast failed due to los reported at {0} on target {1:X}", LastLineOfSightFailure.ToString("HH:mm:ss.fff"), e.DestGuid );
                    }
                    else if (e.Args[14].ToString() == LocalizedUnitNotInfrontFailure )
                    {
                        WoWGuid guid = e.DestGuid;
                        LastUnitNotInfrontFailure = DateTime.UtcNow;
                        if (guid.IsValid && guid != WoWGuid.Empty)
                        {
                            LastUnitNotInfrontGuid = guid;
                            Logger.WriteFile("[CombatLog] not facing SpellTarget [{0}] at {1}", LastUnitNotInfrontGuid, LastUnitNotInfrontFailure.ToString("HH:mm:ss.fff"));
                        }
                        else
                        {
                            LastUnitNotInfrontGuid = Spell.LastSpellTarget;
                            Logger.WriteFile("[CombatLog] not facing LastTarget [{0}] at {1}", LastUnitNotInfrontGuid, LastUnitNotInfrontFailure.ToString("HH:mm:ss.fff"), guid);
                        }
                    }
                    else if (!MovementManager.IsMovementDisabled && StyxWoW.Me.Class == WoWClass.Warrior && e.Args[14].ToString() == LocalizedNoPathAvailableFailure)
                    {
                        LastNoPathFailure = DateTime.UtcNow;
                        LastNoPathGuid = StyxWoW.Me.CurrentTargetGuid;
                        if (!StyxWoW.Me.GotTarget())
                            Logger.WriteFile("[CombatLog] cast failed - no path available to current target");
                        else
                            Logger.WriteFile("[CombatLog] cast failed - no path available to {0}, heightOffGround={1}, pos={2}",
                                StyxWoW.Me.CurrentTarget.SafeName(),
                                StyxWoW.Me.CurrentTarget.HeightOffTheGround(),
                                StyxWoW.Me.CurrentTarget.Location
                                );
                    }
                    else if (!SingularRoutine.IsManualMovementBotActive && (StyxWoW.Me.Class == WoWClass.Druid || StyxWoW.Me.Class == WoWClass.Shaman))
                    {
                        if (LocalizedShapeshiftMessages.ContainsKey(e.Args[14].ToString()))
                        {
                            string symbolicName = LocalizedShapeshiftMessages[e.Args[14].ToString()];
                            SuppressShapeshiftUntil = DateTime.UtcNow.Add( TimeSpan.FromSeconds(30));
                            Logger.Write(LogColor.Cancel, "/cancel{0} - due to Shapeshift Error '{1}' on cast, suppress form for {2:F1} seconds", StyxWoW.Me.Shapeshift.ToString().CamelToSpaced(), symbolicName, (SuppressShapeshiftUntil - DateTime.UtcNow).TotalSeconds);
                            Lua.DoString("CancelShapeshiftForm()");
                        }
                    }
                    else if (StyxWoW.Me.Class == WoWClass.Rogue && SingularSettings.Instance.Rogue().UsePickPocket)
                    {
                        if (e.Args[14].ToString() == LocalizedNoPocketsToPickFailure)
                        {
                            HandleRogueNoPocketsError();
                        }
                    }
                    break;

            #if SOMEONE_USES_LAST_SPELL_AT_SOME_POINT
                case "SPELL_AURA_APPLIED":
                case "SPELL_CAST_SUCCESS":
                    if (e.SourceGuid != StyxWoW.Me.Guid)
                    {
                        return;
                    }

                    // Update the last spell we cast. So certain classes can 'switch' their logic around.
                    Spell.LastSpellCast = e.SpellName;
                    //Logger.WriteDebug("Successfully cast " + Spell.LastSpellCast);

                    // following commented block should not be needed since rewrite of Pet summon
                    //
                    //// Force a wait for all summoned minions. This prevents double-casting it.
                    //if (StyxWoW.Me.Class == WoWClass.Warlock && e.SpellName.StartsWith("Summon "))
                    //{
                    //    StyxWoW.SleepForLagDuration();
                    //}
                    break;
            #endif

                case "SWING_MISSED":
                    if (e.Args[11].ToString() == "EVADE")
                    {
                        HandleEvadeBuggedMob(args, e);
                    }
                    else if (e.Args[11].ToString() == "IMMUNE")
                    {
                        WoWUnit unit = e.DestUnit;
                        if (unit != null && !unit.IsPlayer)
                        {
                            Logger.WriteDebug("{0} is immune to Physical spell school", unit.Name);
                            SpellImmunityManager.Add(unit.Entry, WoWSpellSchool.Physical );
                        }
                    }
                    break;

                case "SPELL_MISSED":
                case "RANGE_MISSED":
                    // Why log misses?  Because users of classes with DoTs testing on training dummies
                    // .. that they don't have enough +Hit for will get DoT spam.  This allows easy
                    // .. diagnosis of false reports of rotation issues where a user simply isn't geared
                    // .. this happens more at the beginning of an expansion especially
                    if (SingularSettings.Debug)
                    {
                        Logger.WriteDebug(
                            "[CombatLog] {0} {1}#{2} {3}",
                            e.Event,
                            e.Spell.Name,
                            e.SpellId,
                            e.Args[14]
                            );
                    }

                    if (e.Args[14].ToString() == "EVADE")
                    {
                        HandleEvadeBuggedMob(args, e);
                    }
                    else if (e.Args[14].ToString() == "IMMUNE")
                    {
                        WoWUnit unit = e.DestUnit;
                        if (unit != null && !unit.IsPlayer)
                        {
                            Logger.WriteDebug("{0} is immune to {1} spell school", unit.Name, e.SpellSchool);
                            SpellImmunityManager.Add(unit.Entry, e.SpellSchool);
                        }

                        if (StyxWoW.Me.Class == WoWClass.Rogue && e.SpellId == 6770)
                        {
                            WoWUnit unitImmune = unit;
                            if (unitImmune == null)
                                unitImmune = ObjectManager.GetObjectByGuid<WoWUnit>(Singular.ClassSpecific.Rogue.Common.lastSapTarget);

                            Singular.ClassSpecific.Rogue.Common.AddEntryToSapImmuneList(unitImmune);
                        }
                    }
                    break;

                case "UNIT_DIED":
                    try
                    {
                        WoWUnit corpse = e.SourceUnit;
                        WoWPartyMember pm = Unit.GroupMemberInfos.First( m => m.Guid == corpse.Guid);
                        Logger.WriteDiagnostic( "Combat Log: UNIT_DIED - Role={0} {1}", pm.Role & (~WoWPartyMember.GroupRole.Leader), corpse.SafeName());
                    }
                    catch
                    {
                    }
                    break;
            }
        }
Example #59
0
 public GameObject(Core core, WoWGuid guid, TypeID typeid)
     : base(core, guid, typeid)
 {
     PhaseMask = core.CurrentPlayerPhaseMask;
     MapID = core.CurrentPlayerMapID;
 }
Example #60
0
        public static Composite CreateMoveToSphereBehavior(SphereType typ, float range)
        {
            return new Decorator(
                ret => SingularSettings.Instance.MoveToSpheres && !MovementManager.IsMovementDisabled,

                new PrioritySelector(

                    // check we haven't gotten out of range due to fall / pushback / port / etc
                    new Decorator(
                        ret => guidSphere.IsValid&& Me.Location.Distance(locSphere) > range,
                        new Action(ret => { guidSphere = WoWGuid.Empty; locSphere = WoWPoint.Empty; })
                        ),

                    // validate the sphere we are moving to
                    new Action(ret =>
                    {
                        WoWObject sph = FindClosestSphere(typ, range);
                        if (sph == null)
                        {
                            guidSphere = WoWGuid.Empty; locSphere = WoWPoint.Empty;
                            return RunStatus.Failure;
                        }

                        if (sph.Guid == guidSphere)
                            return RunStatus.Failure;

                        guidSphere = sph.Guid;
                        locSphere = sph.Location;
                        timeAbortSphere = DateTime.UtcNow + TimeSpan.FromSeconds(5);
                        Logger.WriteDebug("MoveToSphere: Moving {0:F1} yds to {1} Sphere {2} @ {3}", sph.Distance, typ, guidSphere, locSphere);
                        return RunStatus.Failure;
                    }),

                    new Decorator(
                        ret => DateTime.UtcNow > timeAbortSphere,
                        new Action( ret => {
                            Logger.WriteDebug("MoveToSphere: blacklisting timed out {0} sphere {1} at {2}", typ, guidSphere, locSphere);
                            Blacklist.Add(guidSphere, BlacklistFlags.Combat, TimeSpan.FromMinutes(5));
                            })
                        ),

                    // move to the sphere if out of range
                    new Decorator(
                        ret => guidSphere.IsValid && Me.Location.Distance(locSphere) > 1,
                        Movement.CreateMoveToLocationBehavior(ret => locSphere, true, ret => 0f)
                        ),

                    // pause briefly until its consumed
                    new Wait(
                        1,
                        ret => {
                            WoWObject sph = FindClosestSphere(typ, range);
                            return sph == null || sph.Guid != guidSphere ;
                            },
                        new Action( r => { return RunStatus.Failure; } )
                        ),

                    // still exist?  black list it then
                    new Decorator(
                        ret => {
                            WoWObject sph = FindClosestSphere(typ, range);
                            return sph != null && sph.Guid == guidSphere ;
                            },
                        new Action( ret => {
                            Logger.WriteDebug("MoveToSphere: blacklisting unconsumed {0} sphere {1} at {2}", typ, guidSphere, locSphere);
                            Blacklist.Add(guidSphere, BlacklistFlags.Combat, TimeSpan.FromMinutes(5));
                            })
                        )
                    )
                );
        }