Exemple #1
0
        /// <summary>
        /// This coroutine interacts with the waypoint and waits for the world panel to open. When called from a hideout,
        /// the waypoint must be in spawn range, otherwise the coroutine will fail. The movement is done without returning,
        /// so this should be carefully used when not in town.
        /// </summary>
        /// <returns>An OpenStashError that describes the result.</returns>
        public static async Task <Results.OpenWaypointError> OpenWaypoint()
        {
            await Coroutines.CloseBlockingWindows();

            await Coroutines.FinishCurrentAction();

            var waypoint = LokiPoe.ObjectManager.Waypoint;

            if (waypoint == null)
            {
                if (!LokiPoe.Me.IsInTown)
                {
                    return(Results.OpenWaypointError.NoWaypoint);
                }

                if (
                    !await
                    Navigation.MoveToLocation(ExilePather.FastWalkablePositionFor(Actor.GuessWaypointLocation()), 25,
                                              60000, () => LokiPoe.ObjectManager.Waypoint != null))
                {
                    return(Results.OpenWaypointError.CouldNotMoveToWaypoint);
                }

                waypoint = LokiPoe.ObjectManager.Waypoint;
                if (waypoint == null)
                {
                    return(Results.OpenWaypointError.NoWaypoint);
                }
            }

            if (ExilePather.PathDistance(LokiPoe.MyPosition, waypoint.Position) > 30)
            {
                if (!await Navigation.MoveToLocation(ExilePather.FastWalkablePositionFor(waypoint.Position), 25, 15000, () => false))
                {
                    return(Results.OpenWaypointError.CouldNotMoveToWaypoint);
                }
            }

            await Coroutines.FinishCurrentAction();

            waypoint = LokiPoe.ObjectManager.Waypoint;
            if (waypoint == null)
            {
                return(Results.OpenWaypointError.NoWaypoint);
            }

            if (!await InteractWith(waypoint))
            {
                return(Results.OpenWaypointError.InteractFailed);
            }

            if (!await WaitForWorldPanel())
            {
                return(Results.OpenWaypointError.WorldPanelDidNotOpen);
            }

            await Coroutine.Sleep(1000); // Adding this in to let the gui load more

            return(Results.OpenWaypointError.None);
        }
Exemple #2
0
        public static Vector2i CalcSafePosition(double escapeAngle, float safeDistance)
        {
            Vector2i result = new Vector2i();

            for (int angleModificator = 0; angleModificator < 36; angleModificator++)
            {
                //We prioritize a route as close to our escape angle as possible
                double   angle   = escapeAngle + (Math.Ceiling((double)angleModificator / 2) * 0.174533 * (angleModificator % 2 == 0 ? 1 : -1));
                Vector2i pos     = GeometryHelper.GetPointOnCircle(LokiPoe.Me.Position, angle, safeDistance);
                bool     skipPos = false;
                try
                {
                    skipPos = !ExilePather.NavigationGrid.IsWalkable(pos) ||
                              !ExilePather.CanObjectSee(LokiPoe.Me, pos, true) ||
                              Utility.ClosedDoorBetween(LokiPoe.Me, pos, 10, 10, true);
                }
                catch
                {
                    skipPos = true;
                }
                if (skipPos)
                {
                    continue;
                }
                result = pos;
                break;
            }
            return(result);
        }
