Exemple #1
0
        /// <summary>
        /// Returns a path that prevents collisions with the navmesh, but floats freely otherwise
        /// </summary>
        /// <param name="zone"></param>
        /// <param name="start">Start in GlobalXYZ</param>
        /// <param name="end">End in GlobalXYZ</param>
        /// <returns></returns>
        public static PathPoint[] GetPathStraight(Zone2 zone, Vector3 start, Vector3 end, dtPolyFlags includeFilter = dtPolyFlags.ALL ^ dtPolyFlags.DISABLED, dtPolyFlags excludeFilter = 0, float polyExtX = 64.0f, float polyExtY = 64.0f, float polyExtZ = 256.0f, dtStraightPathOptions options = dtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(null);
            }

            var ptrs        = _loadedZones[zone.ID];
            var startFloats = (start + zAxis * 8).ToRecastFloats();
            var endFloats   = (end + zAxis * 8).ToRecastFloats();

            var numNodes = 0;
            var buffer   = new float[MAX_POLY * 3];
            var flags    = new dtPolyFlags[MAX_POLY];
            var filter   = new[] { includeFilter, excludeFilter };

            PathStraight(ptrs.queryPtr, startFloats, endFloats, new Vector3(polyExtX, polyExtY, polyExtZ).ToRecastFloats(), filter, options, ref numNodes, buffer, flags);

            var points    = new PathPoint[numNodes];
            var positions = Vector3ArrayFromRecastFloats(buffer, numNodes);

            for (var i = 0; i < numNodes; i++)
            {
                points[i].Position = positions[i];
                points[i].Flags    = flags[i];
            }

            return(points);
        }
Exemple #2
0
 /// <summary>
 /// Creates a new heightmap
 /// </summary>
 /// <param name="zone"></param>
 public HeightMap(Zone2 zone)
 {
     _terrainMap    = zone.LoadTerrainMap();
     _terrainFactor = zone.TerrainMapScaleFactor;
     _offsetMap     = zone.LoadOffsetMap();
     _offsetFactor  = zone.OffsetMapScaleFactor;
     _loc2Px        = 1.0f * (_size = _terrainMap.GetLength(0)) / zone.Width;
     Log.Debug("Loaded heightmap for {0}", zone);
 }
Exemple #3
0
 /// <summary>
 /// Unloads a zone
 /// </summary>
 /// <param name="z"></param>
 public static void Unload(Zone2 z)
 {
     lock (_loadedZones)
     {
         if (_loadedZones.ContainsKey(z.ID))
         {
             RecastMesh m = _loadedZones[z.ID];
             if (m != null)
             {
                 FreeNavMesh(m.meshPtr, m.queryPtr);
             }
             _loadedZones.Remove(z.ID);
         }
     }
 }
Exemple #4
0
        public static bool SetPolyFlags(Zone2 zone, uint polyRef, dtPolyFlags flags)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(false);
            }

            var ptrs   = _loadedZones[zone.ID];
            var status = SetPolyFlags(ptrs.meshPtr, polyRef, flags);

            if ((status & dtStatus.DT_FAILURE) == dtStatus.DT_FAILURE)
            {
                return(false);
            }
            return(true);
        }
Exemple #5
0
        /// <summary>
        /// Loads all world related data
        /// </summary>
        public static void Init()
        {
            Log.Normal("Loading World ...");

            // Regions
            foreach (var reg in Region.LoadRegions())
            {
                _regions.Add(reg.ID, reg);
            }
            // Zones
            foreach (var zone in Zone2.LoadZones(_regions))
            {
                _zones.Add(zone.ID, zone);
            }

            // Navmeshs
            NavmeshMgr.InitRecast();
        }
