// Fill out your copyright notice in the Description page of Project Settings. #include "DialogueNPC.h" #include "Blueprint/UserWidget.h" #include "Components/TextBlock.h" #include "GameFramework/Character.h" #include "Kismet/KismetStringLibrary.h" #include "Misc/OutputDeviceNull.h" #include "the_twilight_abyss/PlayerTemp/TempCharacter.h" #include "the_twilight_abyss/Quest/QuestSystem.h" // Sets default values for this component's properties UDialogueNPC::UDialogueNPC() { // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features // off to improve performance if you don't need them. PrimaryComponentTick.bCanEverTick = true; static ConstructorHelpers::FClassFinder DialogueWidgetClass(TEXT("/Game/Dialogue/TextPrompt")); DialogueWidget = DialogueWidgetClass.Class; } // Called when the game starts void UDialogueNPC::BeginPlay() { Super::BeginPlay(); DialogueWidgetInstance = CreateWidget(GetWorld(), DialogueWidget); NPCNameText = Cast(DialogueWidgetInstance->GetWidgetFromName("Text_Name")); DialogueText = Cast(DialogueWidgetInstance->GetWidgetFromName("Text_Dialogue")); NextButton = Cast(DialogueWidgetInstance->GetWidgetFromName("Button_Next")); NextButton->OnClicked.AddDynamic(this, &UDialogueNPC::NextDialogue); NPCPortraitImage = Cast(DialogueWidgetInstance->GetWidgetFromName("Image_Portrait")); if (IsValid(NPCPortrait)) NPCPortraitImage->SetBrushFromTexture(NPCPortrait); Choice1Button = Cast(DialogueWidgetInstance->GetWidgetFromName("Button_Choice1")); Choice1Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice1); Choice2Button = Cast(DialogueWidgetInstance->GetWidgetFromName("Button_Choice2")); Choice2Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice2); Choice3Button = Cast(DialogueWidgetInstance->GetWidgetFromName("Button_Choice3")); Choice3Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice3); Choice1Text = Cast(DialogueWidgetInstance->GetWidgetFromName("Text_Choice1")); Choice2Text = Cast(DialogueWidgetInstance->GetWidgetFromName("Text_Choice2")); Choice3Text = Cast(DialogueWidgetInstance->GetWidgetFromName("Text_Choice3")); NextArrow = Cast(DialogueWidgetInstance->GetWidgetFromName("NextArrow")); } void UDialogueNPC::NextDialogue() { if (Choice1Button->GetVisibility() == ESlateVisibility::Visible) return; //Dialogue Skip if (CurrentDialogue.Len() < CurrentDialogueStringPath[DialogueIndex].Len()) { CurrentDialogue = CurrentDialogueStringPath[DialogueIndex]; DialogueText->SetText(FText::FromString(CurrentDialogue)); NextArrow->SetVisibility(ESlateVisibility::SelfHitTestInvisible); return; } if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "##") { Cast(GetWorld()->GetFirstPlayerController()->GetPawn()->GetComponentByClass(UQuestSystem::StaticClass()))->AddQuest(Quests[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))]); DialogueIndex++; } else if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "@@") { FOutputDeviceNull AR; const FString Command = BlueprintFunctions[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))];; GetOwner()->CallFunctionByNameWithArguments(*Command, AR, nullptr, true); if (Command == "OpenShop") bInShop = true; DialogueIndex++; } else if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "$$") { Cast(GetWorld()->GetFirstPlayerController()->GetPawn()->GetComponentByClass(UInventoryComponent::StaticClass()))->AddItem(ItemsToGive[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))]); DialogueIndex++; } else if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "%%") { Cast(GetWorld()->GetFirstPlayerController()->GetPawn()->GetComponentByClass(UQuestSystem::StaticClass()))->AddQuestFlag(QuestFlags[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))], true); DialogueIndex++; } DialogueIndex++; NextArrow->SetVisibility(ESlateVisibility::Hidden); if (DialogueIndex >= CurrentDialogueStringPath.Num()) { if (CurrentDialoguePath->Choices.IsEmpty()) { EndDialogue(); return; } GetWorld()->GetTimerManager().PauseTimer(TextAnimationTimerHandle); DialogueText->SetText(FText::FromString("")); Choice1Button->SetVisibility(ESlateVisibility::Visible); if (Choice2Text->GetText().ToString() != "") Choice2Button->SetVisibility(ESlateVisibility::Visible); if (Choice3Text->GetText().ToString() != "") Choice3Button->SetVisibility(ESlateVisibility::Visible); NextArrow->SetVisibility(ESlateVisibility::Hidden); return; } CurrentDialogue = ""; } void UDialogueNPC::NextCharacter() { if (DialogueIndex >= CurrentDialogueStringPath.Num()) return; if (CurrentDialogue.Len() < CurrentDialogueStringPath[DialogueIndex].Len()) { CurrentDialogue.AppendChar(CurrentDialogueStringPath[DialogueIndex][CurrentDialogue.Len()]); DialogueText->SetText(FText::FromString(CurrentDialogue)); } else NextArrow->SetVisibility(ESlateVisibility::SelfHitTestInvisible); } void UDialogueNPC::ResetDialogueUI() { DialogueIndex = 0; CurrentDialogue = ""; CurrentDialogueStringPath = CurrentDialoguePath->Dialogue; GetWorld()->GetTimerManager().UnPauseTimer(TextAnimationTimerHandle); Choice1Button->SetVisibility(ESlateVisibility::Hidden); Choice2Button->SetVisibility(ESlateVisibility::Hidden); Choice3Button->SetVisibility(ESlateVisibility::Hidden); NextArrow->SetVisibility(ESlateVisibility::Hidden); } // Called every frame void UDialogueNPC::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // ... } void UDialogueNPC::StartDialogue() { Quests.Empty(); bInShop = false; FOutputDeviceNull AR; const FString Command = FString::Printf(TEXT("SetRootDialoguePath")); GetOwner()->CallFunctionByNameWithArguments(*Command, AR, nullptr, true); if (IsValid(RootDialoguePath)) CurrentDialogueStringPath = RootDialoguePath->Dialogue; if (CurrentDialogueStringPath.IsEmpty()) { UE_LOG(LogTemp, Warning, TEXT("Dialogue Path is Empty")); return; } //Disable Character Movement if (ACharacter* PlayerCharacter = Cast(GetWorld()->GetFirstPlayerController()->GetPawn())) { PlayerCharacter->DisableInput(GetWorld()->GetFirstPlayerController()); } //Set to UI Mode Only APlayerController* PlayerController = GetWorld()->GetFirstPlayerController(); PlayerController->SetInputMode(FInputModeUIOnly()); PlayerController->bShowMouseCursor = true; Choice1Button->SetVisibility(ESlateVisibility::Hidden); Choice2Button->SetVisibility(ESlateVisibility::Hidden); Choice3Button->SetVisibility(ESlateVisibility::Hidden); NextArrow->SetVisibility(ESlateVisibility::Hidden); DialogueText->SetText(FText::FromString("")); DialogueWidgetInstance->AddToViewport(); NPCNameText->SetText(FText::FromString(NPCName)); DialogueIndex = 0; CurrentDialogue = ""; CurrentDialoguePath = RootDialoguePath; CurrentDialogueStringPath = RootDialoguePath->Dialogue; GetWorld()->GetTimerManager().SetTimer(TextAnimationTimerHandle, this, &UDialogueNPC::NextCharacter, TextAnimationSpeed, true); } void UDialogueNPC::EndDialogue() { TextAnimationTimerHandle.Invalidate(); DialogueWidgetInstance->RemoveFromParent(); if (!bInShop) { //Enable Character Movement if (ACharacter* PlayerCharacter = Cast(GetWorld()->GetFirstPlayerController()->GetPawn())) { PlayerCharacter->EnableInput(GetWorld()->GetFirstPlayerController()); } //Reset UI Mode APlayerController* PlayerController = GetWorld()->GetFirstPlayerController(); PlayerController->SetInputMode(FInputModeGameOnly()); PlayerController->bShowMouseCursor = false; } } UDialoguePath* UDialogueNPC::CreateRootDialoguePath() { return NewObject(); } UDialoguePath* UDialogueNPC::AddDialogue(UDialoguePath* DialoguePath, FText TextInput) { if (TextInput.IsEmpty()) return DialoguePath; DialoguePath->Dialogue.Add(TextInput.ToString()); return DialoguePath; } void UDialogueNPC::AddChoices(UDialoguePath* ParentPath, FText ChoiceText1, FText ChoiceText2, FText ChoiceText3, UDialoguePath*& Out_ChoicePath1, UDialoguePath*& Out_ChoicePath2, UDialoguePath*& Out_ChoicePath3) { ParentPath->Choices.Add(NewObject()); ParentPath->Choices.Add(NewObject()); ParentPath->Choices.Add(NewObject()); Out_ChoicePath1 = ParentPath->Choices[0]; Out_ChoicePath2 = ParentPath->Choices[1]; Out_ChoicePath3 = ParentPath->Choices[2]; Choice1Text->SetText(ChoiceText1); Choice2Text->SetText(ChoiceText2); Choice3Text->SetText(ChoiceText3); } UDialoguePath* UDialogueNPC::AddQuest(UDialoguePath* DialoguePath, UQuest* Quest) { DialoguePath->Dialogue.Add(FText::FromString("## " + Quests.Num()).ToString()); Quests.Add(Quests.Num(), Quest); return DialoguePath; } UDialoguePath* UDialogueNPC::CallBlueprintFunction(UDialoguePath* DialoguePath, const FString FunctionName) { DialoguePath->Dialogue.Add(FText::FromString("@@ " + FString::FromInt(BlueprintFunctions.Num())).ToString()); BlueprintFunctions.Add(BlueprintFunctions.Num(), FunctionName); return DialoguePath; } UDialoguePath* UDialogueNPC::AddItem(UDialoguePath* DialoguePath, const int ItemIndex) { DialoguePath->Dialogue.Add(FText::FromString("$$ " + FString::FromInt(ItemIndexes.Num())).ToString()); ItemIndexes.Add(ItemIndexes.Num(), ItemIndex); return DialoguePath; } UDialoguePath* UDialogueNPC::AddQuestFlag(UDialoguePath* DialoguePath, FString Flag) { DialoguePath->Dialogue.Add(FText::FromString("%% " + FString::FromInt(QuestFlags.Num())).ToString()); QuestFlags.Add(QuestFlags.Num(), Flag); return DialoguePath; } void UDialogueNPC::Choice1() { CurrentDialoguePath = CurrentDialoguePath->Choices[0]; ResetDialogueUI(); } void UDialogueNPC::Choice2() { CurrentDialoguePath = CurrentDialoguePath->Choices[1]; ResetDialogueUI(); } void UDialogueNPC::Choice3() { CurrentDialoguePath = CurrentDialoguePath->Choices[2]; ResetDialogueUI(); }