Exemplo n.º 1
0
        private bool ChooseAttack(bool onlyLookForTaps = false)
        {
            // Figure out which attack, if any, matches the current conditions
            attackDefinition = (from attack in _wS.attacks
                                //TODO instead of GetAttackDirection with inH and inV, do it relative to rotated player
                                where (!onlyLookForTaps || attack.attackInputType == AttackInputType.Tap) &&
                                attack.directionTriggers.Contains(_wS.GetAttackDirection(inH, inV)) &&
                                (!_wS.mvmt.grounded || attack.groundedState != GroundedState.NotGrounded) &&
                                (_wS.mvmt.grounded || attack.groundedState != GroundedState.Grounded) &&
                                attack.movementStates.Contains(_wS.mvmt.movementState)
                                select attack).DefaultIfEmpty(NoMatches).First();

            // If no attack matches, just cancel this attack (do nothing, basically)
            if (ReferenceEquals(attackDefinition, NoMatches))
            {
                if (ReferenceEquals(this, _wS.bufferAttack))
                {
                    _wS.bufferAttack.state = AttackState.Ended;
                }
                else
                {
                    EndAttack(dontFade: true);  // To also make buffer attack primary
                }
                return(false);
            }
            return(true);
        }
Exemplo n.º 2
0
    internal IEnumerator _CheckMeleeHit(AttackAction attackAction)
    {
        DirectionalAttackDefinition attackDefinition = attackAction.attackDefinition;

        _prevBase = weaponBase.position;
        _prevTip  = weaponTip.position;
        while (attackAction.state == AttackState.Attacking)
        {
            bool GetBaddyHit(out RaycastHit2D swingCheck)
            {
                bool HitBaddy(RaycastHit2D rHit)
                {
#if UNITY_EDITOR
                    if (visualizeDebug && rHit && !(rHit.collider.GetComponentInParent <IDamageable>() is null) &&
                        Linecast(_prevBase, rHit.point, whatIsNotHittable & ~(1 << rHit.collider.gameObject.layer)))
                    {
                        Debug.DrawLine(_prevBase, rHit.point, Color.red);
                    }
#endif
                    return(rHit && !(rHit.collider.GetComponentInParent <IDamageable>() is null) &&
                           // Make sure nothing of a different layer is between where the sword was and where it hit
                           !Linecast(_prevBase, rHit.point,
                                     whatIsNotHittable & ~(1 << rHit.collider.gameObject.layer)));
                }

//               print("CHECK1");
                //CHECK1: along blade
                Vector2 basePos = weaponBase.position;
                Vector2 tipPos  = weaponTip.position;
                swingCheck = Linecast(basePos, tipPos, whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawLine(basePos, tipPos);
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }


//               print("CHECK2");
                //CHECK2: along tip movement
                swingCheck = Linecast(_prevTip, tipPos, whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawLine(_prevTip, tipPos);
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }

//                print("CHECK3");
                //CHECK3: along base movement
                swingCheck = Linecast(_prevBase, basePos, whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawLine(_prevBase, basePos);
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }

//               print("CHECK4");
                //CHECK4: along lower third movement
                swingCheck = Linecast(Vector2.Lerp(_prevBase, _prevTip, 0.33f), Vector2.Lerp(basePos, tipPos, 0.33f),
                                      whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawLine(Vector2.Lerp(_prevBase, _prevTip, 0.33f), Vector2.Lerp(basePos, tipPos, 0.33f));
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }

//               print("CHECK5");
                //CHECK5: along upper third movement
                swingCheck = Linecast(Vector2.Lerp(_prevBase, _prevTip, 0.66f), Vector2.Lerp(basePos, tipPos, 0.66f),
                                      whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawLine(Vector2.Lerp(_prevBase, _prevTip, 0.66f), Vector2.Lerp(basePos, tipPos, 0.66f));
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }

//               print("CHECK6");
                //CHECK6: along first third blade
                float   swordLength = Vector2.Distance(basePos, tipPos);
                Vector2 baseMid     = Vector2.Lerp(_prevBase, basePos, 0.33f);
                Vector2 tipMid      = Vector2.Lerp(_prevTip, tipPos, 0.33f);
                swingCheck = Raycast(baseMid, tipMid - baseMid, swordLength, whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawRay(baseMid, (tipMid - baseMid).normalized * swordLength);
                }
#endif
                if (HitBaddy(swingCheck))
                {
                    return(true);
                }

//               print("CHECK7");
                //CHECK7: along second third blade
                baseMid    = Vector2.Lerp(_prevBase, basePos, 0.66f);
                tipMid     = Vector2.Lerp(_prevTip, tipPos, 0.66f);
                swingCheck = Raycast(baseMid, tipMid - baseMid, swordLength, whatIsHittable);
#if UNITY_EDITOR
                if (visualizeDebug)
                {
                    Debug.DrawRay(baseMid, (tipMid - baseMid).normalized * swordLength);
                }
#endif
                return(HitBaddy(swingCheck));
            }

            // Check for any hits, then update the prev things
            bool baddyHit = GetBaddyHit(out RaycastHit2D swingHit);
            _prevBase = weaponBase.position;
            _prevTip  = weaponTip.position;
            // Wait till next frame if we didn't hit anything hittable
            if (!baddyHit)
            {
                yield return(Yields.WaitForFixedUpdate);

                continue;
            }

            IDamageable damageable = swingHit.collider.GetComponentInParent <IDamageable>();
            Vector2     point      = swingHit.point;
            Vector2     force      = mvmt.rb.velocity; //Relative Velocity
            if (swingHit.collider.attachedRigidbody)
            {
                force -= swingHit.collider.attachedRigidbody.velocity;
            }
            force  = mass * force;                                        //Kinetic Energy = mv^2, but that was too much so just doing mv lol
            force += attackAction.attackDir * attackDefinition.knockback; // Add knockback in the direction of the swing


            switch (damageable.CheckProtected(point, swingHit.collider))
            {
            case ProtectedType.Dodging: yield break;

            case ProtectedType.Blocking: {
                //TODO recoil and sparks or something shit idk
                var     hTf    = holder.transform;
                Vector2 recoil = (hTf.position - swingHit.transform.position + hTf.up / 6) *
                                 attackDefinition.knockback;
                holder.characterPhysics?.AddForceAt(point, recoil, GetComponentInParent <Collider2D>());
                FadeAttackOut(0.30121f);
                attackAction.BeginRecovering();
                yield break;
            }
            }
            // Damage scaled based on relative velocity
            int damageGiven = (int)Math.Max(attackAction.attackDefinition.damage,
                                            attackAction.attackDefinition.knockback * mvmt.rb.velocity.magnitude);
            damageable.DamageMe(point, force, damageGiven, swingHit.collider);
            yield break;
        }
    }