示例#1
0
        /// <summary>
        /// Links scenes objects together by cardinal direction
        /// </summary>
        /// <param name="scene"></param>
        public static void PopulateSceneConnections(CachedScene scene)
        {
            scene.ConnectedScenes.Clear();
            scene.ConnectedSceneGuids.Clear();

            scene.WestConnection  = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.EastEdgeCenter == scene.WestEdgeCenter && s.ExitCodes.Contains(Direction.East));
            scene.EastConnection  = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.WestEdgeCenter == scene.EastEdgeCenter && s.ExitCodes.Contains(Direction.West));
            scene.NorthConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.SouthEdgeCenter == scene.NorthEdgeCenter && s.ExitCodes.Contains(Direction.South));
            scene.SouthConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.NorthEdgeCenter == scene.SouthEdgeCenter && s.ExitCodes.Contains(Direction.North));

            if (scene.SouthConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.SouthConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.SouthConnection);
            }

            if (scene.WestConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.WestConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.WestConnection);
            }

            if (scene.NorthConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.NorthConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.NorthConnection);
            }

            if (scene.EastConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.EastConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.EastConnection);
            }
        }
示例#2
0
            internal static void UpdateSceneHistory()
            {
                if (ZetaDia.Me == null || !ZetaDia.Me.IsValid || ZetaDia.Me.IsDead)
                {
                    return;
                }

                CachedScene currentScene;

                if (!_scenes.TryGetValue(GetSceneHash(ZetaDia.Me.CurrentScene.Mesh.Zone), out currentScene))
                {
                    return;
                }

                if (currentScene == null)
                {
                    return;
                }

                if (_currentScene == null)
                {
                    _currentScene = currentScene;
                    return;
                }

                if (currentScene.SceneHash != _currentScene.SceneHash)
                {
                    _previousScene = _currentScene;
                }

                _currentScene = currentScene;
            }
示例#3
0
        /// <summary>
        /// Returns the point at which two givens scenes connect; Vector3.Zero if they don't connect.
        /// </summary>
        internal static Vector3 GetSceneConnectionPoint(CachedScene targetScene, CachedScene thisScene = null)
        {
            thisScene = thisScene ?? CurrentScene;

            if (thisScene.IsConnectedEast && thisScene.EastConnection.Equals(targetScene))
            {
                return(thisScene.EastEdgeCenter);
            }

            if (thisScene.IsConnectedWest && thisScene.WestConnection.Equals(targetScene))
            {
                return(thisScene.WestEdgeCenter);
            }

            if (thisScene.IsConnectedSouth && thisScene.SouthConnection.Equals(targetScene))
            {
                return(thisScene.SouthEdgeCenter);
            }

            if (thisScene.IsConnectedNorth && thisScene.NorthConnection.Equals(targetScene))
            {
                return(thisScene.NorthEdgeCenter);
            }

            return(Vector3.Zero);
        }
示例#4
0
        /// <summary>
        /// Exit codes (the _NSEW_ part of a scene name) are used to link scenes together
        /// I am aware that some scenes (entrances/exit/special) scenes do not have these codes.
        /// Todo: address non-coded scenes.
        /// </summary>
        public static void PopulateExitCodes(CachedScene scene)
        {
            var exitCodes = SceneConnectionDirectionsRegex.Matches(scene.Name);

            foreach (var exitCode in from object exitCode in exitCodes select exitCode.ToString())
            {
                var exitCount = exitCode.Trim('_').Count();

                scene.ConnectionCount = exitCount;

                if (exitCount == 1)
                {
                    scene.IsDeadEnd = true;
                }

                else if (exitCount == 2)
                {
                    scene.IsCorridor = true;
                }

                else if (exitCount == 4 || exitCount == 3)
                {
                    scene.IsMainHub = true;
                }

                foreach (var exitId in exitCode)
                {
                    if (exitId == 'E')
                    {
                        scene.ExitCodes.Add(Direction.East);
                    }

                    if (exitId == 'W')
                    {
                        scene.ExitCodes.Add(Direction.West);
                    }

                    if (exitId == 'N')
                    {
                        scene.ExitCodes.Add(Direction.North);
                    }

                    if (exitId == 'S')
                    {
                        scene.ExitCodes.Add(Direction.South);
                    }
                }
            }
        }
