예제 #1
0
        /// <summary>
        /// Finds the path.
        /// </summary>
        /// <param name="from">From.</param>
        /// <param name="to">To.</param>
        /// <param name="continentNameMpq">The continent name MPQ.</param>
        /// <param name="resultSuccess">if set to <c>true</c> [result success].</param>
        /// <param name="addFromAndStart">if set to <c>true</c> [add from and start].</param>
        /// <param name="loadAllTile"></param>
        /// <returns></returns>
        private static List <Point> FindPath(Point from, Point to, string continentNameMpq, out bool resultSuccess,
                                             bool addFromAndStart, bool loadAllTile, bool ShortPath, bool hideMe = false)
        {
            // Prevent Z modified with "GetZ" to be passed as reference to original points/lists.
            from = new Point(from);
            to   = new Point(to);
            if (!hideMe)
            {
                // should be run only from the function that allow pathfinder patchwerk, nowhere else
                Logging.WriteError("FindPath: Error, accessed from unknown location.");
            }
            if (from.DistanceTo(to) <= 1f)
            {
                resultSuccess = true;
                return(new List <Point> {
                    from, to
                });
            }
            if (from.Type.ToLower() == "swimming")
            {
                if (TraceLine.TraceLineGo(new Point(to.X, to.Y, to.Z + 1000), to, Enums.CGWorldFrameHitFlags.HitTestLiquid))
                {
                    // The destination is in water
                    if (!TraceLine.TraceLineGo(from, to))
                    {
                        Logging.WriteNavigator("Swimmming right to the destination");
                        resultSuccess = true;
                        return(new List <Point> {
                            from, to
                        });
                    }
                    Logging.WriteNavigator("Swimming to the destination using the PathFinder");
                }
                else
                {
                    from.Z = GetZPosition(from); // get to the bottom of the ocean to avoid infinite 0 count path
                    Logging.WriteNavigator("Using the PathFinder to destination out of water");
                }
            }
            if (from.Type.ToLower() == "flying")
            {
                from.Z = GetZPosition(from);
                Logging.WriteNavigator("Using the PathFinder while flying");
            }
            List <Point> locList = new List <Point>();

            resultSuccess = true;
            try
            {
                if (!UsePatherFind || continentNameMpq == "None")
                {
                    locList.Add(from);
                    locList.Add(to);
                    return(locList);
                }

                if (_pather == null)
                {
                    _pather = new Pather(continentNameMpq);
                }
                if (_pather.Continent != continentNameMpq)
                {
                    _pather.Dispose();
                    _pather = new Pather(continentNameMpq);
                }

                if (addFromAndStart)
                {
                    locList.Add(from);
                }

                if (loadAllTile)
                {
                    _pather.LoadAllTiles();
                }

                bool failedPolyref;
                locList = ShortPath ? _pather.FindPathSimple(from, to, out resultSuccess, out failedPolyref, true) : _pather.FindPath(from, to, out resultSuccess, out failedPolyref);
                if (addFromAndStart && resultSuccess)
                {
                    locList.Add(to);
                }

                if (!resultSuccess && failedPolyref)
                {
                    /*Logging.WriteDebug("Reloading PathFinder...");
                     * _pather.Dispose();
                     * _pather = new Pather(continentNameMpq);
                     * locList = ShortPath ? _pather.FindPathSimple(from, to, out resultSuccess, out failedPolyref, true) : _pather.FindPath(from, to, out resultSuccess, out failedPolyref);
                     * if (addFromAndStart && resultSuccess)
                     *  locList.Add(to);*/
                }

                // Clean list:
                for (int i = 0; i <= locList.Count - 2; i++)
                {
                    if (locList[i].DistanceTo(locList[i + 1]) < 0.5 || !locList[i + 1].IsValid)
                    {
                        locList.RemoveAt(i + 1);
                        i--;
                    }
                }
                // Offset all points except origin and end to pass around obstacles by some distance.
                // We stop at 2.0 before each point in MovementManager and the meshes are done for a player of 0.6 in diameter.
                // So 2.0-0.6=1.4 is the strick minimum offset needed. Since 'click to point' has a precision of 0.5,
                // 1.4+0.5=1.9 is a pretty good value here.
                for (int i = locList.Count - 2; i > 0; i--)
                {
                    Point offset = Helpful.Math.GetPositionOffsetBy3DDistance(locList[i - 1], locList[i], 1.9f);
                    locList[i] = offset;
                }

                Logging.WriteNavigator("Path Count: " + locList.Count() + (resultSuccess ? "" : " but incomplete"));

                return(locList);
            }
            catch (Exception e)
            {
                Logging.WriteError("ToRecast(this Point v): PATH FIND ERROR: " + e);
                Console.WriteLine("Path find ERROR.");

                resultSuccess = false;
                locList       = new List <Point>();

                if (addFromAndStart)
                {
                    if (from != null)
                    {
                        if (from.X != 0 || from.Y != 0 || from.Z != 0)
                        {
                            locList.Add(from);
                        }
                    }

                    if (to != null)
                    {
                        if (to.X != 0 || to.Y != 0 || to.Z != 0)
                        {
                            locList.Add(to);
                        }
                    }
                }

                return(locList);
            }
        }