- Release triggers only fire if one is available in the current node's children.

- Crashes related to PreviousNode occasionally becoming null have been fixed.
This commit is contained in:
Jamie Greunbaum 2023-10-07 19:41:23 -04:00
parent 08b89b9d84
commit b77a9bd2ed

View File

@ -28,18 +28,19 @@ void UComboManagerComponent::InitializeComponent()
Super::InitializeComponent();
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;
this->PreviousNode = this->ActiveNode = this->ComboGraph->StartNode;
}
void UComboManagerComponent::SetComboGraph(const UComboActionGraph *Graph)
{
checkf(Graph, TEXT("Attempting to set a null combo graph."));
this->ComboGraph = Graph;
this->FoundInputsCache.Empty();
this->FindAllUsedInputs();
this->ActiveNode = this->ComboGraph->StartNode;
this->PreviousNode = nullptr;
this->ResetCombo();
}
@ -123,11 +124,40 @@ void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAss
void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *Input)
{
if (this->LastComboAction)
if (this->LastComboAction && this->ActiveNode)
{
this->BroadcastDelegates(this->LastComboAction, EComboActionTriggerEvent::Released);
this->LastComboAction = nullptr;
// See if we have a fallback we can release.
const TObjectPtr<const UComboAction> *FallbackAction = this->FallbackActions.Find(Input);
if (FallbackAction && *FallbackAction == this->LastComboAction)
{
this->ResetCombo();
this->BroadcastDelegates(*FallbackAction, EComboActionTriggerEvent::Released);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("Fallback action %s released"), *(*FallbackAction)->ActionName.ToString());
}
else
{
// Find a node that matches the release action.
const UComboAction *ComboAction = nullptr;
for (const UComboActionGraphNode *Node : this->ActiveNode->ChildNodes)
{
if (const UComboActionGraphNode_ActionNode *ActionNode = StaticCast<const UComboActionGraphNode_ActionNode *>(Node))
{
if (ActionNode->GetTriggerEvent() == EComboActionTriggerEvent::Released)
{
ComboAction = ActionNode->GetComboAction();
break;
}
}
}
if (ComboAction)
{
this->BroadcastDelegates(ComboAction, EComboActionTriggerEvent::Released);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s released"), *ComboAction->ActionName.ToString());
}
}
}
this->LastComboAction = nullptr;
}
@ -148,8 +178,16 @@ void UComboManagerComponent::FinishTransition()
void UComboManagerComponent::ResetCombo()
{
this->GetWorld()->GetTimerManager().ClearTimer(this->DEBUG__ResetComboTimer);
this->PreviousNode = this->ActiveNode;
this->ActiveNode = this->ComboGraph->StartNode;
this->PreviousNode = this->ActiveNode = this->ComboGraph->StartNode;
APlayerController *Controller = UGameplayStatics::GetPlayerController(this, 0);
if (UInputBufferComponent *InputComponent = Cast<UInputBufferComponent>(Controller->InputComponent))
{
for (const UComboInputAsset *Unlock : this->FoundInputsCache)
{
InputComponent->UnlockComboInput(Unlock);
}
}
}
@ -179,13 +217,13 @@ TSet<const UComboInputAsset *> &UComboManagerComponent::FindAllUsedInputs()
}
void UComboManagerComponent::FindAllUsedInputs_RecurseGraph(const UComboActionGraphNode *CurrentNode, TSet<const UComboInputAsset *> &FoundInputs)
{
for (const UComboActionGraphNode *NextNode : CurrentNode->ChildrenNodes)
for (const UComboActionGraphNode *NextNode : CurrentNode->ChildNodes)
{
// It should be safe to assume all of our nodes are action nodes. If at some point
// this becomes less reliable, this should be changed. But just for the sake of
// saving a bit of performance on start-up, we're doing this right now.
checkf(NextNode->GetClass() == UComboActionGraphNode_ActionNode::StaticClass(), TEXT("This graph contains non-action nodes. The cast in this function will fail."));
FoundInputs.Add(static_cast<const UComboActionGraphNode_ActionNode *>(NextNode)->GetComboInput());
FoundInputs.Add(StaticCast<const UComboActionGraphNode_ActionNode *>(NextNode)->GetComboInput());
this->FindAllUsedInputs_RecurseGraph(NextNode, FoundInputs);
}
}
@ -196,7 +234,7 @@ const UComboActionGraphNode *UComboManagerComponent::FindActiveNodeData(const UC
// Find a node that matches both the combo input and the trigger action.
const UComboActionGraphNode *NextNode = nullptr;
for (const UComboActionGraphNode *GraphNode : CurrentNode->ChildrenNodes)
for (const UComboActionGraphNode *GraphNode : CurrentNode->ChildNodes)
{
if (const UComboActionGraphNode_ActionNode *ActionNode = Cast<UComboActionGraphNode_ActionNode>(GraphNode))
{