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);
		}
	}
}
示例#3
0
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);
			}
		}
	}
}