示例#5
0
        public void Render(SKCanvas canvas, float angleInRadians, SKPoint center, float scale)
        {
            if (_cachedScene == null)
            {
                _cachedScene = new CachedScene();
                var paint = new SKPaint();
                paint.IsAntialias            = true;
                paint.Color                  = new SKColor(0x2c, 0x3e, 0x50);
                paint.StrokeCap              = SKStrokeCap.Round;
                _cachedScene.LogoPaint       = paint;
                _cachedScene.BackgroundRect  = new SKRect(0, 0, 1080, 1800);
                _cachedScene.BackgroundPaint = new SKPaint {
                    Color = new SKColor(255, 10, 10)
                };
                _cachedScene.LogoPaths = new List <SKPath>();
                for (int i = 1; i <= Columns; i++)
                {
                    for (int y = 1; y <= Rows; y++)
                    {
                        var path = new SKPath();
                        path.MoveTo(71.4311121f, 56f);
                        path.CubicTo(68.6763107f, 56.0058575f, 65.9796704f, 57.5737917f, 64.5928855f, 59.965729f);
                        path.LineTo(43.0238921f, 97.5342563f);
                        path.CubicTo(41.6587026f, 99.9325978f, 41.6587026f, 103.067402f, 43.0238921f, 105.465744f);
                        path.LineTo(64.5928855f, 143.034271f);
                        path.CubicTo(65.9798162f, 145.426228f, 68.6763107f, 146.994582f, 71.4311121f, 147f);
                        path.LineTo(114.568946f, 147f);
                        path.CubicTo(117.323748f, 146.994143f, 120.020241f, 145.426228f, 121.407172f, 143.034271f);
                        path.LineTo(142.976161f, 105.465744f);
                        path.CubicTo(144.34135f, 103.067402f, 144.341209f, 99.9325978f, 142.976161f, 97.5342563f);
                        path.LineTo(121.407172f, 59.965729f);
                        path.CubicTo(120.020241f, 57.5737917f, 117.323748f, 56.0054182f, 114.568946f, 56f);
                        path.LineTo(71.4311121f, 56f);
                        path.Close();
                        path.Offset(160 * i, 160 * y);
                        _cachedScene.LogoPaths.Add(path);
                    }
                }
            }

            canvas.Clear(SKColors.White);
            canvas.DrawRect(_cachedScene.BackgroundRect, _cachedScene.BackgroundPaint);
            foreach (var path in _cachedScene.LogoPaths)
            {
                canvas.DrawPath(path, _cachedScene.LogoPaint);
            }
        }
示例#6
0
        /// <summary>
        /// Returns a list of scenes between the source scene and the target scene.
        /// </summary>
        internal static List <CachedScene> GetPathToScene(CachedScene targetScene, CachedScene fromScene = null)
        {
            fromScene = fromScene ?? CurrentScene;
            var       direction          = MathUtil.GetDirectionToPoint(targetScene.Center, fromScene.Center);
            var       checkedSceneHashes = new List <int>();
            var       path         = new List <CachedScene>();
            var       found        = false;
            var       done         = false;
            var       currentScene = fromScene;
            const int depthStop    = 20;
            var       depth        = 0;

            while (!found || depth > depthStop || done)
            {
                if (currentScene.IsConnectedTo(targetScene))
                {
                    path.Add(targetScene);
                    found = true;
                }
                else
                {
                    checkedSceneHashes.Add(currentScene.SceneHash);

                    // Attempt to get new scene by direction
                    var newScene = GetConnectedScene(direction, currentScene);

                    // Failing that, just grab any connected scene
                    if (checkedSceneHashes.Contains(newScene.SceneHash))
                    {
                        newScene = currentScene.ConnectedScenes.FirstOrDefault(s => !checkedSceneHashes.Contains(s.SceneHash));
                    }

                    if (newScene == null)
                    {
                        done = true;
                        continue;
                    }

                    currentScene = newScene;
                    path.Add(newScene);
                }
                depth++;
            }
            return(path);
        }
示例#7
0
        /// <summary>
        /// Returns a list of points between the source scene and the target scene.
        /// </summary>
        /// <param name="targetScene"></param>
        /// <param name="fromScene"></param>
        /// <returns></returns>
        internal static List <Vector3> GetVectorPathToScene(CachedScene targetScene, CachedScene fromScene = null)
        {
            fromScene = fromScene ?? CurrentScene;
            var scenePath     = GetPathToScene(targetScene, fromScene);
            var vectorPath    = new List <Vector3>();
            var previousScene = fromScene;

            scenePath.ForEach(scene =>
            {
                vectorPath.Add(GetSceneConnectionPoint(previousScene, scene));
                vectorPath.Add(scene.Center);
                previousScene = scene;
            });

            if (QuestToolsSettings.Instance.DebugEnabled)
            {
                Logger.Debug("Scene Route generated from {0} ({1}) to {2} ({3}) with {4} points", fromScene.Name, fromScene.SceneHash, targetScene.Name, targetScene.SceneHash, vectorPath.Count);
                vectorPath.ForEach(n => Logger.Log("Route Point: {0} Distance={1} Direction={2}", n, n.Distance(ZetaDia.Me.Position), MathUtil.GetDirectionToPoint(n)));
            }

            return(vectorPath);
        }
