public List <Node> FindPath(Node start, Node end)
        {
            PriorityQueue <float, Node> S        = new PriorityQueue <float, Node>();
            Dictionary <Node, Node>     previous = new Dictionary <Node, Node>();
            Dictionary <Node, float>    distance = new Dictionary <Node, float>();

            S.Enqueue(0, start);
            previous.Add(start, null);
            distance.Add(start, 0);
            while (!S.IsEmpty)
            {
                Node n = S.Dequeue();
                if (n == end)
                {
                    List <Node> path = new List <Node>();
                    path.Add(n);
                    while ((n = previous[n]) != null)
                    {
                        path.Add(n);
                    }
                    return(path);
                }
                foreach (Edge e in n.Edges.Values)
                {
                    Node neighbour = e.Left;
                    if (neighbour == n)
                    {
                        neighbour = e.Right;
                    }
                    if (!previous.ContainsKey(neighbour))
                    {
                        float dist     = distance[n] + e.Distance;
                        float distLeft = (neighbour.Center - end.Center).Length();
                        float h        = dist + distLeft;
                        S.Enqueue(h, neighbour);
                        previous.Add(neighbour, n);
                        distance.Add(neighbour, dist);
                    }
                }
            }
            return(null);
        }
        public List <Waypoint> FindPath(Vector3 start, Vector3 end, Node startNode, Node endNode)
        {
            Node s = startNode ?? BoundingRegion.GetNodeAt(start);
            Node e = endNode ?? BoundingRegion.GetNodeAt(end);

            if (s == null || e == null || s == e)
            {
                return(null);
            }
            List <Node> nodePath = FindPath(s, e);

            if (nodePath == null)
            {
                return(null);
            }
            List <Waypoint> allWaypoints = new List <Waypoint>();

            allWaypoints.Add(new Waypoint
            {
                InternalIndex = allWaypoints.Count,
                OptimalPoint  = end,
                Node          = e,
                Edge          = null //nodePath[0].Edges[nodePath[1]]
            });
            for (int i = 0; i < nodePath.Count - 1; i++)
            {
                Edge ed = nodePath[i].Edges[nodePath[i + 1]];
                allWaypoints.Add(new Waypoint
                {
                    InternalIndex = allWaypoints.Count,
                    OptimalPoint  = (ed.PointA + ed.PointB) / 2,
                    Node          = nodePath[i + 1],
                    Edge          = ed
                });
            }
            allWaypoints.Add(new Waypoint
            {
                InternalIndex = allWaypoints.Count,
                OptimalPoint  = start,
                Node          = s,
                Edge          = null //nodePath[nodePath.Count - 2].Edges[nodePath[nodePath.Count - 1]]
            });

            bool[] disabled = new bool[allWaypoints.Count];
            for (int i = 0; i < disabled.Length; i++)
            {
                disabled[i] = false;
            }
            // The first iteration removes unneccessary waypoints
            // Go through, waypoint by waypoint
            for (int left = 0; left < allWaypoints.Count - 2; left++)
            {
                //And see if we can remove any succeding waypoints for this one
                for (int right = left + 2; right < allWaypoints.Count; right++)
                {
                    if (CanMoveStraight(allWaypoints,
                                        left, right,
                                        allWaypoints[left].OptimalPoint,
                                        Vector3.Normalize(allWaypoints[right].OptimalPoint - allWaypoints[left].OptimalPoint)))
                    {
                        disabled[right - 1] = true;
                    }
                    else
                    {
                        left = right - 2;
                        break;
                    }
                }
            }

            List <Waypoint> waypoints = new List <Waypoint>();

            for (int i = 0; i < allWaypoints.Count; i++)
            {
                if (!disabled[i])
                {
                    waypoints.Add(allWaypoints[i]);
                }
            }

            //This tries to move the waypoints along the edge they occupy to optimize the path,
            //basically cutting corners
            //Problem is, it actually looks a bit better if the units walk in the middle of the path
            //instead of taking the absolutely best path, so it's turned off
#if (false)
            for (int i = 1; i < waypoints.Count - 1; i++)
            {
                Edge ed = waypoints[i].Edge;
                //We start by finding the intersection point of the current optimal point
                float currentT = (waypoints[i].OptimalPoint - ed.PointA).Length();
                //And of the best point (a line from the previous waypoint to the next one
                float bestT;
                if (Math.LineLineIntersectionTA(ed.PointA, Vector3.Normalize(ed.PointB - ed.PointA),
                                                waypoints[i - 1].OptimalPoint,
                                                Vector3.Normalize(waypoints[i + 1].OptimalPoint - waypoints[i - 1].OptimalPoint), out bestT))
                {
                    //From that we know which "corner" is the best place for the optimal point
                    Vector3 WP;
                    if (bestT < currentT)
                    {
                        WP = ed.PointA;
                    }
                    else if (bestT > currentT)
                    {
                        WP = ed.PointB;
                    }
                    else
                    {
                        continue;
                    }

                    //Then we just need to check if it's ok to place it there
                    if (CanMoveStraight(allWaypoints,
                                        waypoints[i - 1].InternalIndex, waypoints[i].InternalIndex,
                                        waypoints[i - 1].OptimalPoint,
                                        Vector3.Normalize(WP - waypoints[i - 1].OptimalPoint))
                        &&
                        CanMoveStraight(allWaypoints,
                                        waypoints[i].InternalIndex, waypoints[i + 1].InternalIndex,
                                        WP, Vector3.Normalize(waypoints[i + 1].OptimalPoint - WP)))
                    {
                        waypoints[i].OptimalPoint = WP;
                    }
                }
                else
                {
                    /*if (CanMoveStraight(nodePath, waypointNodeIndexes[i - 2], waypointNodeIndexes[i - 1] - 1,
                     *     waypoints[i - 2].OptimalPoint, Vector3.Normalize(waypoints[i - 1].OptimalPoint - waypoints[i - 2].OptimalPoint)))
                     *  waypoints[i].OptimalPoint = waypoints[i - 1].OptimalPoint;*/
                }
            }
#endif
            List <Waypoint> revWP = new List <Waypoint>();
            revWP.Add(waypoints.Last());
            for (int i = waypoints.Count - 2; i >= 0; i--)
            {
                if (waypoints[i] != revWP.Last())
                {
                    revWP.Add(waypoints[i]);
                }
            }
            return(revWP);
        }
        void SpawnOneUnit()
        {
            #if DEBUG
            RedGate.Profiler.UserEvents.ProfilerEvent.SignalEvent("Spawning unit");
            #endif
            Vector3 spawnPos;
            if (region != null)
            {
                if (Distribution == SpawnDistribution.Even)
                {
                    node = region.BoundingRegion.Nodes[nodeI];
                    nodeI++;
                    if (nodeI >= region.BoundingRegion.Nodes.Length) nodeI = 0;
                }

                if (Distribution == SpawnDistribution.GroupRandom || Distribution == SpawnDistribution.Even)
                    spawnPos = region.BoundingRegion.GetRandomPosition(Game.Instance.SpawnRandomizer, node);
                else
                    spawnPos = region.BoundingRegion.GetRandomPosition(Game.Instance.SpawnRandomizer);

                spawnPos += PointOffset;
            }
            else if (point is GameEntity)
            {
                spawnPos = ((GameEntity)point).SpawnAtPoint;
                spawnPos += Vector3.TransformCoordinate(PointOffset, Matrix.RotationZ(((GameEntity)point).Orientation));
            }
            else
            {
                spawnPos = point.Translation + Vector3.UnitZ * 0.1f;
                spawnPos += Vector3.TransformCoordinate(PointOffset, Matrix.RotationQuaternion(point.Rotation));
            }

            spawnPos = Game.Instance.Map.Ground.GetHeight(spawnPos);

            var type = binder.BindToType(typeof(SpawnScript).Assembly.FullName, SpawnType);
            /*var type = typeof(SpawnScript).Assembly.GetType("Client.Game.Map.Units." + SpawnType);
            if(type == null)
                typeof(SpawnScript).Assembly.GetType("Client.Game.Map.Props." + SpawnType);*/
            var unit = (GameEntity)Activator.CreateInstance(type);
            unit.Translation = spawnPos;
            unit.EditorInit();
            unit.GameStart();
            Game.Instance.Scene.Root.AddChild(unit);
            if (DisableUnit)
            {
                ((Unit)unit).CanControlMovementBlockers++;
                ((Unit)unit).CanControlRotationBlockers++;
                ((Unit)unit).CanPerformAbilitiesBlockers++;
            }
            if (unit is NPC && SeekMainCharacter && Game.Instance.Map.MainCharacter.State == UnitState.Alive)
                ((NPC)unit).MotionNPC.Pursue(Game.Instance.Map.MainCharacter.MotionObject, 0);

            if (SpawnEffect != null)
            {
                var e = (Graphics.Entity)Activator.CreateInstance(SpawnEffect);
                e.Translation = spawnPos;
                Game.Instance.Scene.Add(e);
            }

            if (LimitSimultaneouslyAlive > 0 && unit is Destructible)
                spawns.Add((Destructible)unit);
        }
        protected override void PerformingTick()
        {
            base.PerformingTick();

            for (int i = 0; i < frameSpawnN; i++)
                SpawnOneUnit();
            frameSpawnN = 0;

            if (!(SkipFirstTick && isFirstTick))
            {
                if (point == null && region == null)
                {
                    region = Game.Instance.Map.GetRegion(Point);
                    if (region == null)
                        point = Game.Instance.Scene.GetByName(Point);
                }

                if (region != null && Distribution == SpawnDistribution.GroupRandom)
                {
                    if (Distribution == SpawnDistribution.GroupRandom)
                        node = region.BoundingRegion.GetRandomNode(Game.Instance.SpawnRandomizer);
                    else
                        nodeI = 0;
                }

                int n = SpawnMinPerRound + Game.Instance.SpawnRandomizer.Next(SpawnMaxPerRound - SpawnMinPerRound);
                n = Math.Min(n, SpawnCount - spawnedCount);
                if (LimitSimultaneouslyAlive > 0)
                {
                    List<Destructible> alive=  new List<Destructible>();
                    foreach (var v in spawns)
                        if (v.State == UnitState.Alive)
                            alive.Add(v);
                    spawns = alive;
                    n = Common.Math.Clamp(n, 0, Math.Max(0, LimitSimultaneouslyAlive - alive.Count));
                }
                spawnedCount += n;
                frameSpawnN = n;

                if (n == 0 && EndPerformWhenAllUnitsHaveSpawned)
                    TryEndPerform(false);
            }
            isFirstTick = false;
            TickPeriod = MinPeriod + (float)Game.Instance.SpawnRandomizer.NextDouble() * (MaxPeriod - MinPeriod);
        }
        public List<Waypoint> FindPath(Vector3 start, Vector3 end, Node startNode, Node endNode)
        {
            Node s = startNode ?? BoundingRegion.GetNodeAt(start);
            Node e = endNode ?? BoundingRegion.GetNodeAt(end);
            if (s == null || e == null || s == e) return null;
            List<Node> nodePath = FindPath(s, e);
            if (nodePath == null) return null;
            List<Waypoint> allWaypoints = new List<Waypoint>();
            allWaypoints.Add(new Waypoint
            {
                InternalIndex = allWaypoints.Count,
                OptimalPoint = end,
                Node = e,
                Edge = null //nodePath[0].Edges[nodePath[1]]
            });
            for(int i=0; i < nodePath.Count - 1; i++)
            {
                Edge ed = nodePath[i].Edges[nodePath[i + 1]];
                allWaypoints.Add(new Waypoint
                {
                    InternalIndex = allWaypoints.Count,
                    OptimalPoint = (ed.PointA + ed.PointB) / 2,
                    Node = nodePath[i + 1],
                    Edge = ed
                });
            }
            allWaypoints.Add(new Waypoint
            {
                InternalIndex = allWaypoints.Count,
                OptimalPoint = start,
                Node = s,
                Edge = null //nodePath[nodePath.Count - 2].Edges[nodePath[nodePath.Count - 1]]
            });

            bool[] disabled = new bool[allWaypoints.Count];
            for (int i = 0; i < disabled.Length; i++) disabled[i] = false;
            // The first iteration removes unneccessary waypoints
            // Go through, waypoint by waypoint
            for (int left = 0; left < allWaypoints.Count - 2; left++)
            {
                //And see if we can remove any succeding waypoints for this one
                for (int right = left + 2; right < allWaypoints.Count; right++)
                {
                    if (CanMoveStraight(allWaypoints,
                        left, right,
                        allWaypoints[left].OptimalPoint,
                        Vector3.Normalize(allWaypoints[right].OptimalPoint - allWaypoints[left].OptimalPoint)))
                        disabled[right - 1] = true;
                    else
                    {
                        left = right - 2;
                        break;
                    }
                }
            }

            List<Waypoint> waypoints = new List<Waypoint>();
            for(int i=0; i < allWaypoints.Count; i++)
                if (!disabled[i])
                    waypoints.Add(allWaypoints[i]);

            //This tries to move the waypoints along the edge they occupy to optimize the path,
            //basically cutting corners
            //Problem is, it actually looks a bit better if the units walk in the middle of the path
            //instead of taking the absolutely best path, so it's turned off
            #if(false)
            for (int i = 1; i < waypoints.Count - 1; i++)
            {
                Edge ed = waypoints[i].Edge;
                //We start by finding the intersection point of the current optimal point
                float currentT = (waypoints[i].OptimalPoint - ed.PointA).Length();
                //And of the best point (a line from the previous waypoint to the next one
                float bestT;
                if (Math.LineLineIntersectionTA(ed.PointA, Vector3.Normalize(ed.PointB - ed.PointA),
                    waypoints[i - 1].OptimalPoint,
                    Vector3.Normalize(waypoints[i + 1].OptimalPoint - waypoints[i - 1].OptimalPoint), out bestT))
                {
                    //From that we know which "corner" is the best place for the optimal point
                    Vector3 WP;
                    if (bestT < currentT) WP = ed.PointA;
                    else if (bestT > currentT) WP = ed.PointB;
                    else continue;

                    //Then we just need to check if it's ok to place it there
                    if (CanMoveStraight(allWaypoints,
                            waypoints[i - 1].InternalIndex, waypoints[i].InternalIndex,
                            waypoints[i - 1].OptimalPoint,
                            Vector3.Normalize(WP - waypoints[i - 1].OptimalPoint))
                            &&
                        CanMoveStraight(allWaypoints,
                            waypoints[i].InternalIndex, waypoints[i + 1].InternalIndex,
                            WP, Vector3.Normalize(waypoints[i + 1].OptimalPoint - WP)))
                        waypoints[i].OptimalPoint = WP;
                }
                else
                {
                    /*if (CanMoveStraight(nodePath, waypointNodeIndexes[i - 2], waypointNodeIndexes[i - 1] - 1,
                           waypoints[i - 2].OptimalPoint, Vector3.Normalize(waypoints[i - 1].OptimalPoint - waypoints[i - 2].OptimalPoint)))
                        waypoints[i].OptimalPoint = waypoints[i - 1].OptimalPoint;*/
                }
            }
            #endif
            List<Waypoint> revWP = new List<Waypoint>();
            revWP.Add(waypoints.Last());
            for (int i = waypoints.Count - 2; i >= 0; i--)
                if (waypoints[i] != revWP.Last())
                    revWP.Add(waypoints[i]);
            return revWP;
        }
 public List<Node> FindPath(Node start, Node end)
 {
     PriorityQueue<float, Node> S = new PriorityQueue<float, Node>();
     Dictionary<Node, Node> previous = new Dictionary<Node, Node>();
     Dictionary<Node, float> distance = new Dictionary<Node, float>();
     S.Enqueue(0, start);
     previous.Add(start, null);
     distance.Add(start, 0);
     while (!S.IsEmpty)
     {
         Node n = S.Dequeue();
         if (n == end)
         {
             List<Node> path = new List<Node>();
             path.Add(n);
             while ((n = previous[n]) != null)
                 path.Add(n);
             return path;
         }
         foreach (Edge e in n.Edges.Values)
         {
             Node neighbour = e.Left;
             if (neighbour == n) neighbour = e.Right;
             if (!previous.ContainsKey(neighbour))
             {
                 float dist = distance[n] + e.Distance;
                 float distLeft = (neighbour.Center - end.Center).Length();
                 float h = dist + distLeft;
                 S.Enqueue(h, neighbour);
                 previous.Add(neighbour, n);
                 distance.Add(neighbour, dist);
             }
         }
     }
     return null;
 }