Exemple #3
0
        /// <summary>
        /// Checks for a closed door between start and end.
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="distanceFromPoint">How far to check around each point for a door object.</param>
        /// <param name="stride">The distance between points to check in the path.</param>
        /// <param name="dontLeaveFrame">Should the current frame not be left?</param>
        /// <returns>true if there's a closed door and false otherwise.</returns>
        public static bool ClosedDoorBetween(
            Vector2i start,
            Vector2i end,
            int distanceFromPoint = 10,
            int stride            = 10,
            bool dontLeaveFrame   = false)
        {
            var doors = LokiPoe.ObjectManager.Doors.Where(d => !d.IsOpened).ToList();

            if (!doors.Any())
            {
                return(false);
            }

            var path = ExilePather.GetPointsOnSegment(start, end, dontLeaveFrame);

            for (var i = 0; i < path.Count; i += stride)
            {
                if (doors.Any(door => door.Position.Distance(path[i]) <= distanceFromPoint))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #4
0
        public static WorldPosition FindPathablePosition(Vector2i pos, int step = 10, int radius = 30)
        {
            var myPos = LokiPoe.MyPosition;
            int x     = pos.X;
            int y     = pos.Y;

            for (int r = step; r <= radius; r += step)
            {
                int minX = x - r;
                int minY = y - r;
                int maxX = x + r;
                int maxY = y + r;
                for (int i = minX; i <= maxX; i += step)
                {
                    for (int j = minY; j <= maxY; j += step)
                    {
                        if (i != minX && i != maxX && j != minY && j != maxY)
                        {
                            continue;
                        }

                        var p = new Vector2i(i, j);
                        if (ExilePather.PathExistsBetween(myPos, p))
                        {
                            return(new WorldPosition(p));
                        }
                    }
                }
            }
            return(null);
        }
Exemple #5
0
        /// <summary>
        /// Used to reset the starting area transition. This is for handling local area transitions.
        /// </summary>
        public void ResetStartingAreaTransition()
        {
            var at = LokiPoe.ObjectManager.GetObjectsByType <AreaTransition>().OrderBy(a => a.Distance).FirstOrDefault();

            StartingAreaTransitionName     = at != null ? at.Name : "";
            StartingAreaTransitionLocation = at != null
                ? ExilePather.FastWalkablePositionFor(at)
                : Vector2i.Zero;
        }
Exemple #6
0
        public BreachCache(Breach breach)
        {
            Id               = breach.Id;
            Position         = breach.Position;
            WalkablePosition = ExilePather.FastWalkablePositionFor(breach);
            IsValid          = true;

            Log.InfoFormat("[BreachCache] {0} {1}", Id, WalkablePosition);
        }
Exemple #7
0
 private void ReloadExilePatherButton_OnClick(object sender, RoutedEventArgs e)
 {
     Dispatcher.BeginInvoke(new Action(() =>
     {
         using (LokiPoe.AcquireFrame())
         {
             ExilePather.Reload(true);
         }
         GetDataFunc().ForceReload = true;
         Log.InfoFormat("[ReloadExilePatherButton_OnClick] Done!");
     }));
 }
        public MonolithCache(Monolith monolith)
        {
            Id               = monolith.Id;
            Position         = monolith.Position;
            WalkablePosition = ExilePather.FastWalkablePositionFor(monolith);
            MonsterName      = monolith.Name;
            MonsterMetadata  = monolith.MonsterTypeMetadata;
            Essences         = monolith.EssenceBaseItemTypes;
            IsValid          = true;

            Log.InfoFormat("[MonolithCache] {0} {1} {2} {3} {4}", Id, WalkablePosition, MonsterName, MonsterMetadata,
                           string.Join(", ", Essences.Select(e => e.Metadata)));
        }
Exemple #9
0
        public void Start()
        {
            ItemEvaluator.Instance   = DefaultItemEvaluator.Instance;
            Explorer.CurrentDelegate = user => CombatAreaCache.Current.Explorer.BasicExplorer;

            ComplexExplorer.ResetSettingsProviders();
            ComplexExplorer.AddSettingsProvider("MapBot", MapBotExploration, ProviderPriority.Low);

            // Cache all bound keys.
            LokiPoe.Input.Binding.Update();

            // Reset the default MsBetweenTicks on start.
            Log.Debug($"[Start] MsBetweenTicks: {BotManager.MsBetweenTicks}.");
            Log.Debug($"[Start] NetworkingMode: {LokiPoe.ConfigManager.NetworkingMode}.");
            Log.Debug($"[Start] KeyPickup: {LokiPoe.ConfigManager.KeyPickup}.");
            Log.Debug($"[Start] IsAutoEquipEnabled: {LokiPoe.ConfigManager.IsAutoEquipEnabled}.");

            // Since this bot will be performing client actions, we need to enable the process hook manager.
            LokiPoe.ProcessHookManager.Enable();

            _coroutine = null;

            ExilePather.Reload();

            _taskManager.Reset();

            AddTasks();

            Events.Start();
            PluginManager.Start();
            RoutineManager.Start();
            PlayerMoverManager.Start();
            _taskManager.Start();

            foreach (var plugin in PluginManager.EnabledPlugins)
            {
                Log.Debug($"[Start] The plugin {plugin.Name} is enabled.");
            }

            if (ExilePather.BlockTrialOfAscendancy == FeatureEnum.Unset)
            {
                //no need for this, map trials are in separate areas
                ExilePather.BlockTrialOfAscendancy = FeatureEnum.Disabled;
            }
        }
Exemple #10
0
        /// <summary>
        /// Returns the number of mobs between 2 points
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="distanceFromPoint"></param>
        /// <param name="dontLeaveFrame">Should the current frame not be left?</param>
        /// <returns></returns>
        public static int NumberOfMobsBetween(Vector2i start, Vector2i end, int distanceFromPoint = 5, bool dontLeaveFrame = false)
        {
            var mobs = LokiPoe.ObjectManager.GetObjectsByType <Monster>().Where(d => d.IsActive).ToList();

            if (!mobs.Any())
            {
                return(0);
            }

            var path = ExilePather.GetPointsOnSegment(start, end, dontLeaveFrame);

            var count = 0;

            for (var i = 0; i < path.Count; i += 10)
            {
                count += mobs.Count(mob => mob.Position.Distance(path[i]) <= distanceFromPoint);
            }

            return(count);
        }
Exemple #11
0
        private void ShowAreaInformation(DatWorldAreaWrapper area)
        {
            TextBoxInfoRaw.AppendText(area.ToString());

            var sb = new StringBuilder();

            // Handle updates when the bot isn't running.
            if (!BotManager.IsRunning)
            {
                ExilePather.Reload();
                //StaticLocationManager.Tick();
            }

            /*sb.AppendLine(string.Format("[Static Locations]"));
             * foreach (var kvp in StaticLocationManager.StaticLocations)
             * {
             *      sb.AppendLine(string.Format("\t{0}", kvp.Key));
             *      foreach (var pos in kvp.Value)
             *      {
             *              sb.AppendLine(string.Format("\t\t{0}", pos));
             *      }
             * }*/

            /*sb.AppendLine(string.Format("[Static Waypoints]"));
             * foreach (var pos in StaticLocationManager.StaticWaypointLocations)
             * {
             *      sb.AppendLine(string.Format("\t{0}", pos));
             * }*/

            sb.AppendLine(string.Format("[Mods]"));
            foreach (var mod in LokiPoe.LocalData.MapMods)
            {
                sb.AppendLine(string.Format("\t{0}: {1}", mod.Key, mod.Value));
            }

            sb.AppendLine(string.Format("[Terrain]"));
            sb.AppendLine(string.Format("\tCols: {0}", LokiPoe.TerrainData.Cols));
            sb.AppendLine(string.Format("\tRows: {0}", LokiPoe.TerrainData.Rows));

            TextBoxInfoRaw.AppendText(sb.ToString());
        }
Exemple #12
0
        public void Tick()
        {
            if (_coroutine == null)
            {
                _coroutine = new Coroutine(() => MainCoroutine());
            }

            ExilePather.Reload();

            Events.Tick();
            CombatAreaCache.Tick();
            _taskManager.Tick();
            PluginManager.Tick();
            RoutineManager.Tick();
            PlayerMoverManager.Tick();
            StuckDetection.Tick();

            Statistics.Instance.Tick();

            // Check to see if the coroutine is finished. If it is, stop the bot.
            if (_coroutine.IsFinished)
            {
                Log.Debug($"The bot coroutine has finished in a state of {_coroutine.Status}");
                BotManager.Stop();
                return;
            }

            try
            {
                _coroutine.Resume();
            }
            catch
            {
                var c = _coroutine;
                _coroutine = null;
                c.Dispose();
                throw;
            }
        }
Exemple #13
0
        private AreaStateCache(uint hash)
        {
            Hash = hash;

            WorldArea = LokiPoe.CurrentWorldArea;

            ShouldCheckForWaypoint = LokiPoe.CurrentWorldArea.HasWaypoint;

            ShouldCheckForStash = LokiPoe.CurrentWorldArea.IsTown;
            HasStashLocation    = false;

            HasWaypointLocation = false;

            var areaId = WorldArea.Id;

            HasWaypointEntry = LokiPoe.InstanceInfo.AvailableWaypoints.ContainsKey(areaId);

            SeenAreaTransitions = new List <string>();

            //GenerateStaticLocations();

            ResetStartingAreaTransition();

            var portal = LokiPoe.ObjectManager.GetObjectsByType <Portal>().OrderBy(a => a.Distance).FirstOrDefault();

            StartingPortalLocation = portal != null
                ? ExilePather.FastWalkablePositionFor(portal)
                : Vector2i.Zero;

            //if (!DisableDefaultExplorer)
            //{
            //    var ge = new GridExplorer
            //    {
            //        AutoResetOnAreaChange = false
            //    };
            //    Explorer = ge;
            //}
        }
Exemple #14
0
        /// <summary>
        /// This coroutine will attempt to take a portal
        /// </summary>
        /// <returns>true if the portal was taken, and an area change occurred, and false otherwise.</returns>
        public static async Task <bool> TakeClosestPortal()
        {
            var sw = Stopwatch.StartNew();

            if (LokiPoe.ConfigManager.IsAlwaysHighlightEnabled)
            {
                CommunityLib.Log.InfoFormat("[TakeClosestPortal] Now disabling Always Highlight to avoid label issues.");
                LokiPoe.Input.SimulateKeyEvent(LokiPoe.Input.Binding.highlight_toggle, true, false, false);
                await Coroutine.Sleep(16);
            }

            NetworkObject portal = null;

            while (portal == null || !portal.IsTargetable)
            {
                CommunityLib.Log.DebugFormat($"[TakeClosestPortal] Now waiting for the portal to spawn. {sw.Elapsed} elapsed.");
                await Coroutines.LatencyWait();

                portal =
                    LokiPoe.ObjectManager.GetObjectsByType <Portal>()
                    .Where(p => p.Distance < 50)
                    .OrderBy(p => p.Distance)
                    .FirstOrDefault();

                if (sw.ElapsedMilliseconds > 10000)
                {
                    break;
                }
            }

            if (portal == null)
            {
                CommunityLib.Log.ErrorFormat("[TakeClosestPortal] A portal was not found.");
                return(false);
            }

            var pos = ExilePather.FastWalkablePositionFor(portal);

            CommunityLib.Log.Debug($"[TakeClosestPortal] The portal was found at {pos}.");

            if (!await Navigation.MoveToLocation(pos, 5, 10000, () => false))
            {
                return(false);
            }

            var hash = LokiPoe.LocalData.AreaHash;

            // Try to interact 3 times.
            for (var i = 0; i < 3; i++)
            {
                if (LokiPoe.Me.IsDead)
                {
                    break;
                }

                await Coroutines.FinishCurrentAction();

                CommunityLib.Log.Debug($"[TakeClosestPortal] The portal to interact with is {portal.Id} at {pos}.");

                if (await InteractWith(portal))
                {
                    if (await Areas.WaitForAreaChange(hash))
                    {
                        CommunityLib.Log.Debug("[TakeClosestPortal] The portal has been taken.");
                        return(true);
                    }
                }

                await Coroutine.Sleep(1000);
            }

            CommunityLib.Log.ErrorFormat("[TakeClosestPortal] We have failed to take the portal 3 times.");
            return(false);
        }
 public static float PathDistance(this NetworkObject obj)
 {
     return(ExilePather.PathDistance(LokiPoe.MyPosition, obj.Position));
 }
Exemple #16
0
        /// <summary>
        /// Runs a task.
        /// </summary>
        /// <returns>true if the task ran and false otherwise.</returns>
        public async Task <bool> Run()
        {
            StuckDetection.Reset();             // We don't want StuckDetection logic running really.

            var leader = Leader;
            var me     = LokiPoe.Me;

            // If we don't have the leader in view, let's try to guess what they did.
            if (leader == null)
            {
                // If we've at least seen the leader once, first try moving to where they were last seen.
                if (_leaderData.LastKnownPosition != Vector2i.Zero)
                {
                    // Move closer to their last known position if we're out of range.
                    if (me.Position.Distance(_leaderData.LastKnownPosition) > 20)
                    {
                        // First, make sure we can actually get to the player's last known position before trying to move there.
                        if (ExilePather.PathExistsBetween(me.Position, _leaderData.LastKnownPosition, true))
                        {
                            // Just move to the location.
                            if (!PlayerMoverManager.MoveTowards(_leaderData.LastKnownPosition))
                            {
                                Log.Error($"[FollowerTask] PlayerMoverManager.MoveTowards failed for {_leaderData.LastKnownPosition}.");
                            }
                        }
                    }

                    // Clear the data so we don't run again.
                    _leaderData.LastKnownPosition = Vector2i.Zero;
                }

                // We have to decide which we want to use based on distance.
                if (_leaderData.LabyrinthReturnPortal != null && _leaderData.LastAreaTransition != null)
                {
                    if (_leaderData.LabyrinthReturnPortal.Distance < _leaderData.LastAreaTransition.Distance)
                    {
                        // Check to see if we saw the player near an area transition or the exit portal
                        if (await HandleLabyrinthReturnPortal())
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        // Check to see if we saw the player near an area transition or the exit portal
                        if (await HandleLastAreaTransition())
                        {
                            return(true);
                        }
                    }
                }
                else                 // Order doesn't matter
                {
                    // Check to see if we saw the player near an area transition or the exit portal
                    if (await HandleLastAreaTransition())
                    {
                        return(true);
                    }

                    // Check to see if we saw the player near an area transition or the exit portal
                    if (await HandleLabyrinthReturnPortal())
                    {
                        return(true);
                    }
                }

                Log.Warn("[TODO 1]");

                return(true);
            }

            // Check to see if were within range. If so, return, as we have nothing else to do here.
            if (leader.Distance <= FollowerSettings.Instance.FollowDistance)
            {
                return(true);
            }

            // Otherwise, first check to see if a path exists between us and the leader, this is mostly to handle transitions
            if (ExilePather.PathExistsBetween(me.Position, leader.Position, true))
            {
                var leaderDistance = leader.Distance;

                // If there's an area transition closer to us than the leader, it's a special boss one,
                // but we don't need to stop the bot really, we can just sit and wait until it opens. Unless
                // we want the character to take it, in which case we can add that logic s well.
                if (LokiPoe.ObjectManager.Objects.OfType <AreaTransition>().Any(at => StringHelper.IsArenaTransition(at) && at.Distance < leaderDistance && at.IsTargetable))
                {
                    return(true);
                }

                // Just move to towards the player.
                if (!PlayerMoverManager.MoveTowards(leader.Position))
                {
                    // We can't do much other than log the error and let the user fix the issue.
                    Log.Error($"[FollowerTask] PlayerMoverManager.MoveTowards failed for {leader.Position}.");
                }

                // Nothing else to do.
                return(true);
            }

            // Check to see if we saw the player near an area transition.
            if (await HandleLastAreaTransition())
            {
                return(true);
            }

            Log.Warn("[TODO 2]");

            // This task takes control over QB/MB, so it should always return true;
            return(true);
        }
Exemple #17
0
        /// <summary>
        /// This coroutine interacts with stash and waits for the stash panel to open. When called from a hideout,
        /// the stash must be in spawn range, otherwise the coroutine will fail.
        /// </summary>
        ///<param name="guild">Should the guild stash be opened?</param>
        /// <returns>An OpenStashError that describes the result.</returns>
        public static async Task <Results.OpenStashError> OpenStash(bool guild = false)
        {
            await Coroutines.CloseBlockingWindows();

            await Coroutines.FinishCurrentAction();

            var stash = Stash.DetermineStash(guild);

            if (stash == null)
            {
                if (LokiPoe.Me.IsInHideout)
                {
                    return(Results.OpenStashError.NoStash);
                }

                var mtl = await Navigation.MoveToLocation(
                    ExilePather.FastWalkablePositionFor(Actor.GuessStashLocation()), 25, 60000,
                    () => Stash.DetermineStash(guild) != null && Stash.DetermineStash(guild).Distance < 75);

                if (!mtl)
                {
                    return(Results.OpenStashError.CouldNotMoveToStash);
                }

                stash = Stash.DetermineStash(guild);
                if (stash == null)
                {
                    return(Results.OpenStashError.NoStash);
                }
            }

            if (stash.Distance > 30)
            {
                var p = stash.Position;
                if (!await Navigation.MoveToLocation(ExilePather.FastWalkablePositionFor(p), 25, 15000, () => false))
                {
                    return(Results.OpenStashError.CouldNotMoveToStash);
                }
            }

            await Coroutines.FinishCurrentAction();

            stash = Stash.DetermineStash(guild);
            if (stash == null)
            {
                return(Results.OpenStashError.NoStash);
            }

            if (!await InteractWith(stash))
            {
                return(Results.OpenStashError.InteractFailed);
            }

            if (guild)
            {
                if (!await Dialog.WaitForPanel(Dialog.PanelType.GuildStash))
                {
                    return(Results.OpenStashError.StashPanelDidNotOpen);
                }

                await Stash.WaitForStashTabChange(guild : true);
            }
            else
            {
                if (!await Dialog.WaitForPanel(Dialog.PanelType.Stash))
                {
                    return(Results.OpenStashError.StashPanelDidNotOpen);
                }

                await Stash.WaitForStashTabChange();
            }

            return(Results.OpenStashError.None);
        }
Exemple #18
0
        private void OnTick()
        {
            //if (Explorer != null)
            //{
            //    Explorer.Tick();
            //}

            var update = false;

            if (!_itemThrottle.IsRunning)
            {
                _itemThrottle.Start();
                update = true;
            }
            else
            {
                if (_itemThrottle.ElapsedMilliseconds >= ItemThrottleMs)
                {
                    update = true;
                }
            }

            //using (new PerformanceTimer("Tick::WorldItem", 1))
            {
                if (update)
                {
                    var myPos = LokiPoe.MyPosition;

                    var added = 0;
                    foreach (var worldItem in LokiPoe.ObjectManager.GetObjectsByType <WorldItem>())
                    {
                        var doAdd = false;

                        Vector2i pos;
                        if (!_ignoreItems.TryGetValue(worldItem.Id, out pos))
                        {
                            doAdd = true;
                        }
                        else
                        {
                            if (pos != worldItem.Position)
                            {
                                Log.InfoFormat("[AreaStateCache] An item collision has been detected! Item id {0}.", worldItem.Id);
                                _ignoreItems.Remove(worldItem.Id);
                                doAdd = true;
                            }
                        }

                        if (doAdd)
                        {
                            if (added > 10)
                            {
                                break;
                            }

                            ++added;

                            var item = worldItem.Item;

                            if (worldItem.IsAllocatedToOther)
                            {
                                if (DateTime.Now < worldItem.PublicTime)
                                {
                                    //Log.InfoFormat("[AreaStateCache] The item {0} is not being marked for pickup because it is allocated to another player.", item.FullName);
                                    //_ignoreItems.Add(worldItem.Id, worldItem.Position);
                                    continue;
                                }
                            }

                            var visibleOverride = false;
                            if (LootVisibleItemsOverride)
                            {
                                // We can only consider items when they are visible, otherwise we ignore stuff we might want.
                                if (!LokiPoe.ConfigManager.IsAlwaysHighlightEnabled)
                                {
                                    continue;
                                }

                                if (LokiPoe.Input.GetClickableHighlightLabelPosition(worldItem) != Vector2.Zero)
                                {
                                    visibleOverride = true;
                                }
                            }

                            IItemFilter filter = null;
                            if (visibleOverride || ItemEvaluator.Match(item, EvaluationType.PickUp, out filter))
                            {
                                var location = new ItemLocation
                                {
                                    Id       = worldItem.Id,
                                    Name     = worldItem.Name,
                                    Position = worldItem.Position,
                                    Rarity   = worldItem.Item.Rarity,
                                    Metadata = worldItem.Item.Metadata
                                };

                                if (_itemLocations.ContainsKey(location.Id))
                                {
                                    _itemLocations[location.Id] = location;
                                }
                                else
                                {
                                    _itemLocations.Add(location.Id, location);
                                }

                                Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being added from filter [{3}].{2}", location.Id,
                                               location.Name,
                                               worldItem.HasAllocation ? " [Allocation " + worldItem.PublicTime + "]" : "",
                                               filter != null ? filter.Name : "(null)");
                            }

                            _ignoreItems.Add(worldItem.Id, worldItem.Position);
                        }
                    }

                    var toRemove = new List <int>();
                    foreach (var kvp in _itemLocations)
                    {
                        if (Blacklist.Contains(kvp.Key))
                        {
                            Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being removed because the id has been Blacklisted.",
                                           kvp.Value.Id, kvp.Value.Name);
                            toRemove.Add(kvp.Value.Id);
                        }
                        else if (myPos.Distance(kvp.Value.Position) < 30)
                        {
                            if (LokiPoe.ObjectManager.GetObjectById <WorldItem>(kvp.Value.Id) == null)
                            {
                                Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being removed because the WorldItem does not exist.",
                                               kvp.Value.Id, kvp.Value.Name);
                                toRemove.Add(kvp.Value.Id);
                            }
                        }
                    }

                    foreach (var id in toRemove)
                    {
                        _itemLocations.Remove(id);
                    }

                    _itemThrottle.Restart();
                }
            }

            if (!_chestThrottle.IsRunning)
            {
                _chestThrottle.Start();
            }
            else
            {
                if (_chestThrottle.ElapsedMilliseconds >= ChestThrottleMs)
                {
                    //using (new PerformanceTimer("Tick::Chest", 1))
                    {
                        var addedChests = new List <ChestLocation>();
                        foreach (var chest in LokiPoe.ObjectManager.GetObjectsByType <Chest>().ToList())
                        {
                            ChestLocation location;
                            if (!_chestLocations.TryGetValue(chest.Id, out location))
                            {
                                location = new ChestLocation
                                {
                                    Id            = chest.Id,
                                    Name          = chest.Name,
                                    IsTargetable  = chest.IsTargetable,
                                    IsOpened      = chest.IsOpened,
                                    IsStrongBox   = chest.IsStrongBox,
                                    IsVaalVessel  = chest.IsVaalVessel,
                                    OpensOnDamage = chest.OpensOnDamage,
                                    Position      = chest.Position,
                                    Stats         = chest.Stats.ToList(),
                                    IsIdentified  = chest.IsIdentified,
                                    IsBreakable   = chest.OpensOnDamage,
                                    Rarity        = chest.Rarity,
                                    Metadata      = chest.Type
                                };

                                _chestLocations.Add(location.Id, location);

                                addedChests.Add(location);
                            }

                            if (!location.IsOpened)
                            {
                                location.IsOpened     = chest.IsOpened;
                                location.IsLocked     = chest.IsLocked;
                                location.IsTargetable = chest.IsTargetable;
                                // Support for chests that change locked state, without the lock state updating.
                                var tc = chest.Components.TransitionableComponent;
                                if (tc != null)
                                {
                                    if ((tc.Flag1 & 2) != 0)
                                    {
                                        location.IsLocked = false;
                                    }
                                }
                                if (chest.IsVaalVessel)
                                {
                                    location.IsLocked = false;
                                }
                                if (!location.IsCorrupted && chest.IsCorrupted)
                                {
                                    location.IsCorrupted = chest.IsCorrupted;
                                    location.Stats       = chest.Stats.ToList();
                                }
                                if (!location.IsIdentified && chest.IsIdentified)
                                {
                                    location.IsIdentified = chest.IsIdentified;
                                    location.Stats        = chest.Stats.ToList();
                                }
                            }

                            if (addedChests.Count > 10)
                            {
                                break;
                            }
                        }

                        foreach (var location in addedChests)
                        {
                            if (!location.IsBreakable)
                            {
                                location.Position = ExilePather.FastWalkablePositionFor(location.Position);
                            }

                            LokiPoe.InvokeEvent(OnChestLocationAdded, null, new OnChestLocationAddedEventArgs(location));
                        }

                        addedChests.Clear();

                        _chestThrottle.Restart();
                    }
                }
            }

            if (!_questThrottle.IsRunning)
            {
                _questThrottle.Start();
            }
            else
            {
                if (_questThrottle.ElapsedMilliseconds >= QuestThrottleMs)
                {
                    if (LokiPoe.CurrentWorldArea.IsMissionArea)
                    {
                        if (!HasKaruiSpiritLocation)
                        {
                            var obj = LokiPoe.ObjectManager.GetObjectByName("Karui Spirit");
                            if (obj != null)
                            {
                                AddLocation(ExilePather.FastWalkablePositionFor(obj), obj.Id, obj.Name);
                                HasKaruiSpiritLocation = true;
                            }
                        }
                    }

                    _questThrottle.Restart();
                }
            }

            if (!_throttle.IsRunning)
            {
                _throttle.Start();
            }
            else
            {
                if (_throttle.ElapsedMilliseconds >= ThrottleMs)
                {
                    if (!_timeInInstance.IsRunning)
                    {
                        _timeInInstance.Start();
                    }

                    if (!_timeInArea.IsRunning)
                    {
                        _timeInArea.Start();
                    }

                    // Do we need to update wp state flags.
                    if (_updateCheckForWaypoint)
                    {
                        // If the current area doesn't have a wp, we do not want to do any more logic processing.
                        if (!LokiPoe.CurrentWorldArea.HasWaypoint)
                        {
                            _updateCheckForWaypoint = false;
                            ShouldCheckForWaypoint  = false;
                            HasWaypointLocation     = false;
                            HasWaypointEntry        = false;
                        }
                        else
                        {
                            ShouldCheckForWaypoint = true;
                        }
                    }

                    // Do we need to update at state flags.
                    if (_updateAreaTransition)
                    {
                        ShouldCheckForAreaTransition = true;
                    }

                    if (ShouldCheckForStash)
                    {
                        //using (new PerformanceTimer("ShouldCheckForStash", 1))
                        {
                            if (!HasStashLocation)
                            {
                                var stash = LokiPoe.ObjectManager.Stash;
                                if (stash != null)
                                {
                                    // Save the location so we know where it is when the entity isn't in view.
                                    AddLocation(ExilePather.FastWalkablePositionFor(stash), stash.Id, "Stash");

                                    // We now have the waypoint location.
                                    HasStashLocation = true;
                                }
                            }
                            else
                            {
                                ShouldCheckForStash = false;
                            }
                        }
                    }

                    // If we need to handle wps.
                    if (ShouldCheckForWaypoint)
                    {
                        //using (new PerformanceTimer("ShouldCheckForWaypoint", 1))
                        {
                            // If we don't have the wp location yet, check to see if we see one.
                            if (!HasWaypointLocation)
                            {
                                var wp = LokiPoe.ObjectManager.Waypoint;
                                if (wp != null)
                                {
                                    // Save the location so we know where it is when the entity isn't in view.
                                    AddLocation(ExilePather.FastWalkablePositionFor(wp), wp.Id, "Waypoint");

                                    // We now have the waypoint location.
                                    HasWaypointLocation = true;
                                }
                            }

                            // If we don't have the wp entry yet, poll for us having it now.
                            // But only if we've seen the waypoint, since otherwise there's no way we have it.
                            if (HasWaypointLocation && !HasWaypointEntry)
                            {
                                var areaId = WorldArea.Id;
                                HasWaypointEntry = LokiPoe.InstanceInfo.AvailableWaypoints.ContainsKey(areaId);
                            }

                            // Once we have both the location and the entry, we do not need to execute wp logic anymore.
                            if (HasWaypointLocation && HasWaypointEntry)
                            {
                                _updateCheckForWaypoint = false;
                                ShouldCheckForWaypoint  = false;
                            }
                        }
                    }

                    // If we need to handle ats.
                    if (ShouldCheckForAreaTransition)
                    {
                        //using (new PerformanceTimer("ShouldCheckForAreaTransition", 1))
                        {
                            // If there are any area transitions on screen, add them if we don't already know of them.
                            foreach (var transition in LokiPoe.ObjectManager.Objects.OfType <AreaTransition>().ToList())
                            {
                                var name = transition.Name;

                                // We have to check all this in order to handle the areas that have transitions with the same name, but different
                                // entity ids.
                                if (HasLocation(name, transition.Id))
                                {
                                    continue;
                                }

                                AddLocation(ExilePather.FastWalkablePositionFor(transition), transition.Id, name);

                                if (!SeenAreaTransitions.Contains(name))
                                {
                                    SeenAreaTransitions.Add(name);
                                }
                            }
                        }
                    }

                    // Check to see if we need a new anchor point to kite back towards.
                    if (!_hasAnchorPoint || LokiPoe.LocalData.AreaHash != _anchorPointSeed)
                    {
                        ResetAnchorPoint();
                        ResetCurrentAnchorPoint();
                    }

                    _throttle.Restart();
                }
            }
        }
 public static bool PathExists(this NetworkObject obj)
 {
     return(ExilePather.PathExistsBetween(LokiPoe.MyPosition, obj.Position));
 }
