Exemple #1
0
        internal RunStatus TargetMoveTo(CacheObject obj)
        {
            #region DebugInfo
            if (Bot.Settings.Debug.DebugStatusBar)
            {
                string Action = "[Move-";
                switch (obj.targetType.Value)
                {
                case TargetType.Avoidance:
                    Action += "Avoid] ";
                    break;

                case TargetType.Fleeing:
                    Action += "Flee] ";
                    break;

                case TargetType.Backtrack:
                    Action += "BackTrack] ";
                    break;

                case TargetType.LineOfSight:
                    Action += "LOS] ";
                    break;

                case TargetType.Unit:
                    if (Bot.NavigationCache.groupRunningBehavior && Bot.NavigationCache.groupingCurrentUnit != null && Bot.NavigationCache.groupingCurrentUnit == obj)
                    {
                        Action += "Grouping] ";
                    }
                    else
                    {
                        Action += "Combat] ";
                    }

                    break;

                case TargetType.Item:
                case TargetType.Gold:
                case TargetType.Globe:
                    Action += "Pickup] ";
                    break;

                case TargetType.Interactable:
                    Action += "Interact] ";
                    break;

                case TargetType.Container:
                    Action += "Open] ";
                    break;

                case TargetType.Destructible:
                case TargetType.Barricade:
                    Action += "Destroy] ";
                    break;

                case TargetType.Shrine:
                    Action += "Click] ";
                    break;
                }
                Bot.Targeting.Handler.UpdateStatusText(Action);
            }
            #endregion

            // Are we currently incapacitated? If so then wait...
            if (Bot.Character.Data.bIsIncapacitated || Bot.Character.Data.bIsRooted)
            {
                return(RunStatus.Running);
            }

            //Ignore skip ahead cache for LOS movements..
            if (Bot.Settings.Debug.SkipAhead && obj.targetType.Value != TargetType.LineOfSight)
            {
                SkipAheadCache.RecordSkipAheadCachePoint();
            }

            // Some stuff to avoid spamming usepower EVERY loop, and also to detect stucks/staying in one place for too long
            bool bForceNewMovement = false;

            //Herbfunk: Added this to prevent stucks attempting to move to a target blocked. (Case: 3 champs behind a wall, within range but could not engage due to being on the other side.)
            #region Non Movement Counter Reached
            if (NonMovementCounter > Bot.Settings.Plugin.MovementNonMovementCount)
            {
                Logger.Write(LogLevel.Movement, "non movement counter reached {0}", NonMovementCounter);

                if (obj.Actortype.HasValue && obj.Actortype.Value.HasFlag(ActorType.Item))
                {
                    if (NonMovementCounter > 250)
                    {
                        //Are we stuck?
                        if (!Navigation.MGP.CanStandAt(Bot.Character.Data.Position))
                        {
                            Logger.DBLog.InfoFormat("Character is stuck inside non-standable location.. attempting townportal cast..");
                            ZetaDia.Me.UseTownPortal();
                            NonMovementCounter = 0;
                            return(RunStatus.Running);
                        }
                    }


                    //Check if we can walk to this location from current location..
                    if (!Navigation.CanRayCast(Bot.Character.Data.Position, CurrentTargetLocation, UseSearchGridProvider: true))
                    {
                        obj.RequiresLOSCheck = true;
                        obj.BlacklistLoops   = 50;

                        Logger.Write(LogLevel.Movement, "Ignoring Item {0} -- due to RayCast Failure!", obj.InternalName);

                        Bot.Targeting.Cache.bForceTargetUpdate = true;
                        return(RunStatus.Running);
                    }
                }
                else if (ObjectCache.CheckTargetTypeFlag(obj.targetType.Value, TargetType.LineOfSight | TargetType.Backtrack))
                {
                    Logger.Write(LogLevel.Movement, "Line of Sight Movement Stalled!");

                    Bot.NavigationCache.LOSmovementObject  = null;
                    Bot.Targeting.Cache.bForceTargetUpdate = true;
                    NonMovementCounter = 0;
                    // Reset the emergency loop counter and return success
                    return(RunStatus.Running);
                }
                else
                {
                    Logger.Write(LogLevel.Movement, "Ignoring obj {0} ", obj.InternalName + " _ SNO:" + obj.SNOID);
                    obj.BlacklistLoops   = 50;
                    obj.RequiresLOSCheck = true;
                    Bot.Targeting.Cache.bForceTargetUpdate = true;
                    NonMovementCounter = 0;

                    // Reset the emergency loop counter and return success
                    return(RunStatus.Running);
                }
            }
            #endregion

            //update misc movement info (rotation, state, flags, etc)
            Bot.NavigationCache.RefreshMovementCache();

            //Do a priority check for nearby obstacle objects.
            Bot.NavigationCache.ObstaclePrioritizeCheck(15f);

            #region Evaluate Last Action

            // Position didn't change last update.. check if we are stuck!
            if (DateTime.Now.Subtract(lastPositionChange).TotalMilliseconds > 150 &&
                (!Bot.NavigationCache.IsMoving || Bot.NavigationCache.currentMovementState == MovementState.WalkingInPlace || Bot.NavigationCache.currentMovementState.Equals(MovementState.None)))
            {
                bForceNewMovement = true;
                if (DateTime.Now.Subtract(LastMovementDuringCombat).TotalMilliseconds >= 250)
                {
                    LastMovementDuringCombat = DateTime.Now;
                    BlockedMovementCounter++;

                    // Tell target finder to prioritize close-combat targets incase we were bodyblocked
                    #region TargetingPriortize
                    switch (BlockedMovementCounter)
                    {
                    case 2:
                    case 3:
                        if (Bot.NavigationCache.groupRunningBehavior)
                        {
                            Logger.Write(LogLevel.Movement, "Grouping Behavior stopped due to blocking counter");

                            Bot.NavigationCache.GroupingFinishBehavior();
                            Bot.NavigationCache.groupingSuspendedDate = DateTime.Now.AddMilliseconds(4000);
                            Bot.Targeting.Cache.bForceTargetUpdate    = true;
                            return(RunStatus.Running);
                        }

                        if (!ObjectCache.CheckTargetTypeFlag(obj.targetType.Value, TargetType.AvoidanceMovements))
                        {
                            //Finally try raycasting to see if navigation is possible..
                            if (obj.Actortype.HasValue &&
                                (obj.Actortype.Value == ActorType.Gizmo || obj.Actortype.Value == ActorType.Monster))
                            {
                                Vector3 hitTest;
                                // No raycast available, try and force-ignore this for a little while, and blacklist for a few seconds
                                if (Navigator.Raycast(Bot.Character.Data.Position, obj.Position, out hitTest))
                                {
                                    if (hitTest != Vector3.Zero)
                                    {
                                        obj.RequiresLOSCheck = true;
                                        obj.BlacklistLoops   = 10;
                                        Logger.Write(LogLevel.Movement, "Ignoring object " + obj.InternalName + " due to not moving and raycast failure!", true);

                                        Bot.Targeting.Cache.bForceTargetUpdate = true;
                                        return(RunStatus.Running);
                                    }
                                }
                            }
                            else if (obj.targetType.Value == TargetType.Item)
                            {
                                obj.BlacklistLoops = 10;
                                Bot.Targeting.Cache.bForceTargetUpdate = true;
                            }
                        }
                        else
                        {
                            if (!Navigation.CanRayCast(Bot.Character.Data.Position, CurrentTargetLocation, NavCellFlags.AllowWalk))
                            {
                                Logger.Write(LogLevel.Movement, "Cannot continue with avoidance movement due to raycast failure!");
                                BlockedMovementCounter = 0;

                                Bot.NavigationCache.CurrentGPArea.BlacklistLastSafespot();
                                Bot.NavigationCache.vlastSafeSpot      = Vector3.Zero;
                                Bot.Targeting.Cache.bForceTargetUpdate = true;
                                return(RunStatus.Running);
                            }
                        }
                        break;
                    }
                    #endregion

                    return(RunStatus.Running);
                }
            }
            else
            {
                // Movement has been made, so count the time last moved!
                LastMovementDuringCombat = DateTime.Now;
            }
            #endregion

            // See if we want to ACTUALLY move, or are just waiting for the last move command...
            if (!bForceNewMovement && IsAlreadyMoving && CurrentTargetLocation == LastTargetLocation && DateTime.Now.Subtract(LastMovementCommand).TotalMilliseconds <= 100)
            {
                return(RunStatus.Running);
            }

            // If we're doing avoidance, globes or backtracking, try to use special abilities to move quicker
            #region SpecialMovementChecks
            if (ObjectCache.CheckTargetTypeFlag(obj.targetType.Value, Bot.Settings.Combat.CombatMovementTargetTypes))
            {
                Skill   MovementPower;
                Vector3 MovementVector = Bot.Character.Class.FindCombatMovementPower(out MovementPower, obj.Position);
                if (MovementVector != Vector3.Zero)
                {
                    ZetaDia.Me.UsePower(MovementPower.Power, MovementVector, Bot.Character.Data.iCurrentWorldID, -1);
                    MovementPower.OnSuccessfullyUsed();

                    // Store the current destination for comparison incase of changes next loop
                    LastTargetLocation = CurrentTargetLocation;
                    // Reset total body-block count, since we should have moved
                    //if (DateTime.Now.Subtract(Bot.Targeting.Cache.Environment.lastForcedKeepCloseRange).TotalMilliseconds>=2000)
                    BlockedMovementCounter = 0;

                    return(RunStatus.Running);
                }

                //Special Whirlwind Code
                if (Bot.Character.Class.AC == ActorClass.Barbarian && Bot.Character.Class.HotBar.HotbarPowers.Contains(SNOPower.Barbarian_Whirlwind))
                {
                    // Whirlwind against everything within range (except backtrack points)
                    if (Bot.Character.Data.dCurrentEnergy >= 10 &&
                        Bot.Targeting.Cache.Environment.iAnythingWithinRange[(int)RangeIntervals.Range_20] >= 1 &&
                        obj.DistanceFromTarget <= 12f &&
                        (!Bot.Character.Class.HotBar.HotbarPowers.Contains(SNOPower.Barbarian_Sprint) || Bot.Character.Class.HotBar.HasBuff(SNOPower.Barbarian_Sprint)) &&
                        (ObjectCache.CheckTargetTypeFlag(obj.targetType.Value, TargetType.AvoidanceMovements | TargetType.Gold | TargetType.Globe) == false) &&
                        (obj.targetType.Value != TargetType.Unit ||
                         (obj.targetType.Value == TargetType.Unit && !obj.IsTreasureGoblin &&
                          (!Bot.Settings.Class.bSelectiveWhirlwind ||
                           Bot.Targeting.Cache.Environment.bAnyNonWWIgnoreMobsInRange ||
                           !CacheIDLookup.hashActorSNOWhirlwindIgnore.Contains(obj.SNOID)))))
                    {
                        // Special code to prevent whirlwind double-spam, this helps save fury
                        bool bUseThisLoop = SNOPower.Barbarian_Whirlwind != Bot.Character.Class.LastUsedAbility.Power;
                        if (!bUseThisLoop)
                        {
                            if (Bot.Character.Class.Abilities[SNOPower.Barbarian_Whirlwind].LastUsedMilliseconds >= 200)
                            {
                                bUseThisLoop = true;
                            }
                        }
                        if (bUseThisLoop)
                        {
                            ZetaDia.Me.UsePower(SNOPower.Barbarian_Whirlwind, CurrentTargetLocation, Bot.Character.Data.iCurrentWorldID);
                            Bot.Character.Class.Abilities[SNOPower.Barbarian_Whirlwind].OnSuccessfullyUsed();
                        }
                        // Store the current destination for comparison incase of changes next loop
                        LastTargetLocation     = CurrentTargetLocation;
                        BlockedMovementCounter = 0;
                        return(RunStatus.Running);
                    }
                }
            }
            #endregion


            // Now for the actual movement request stuff
            IsAlreadyMoving = true;
            UseTargetMovement(obj, bForceNewMovement);

            // Store the current destination for comparison incase of changes next loop
            LastMovementAttempted = DateTime.Now;
            LastTargetLocation    = CurrentTargetLocation;

            //Check if we moved at least 5f..
            if (LastPlayerLocation.Distance(Bot.Character.Data.Position) <= 5f)
            {
                NonMovementCounter++;
            }
            else
            {
                NonMovementCounter     = 0;
                BlockedMovementCounter = 0;
            }

            //store player location
            LastPlayerLocation = Bot.Character.Data.Position;

            return(RunStatus.Running);
        }
