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;
}
Exemplo n.º 2
0
EBTNodeResult::Type UBTTask_FlyTo::SchedulePathfindingRequest(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	if(!NavigationManager)
		NavigationManager =  UDonNavigationHelper::DonNavigationManager(this);

	auto pawn        =  OwnerComp.GetAIOwner()->GetPawn();
	auto myMemory    =  (FBT_FlyToTarget*)NodeMemory;
	auto blackboard  =  pawn ? pawn->GetController()->FindComponentByClass<UBlackboardComponent>() : NULL;
	
	// Validate internal state:
	if (!pawn || !myMemory || !blackboard || !NavigationManager)
	{
		UE_LOG(LogTemp, Log, TEXT("[DoN Navigation] BTTask_FlyTo has invalid data for AI Pawn or NodeMemory or NavigationManager. Unable to proceed."));

		if(blackboard)
			HandleTaskFailure(blackboard);

		return EBTNodeResult::Failed;
	}
	
	// Validate blackboard key data:
	if(FlightLocationKey.SelectedKeyType != UBlackboardKeyType_Vector::StaticClass())
	{
		UE_LOG(LogTemp, Log, TEXT("[DoN Navigation] Invalid FlightLocationKey. Expected Vector type, found %s"), *(FlightLocationKey.SelectedKeyType ? FlightLocationKey.SelectedKeyType->GetName() : FString("?")));
		HandleTaskFailure(blackboard);

		return EBTNodeResult::Failed;
	}	

	// Prepare input:
	myMemory->Reset();	
	myMemory->Metadata.ActiveInstanceIdx = OwnerComp.GetActiveInstanceIdx();
	myMemory->Metadata.OwnerComp = &OwnerComp;
	myMemory->QueryParams = QueryParams;
	myMemory->QueryParams.CustomDelegatePayload = &myMemory->Metadata;
	myMemory->bIsANavigator = pawn->GetClass()->ImplementsInterface(UDonNavigator::StaticClass());

	FVector flightDestination = blackboard->GetValueAsVector(FlightLocationKey.SelectedKeyName);

	// Bind result notification delegate:
	FDoNNavigationResultHandler resultHandler;
	resultHandler.BindDynamic(this, &UBTTask_FlyTo::Pathfinding_OnFinish);

	// Bind dynamic collision updates delegate:		
	myMemory->DynamicCollisionListener.BindDynamic(this, &UBTTask_FlyTo::Pathfinding_OnDynamicCollisionAlert);

	// Schedule task:	
	bool bTaskScheduled = NavigationManager->SchedulePathfindingTask(pawn, flightDestination, myMemory->QueryParams, DebugParams, resultHandler, myMemory->DynamicCollisionListener);

	if (bTaskScheduled)
	{
		if(myMemory->QueryResults.QueryStatus != EDonNavigationQueryStatus::Success) // for simple paths the scheduler may have already solved the path synchronously
			myMemory->QueryResults.QueryStatus = EDonNavigationQueryStatus::InProgress;

		return EBTNodeResult::InProgress;
	}
	else
	{
		HandleTaskFailure(blackboard);

		return EBTNodeResult::Failed;
	}	
}