private static WeaponAnimType GetWeaponFallback(WeaponAnimType weaponType)
    {
        switch (weaponType)
        {
        // Oddly enough these are not marked as having substitutes, so i wonder
        // if they are actually used...
        case WeaponAnimType.Mace:
        case WeaponAnimType.Hammer:
        case WeaponAnimType.Axe:
        case WeaponAnimType.Club:
        case WeaponAnimType.Battleaxe:
            return(WeaponAnimType.Sword);

        case WeaponAnimType.Greataxe:
        case WeaponAnimType.Greathammer:
            return(WeaponAnimType.Greatsword);

        case WeaponAnimType.Shield:
            return(WeaponAnimType.Unarmed);

        case WeaponAnimType.Flail:
            return(WeaponAnimType.Sword);

        case WeaponAnimType.TwoHandedFlail:
            return(WeaponAnimType.Polearm);

        case WeaponAnimType.Shuriken:
        case WeaponAnimType.Monk:
            return(WeaponAnimType.Unarmed);

        default:
            return(weaponType);
        }
    }
    public EncodedAnimId(WeaponAnim anim,
                         WeaponAnimType mainHand = WeaponAnimType.Unarmed,
                         WeaponAnimType offHand  = WeaponAnimType.Unarmed) : this(sWeaponAnimFlag)
    {
        var animId     = (int)anim;
        var mainHandId = (int)mainHand;
        var offHandId  = (int)offHand;

        mId |= animId & 0xFFFFF;
        mId |= mainHandId << 20;
        mId |= offHandId << 25;
    }
// True if the weapon has to fallback on both hands
    private static bool IsWeapon2hFallback(WeaponAnimType weaponType)
    {
        switch (weaponType)
        {
        case WeaponAnimType.Greatsword:
        case WeaponAnimType.Greataxe:
        case WeaponAnimType.Greathammer:
        case WeaponAnimType.Spear:
        case WeaponAnimType.Staff:
        case WeaponAnimType.Polearm:
        case WeaponAnimType.Bow:
        case WeaponAnimType.Crossbow:
        case WeaponAnimType.Chain:
        case WeaponAnimType.TwoHandedFlail:
        case WeaponAnimType.Shuriken:
        case WeaponAnimType.Monk:
            return(true);

        default:
            return(false);
        }
    }
    private void HandleTurnMovement()
    {
        if (this.ParentCharacter.UpperBodyState == HumanUpperBodyStates.Idle || this.ParentCharacter.UpperBodyState == HumanUpperBodyStates.HalfAim)
        {
            _isStrafing = false;

            //check the destination and look angle
            Vector3 lookDir = this.ParentCharacter.LookTarget.position - this.ParentCharacter.transform.position;
            lookDir = new Vector3(lookDir.x, 0, lookDir.z);

            Vector3 destDir = this.ParentCharacter.GetCharacterVelocity().normalized;
            destDir = new Vector3(destDir.x, 0, destDir.z);
            float lookDestAngle      = Vector3.Angle(lookDir, destDir);
            float destRightBodyAngle = Vector3.Angle(destDir, this.ParentCharacter.transform.right);

            this.ParentCharacter.MyAnimator.SetFloat("LookDestAngle", 0);
            this.ParentCharacter.MyAnimator.SetFloat("DestRightBodyAngle", destRightBodyAngle);

            /*
             * if(lookDestAngle > 90)
             * {
             *      _isWalkingBack = true;
             *      _isStrafing = false;
             *
             *      Vector3 direction = destDir * -1 + lookDir.normalized * 0.05f;
             *      Quaternion rotation = Quaternion.LookRotation(direction);
             *      this.ParentCharacter.transform.rotation = Quaternion.Lerp(this.ParentCharacter.transform.rotation, rotation, Time.deltaTime * 5);
             * }
             * else */
            {
                _isWalkingBack = false;
                _isStrafing    = false;

                Vector3    direction = destDir + lookDir.normalized * 0.05f;
                Quaternion rotation  = Quaternion.LookRotation(direction);
                this.ParentCharacter.transform.rotation = Quaternion.Lerp(this.ParentCharacter.transform.rotation, rotation, Time.deltaTime * 5);
            }
        }
        else if (this.ParentCharacter.UpperBodyState == HumanUpperBodyStates.Aim)
        {
            //check the destination and look angle
            Vector3 lookDir = this.ParentCharacter.LookTarget.position - this.ParentCharacter.transform.position;
            lookDir = new Vector3(lookDir.x, 0, lookDir.z);

            Vector3 destDir = this.ParentCharacter.Destination.Value - this.ParentCharacter.transform.position;
            destDir = new Vector3(destDir.x, 0, destDir.z);

            float lookDestAngle      = Vector3.Angle(lookDir, destDir);
            float destRightBodyAngle = Vector3.Angle(destDir, this.ParentCharacter.transform.right);
            this.ParentCharacter.MyAnimator.SetFloat("LookDestAngle", lookDestAngle);
            this.ParentCharacter.MyAnimator.SetFloat("DestRightBodyAngle", destRightBodyAngle);
            //Debug.Log("look dest angle " + lookDestAngle);
            //if destination and look dir angle greater than 90 it means we are walking backwards. when
            //walking backwards disable agent update rotation and manually align rotation to opposite of destDir
            //when holding weapon and aiming, then it's 45 degrees so we will go into strafe mode
            WeaponAnimType weaponType = (WeaponAnimType)this.ParentCharacter.MyAnimator.GetInteger("WeaponType");

            if (weaponType == WeaponAnimType.Pistol || weaponType == WeaponAnimType.Longgun || weaponType == WeaponAnimType.Grenade)
            {
                if (lookDestAngle > 45 && lookDestAngle <= 135)
                {
                    //strafe
                    _isStrafing    = true;
                    _isWalkingBack = false;

                    Vector3 direction = Vector3.zero;
                    //check if body is turning left or right by checking the angle between lookdir and cross(up, destdir)
                    Vector3 crossUpDestDir    = Vector3.Cross(Vector3.up, destDir);
                    float   lookCrossDirAngle = Vector3.Angle(lookDir, crossUpDestDir);

                    if (lookCrossDirAngle > 90)
                    {
                        direction = crossUpDestDir * -1;
                    }
                    else
                    {
                        direction = crossUpDestDir;
                    }

                    Quaternion rotation = Quaternion.LookRotation(direction);
                    this.ParentCharacter.transform.rotation = Quaternion.Lerp(this.ParentCharacter.transform.rotation, rotation, Time.deltaTime * 5);
                }
                else if (lookDestAngle > 135)
                {
                    //walk back
                    _isWalkingBack = true;
                    _isStrafing    = false;

                    Vector3    direction = destDir * -1 + lookDir.normalized * 0.05f;
                    Quaternion rotation  = Quaternion.LookRotation(direction);
                    this.ParentCharacter.transform.rotation = Quaternion.Lerp(this.ParentCharacter.transform.rotation, rotation, Time.deltaTime * 5);
                }
                else
                {
                    //walk forward
                    _isWalkingBack = false;
                    _isStrafing    = false;

                    Vector3    direction = destDir + lookDir.normalized * 0.05f;
                    Quaternion rotation  = Quaternion.LookRotation(direction);
                    this.ParentCharacter.transform.rotation = Quaternion.Lerp(this.ParentCharacter.transform.rotation, rotation, Time.deltaTime * 5);
                }
            }
        }
    }
 private static string GetWeaponTypeName(WeaponAnimType weaponAnimType)
 {
     return(sWeaponTypeNames[(int)weaponAnimType]);
 }