//same as previous, but take into account movement cost of cells
    public static void FillPlayerBreath(ref BreathArea breath, ref List <ThingController> monstersList, bool cullByTrueDistance = false)
    {
        int   maxDistance = breath.maxDistance;
        int   arraySize   = breath.size;
        Vec2I StartPoint  = breath.position;

        breath.Invalidate();
        monstersList.Clear();

        if (GetHeat(StartPoint).x == -1)
        {
            return;
        }

        //init arrays
        bool[,] closedCheck   = new bool[arraySize, arraySize];
        bool[,] openCheck     = new bool[arraySize, arraySize];
        PathStep[,] openArray = new PathStep[arraySize, arraySize];

        //set start point
        BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize);

        openList.Add(new PathStep(StartPoint, 0));
        openCheck[maxDistance, maxDistance] = true;

        breath.exist[maxDistance, maxDistance]     = true;
        breath.steps[maxDistance, maxDistance]     = 0;
        breath.distance[maxDistance, maxDistance]  = 0;
        breath.direction[maxDistance, maxDistance] = 0;

        List <ThingController> monsters = new List <ThingController>();

        int maxStepDistance = maxDistance * 10;

        while (openList.ItemCount > 0)
        {
            //get top of heap
            PathStep current         = openList.RemoveFirst();
            int      ax              = current.position.x - StartPoint.x + maxDistance;
            int      ay              = current.position.y - StartPoint.y + maxDistance;
            int      currentDistance = breath.distance[ax, ay];
            int      currentSteps    = breath.steps[ax, ay];
            closedCheck[ax, ay] = true;

            TheGrid.GetNearbyMonsters(current.position, 0).Perform((n) => { monsters.Add(n.Data); });

            if (cullByTrueDistance)
            {
                if (currentDistance >= maxStepDistance)
                {
                    continue;
                }
            }

            Vector3 currentHeat = GetHeat(current.position);

            //no propagation through solids
            if (currentHeat.x >= 1f)
            {
                if (current.position != StartPoint)
                {
                    continue;
                }
            }

            for (int i = 1; i < 9; i++)
            {
                Vec2I neighbor = current.position + Vec2I.directions[i];

                //calculate array position
                int arrayX = neighbor.x - StartPoint.x + maxDistance;
                int arrayY = neighbor.y - StartPoint.y + maxDistance;

                //cull disallowed
                if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance)
                {
                    continue;
                }
                if (openCheck[arrayX, arrayY])
                {
                    continue;
                }
                if (closedCheck[arrayX, arrayY])
                {
                    continue;
                }

                if (!CanPath(neighbor))
                {
                    continue;
                }

                if (HasLedge(current.position, neighbor, false))
                {
                    continue;
                }

                //calculate cost
                int travelCost = current.travelCost + GetTravelCost(neighbor);
                int heuristic  = AxMath.WeightedDistance(neighbor, StartPoint);
                int fullCost   = travelCost + heuristic;

                //reverse direction to point towards the source of breath
                int p = i + 4;
                if (p > 8)
                {
                    p -= 8;
                }

                //check if we can update parent to better
                if (openCheck[arrayX, arrayY])
                {
                    if (openArray[arrayX, arrayY].travelCost > travelCost)
                    {
                        openArray[arrayX, arrayY].travelCost = travelCost;
                        openArray[arrayX, arrayY].heuristic  = heuristic;
                        openArray[arrayX, arrayY].fullCost   = fullCost;
                        breath.direction[arrayX, arrayY]     = p;
                        breath.distance[arrayX, arrayY]      = currentDistance + StepDistance(i);
                        breath.steps[arrayX, arrayY]         = currentSteps + 1;
                        openList.UpdateItem(openArray[arrayX, arrayY]);
                        continue;
                    }
                    else
                    {
                        continue;
                    }
                }

                //priority sorted by heap
                PathStep step = new PathStep(neighbor, travelCost, heuristic);
                openList.Add(step);
                openArray[arrayX, arrayY] = step;
                openCheck[arrayX, arrayY] = true;

                breath.exist[arrayX, arrayY]     = true;
                breath.direction[arrayX, arrayY] = p;
                breath.distance[arrayX, arrayY]  = currentDistance + StepDistance(i);
                breath.steps[arrayX, arrayY]     = currentSteps + 1;
            }
        }

        monstersList = monsters;
    }
    //optimized A* pathfinding
    public static bool GetPath(Vec2I StartPoint, Vec2I EndPoint, int maxDistance, out Vec2I[] path)
    {
        if (StartPoint == EndPoint)
        {
            path    = new Vec2I[1];
            path[0] = EndPoint;
            return(true);
        }

        path = null;

        if (AxMath.RogueDistance(StartPoint, EndPoint) > maxDistance)
        {
            return(false);
        }
        if (GetHeat(StartPoint).x == -1)
        {
            return(false);
        }
        if (GetHeat(EndPoint).x == -1)
        {
            return(false);
        }

        //init arrays
        int arraySize = maxDistance * 2 + 1;

        bool[,] closedCheck   = new bool[arraySize, arraySize];
        bool[,] openCheck     = new bool[arraySize, arraySize];
        Vec2I[,] parents      = new Vec2I[arraySize, arraySize];
        PathStep[,] openArray = new PathStep[arraySize, arraySize];

        //set start point
        BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize);

        openList.Add(new PathStep(StartPoint, AxMath.WeightedDistance(StartPoint, EndPoint)));
        openCheck[maxDistance, maxDistance] = true;
        parents[maxDistance, maxDistance]   = StartPoint;

        bool found = false;

        while (openList.ItemCount > 0)
        {
            //get top of heap
            PathStep current = openList.RemoveFirst();
            closedCheck[current.position.x - StartPoint.x + maxDistance, current.position.y - StartPoint.y + maxDistance] = true;

            foreach (Vec2I neighbor in current.position.neighbors)
            {
                //calculate array position
                int arrayX = neighbor.x - StartPoint.x + maxDistance;
                int arrayY = neighbor.y - StartPoint.y + maxDistance;

                //cull disallowed
                if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance)
                {
                    continue;
                }
                if (closedCheck[arrayX, arrayY])
                {
                    continue;
                }

                //found target
                if (neighbor == EndPoint)
                {
                    parents[arrayX, arrayY] = current.position;
                    found = true;
                    goto finalize;
                }

                if (!CanPath(neighbor))
                {
                    continue;
                }

                //calculate cost
                int travelCost = current.travelCost + AxMath.WeightedDistance(current.position, neighbor);
                int heuristic  = AxMath.WeightedDistance(neighbor, EndPoint);
                int fullCost   = travelCost + heuristic;

                //check if we can update parent to better
                if (openCheck[arrayX, arrayY])
                {
                    if (openArray[arrayX, arrayY].travelCost > travelCost)
                    {
                        openArray[arrayX, arrayY].travelCost = travelCost;
                        openArray[arrayX, arrayY].heuristic  = heuristic;
                        openArray[arrayX, arrayY].fullCost   = fullCost;
                        parents[arrayX, arrayY] = current.position;
                        openList.UpdateItem(openArray[arrayX, arrayY]);
                        continue;
                    }
                    else
                    {
                        continue;
                    }
                }

                //priority sorted by heap
                PathStep step = new PathStep(neighbor, travelCost, heuristic);
                openList.Add(step);
                openCheck[arrayX, arrayY] = true;
                openArray[arrayX, arrayY] = step;
                parents[arrayX, arrayY]   = current.position;
            }
        }

