public List<Vector3> FindPath(GridmapCell start, GridmapCell end, bool checkValidity)
        {
            if (start == null || end == null) return new List<Vector3>();
            if ((start.treeID != end.treeID) && checkValidity) return new List<Vector3>();

            return PathingHelper.FindPath(start, end, this, checkValidity);
        }
 private void SetSelected(Gridmap map)
 {
     RaycastHit hitinfo;
     if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hitinfo))
     {
         selected = map.GetCellFromPoint(hitinfo.point);
         if (selected.state != GridmapCell.CellState.Buildable) selected = null;
     }
 }
        /// <summary>
        /// Instantiate a structure from the array of buildable ones at a given location for the player.
        /// </summary>
        /// <param name="sIndex">the index into this builder's array of buildable structures to specify which structure.</param>
        /// <param name="cell">which cell on the map the structure will be built on</param>
        /// TODO: IMPLEMENT MULTI-CELL FOOTPRINTS FOR STRUCTURES
        /// <returns>true if the structure was built succesfully, otherwise false.</returns>
        public bool BuildStructure(int sIndex, GridmapCell cell)
        {
            if (cell.state != GridmapCell.CellState.Buildable) return false;

            try
            {
                GameStructure structure = Instantiate(StructuresBuilt[sIndex], cell.center, Quaternion.identity) as GameStructure;
                structure.owner = gameObject.GetComponent<GameEntity>().owner;
                cell.state = GridmapCell.CellState.Occupied;

                return true;
            }
            catch (System.Exception) { return false; }
        }
        /// <summary>
        /// Sets the position of the TileBound object.
        /// </summary>
        /// <param name="position">The position of the tile which the object will be centered around</param>
        /// <returns>True if the position was valid or false if it was not.</returns>
        public bool SetPosition(Vector3 position)
        {
            GridmapCell center = map.GetCellFromPoint(position);
            GridmapCell[] cells = new GridmapCell[footprintX * footprintZ];

            for (int x = 0; x < footprintX; x++)
            {
                for (int z = 0; z < footprintZ; z++)
                {
                    GridmapCell n = map[x + center.x, z + center.z];
                    if (n == null || n.state != GridmapCell.CellState.Buildable) return false;

                    cells[(x * footprintZ) + z] = n;
                }
            }

            //TODO: Fix for 1-sized footprints
            //for (int x = -(footprintX / 2) + 1 - (footprintX % 2); x < footprintX / 2; x++)
            //{
            //    for (int z = -(footprintZ / 2) + 1 - (footprintZ % 2); z < footprintZ / 2; z++)
            //    {
            //        Debug.Log("x:" + x + "\tz:" + z);

            //        // TODO: cache map[x,z] maybe
            //        if (map[x, z] == null || map[x, z].state == GridmapCell.CellState.Occupied)
            //            return false;
            //        else
            //        {
            //            cells[(x * footprintZ) + z] = map[x, z];
            //        }
            //    }
            //}

            occupiedTiles = new GridmapCell[footprintX * footprintZ];
            cells.CopyTo(occupiedTiles, 0);

            for (int i = 0; i < footprintX * footprintZ; i++)
                occupiedTiles[i].state = GridmapCell.CellState.Occupied;

            return true;
        }
        private bool CellIsSmooth(GridmapCell c, Terrain t)
        {
            // grab 4-corners + center heights
            float ch = t.SampleHeight(c.center);
            float tl = t.SampleHeight(c.center + new Vector3(-cellWidth / 2.0f, 0, cellDepth / 2.0f));
            float tr = t.SampleHeight(c.center + new Vector3(cellWidth / 2.0f, 0, cellDepth / 2.0f));
            float bl = t.SampleHeight(c.center + new Vector3(-cellWidth / 2.0f, 0, -cellDepth / 2.0f));
            float br = t.SampleHeight(c.center + new Vector3(cellWidth / 2.0f, 0, -cellDepth / 2.0f));

            // check if center diff is too big:
            if (Mathf.Abs(ch - tl) > cliffHeight ||
                Mathf.Abs(ch - tr) > cliffHeight ||
                Mathf.Abs(ch - bl) > cliffHeight ||
                Mathf.Abs(ch - br) > cliffHeight)
                return false;

            // check if top-left diff is too big:
            if (Mathf.Abs(tl - tr) > cliffHeight ||
                Mathf.Abs(tl - bl) > cliffHeight)
                return false;

            // check if bot-right diff is too big:
            if (Mathf.Abs(br - tr) > cliffHeight ||
                Mathf.Abs(br - bl) > cliffHeight)
                return false;

            return true;
        }
                public AStarRecord(GridmapCell c, AStarRecord p, float cost)
                {
                    if (c == null) throw new UnityException("Cannot create an AStarRecord with a null node.");

                    cell = c;
                    parent = p;
                    linkCost = cost;

                    totalCost = (parent != null) ? parent.totalCost + linkCost : linkCost;
                    estimatedFinalCost = totalCost + (finalTarget - cell.center).magnitude;
                }
            private static bool PlaceInCorrectList(GridmapCell cell, AStarRecord parent, float cost)
            {
                if (cell == null) return false;
                if (!cell.Valid && checkValiditiy) return false;

                AStarRecord olinstance = openList.FirstOrDefault(r => r.cell.Equals(cell));
                if (olinstance != null)  // it's on the open list.
                {
                    if (olinstance.totalCost > parent.totalCost + cost)  // this new path is shorter
                        olinstance.Reparent(parent, cost);
                    return true;
                }

                AStarRecord clinstance = closedList.FirstOrDefault(r => r.cell.Equals(cell));
                if (clinstance != null) // it's in the closed list
                {
                    return true;
                }

                // add it to the open list
                openList.Add(new AStarRecord(cell, parent, cost));
                return true;
            }
            public static List<Vector3> FindPath(GridmapCell start, GridmapCell end, Gridmap map, bool check)
            {
                List<Vector3> path = new List<Vector3>();
                if (start == null || end == null) return path;

                openList.Clear();
                closedList.Clear();
                checkValiditiy = check;
                AStarRecord.finalTarget = end.center;

                openList.Add(new AStarRecord(start, null, 0));

                while (openList.Count > 0)
                {
                    AStarRecord current = openList[0];
                    if (current.cell.Equals(end)) break;

                    bool up_ok =    PlaceInCorrectList(map[current.cell.x, current.cell.z + 1], current, 1.0f);
                    bool left_ok =  PlaceInCorrectList(map[current.cell.x - 1, current.cell.z], current, 1.0f);
                    bool right_ok = PlaceInCorrectList(map[current.cell.x + 1, current.cell.z], current, 1.0f);
                    bool down_ok =  PlaceInCorrectList(map[current.cell.x, current.cell.z - 1], current, 1.0f);

                    if (up_ok && left_ok) PlaceInCorrectList(map[current.cell.x - 1, current.cell.z + 1], current, 1.4f);
                    if (up_ok && right_ok) PlaceInCorrectList(map[current.cell.x + 1, current.cell.z + 1], current, 1.4f);
                    if (down_ok && left_ok) PlaceInCorrectList(map[current.cell.x - 1, current.cell.z - 1], current, 1.4f);
                    if (down_ok && right_ok) PlaceInCorrectList(map[current.cell.x + 1, current.cell.z - 1], current, 1.4f);

                    closedList.Add(current);
                    openList.RemoveAt(0);

                    // TODO: Don't sort, just cache the index of the lowest cost (n instead of nlogn)
                    openList.Sort((l1, l2) => l1.estimatedFinalCost.CompareTo(l2.estimatedFinalCost));
                }

                if (openList.Count == 0) return path;   // no path found.

                AStarRecord r = openList[0];
                do
                {
                    path.Add(r.cell.center);
                    r = r.parent;
                } while (r != null && !r.cell.Equals(start));
                path.Reverse();
                return path;
            }
        private void GenerateGrid_Terrain()
        {
            countx = (int)(gameObject.collider.bounds.size.x / cellWidth);
            countz = (int)(gameObject.collider.bounds.size.z / cellDepth);

            Terrain terrain = gameObject.GetComponent<Terrain>() as Terrain;

            cells = new GridmapCell[countx * countz];

            for (int x = 0; x < countx; x++)
            {
                for (int z = 0; z < countz; z++)
                {
                    cells[(x * countz) + z] = new GridmapCell();
                    cells[(x * countz) + z].Initialize(new Vector3(x * cellWidth, 0, z * cellDepth) + halfCellSize + gameObject.transform.position, cellWidth, cellDepth);
                    cells[(x * countz) + z].center.y = terrain.SampleHeight(cells[(x * countz) + z].center);
                    cells[(x * countz) + z].SetSceneVerts(terrain);
                    cells[(x * countz) + z].Valid = CellIsSmooth(cells[(x * countz) + z], terrain);
                    cells[(x * countz) + z].state = cells[(x * countz) + z].Valid ? GridmapCell.CellState.Buildable : GridmapCell.CellState.Unbuildable;
                    cells[(x * countz) + z].x = x;
                    cells[(x * countz) + z].z = z;
                }
            }
        }
 // Use this for initialization
 void Start()
 {
     Messenger<GameEntity>.RegisterListener("GameEntityPressed", x => { selected = null; });
     Messenger<Gridmap>.RegisterListener("MapPressed", SetSelected);
 }