diff --git a/Source/ComboInput/Private/Components/InputBufferComponent.cpp b/Source/ComboInput/Private/Components/InputBufferComponent.cpp index 9f5b738..01ad2fe 100644 --- a/Source/ComboInput/Private/Components/InputBufferComponent.cpp +++ b/Source/ComboInput/Private/Components/InputBufferComponent.cpp @@ -59,20 +59,47 @@ void UInputBufferComponent::InitializeComponent() void UInputBufferComponent::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action) { - this->MostRecentActions.Add(Action); + this->MultiPressActions.Add(Action); this->ExpiringActions.Remove(Action); // Find any combo input that matches this action, plus buffered actions. + bool bComboInputFound = false; for (TObjectPtr ComboInput : this->ComboInputList) { - if (ComboInput->MatchesInputActions(this->MostRecentActions)) + if (ComboInput->MatchesInputActions(this->MultiPressActions)) { this->ActivateComboInput(ComboInput.Get()); - + bComboInputFound = true; break; } } + // If we haven't found any matching inputs, check if anything was somehow unhandled. + // This can happen if, for example, a jump input can combine with an attack input to + // create a combo action, but jump by itself has no action on its own. + if (!bComboInputFound) + { + if (!this->UnhandledActions.IsEmpty()) + { + TSet HandledActions = this->MultiPressActions; + for (const UInputAction *UnhandledAction : this->UnhandledActions) + { + HandledActions.Remove(UnhandledAction); + } + + for (TObjectPtr ComboInput : this->ComboInputList) + { + if (ComboInput->MatchesInputActions(HandledActions)) + { + this->ActivateComboInput(ComboInput); + bComboInputFound = true; + break; + } + } + } + this->UnhandledActions.Add(Action); + } + const UInputBufferGlobalSettings *Settings = GetDefault(); this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferComponent::ClearMultiPresses, Settings->MultiPressTimerLength); } @@ -80,13 +107,14 @@ void UInputBufferComponent::ClearMultiPresses() { #if WITH_EDITOR TArray ActionNames; - for (const UInputAction *Action : this->MostRecentActions) + for (const UInputAction *Action : this->MultiPressActions) { ActionNames.Add(Action->GetName()); } UE_LOG(LogInputBufferComponent, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | "))); #endif - this->MostRecentActions.Empty(); + this->MultiPressActions.Empty(); + this->UnhandledActions.Empty(); } void UInputBufferComponent::ActivateComboInput(const UComboInputAsset *ComboInput) diff --git a/Source/ComboInput/Public/Components/InputBufferComponent.h b/Source/ComboInput/Public/Components/InputBufferComponent.h index f4a2bd0..e8ceb7f 100644 --- a/Source/ComboInput/Public/Components/InputBufferComponent.h +++ b/Source/ComboInput/Public/Components/InputBufferComponent.h @@ -53,7 +53,8 @@ private: // A local backup of the global setting containing the list of combo inputs to respond to. TSet> ComboInputList; - TSet MostRecentActions; + TSet MultiPressActions; + TSet UnhandledActions; TSet ExpiringActions; FNewComboInput OnNewComboInput;