Exemple #20
0
        public static WorldPosition FindWalkablePosition(Vector2i pos, int radius = 15)
        {
            var walkable = ExilePather.FastWalkablePositionFor(pos, radius);

            return(ExilePather.PathExistsBetween(LokiPoe.MyPosition, walkable) ? new WorldPosition(walkable) : null);
        }
Exemple #21
0
        /// <summary>
        /// Attempts to move towards a position. This function will perform pathfinding logic and take into consideration move distance
        /// to try and smoothly move towards a point.
        /// </summary>
        /// <param name="position">The position to move towards.</param>
        /// <param name="user">A user object passed.</param>
        /// <returns>true if the position was moved towards, and false if there was a pathfinding error.</returns>
        public bool MoveTowards(Vector2i position, params dynamic[] user)
        {
            var myPosition = LokiPoe.MyPosition;

            if (
                _cmd == null ||                                                                                   // No command yet
                _cmd.Path == null ||
                _cmd.EndPoint != position ||                                                                      // Moving to a new position
                LokiPoe.CurrentWorldArea.IsTown ||                                                                // In town, always generate new paths
                (_sw.IsRunning && _sw.ElapsedMilliseconds > OldPlayerMoverSettings.Instance.PathRefreshRateMs) || // New paths on interval
                _cmd.Path.Count <= 2 ||                                                                           // Not enough points
                _cmd.Path.All(p => myPosition.Distance(p) > 7))
            // Try and find a better path to follow since we're off course
            {
                _cmd = new PathfindingCommand(myPosition, position, 3, OldPlayerMoverSettings.Instance.AvoidWallHugging);
                if (!ExilePather.FindPath(ref _cmd))
                {
                    _sw.Restart();
                    Log.ErrorFormat("[OldPlayerMover.MoveTowards] ExilePather.FindPath failed from {0} to {1}.",
                                    myPosition, position);
                    return(false);
                }
                //Log.InfoFormat("[OldPlayerMover.MoveTowards] Finding new path.");
                _sw.Restart();
                //_originalPath = new IndexedList<Vector2i>(_cmd.Path);
            }

            // Eliminate points until we find one within a good moving range.
            while (_cmd.Path.Count > 1)
            {
                if (_cmd.Path[0].Distance(myPosition) < OldPlayerMoverSettings.Instance.MoveRange)
                {
                    _cmd.Path.RemoveAt(0);
                }
                else
                {
                    break;
                }
            }

            var point = _cmd.Path[0];

            point += new Vector2i(LokiPoe.Random.Next(-2, 3), LokiPoe.Random.Next(-2, 3));

            if (_useForceAdjustments)
            {
                var negX = 0;
                var posX = 0;

                var tmp1 = point;
                var tmp2 = point;

                for (var i = 0; i < 10; i++)
                {
                    tmp1.X--;
                    if (!ExilePather.IsWalkable(tmp1))
                    {
                        negX++;
                    }

                    tmp2.X++;
                    if (!ExilePather.IsWalkable(tmp2))
                    {
                        posX++;
                    }
                }

                if (negX > 5 && posX == 0)
                {
                    point.X += 10;
                    if (OldPlayerMoverSettings.Instance.DebugAdjustments)
                    {
                        Log.WarnFormat("[OldPlayerMover.MoveTowards] X-Adjustments being made!");
                    }
                    _cmd.Path[0] = point;
                }
                else if (posX > 5 && negX == 0)
                {
                    point.X -= 10;
                    if (OldPlayerMoverSettings.Instance.DebugAdjustments)
                    {
                        Log.WarnFormat("[OldPlayerMover.MoveTowards] X-Adjustments being made!");
                    }
                    _cmd.Path[0] = point;
                }

                var negY = 0;
                var posY = 0;

                tmp1 = point;
                tmp2 = point;

                for (var i = 0; i < 10; i++)
                {
                    tmp1.Y--;
                    if (!ExilePather.IsWalkable(tmp1))
                    {
                        negY++;
                    }

                    tmp2.Y++;
                    if (!ExilePather.IsWalkable(tmp2))
                    {
                        posY++;
                    }
                }

                if (negY > 5 && posY == 0)
                {
                    point.Y += 10;
                    if (OldPlayerMoverSettings.Instance.DebugAdjustments)
                    {
                        Log.WarnFormat("[OldPlayerMover.MoveTowards] Y-Adjustments being made!");
                    }
                    _cmd.Path[0] = point;
                }
                else if (posY > 5 && negY == 0)
                {
                    point.Y -= 10;
                    if (OldPlayerMoverSettings.Instance.DebugAdjustments)
                    {
                        Log.WarnFormat("[OldPlayerMover.MoveTowards] Y-Adjustments being made!");
                    }
                    _cmd.Path[0] = point;
                }
            }

            // Le sigh...
            if (_useAct3TownAdjustments)
            {
                var seed = LokiPoe.LocalData.AreaHash;
                if (_tgtSeed != seed || _tgts == null)
                {
                    Log.InfoFormat("[OldPlayerMover.MoveTowards] Now building TGT info.");
                    _tgts    = LokiPoe.TerrainData.TgtEntries;
                    _tgtSeed = seed;
                }
                if (TgtUnderPlayer.TgtName.Equals("Art/Models/Terrain/Act3Town/Act3_town_01_01_c16r7.tgt"))
                {
                    Log.InfoFormat("[OldPlayerMover.MoveTowards] Act 3 Town force adjustment being made!");
                    point.Y += 5;
                }
            }

            var move = LokiPoe.InGameState.SkillBarHud.LastBoundMoveSkill;

            if (move == null)
            {
                Log.ErrorFormat("[OldPlayerMover.MoveTowards] Please assign the \"Move\" skill to your skillbar!");
                return(false);
            }

            if ((LokiPoe.ProcessHookManager.GetKeyState(move.BoundKeys.Last()) & 0x8000) != 0 &&
                LokiPoe.Me.HasCurrentAction)
            {
                if (myPosition.Distance(position) < OldPlayerMoverSettings.Instance.SingleUseDistance)
                {
                    LokiPoe.ProcessHookManager.ClearAllKeyStates();
                    LokiPoe.InGameState.SkillBarHud.UseAt(move.Slots.Last(), false, point);
                    if (OldPlayerMoverSettings.Instance.DebugInputApi)
                    {
                        Log.WarnFormat("[SkillBarHud.UseAt] {0}", point);
                    }
                    _lastPoint = point;
                }
                else
                {
                    if (OldPlayerMoverSettings.Instance.UseMouseSmoothing)
                    {
                        var d = _lastPoint.Distance(point);
                        if (d >= OldPlayerMoverSettings.Instance.MouseSmoothDistance)
                        {
                            MouseManager.SetMousePos("OldPlayerMover.MoveTowards", point, false);
                            if (OldPlayerMoverSettings.Instance.DebugInputApi)
                            {
                                Log.WarnFormat("[MouseManager.SetMousePos] {0} [{1}]", point, d);
                            }
                            _lastPoint = point;
                        }
                        else
                        {
                            if (OldPlayerMoverSettings.Instance.DebugInputApi)
                            {
                                Log.WarnFormat("[MouseManager.SetMousePos] Skipping moving mouse to {0} because [{1}] < [{2}]", point, d, OldPlayerMoverSettings.Instance.MouseSmoothDistance);
                            }
                        }
                    }
                    else
                    {
                        MouseManager.SetMousePos("OldPlayerMover.MoveTowards", point, false);
                    }
                }
            }
            else
            {
                LokiPoe.ProcessHookManager.ClearAllKeyStates();
                if (myPosition.Distance(position) < OldPlayerMoverSettings.Instance.SingleUseDistance)
                {
                    LokiPoe.InGameState.SkillBarHud.UseAt(move.Slots.Last(), false, point);
                    if (OldPlayerMoverSettings.Instance.DebugInputApi)
                    {
                        Log.WarnFormat("[SkillBarHud.UseAt] {0}", point);
                    }
                }
                else
                {
                    LokiPoe.InGameState.SkillBarHud.BeginUseAt(move.Slots.Last(), false, point);
                    if (OldPlayerMoverSettings.Instance.DebugInputApi)
                    {
                        Log.WarnFormat("[BeginUseAt] {0}", point);
                    }
                }
            }

            return(true);
        }
