bool FindNodeOwner(AActor* OwningActor, class UBTNode* Node, UBehaviorTreeComponent*& OwningComp, int32& OwningInstanceIdx) { bool bFound = false; APawn* OwningPawn = Cast<APawn>(OwningActor); if (OwningPawn && OwningPawn->Controller) { bFound = FindNodeOwner(OwningPawn->Controller, Node, OwningComp, OwningInstanceIdx); } if (OwningActor && !bFound) { TArray<UBehaviorTreeComponent*> Components; OwningActor->GetComponents(Components); for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++) { UBehaviorTreeComponent* BTComp = Components[ComponentIndex]; if (BTComp) { const int32 InstanceIdx = BTComp->FindInstanceContainingNode(Node); if (InstanceIdx != INDEX_NONE) { OwningComp = BTComp; OwningInstanceIdx = InstanceIdx; bFound = true; break; } } } } return bFound; }
void UBTComposite_SimpleParallel::NotifyChildExecution(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32 ChildIdx, EBTNodeResult::Type& NodeResult) const { FBTParallelMemory* MyMemory = (FBTParallelMemory*)NodeMemory; if (ChildIdx == EBTParallelChild::MainTask) { MyMemory->MainTaskResult = NodeResult; if (NodeResult == EBTNodeResult::InProgress) { EBTTaskStatus::Type Status = OwnerComp.GetTaskStatus(Children[EBTParallelChild::MainTask].ChildTask); if (Status == EBTTaskStatus::Active) { // can't register if task is currently being aborted (latent abort returns in progress) MyMemory->bMainTaskIsActive = true; MyMemory->bForceBackgroundTree = false; OwnerComp.RegisterParallelTask(Children[EBTParallelChild::MainTask].ChildTask); RequestDelayedExecution(OwnerComp, EBTNodeResult::Succeeded); } } else if (MyMemory->bMainTaskIsActive) { MyMemory->bMainTaskIsActive = false; const int32 MyInstanceIdx = OwnerComp.FindInstanceContainingNode(this); OwnerComp.UnregisterParallelTask(Children[EBTParallelChild::MainTask].ChildTask, MyInstanceIdx); if (NodeResult != EBTNodeResult::Aborted && !MyMemory->bRepeatMainTask) { // check if subtree should be aborted when task finished with success/failed result if (FinishMode == EBTParallelMode::AbortBackground) { OwnerComp.RequestExecution((UBTCompositeNode*)this, MyInstanceIdx, Children[EBTParallelChild::MainTask].ChildTask, EBTParallelChild::MainTask, NodeResult); } } } else if (NodeResult == EBTNodeResult::Succeeded && FinishMode == EBTParallelMode::WaitForBackground) { // special case: if main task finished instantly, but composite is supposed to wait for background tree, // request single run of background tree anyway MyMemory->bForceBackgroundTree = true; RequestDelayedExecution(OwnerComp, EBTNodeResult::Succeeded); } } }
void UBTTaskNode::ReceivedMessage(UBrainComponent* BrainComp, const FAIMessage& Message) { UBehaviorTreeComponent* OwnerComp = static_cast<UBehaviorTreeComponent*>(BrainComp); check(OwnerComp); const uint16 InstanceIdx = OwnerComp->FindInstanceContainingNode(this); if (OwnerComp->InstanceStack.IsValidIndex(InstanceIdx)) { uint8* NodeMemory = GetNodeMemory<uint8>(OwnerComp->InstanceStack[InstanceIdx]); OnMessage(*OwnerComp, NodeMemory, Message.MessageName, Message.RequestID, Message.Status == FAIMessage::Success); } else { UE_VLOG(OwnerComp->GetOwner(), LogBehaviorTree, Warning, TEXT("UBTTaskNode::ReceivedMessage called while %s node no longer in active BT") , *GetNodeName()); } }
void UBTTask_GameplayTaskBase::OnGameplayTaskDeactivated(UGameplayTask& Task) { UAITask* AITask = Cast<UAITask>(&Task); if (AITask && AITask->GetAIController() && AITask->GetState() != EGameplayTaskState::Paused) { UBehaviorTreeComponent* BehaviorComp = GetBTComponentForTask(Task); if (BehaviorComp) { uint8* RawMemory = BehaviorComp->GetNodeMemory(this, BehaviorComp->FindInstanceContainingNode(this)); FBTGameplayTaskMemory* MyMemory = reinterpret_cast<FBTGameplayTaskMemory*>(RawMemory); if (MyMemory->bObserverCanFinishTask && (AITask == MyMemory->Task)) { const EBTNodeResult::Type FinishResult = DetermineGameplayTaskResult(*AITask); FinishLatentTask(*BehaviorComp, FinishResult); } } } }