/// <summary>
    /// Uninitializes attack state after completing animation
    /// </summary>
    void ExitAttack()
    {
        // darken agent and initializes cooldown timer
        mySpriteRenderer.material.SetVector("_HSVAAdjust", cooldownHSV);
        waitCounter = attackCooldown;

        // set animation triggers and transition to wait state
        myAnimator.SetTrigger("OnWaitTrigger");
        myAnimator.ResetTrigger("OnAttackTrigger");
        currState = ChaseStates.Wait;
    }
    /// <summary>
    /// Used for initialization
    /// </summary>
    void Awake()
    {
        // retrieve components from agent
        myRigidbody      = GetComponent <Rigidbody2D>();
        mySpriteRenderer = GetComponent <SpriteRenderer>();
        myAnimator       = GetComponent <Animator>();
        sightTrigger     = GetComponent <CircleCollider2D>();

        // initialize agent and set internal variables
        currState = startingState;
        sightTrigger.isTrigger = true;
        standardHSV            = mySpriteRenderer.material.GetVector("_HSVAAdjust");
        ignoreLayerMask        = ~(1 << 12);
    }
    /// <summary>
    /// Updates agent as it waits for cooldown before returning to idle state
    /// </summary>
    void UpdateWait()
    {
        // gradually slow agent to a halt
        myRigidbody.velocity = Vector2.Lerp(myRigidbody.velocity, Vector2.zero, Time.deltaTime);

        // decrease wait counter by time between frames
        waitCounter -= Time.deltaTime;

        // after waiting specific time, transition to idle
        if (waitCounter <= 0)
        {
            currState = ChaseStates.Idle;
        }
    }
    /// <summary>
    /// Updates agent as it waits idly
    /// </summary>
    void UpdateIdle()
    {
        // slow agent to halt and lerp color to normal
        myRigidbody.velocity = Vector2.Lerp(myRigidbody.velocity, Vector2.zero, Time.deltaTime);
        mySpriteRenderer.material.SetVector("_HSVAAdjust",
                                            Vector4.Lerp(mySpriteRenderer.material.GetVector("_HSVAAdjust"), standardHSV, Time.deltaTime));

        // if agent has a target that they can see
        if (targetTransform != null && CanSeeTarget())
        {
            // set animation triggers
            myAnimator.SetTrigger("OnPursueTrigger");
            myAnimator.ResetTrigger("OnIdleTrigger");

            // move to pursue state
            currState = ChaseStates.Pursue;
            EnterPursue();
        }
    }
    /// <summary>
    /// Updates agent as it pursues its target
    /// </summary>
    void UpdatePursue()
    {
        // if agent can longer see target or has no target to pursue
        if (!(targetTransform != null && CanSeeTarget()))
        {
            // set animation triggers
            myAnimator.SetTrigger("OnIdleTrigger");
            myAnimator.ResetTrigger("OnPursueTrigger");

            // move to idle animation
            currState = ChaseStates.Idle;

            // return from this method to avoid target calculations
            return;
        }

        // lerp agent's color to normal
        mySpriteRenderer.material.SetVector("_HSVAAdjust",
                                            Vector4.Lerp(mySpriteRenderer.material.GetVector("_HSVAAdjust"), standardHSV, Time.deltaTime));

        // find distance from agent to target
        float distToTarget = (transform.position - targetTransform.position).magnitude;

        // move agent to intercept target
        float   targetDisplacementAtIntercept = (distToTarget / Mathf.Max(0.1f, myRigidbody.velocity.magnitude)) * targetRigidbody.velocity.magnitude;
        Vector3 interceptPoint = (Vector3)targetRigidbody.velocity.normalized * targetDisplacementAtIntercept + targetTransform.position;

        myRigidbody.velocity = Vector2.Lerp(myRigidbody.velocity, (interceptPoint - transform.position).normalized * AgentSpeed, Time.deltaTime);

        // if agent is within attack range
        if (distToTarget <= attackRange)
        {
            // set animation triggers
            myAnimator.SetTrigger("OnAttackTrigger");
            myAnimator.ResetTrigger("OnPursueTrigger");

            // move to attack state
            currState = ChaseStates.Attack;
            EnterAttack();
        }
    }