bool UBTTask_BlueprintBase::IsTaskExecuting() const
{
	UBehaviorTreeComponent* OwnerComp = Cast<UBehaviorTreeComponent>(GetOuter());
	EBTTaskStatus::Type TaskStatus = OwnerComp->GetTaskStatus(this);

	return (TaskStatus == EBTTaskStatus::Active);
}
//----------------------------------------------------------------------//
// UBTTaskNode IGameplayTaskOwnerInterface
//----------------------------------------------------------------------//
void UBTTaskNode::OnTaskDeactivated(UGameplayTask& Task)
{
	ensure(Task.GetTaskOwner() == this);
	UBehaviorTreeComponent* BTComp = GetBTComponentForTask(Task);
	if (BTComp)
	{
		// this is a super-default behavior. Specific task will surely like to 
		// handle this themselves, finishing with specific result
		const EBTTaskStatus::Type Status = BTComp->GetTaskStatus(this);
		FinishLatentTask(*BTComp, Status == EBTTaskStatus::Aborting ? EBTNodeResult::Aborted : EBTNodeResult::Succeeded);
	}
}
void UBTTaskNode::OnMessage(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, FName Message, int32 RequestID, bool bSuccess)
{
	const EBTTaskStatus::Type Status = OwnerComp.GetTaskStatus(this);
	if (Status == EBTTaskStatus::Active)
	{
		FinishLatentTask(OwnerComp, bSuccess ? EBTNodeResult::Succeeded : EBTNodeResult::Failed);
	}
	else if (Status == EBTTaskStatus::Aborting)
	{
		FinishLatentAbort(OwnerComp);
	}
}
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);
		}
	}
}