ComboManagerComponent has been modified to use the combo graph nodes instead of the placeholder ComboSequenceNode class.

This commit is contained in:
Jamie Greunbaum 2023-10-02 18:48:33 -04:00
parent 49ffadd4f3
commit 510ccb936a
5 changed files with 62 additions and 101 deletions

View File

@ -2,21 +2,31 @@
#include "Components/ComboManagerComponent.h"
#include "ComboActionGraph.h"
#include "ComboInputAssets.h"
#include "Components/InputBufferComponent.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
#include "Nodes/ComboActionGraphNode_ActionNode.h"
DEFINE_LOG_CATEGORY(LogComboManagerComponent);
UComboManagerComponent::UComboManagerComponent()
{
PrimaryComponentTick.bStartWithTickEnabled = false;
PrimaryComponentTick.bTickEvenWhenPaused = false;
PrimaryComponentTick.bCanEverTick = false;
this->PrimaryComponentTick.bStartWithTickEnabled = false;
this->PrimaryComponentTick.bTickEvenWhenPaused = false;
this->PrimaryComponentTick.bCanEverTick = false;
}
void UComboManagerComponent::BeginPlay()
{
Super::BeginPlay();
checkf(this->ComboGraph, TEXT("No combo graph is set for %s in actor %s"), *UComboManagerComponent::StaticClass()->GetName(), *this->GetOwner()->GetName());
this->ActiveNode = this->ComboGraph->StartNode;
}
@ -59,23 +69,29 @@ void UComboManagerComponent::ActivateComboAction(const UComboInputAsset *Input)
return;
}
const TObjectPtr<const UComboSequenceNode> CurrentNode = (this->ActiveNode ? this->ActiveNode : this->DefaultStartNode);
checkf(CurrentNode, TEXT("No combo sequence nodes available."));
const FComboSequenceAction *ActionData = CurrentNode->ComboBranch.Find(Input);
// If this node has an action we can activate, then activate it.
if (ActionData && ActionData->ComboAction)
// Find the next node in the graph.
const UComboAction *ComboAction = nullptr;
const UComboActionGraphNode *NextNode = this->FindActiveNodeData(this->ActiveNode, Input, EComboActionTriggerEvent::Activated, ComboAction);
if (!NextNode)
{
this->BeginNodeTransition(ActionData->NextNode);
this->BroadcastDelegates(ActionData->ComboAction, EComboActionTriggerEvent::Activated);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s activated"), *ActionData->ComboAction->ActionName.ToString());
// If there is no next active node, then return to the start node.
NextNode = this->FindActiveNodeData(this->ComboGraph->StartNode, Input, EComboActionTriggerEvent::Activated, ComboAction);
}
checkf(NextNode, TEXT("No combo sequence nodes available."));
// If this node has an action we can activate, then activate it.
if (ComboAction)
{
this->BeginNodeTransition(NextNode);
this->BroadcastDelegates(ComboAction, EComboActionTriggerEvent::Activated);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s activated"), *ComboAction->ActionName.ToString());
}
// Otherwise, see if we have a fallback we can use.
else if (const TObjectPtr<const UComboAction> *ComboAction = this->FallbackActions.Find(Input))
else if (const TObjectPtr<const UComboAction> *FallbackAction = this->FallbackActions.Find(Input))
{
this->ResetCombo();
this->BroadcastDelegates(*ComboAction, EComboActionTriggerEvent::Activated);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("Fallback action %s activated"), *(*ComboAction)->ActionName.ToString());
this->BroadcastDelegates(*FallbackAction, EComboActionTriggerEvent::Activated);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("Fallback action %s activated"), *(*FallbackAction)->ActionName.ToString());
}
// If we haven't found an action to perform, end here.
else
@ -102,7 +118,7 @@ void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *In
}
void UComboManagerComponent::BeginNodeTransition(const UComboSequenceNode *NextNode)
void UComboManagerComponent::BeginNodeTransition(const UComboActionGraphNode *NextNode)
{
this->PreviousNode = this->ActiveNode;
this->ActiveNode = NextNode;
@ -119,7 +135,28 @@ void UComboManagerComponent::FinishTransition()
void UComboManagerComponent::ResetCombo()
{
this->GetWorld()->GetTimerManager().ClearTimer(this->DEBUG__ResetComboTimer);
this->ActiveNode = this->PreviousNode = nullptr;
this->PreviousNode = this->ActiveNode;
this->ActiveNode = this->ComboGraph->StartNode;
}
const UComboActionGraphNode *UComboManagerComponent::FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction)
{
// Find a node that matches both the combo input and the trigger action.
const UComboActionGraphNode *NextNode = nullptr;
for (const UComboActionGraphNode *GraphNode : CurrentNode->ChildrenNodes)
{
if (const UComboActionGraphNode_ActionNode *ActionNode = Cast<UComboActionGraphNode_ActionNode>(GraphNode))
{
if (ActionNode->GetComboInput() == Input && ActionNode->GetTriggerEvent() == EComboActionTriggerEvent::Activated)
{
ComboAction = ActionNode->GetComboAction();
NextNode = ActionNode;
break;
}
}
}
return NextNode;
}

View File

