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; }
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; } }