IEnumerator StartChasing()
    {
        switch (ecoState)
        {
        case EcoState.ANGRY:
        case EcoState.TALK:
            animator.SetFloat(zombieData.HashCommunication, (int)Random.Range(1f, 21f));
            animator.SetBool(zombieData.HashMatchComplete, false);
            matchedZombie = null;
            break;

        case EcoState.BITE:
            animator.SetTrigger(zombieData.HashStandUp);
            yield return(new WaitForSeconds(clipTimes["StandUp"]));

            animator.SetFloat(zombieData.HashHungry, (int)Random.Range(0f, 20f));
            animator.SetBool(zombieData.HashBite, false);
            findFood = null;
            break;
        }

        agent.stoppingDistance = 0;
        if (state == State.IDLE)
        {
            animator.SetBool(zombieData.HashMove, false);
        }
        else
        {
            animator.SetBool(zombieData.HashMove, true);
        }
        ecoState = EcoState.NONE;
    }
 /// <summary>
 /// Initialize economics with initial params.
 /// </summary>
 public void StartEconomics(PlayerData playerData)
 {
     SetPrices();
     currentPrice = initialPrice;
     influence    = 2f;
     Quantity     = playerData.quantity;
     Deposit      = playerData.deposit;
     PositionOpen = false;
     newEcoState  = EcoState.middle;
     ecoState     = EcoState.middle;
 }
    public void ReactiveZombie()
    {
        if (!target)
        {
            var player = GameObject.FindGameObjectWithTag("Player");
            if (player != null && state != State.TRIGGER)
            {
                target = player.transform;
            }
        }
        if (!agent)
        {
            agent = GetComponent <NavMeshAgent>();
        }
        if (!animator)
        {
            animator = GetComponentInChildren <Animator>();
        }

        ws = new WaitForSeconds(0.3f);

        if (clipTimes.Count == 0)
        {
            UpdateAnimClipTimes();
        }
        agent.updateRotation    = false;
        agent.autoBraking       = false;
        agent.avoidancePriority = Random.Range(30, 50);
        HP      = zombieData.InitHp;
        damping = zombieData.Damping;
        agent.stoppingDistance = zombieData.AttackDist - 0.1f;
        animator.SetFloat(zombieData.HashCommunication, Random.Range(1f, 21f));
        animator.SetFloat(zombieData.HashHungry, Random.Range(0f, 20f));
        life          = 0;
        state         = State.IDLE;
        ecoState      = EcoState.NONE;
        isDie         = false;
        transform.tag = "Zombie";
        StartCoroutine(Action());
        StartCoroutine(RandomState());
        StartCoroutine(Eco());
        StartCoroutine(StateRoutine());
        StartCoroutine(RotateRoutine());
    }
    IEnumerator RotateRoutine()
    {
        while (!isDie)
        {
            yield return(ws);

            damping = ((state != State.ATTACK && state != State.CHASING) ? 3.0f : 7.0f);

            var rotValue = (state != State.ATTACK ? agent.desiredVelocity : (targetPos - transform.position).normalized);
            var rot      = Quaternion.LookRotation(rotValue);

            try
            {
                if (ecoState == EcoState.TALK && matchedZombie)
                {
                    rot = Quaternion.LookRotation((matchedZombie.position - transform.position).normalized);
                    transform.rotation = Quaternion.Slerp(transform.rotation, rot, Time.deltaTime * damping);
                }
                else if (findFood && ecoState == EcoState.BITE &&
                         findFood.gameObject.activeInHierarchy)
                {
                    rot = Quaternion.LookRotation((findFood.position - transform.position).normalized);
                    transform.rotation = Quaternion.Slerp(transform.rotation, rot, Time.deltaTime * damping);
                }
                else
                {
                    transform.rotation = ((state != State.IDLE) ?
                                          Quaternion.Slerp(transform.rotation, rot, Time.deltaTime * damping) :
                                          Quaternion.Slerp(transform.rotation, Quaternion.identity, Time.deltaTime * damping));
                }
            }
            catch (MissingReferenceException e)
            {
                animator.SetFloat(zombieData.HashHungry, (int)Random.Range(0f, 20f));
                findFood = null;
                agent.stoppingDistance = 0;
                animator.SetBool(zombieData.HashMove, false);
                agent.speed = 0;
                ecoState    = EcoState.NONE;
            }
        }
    }
 /// <summary>
 /// Returns true if economics state is changed. (Current price crosses support/resistance prices.)
 /// </summary>
 /// <returns></returns>
 public bool GetEconomicChanged()
 {
     if (currentPrice > resistancePrice)
     {
         newEcoState = EcoState.upper;
     }
     else if (currentPrice < supportPrice)
     {
         newEcoState = EcoState.lower;
     }
     else
     {
         newEcoState = EcoState.middle;
     }
     if (ecoState != newEcoState)
     {
         ecoState = newEcoState;
         return(true);
     }
     else
     {
         return(false);
     }
 }
    IEnumerator Eco()
    {
        while (state < State.TRIGGER)
        {
            yield return(new WaitForSeconds(0.5f));

            life += Time.deltaTime;
            if (life >= 10 && Vector3.Distance(targetPos, transform.position) >= 10.0f)
            {
                ResetZombieStat();
            }

            int angry = (int)Random.Range(1f, 101f);
            if (angry <= 1 && ecoState == EcoState.NONE)
            {
                animator.SetFloat(zombieData.HashCommunication, 0f);
            }
            else if (ecoState == EcoState.NONE)
            {
                animator.SetFloat(zombieData.HashCommunication, animator.GetFloat(zombieData.HashCommunication) + (int)Random.Range(0f, 10f));
                animator.SetFloat(zombieData.HashHungry, animator.GetFloat(zombieData.HashHungry) + (int)Random.Range(0f, 10f));
            }

            int maxState = (animator.GetFloat(zombieData.HashCommunication) < animator.GetFloat(zombieData.HashHungry) &&
                            animator.GetFloat(zombieData.HashCommunication) > 0 ? 1 : 0);
            switch (maxState)
            {
            case 0:
                if (animator.GetFloat(zombieData.HashCommunication) > 75)
                {
                    ecoState = EcoState.TALK;
                }
                else if (animator.GetFloat(zombieData.HashCommunication) == 0)
                {
                    ecoState = EcoState.ANGRY;
                }
                else
                {
                    ecoState = EcoState.NONE;
                }
                break;

            case 1:
                if (animator.GetFloat(zombieData.HashHungry) > 75)
                {
                    ecoState = EcoState.BITE;
                }
                else
                {
                    ecoState = EcoState.NONE;
                }
                break;
            }

            switch (ecoState)
            {
            case EcoState.ANGRY:
                agent.isStopped = true;
                yield return(new WaitForSeconds(clipTimes["Scream"]));

                animator.SetFloat(zombieData.HashCommunication, (int)Random.Range(1f, 21f));
                ecoState = EcoState.NONE;
                break;

            case EcoState.TALK:
                if (!matchedZombie)
                {
                    MatchZombie();
                }
                if (!matchedZombie)
                {
                    animator.SetFloat(zombieData.HashCommunication, 0f);
                    break;
                }

                agent.isStopped      = false;
                agent.updateRotation = true;
                animator.SetBool(zombieData.HashMove, true);
                agent.speed            = zombieData.PatrolSpeed;
                agent.stoppingDistance = zombieData.TalkDist;
                agent.SetDestination(matchedZombie.position);
                if (Vector3.Distance(transform.position, matchedZombie.position) <= zombieData.TalkDist)
                {
                    agent.isStopped      = true;
                    agent.updateRotation = false;
                    animator.SetBool(zombieData.HashMatchComplete, true);
                    yield return(new WaitForSeconds(clipTimes["Talk"]));

                    animator.SetFloat(zombieData.HashCommunication, (int)Random.Range(1f, 21f));
                    animator.SetBool(zombieData.HashMatchComplete, false);
                    matchedZombie          = null;
                    agent.stoppingDistance = 0;
                    if (state == State.IDLE)
                    {
                        animator.SetBool(zombieData.HashMove, false);
                    }
                    else
                    {
                        animator.SetBool(zombieData.HashMove, true);
                    }
                    ecoState = EcoState.NONE;
                }
                break;

            case EcoState.BITE:
                if (findFood == null)
                {
                    FindFood();
                }
                if (findFood == null)
                {
                    animator.SetFloat(zombieData.HashHungry, (int)Random.Range(0f, 20f));
                    break;
                }

                agent.isStopped      = false;
                agent.updateRotation = true;
                animator.SetBool(zombieData.HashMove, true);
                agent.speed            = zombieData.PatrolSpeed;
                agent.stoppingDistance = zombieData.AttackDist;
                agent.SetDestination(findFood.position);
                if (Vector3.Distance(findFood.position, transform.position) <= zombieData.AttackDist)
                {
                    agent.isStopped      = true;
                    agent.updateRotation = false;
                    animator.SetBool(zombieData.HashBite, true);
                    yield return(new WaitForSeconds(clipTimes["Bite"]));

                    animator.SetFloat(zombieData.HashHungry, (int)Random.Range(0f, 20f));
                    animator.SetBool(zombieData.HashBite, false);
                    if (findFood != null && findFood.gameObject.activeInHierarchy)
                    {
                        findFood.GetComponent <ZombieController>().ResetZombieStat();
                    }
                    findFood = null;
                    agent.stoppingDistance = 0;
                    animator.SetBool(zombieData.HashMove, false);
                    agent.speed = 0;
                    ecoState    = EcoState.NONE;
                }
                else if (!findFood.gameObject.activeInHierarchy)
                {
                    animator.SetFloat(zombieData.HashHungry, (int)Random.Range(0f, 20f));
                    findFood = null;
                    agent.stoppingDistance = 0;
                    animator.SetBool(zombieData.HashMove, false);
                    agent.speed = 0;
                    ecoState    = EcoState.NONE;
                }
                break;
            }
        }
    }
    IEnumerator Action()
    {
        while (!isDie)
        {
            yield return(ws);

            switch (state)
            {
            case State.DIE:
                agent.isStopped = true;
                agent.ResetPath();
                ecoState = EcoState.NONE;
                animator.SetBool(zombieData.HashMove, false);
                isDie         = true;
                transform.tag = "Food";
                //StopAllCoroutines();
                yield return(new WaitForSeconds(15.0f));

                ResetZombieStat();
                break;

            case State.IDLE:
                if (ecoState != EcoState.NONE)
                {
                    break;
                }
                agent.isStopped = true;
                animator.SetBool(zombieData.HashMove, false);
                break;

            case State.PATROL:
                if (ecoState != EcoState.NONE)
                {
                    break;
                }
                agent.isStopped = false;
                animator.SetBool(zombieData.HashMove, true);
                agent.speed = zombieData.PatrolSpeed;
                if (!agent.hasPath || Vector3.Distance(agent.pathEndPosition, transform.position) <= agent.stoppingDistance)
                {
                    agent.SetDestination(SetRandomPoint(transform, zombieData.PatrolRadius));
                }
                break;

            case State.CHASING:
                if (animator.GetBool(zombieData.HashNotFoundTarget))
                {
                    animator.SetTrigger(zombieData.HashFoundTarget);
                }
                agent.isStopped = false;
                if (!isCalling)
                {
                    NearZombieAttack();
                    isCalling = true;
                }
                animator.SetBool(zombieData.HashMove, true);
                agent.speed = zombieData.ChaseSpeed;
                bool chaseTargetMode;
                if (NavMesh.CalculatePath(transform.position, targetPos, NavMesh.AllAreas, new NavMeshPath()))
                {
                    notHavePath = false;
                    if (mode == Mode.Spread)
                    {
                        if (randomPos == null || Vector3.Distance(targetPos, randomPos) > zombieData.SpreadDist)
                        {
                            CheckTargetPosition(zombieData.SpreadDist);
                        }
                    }
                    chaseTargetMode = (mode == Mode.Basic ||
                                       Vector3.Distance(targetPos, transform.position) <= zombieData.SpreadDist);
                    agent.SetDestination(chaseTargetMode ? targetPos : randomPos);
                }
                else
                {
                    notHavePath = true;
                    NavMeshHit hit;
                    if (agent.FindClosestEdge(out hit))
                    {
                        agent.SetDestination(hit.position);
                    }
                }
                agent.stoppingDistance = zombieData.AttackDist;
                agent.autoBraking      = true;
                break;

            case State.ATTACK:
                agent.isStopped = true;
                animator.SetBool(zombieData.HashMove, false);
                if (notHavePath)
                {
                    animator.SetTrigger(zombieData.HashNotFoundTarget);
                    yield return(new WaitForSeconds(clipTimes["Scream"]));
                }
                else
                {
                    animator.SetTrigger(zombieData.HashAttack);
                    yield return(new WaitForSeconds(clipTimes["Attack"]));

                    NearZombieAttack();
                }
                break;

            case State.TRIGGER:
                if (ecoState != EcoState.NONE)
                {
                    break;
                }
                if (animator.GetBool(zombieData.HashNotFoundTarget))
                {
                    animator.SetTrigger(zombieData.HashFoundTarget);
                }
                agent.isStopped = false;
                agent.speed     = zombieData.ChaseSpeed;
                animator.SetBool(zombieData.HashMove, true);
                if (mode == Mode.Spread)
                {
                    if (randomPos == null || Vector3.Distance(targetPos, randomPos) > zombieData.SpreadDist)
                    {
                        CheckTargetPosition(zombieData.SpreadDist);
                    }
                }
                chaseTargetMode = (mode == Mode.Basic || Vector3.Distance(targetPos, transform.position) <= zombieData.SpreadDist);
                agent.SetDestination(chaseTargetMode ? targetPos : randomPos);
                if (agent.destination.x == 0 && agent.destination.z == 0)
                {
                    agent.SetDestination(new Vector3(targetPos.x, transform.position.y, targetPos.z));
                }
                break;
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        food       -= Time.deltaTime;
        spawnTimer += Time.deltaTime;

        if (spawnTimer >= spawnRate)
        {
            spawnTimer = 0;
            int scount = Random.Range(spawnMin, spawnMax);
            for (int i = 0; i < scount; ++i)
            {
                GameObject kid = Instantiate(child);
                kid.transform.position = transform.position;
                Vector3 posmod = new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f));
                kid.transform.position += posmod;
            }
        }

        if (predatorType != "" && FindPredator())
        {
            state = EcoState.FLEE;
        }

        switch (state)
        {
        case EcoState.WANDER:
            Wander();
            if (food < huntingThreshold && FindTarget())
            {
                state = EcoState.PURSUE;
            }
            break;

        case EcoState.PURSUE:
            if (target == null)
            {
                SwitchToWander();
                break;
            }
            Pursue();
            break;

        case EcoState.FLEE:
            if (target == null)
            {
                SwitchToWander();
                break;
            }
            Flee();
            if (Vector3.Distance(transform.position, target.position) > fleeingRange)
            {
                SwitchToWander();
            }
            break;
        }

        if (food <= 0 || transform.position.y < -1f)
        {
            Destroy(gameObject);
        }
    }
 // Use this for initialization
 void Start()
 {
     state      = EcoState.WANDER;
     food       = bellySize;
     wanderTarg = transform.position;
 }
 private void SwitchToWander()
 {
     resetWander = true;
     state       = EcoState.WANDER;
 }