Exemple #6
0
        /// <summary>
        /// Loads all zones and associates them with the appropriate regions
        /// </summary>
        /// <param name="regions"></param>
        /// <returns></returns>
        public static IEnumerable <Zone2> LoadZones(Dictionary <ushort, Region> regions)
        {
            IniFile ini;

            using (Stream fs = ClientData.ZonesDat)
                ini = new IniFile(fs);

            // Load Zones
            var newZones = from entry in ini.Topics
                           where entry.Name.StartsWith("zone") && entry.Items["enabled"] != "0"
                           select new { ID = ushort.Parse(entry.Name.Substring("zone".Length)), Data = entry.Items };
            int zones = 0;

            foreach (var entry in newZones)
            {
                ushort regionID = ushort.Parse(entry.Data["region"]);

                if (!regions.ContainsKey(regionID))
                {
                    regions.Add(regionID, new Region(regionID, "")); // some zones miss region entries
                }
                Region region = regions[regionID];

                ushort zoneID = entry.ID;
                string name   = entry.Data["name"];
                ushort proxy  = 0;
                if (entry.Data.ContainsKey("proxy_zone"))
                {
                    proxy = ushort.Parse(entry.Data["proxy_zone"]);
                }
                int w    = int.Parse(entry.Data["width"]) * 8192;
                int h    = int.Parse(entry.Data["height"]) * 8192;
                int xoff = int.Parse(entry.Data["region_offset_x"]) * 8192;
                int yoff = int.Parse(entry.Data["region_offset_y"]) * 8192;
                var type = (eZoneType)int.Parse(entry.Data.ContainsKey("type") ? entry.Data["type"] : "0");
                var zone = new Zone2(region, zoneID, name, xoff, yoff, w, h, type, proxy);
                region.Add(zoneID, zone);
                yield return(zone);

                zones++;
            }
            Log.Normal("Loaded {0} zones in {1} regions!", zones, regions.Count);
        }
Exemple #7
0
        public static bool GetPolyAt(Zone2 zone, Vector3 center, Vector3 extents, dtPolyFlags includeFilter, dtPolyFlags excludeFilter, ref uint polyRef, ref Vector3 point)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(false);
            }

            float[] outPoint = new float[3];

            var ptrs   = _loadedZones[zone.ID];
            var status = GetPolyAt(ptrs.queryPtr, center.ToRecastFloats(), extents.ToRecastFloats(), new dtPolyFlags[] { includeFilter, excludeFilter }, ref polyRef, outPoint);

            point = new Vector3(outPoint[0] * INV_FACTOR, outPoint[2] * INV_FACTOR, outPoint[1] * INV_FACTOR);
            if ((status & dtStatus.DT_FAILURE) == dtStatus.DT_FAILURE)
            {
                return(false);
            }
            return(true);
        }
Exemple #8
0
        /// <summary>
        /// Gets or loads a recast mesh
        /// </summary>
        private static RecastMesh LoadZoneMesh(Zone2 zone)
        {
            lock (_loadedZones) {
                if (_loadedZones.ContainsKey(zone.ID))
                {
                    return(_loadedZones[zone.ID]);
                }

                RecastMesh mesh = null;
                try {
                    string file = zone.NavFile;
                    if (!File.Exists(file))
                    {
                        return(null);              // no navmesh available
                    }
                    file = Path.GetFullPath(file); // not sure if c dll can load relative stuff
                    IntPtr meshPtr  = IntPtr.Zero;
                    IntPtr queryPtr = IntPtr.Zero;

                    if (!LoadNavMesh(file, ref meshPtr, ref queryPtr))
                    {
                        Log.Error("Loading NavMesh failed for {0}!", zone);
                        return(null);
                    }

                    if (meshPtr == IntPtr.Zero || queryPtr == IntPtr.Zero)
                    {
                        Log.Error("Loading NavMesh failed for {0}! (Pointer was zero!)", zone);
                        return(null);
                    }
                    Log.Normal("Loading NavMesh sucessful for region {0}", zone);
                    return(mesh = new RecastMesh(meshPtr, queryPtr));
                }
                finally {
                    _loadedZones.Add(zone.ID, mesh);
                }
            }
        }
Exemple #9
0
        public static bool QueryPolygons(Zone2 zone, Vector3 center, Vector3 polyPickExt, dtPolyFlags includeFlags, dtPolyFlags excludeFlags, ref uint[] results, int maxResults = 32)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(false);
            }

            var resultIdBuffer = new uint[maxResults];
            var resultCount    = 0;

            var ptrs   = _loadedZones[zone.ID];
            var status = QueryPolygons(ptrs.queryPtr, center.ToRecastFloats(), polyPickExt.ToRecastFloats(), new dtPolyFlags[] { includeFlags, excludeFlags }, resultIdBuffer, ref resultCount, maxResults);

            if ((status & dtStatus.DT_FAILURE) == dtStatus.DT_FAILURE)
            {
                return(false);
            }

            results = new uint[resultCount];
            Array.Copy(resultIdBuffer, results, resultCount);

            return(true);
        }