Exemple #2
0
            public void MoveTowards(Vector3 vMoveToTarget)
            {
                if (Bot.Character.Class == null)
                {
                    Logger.DBLog.InfoFormat("Bot did not properly initilize, stopping bot!");
                    BotMain.Stop(false, "Bot Init Failure");
                    return;
                }

                #region LogStucks
                // The below code is to help profile/routine makers avoid waypoints with a long distance between them.
                // Long-distances between waypoints is bad - it increases stucks, and forces the DB nav-server to be called.

                //if (vLastMoveTo==Vector3.Zero) vLastMoveTo=vMoveToTarget;

                if (vMoveToTarget != vLastMoveTo)
                {
                    vLastMoveTo = vMoveToTarget;

                    if (Bot.Settings.Debug.LogStuckLocations)
                    {
                        vLastMoveTo          = vMoveToTarget;
                        bLastWaypointWasTown = false;

                        float fDistance = Vector3.Distance(vMoveToTarget, vLastMoveTo);
                        // Logger.DBLog.InfoFormat if not in town, last waypoint wasn't FROM town, and the distance is >200 but <2000 (cos 2000+ probably means we changed map zones!)
                        if (!ZetaDia.IsInTown && !bLastWaypointWasTown && fDistance >= 200 & fDistance <= 2000)
                        {
                            if (!hashDoneThisVector.Contains(vMoveToTarget))
                            {
                                // Logger.DBLog.InfoFormat it
                                string     sLogFileName = Logger.LoggingPrefixString + " -- LongPaths.log";
                                FileStream LogStream    = File.Open(Logger.LoggingFolderPath + sLogFileName, FileMode.Append, FileAccess.Write, FileShare.Read);
                                using (StreamWriter LogWriter = new StreamWriter(LogStream))
                                {
                                    LogWriter.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture) + ":");
                                    LogWriter.WriteLine("Profile Name=" + ProfileManager.CurrentProfile.Name);
                                    LogWriter.WriteLine("'From' Waypoint=" + vLastMoveTo + ". 'To' Waypoint=" + vMoveToTarget + ". Distance=" + fDistance.ToString(CultureInfo.InvariantCulture));
                                }
                                //LogStream.Close();
                                hashDoneThisVector.Add(vMoveToTarget);
                            }
                        }
                    }

                    if (ZetaDia.IsInTown)
                    {
                        bLastWaypointWasTown = true;
                    }
                }

                #endregion



                // Make sure GilesTrinity doesn't want us to avoid routine-movement
                if (Bot.Targeting.Cache.DontMove)
                {
                    return;
                }

                // Store player current position
                Vector3 vMyCurrentPosition = ZetaDia.Me.Position;

                //Check GPC entry (backtracking cache) -- only when not in town!
                if (BackTrackCache.EnableBacktrackGPRcache && !ZetaDia.IsInTown)
                {
                    if (DateTime.Now.Subtract(LastCombatPointChecked).TotalMilliseconds > 1250)
                    {
                        if (BackTrackCache.cacheMovementGPRs.Count == 0)
                        {
                            BackTrackCache.StartNewGPR(vMyCurrentPosition);
                        }
                        else
                        {                        //Add new point only if distance is 25f difference
                            if (BackTrackCache.cacheMovementGPRs.Count == 1)
                            {
                                if (BackTrackCache.cacheMovementGPRs[0].CreationVector.Distance(vMyCurrentPosition) >= BackTrackCache.MinimumRangeBetweenMovementGPRs)
                                {
                                    BackTrackCache.StartNewGPR(vMyCurrentPosition);
                                }
                            }
                            else
                            {
                                //Only if no GPCs currently are less than 20f from us..
                                if (!BackTrackCache.cacheMovementGPRs.Any(GPC => GPC.CreationVector.Distance(vMyCurrentPosition) < BackTrackCache.MinimumRangeBetweenMovementGPRs))
                                {
                                    BackTrackCache.StartNewGPR(vMyCurrentPosition);
                                }
                            }
                        }
                        //Reset Timer
                        LastCombatPointChecked = DateTime.Now;
                    }
                }

                //Special cache for skipping locations visited.
                if (Bot.Settings.Debug.SkipAhead)
                {
                    SkipAheadCache.RecordSkipAheadCachePoint();
                }

                // Store distance to current moveto target
                float fDistanceFromTarget;

                #region Unstucker
                // Do unstuckery things
                if (Bot.Settings.Debug.EnableUnstucker)
                {
                    // Store the "real" (not anti-stuck) destination
                    vOldMoveToTarget = vMoveToTarget;

                    // See if we can reset the 10-limit unstuck counter, if >120 seconds since we last generated an unstuck location
                    if (iTotalAntiStuckAttempts > 1 && DateTime.Now.Subtract(timeStartedUnstuckMeasure).TotalSeconds >= 120)
                    {
                        iTotalAntiStuckAttempts = 1;
                        iTimesReachedStuckPoint = 0;
                        vSafeMovementLocation   = Vector3.Zero;
                    }

                    // See if we need to, and can, generate unstuck actions
                    if (DateTime.Now.Subtract(timeCancelledUnstuckerFor).TotalSeconds > iCancelUnstuckerForSeconds && UnstuckChecker(vMyCurrentPosition))
                    {
                        // Record the time we last apparently couldn't move for a brief period of time
                        timeLastReportedAnyStuck = DateTime.Now;
                        // See if there's any stuck position to try and navigate to generated by random mover
                        vSafeMovementLocation = UnstuckHandler(vMyCurrentPosition, vOldMoveToTarget);
                        if (vSafeMovementLocation == Vector3.Zero)
                        {
                            return;
                        }
                    }

                    // See if we can clear the total unstuckattempts if we haven't been stuck in over 6 minutes.
                    if (DateTime.Now.Subtract(timeLastReportedAnyStuck).TotalSeconds >= 360)
                    {
                        iTimesReachedMaxUnstucks = 0;
                    }

                    // Did we have a safe point already generated (eg from last loop through), if so use it as our current location instead
                    if (vSafeMovementLocation != Vector3.Zero)
                    {
                        // Set our current movement target to the safe point we generated last cycle
                        vMoveToTarget = vSafeMovementLocation;
                    }

                    // Get distance to current destination
                    fDistanceFromTarget = Vector3.Distance(vMyCurrentPosition, vMoveToTarget);

                    // Remove the stuck position if it's been reached, this bit of code also creates multiple stuck-patterns in an ever increasing amount
                    if (vSafeMovementLocation != Vector3.Zero && fDistanceFromTarget <= 3f)
                    {
                        vSafeMovementLocation = Vector3.Zero;
                        iTimesReachedStuckPoint++;
                        // Do we want to immediately generate a 2nd waypoint to "chain" anti-stucks in an ever-increasing path-length?
                        if (iTimesReachedStuckPoint <= iTotalAntiStuckAttempts)
                        {
                            Bot.NavigationCache.AttemptFindSafeSpot(out vSafeMovementLocation, Vector3.Zero, Bot.Settings.Plugin.AvoidanceFlags);
                            vMoveToTarget = vSafeMovementLocation;
                        }
                        else
                        {
                            Logger.DBLog.DebugFormat("[Funky] Clearing old route and trying new path find to: " + vOldMoveToTarget.ToString());
                            // Reset the path and allow a whole "New" unstuck generation next cycle
                            iTimesReachedStuckPoint = 0;
                            // And cancel unstucking for 9 seconds so DB can try to navigate
                            iCancelUnstuckerForSeconds = (9 * iTotalAntiStuckAttempts);
                            if (iCancelUnstuckerForSeconds < 20)
                            {
                                iCancelUnstuckerForSeconds = 20;
                            }
                            timeCancelledUnstuckerFor = DateTime.Now;
                            Navigator.Clear();
                            Navigator.MoveTo(vOldMoveToTarget, "original destination", false);
                            return;
                        }
                    }
                }
                else
                {
                    // Get distance to current destination
                    fDistanceFromTarget = vMyCurrentPosition.Distance(vMoveToTarget);
                }                 // Is the built-in unstucker enabled or not?
                #endregion


                //Prioritize "blocking" objects.
                if (!Bot.Character.Data.bIsInTown)
                {
                    Bot.NavigationCache.ObstaclePrioritizeCheck();
                }



                #region MovementAbilities
                // See if we can use abilities like leap etc. for movement out of combat, but not in town and only if we can raycast.
                if (Bot.Settings.OutOfCombatMovement && !ZetaDia.IsInTown && !Bot.IsInNonCombatBehavior)
                {
                    Skill   MovementPower;
                    Vector3 MovementVector = Bot.Character.Class.FindOutOfCombatMovementPower(out MovementPower, vMoveToTarget);
                    if (MovementVector != Vector3.Zero)
                    {
                        ZetaDia.Me.UsePower(MovementPower.Power, MovementVector, Bot.Character.Data.iCurrentWorldID);
                        MovementPower.OnSuccessfullyUsed();
                        return;
                    }
                }                 // Allowed to use movement powers to move out-of-combat?
                #endregion


                //Send Movement Command!
                //ZetaDia.Me.Movement.MoveActor(vMoveToTarget);
                ZetaDia.Me.UsePower(SNOPower.Walk, vMoveToTarget, Bot.Character.Data.iCurrentWorldID);
            }