示例#8
0
        /// <summary>
        /// Returns a list of points that cover the closest walkable points to the four edges and center of the specified scene.
        /// </summary>
        internal static List <Vector3> GetSceneExploreRoute(CachedScene targetScene = null)
        {
            targetScene = targetScene ?? CurrentScene;
            var zone   = targetScene.Scene.Mesh.Zone;
            var points = zone.NavZoneDef.NavCells.Where(n => n.IsValid && n.Flags.HasFlag(NavCellFlags.AllowWalk)).Select(n => GetNavCellCenter(n, zone)).ToList();

            var route = new List <Vector3>
            {
                points.OrderBy(point => point.Distance2D(targetScene.Center)).FirstOrDefault(),
                points.OrderBy(point => point.Distance2D(targetScene.EastEdgeCenter)).FirstOrDefault(),
                points.OrderBy(point => point.Distance2D(targetScene.NorthEdgeCenter)).FirstOrDefault(),
                points.OrderBy(point => point.Distance2D(targetScene.SouthEdgeCenter)).FirstOrDefault(),
                points.OrderBy(point => point.Distance2D(targetScene.WestEdgeCenter)).FirstOrDefault()
            };

            if (QuestToolsSettings.Instance.DebugEnabled)
            {
                Logger.Debug("Scene Explore Route generated for {0} ({1}) with {2} points", targetScene.Name, targetScene.SceneHash, route.Count);
                route.ForEach(n => Logger.Log("Route Point: {0} Distance={1} Direction={2}", n, n.Distance(ZetaDia.Me.Position), MathUtil.GetDirectionToPoint(n)));
            }

            return(route);
        }
示例#9
0
文件: CachedMap.cs 项目: ipo/AGBA
 public CachedMapArea(Scene scene)
 {
     var temp = new CachedScene(scene);
     temp.UpdateNavcells();
     ZoneMin = new Vector2(temp.ZoneMin.X, temp.ZoneMin.Y);
     ZoneMax = new Vector2(temp.ZoneMax.X, temp.ZoneMax.Y);
     foreach (var cell in temp.NavCells)
     {
         var tempCell = new CachedMapCell(cell);
         if (tempCell.Passable)
         {
             Cells.Add(tempCell);
         }
     }
 }
示例#10
0
        /// <summary>
        /// Links scenes objects together by cardinal direction
        /// </summary>
        /// <param name="scene"></param>
        public static void PopulateSceneConnections(CachedScene scene)
        {
            scene.ConnectedScenes.Clear();
            scene.ConnectedSceneGuids.Clear();

            scene.WestConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.EastEdgeCenter == scene.WestEdgeCenter && s.ExitCodes.Contains(Direction.East));
            scene.EastConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.WestEdgeCenter == scene.EastEdgeCenter && s.ExitCodes.Contains(Direction.West));
            scene.NorthConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.SouthEdgeCenter == scene.NorthEdgeCenter && s.ExitCodes.Contains(Direction.South));
            scene.SouthConnection = Scenes.FirstOrDefault(s => s.SceneHash != scene.SceneHash && s.NorthEdgeCenter == scene.SouthEdgeCenter && s.ExitCodes.Contains(Direction.North));

            if (scene.SouthConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.SouthConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.SouthConnection);
            }

            if (scene.WestConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.WestConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.WestConnection);
            }

            if (scene.NorthConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.NorthConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.NorthConnection);
            }

            if (scene.EastConnection != null)
            {
                scene.ConnectedSceneGuids.Add(scene.EastConnection.SceneHash);
                scene.ConnectedScenes.Add(scene.EastConnection);
            }            
        }
示例#11
0
        /// <summary>
        /// Exit codes (the _NSEW_ part of a scene name) are used to link scenes together
        /// I am aware that some scenes (entrances/exit/special) scenes do not have these codes. 
        /// Todo: address non-coded scenes.
        /// </summary>
        public static void PopulateExitCodes(CachedScene scene)
        {
            var exitCodes = SceneConnectionDirectionsRegex.Matches(scene.Name);

            foreach (var exitCode in from object exitCode in exitCodes select exitCode.ToString())
            {
                var exitCount = exitCode.Trim('_').Count();

                scene.ConnectionCount = exitCount;

                if (exitCount == 1)
                    scene.IsDeadEnd = true;

                else if (exitCount == 2)
                    scene.IsCorridor = true;

                else if (exitCount == 4 || exitCount == 3)
                    scene.IsMainHub = true;

                foreach (var exitId in exitCode)
                {
                    if (exitId == 'E')
                        scene.ExitCodes.Add(Direction.East);

                    if (exitId == 'W')
                        scene.ExitCodes.Add(Direction.West);

                    if (exitId == 'N')
                        scene.ExitCodes.Add(Direction.North);

                    if (exitId == 'S')
                        scene.ExitCodes.Add(Direction.South);
                }
            }
        }