Exemple #10
0
        /// <summary>
        /// Returns the closest point on the navmesh (UNTESTED! EXPERIMENTAL! WILL GO SUPERNOVA ON USE! MAYBE!?)
        /// </summary>
        public static Vector3?GetClosestPoint(Zone2 zone, Vector3 position, float xRange = 256f, float yRange = 256f, float zRange = 256f)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(position);
            }

            var ptrs   = _loadedZones[zone.ID];
            var center = (position + zAxis * 8).ToRecastFloats();
            var outVec = new float[3];

            var defaultInclude = (dtPolyFlags.ALL ^ dtPolyFlags.DISABLED);
            var defaultExclude = (dtPolyFlags)0;
            var filter         = new dtPolyFlags[] { defaultInclude, defaultExclude };

            var polyPickEx = new Vector3(xRange, yRange, zRange).ToRecastFloats();

            FindClosestPoint(ptrs.queryPtr, center, polyPickEx, filter, outVec);

            var result = new Vector3(outVec[0] * INV_FACTOR, outVec[2] * INV_FACTOR, outVec[1] * INV_FACTOR);

            return(result == Vector3.Zero ? null : (Vector3?)result);
        }
Exemple #11
0
        /// <summary>
        /// Returns a random point on the navmesh around the given position
        /// </summary>
        /// <param name="zone">Zone</param>
        /// <param name="position">Start in GlobalXYZ</param>
        /// <param name="radius">End in GlobalXYZ</param>
        /// <returns></returns>
        public static Vector3 GetRandomPoint(Zone2 zone, Vector3 position, float radius)
        {
            if (!_loadedZones.ContainsKey(zone.ID))
            {
                return(Vector3.Zero);
            }

            var ptrs    = _loadedZones[zone.ID];
            var center  = (position + zAxis * 8).ToRecastFloats();
            var cradius = (radius * CONVERSION_FACTOR);
            var outVec  = new float[3];

            var defaultInclude = (dtPolyFlags.ALL ^ dtPolyFlags.DISABLED);
            var defaultExclude = (dtPolyFlags)0;
            var filter         = new dtPolyFlags[] { defaultInclude, defaultExclude };

            var polyPickEx = new float[3] {
                2.0f, 4.0f, 2.0f
            };

            FindRandomPointAroundCircle(ptrs.queryPtr, center, cradius, polyPickEx, filter, outVec);

            return(new Vector3(outVec[0] * INV_FACTOR, outVec[2] * INV_FACTOR, outVec[1] * INV_FACTOR));
        }
Exemple #12
0
        /// <summary>
        /// Builds the navmesh for the specified zone
        /// </summary>
        public static void BuildNavMesh(Zone2 z)
        {
            if (z.Name == "ArtOutside" || z.Name == "ArtInside")
            {
                Log.Normal("Skipping zone {0} because it has name {1}", z, z.Name);
                return;
            }
            if (z.ProxyZone != 0)
            {
                Log.Normal("Skipping zone {0} because it has a proxy zone id {1}", z, z.ProxyZone);
                return;
            }

            string obj = z.ObjFile;
            string nav = z.NavFile.Replace(".gz", "");

            for (int i = 0; i <= 1; i++)
            {
                // Create .obj
                if (i == 1)
                {
                    LoadZoneMesh(z);
                }
                else
                {
                    Unload(z);
                }
                DateTime start = DateTime.Now;
                Log.Normal("Building navmesh for zone {0} (pass={1})...", z, i);
                if (File.Exists(obj))
                {
                    File.Delete(obj);
                }
                using (var exp = new Zone2Obj(z))
                    exp.Export();
                Unload(z);

                if (Program.Arguments.ExportObjOnly)
                {
                    return;
                }

                // .obj -> .nav
                //if (i == 0)
                {
                    Log.Normal("Running buildnav.exe for {0}", z.Name);
                    Process buildnav = Process.Start("buildnav.exe", Util.MakeProcessArguments(new[] { obj.Replace(".obj", ".geomset"), nav }));
                    buildnav.PriorityClass = ProcessPriorityClass.BelowNormal;
                    buildnav.WaitForExit();
                    if (buildnav.ExitCode > 0)
                    {
                        throw new InvalidOperationException("buildnav.exe failed with " + buildnav.ExitCode);
                    }
                    if (!File.Exists(nav))
                    {
                        Log.Error("Did not generate navmesh for file {0} for unknown reasons", nav);
                    }
                    else if (new FileInfo(nav).Length < 2048)
                    {
                        // empty mesh
                        Log.Warn("{0} was empty :(", nav);
                        File.Delete(nav);
                    }
                }

                Log.Normal("Zone {0} finished in {1}", z, DateTime.Now - start);
                lock (_loadedZones)
                {
                    if (_loadedZones.ContainsKey(z.ID))
                    {
                        _loadedZones.Remove(z.ID);
                    }
                }
            }
        }
Exemple #13
0
 /// <summary>
 /// True if pathing is enabled for the specified region
 /// </summary>
 public static bool IsPathingEnabled(Zone2 zone)
 {
     return(_loadedZones.ContainsKey(zone.ID));
 }