2023-02-02 01:59:33 +00:00
|
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "DialogueNPC.h"
|
|
|
|
|
#include "Blueprint/UserWidget.h"
|
|
|
|
|
#include "Components/TextBlock.h"
|
2023-02-02 02:39:35 +00:00
|
|
|
|
#include "GameFramework/Character.h"
|
2023-05-02 06:16:40 +00:00
|
|
|
|
#include "Kismet/KismetStringLibrary.h"
|
2023-05-04 05:31:59 +00:00
|
|
|
|
#include "Misc/OutputDeviceNull.h"
|
2023-05-11 07:52:30 +00:00
|
|
|
|
#include "the_twilight_abyss/PlayerTemp/TempCharacter.h"
|
2023-05-02 06:16:40 +00:00
|
|
|
|
#include "the_twilight_abyss/Quest/QuestSystem.h"
|
2023-02-02 01:59:33 +00:00
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
2023-03-14 01:33:06 +00:00
|
|
|
|
static ConstructorHelpers::FClassFinder<UUserWidget> DialogueWidgetClass(TEXT("/Game/Dialogue/TextPrompt"));
|
2023-02-02 01:59:33 +00:00
|
|
|
|
DialogueWidget = DialogueWidgetClass.Class;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Called when the game starts
|
|
|
|
|
void UDialogueNPC::BeginPlay()
|
|
|
|
|
{
|
|
|
|
|
Super::BeginPlay();
|
|
|
|
|
|
|
|
|
|
DialogueWidgetInstance = CreateWidget<UUserWidget>(GetWorld(), DialogueWidget);
|
|
|
|
|
|
|
|
|
|
NPCNameText = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("Text_Name"));
|
|
|
|
|
DialogueText = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("Text_Dialogue"));
|
|
|
|
|
NextButton = Cast<UButton>(DialogueWidgetInstance->GetWidgetFromName("Button_Next"));
|
|
|
|
|
NextButton->OnClicked.AddDynamic(this, &UDialogueNPC::NextDialogue);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
NPCPortraitImage = Cast<UImage>(DialogueWidgetInstance->GetWidgetFromName("Image_Portrait"));
|
|
|
|
|
if (IsValid(NPCPortrait)) NPCPortraitImage->SetBrushFromTexture(NPCPortrait);
|
|
|
|
|
|
|
|
|
|
Choice1Button = Cast<UButton>(DialogueWidgetInstance->GetWidgetFromName("Button_Choice1"));
|
|
|
|
|
Choice1Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice1);
|
|
|
|
|
Choice2Button = Cast<UButton>(DialogueWidgetInstance->GetWidgetFromName("Button_Choice2"));
|
|
|
|
|
Choice2Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice2);
|
|
|
|
|
Choice3Button = Cast<UButton>(DialogueWidgetInstance->GetWidgetFromName("Button_Choice3"));
|
|
|
|
|
Choice3Button->OnClicked.AddDynamic(this, &UDialogueNPC::Choice3);
|
|
|
|
|
Choice1Text = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("Text_Choice1"));
|
|
|
|
|
Choice2Text = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("Text_Choice2"));
|
|
|
|
|
Choice3Text = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("Text_Choice3"));
|
2023-05-01 04:23:43 +00:00
|
|
|
|
NextArrow = Cast<UTextBlock>(DialogueWidgetInstance->GetWidgetFromName("NextArrow"));
|
2023-02-02 01:59:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UDialogueNPC::NextDialogue()
|
|
|
|
|
{
|
2023-05-09 05:05:59 +00:00
|
|
|
|
if (Choice1Button->GetVisibility() == ESlateVisibility::Visible) return;
|
2023-02-02 01:59:33 +00:00
|
|
|
|
//Dialogue Skip
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (CurrentDialogue.Len() < CurrentDialogueStringPath[DialogueIndex].Len())
|
2023-02-02 01:59:33 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialogue = CurrentDialogueStringPath[DialogueIndex];
|
2023-02-02 01:59:33 +00:00
|
|
|
|
DialogueText->SetText(FText::FromString(CurrentDialogue));
|
2023-05-09 05:05:59 +00:00
|
|
|
|
NextArrow->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
2023-02-02 01:59:33 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2023-05-15 03:02:05 +00:00
|
|
|
|
if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "--")
|
2023-05-02 06:16:40 +00:00
|
|
|
|
{
|
2023-05-15 03:02:05 +00:00
|
|
|
|
UE_LOG(LogTemp, Warning, TEXT("DialogueIndex: %d"), UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3)));
|
2023-05-02 06:16:40 +00:00
|
|
|
|
Cast<UQuestSystem>(GetWorld()->GetFirstPlayerController()->GetPawn()->GetComponentByClass(UQuestSystem::StaticClass()))->AddQuest(Quests[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))]);
|
|
|
|
|
DialogueIndex++;
|
|
|
|
|
}
|
2023-05-11 05:32:11 +00:00
|
|
|
|
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);
|
2023-05-13 15:25:07 +00:00
|
|
|
|
if (Command == "OpenShop") bResetUserControls = false;
|
2023-05-11 07:52:30 +00:00
|
|
|
|
DialogueIndex++;
|
|
|
|
|
}
|
|
|
|
|
else if (CurrentDialogueStringPath[FMath::Clamp(DialogueIndex + 1, 0, CurrentDialogueStringPath.Num() - 1)].Mid(0, 2) == "$$")
|
|
|
|
|
{
|
|
|
|
|
Cast<UInventoryComponent>(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<UQuestSystem>(GetWorld()->GetFirstPlayerController()->GetPawn()->GetComponentByClass(UQuestSystem::StaticClass()))->AddQuestFlag(QuestFlags[UKismetStringLibrary::Conv_StringToInt(CurrentDialogueStringPath[DialogueIndex].RightChop(3))], true);
|
2023-05-11 05:32:11 +00:00
|
|
|
|
DialogueIndex++;
|
|
|
|
|
}
|
2023-02-02 01:59:33 +00:00
|
|
|
|
|
|
|
|
|
DialogueIndex++;
|
2023-05-09 05:05:59 +00:00
|
|
|
|
NextArrow->SetVisibility(ESlateVisibility::Hidden);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (DialogueIndex >= CurrentDialogueStringPath.Num())
|
2023-02-02 01:59:33 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (CurrentDialoguePath->Choices.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
EndDialogue();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
GetWorld()->GetTimerManager().PauseTimer(TextAnimationTimerHandle);
|
|
|
|
|
DialogueText->SetText(FText::FromString(""));
|
2023-05-14 22:02:09 +00:00
|
|
|
|
Choice1Text->SetText(CurrentDialoguePath->ChoiceText1);
|
|
|
|
|
Choice2Text->SetText(CurrentDialoguePath->ChoiceText2);
|
|
|
|
|
Choice3Text->SetText(CurrentDialoguePath->ChoiceText3);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
Choice1Button->SetVisibility(ESlateVisibility::Visible);
|
2023-05-12 12:08:00 +00:00
|
|
|
|
if (Choice2Text->GetText().ToString() != "") Choice2Button->SetVisibility(ESlateVisibility::Visible);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (Choice3Text->GetText().ToString() != "") Choice3Button->SetVisibility(ESlateVisibility::Visible);
|
2023-05-01 04:23:43 +00:00
|
|
|
|
NextArrow->SetVisibility(ESlateVisibility::Hidden);
|
2023-02-02 01:59:33 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
CurrentDialogue = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UDialogueNPC::NextCharacter()
|
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (DialogueIndex >= CurrentDialogueStringPath.Num()) return;
|
2023-02-02 02:39:35 +00:00
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (CurrentDialogue.Len() < CurrentDialogueStringPath[DialogueIndex].Len())
|
2023-02-02 01:59:33 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialogue.AppendChar(CurrentDialogueStringPath[DialogueIndex][CurrentDialogue.Len()]);
|
2023-02-02 01:59:33 +00:00
|
|
|
|
DialogueText->SetText(FText::FromString(CurrentDialogue));
|
|
|
|
|
}
|
2023-05-09 05:05:59 +00:00
|
|
|
|
else NextArrow->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
2023-02-02 01:59:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-04 00:42:54 +00:00
|
|
|
|
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);
|
2023-05-09 05:05:59 +00:00
|
|
|
|
NextArrow->SetVisibility(ESlateVisibility::Hidden);
|
2023-05-04 00:42:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-02 01:59:33 +00:00
|
|
|
|
// Called every frame
|
|
|
|
|
void UDialogueNPC::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
|
|
|
{
|
|
|
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UDialogueNPC::StartDialogue()
|
|
|
|
|
{
|
2023-05-19 01:20:15 +00:00
|
|
|
|
bIsInDialogue = true;
|
2023-05-04 05:59:05 +00:00
|
|
|
|
Quests.Empty();
|
2023-05-15 03:02:05 +00:00
|
|
|
|
BlueprintFunctions.Empty();
|
|
|
|
|
ItemIndexes.Empty();
|
|
|
|
|
QuestFlags.Empty();
|
2023-05-04 05:31:59 +00:00
|
|
|
|
FOutputDeviceNull AR;
|
|
|
|
|
const FString Command = FString::Printf(TEXT("SetRootDialoguePath"));
|
|
|
|
|
GetOwner()->CallFunctionByNameWithArguments(*Command, AR, nullptr, true);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (IsValid(RootDialoguePath)) CurrentDialogueStringPath = RootDialoguePath->Dialogue;
|
|
|
|
|
if (CurrentDialogueStringPath.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogTemp, Warning, TEXT("Dialogue Path is Empty"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-02-02 01:59:33 +00:00
|
|
|
|
//Set to UI Mode Only
|
|
|
|
|
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
|
2023-05-13 15:25:07 +00:00
|
|
|
|
PlayerController->SetIgnoreMoveInput(true);
|
|
|
|
|
PlayerController->SetIgnoreLookInput(true);
|
|
|
|
|
PlayerController->SetInputMode(FInputModeGameAndUI());
|
2023-02-02 01:59:33 +00:00
|
|
|
|
PlayerController->bShowMouseCursor = true;
|
2023-02-02 02:39:35 +00:00
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
Choice1Button->SetVisibility(ESlateVisibility::Hidden);
|
|
|
|
|
Choice2Button->SetVisibility(ESlateVisibility::Hidden);
|
|
|
|
|
Choice3Button->SetVisibility(ESlateVisibility::Hidden);
|
2023-05-09 05:05:59 +00:00
|
|
|
|
NextArrow->SetVisibility(ESlateVisibility::Hidden);
|
2023-03-13 04:49:09 +00:00
|
|
|
|
DialogueText->SetText(FText::FromString(""));
|
2023-02-02 01:59:33 +00:00
|
|
|
|
DialogueWidgetInstance->AddToViewport();
|
|
|
|
|
NPCNameText->SetText(FText::FromString(NPCName));
|
2023-03-13 04:49:09 +00:00
|
|
|
|
DialogueIndex = 0;
|
2023-02-02 01:59:33 +00:00
|
|
|
|
CurrentDialogue = "";
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialoguePath = RootDialoguePath;
|
|
|
|
|
CurrentDialogueStringPath = RootDialoguePath->Dialogue;
|
2023-02-06 01:13:17 +00:00
|
|
|
|
GetWorld()->GetTimerManager().SetTimer(TextAnimationTimerHandle, this, &UDialogueNPC::NextCharacter, TextAnimationSpeed, true);
|
2023-02-02 01:59:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UDialogueNPC::EndDialogue()
|
|
|
|
|
{
|
2023-05-19 01:20:15 +00:00
|
|
|
|
bIsInDialogue = false;
|
2023-02-02 01:59:33 +00:00
|
|
|
|
TextAnimationTimerHandle.Invalidate();
|
|
|
|
|
DialogueWidgetInstance->RemoveFromParent();
|
|
|
|
|
|
2023-05-13 15:25:07 +00:00
|
|
|
|
if (bResetUserControls)
|
2023-02-02 02:39:35 +00:00
|
|
|
|
{
|
2023-05-11 07:52:30 +00:00
|
|
|
|
//Reset UI Mode
|
|
|
|
|
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
|
2023-05-13 15:25:07 +00:00
|
|
|
|
PlayerController->SetIgnoreMoveInput(false);
|
|
|
|
|
PlayerController->SetIgnoreLookInput(false);
|
2023-05-11 07:52:30 +00:00
|
|
|
|
PlayerController->SetInputMode(FInputModeGameOnly());
|
|
|
|
|
PlayerController->bShowMouseCursor = false;
|
2023-02-02 02:39:35 +00:00
|
|
|
|
}
|
2023-02-02 01:59:33 +00:00
|
|
|
|
}
|
2023-02-06 03:28:53 +00:00
|
|
|
|
|
2023-05-13 15:25:07 +00:00
|
|
|
|
UDialoguePath* UDialogueNPC::CreateRootDialoguePath(const bool ResetUserControls)
|
2023-02-06 03:28:53 +00:00
|
|
|
|
{
|
2023-05-13 15:25:07 +00:00
|
|
|
|
bResetUserControls = ResetUserControls;
|
2023-05-04 05:31:59 +00:00
|
|
|
|
return NewObject<UDialoguePath>();
|
2023-02-09 17:01:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
UDialoguePath* UDialogueNPC::AddDialogue(UDialoguePath* DialoguePath, FText TextInput)
|
2023-02-09 17:01:03 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
if (TextInput.IsEmpty()) return DialoguePath;
|
|
|
|
|
DialoguePath->Dialogue.Add(TextInput.ToString());
|
|
|
|
|
return DialoguePath;
|
2023-02-09 17:01:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
void UDialogueNPC::AddChoices(UDialoguePath* ParentPath, FText ChoiceText1, FText ChoiceText2, FText ChoiceText3, UDialoguePath*& Out_ChoicePath1, UDialoguePath*& Out_ChoicePath2, UDialoguePath*& Out_ChoicePath3)
|
2023-02-20 09:50:09 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
ParentPath->Choices.Add(NewObject<UDialoguePath>());
|
|
|
|
|
ParentPath->Choices.Add(NewObject<UDialoguePath>());
|
|
|
|
|
ParentPath->Choices.Add(NewObject<UDialoguePath>());
|
|
|
|
|
Out_ChoicePath1 = ParentPath->Choices[0];
|
|
|
|
|
Out_ChoicePath2 = ParentPath->Choices[1];
|
|
|
|
|
Out_ChoicePath3 = ParentPath->Choices[2];
|
2023-05-14 22:02:09 +00:00
|
|
|
|
ParentPath->ChoiceText1 = ChoiceText1;
|
|
|
|
|
ParentPath->ChoiceText2 = ChoiceText2;
|
|
|
|
|
ParentPath->ChoiceText3 = ChoiceText3;
|
2023-02-20 09:50:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 06:16:40 +00:00
|
|
|
|
UDialoguePath* UDialogueNPC::AddQuest(UDialoguePath* DialoguePath, UQuest* Quest)
|
|
|
|
|
{
|
2023-05-15 03:02:05 +00:00
|
|
|
|
DialoguePath->Dialogue.Add(FText::FromString("-- " + FString::FromInt(Quests.Num())).ToString());
|
2023-05-02 06:16:40 +00:00
|
|
|
|
Quests.Add(Quests.Num(), Quest);
|
|
|
|
|
return DialoguePath;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 05:32:11 +00:00
|
|
|
|
UDialoguePath* UDialogueNPC::CallBlueprintFunction(UDialoguePath* DialoguePath, const FString FunctionName)
|
|
|
|
|
{
|
2023-05-11 07:52:30 +00:00
|
|
|
|
DialoguePath->Dialogue.Add(FText::FromString("@@ " + FString::FromInt(BlueprintFunctions.Num())).ToString());
|
2023-05-11 05:32:11 +00:00
|
|
|
|
BlueprintFunctions.Add(BlueprintFunctions.Num(), FunctionName);
|
|
|
|
|
return DialoguePath;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 07:52:30 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
void UDialogueNPC::Choice1()
|
2023-02-09 17:01:03 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialoguePath = CurrentDialoguePath->Choices[0];
|
2023-05-04 00:42:54 +00:00
|
|
|
|
ResetDialogueUI();
|
2023-02-09 17:01:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
void UDialogueNPC::Choice2()
|
2023-02-09 17:01:03 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialoguePath = CurrentDialoguePath->Choices[1];
|
2023-05-04 00:42:54 +00:00
|
|
|
|
ResetDialogueUI();
|
2023-02-06 03:28:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 04:49:09 +00:00
|
|
|
|
void UDialogueNPC::Choice3()
|
2023-02-06 03:28:53 +00:00
|
|
|
|
{
|
2023-03-13 04:49:09 +00:00
|
|
|
|
CurrentDialoguePath = CurrentDialoguePath->Choices[2];
|
2023-05-04 00:42:54 +00:00
|
|
|
|
ResetDialogueUI();
|
2023-02-06 03:28:53 +00:00
|
|
|
|
}
|