示例#12
0
        /// <summary>
        /// Returns the point at which two givens scenes connect; Vector3.Zero if they don't connect.
        /// </summary>
        internal static Vector3 GetSceneConnectionPoint(CachedScene targetScene, CachedScene thisScene = null)
        {
            thisScene = thisScene ?? CurrentScene;

            if (thisScene.IsConnectedEast && thisScene.EastConnection.Equals(targetScene))
                return thisScene.EastEdgeCenter;

            if (thisScene.IsConnectedWest && thisScene.WestConnection.Equals(targetScene))
                return thisScene.WestEdgeCenter;

            if (thisScene.IsConnectedSouth && thisScene.SouthConnection.Equals(targetScene))
                return thisScene.SouthEdgeCenter;

            if (thisScene.IsConnectedNorth && thisScene.NorthConnection.Equals(targetScene))
                return thisScene.NorthEdgeCenter;

            return Vector3.Zero;
        }
示例#13
0
            internal static void UpdateSceneHistory()
            {
                if (ZetaDia.Me == null || !ZetaDia.Me.IsValid || ZetaDia.Me.IsDead)
                    return;

                CachedScene currentScene;

                if (!_scenes.TryGetValue(GetSceneHash(ZetaDia.Me.CurrentScene.Mesh.Zone), out currentScene))
                    return;

                if (currentScene == null)
                    return;

                if (_currentScene == null)
                {
                    _currentScene = currentScene;
                    return;
                }

                if (currentScene.SceneHash != _currentScene.SceneHash)
                    _previousScene = _currentScene;

                _currentScene = currentScene;
 
            }
示例#14
0
 internal bool IsConnectedTo(CachedScene scene)
 {
     return(GetSceneConnectionPoint(this, scene) != Vector3.Zero);
 }
