Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
095cf66937 | ||
|
|
6af0b1c23a | ||
|
|
1d2dcdd693 |
@@ -37,7 +37,22 @@ void UComboManagerComponent::BeginPlay()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UComboManagerComponent::ActivateComboInput(const UComboInputAsset *Input)
|
void UComboManagerComponent::HandleComboInput(const UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent)
|
||||||
|
{
|
||||||
|
switch (TriggerEvent)
|
||||||
|
{
|
||||||
|
case EComboActionTriggerEvent::Activated:
|
||||||
|
this->ActivateComboAction(Input);
|
||||||
|
break;
|
||||||
|
case EComboActionTriggerEvent::Released:
|
||||||
|
this->ReleaseComboAction(Input);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboManagerComponent::ActivateComboAction(const UComboInputAsset *Input)
|
||||||
{
|
{
|
||||||
/************ DEBUG ************/
|
/************ DEBUG ************/
|
||||||
for (const TPair<TObjectPtr<const UComboInputAsset>, float> &Pair : this->DEBUG__UnlockTimers)
|
for (const TPair<TObjectPtr<const UComboInputAsset>, float> &Pair : this->DEBUG__UnlockTimers)
|
||||||
@@ -64,19 +79,27 @@ void UComboManagerComponent::ActivateComboInput(const UComboInputAsset *Input)
|
|||||||
const TObjectPtr<const UComboSequenceNode> CurrentNode = (this->ActiveNode ? this->ActiveNode : this->DefaultStartNode);
|
const TObjectPtr<const UComboSequenceNode> CurrentNode = (this->ActiveNode ? this->ActiveNode : this->DefaultStartNode);
|
||||||
checkf(CurrentNode, TEXT("No combo sequence nodes available."));
|
checkf(CurrentNode, TEXT("No combo sequence nodes available."));
|
||||||
|
|
||||||
if (CurrentNode->ComboBranch.Contains(Input))
|
const FComboSequenceAction *ActionData = CurrentNode->ComboBranch.Find(Input);
|
||||||
|
// If this node has an action we can activate, then activate it.
|
||||||
|
if (ActionData && ActionData->ComboAction)
|
||||||
{
|
{
|
||||||
const FComboSequenceAction &ActionData = CurrentNode->ComboBranch[Input];
|
this->BeginNodeTransition(ActionData->NextNode);
|
||||||
if (ActionData.ComboAction)
|
this->BroadcastDelegates(ActionData->ComboAction, EComboActionTriggerEvent::Activated);
|
||||||
{
|
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s activated"), *ActionData->ComboAction->ActionName.ToString());
|
||||||
this->BeginNodeTransition(ActionData.NextNode);
|
|
||||||
this->BroadcastDelegates(ActionData.ComboAction, EComboActionTriggerEvent::Activated);
|
|
||||||
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s activated"), *ActionData.ComboAction->ActionName.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Otherwise, see if we have a fallback we can use.
|
||||||
|
else if (const TObjectPtr<const UComboAction> *ComboAction = this->FallbackActions.Find(Input))
|
||||||
|
{
|
||||||
|
this->ResetCombo();
|
||||||
|
this->BroadcastDelegates(*ComboAction, EComboActionTriggerEvent::Activated);
|
||||||
|
UE_LOG(LogComboManagerComponent, Verbose, TEXT("Fallback action %s activated"), *(*ComboAction)->ActionName.ToString());
|
||||||
|
}
|
||||||
|
// If we haven't found an action to perform, reset the combo and activate using the default start node.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UE_LOG(LogComboManagerComponent, Verbose, TEXT("No branch found for this action"));
|
this->ActiveNode = nullptr;
|
||||||
|
this->ActivateComboAction(Input);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAsset> Unlock)
|
void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAsset> Unlock)
|
||||||
@@ -86,6 +109,15 @@ void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAss
|
|||||||
Subsystem->UnlockComboInput(Unlock);
|
Subsystem->UnlockComboInput(Unlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *Input)
|
||||||
|
{
|
||||||
|
if (this->LastComboAction)
|
||||||
|
{
|
||||||
|
this->BroadcastDelegates(this->LastComboAction, EComboActionTriggerEvent::Released);
|
||||||
|
this->LastComboAction = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void UComboManagerComponent::BeginNodeTransition(const UComboSequenceNode *NextNode)
|
void UComboManagerComponent::BeginNodeTransition(const UComboSequenceNode *NextNode)
|
||||||
{
|
{
|
||||||
@@ -93,11 +125,7 @@ void UComboManagerComponent::BeginNodeTransition(const UComboSequenceNode *NextN
|
|||||||
this->ActiveNode = NextNode;
|
this->ActiveNode = NextNode;
|
||||||
this->GetWorld()->GetTimerManager().SetTimer(this->FinishTransitionTimer, this, &UComboManagerComponent::FinishTransition, 0.5f);
|
this->GetWorld()->GetTimerManager().SetTimer(this->FinishTransitionTimer, this, &UComboManagerComponent::FinishTransition, 0.5f);
|
||||||
|
|
||||||
this->GetWorld()->GetTimerManager().SetTimer(this->DEBUG__ResetComboTimer, this, &UComboManagerComponent::DEBUG__ResetCombo, 1.0f);
|
this->GetWorld()->GetTimerManager().SetTimer(this->DEBUG__ResetComboTimer, this, &UComboManagerComponent::ResetCombo, 1.0f);
|
||||||
}
|
|
||||||
void UComboManagerComponent::DEBUG__ResetCombo()
|
|
||||||
{
|
|
||||||
this->ActiveNode = this->PreviousNode = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UComboManagerComponent::FinishTransition()
|
void UComboManagerComponent::FinishTransition()
|
||||||
@@ -105,6 +133,12 @@ void UComboManagerComponent::FinishTransition()
|
|||||||
this->PreviousNode = this->ActiveNode;
|
this->PreviousNode = this->ActiveNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UComboManagerComponent::ResetCombo()
|
||||||
|
{
|
||||||
|
this->GetWorld()->GetTimerManager().ClearTimer(this->DEBUG__ResetComboTimer);
|
||||||
|
this->ActiveNode = this->PreviousNode = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void UComboManagerComponent::BroadcastDelegates(const UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent)
|
void UComboManagerComponent::BroadcastDelegates(const UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent)
|
||||||
{
|
{
|
||||||
@@ -114,4 +148,5 @@ void UComboManagerComponent::BroadcastDelegates(const UComboAction *ComboAction,
|
|||||||
Binding->Execute(ComboAction, TriggerEvent);
|
Binding->Execute(ComboAction, TriggerEvent);
|
||||||
}
|
}
|
||||||
this->OnComboAction.Broadcast(ComboAction, (TriggerEvent == EComboActionTriggerEvent::Activated) ? true : false);
|
this->OnComboAction.Broadcast(ComboAction, (TriggerEvent == EComboActionTriggerEvent::Activated) ? true : false);
|
||||||
|
this->LastComboAction = ComboAction;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ FText UK2Node_ComboAction::GetTooltipText() const
|
|||||||
if (CachedTooltip.IsOutOfDate(this))
|
if (CachedTooltip.IsOutOfDate(this))
|
||||||
{
|
{
|
||||||
// FText::Format() is slow, so we cache this to save on performance
|
// FText::Format() is slow, so we cache this to save on performance
|
||||||
CachedTooltip.SetCachedText(FText::Format(NSLOCTEXT("K2Node", "ComboAction_Tooltip", "Event for when the combo action {0} is pressed or released."), FText::FromName(this->ComboAction->GetFName())), this);
|
CachedTooltip.SetCachedText(FText::Format(NSLOCTEXT("K2Node", "ComboAction_Tooltip", "Event for when the combo action {0} is activated or released.\nBoth execution pins might fire on the same frame if an action\nwas buffered during a release action, but \"Activated\" will\nalways happen before \"Released\"."), FText::FromName(this->ComboAction->GetFName())), this);
|
||||||
}
|
}
|
||||||
return CachedTooltip;
|
return CachedTooltip;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void UInputBufferLocalPlayerSubsystem::Initialize(FSubsystemCollectionBase &Coll
|
|||||||
void UInputBufferLocalPlayerSubsystem::AttachComboManager(UComboManagerComponent *ComboManager, UEnhancedInputComponent *InputComponent)
|
void UInputBufferLocalPlayerSubsystem::AttachComboManager(UComboManagerComponent *ComboManager, UEnhancedInputComponent *InputComponent)
|
||||||
{
|
{
|
||||||
// Get the player character and try to connect to its combo manager.
|
// Get the player character and try to connect to its combo manager.
|
||||||
this->NewComboInput.BindUObject(ComboManager, &UComboManagerComponent::ActivateComboInput);
|
this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput);
|
||||||
|
|
||||||
// Get all unique EnhancedInput actions bound to combo input actions.
|
// Get all unique EnhancedInput actions bound to combo input actions.
|
||||||
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
||||||
@@ -82,10 +82,12 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
|
|||||||
// overwriting a previous combo input with a multi-press combo input.
|
// overwriting a previous combo input with a multi-press combo input.
|
||||||
if (bNewSupercedesActive || !bNewInputLocked)
|
if (bNewSupercedesActive || !bNewInputLocked)
|
||||||
{
|
{
|
||||||
|
// Set the combo input as active.
|
||||||
|
this->InputBufferActive = ComboInput;
|
||||||
|
|
||||||
|
// If we have inputs to lock, prepare the buffer.
|
||||||
if (!ComboInput->LockedComboInputs.IsEmpty())
|
if (!ComboInput->LockedComboInputs.IsEmpty())
|
||||||
{
|
{
|
||||||
// Set the combo input as active, and copy its lock data.
|
|
||||||
this->InputBufferActive = ComboInput;
|
|
||||||
this->LockedComboInputs = ComboInput->LockedComboInputs;
|
this->LockedComboInputs = ComboInput->LockedComboInputs;
|
||||||
|
|
||||||
this->InputBufferHold = nullptr;
|
this->InputBufferHold = nullptr;
|
||||||
@@ -97,7 +99,14 @@ void UInputBufferLocalPlayerSubsystem::ActivateComboInput(const UComboInputAsset
|
|||||||
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is active and won't lock inputs."), *ComboInput->ComboInputName.ToString());
|
UE_LOG(LogInputBufferLocalPlayerSubsystem, Verbose, TEXT("%s is active and won't lock inputs."), *ComboInput->ComboInputName.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->NewComboInput.Execute(ComboInput);
|
this->OnNewComboInput.Execute(ComboInput, EComboActionTriggerEvent::Activated);
|
||||||
|
|
||||||
|
// If the incoming combo input contains an expiring action,
|
||||||
|
// we know it's been released, so send that signal too.
|
||||||
|
if (ComboInput->ContainsOneOf(this->ExpiringActions))
|
||||||
|
{
|
||||||
|
this->OnNewComboInput.Execute(ComboInput, EComboActionTriggerEvent::Released);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -147,6 +156,14 @@ void UInputBufferLocalPlayerSubsystem::UnlockComboInput(const UComboInputAsset *
|
|||||||
|
|
||||||
void UInputBufferLocalPlayerSubsystem::ExpireAction(const FInputActionValue &Value, const class UInputAction *Action)
|
void UInputBufferLocalPlayerSubsystem::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.
|
||||||
|
if (this->InputBufferActive && this->InputBufferActive != this->InputBufferHold && this->InputBufferActive->MatchesInputAction(Action))
|
||||||
|
{
|
||||||
|
this->OnNewComboInput.Execute(this->InputBufferActive, EComboActionTriggerEvent::Released);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to expire any buffered combo inputs
|
||||||
this->ExpiringActions.Add(Action);
|
this->ExpiringActions.Add(Action);
|
||||||
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
const UInputBufferSubsystemGlobalSettings *Settings = GetDefault<UInputBufferSubsystemGlobalSettings>();
|
||||||
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
|
this->GetWorld()->GetTimerManager().SetTimer(this->InputReleaseExpirationTimerHandle, this, &UInputBufferLocalPlayerSubsystem::ExpireBufferedActions, Settings->InputReleaseExpirationTimerLength);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
void ActivateComboInput(const class UComboInputAsset *Input);
|
void HandleComboInput(const class UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent);
|
||||||
|
|
||||||
void BindAction(UObject *ObjectToBindTo, FName FunctionName, const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent)
|
void BindAction(UObject *ObjectToBindTo, FName FunctionName, const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent)
|
||||||
{
|
{
|
||||||
@@ -66,6 +66,11 @@ protected:
|
|||||||
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
|
||||||
FComboOffsetMap OffsetMap;
|
FComboOffsetMap OffsetMap;
|
||||||
|
|
||||||
|
// A list of default input->action mappings. If you wish for an action to be handled
|
||||||
|
// outside the scope of a combo sequence node, it should go here.
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
|
||||||
|
TMap<TObjectPtr<const class UComboInputAsset>, TObjectPtr<const class UComboAction>> FallbackActions;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
|
||||||
TMap<TObjectPtr<const class UComboInputAsset>, float> DEBUG__UnlockTimers;
|
TMap<TObjectPtr<const class UComboInputAsset>, float> DEBUG__UnlockTimers;
|
||||||
|
|
||||||
@@ -73,17 +78,22 @@ protected:
|
|||||||
FComboActionHandlerDelegate OnComboAction;
|
FComboActionHandlerDelegate OnComboAction;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ActivateComboAction(const class UComboInputAsset *Input);
|
||||||
|
void ReleaseComboAction(const class UComboInputAsset *Input);
|
||||||
|
|
||||||
void BeginNodeTransition(const class UComboSequenceNode *NextNode);
|
void BeginNodeTransition(const class UComboSequenceNode *NextNode);
|
||||||
void FinishTransition();
|
void FinishTransition();
|
||||||
|
void ResetCombo();
|
||||||
|
|
||||||
void BroadcastDelegates(const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent);
|
void BroadcastDelegates(const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent);
|
||||||
|
|
||||||
void DEBUG__UnlockAction(TObjectPtr<const class UComboInputAsset> Unlock);
|
void DEBUG__UnlockAction(TObjectPtr<const class UComboInputAsset> Unlock);
|
||||||
void DEBUG__ResetCombo();
|
|
||||||
|
|
||||||
const class UComboSequenceNode *ActiveNode = nullptr;
|
const class UComboSequenceNode *ActiveNode = nullptr;
|
||||||
const class UComboSequenceNode *PreviousNode = nullptr;
|
const class UComboSequenceNode *PreviousNode = nullptr;
|
||||||
|
|
||||||
|
TObjectPtr<const class UComboAction> LastComboAction = nullptr;
|
||||||
|
|
||||||
TMap<FName, FComboActionHandlerDynamicSignature> ComboActionEventBindings;
|
TMap<FName, FComboActionHandlerDynamicSignature> ComboActionEventBindings;
|
||||||
|
|
||||||
TObjectPtr<class UInputBufferComponent> AttachedInputBuffer;
|
TObjectPtr<class UInputBufferComponent> AttachedInputBuffer;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(LogInputBufferLocalPlayerSubsystem, Log, All);
|
DECLARE_LOG_CATEGORY_EXTERN(LogInputBufferLocalPlayerSubsystem, Log, All);
|
||||||
|
|
||||||
DECLARE_DELEGATE_OneParam(FNewComboInput, const class UComboInputAsset*);
|
DECLARE_DELEGATE_TwoParams(FNewComboInput, const class UComboInputAsset*, const EComboActionTriggerEvent &);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +52,7 @@ private:
|
|||||||
TSet<const class UInputAction*> MostRecentActions;
|
TSet<const class UInputAction*> MostRecentActions;
|
||||||
TSet<const class UInputAction*> ExpiringActions;
|
TSet<const class UInputAction*> ExpiringActions;
|
||||||
|
|
||||||
FNewComboInput NewComboInput;
|
FNewComboInput OnNewComboInput;
|
||||||
|
|
||||||
FTimerHandle MultiPressTimerHandle;
|
FTimerHandle MultiPressTimerHandle;
|
||||||
FTimerHandle InputReleaseExpirationTimerHandle;
|
FTimerHandle InputReleaseExpirationTimerHandle;
|
||||||
|
|||||||
Reference in New Issue
Block a user