C++ Disable Player input when melee attacking

I need to disable character movement when melee attacking. I can do this in Blueprints with Montage is Playing node, Disable Movement then Set Movement Mode to walking. Also I use the Retriggerable Delay node so the player can’t spam the LMB.

Trying to get this done in C++ and this is what I have so far. When player uses LMB it call MainAttack.

This code disables the movement when I start in editor by clicking LMB.

void ARPGCharacter::MainAttack()
{
	UCharacterMovementComponent* MoveComp = GetCharacterMovement();
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	
	if (AnimInstance && MainAttackMontage)
	{
		MoveComp->DisableMovement();
		AnimInstance->Montage_Play(MainAttackMontage);
		MoveComp->SetMovementMode(MOVE_Walking);
	}
}

What is the best way of disabling character movement when montage is playing?

After looking at what others have done and reading through some code; I got it working. Here is what it looks like.

RPGCharacter.h

protected:

UFUNCTION()
void EnableWalk();

private:

FTimerHandle TimerMovementWalking;

RPGCharacter.cpp

void ARPGCharacter::MainAttack()
{
	UCharacterMovementComponent* MoveComp = GetCharacterMovement();
	
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	
	if (AnimInstance && MainAttackMontage)
	{
		MoveComp->DisableMovement();
		float EnableWalkTime = AnimInstance->Montage_Play(MainAttackMontage);

		GetWorldTimerManager().SetTimer(TimerMovementWalking, this, &ARPGCharacter::EnableWalk, EnableWalkTime);
	}
}

void ARPGCharacter::EnableWalk()
{
	UCharacterMovementComponent* MoveComp = GetCharacterMovement();
	MoveComp->SetMovementMode(MOVE_Walking);
}

What I don’t like is that I have 2 pointers for the MoveComp. I don’t know CPP that good, but I do think that duplicating code is bad. What is the best way to handle the MoveComp duplication?

Also need to find the best way to stop LMB spam that resets the animation. In blueprints I used retriggable delay.

you can cache it. With cache I mean save this pointer reference in a variable and use this variable instead to go and get this reference every time.

So, create a private pointer in your header (.h) file such as

private:
UCharacterMovementComponent* MoveCompRef = nullptr;

then properly fill its value in your .cpp

void ARPGCharacter::BeginPlay()
{
  MoveCompRef = GetCharacterMovement();
}

Now you can use MoveCompRef wherever you want with

if(MoveCompRef) //always check that is different from nullptr
{
  //use MoveCompRef 
}

good luck

I got it all done. Thanks for the help. Posting the completed code here if anybody in the future needs it. I created the reference to CharacterMovementComponent and it works great. Just incase the reference at begin play fails the else statement will use MoveComp. With the AnimInstance->Montage_IsPlaying this disables the player from spamming the button and restarting the animation.

header.h

protected:

    // Called when Main Attack button pressed IE: LMB
    void MainAttack();

    // Used to set walking again when disabled before using anim play montage
    UFUNCTION()
    void EnableWalk();

private:

	// Timer handle for disable character movement
	FTimerHandle TimerMovementWalking;

	// Save pointer reference for CharacterMovementComponent
	UCharacterMovementComponent* MoveCompRef = nullptr;

file.cpp

// Called when the game starts or when spawned
void ARPGCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	MoveCompRef = GetCharacterMovement();
}

void ARPGCharacter::MainAttack()
{
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && MainAttackMontage)
	{
		// Check to see if the montage is already playing
		if (!AnimInstance->Montage_IsPlaying(MainAttackMontage))
		{
			// Check reference to CharacterMovementComponent and disable movement.
			if (MoveCompRef)
			{
				MoveCompRef->DisableMovement();
			}
			else
			{
				UCharacterMovementComponent* MoveComp = GetCharacterMovement();
				MoveComp->DisableMovement();
			}
			
			float EnableWalkTime = AnimInstance->Montage_Play(MainAttackMontage);
			GetWorldTimerManager().SetTimer(TimerMovementWalking, this, &ARPGCharacter::EnableWalk, EnableWalkTime);
		}
	}
}

void ARPGCharacter::EnableWalk()
{
	// Check reference to CharactermovementComponent and set character movement to walking
	if (MoveCompRef)
	{
		MoveCompRef->SetMovementMode(MOVE_Walking);
	}
	else
	{
		UCharacterMovementComponent* MoveComp = GetCharacterMovement();
		MoveComp->SetMovementMode(MOVE_Walking);
	}
}