Ejemplo n.º 1
0
    IEnumerator <float> Attack()
    {
        var   attackRangeSqrd = settings.AttackRange * settings.AttackRange;
        float t = 0;

        state = State.Attack;
        anim.SetFloat(CharacterAnimationHelper.DirZ, 0);
        anim.SetFloat(CharacterAnimationHelper.Speed, 0);

        // Make the enemy rotate towards the target while waiting for SecondsBeforeAttack
        while (t < settings.SecondsBeforeAttack)
        {
            t += Time.deltaTime;

            var dist = (target.position - transform.position).WithY(0);

            var targetLookRot = Quaternion.LookRotation(dist, Vector3.up);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetLookRot, t / settings.SecondsBeforeAttack);

            var sqrMagn = dist.sqrMagnitude;

            if (sqrMagn > attackRangeSqrd)
            {
                yield return(MEC.Timing.WaitForSeconds(0.15f));

                Reset();
                yield break;
            }
            yield return(0f);
        }

        // Attack using one of the three attack moves
        var attackHash = CharacterAnimationHelper.GetHashForCombo(Random.Range(0, 3));

        anim.CrossFadeInFixedTime(attackHash, 0.1f);

        // Hit scanning will be registered via animation events

        t = 0;
        while (t < settings.SecondsAfterAttack)
        {
            t += Time.deltaTime;
            yield return(0f);
        }

        Reset();

        void Reset()
        {
            state = State.Chase;
            anim.SetFloat(CharacterAnimationHelper.DirZ, 1);
            anim.SetFloat(CharacterAnimationHelper.Speed, 1);
        }
    }
Ejemplo n.º 2
0
    void HandleAttack()
    {
        if ((state == State.FreeToDoActions || state == State.Attacking) && currentCombo < 2 && Input.GetMouseButtonDown(0))
        {
            var  percentage = timeSincePrevAttack / (float)anim.GetCurrentAnimatorStateInfo(0).length;
            bool canAttack  = percentage >= settings.minComboSkipTime;
            if (canAttack)
            {
                PlayNextCombo();
            }
        }

        timeSincePrevAttack += Time.deltaTime;
        if (timeSincePrevAttack >= settings.maxSecondsToKeepCombo && currentCombo != -1)
        {
            ResetCombo();
        }



        void PlayNextCombo()
        {
            currentCombo++;
            timeSincePrevAttack = 0;

            state = State.Attacking;

            MEC.Timing.KillCoroutines(attackCommand);
            attackCommand = MEC.Timing.RunCoroutine(DoAttackStuff());

            var t = currentCombo == -1 ? 0 : settings.comboSkipTimeCurve.Evaluate(timeSincePrevAttack / settings.maxSecondsToKeepCombo);

            anim.CrossFadeInFixedTime(CharacterAnimationHelper.GetHashForCombo(currentCombo), 0.2f, 0, t);
        }

        void ResetCombo()
        {
            currentCombo = -1;
            if (state == State.Attacking)
            {
                state = State.FreeToDoActions;
            }
        }

        IEnumerator <float> DoAttackStuff()
        {
            const float totalTimeToRotate   = 0.25f;
            const float totalTimeToAnimMove = 0.25f;
            float       t = 0;

            var extents = hitCollider.bounds.extents;

            enemiesHit.Clear();

            while (t < totalTimeToRotate)
            {
                var targetRotY = Mathf.MoveTowardsAngle(transform.eulerAngles.y, targetLookRot.eulerAngles.y, settings.AttackRotationSpeed * Time.deltaTime);
                transform.eulerAngles = transform.eulerAngles.WithY(targetRotY);

                t += Time.deltaTime;
                yield return(0f);
            }

            var curve = CharacterAnimationHelper.GetSettingForCombo(currentCombo, settings);

            t = 0;

            while (t < totalTimeToAnimMove)
            {
                t += Time.deltaTime;
                cc.Move(curve.Evaluate(t / totalTimeToAnimMove) * transform.forward * settings.moveForcePerAttack * Time.deltaTime);

                ScanForHitsAndAttack();

                yield return(0f);
            }
        }

        void ScanForHitsAndAttack()
        {
            int hitAmount = Physics.OverlapBoxNonAlloc(hitCollider.bounds.center, hitCollider.bounds.extents, results, Quaternion.identity, LayerHelper.enemyLayer, QueryTriggerInteraction.Collide);

            for (int i = 0; i < hitAmount; i++)
            {
                var col = results[i];
                if (!col || enemiesHit.Contains(col))
                {
                    return;
                }
                var enemy = col.GetComponent <Enemy>();
                enemy.OnDamaged?.Invoke(settings.Damage);
                enemiesHit.Add(col);
            }
        }
    }