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;
        }
    }