@ -9,24 +9,6 @@
#include "ComboInputAssets.generated.h"
/**
* Struct that is used as the value for a combo branch. ComboAction is the action to be
* executed, and NextNode is the node that will be activated next in the sequence.
*/
USTRUCT(BlueprintType)
struct COMBOINPUT_API FComboSequenceAction
{
GENERATED_BODY()
public:
// Action to perform when the associated combo sequence node is activated.
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TObjectPtr<const class UComboAction> ComboAction;
// Sequence node to switch to once this action is complete.
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TObjectPtr<const class UComboSequenceNode> NextNode;
};
/**
* An action that can be executed as part of a combo sequence. This is essentially a
* representation of an attack, and can be sent to the Animation Graph to play an
@ -43,21 +25,6 @@ public:
FName ActionName;
};
/**
* This represents a node in the combo graph, with each key in the ComboBranch being
* an input this node can react to, and each value containing the action to be executed
* next, and the node to activate after the action is complete.
*/
UCLASS(BlueprintType)
class COMBOINPUT_API UComboSequenceNode : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TMap<const class UComboInputAsset *, struct FComboSequenceAction> ComboBranch;
};
/**
* This maps a sequence of button inputs from EnhancedInput to a combo action that can
* be used to execute a sequence of moves. This gets sent from the input buffer subsystem

View File

@ -43,6 +43,8 @@ class COMBOINPUT_API UComboManagerComponent : public UActorComponent
public:
UComboManagerComponent();
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable)
void HandleComboInput(const class UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent);
@ -56,7 +58,7 @@ public:
protected:
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TObjectPtr<const class UComboSequenceNode> DefaultStartNode;
TObjectPtr<const class UComboActionGraph> ComboGraph;
// This input will be recognised as an offset input, which cancels a node transition
// if activated early enough in the transition. This locks the current place in the
@ -80,16 +82,18 @@ private:
void ActivateComboAction(const class UComboInputAsset *Input);
void ReleaseComboAction(const class UComboInputAsset *Input);
void BeginNodeTransition(const class UComboSequenceNode *NextNode);
void BeginNodeTransition(const class UComboActionGraphNode *NextNode);
void FinishTransition();
void ResetCombo();
const UComboActionGraphNode *FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction);
void BroadcastDelegates(const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent);
void DEBUG__UnlockAction(TObjectPtr<const class UComboInputAsset> Unlock);
TObjectPtr<const class UComboSequenceNode> ActiveNode = nullptr;
TObjectPtr<const class UComboSequenceNode> PreviousNode = nullptr;
TObjectPtr<const class UComboActionGraphNode> ActiveNode = nullptr;
TObjectPtr<const class UComboActionGraphNode> PreviousNode = nullptr;
TObjectPtr<const class UComboAction> LastComboAction = nullptr;

View File

@ -36,16 +36,6 @@ public:
virtual UClass *GetSupportedClass() const override { return UComboAction::StaticClass(); }
};
class FAssetTypeActions_ComboSequenceNode : public FAssetTypeActions_DataAsset
{
public:
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboSequenceNode", "Combo Sequence Node"); }
virtual uint32 GetCategories() override { return FComboInputEditorModule::GetInputAssetsCategory(); }
virtual FColor GetTypeColor() const override { return FColor(255, 127, 255); }
virtual FText GetAssetDescription(const FAssetData &AssetData) const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboSequenceNodeDesc", "This represents a node in the combo graph, with each key in the ComboBranch being an input this node can react to, and each value containing the action to be executed next, and the node to activate after the action is complete."); }
virtual UClass *GetSupportedClass() const override { return UComboSequenceNode::StaticClass(); }
};
class FAssetTypeActions_ComboInputAsset : public FAssetTypeActions_DataAsset
{
public:
@ -120,28 +110,6 @@ UObject *UComboAction_Factory::FactoryCreateNew(UClass *Class, UObject *InParent
}
UComboSequenceNode_Factory::UComboSequenceNode_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
this->SupportedClass = UComboSequenceNode::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboSequenceNode_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboSequenceNodeClass != nullptr)
{
return NewObject<UComboSequenceNode>(InParent, this->ComboSequenceNodeClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboSequenceNode::StaticClass()));
return NewObject<UComboSequenceNode>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
UComboInputAsset_Factory::UComboInputAsset_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
@ -315,7 +283,6 @@ void FComboInputEditorModule::StartupModule()
IAssetTools &AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
FComboInputEditorModule::ComboAssetsCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Combo Input")), LOCTEXT("ComboInputAssetsCategory", "Combo Input"));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboAction));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboSequenceNode));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboInputAsset));
// Make a new style set for Combo Input, which will register any custom icons for the types in this plugin

View File

@ -27,20 +27,6 @@ public:
virtual UObject *FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn) override;
};
UCLASS()
class COMBOINPUTEDITOR_API UComboSequenceNode_Factory : public UFactory
{
GENERATED_BODY()
public:
UComboSequenceNode_Factory(const class FObjectInitializer &ObjectInitializer);
UPROPERTY(EditAnywhere, Category="Combo Input")
TSubclassOf<class UComboSequenceNode> ComboSequenceNodeClass;
virtual UObject *FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn) override;
};
UCLASS()
class COMBOINPUTEDITOR_API UComboInputAsset_Factory : public UFactory
{