public bool ManualUpdate()
        {
            if (_mode != Mode.Grenade)
            {
                destroyGrenadePreview();
            }

            checkLanded();

            switch (_mode)
            {
            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Default:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Melee));
                }

                if (_motor.IsInCover)
                {
                    return(transitionAndPerform(Mode.Cover));
                }

                //// LOGIC //////////////////////

                checkArmLift();
                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkCover();
                checkGrenade();
                checkCrouch();
                checkMelee();
            } break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Sprint:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (!isSprinting())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                lowerArms();

                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkCover();
                checkGrenade();
                checkCrouch();
            }
            break;

            case Mode.Cover:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Aim));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Melee));
                }

                if (!_motor.IsInCover)
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                lowerArms();

                checkMelee();
                checkReload();
                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkGrenade();
                checkCrouch();
            } break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Aim:
            {
                //// TRANSITIONS //////////////////////

                if (!updateIsAiming())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                _noAimSustain = 0;

                if (AimWhenWalking && MovementInput.IsMoving)
                {
                    _aimSustain = AimSustain;
                }
                else
                {
                    _aimSustain -= Time.deltaTime;
                }

                checkZoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(1);
                checkCover();
                checkGrenade();
                checkCrouch();
                checkReload();
                checkMelee();

                if (CancelHurt)
                {
                    _motor.CancelAndPreventGetHit(0.3f);
                }

                liftArms();

                _motor.SetBodyTarget(BodyTargetInput);
                _motor.SetAimTarget(AimTargetInput);

                if (ImmediateTurns)
                {
                    _motor.InputPossibleImmediateTurn();
                }

                if (_motor.IsInCover)
                {
                    _motor.InputAimWhenLeavingCover();
                }

                _motor.InputAim();

                if (_motor.IsWeaponReady && FireInput)
                {
                    _aimSustain = AimSustain;

                    var gun = _motor.ActiveWeapon.Gun;

                    if (gun != null && gun.LoadedBulletsLeft <= 0)
                    {
                        _motor.InputReload();
                    }
                    else
                    {
                        _motor.InputFire();
                    }
                }

                if (_motor.IsWeaponScopeReady && ZoomInput)
                {
                    _aimSustain = AimSustain;

                    _motor.InputZoom();

                    if (_isScoping)
                    {
                        _motor.InputScope();
                    }
                }
            }
            break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Grenade:
            {
                if (!_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Default));
                }

                if (_motor.IsReadyToThrowGrenade && _motor.CurrentGrenade != null)
                {
                    GrenadeDescription desc;
                    desc.Gravity    = _motor.Grenade.Gravity;
                    desc.Duration   = _motor.PotentialGrenade.Timer;
                    desc.Bounciness = _motor.PotentialGrenade.Bounciness;

                    var verticalAngle = Mathf.Min(GrenadeVerticalAngleInput + ThrowAngleOffset, MaxThrowAngle);

                    var velocity = _motor.Grenade.MaxVelocity;

                    if (verticalAngle < 45)
                    {
                        velocity *= Mathf.Clamp01((verticalAngle + 15) / 45f);
                    }

                    _grenadePathLength = GrenadePath.Calculate(GrenadePath.Origin(_motor, GrenadeHorizontalAngleInput),
                                                               GrenadeHorizontalAngleInput,
                                                               verticalAngle,
                                                               velocity,
                                                               desc,
                                                               _grenadePath,
                                                               _motor.Grenade.Step);
                    _hasGrenadePath = true;

                    if (_explosionPreview == null && ExplosionPreview != null)
                    {
                        _explosionPreview = GameObject.Instantiate(ExplosionPreview);
                        _explosionPreview.transform.SetParent(null);
                        _explosionPreview.SetActive(true);
                    }

                    if (_explosionPreview != null)
                    {
                        _explosionPreview.transform.localScale = Vector3.one * _motor.PotentialGrenade.ExplosionRadius * 2;
                        _explosionPreview.transform.position   = _grenadePath[_grenadePathLength - 1];
                    }

                    if (_pathPreview == null && PathPreview != null)
                    {
                        _pathPreview = GameObject.Instantiate(PathPreview);
                        _pathPreview.transform.SetParent(null);
                        _pathPreview.SetActive(true);
                    }

                    if (_pathPreview != null)
                    {
                        _pathPreview.transform.position = _grenadePath[0];

                        var path = _pathPreview.GetComponent <PathPreview>();

                        if (path != null)
                        {
                            path.Points     = _grenadePath;
                            path.PointCount = _grenadePathLength;
                        }
                    }
                }
                else
                {
                    destroyGrenadePreview();
                }

                if (_hasGrenadePath && _wantsToThrowGrenade)
                {
                    if (ImmediateTurns)
                    {
                        _motor.InputPossibleImmediateTurn();
                    }

                    _motor.SetBodyTarget(BodyTargetInput);
                    _motor.SetAimTarget(BodyTargetInput);
                    _motor.InputThrowGrenade(_grenadePath, _grenadePathLength, _motor.Grenade.Step);
                }

                if (_wantsToCancelGrenade)
                {
                    _motor.InputCancelGrenade();
                }

                lowerArms();

                checkZoom();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkCover();
                checkCrouch();
            }
            break;

            //////////////////////////////////////////////////////////////////////////////////////////////////////
            case Mode.Melee:
            {
                //// TRANSITIONS //////////////////////

                if (_motor.HasGrenadeInHand)
                {
                    return(transitionAndPerform(Mode.Grenade));
                }

                if (isSprinting())
                {
                    return(transitionAndPerform(Mode.Sprint));
                }

                if (!updateIsMelee())
                {
                    return(transitionAndPerform(Mode.Default));
                }

                //// LOGIC //////////////////////

                checkUnzoom();
                checkEquipment();
                checkJump();
                checkRoll();
                checkClimbOrVault();
                checkMovement(2);
                checkGrenade();
                checkCrouch();
                checkMelee();

                if (_meleeTarget != null)
                {
                    _motor.SetBodyTarget(_meleeTarget.transform.position);
                    _motor.SetAimTarget(_meleeTarget.transform.position + Vector3.up * 1.5f);
                    _motor.InputMeleeTarget(_meleeTarget.transform.position);

                    if (!MovementInput.IsMoving)
                    {
                        var vector   = _meleeTarget.transform.position - _motor.transform.position;
                        var distance = vector.magnitude;

                        if (distance < MinMeleeDistance)
                        {
                            var other = Characters.Get(_meleeTarget.gameObject);

                            if (other.Motor == null || !other.Motor.IsPerformingMelee)
                            {
                                const float minMovementDuration = 0.2f;

                                if (distance < MinMeleeDistance * 0.35f)
                                {
                                    _motor.InputMovement(new CharacterMovement(-vector / distance, 1, minMovementDuration));
                                }
                                else
                                {
                                    _motor.InputMovement(new CharacterMovement(-vector / distance, 0.5f, minMovementDuration));
                                }
                            }
                        }
                    }
                }
            }
            break;
            }

            // RESET

            _wantsToThrowGrenade  = false;
            _wantsToAim           = false;
            _wantsToHit           = false;
            _wantsToRoll          = false;
            _wantsToReload        = false;
            _wantsToUnequip       = false;
            _wantsToTakeGrenade   = false;
            _wantsToCancelGrenade = false;
            _wantsToCrouch        = false;
            _wantsToTakeCover     = false;
            _wantsToJump          = false;
            _wantsToClimbOrVault  = null;

            if (!_wantsToEquip.IsNull)
            {
                _wantsToEquip = new WeaponDescription();
            }

            // RETURN

            return(true);
        }