示例#15
0
        public static void Update()
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var oldNodes = _nodes;

            var newScenes = ZetaDia.Scenes.Where(s => s.Mesh.Zone != null).ToList();

            int minEdgeLength  = (int)Math.Ceiling(newScenes.Min(s => Math.Min(s.Mesh.Zone.ZoneMax.X - s.Mesh.Zone.ZoneMin.X, s.Mesh.Zone.ZoneMax.Y - s.Mesh.Zone.ZoneMin.Y)));
            int halfEdgeLength = minEdgeLength / 2;

            var nodes        = new List <DungeonNode>();
            var cachedScenes = new List <CachedScene>();

            var completeScenes = new HashSet <int>(_scenes.Where(pair => pair.Value.IsExplored).Select(pair => pair.Key));

            // Iterate through scenes, find connecting scene names and create a dungeon node to navigate to the scene center
            newScenes.AsParallel().ForEach(scene =>
            {
                if (scene.Name.EndsWith("_Filler") || !scene.IsValid)
                {
                    return;
                }

                var zone      = scene.Mesh.Zone;
                var zoneMin   = zone.ZoneMin;
                var zoneMax   = zone.ZoneMax;
                var sceneHash = GetSceneHash(zone);

                if (completeScenes.Contains(sceneHash))
                {
                    return;
                }

                var cachedScene = new CachedScene
                {
                    Scene          = scene,
                    SceneHash      = sceneHash,
                    Name           = scene.Name,
                    Zone           = zone,
                    ZoneMax        = zoneMax,
                    ZoneMin        = zoneMin,
                    MinEdgeLength  = minEdgeLength,
                    HalfEdgeLength = halfEdgeLength
                };

                PopulateExitCodes(cachedScene);

                var baseNode         = new DungeonNode(zoneMin, zoneMax);
                cachedScene.BaseNode = baseNode;
                cachedScene.Nodes.Add(baseNode);
                if (nodes.All(node => node.WorldTopLeft != baseNode.WorldTopLeft))
                {
                    nodes.Add(baseNode);
                }

                cachedScene.Center          = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.NorthEdgeCenter = new Vector3(zoneMin.X, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.SouthEdgeCenter = new Vector3(zoneMax.X, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.EastEdgeCenter  = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMax.Y, 0);
                cachedScene.WestEdgeCenter  = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMin.Y, 0);

                // North
                var northNode         = (new DungeonNode(new Vector2(zoneMin.X - halfEdgeLength, zoneMin.Y), new Vector2(zoneMax.X - halfEdgeLength, zoneMin.Y)));
                cachedScene.NorthNode = northNode;
                cachedScene.Nodes.Add(northNode);
                if (nodes.All(node => node.WorldTopLeft != northNode.WorldTopLeft))
                {
                    nodes.Add(northNode);
                }

                // South
                var southNode         = (new DungeonNode(new Vector2(zoneMin.X + halfEdgeLength, zoneMin.Y), new Vector2(zoneMax.X + halfEdgeLength, zoneMin.Y)));
                cachedScene.SouthNode = southNode;
                cachedScene.Nodes.Add(southNode);
                if (nodes.All(node => node.WorldTopLeft != southNode.WorldTopLeft))
                {
                    nodes.Add(southNode);
                }

                // East
                var eastNode         = (new DungeonNode(new Vector2(zoneMin.X, zoneMin.Y - halfEdgeLength), new Vector2(zoneMax.X, zoneMin.Y - halfEdgeLength)));
                cachedScene.EastNode = eastNode;
                cachedScene.Nodes.Add(eastNode);
                if (nodes.All(node => node.WorldTopLeft != eastNode.WorldTopLeft))
                {
                    nodes.Add(eastNode);
                }

                // West
                var westNode         = (new DungeonNode(new Vector2(zoneMin.X, zoneMin.Y + halfEdgeLength), new Vector2(zoneMax.X, zoneMin.Y + halfEdgeLength)));
                cachedScene.WestNode = westNode;
                cachedScene.Nodes.Add(westNode);
                if (nodes.All(node => node.WorldTopLeft != westNode.WorldTopLeft))
                {
                    nodes.Add(westNode);
                }


                if (!_scenes.ContainsKey(cachedScene.SceneHash))
                {
                    _scenes.Add(cachedScene.SceneHash, cachedScene);
                }
                else
                {
                    _scenes[cachedScene.SceneHash] = cachedScene;
                }
            });

            _scenes.Values.ForEach(PopulateSceneConnections);

            if (oldNodes != null && oldNodes.Any())
            {
                nodes.AsParallel().ForEach(node =>
                {
                    var oldNode = oldNodes.FirstOrDefault(n => node.WorldTopLeft == n.WorldTopLeft);
                    if (oldNode != null && oldNode.Visited)
                    {
                        node.Visited = true;
                    }
                });

                oldNodes.AsParallel().ForEach(oldNode =>
                {
                    if (nodes.All(newNode => newNode.Center != oldNode.WorldTopLeft))
                    {
                        nodes.Add(oldNode);
                    }
                });
            }

            SceneHistory.UpdateSceneHistory();

            _nodes = new ConcurrentBag <DungeonNode>(nodes.Distinct());
            Logger.Debug("Updated SceneSegmentation {0} Scenes {1} nodes in {2:0}ms", _scenes.Count, _nodes.Count, stopwatch.ElapsedMilliseconds);
        }
示例#16
0
        /// <summary>
        /// The closest scene that has its one or more of its connected scenes undiscovered.
        /// </summary>
        internal static CachedScene GetNearestUnexploredScene(CachedScene thisScene = null)
        {
            var scene = thisScene ?? CurrentScene;

            return(Scenes.Where(s => !s.IsExplored).OrderBy(s => scene.Center.Distance2D(s.Center)).FirstOrDefault());
        }
