// Pathfinding from one character to other
    // Returns cells of the path (in order)
    public List <Cell> GetPathFromCharToChar(CharacterScript character, CharacterScript target)
    {
        Entity entity = character.transform.GetComponent(typeof(Entity)) as Entity;

        IsoUnity.Cell           currentCell = character.transform.parent.transform.GetComponent(typeof(IsoUnity.Cell)) as IsoUnity.Cell;
        IsoUnity.Cell           targetCell  = target.transform.parent.transform.GetComponent(typeof(IsoUnity.Cell)) as IsoUnity.Cell;
        List <CellWithDistance> openList    = new List <CellWithDistance>();
        List <CellWithDistance> closeList   = new List <CellWithDistance>();
        float attackRan = character.character.attributesWithFormulas.Find(x => x.attribute.id == moveRange.id).value;
        float heighMax  = character.character.attributesWithFormulas.Find(x => x.attribute.id == moveHeight.id).value;

        openList.Add(new CellWithDistance(currentCell, 0, null));
        while (openList.Count > 0)
        {
            CellWithDistance current = openList[0];
            openList.Remove(current);
            closeList.Add(current);
            if (current.cell == targetCell)
            {
                List <Cell> path = new List <Cell>();
                while (current.previousCell != null)
                {
                    path.Add(new Cell(current.cell.Map.getCoords(current.cell.gameObject).x, current.cell.Map.getCoords(current.cell.gameObject).y));
                    current = current.previousCell;
                }
                path.Reverse();
                return(path);
            }

            float distanceManhattan = Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).x - targetCell.Map.getCoords(targetCell.gameObject).x) + Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).y - targetCell.Map.getCoords(targetCell.gameObject).y);
            foreach (IsoUnity.Cell neighbour in current.cell.Map.getNeightbours(current.cell))
            {
                if (neighbour != null && !closeList.Any(x => x.cell == neighbour) && neighbour.Walkable &&
                    ((neighbour != currentCell && neighbour != targetCell && neighbour.transform.GetComponentInChildren <CharacterScript>() == null) || (neighbour == currentCell || neighbour == targetCell)))
                {
                    float distanceManhattanFromCurrentToNeigh = Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).x - neighbour.Map.getCoords(neighbour.gameObject).x) + Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).y - neighbour.Map.getCoords(neighbour.gameObject).y);
                    if (distanceManhattanFromCurrentToNeigh <= 1 && Mathf.Abs(neighbour.Height - current.cell.Height) <= heighMax)
                    {
                        if (!openList.Any(x => x.cell == neighbour))
                        {
                            CellWithDistance neigh = new CellWithDistance(neighbour, current.distanceFromCharacter + distanceManhattanFromCurrentToNeigh, current);
                            openList.Add(neigh);
                        }
                        else
                        {
                            CellWithDistance neigh = openList.Find(x => x.cell == neighbour);
                            if (current.distanceFromCharacter + distanceManhattanFromCurrentToNeigh < neigh.distanceFromCharacter)
                            {
                                neigh.distanceFromCharacter = current.distanceFromCharacter + distanceManhattanFromCurrentToNeigh;
                                neigh.previousCell          = current;
                            }
                        }
                    }
                }
            }
        }
        return(null);
    }
    /******************* PRIVATE AUX METHODS *******************/

    // Calculate the area of the event type
    private List <CharacterScript> CalculateDistanceArea(Entity entity, IsoUnity.Cell currentCell, EventTypes eventType, int distanceMax, int heighMax)
    {
        List <CellWithDistance> openList         = new List <CellWithDistance>();
        List <CellWithDistance> closeList        = new List <CellWithDistance>();
        List <CharacterScript>  charactersInArea = new List <CharacterScript>();

        charactersInArea.Add(currentCell.transform.GetComponentInChildren <CharacterScript>());

        openList.Add(new CellWithDistance(currentCell, 0, null));
        while (openList.Count > 0)
        {
            CellWithDistance current = openList[0];
            openList.Remove(current);
            closeList.Add(current);
            foreach (IsoUnity.Cell neighbour in current.cell.Map.getNeightbours(current.cell))
            {
                if (neighbour != null && !closeList.Any(x => x.cell == neighbour) && neighbour.Walkable)
                {
                    float distanceManhattanFromCurrentToNeigh   = Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).x - neighbour.Map.getCoords(neighbour.gameObject).x) + Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).y - neighbour.Map.getCoords(neighbour.gameObject).y);
                    float distanceManhattanFromCharacterToNeigh = current.distanceFromCharacter + distanceManhattanFromCurrentToNeigh;
                    if (distanceManhattanFromCurrentToNeigh <= 1 && distanceManhattanFromCharacterToNeigh <= distanceMax &&
                        Mathf.Abs(neighbour.Height - current.cell.Height) <= heighMax && (((eventType == EventTypes.IA_MOVE || eventType == EventTypes.MOVE) &&
                                                                                           neighbour.transform.GetComponentInChildren <CharacterScript>() == null) || (eventType != EventTypes.MOVE && eventType != EventTypes.IA_MOVE)))
                    {
                        if (!openList.Any(x => x.cell == neighbour))
                        {
                            PaintCell(neighbour, eventType);
                            openList.Add(new CellWithDistance(neighbour, distanceManhattanFromCharacterToNeigh, null));
                            CharacterScript character = neighbour.transform.GetComponentInChildren <CharacterScript>();
                            if (character != null)
                            {
                                charactersInArea.Add(character);
                            }
                        }
                    }
                }
            }
        }

        return(charactersInArea);
    }
    // Get characters in attack range of the character
    // Returns the list of all the characters in the attack range
    public List <CharacterScript> GetAttackRangeTargets(CharacterScript character)
    {
        List <CharacterScript> characters = new List <CharacterScript>();
        Entity entity = character.transform.GetComponent(typeof(Entity)) as Entity;

        IsoUnity.Cell           currentCell = character.transform.parent.transform.GetComponent(typeof(IsoUnity.Cell)) as IsoUnity.Cell;
        List <CellWithDistance> openList    = new List <CellWithDistance>();
        List <CellWithDistance> closeList   = new List <CellWithDistance>();
        float attackRan = character.character.attributesWithFormulas.Find(x => x.attribute.id == attackRange.id).value;
        float heighMax  = character.character.attributesWithFormulas.Find(x => x.attribute.id == attackHeight.id).value;

        openList.Add(new CellWithDistance(currentCell, 0, null));
        while (openList.Count > 0)
        {
            CellWithDistance current = openList[0];
            openList.Remove(current);
            closeList.Add(current);
            foreach (IsoUnity.Cell neighbour in current.cell.Map.getNeightbours(current.cell))
            {
                if (neighbour != null && !closeList.Any(x => x.cell == neighbour) && neighbour.Walkable)
                {
                    float distanceManhattanFromCurrentToNeigh   = Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).x - neighbour.Map.getCoords(neighbour.gameObject).x) + Mathf.Abs(current.cell.Map.getCoords(current.cell.gameObject).y - neighbour.Map.getCoords(neighbour.gameObject).y);
                    float distanceManhattanFromCharacterToNeigh = current.distanceFromCharacter + distanceManhattanFromCurrentToNeigh;
                    if (distanceManhattanFromCurrentToNeigh <= 1 && distanceManhattanFromCharacterToNeigh <= attackRan &&
                        Mathf.Abs(neighbour.Height - current.cell.Height) <= heighMax)
                    {
                        if (!openList.Any(x => x.cell == neighbour))
                        {
                            CharacterScript charAtCell = GetCharacterAtCell(new Cell(neighbour.Map.getCoords(neighbour.gameObject).x, neighbour.Map.getCoords(neighbour.gameObject).y));
                            if (charAtCell != null)
                            {
                                characters.Add(charAtCell);
                            }
                            openList.Add(new CellWithDistance(neighbour, distanceManhattanFromCharacterToNeigh, null));
                        }
                    }
                }
            }
        }
        return(characters);
    }
 public void setPreviousCell(CellWithDistance previous)
 {
     this.previousCell = previous;
 }
 public CellWithDistance(IsoUnity.Cell cell, float distance, CellWithDistance previous)
 {
     this.cell = cell;
     this.distanceFromCharacter = distance;
     this.previousCell          = previous;
 }