Exemple #22
0
        /// <summary>
        /// This coroutine interacts with a npc and waits for the npc dialog panel to open. When called for a non-main town npc
        /// the npc must be in spawn range, otherwise the coroutine will fail. The movement is done without returning,
        /// so this should be carefully used when not in town.
        /// </summary>
        /// <param name="name">Name of the NPC to interact with</param>
        /// <param name="skipTalk">Should the bot skip all the dialog NPC's have before the dialog panel appears"</param>
        /// <returns>An OpenStashError that describes the result.</returns>
        public static async Task <Results.TalkToNpcError> TalkToNpc(string name, bool skipTalk = true)
        {
            await Coroutines.CloseBlockingWindows();

            await Coroutines.FinishCurrentAction();

            var npc = LokiPoe.ObjectManager.GetObjectByName(name);

            if (npc == null)
            {
                var pos = Actor.GuessNpcLocation(name);

                if (pos == Vector2i.Zero)
                {
                    return(Results.TalkToNpcError.NoNpc);
                }

                if (!await Navigation.MoveToLocation(ExilePather.FastWalkablePositionFor(pos), 25, 60000, () => LokiPoe.ObjectManager.GetObjectByName(name) != null))
                {
                    return(Results.TalkToNpcError.CouldNotMoveToNpc);
                }

                npc = LokiPoe.ObjectManager.GetObjectByName(name);
                if (npc == null)
                {
                    return(Results.TalkToNpcError.NoNpc);
                }
            }

            if (ExilePather.PathDistance(LokiPoe.MyPosition, npc.Position) > 30)
            {
                if (!await Navigation.MoveToLocation(ExilePather.FastWalkablePositionFor(npc.Position), 25, 15000, () => false))
                {
                    return(Results.TalkToNpcError.CouldNotMoveToNpc);
                }

                npc = LokiPoe.ObjectManager.GetObjectByName(name);
                if (npc == null)
                {
                    return(Results.TalkToNpcError.NoNpc);
                }
            }

            await Coroutines.FinishCurrentAction();

            if (!await InteractWith(npc))
            {
                return(Results.TalkToNpcError.InteractFailed);
            }

            // Clicking continue if NPC is blablaing (xD)
            while (skipTalk && LokiPoe.InGameState.NpcDialogUi.DialogDepth != 1)
            {
                if (LokiPoe.InGameState.NpcDialogUi.DialogDepth == 2)
                {
                    CommunityLib.Log.DebugFormat("[CommunityLib][TalkToNpc] Now closing a dialog/reward window.");
                    LokiPoe.Input.SimulateKeyEvent(Keys.Escape, true, false, false);
                    // Give the client enough time to close the gui itself. It waits for the server to show the new one.
                    await Coroutine.Sleep(LokiPoe.Random.Next(800, 1000));

                    await Coroutines.ReactionWait();
                }
                else
                {
                    CommunityLib.Log.InfoFormat("[CommunityLib][TalkToNpc] Waiting for the Npc window to open.");
                    await Coroutines.ReactionWait();
                }
            }

            if (!await Dialog.WaitForPanel(Dialog.PanelType.NpcDialog))
            {
                return(Results.TalkToNpcError.NpcDialogPanelDidNotOpen);
            }

            return(Results.TalkToNpcError.None);
        }