示例#17
0
        public static void Update()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var oldNodes = _nodes;

            var newScenes = ZetaDia.Scenes.Where(s => s.Mesh.Zone != null).ToList();

            int minEdgeLength = (int)Math.Ceiling(newScenes.Min(s => Math.Min(s.Mesh.Zone.ZoneMax.X - s.Mesh.Zone.ZoneMin.X, s.Mesh.Zone.ZoneMax.Y - s.Mesh.Zone.ZoneMin.Y)));
            int halfEdgeLength = minEdgeLength / 2;

            var nodes = new List<DungeonNode>();
            var cachedScenes = new List<CachedScene>();

            var completeScenes = new HashSet<int>(_scenes.Where(pair => pair.Value.IsExplored).Select(pair => pair.Key));

            // Iterate through scenes, find connecting scene names and create a dungeon node to navigate to the scene center
            newScenes.AsParallel().ForEach(scene =>
            {
                if (scene.Name.EndsWith("_Filler") || !scene.IsValid)
                    return;

                var zone = scene.Mesh.Zone;
                var zoneMin = zone.ZoneMin;
                var zoneMax = zone.ZoneMax;
                var sceneHash = GetSceneHash(zone);

                if (completeScenes.Contains(sceneHash))
                    return;

                var cachedScene = new CachedScene
                {
                    Scene = scene,
                    SceneHash = sceneHash,
                    Name = scene.Name,
                    Zone = zone,
                    ZoneMax = zoneMax,
                    ZoneMin = zoneMin,
                    MinEdgeLength = minEdgeLength,
                    HalfEdgeLength = halfEdgeLength
                };
                
                PopulateExitCodes(cachedScene);

                var baseNode = new DungeonNode(zoneMin, zoneMax);
                cachedScene.BaseNode = baseNode;
                cachedScene.Nodes.Add(baseNode);
                if (nodes.All(node => node.WorldTopLeft != baseNode.WorldTopLeft))
                    nodes.Add(baseNode);

                cachedScene.Center = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.NorthEdgeCenter = new Vector3(zoneMin.X, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.SouthEdgeCenter = new Vector3(zoneMax.X, zoneMax.Y - (zoneMax.Y - zoneMin.Y) / 2, 0);
                cachedScene.EastEdgeCenter = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMax.Y, 0);
                cachedScene.WestEdgeCenter = new Vector3(zoneMax.X - (zoneMax.X - zoneMin.X) / 2, zoneMin.Y, 0);

                // North
                var northNode = (new DungeonNode(new Vector2(zoneMin.X - halfEdgeLength, zoneMin.Y), new Vector2(zoneMax.X - halfEdgeLength, zoneMin.Y)));
                cachedScene.NorthNode = northNode;
                cachedScene.Nodes.Add(northNode);
                if (nodes.All(node => node.WorldTopLeft != northNode.WorldTopLeft))
                    nodes.Add(northNode);

                // South
                var southNode = (new DungeonNode(new Vector2(zoneMin.X + halfEdgeLength, zoneMin.Y), new Vector2(zoneMax.X + halfEdgeLength, zoneMin.Y)));
                cachedScene.SouthNode = southNode;
                cachedScene.Nodes.Add(southNode);
                if (nodes.All(node => node.WorldTopLeft != southNode.WorldTopLeft))
                    nodes.Add(southNode);

                // East
                var eastNode = (new DungeonNode(new Vector2(zoneMin.X, zoneMin.Y - halfEdgeLength), new Vector2(zoneMax.X, zoneMin.Y - halfEdgeLength)));
                cachedScene.EastNode = eastNode;
                cachedScene.Nodes.Add(eastNode);
                if (nodes.All(node => node.WorldTopLeft != eastNode.WorldTopLeft))
                    nodes.Add(eastNode);
  
                // West
                var westNode = (new DungeonNode(new Vector2(zoneMin.X, zoneMin.Y + halfEdgeLength), new Vector2(zoneMax.X, zoneMin.Y + halfEdgeLength)));
                cachedScene.WestNode = westNode;
                cachedScene.Nodes.Add(westNode);
                if (nodes.All(node => node.WorldTopLeft != westNode.WorldTopLeft))
                    nodes.Add(westNode);


                if (!_scenes.ContainsKey(cachedScene.SceneHash))
                    _scenes.Add(cachedScene.SceneHash, cachedScene);
                else
                    _scenes[cachedScene.SceneHash] = cachedScene;
            });

            _scenes.Values.ForEach(PopulateSceneConnections);

            if (oldNodes != null && oldNodes.Any())
            {
                nodes.AsParallel().ForEach(node =>
                {
                    var oldNode = oldNodes.FirstOrDefault(n => node.WorldTopLeft == n.WorldTopLeft);
                    if (oldNode != null && oldNode.Visited)
                        node.Visited = true;
                });

                oldNodes.AsParallel().ForEach(oldNode =>
                {
                    if (nodes.All(newNode => newNode.Center != oldNode.WorldTopLeft))
                    {
                        nodes.Add(oldNode);
                    }
                });
            }

            SceneHistory.UpdateSceneHistory();

            _nodes = new ConcurrentBag<DungeonNode>(nodes.Distinct());
            Logger.Debug("Updated SceneSegmentation {0} Scenes {1} nodes in {2:0}ms", _scenes.Count, _nodes.Count, stopwatch.ElapsedMilliseconds);
        }
