Character custom movement mode is overriden when in the air

Your problem is that the character movement component sets the state to falling in several places.

SimulateMovement:


if (!CurrentFloor.IsWalkableFloor())
                {
                    if (!bSimGravityDisabled)
                    {
                        // No floor, must fall.
                        Velocity = NewFallVelocity(Velocity, FVector(0.f, 0.f, GetGravityZ()), DeltaSeconds);
                    }
                    SetMovementMode(MOVE_Falling);
                }

Also in ApplyRootMotionToVelocity (and 1 or 2 more physics calc functions):


if( AppliedVelocityDelta.Z > LiftoffBound )
        {
            SetMovementMode(MOVE_Falling);
        }

And more importantly, any time you perform the action “jump”.

DoJump:


// Don't jump if we can't move up/down.
        if (!bConstrainToPlane || FMath::Abs(PlaneConstraintNormal.Z) != 1.f)
        {
            Velocity.Z = JumpZVelocity;
            SetMovementMode(MOVE_Falling);
            return true;
        }

The right way to do this would be to write your own movement logic, is it worth it? Porbably not…

You can have a boolean that forcibly sets the state to Grappling within tick if true, this way you only cheat the engine for as long as you need it.