|
|
|
@@ -1,22 +1,24 @@
|
|
|
|
|
// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "InputBufferLocalPlayerSubsystem.h"
|
|
|
|
|
#include "Components/InputBufferComponent.h"
|
|
|
|
|
|
|
|
|
|
#include "ComboInputAssets.h"
|
|
|
|
|
#include "EnhancedInputComponent.h"
|
|
|
|
|
#include "Kismet/GameplayStatics.h"
|
|
|
|
|
|
|
|
|
|
#include "Components/ComboManagerComponent.h"
|
|
|
|
|
#include "GlobalSettings/InputBufferSubsystemGlobalSettings.h"
|
|
|
|
|
|
|
|
|
|
DEFINE_LOG_CATEGORY(LogInputBufferLocalPlayerSubsystem);
|
|
|
|
|
DEFINE_LOG_CATEGORY(LogInputBufferComponent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::Initialize(FSubsystemCollectionBase &Collection)
|
|
|
|
|
void UInputBufferComponent::BeginPlay()
|
|
|
|
|
{
|
|
|
|
|
Super::Initialize(Collection);
|
|
|
|
|
}
|
|
|
|
|
Super::BeginPlay();
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::AttachComboManager(UComboManagerComponent *ComboManager, UEnhancedInputComponent *InputComponent)
|
|
|
|
|
if (APlayerController *PlayerController = UGameplayStatics::GetPlayerController(this, 0))
|
|
|
|
|
{
|
|
|
|
|
if (UComboManagerComponent *ComboManager = PlayerController->GetComponentByClass<UComboManagerComponent>())
|
|
|
|
|
{
|
|
|
|
|
// Get the player character and try to connect to its combo manager.
|
|
|
|
|
this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput);
|
|
|
|
@@ -33,13 +35,15 @@ void UInputBufferLocalPlayerSubsystem::AttachComboManager(UComboManagerComponent
|
|
|
|
|
}
|
|
|
|
|
for (const UInputAction *InputAction : InputActionsToBind)
|
|
|
|
|
{
|
|
|
|
|
InputComponent->BindAction(InputAction, ETriggerEvent::Started, this, &UInputBufferLocalPlayerSubsystem::AddActionToBuffer, InputAction);
|
|
|
|
|
InputComponent->BindAction(InputAction, ETriggerEvent::Completed, this, &UInputBufferLocalPlayerSubsystem::ExpireAction, InputAction);
|
|
|
|
|
this->BindAction(InputAction, ETriggerEvent::Started, this, &UInputBufferComponent::AddActionToBuffer, InputAction);
|
|
|
|
|
this->BindAction(InputAction, ETriggerEvent::Completed, this, &UInputBufferComponent::ExpireAction, InputAction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action)
|
|
|
|
|
void UInputBufferComponent::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action)
|
|
|
|
|
{
|
|
|
|
|
this->MostRecentActions.Add(Action);
|
|
|
|
|
this->ExpiringActions.Remove(Action);
|
|
|
|
@@ -56,9 +60,9 @@ void UInputBufferLocalPlayerSubsystem::AddActionToBuffer(const FInputActionValue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ClearMultiPresses, Settings->MultiPressTimerLength);
|
|
|
|
|
this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferComponent::ClearMultiPresses, Settings->MultiPressTimerLength);
|
|
|
|
|
}
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::ClearMultiPresses()
|
|
|
|
|
void UInputBufferComponent::ClearMultiPresses()
|
|
|
|
|
{
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
TArray<FString> ActionNames;
|
|
|
|
@@ -66,12 +70,12 @@ void UInputBufferLocalPlayerSubsystem::ClearMultiPresses()
|
|
|
|
|
{
|
|
|
|
|
ActionNames.Add(Action->GetName());
|
|
|
|
|
}
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
|
|
|
|
|
#endif
|
|
|
|
|
this->MostRecentActions.Empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset *ComboInput)
|
|
|
|
|
void UInputBufferComponent::ActivateComboInput(const UComboInputAsset *ComboInput)
|
|
|
|
|
{
|
|
|
|
|
checkf(ComboInput, TEXT("Invalid %s."), *UComboInputAsset::StaticClass()->GetName());
|
|
|
|
|
|
|
|
|
@@ -84,19 +88,12 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
|
|
|
|
|
{
|
|
|
|
|
// Set the combo input as active.
|
|
|
|
|
this->InputBufferActive = ComboInput;
|
|
|
|
|
|
|
|
|
|
// If we have inputs to lock, prepare the buffer.
|
|
|
|
|
if (!ComboInput->LockedComboInputs.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
this->LockedComboInputs = ComboInput->LockedComboInputs;
|
|
|
|
|
|
|
|
|
|
this->InputBufferHold = nullptr;
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is active."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
|
|
|
|
for (const TSoftObjectPtr<const UComboInputAsset> &LockedAsset : Settings->ComboActions)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is active and won't lock inputs."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
this->LockComboInput(LockedAsset.Get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->OnNewComboInput.Execute(ComboInput, EComboActionTriggerEvent::Activated);
|
|
|
|
@@ -107,6 +104,8 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
|
|
|
|
|
{
|
|
|
|
|
this->OnNewComboInput.Execute(ComboInput, EComboActionTriggerEvent::Released);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s is active."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@@ -114,27 +113,32 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::HoldComboInput(const UComboInputAsset *ComboInput)
|
|
|
|
|
void UInputBufferComponent::HoldComboInput(const UComboInputAsset *ComboInput)
|
|
|
|
|
{
|
|
|
|
|
this->InputBufferHold = ComboInput;
|
|
|
|
|
UE_SUPPRESS(LogInputBufferLocalPlayerSubsystem, Verbose,
|
|
|
|
|
UE_SUPPRESS(LogInputBufferComponent, Verbose,
|
|
|
|
|
{
|
|
|
|
|
if (this->LockedComboInputs.Contains(ComboInput))
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is locked and won't be activated yet."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s is locked and won't be activated yet."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s added to buffer."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s added to buffer."), *ComboInput->ComboInputName.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::UnlockComboInput(const UComboInputAsset *Unlocked)
|
|
|
|
|
void UInputBufferComponent::LockComboInput(const UComboInputAsset *Input)
|
|
|
|
|
{
|
|
|
|
|
this->LockedComboInputs.Emplace(Input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UInputBufferComponent::UnlockComboInput(const UComboInputAsset *Unlocked)
|
|
|
|
|
{
|
|
|
|
|
// Remove the newly-unlocked asset from the locked combo inputs.
|
|
|
|
|
UE_CLOG(this->LockedComboInputs.Contains(Unlocked), LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has unlocked."), *Unlocked->ComboInputName.ToString());
|
|
|
|
|
UE_CLOG(this->LockedComboInputs.Contains(Unlocked), LogInputBufferComponent, Verbose, TEXT("%s has unlocked."), *Unlocked->ComboInputName.ToString());
|
|
|
|
|
this->LockedComboInputs.Remove(Unlocked);
|
|
|
|
|
|
|
|
|
|
// Check if the newly unlocked combo input is in the hold.
|
|
|
|
@@ -150,11 +154,11 @@ void UInputBufferLocalPlayerSubsystem::UnlockComboInput(const UComboInputAsset *
|
|
|
|
|
this->ActivateComboInput(HeldAsset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has expired."), *OriginalActive->ComboInputName.ToString());
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s has expired."), *OriginalActive->ComboInputName.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::ExpireAction(const FInputActionValue &Value, const class UInputAction *Action)
|
|
|
|
|
void UInputBufferComponent::ExpireAction(const FInputActionValue &Value, const class UInputAction *Action)
|
|
|
|
|
{
|
|
|
|
|
// Only send a release event if we haven't already, i.e. if the combo input associated
|
|
|
|
|
// with the action is not already buffered for another future activation.
|
|
|
|
@@ -166,21 +170,21 @@ void UInputBufferLocalPlayerSubsystem::ExpireAction(const FInputActionValue &Val
|
|
|
|
|
// Prepare to expire any buffered combo inputs
|
|
|
|
|
this->ExpiringActions.Add(Action);
|
|
|
|
|
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
|
|
|
|
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
|
|
|
|
|
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferComponent::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
|
|
|
|
|
}
|
|
|
|
|
void UInputBufferLocalPlayerSubsystem::ExpireBufferedActions()
|
|
|
|
|
void UInputBufferComponent::ExpireBufferedActions()
|
|
|
|
|
{
|
|
|
|
|
// Only bother dealing with this if there's something to deal with in the first place.
|
|
|
|
|
if (!this->ExpiringActions.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
UE_SUPPRESS(LogInputBufferLocalPlayerSubsystem, Verbose,
|
|
|
|
|
UE_SUPPRESS(LogInputBufferComponent, Verbose,
|
|
|
|
|
{
|
|
|
|
|
TArray<FString> ActionNames;
|
|
|
|
|
for (const UInputAction *Action : this->ExpiringActions)
|
|
|
|
|
{
|
|
|
|
|
ActionNames.Add(Action->GetName());
|
|
|
|
|
}
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("Released actions expired (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Released actions expired (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
@@ -192,7 +196,7 @@ void UInputBufferLocalPlayerSubsystem::ExpireBufferedActions()
|
|
|
|
|
{
|
|
|
|
|
if (this->InputBufferHold->MatchesInputAction(Action))
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s has been cancelled."), *this->InputBufferHold->ComboInputName.ToString());
|
|
|
|
|
UE_LOG(LogInputBufferComponent, Verbose, TEXT("%s has been cancelled."), *this->InputBufferHold->ComboInputName.ToString());
|
|
|
|
|
this->InputBufferHold = nullptr;
|
|
|
|
|
break;
|
|
|
|
|
}
|