示例#18
0
        /// <summary>
        /// Returns a scene that is directly connected to the specified scene; avoids DeadEnds and leans towards the specified direction.
        /// </summary>
        /// <param name="direction">the long range direction you want to go</param>
        /// <param name="thisScene">source scene</param>
        /// <param name="avoidPreviousScenes">whether to avoid scenes you've been in recently</param>
        /// <returns></returns>
        internal static CachedScene GetConnectedScene(Direction direction = Direction.Any, CachedScene thisScene = null, bool avoidPreviousScenes = true)
        {
            var scene = thisScene ?? CurrentScene;
            var previousScene = SceneHistory.PreviousScene;

            CachedScene result = null;

            switch (direction)
            {
                case Direction.North:
                    if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                        result = scene.NorthConnection;
                    else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.EastConnection.SceneHash))
                        result = scene.EastConnection;
                    else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                        result = scene.WestConnection;
                    break;

                case Direction.South:
                    if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                        result = scene.SouthConnection;
                    else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.EastConnection.SceneHash))
                        result = scene.EastConnection;
                    else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                        result = scene.WestConnection;
                    break;

                case Direction.East:
                    if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                        result = scene.EastConnection;
                    else if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.SouthConnection.SceneHash))
                        result = scene.SouthConnection;
                    else if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                        result = scene.NorthConnection;
                    break;

                case Direction.West:
                    if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                        result = scene.WestConnection;
                    else if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.SouthConnection.SceneHash))
                        result = scene.SouthConnection;
                    else if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                        result = scene.NorthConnection;
                    break;

                case Direction.SouthEast:
                    if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                        result = scene.SouthConnection;
                    else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                        result = scene.EastConnection;
                    break;

                case Direction.NorthEast:
                    if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                        result = scene.NorthConnection;
                    else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                        result = scene.EastConnection;
                    break;

                case Direction.SouthWest:
                    if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                        result = scene.SouthConnection;
                    else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                        result = scene.WestConnection;
                    break;

                case Direction.NorthWest:
                    if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                        result = scene.NorthConnection;
                    else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                        result = scene.WestConnection;
                    break;
            }

            return result ?? scene.ConnectedScenes.FirstOrDefault();
        }
示例#19
0
 /// <summary>
 /// The closest scene that has its one or more of its connected scenes undiscovered.
 /// </summary>
 internal static CachedScene GetNearestUnexploredScene(CachedScene thisScene = null)
 {
     var scene = thisScene ?? CurrentScene;
     return Scenes.Where(s => !s.IsExplored).OrderBy(s => scene.Center.Distance2D(s.Center)).FirstOrDefault();
 }
示例#20
0
        /// <summary>
        /// Returns a list of scenes between the source scene and the target scene.
        /// </summary>
        internal static List<CachedScene> GetPathToScene(CachedScene targetScene, CachedScene fromScene = null)
        {
            fromScene = fromScene ?? CurrentScene;
            var direction = MathUtil.GetDirectionToPoint(targetScene.Center, fromScene.Center);
            var checkedSceneHashes = new List<int>();
            var path = new List<CachedScene>();
            var found = false;
            var done = false;
            var currentScene = fromScene;
            const int depthStop = 20;
            var depth = 0;

            while (!found || depth > depthStop || done)
            {
                if (currentScene.IsConnectedTo(targetScene))
                {
                    path.Add(targetScene); 
                    found = true;
                }
                else
                {
                    checkedSceneHashes.Add(currentScene.SceneHash);
                    
                    // Attempt to get new scene by direction
                    var newScene = GetConnectedScene(direction, currentScene);

                    // Failing that, just grab any connected scene
                    if (checkedSceneHashes.Contains(newScene.SceneHash))
                        newScene = currentScene.ConnectedScenes.FirstOrDefault(s => !checkedSceneHashes.Contains(s.SceneHash));

                    if (newScene == null)
                    {
                        done = true;
                        continue;
                    }

                    currentScene = newScene;
                    path.Add(newScene);                        
                }
                depth++;
            }
            return path;
        }
示例#21
0
        /// <summary>
        /// Returns a list of points between the source scene and the target scene.
        /// </summary>
        /// <param name="targetScene"></param>
        /// <param name="fromScene"></param>
        /// <returns></returns>
        internal static List<Vector3> GetVectorPathToScene(CachedScene targetScene, CachedScene fromScene = null)
        {
            fromScene = fromScene ?? CurrentScene;
            var scenePath = GetPathToScene(targetScene, fromScene);
            var vectorPath = new List<Vector3>();
            var previousScene = fromScene;

            scenePath.ForEach(scene =>
            {
                vectorPath.Add(GetSceneConnectionPoint(previousScene, scene));
                vectorPath.Add(scene.Center);
                previousScene = scene;
            });

            if (QuestToolsSettings.Instance.DebugEnabled)
            {
                Logger.Debug("Scene Route generated from {0} ({1}) to {2} ({3}) with {4} points", fromScene.Name, fromScene.SceneHash, targetScene.Name, targetScene.SceneHash, vectorPath.Count);
                vectorPath.ForEach(n => Logger.Log("Route Point: {0} Distance={1} Direction={2}", n, n.Distance(ZetaDia.Me.Position), MathUtil.GetDirectionToPoint(n)));
            }    

            return vectorPath;
        }