finalize:
        if (found)
        {
            SingleLinkedList <Vec2I> list = new SingleLinkedList <Vec2I>();

            Vec2I current = EndPoint;
            while (current != StartPoint)
            {
                list.InsertFront(current);
                current = parents[current.x - StartPoint.x + maxDistance, current.y - StartPoint.y + maxDistance];
            }
            //list.InsertFront(current); //adds the starting point to the path
            path = list.ToArray();
            return(true);
        }

        return(false);
    }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }
            decisionTime = Random.Range(.4f, .6f);

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);
            if (distance > SeeDistance)
            {
                return;
            }

            if (Random.value <= NearSoundChanceSleeping)
            {
                if (mc.NearSounds.Length > 0)
                {
                    if (!mc.audioSource.isPlaying)
                    {
                        mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                        mc.audioSource.Play();
                    }
                }
            }

            if (SeePlayerRay())
            {
                alert        = true;
                decisionTime = 0f;
            }

            if (!alert)
            {
                return;
            }
        }

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            attackTime    = 0f;
            decisionTime  = 0f;
            return;
        }

        if (attackTime > 0f)
        {
            attackTime -= Time.deltaTime;

            Vector3 aimAt = (GameManager.Instance.Player[0].transform.position - mc.transform.position).normalized;
            //mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, new Vector3(aimAt.x, 0, aimAt.z), Time.deltaTime * mc.turnSpeed), Vector3.up);
            //instantenous rotation towards target
            mc.transform.rotation = Quaternion.LookRotation(new Vector3(aimAt.x, 0, aimAt.z), Vector3.up);

            if (attackTime < AttackHappenTime && !attacked)
            {
                attacked = true;

                if (mc.AttackSounds.Length > 0)
                {
                    GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[Random.Range(0, mc.AttackSounds.Length)], 10f);
                }

                PlayerThing player = GameManager.Instance.Player[0];
                if (player != null)
                {
                    //swap layers for a while to avoid hitting self
                    int originalLayer = owner.gameObject.layer;
                    owner.gameObject.layer = 9;

                    for (int i = 0; i < shotCount; i++)
                    {
                        Vector3 eyePos   = owner.transform.position + Vector3.up * EyeHeight;
                        Vector3 toPlayer = ((player.transform.position + Random.onUnitSphere * player.RayCastSphereRadius) - eyePos).normalized;
                        toPlayer += Random.insideUnitSphere * attackSpread;
                        toPlayer.Normalize();
                        Ray ray = new Ray(eyePos, toPlayer);

                        /*GameObject visualLine = new GameObject();
                         * LineRenderer lr = visualLine.AddComponent<LineRenderer>();
                         * lr.positionCount = 2;
                         * lr.SetPosition(0, ray.origin);
                         * lr.SetPosition(1, ray.origin + ray.direction * 200);
                         * lr.widthMultiplier = .02f;
                         * visualLine.AddComponent<DestroyAfterTime>();*/

                        RaycastHit hit;
                        if (Physics.Raycast(ray, out hit, 200, ~((1 << 9) | (1 << 14)), QueryTriggerInteraction.Ignore))
                        {
                            Damageable target = hit.collider.gameObject.GetComponent <Damageable>();
                            if (target != null)
                            {
                                target.Damage(Random.Range(DamageMin, DamageMax + 1), DamageType.Generic, owner.gameObject);

                                if (target.Bleed)
                                {
                                    GameObject blood = GameObject.Instantiate(GameManager.Instance.BloodDrop);
                                    blood.transform.position = hit.point - ray.direction * .2f;
                                }
                                else
                                {
                                    GameObject puff = GameObject.Instantiate(GameManager.Instance.BulletPuff);
                                    puff.transform.position = hit.point - ray.direction * .2f;
                                }
                            }
                            else
                            {
                                GameObject puff = GameObject.Instantiate(GameManager.Instance.BulletPuff);
                                puff.transform.position = hit.point - ray.direction * .2f;
                            }
                        }
                    }

                    owner.gameObject.layer = originalLayer;
                }
            }

            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
        }

        if (decisionTime > 0f)
        {
            decisionTime -= Time.deltaTime;
            return;
        }

        if (Random.value <= PokeChance)
        {
            Ray        ray = new Ray(owner.transform.position + Vector3.up, owner.transform.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 2, ~((1 << 9) | (1 << 11)), QueryTriggerInteraction.Ignore))
            {
                Pokeable lc = hit.collider.gameObject.GetComponent <Pokeable>();
                if (lc != null)
                {
                    if (lc.AllowMonsters())
                    {
                        lc.Poke(owner.gameObject);
                    }
                }
            }
        }

        if (Random.value <= NearSoundChanceAwake)
        {
            if (mc.NearSounds.Length > 0)
            {
                if (!mc.audioSource.isPlaying)
                {
                    mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                    mc.audioSource.Play();
                }
            }
        }

        decisionTime  = Random.Range(.4f, .6f);
        wantDirection = Vector3.zero;

        bool aggro = false;

        if (Random.value < AggroChance)
        {
            Ray toPlayer;
            if (SeePlayerRay(out toPlayer))
            {
                wantDirection = new Vector3(toPlayer.direction.x, 0, toPlayer.direction.z);
                wantMove      = false;
                aggro         = true;
                attacked      = false;
                attackTime    = 1f;
                decisionTime  = 0f;
                mc.InitAttackAnimation();
            }
        }

        if (!aggro)
        {
            float moveRoll = Random.value;
            if (moveRoll < randomMoveChance)
            {
                MoveToRandomNearbyCell();
            }
            else if (moveRoll < closestMoveChance)
            {
                if (!MoveToRandomClosestBreath())
                {
                    MoveToRandomNearbyCell();
                }
            }
            else
            {
                if (!MoveTowardsBreath())
                {
                    if (!MoveToRandomClosestBreath())
                    {
                        MoveToRandomNearbyCell();
                    }
                }
            }
        }

        if (Random.value < IdleChance)
        {
            wantMove = false;
        }

        if (wantMove)
        {
            mc.moveVector.x = 1;
        }
        else
        {
            mc.moveVector.x = 0;
        }
    }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }
            decisionTime = Random.Range(.4f, .6f);

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);
            if (distance > SeeDistance)
            {
                return;
            }

            if (Random.value <= NearSoundChanceSleeping)
            {
                if (mc.NearSounds.Length > 0)
                {
                    if (!mc.audioSource.isPlaying)
                    {
                        mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                        mc.audioSource.Play();
                    }
                }
            }

            if (SeePlayerRay())
            {
                alert        = true;
                decisionTime = 0f;
            }

            if (!alert)
            {
                return;
            }
        }

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            attackTime    = 0f;
            decisionTime  = 0f;
            return;
        }

        if (attackTime > 0f)
        {
            attackTime -= Time.deltaTime;

            Vector3 aimAt = (GameManager.Instance.Player[0].transform.position - mc.transform.position).normalized;
            //mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, new Vector3(aimAt.x, 0, aimAt.z), Time.deltaTime * mc.turnSpeed), Vector3.up);
            //instantenous rotation towards target
            mc.transform.rotation = Quaternion.LookRotation(new Vector3(aimAt.x, 0, aimAt.z), Vector3.up);

            if (attackTime < AttackHappenTime && !attacked)
            {
                attacked = true;

                float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
                if (distance < meleeAttackRange)
                {
                    if (CanMeleeRay(distance))
                    {
                        if (mc.AttackSounds.Length > 0)
                        {
                            GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[1], 5f);
                        }

                        Damageable d = GameManager.Instance.Player[0].GetComponent <Damageable>();
                        if (d != null)
                        {
                            d.Damage(Random.Range(MeleeDamageMin, MeleeDamageMax + 1), DamageType.Generic, owner.gameObject);
                        }
                    }
                }
                else
                {
                    if (mc.AttackSounds.Length > 0)
                    {
                        GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[0], 5f);
                    }

                    if (mc.AttackProjectile != null)
                    {
                        FireballProjectile fireball = GameObject.Instantiate(mc.AttackProjectile).GetComponent <FireballProjectile>();
                        if (fireball != null)
                        {
                            fireball.transform.position = owner.transform.position + Vector3.up * AttackHeight;
                            fireball.owner = owner.gameObject;
                            fireball.transform.LookAt(GameManager.Instance.Player[0].transform.position + Random.insideUnitSphere * AttackSpread + Vector3.up * TargetHeightAimFix);
                            fireball.transform.SetParent(GameManager.Instance.TemporaryObjectsHolder);
                        }
                    }
                }
            }

            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
        }

        if (decisionTime > 0f)
        {
            decisionTime -= Time.deltaTime;
            return;
        }

        if (Random.value <= PokeChance)
        {
            Ray        ray = new Ray(owner.transform.position + Vector3.up, owner.transform.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 2, ~((1 << 9) | (1 << 11)), QueryTriggerInteraction.Ignore))
            {
                Pokeable lc = hit.collider.gameObject.GetComponent <Pokeable>();
                if (lc != null)
                {
                    if (lc.AllowMonsters())
                    {
                        lc.Poke(owner.gameObject);
                    }
                }
            }
        }

        if (Random.value <= NearSoundChanceAwake)
        {
            if (mc.NearSounds.Length > 0)
            {
                if (!mc.audioSource.isPlaying)
                {
                    mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                    mc.audioSource.Play();
                }
            }
        }

        decisionTime  = Random.Range(.4f, .6f);
        wantDirection = Vector3.zero;

        bool aggro = false;

        {
            float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
            if (distance < meleeAttackRange)
            {
                wantMove     = false;
                aggro        = true;
                attacked     = false;
                attackTime   = .7f;
                decisionTime = 0f;
                mc.InitAttackAnimation();
                mc.frametime = .2f;
            }
            else if (Random.value < AggroChance)
            {
                Ray toPlayer;
                if (SeePlayerRay(out toPlayer))
                {
                    wantDirection = new Vector3(toPlayer.direction.x, 0, toPlayer.direction.z);
                    wantMove      = false;
                    aggro         = true;
                    attacked      = false;
                    attackTime    = 1f;
                    decisionTime  = 0f;
                    mc.InitAttackAnimation();
                }
            }
        }

        if (!aggro)
        {
            float moveRoll = Random.value;
            if (moveRoll < randomMoveChance)
            {
                MoveToRandomNearbyCell();
            }
            else if (moveRoll < closestMoveChance)
            {
                if (!MoveToRandomClosestBreath())
                {
                    MoveToRandomNearbyCell();
                }
            }
            else
            {
                if (!MoveTowardsBreath())
                {
                    if (!MoveToRandomClosestBreath())
                    {
                        MoveToRandomNearbyCell();
                    }
                }
            }
        }

        if (Random.value < IdleChance)
        {
            wantMove = false;
        }

        if (wantMove)
        {
            mc.moveVector.x = 1;
        }
        else
        {
            mc.moveVector.x = 0;
        }
    }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }
            decisionTime = Random.Range(.4f, .6f);

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);
            if (distance > SeeDistance)
            {
                return;
            }

            if (Random.value <= NearSoundChanceSleeping)
            {
                if (mc.NearSounds.Length > 0)
                {
                    if (!mc.audioSource.isPlaying)
                    {
                        mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                        mc.audioSource.Play();
                    }
                }
            }

            if (SeePlayerRay())
            {
                alert        = true;
                decisionTime = 0f;
            }

            if (!alert)
            {
                return;
            }
        }

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            attackTime    = 0f;
            decisionTime  = 0f;
            return;
        }

        if (attackTime > 0f)
        {
            attackTime -= Time.deltaTime;

            Vector3 aimAt = (GameManager.Instance.Player[0].transform.position - mc.transform.position).normalized;
            //mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, new Vector3(aimAt.x, 0, aimAt.z), Time.deltaTime * mc.turnSpeed), Vector3.up);
            //instantenous rotation towards target
            mc.transform.rotation = Quaternion.LookRotation(new Vector3(aimAt.x, 0, aimAt.z), Vector3.up);

            if (attackTime < AttackHappenTime && !attacked)
            {
                attacked = true;

                float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
                if (distance < meleeAttackRange)
                {
                    if (CanMeleeRay(distance))
                    {
                        if (mc.AttackSounds.Length > 0)
                        {
                            GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[0], 5f);
                        }

                        Damageable d = GameManager.Instance.Player[0].GetComponent <Damageable>();
                        if (d != null)
                        {
                            d.Damage(Random.Range(MeleeDamageMin, MeleeDamageMax + 1), DamageType.Generic, owner.gameObject);
                        }
                    }
                }
            }

            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
        }

        if (decisionTime > 0f)
        {
            decisionTime -= Time.deltaTime;
            return;
        }

        if (Random.value <= NearSoundChanceAwake)
        {
            if (mc.NearSounds.Length > 0)
            {
                if (!mc.audioSource.isPlaying)
                {
                    mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                    mc.audioSource.Play();
                }
            }
        }

        decisionTime  = Random.Range(.2f, .3f);
        wantDirection = Vector3.zero;

        bool aggro = false;

        {
            float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
            if (distance < meleeAttackRange)
            {
                wantMove     = false;
                aggro        = true;
                attacked     = false;
                attackTime   = .7f;
                decisionTime = 0f;
                mc.InitAttackAnimation();
                mc.frametime = .2f;
            }
        }

        if (!aggro)
        {
            if (!MoveToRandomClosestBreath())
            {
                if (!MoveTowardsBreath())
                {
                    MoveToRandomNearbyCell();
                }
            }
        }

        if (Random.value < IdleChance)
        {
            wantMove = false;
        }

        if (wantMove)
        {
            mc.moveVector.x = 1;
        }
        else
        {
            mc.moveVector.x = 0;
        }
    }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }

            decisionTime = .5f;

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);

            if (distance > 400)
            {
                return;
            }

            Vector3 eyePos   = owner.transform.position + Vector3.up * 1.55f;
            Vector3 toPlayer = ((GameManager.Instance.Player[0].transform.position + Random.onUnitSphere * .5f) - eyePos).normalized;

            if (Vector3.Dot(owner.transform.forward, toPlayer) < -.15f)
            {
                return;
            }

            Ray        ray = new Ray(eyePos, toPlayer);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 400, ~((1 << 9) | (1 << 11) | (1 << 14)), QueryTriggerInteraction.Ignore))
            {
                if (hit.collider.GetComponent <PlayerThing>() != null)
                {
                    alert = true;
                }
            }

            if (!alert)
            {
                return;
            }
        }

        /*float mag = (lastpos - owner.transform.position).magnitude;
         * if (mag > 0.001f && mag < .02f)
         *  Debug.Log("hug");
         * lastpos = owner.transform.position;*/

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
            mc.moveVector         = mc.transform.forward;
        }

        if (decisionTime > 0f)
        {
            decisionTime -= Time.deltaTime;
            return;
        }

        decisionTime = Random.Range(.6f, 2f);

        wantDirection = Vector3.zero;

        if (!MoveToRandomClosestBreath())
        {
            if (!MoveTowardsBreath())
            {
                MoveToRandomNearbyCell();
            }
        }
    }