void UBTService_BlueprintBase::OnCeaseRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	Super::OnCeaseRelevant(OwnerComp, NodeMemory);

	if (!OwnerComp.HasAnyFlags(RF_BeginDestroyed) && OwnerComp.GetOwner())
	{
		// force dropping all pending latent actions associated with this blueprint
		// we can't have those resuming activity when node is/was aborted
		BlueprintNodeHelpers::AbortLatentActions(OwnerComp, *this);

		if (AIOwner != nullptr && ReceiveActivationImplementations & FBTNodeBPImplementationHelper::AISpecific)
		{
			ReceiveDeactivationAI(AIOwner, AIOwner->GetPawn());
		}
		else if (ReceiveActivationImplementations & FBTNodeBPImplementationHelper::Generic)
		{
			ReceiveDeactivation(ActorOwner);
		}
	}
	else
	{
		UE_LOG(LogBehaviorTree, Warning,
			TEXT("OnCeaseRelevant called on Blueprint service %s with invalid owner.  OwnerComponent: %s, OwnerComponent Owner: %s.  %s")
			, *GetNameSafe(this), *OwnerComp.GetName(), *GetNameSafe(OwnerComp.GetOwner())
			, OwnerComp.HasAnyFlags(RF_BeginDestroyed) ? TEXT("OwnerComponent has BeginDestroyed flag") : TEXT("")
		);
	}
}
FString FBehaviorTreeDebugger::DescribeInstance(UBehaviorTreeComponent& InstanceToDescribe) const
{
	FString ActorDesc;
	if (InstanceToDescribe.GetOwner())
	{
		AController* TestController = Cast<AController>(InstanceToDescribe.GetOwner());
		ActorDesc = TestController ?
			TestController->GetName() :
			InstanceToDescribe.GetOwner()->GetActorLabel();
	}

	return ActorDesc;
}
Exemple #3
0
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const
{
    if (bCreateNodeInstance)
    {
        // composite nodes can't be instanced!
        check(IsA(UBTCompositeNode::StaticClass()) == false);

        UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL;
        if (NodeInstance == NULL)
        {
            NodeInstance = NewObject<UBTNode>(&OwnerComp, GetClass(), GetFName(), RF_NoFlags, (UObject*)(this));
            NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth());
            NodeInstance->bIsInstanced = true;

            OwnerComp.NodeInstances.Add(NodeInstance);
        }
        check(NodeInstance);

        NodeInstance->SetOwner(OwnerComp.GetOwner());

        FBTInstancedNodeMemory* MyMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory);
        MyMemory->NodeIdx = NextInstancedIndex;

        NodeInstance->OnInstanceCreated(OwnerComp);
        NextInstancedIndex++;
    }
    else
    {
        InitializeMemory(OwnerComp, NodeMemory, InitType);
    }
}
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());
	}
}
EBTNodeResult::Type UBTTask_GameplayTaskBase::StartGameplayTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, UAITask& Task)
{
	FBTGameplayTaskMemory* MyMemory = reinterpret_cast<FBTGameplayTaskMemory*>(NodeMemory);
	MyMemory->bObserverCanFinishTask = false;
	MyMemory->Task = &Task;

#if ENABLE_VISUAL_LOG
	const UObject* TaskOwnerOb = Cast<const UObject>(Task.GetTaskOwner());
	UE_VLOG(OwnerComp.GetOwner(), LogBehaviorTree, Log, TEXT("%s is ready to execute gameplay task: %s, finish %s"),
		*UBehaviorTreeTypes::DescribeNodeHelper(this), *Task.GetName(),
		!bWaitForGameplayTask ? TEXT("instantly") :
		((TaskOwnerOb == this) ? TEXT("with gameplay task") : *FString::Printf(TEXT("UNKNOWN (gameplay task owner: %s)"), *GetNameSafe(TaskOwnerOb))) );
#endif

	Task.ReadyForActivation();
	MyMemory->bObserverCanFinishTask = bWaitForGameplayTask;

	return (Task.GetState() != EGameplayTaskState::Finished) ? EBTNodeResult::InProgress : DetermineGameplayTaskResult(Task);
}
bool UBTDecorator_HasLoSTo::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
{
	const UBlackboardComponent* MyBlackboard = OwnerComp.GetBlackboardComponent();
	AAIController* MyController = OwnerComp.GetAIOwner();
	bool HasLOS = false;

	if (MyController && MyBlackboard)
	{
		auto MyID = MyBlackboard->GetKeyID(EnemyKey.SelectedKeyName);
		auto TargetKeyType = MyBlackboard->GetKeyType(MyID);

		FVector TargetLocation;
		bool bGotTarget = false;
		AActor* EnemyActor = NULL;
		if (TargetKeyType == UBlackboardKeyType_Object::StaticClass())
		{
			UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(MyID);
			EnemyActor = Cast<AActor>(KeyValue);
			if (EnemyActor)
			{
				TargetLocation = EnemyActor->GetActorLocation();
				bGotTarget = true;
			}
		}
		else if (TargetKeyType == UBlackboardKeyType_Vector::StaticClass())
		{
			TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(MyID);
			bGotTarget = true;
		}

		if (bGotTarget == true)
		{
			if (LOSTrace(OwnerComp.GetOwner(), EnemyActor, TargetLocation) == true)
			{
				HasLOS = true;
			}
		}
	}

	return HasLOS;
}
/* Fonction d'exécution de la tâche, cette tâche devra retourner Succeeded, Failed ou InProgress */
EBTNodeResult::Type UMurphysLawSeekTargetTask::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	EBTNodeResult::Type TaskResult = EBTNodeResult::Succeeded;
	AMurphysLawAIController* Controller = CastChecked<AMurphysLawAIController>(OwnerComp.GetOwner());

	// Retreive needed references
	AActor* Target = Controller->GetBlackboardTarget();
	AMurphysLawCharacter* Self = Controller->GetBlackboardSelfActor();
	
	if(Target != nullptr && Self != nullptr)
	{
		const FVector PredictedDestination = PredictTargetDestination(Target, Self);
		Controller->SetBlackboardDestination(PredictedDestination);
	}
	else
	{
		TaskResult = EBTNodeResult::Failed;
	}

	return TaskResult;
}
void UBTS_DistanceToTarget::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);

	AAIControllerPSI* EnemyController = Cast<AAIControllerPSI>(OwnerComp.GetOwner());

	if (EnemyController)
	{
		APawn* Enemy;
		APawn* Player;
		Enemy = EnemyController->GetAIOwner();
		if (!Enemy)
		{
			return;
		}
		
		Player = EnemyController->GetSensedTarget();
		
		if (!Player)
		{
			return;
		}

		float Distance = Enemy->GetDistanceTo(Player);
		EnemyController->SetDistanceToPlayer(Distance);

		if (Distance >= 3500)
		{
			AAICharacter* EnemyBot = Cast<AAICharacter>(Enemy);
			EnemyBot->LostPlayer();
		}
		

	}
	else
	{
		return;
	}

}
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const
{
	FBTInstancedNodeMemory* SpecialMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory);
	if (SpecialMemory)
	{
		SpecialMemory->NodeIdx = INDEX_NONE;
	}

	if (bCreateNodeInstance)
	{
		// composite nodes can't be instanced!
		check(IsA(UBTCompositeNode::StaticClass()) == false);

		UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL;
		if (NodeInstance == NULL)
		{
			NodeInstance = (UBTNode*)StaticDuplicateObject(this, &OwnerComp);
			NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth());
			NodeInstance->bIsInstanced = true;

			OwnerComp.NodeInstances.Add(NodeInstance);
		}

		check(NodeInstance);
		check(SpecialMemory);

		SpecialMemory->NodeIdx = NextInstancedIndex;

		NodeInstance->SetOwner(OwnerComp.GetOwner());
		NodeInstance->InitializeMemory(OwnerComp, NodeMemory, InitType);
		check(TreeAsset);
		NodeInstance->InitializeFromAsset(*TreeAsset);
		NodeInstance->OnInstanceCreated(OwnerComp);
		NextInstancedIndex++;
	}
	else
	{
		InitializeMemory(OwnerComp, NodeMemory, InitType);
	}
}
void UBTService_SearchPlayer::TickNode(UBehaviorTreeComponent &OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	if (!OwnerComp.GetBlackboardComponent())
	{
		GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Red, "Failed to get Blackboard Component");
		return;
	}

	OwnerComp.GetBlackboardComponent()->SetValueAsObject("Player", (UGameplayStatics::GetPlayerCharacter(GetWorld(), 0)));

	if (OwnerComp.GetBlackboardComponent()->GetValueAsEnum("State") == static_cast<uint8>(EState::ES_Combat))
	{
		APawn* Player = (UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
		ALivingEntity* Enemy = nullptr;
		
		AEnemyController* EnemyController = Cast<AEnemyController>(OwnerComp.GetOwner());
		if (EnemyController)
		{
			Enemy = Cast<ALivingEntity>(EnemyController->GetPawn());
		}

		if (Player && Enemy)
		{
			if (!CanSeePlayer(Enemy, Player))
			{
				OwnerComp.GetBlackboardComponent()->SetValueAsEnum("State", static_cast<uint8>(EState::ES_Walking));
			}
			else
			{
				EnemyController->UpdateMemoryMarker(Player->GetActorLocation());
			}
		}
		else
		{
			GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Red, "Error whilst casting");
		}
	}
}
bool URandomWander::TraceFromPosition(FHitResult& OutResult, const float TraceDistance, ECollisionChannel const CollisionChannel, FVector CastFrom, UBehaviorTreeComponent& OwnerComp)
{
	FVector RandomPointLocation = CastFrom;

	//GetPlayerViewPoint is used to give the origin and direction
	//of the trace from the player

	FVector const StartTrace = RandomPointLocation;
	FVector const TraceDirection = RandomPointLocation.UpVector * -1;
	FVector const EndTrace = StartTrace + TraceDirection*TraceDistance;

	//Struct that defines parameters into collision function
	FCollisionQueryParams TraceParams(FName(TEXT("TraceFromPosition")), true, OwnerComp.GetOwner());

	bool bHitReturned = false;
	UWorld* const World = GetWorld();

	if (World)
	{
		bHitReturned = World->LineTraceSingleByChannel(OutResult, StartTrace, EndTrace, CollisionChannel, TraceParams);
	}
	return bHitReturned;
}
EBTNodeResult::Type UBTTask_WaitAnswer::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	ClearAnswer();
	EBTNodeResult::Type NodeResult = !bAnswerDone ? EBTNodeResult::InProgress : NodeResult = EBTNodeResult::Succeeded;
	TimerCount = Timer;
	AActor* OwnerActor = OwnerComp.GetOwner();

	if (!DialogueWidget.IsNone())
	{
		FName WidgetKeyName = DialogueWidget.SelectedKeyName;
		BlackboardComp = OwnerComp.GetBlackboardComponent();
		Widget = Cast<UUserWidget>(BlackboardComp->GetValueAsObject(WidgetKeyName));
		WidgetComp = Cast<UWidgetComponent>(BlackboardComp->GetValueAsObject(WidgetKeyName));
		UDialogueButton* FirstButton = nullptr;

		if (!Widget && !WidgetComp)
		{
#if WITH_EDITOR
			FMessageLog("PIE").Error()
				->AddToken(FTextToken::Create(LOCTEXT("InvalidWidgetKey", "Invalid key for Dialogue Widget in ")))
				->AddToken(FUObjectToken::Create((UObject*)OwnerComp.GetCurrentTree()));
#endif
			return EBTNodeResult::Failed;
		}

		if (WidgetComp)
		{
			Widget = CreateWidget<UUserWidget>(GetWorld(), WidgetComp->GetWidgetClass());
			PlayerController = WidgetComp->GetUserWidgetObject()->GetOwningPlayer();
			bIsUserWidget = false;
		}
		else
		{
			bIsUserWidget = true;
			PlayerController = Widget->GetOwningPlayer();
		}

		if (Widget && Widget->IsInViewport())
		{
			Widget->RemoveFromParent();
		}
		if (!Widget)
		{
			NodeResult = EBTNodeResult::Failed;
		}
		else
		{
			WidgetTree = Widget->WidgetTree;
			UWidget* DialogueQuestionsSlot = WidgetTree->FindWidget(DialogueQuestionsSlotName);
			UPanelWidget* Panel = Cast<UPanelWidget>(DialogueQuestionsSlot);
			if (Panel)
			{
				TArray<UWidget*> Buttons;
				UDialogueButton* SampleButton = nullptr;
				UTextBlock* SampleTextBlock = nullptr;
				WidgetTree->GetChildWidgets(DialogueQuestionsSlot, Buttons);
				for (auto& elem : Buttons)
				{
					UDialogueButton* Button = Cast<UDialogueButton>(elem);
					if (Button)
					{
						SampleButton = Button;
						WidgetTree->RemoveWidget(elem);
					}
					UTextBlock* TextBlock = Cast<UTextBlock>(elem);
					if (TextBlock)
					{
						SampleTextBlock = TextBlock;
						WidgetTree->RemoveWidget(elem);
					}
				}
				if (SampleButton != nullptr && SampleTextBlock != nullptr)
				{
					const UBTNode* BTNode = GetParentNode();
					const UBTCompositeNode* CBTNode = Cast<UBTCompositeNode>(BTNode);
					Panel->SetVisibility(ESlateVisibility::Visible);
					if (CBTNode)
					{
						int32 ButtonNumber = 0;
						for (int32 Index = 0; Index != CBTNode->Children.Num(); ++Index)
						{
							auto& Child = CBTNode->Children[Index];
							UBTComposite_Question* Question = Cast<UBTComposite_Question>(Child.ChildComposite);
							bool bDecoratorOk = CBTNode->DoDecoratorsAllowExecution(OwnerComp, OwnerComp.GetActiveInstanceIdx(), Index);

							if(Question)
							{
								Question->bCanExecute = false;
								Question->bSelected = false;
							}
							if (
									Question
									&& Question->Children.Num() > 0
									&& Question->GetVisibility(PlayerController)
									&& Question->bVisible
									&& bDecoratorOk
								)
							{
								Question->bCanExecute = true;
								UDialogueButton *NewSampleButton = NewObject<UDialogueButton>(this, NAME_None, SampleButton->GetFlags(), SampleButton);
								UTextBlock *NewSampleTextBlock = NewObject<UTextBlock>(this, NAME_None, SampleTextBlock->GetFlags(), SampleTextBlock);

								ButtonNumber++;
								if (bUseGamepad)
								{
									NewSampleButton->IsFocusable = true;
									if (ButtonNumber == 1)
									{
										FirstButton = NewSampleButton;
									}
								}
								else
								{
									NewSampleButton->IsFocusable = false;
								}

								NewSampleTextBlock->SetText(FText::Format(NSLOCTEXT("DialogueSystem", "ButtonText", "{0}"), Question->QuestionThumbnail));
								UWidget* Oldtext = NewSampleButton->GetChildAt(0);
								NewSampleButton->WaitTask = this;
								NewSampleButton->RemoveChild(Oldtext);
								NewSampleButton->AddChild(NewSampleTextBlock);
								Panel->AddChild(NewSampleButton);
							}
						}
					}
				}
				// Event Listener
				UWidget* DialogueEventListener = WidgetTree->FindWidget(FName("DialogueEventListener"));
				if (DialogueEventListener != nullptr)
				{
					UDialogueEventListener* EventListener = Cast<UDialogueEventListener>(DialogueEventListener);
					if (EventListener)
					{
						EventListener->WaitAnswerNode = this;
					}
				}
			}
			if (bIsUserWidget)
			{
				Widget->AddToViewport();
			}
			else
			{
				WidgetComp->SetWidget(Widget);
				WidgetComp->SetVisibility(true);
			}
			PlayerController->bShowMouseCursor = !bUseGamepad;
			FInputModeUIOnly InputModeUIOnly;
			FInputModeGameAndUI InputModeGameAndUI;

			if (InputMode == EWidggetInputMode::UIOnly)
			{
				PlayerController->SetInputMode(InputModeUIOnly);
			}
			else
			{
				PlayerController->SetInputMode(InputModeGameAndUI);
			}
			if (bUseGamepad && Panel)
			{
				FirstButton->SetKeyboardFocus();
			}
			else
			{
				if (InputMode == EWidggetInputMode::UIOnly)
				{
					InputModeUIOnly.SetWidgetToFocus(Widget->TakeWidget());
				}
				else
				{
					InputModeGameAndUI.SetWidgetToFocus(Widget->TakeWidget());
				}
			}

		}

		// cinematic
		if (DialogueCinematicOptions.bPlayMatinee && !DialogueCinematicOptions.Matinee.Equals("None"))
		{
			for (TActorIterator<AMatineeActor> It(OwnerActor->GetWorld()); It; ++It)
			{
				MatineeActor = *It;
				if (MatineeActor && MatineeActor->GetName().Equals(DialogueCinematicOptions.Matinee))
				{
					MatineeActor->bLooping = DialogueCinematicOptions.bLoop;
					MatineeActor->Play();
					break;
				}
			}
		}

		// camera
		if (DialogueCameraOptions.bUseCamera)
		{
			if (!DialogueCameraOptions.CameraToView.IsNone() && !DialogueCameraOptions.PlayerCamera.IsNone())
			{
				FName CameraToViewKeyName = DialogueCameraOptions.CameraToView.SelectedKeyName;
				BlackboardComp = OwnerComp.GetBlackboardComponent();
				UCameraComponent* CameraToView = Cast<UCameraComponent>(BlackboardComp->GetValueAsObject(CameraToViewKeyName));

				FName PlayerCameraKeyName = DialogueCameraOptions.PlayerCamera.SelectedKeyName;
				PlayerCamera = Cast<UCameraComponent>(BlackboardComp->GetValueAsObject(PlayerCameraKeyName));

				if (PlayerCamera && CameraToView)
				{
					SaveDefaultCameraData(PlayerCamera);
					if (PlayerCamera == CameraToView)
					{
						PlayerCamera->SetWorldLocationAndRotation(DefaultCameraLocation, DefaultCameraRotation);
					}
					else
					{
						PlayerCamera->SetWorldLocationAndRotation(CameraToView->GetComponentLocation(), CameraToView->GetComponentRotation());
					}
				}
			}
		}
	}

	return NodeResult;
}
bool UPlayerVisibleDecorator::CalculateRawConditionValue(UBehaviorTreeComponent& comp, uint8* memory) const
{
	AEnemyController* c = ((AEnemyController*)comp.GetOwner());
	return c ? c->canSeePlayer() : false;
}
EBTNodeResult::Type UBTTask_ShowPhrases::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{	
	EBTNodeResult::Type NodeResult = ShowingNumPhrase <= PhrasesCount ? EBTNodeResult::InProgress : NodeResult = EBTNodeResult::Succeeded;
	// reset timer handle
	TimerHandle.Invalidate();
	//AudioComponent = NULL;
	
	if (!DialogueWidget.IsNone())
	{
		FName WidgetKeyName = DialogueWidget.SelectedKeyName;
		BlackboardComp = OwnerComp.GetBlackboardComponent();
		Widget = Cast<UUserWidget>(BlackboardComp->GetValueAsObject(WidgetKeyName));
		WidgetComp = Cast<UWidgetComponent>(BlackboardComp->GetValueAsObject(WidgetKeyName));
		OwnerActor = OwnerComp.GetOwner();

		if (!Widget && !WidgetComp)
		{
#if WITH_EDITOR
			FMessageLog("PIE").Error()
				->AddToken(FTextToken::Create(LOCTEXT("InvalidWidgetKey", "Invalid key for Dialogue Widget in ")))
				->AddToken(FUObjectToken::Create((UObject*)OwnerComp.GetCurrentTree()));
#endif
			return EBTNodeResult::Failed;
		}

		if (WidgetComp)
		{
			Widget = CreateWidget<UUserWidget>(GetWorld(), WidgetComp->GetWidgetClass());
			bIsUserWidget = false;
		}
		else
		{
			bIsUserWidget = true;
		}

		if (Widget && Widget->IsInViewport())
		{
			Widget->RemoveFromParent();
		}

		if (Widget && !Widget->IsInViewport())
		{
			UWidgetTree* WidgetTree = Widget->WidgetTree;
			UWidget* DialogueQuestionsSlot = WidgetTree->FindWidget(DialogueTextOptions.DialogueQuestionsSlotName);
			if (DialogueQuestionsSlot != nullptr)
			{
				DialogueQuestionsSlot->SetVisibility(ESlateVisibility::Hidden);
			}

			// text
			DialoguePhraseSlot = WidgetTree->FindWidget(DialogueTextOptions.DialoguePhraseSlotName);
			if (DialoguePhraseSlot != nullptr)
			{
				DialoguePhraseSlot->SetVisibility(ESlateVisibility::Visible);
				UTextBlock* StartPhraseTextBlock = Cast<UTextBlock>(DialoguePhraseSlot);
				if (StartPhraseTextBlock)
				{
					if (DialogueTextOptions.bShowTextPhrases)
					{
						PhrasesCount = DialogueTextOptions.Phrases.Num() - 1; // starts from 0
						if (ShowingNumPhrase > PhrasesCount)
						{
							ShowingNumPhrase = 0;
						}
						FText StartPhrase = DialogueTextOptions.Phrases.Num() > 0 ? DialogueTextOptions.Phrases[ShowingNumPhrase].Phrase : FText::GetEmpty();
						if (DialogueTextOptions.TextEffect == ETextEffect::NoEffect || DialogueTextOptions.Delay == 0.0f)
						{
							StartPhraseTextBlock->SetText(FText::Format(NSLOCTEXT("DialogueSystem", "ShowPhraseText", "{0}"), StartPhrase));
							float ShowingTime = DialogueTextOptions.UseGeneralTime ? DialogueTextOptions.GeneralShowingTime : DialogueTextOptions.Phrases[ShowingNumPhrase].ShowingTime;
							TimerDelegate = FTimerDelegate::CreateUObject(this, &UBTTask_ShowPhrases::ShowNewDialoguePhrase, false);
							OwnerActor->GetWorldTimerManager().SetTimer(TimerHandle, TimerDelegate, ShowingTime, false);
						}
						else
						{
							if (DialogueTextOptions.TextEffect == ETextEffect::Typewriter)
							{
								CurrentCharNum = 1; StringToDisplay = "";
								FullString = StartPhrase.ToString().GetCharArray();
								StringToDisplay.AppendChar(FullString[0]);
								if (StartPhraseTextBlock)
								{
									StartPhraseTextBlock->SetText(FText::Format(NSLOCTEXT("DialogueSystem", "ShowPhraseText", "{0}"), FText::FromString(StringToDisplay)));
								}
								TimerDelegate = FTimerDelegate::CreateUObject(this, &UBTTask_ShowPhrases::ShowNewChar);
								OwnerActor->GetWorldTimerManager().SetTimer(TimerHandle, TimerDelegate, DialogueTextOptions.Delay, false);
							}
						}
						// play phrase sound 
						if (DialogueTextOptions.Phrases[ShowingNumPhrase].SoundToPlay)
						{
							PhraseAudioComponent = UGameplayStatics::SpawnSound2D(GetWorld(), DialogueTextOptions.Phrases[ShowingNumPhrase].SoundToPlay);
						}
					}
					else
					{
						DialoguePhraseSlot->SetVisibility(ESlateVisibility::Hidden);
						bTextFinished = true;
					}
				}
			}
			// name
			DialogueNameSlot = WidgetTree->FindWidget(DialogueNameOptions.DialogueSpeakerNameSlotName);
			if (DialogueNameSlot != nullptr)
			{
				if (DialogueNameOptions.bShowName)
				{
					DialogueNameSlot->SetVisibility(ESlateVisibility::Visible);
					UTextBlock* NameTextBlock = Cast<UTextBlock>(DialogueNameSlot);
					if (NameTextBlock)
					{
						NameTextBlock->SetText(DialogueNameOptions.Name);
					}
				}
				else
				{
					DialogueNameSlot->SetVisibility(ESlateVisibility::Hidden);
				}
			}
			// image
			DialogueImageSlot = WidgetTree->FindWidget(DialogueImageOptions.DialogueSpeakerImageSlotName);
			if (DialogueImageSlot != nullptr)
			{
				if (DialogueImageOptions.bShowImage)
				{
					DialogueImageSlot->SetVisibility(ESlateVisibility::Visible);
					UImage* DialogueImage = Cast<UImage>(DialogueImageSlot);
					if (DialogueImage)
					{
						DialogueImage->SetBrushFromTexture(DialogueImageOptions.Image);
					}
				}
				else
				{
					DialogueImageSlot->SetVisibility(ESlateVisibility::Hidden);
				}
			}
			// general sound
			if (DialogueSoundOptions.bPlaySound)
			{
				if (DialogueSoundOptions.SoundToPlay)
				{
					GeneralAudioComponent = UGameplayStatics::SpawnSound2D(GetWorld(), DialogueSoundOptions.SoundToPlay);
				}
			}
			// camera
			if (DialogueCameraOptions.bUseCamera)
			{
				if (!DialogueCameraOptions.CameraToView.IsNone() && !DialogueCameraOptions.PlayerCamera.IsNone() && !DialogueCinematicOptions.bPlayMatinee)
				{
					FName CameraToViewKeyName = DialogueCameraOptions.CameraToView.SelectedKeyName;
					BlackboardComp = OwnerComp.GetBlackboardComponent();
					UCameraComponent* CameraToView = Cast<UCameraComponent>(BlackboardComp->GetValueAsObject(CameraToViewKeyName));

					FName PlayerCameraKeyName = DialogueCameraOptions.PlayerCamera.SelectedKeyName;
					PlayerCamera = Cast<UCameraComponent>(BlackboardComp->GetValueAsObject(PlayerCameraKeyName));

					if (PlayerCamera && CameraToView)
					{
						SaveDefaultCameraData(PlayerCamera);
						if (PlayerCamera == CameraToView)
						{
							PlayerCamera->SetWorldLocationAndRotation(DefaultCameraLocation, DefaultCameraRotation);
						}
						else
						{
							PlayerCamera->SetWorldLocationAndRotation(CameraToView->GetComponentLocation(), CameraToView->GetComponentRotation());
						}
					}
				}
				
			}
			// cinematic
			if (DialogueCinematicOptions.bPlayMatinee && !DialogueCinematicOptions.Matinee.Equals("None"))
			{
				for (TActorIterator<AMatineeActor> It(OwnerActor->GetWorld()); It; ++It)
				{
					MatineeActor = *It;
					if (MatineeActor && MatineeActor->GetName().Equals(DialogueCinematicOptions.Matinee))
					{
						MatineeActor->bLooping = DialogueCinematicOptions.bLoop;
						MatineeActor->Play();
						break;
					}
				}
			}

			// character animation
			if (DialogueCharacterAnimationOptions.bPlayAnimation && !DialogueCharacterAnimationOptions.Mesh.IsNone() && DialogueCharacterAnimationOptions.Animation != nullptr)
			{
				FName MeshKeyName = DialogueCharacterAnimationOptions.Mesh.SelectedKeyName;
				BlackboardComp = OwnerComp.GetBlackboardComponent();
				Mesh = Cast<USkeletalMeshComponent>(BlackboardComp->GetValueAsObject(MeshKeyName));
				if (Mesh)
				{
					UAnimInstance *AnimInst = Mesh->GetAnimInstance();
					if (AnimInst)
					{
						AnimInst->PlaySlotAnimationAsDynamicMontage(DialogueCharacterAnimationOptions.Animation, 
							DialogueCharacterAnimationOptions.AnimationBlendOptions.SlotNodeName,
							DialogueCharacterAnimationOptions.AnimationBlendOptions.BlendInTime,
							DialogueCharacterAnimationOptions.AnimationBlendOptions.BlendOutTime,
							DialogueCharacterAnimationOptions.AnimationBlendOptions.InPlayRate);
					}
					if (DialogueCharacterAnimationOptions.bWaitEndOfAnimation)
					{
						UAnimSequenceBase* SequenceBase = DialogueCharacterAnimationOptions.Animation;
						CharacterAnimationDuration = SequenceBase->SequenceLength / SequenceBase->RateScale;
					}
				}
				bCharacterAnimationStarted = true;
			}
			// Event Listener

			UWidget* DialogueEventListener = WidgetTree->FindWidget(FName("DialogueEventListener"));
			if (DialogueEventListener != nullptr)
			{
				UDialogueEventListener* EventListener = Cast<UDialogueEventListener>(DialogueEventListener);
				if (EventListener)
				{
					EventListener->ShowPhrasesNode = this;
				}
			}
	
			if (bIsUserWidget)
			{
				Widget->AddToViewport();
			}
			else
			{
				WidgetComp->SetWidget(Widget);
				WidgetComp->SetVisibility(true);
			}
			PlayerController = Widget->GetOwningPlayer();
			if (InputMode == EWidggetInputMode::UIOnly)
			{
				FInputModeUIOnly InputModeUIOnly;
				InputModeUIOnly.SetWidgetToFocus(Widget->TakeWidget());
				PlayerController->SetInputMode(InputModeUIOnly);
			}
			else
			{
				FInputModeGameAndUI InputModeGameAndUI;
				InputModeGameAndUI.SetWidgetToFocus(Widget->TakeWidget());
				PlayerController->SetInputMode(InputModeGameAndUI);
			}
		}
		else
		{
			bTextFinished = true;
			NodeResult = EBTNodeResult::Failed;
		}
	}
	
	return NodeResult;
}