示例#22
0
        /// <summary>
        /// Returns a list of points that cover the closest walkable points to the four edges and center of the specified scene.
        /// </summary>
        internal static List<Vector3> GetSceneExploreRoute(CachedScene targetScene = null)
        {
            targetScene = targetScene ?? CurrentScene;
            var zone = targetScene.Scene.Mesh.Zone;
            var points = zone.NavZoneDef.NavCells.Where(n => n.IsValid && n.Flags.HasFlag(NavCellFlags.AllowWalk)).Select(n => GetNavCellCenter(n, zone)).ToList();

            var route = new List<Vector3>
            {
                points.OrderBy(point => point.Distance2D(targetScene.Center)).FirstOrDefault(), 
                points.OrderBy(point => point.Distance2D(targetScene.EastEdgeCenter)).FirstOrDefault(), 
                points.OrderBy(point => point.Distance2D(targetScene.NorthEdgeCenter)).FirstOrDefault(), 
                points.OrderBy(point => point.Distance2D(targetScene.SouthEdgeCenter)).FirstOrDefault(), 
                points.OrderBy(point => point.Distance2D(targetScene.WestEdgeCenter)).FirstOrDefault()
            };

            if (QuestToolsSettings.Instance.DebugEnabled)
            {
                Logger.Debug("Scene Explore Route generated for {0} ({1}) with {2} points", targetScene.Name, targetScene.SceneHash, route.Count);
                route.ForEach(n => Logger.Log("Route Point: {0} Distance={1} Direction={2}", n, n.Distance(ZetaDia.Me.Position), MathUtil.GetDirectionToPoint(n)));
            }                

            return route;
        }
示例#23
0
        /// <summary>
        /// Returns a scene that is directly connected to the specified scene; avoids DeadEnds and leans towards the specified direction.
        /// </summary>
        /// <param name="direction">the long range direction you want to go</param>
        /// <param name="thisScene">source scene</param>
        /// <param name="avoidPreviousScenes">whether to avoid scenes you've been in recently</param>
        /// <returns></returns>
        internal static CachedScene GetConnectedScene(Direction direction = Direction.Any, CachedScene thisScene = null, bool avoidPreviousScenes = true)
        {
            var scene         = thisScene ?? CurrentScene;
            var previousScene = SceneHistory.PreviousScene;

            CachedScene result = null;

            switch (direction)
            {
            case Direction.North:
                if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                {
                    result = scene.NorthConnection;
                }
                else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.EastConnection.SceneHash))
                {
                    result = scene.EastConnection;
                }
                else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                {
                    result = scene.WestConnection;
                }
                break;

            case Direction.South:
                if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                {
                    result = scene.SouthConnection;
                }
                else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.EastConnection.SceneHash))
                {
                    result = scene.EastConnection;
                }
                else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                {
                    result = scene.WestConnection;
                }
                break;

            case Direction.East:
                if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                {
                    result = scene.EastConnection;
                }
                else if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.SouthConnection.SceneHash))
                {
                    result = scene.SouthConnection;
                }
                else if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                {
                    result = scene.NorthConnection;
                }
                break;

            case Direction.West:
                if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                {
                    result = scene.WestConnection;
                }
                else if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd && (!avoidPreviousScenes || previousScene.SceneHash != scene.SouthConnection.SceneHash))
                {
                    result = scene.SouthConnection;
                }
                else if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                {
                    result = scene.NorthConnection;
                }
                break;

            case Direction.SouthEast:
                if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                {
                    result = scene.SouthConnection;
                }
                else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                {
                    result = scene.EastConnection;
                }
                break;

            case Direction.NorthEast:
                if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                {
                    result = scene.NorthConnection;
                }
                else if (scene.IsConnectedEast && !scene.EastConnection.IsDeadEnd)
                {
                    result = scene.EastConnection;
                }
                break;

            case Direction.SouthWest:
                if (scene.IsConnectedSouth && !scene.SouthConnection.IsDeadEnd)
                {
                    result = scene.SouthConnection;
                }
                else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                {
                    result = scene.WestConnection;
                }
                break;

            case Direction.NorthWest:
                if (scene.IsConnectedNorth && !scene.NorthConnection.IsDeadEnd)
                {
                    result = scene.NorthConnection;
                }
                else if (scene.IsConnectedWest && !scene.WestConnection.IsDeadEnd)
                {
                    result = scene.WestConnection;
                }
                break;
            }

            return(result ?? scene.ConnectedScenes.FirstOrDefault());
        }
示例#24
0
 internal bool IsConnectedTo(CachedScene scene)
 {
     return GetSceneConnectionPoint(this, scene) != Vector3.Zero;
 }