How to check whether an Input Action made in Blueprints is triggered (or grabs the value) from a C++ class that doesn't handle input for MOBA style ability indicator

Thank you for your detailed explanation as well as the documentation. It makes a lot of sense now. I’m curious about your thoughts on what’s written below, on whether this is the right logic.

I’m trying to learn how to do a system similar to Atlas Reactor but singleplayer (no way in heck can I do multiplayer at my skill level), the game has multiple phases, decision → prep → dash → blast → move, where all abilities happen simultaneously, but they have different phases and will activate during those phases.

My idea was to have a class that handles the turn queue (not sure what it would inherit from, GameModeBase? Then use that class, make delegates then bind them to the corresponding abilities. And then maybe have a function somewhere like:

{
	switch (AbilityPhase)
	{
	case EPhase::Prep:
		TurnQueue->OnPrepSignature.AddDynamic(this, &UAbilityComponent::Resolution);
		break;
	case EPhase::Dash:
		TurnQueue->OnDashSignature.AddDynamic(this, &UAbilityComponent::Resolution);
		break;
	case EPhase::Blast:
		TurnQueue->OnBlastSignature.AddDynamic(this, &UAbilityComponent::Resolution);
		break;
	case EPhase::Move:
		TurnQueue->OnBlastSignature.AddDynamic(this, &UAbilityComponent::Resolution);
		break;
	}
}

But I guess this system would be a subsystem? I already made sure to have two IMC that I’ll switch out for ‘Atlas Reactor mode’ and normal mode.

I also just realised, I wouldn’t actually even need to use SetTimer() inside of UAbilityComponent itself to check where to put the indicator (while you’re in decision mode). Because presumably in the decision mode, you’d have a timer that’s counting down, from the class that handles the turns, you’ll set the timer in there to check your mouse movement and choices.

This

would instead all be handled by APawn/ACharacter/AController since you said only pawns can have controllers.

FVector UAbilityComponent::GetPlayerCursorLocation() const
{
	FHitResult HitResult;
	GetWorld()->GetFirstPlayerController()->GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, true, HitResult);
	return HitResult.Location;
}

void UAbilityComponent::SetIndicatorDecalAtLocation()
{
	if (GetOwner() == nullptr || IndicatorDecalComponent == nullptr)
		return;

	FVector PlayerCursorLocation = GetPlayerCursorLocation();
	// Cự ly của indicator nên tương đối, 0 là địa điểm của nhân vật
	FVector PlayerCharacterLocation = GetOwner()->GetActorLocation();

	if (FVector::Dist(PlayerCursorLocation, PlayerCharacterLocation) > GetAbilityRange())
	{
		FHitResult Hit;
		FVector End = PlayerCharacterLocation + UKismetMathLibrary::FindLookAtRotation(PlayerCharacterLocation, PlayerCursorLocation).Vector() * GetAbilityRange();
		const FCollisionQueryParams CollisionQueryParams;
		const FCollisionResponseParams CollisionResponseParams;

		GetWorld()->LineTraceSingleByChannel(Hit, PlayerCharacterLocation, End, ECollisionChannel::ECC_Visibility, CollisionQueryParams, CollisionResponseParams);

		PlayerCursorLocation = Hit.Location;
	}

	IndicatorDecalComponent->SetWorldLocation(PlayerCursorLocation);
}

SetIndicatorDecalAtLocation() would be inside of the UAbilityComponent though and so would the UDecalComponent, I think. To me it doesn’t really make sense it would be attached to the character if it changes based on what ability it is.


I do have one problem though when I was trying to test setting my indicator, I can’t figure out though why it’s not setting the decal component in the world correctly when I move my mouse around, if the range is 0.0 it should be below the character. I have a timer that checks SetIndicatorDecalAtLocation() every 0.35 seconds and it runs. I was looking at the top down template for 4.27 and it was only adding a decal component to the character itself, not sure if that’s what’s causing the issue.

If I click on a specific spot it shows the decal but it doesn’t look right (should be circular). I can’t grab the decal component and reposition it despite it being editable anywhere (public), so I’m not sure if that’s the issue. I also tried adding a USceneComponent then attached the decal component to it, still can’t move either of them.



Mhm, I am confused why it would call PostInitializeComponents() in this situation. From what I understand in BP, when you add a component on the side, it’s the equivalent of CreateDefaultSubobject in C++ inside the constructor, so shouldn’t it be InitializeComponents()? Thank you, sorry for my late response, I got busy.