protected double TryPath(Vector3 start, Vector3 end, out System.Collections.Generic.List <Hop> hops, bool acceptIncomplete) { var result = Pather.FindPath(start, end); Assert.IsNotNull(result); Assert.Greater(result.Count, 0); // make sure we didn't get an incomplete path if (!acceptIncomplete) { Assert.Less((end - result[result.Count - 1].Location).Length(), 5f); } foreach (var hop in result) { float tx, ty; Pather.GetTileByLocation(hop.Location.ToRecast().ToFloatArray(), out tx, out ty); Console.WriteLine("TX: " + tx + " TY: " + ty + " X: " + hop.Location.X + " Y: " + hop.Location.Y + " Z: " + hop.Location.Z); } Console.WriteLine("Memory: " + (Pather.MemoryPressure / 1024 / 1024) + "MB"); double length = 0; for (int i = 0; i < result.Count - 1; i++) { length += (result[i].Location - result[i + 1].Location).Length(); } hops = result; return(length); }
public void CrossingTest() { MpqManager.Initialize("S:\\WoW"); byte[] dataA, dataB; // Build tile A { var builder = new TileBuilder("Azeroth", 31, 49); dataA = builder.Build(new ConsoleLog()); Assert.IsNotNull(dataA); } // Build tile B { var builder = new TileBuilder("Azeroth", 32, 49); dataB = builder.Build(new ConsoleLog()); Assert.IsNotNull(dataB); } // Load into mesh var pather = new Pather("Azeroth"); Assert.IsTrue(pather.LoadTile(dataA)); Assert.IsTrue(pather.LoadTile(dataB)); // and try pathing, coords from AzerothMeshTest -> TileCrossing which is a non-building version of this var start = new Vector3(-9467.8f, 64.2f, 55.9f); var end = new Vector3(-9248.9f, -93.35f, 70.3f); var path = pather.FindPath(start, end); // check result Assert.IsNotNull(path); Assert.Greater(path.Count, 0); Assert.Less((end - path[path.Count - 1].Location).Length(), 3f); }
protected void TryPath(Vector3 start, Vector3 end) { var result = Pather.FindPath(start, end); Assert.IsNotNull(result); Assert.Greater(result.Count, 0); // make sure we didn't get an incomplete path Assert.Less((end - result[result.Count - 1].Location).Length(), 5f); foreach (var hop in result) { Console.WriteLine("X: " + hop.Location.X + " Y: " + hop.Location.Y + " Z: " + hop.Location.Z); } Console.WriteLine("Memory: " + (Pather.MemoryPressure / 1024) + "kB"); }
public static void MoveTomephisto() { PC me = new PC(); AreaMap map = new AreaMap(me.Area); map.Initialize(); Pather p = me.GetSkillLevel(SkillType.Teleport) > 0 ? new Pather(map, new TeleportReducer(25)) : p = new Pather(map, new WalkingReducer(7, 13)); p.FindPath(me.Position, new System.Drawing.Point(17564, 8069)); Pathing.Mover m = new Pathing.Mover(p); m.Move(me.GetSkillLevel(SkillType.Teleport) > 0 ? Reduction.TeleportReduction : Reduction.WalkingReduction); }
protected double TryPath(Vector3 start, Vector3 end, out System.Collections.Generic.List <Hop> hops, bool acceptIncomplete) { //Pather.LoadAllTiles(); var result = Pather.FindPath(start, end); if (result == null || result.Count == 0) { hops = new System.Collections.Generic.List <Hop>(); return(0); } //Assert.IsNotNull(result); //Assert.Greater(result.Count, 0); // make sure we didn't get an incomplete path if (!acceptIncomplete) { Assert.Less((end - result[result.Count - 1].Location).Length(), 5f); } double length = 0; for (int i = 0; i < result.Count - 1; i++) { length += (result[i].Location - result[i + 1].Location).Length(); } Console.WriteLine("Total distance flying : " + (end - start).Length() + ", walking : " + length); Console.WriteLine("Distance to end : " + (end - result[result.Count - 1].Location).Length()); /* foreach (var hop in result) * { * float tx, ty; * Pather.GetTileByLocation(hop.Location.ToRecast().ToFloatArray(), out tx, out ty); * Console.WriteLine("TX: " + tx + " TY: " + ty + " X: " + hop.Location.X + " Y: " + hop.Location.Y + " Z: " + hop.Location.Z); * }*/ Console.WriteLine("Number of hops : " + result.Count); Console.WriteLine("Memory: " + (Pather.MemoryPressure / 1024 / 1024) + "MB"); hops = result; return(length); }
public static bool PathTo(Location from, Location to, bool preferRoads = true) { try { // Reinstate the pather with our current continent/dungeon _Pather = new Pather(WoWWorld.CurrentMap); if (_Pather == null) { Log.WriteLine("Unable to instantiate the pather on map {0} (#{1})", WoWWorld.CurrentMap, WoWWorld.CurrentMapId); return(false); } if (preferRoads) { // Use only water if necessary _Pather.Filter.SetAreaCost((int)PolyArea.Water, 10); // Roads and terrain keeps their priority _Pather.Filter.SetAreaCost((int)PolyArea.Road, 1); _Pather.Filter.SetAreaCost((int)PolyArea.Terrain, 1); // Exclude flightmasters as they arent properly implemented (yet) // Remember that they are implemented in the mesh, just not into the pather! _Pather.Filter.ExcludeFlags = (int)PolyFlag.FlightMaster; // Eventually add (int)PolyFlag.Swim } // Convert our locations to XNA and request a path var hops = _Pather.FindPath(from.ToXNA(), to.ToXNA()); if (hops == null) { Log.WriteLine("Unable to generate path to {0}", to); return(false); } // Since we now know that we're ready to move, we can let the rest of the both know that we have a destination Destination = to; _lastLocation = from; stuckCheckTimer = DateTime.Now + TimeSpan.FromMilliseconds(5000); if (_GeneratedPath == null) { _GeneratedPath = new Queue <Location>(); } _GeneratedPath.Clear(); foreach (var hop in hops) { _GeneratedPath.Enqueue(new Location(hop.Location.X, hop.Location.Y, hop.Location.Z)); } } catch (NavMeshException ex) { Log.WriteLine("Exception in NavMesh (Status: {0}):", ex.Status); Log.WriteLine(ex.Message); Exception inner; while ((inner = ex.InnerException) != null) { Log.WriteLine(inner.Message); } Status = MovementStatus.Error; return(false); } catch (Exception ex) { return(false); } return(true); }
/// <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); } }