286 lines
8.5 KiB
C++
286 lines
8.5 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "DialogueComponent.h"
|
|
|
|
#include "DialogueSubsystem.h"
|
|
#include "DialogueWidget.h"
|
|
#include "EleriPlayerController.h"
|
|
#include "Speech.h"
|
|
#include "SpeechDataAsset.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "ProjectEleri/GameEventSystem/GameEventSubsystem.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "DialogueSystem"
|
|
|
|
void UDialogueComponent::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
OwnerActor = GetOwner();
|
|
|
|
if(UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()))
|
|
{
|
|
if(UDialogueSubsystem* DialogueSubsystem = GameInstance->GetSubsystem<UDialogueSubsystem>())
|
|
{
|
|
if(DialogueSubsystem->IsDialogueLoaded())
|
|
SpeechData = DialogueSubsystem->GetDialogueForActor(GetOwner());
|
|
else
|
|
DialogueSubsystem->OnDialogueAssetsLoaded.AddDynamic(this, &UDialogueComponent::OnDialogueLoaded);
|
|
}
|
|
}
|
|
|
|
EleriPlayerController = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(this, 0));
|
|
}
|
|
|
|
void UDialogueComponent::OnDialogueLoaded()
|
|
{
|
|
if(UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()))
|
|
{
|
|
if(UDialogueSubsystem* DialogueSubsystem = GameInstance->GetSubsystem<UDialogueSubsystem>())
|
|
SpeechData = DialogueSubsystem->GetDialogueForActor(GetOwner());
|
|
}
|
|
}
|
|
|
|
void UDialogueComponent::FilterSpeechData()
|
|
{
|
|
ActiveSpeechData.Empty();
|
|
for (int i = 0; i < SpeechData.Num(); ++i)
|
|
{
|
|
//Check if speech event condition is met
|
|
ActiveSpeechData.Add(SpeechData[i]);
|
|
}
|
|
}
|
|
|
|
void UDialogueComponent::StartDialogueWithNpc()
|
|
{
|
|
UDialogueSubsystem* DialogueSubsystem = UDialogueSubsystem::Get(this);
|
|
ensure(DialogueSubsystem);
|
|
|
|
if (!DialogueSubsystem->StartDialogue()) return;
|
|
|
|
MappedDialogueOptions.Empty();
|
|
FilterSpeechData();
|
|
TArray<USpeechDataAsset*> StartingDialogues = GetStartingDialogues();
|
|
if (StartingDialogues.IsEmpty()) return;
|
|
|
|
TriggerDialogue(StartingDialogues[FMath::RandRange(0, StartingDialogues.Num() - 1)], CurrentDialogueReplacementMap);
|
|
|
|
TArray<USpeechDataAsset*> ActiveDialogues = GetActiveDialogues();
|
|
TArray<FText> PlayerAsks = GetPlayerAsksFromDialogueList(ActiveDialogues);
|
|
for (int32 i = 0; i < ActiveDialogues.Num() - 1; i++)
|
|
{
|
|
FPlayerSpeakToDialogue SpeakToDialogue;
|
|
SpeakToDialogue.NextSpeechDataAsset = ActiveDialogues[i];
|
|
MappedDialogueOptions.Add(i, SpeakToDialogue);
|
|
}
|
|
TriggerDialogueSelect(PlayerAsks, true);
|
|
}
|
|
|
|
void UDialogueComponent::TriggerDialogue_Async(TSoftObjectPtr<USpeechDataAsset> DialogueAssetPath, const TMap<FString, FText>& ReplacementMap)
|
|
{
|
|
DialogueAssetPath.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, ReplacementMap](const FSoftObjectPath& Path, UObject* Object)
|
|
{
|
|
if (USpeechDataAsset* DataAsset = Cast<USpeechDataAsset>(Object))
|
|
{
|
|
TriggerDialogue(DataAsset, ReplacementMap);
|
|
}
|
|
}));
|
|
}
|
|
|
|
void UDialogueComponent::TriggerDialogue(USpeechDataAsset* DialogueAssetPath, const TMap<FString, FText>& ReplacementMap)
|
|
{
|
|
UDialogueSubsystem* DialogueSubsystem = UDialogueSubsystem::Get(this);
|
|
if (!DialogueSubsystem) return;
|
|
|
|
if (!DialogueSubsystem->IsDialogueStarted())
|
|
{
|
|
BindToControllerInput();
|
|
bDialogueSelectOpen = false;
|
|
DialogueWidget = Cast<UDialogueWidget>(EleriPlayerController->ToggleDialogueWindow(true));
|
|
DialogueWidget->AssignDialogueComponent(this);
|
|
}
|
|
|
|
CurrentLineIndex = 0;
|
|
CurrentActiveDialogue = DialogueAssetPath;
|
|
CurrentDialogueReplacementMap = ReplacementMap;
|
|
DialogueWidget->DisplayDialogue(CurrentActiveDialogue, GetOwner(), CurrentDialogueReplacementMap);
|
|
|
|
if (DialogueAssetPath->RandomizeLines && !DialogueAssetPath->PlayerSpeechMap.IsEmpty())
|
|
{
|
|
MappedDialogueOptions.Empty();
|
|
TArray<FText> PlayerSpeakOptions;
|
|
for (int32 i = 0; i <= CurrentActiveDialogue->PlayerSpeechMap.Num() - 1; i++)
|
|
{
|
|
MappedDialogueOptions.Add(i, CurrentActiveDialogue->PlayerSpeechMap[i]);
|
|
PlayerSpeakOptions.Add(CurrentActiveDialogue->PlayerSpeechMap[i].PlayerSpeak);
|
|
}
|
|
//TriggerDialogueSelect(PlayerSpeakOptions, false);
|
|
}
|
|
|
|
DialogueSubsystem->StartDialogue();
|
|
}
|
|
|
|
TArray<USpeechDataAsset*> UDialogueComponent::GetActiveSpeechData() { return ActiveSpeechData; }
|
|
|
|
TArray<USpeechDataAsset*> UDialogueComponent::GetStartingDialogues()
|
|
{
|
|
TArray<USpeechDataAsset*> TempSpeechData;
|
|
for (int i = 0; i < ActiveSpeechData.Num(); ++i)
|
|
{
|
|
if(ActiveSpeechData[i]->TestRequirements(GetWorld()) && ActiveSpeechData[i]->PlayerAsk.IsEmpty())
|
|
TempSpeechData.AddUnique(ActiveSpeechData[i]);
|
|
}
|
|
|
|
return TempSpeechData;
|
|
}
|
|
|
|
TArray<USpeechDataAsset*> UDialogueComponent::GetActiveDialogues()
|
|
{
|
|
TArray<USpeechDataAsset*> TempSpeechData;
|
|
for (int i = 0; i < ActiveSpeechData.Num(); ++i)
|
|
{
|
|
if(ActiveSpeechData[i]->TestRequirements(GetWorld()) && !ActiveSpeechData[i]->PlayerAsk.IsEmpty())
|
|
TempSpeechData.AddUnique(ActiveSpeechData[i]);
|
|
}
|
|
|
|
return TempSpeechData;
|
|
}
|
|
|
|
void UDialogueComponent::SetTextReplacementMap(const TMap<FString, FText>& ReplacementMap)
|
|
{
|
|
CurrentDialogueReplacementMap = ReplacementMap;
|
|
}
|
|
|
|
void UDialogueComponent::CloseDialogue()
|
|
{
|
|
UDialogueSubsystem* DialogueSubsystem = UDialogueSubsystem::Get(this);
|
|
if (!DialogueSubsystem) return;
|
|
DialogueSubsystem->EndDialogue();
|
|
|
|
SelectedDialogueOptionIndex = 0;
|
|
CurrentLineIndex = 0;
|
|
CurrentActiveDialogue = nullptr;
|
|
UnbindControllerInput();
|
|
EleriPlayerController->ToggleDialogueWindow(false);
|
|
}
|
|
|
|
void UDialogueComponent::AdvanceDialogue()
|
|
{
|
|
const UDialogueSubsystem* DialogueSubsystem = UDialogueSubsystem::Get(this);
|
|
if (!DialogueSubsystem) return;
|
|
|
|
if (!DialogueWidget) return;
|
|
|
|
if (CurrentActiveDialogue)
|
|
{
|
|
if (bDialogueSelectOpen) return;
|
|
|
|
if (DialogueWidget->IsTypingDialogue())
|
|
{
|
|
DialogueWidget->SkipDialogueTyping();
|
|
return;
|
|
}
|
|
|
|
if (CurrentLineIndex < CurrentActiveDialogue->DialogueLines.Num())
|
|
{
|
|
const FSoftObjectPath EventToTrigger = CurrentActiveDialogue->DialogueLines[CurrentLineIndex].TriggerEventStart;
|
|
if (!EventToTrigger.IsNull())
|
|
{
|
|
UGameEventSubsystem::GetGameEventSubsystem()->StartEvent(EventToTrigger);
|
|
}
|
|
}
|
|
|
|
if (!CurrentActiveDialogue->RandomizeLines && (CurrentLineIndex <= CurrentActiveDialogue->DialogueLines.Num() - 1))
|
|
{
|
|
CurrentLineIndex++;
|
|
DialogueWidget->AdvanceDialogue(CurrentActiveDialogue->DialogueLines[CurrentLineIndex].DialogueLine, CurrentActiveDialogue->DialogueLines[CurrentLineIndex].SpeakerName);
|
|
return;
|
|
}
|
|
|
|
if (!CurrentActiveDialogue->PlayerSpeechMap.IsEmpty())
|
|
{
|
|
MappedDialogueOptions.Empty();
|
|
TArray<FText> PlayerSpeakOptions;
|
|
for (int32 i = 0; i <= CurrentActiveDialogue->PlayerSpeechMap.Num() - 1; i++)
|
|
{
|
|
MappedDialogueOptions.Add(i, CurrentActiveDialogue->PlayerSpeechMap[i]);
|
|
PlayerSpeakOptions.Add(CurrentActiveDialogue->PlayerSpeechMap[i].PlayerSpeak);
|
|
}
|
|
TriggerDialogueSelect(PlayerSpeakOptions, false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
CloseDialogue();
|
|
DialogueSubsystem->OnDialogueEnded.Broadcast();
|
|
}
|
|
|
|
void UDialogueComponent::TriggerDialogueSelect(TArray<FText>& DialogueOptions, bool bIsDialogueStart)
|
|
{
|
|
if (DialogueOptions.IsEmpty()) return;
|
|
|
|
if (bIsDialogueStart)
|
|
{
|
|
DialogueOptions.Add(LOCTEXT("Bye_DialogueEnd", "Bye"));
|
|
}
|
|
|
|
DialogueWidget->OnDialogueOptionSelected.AddUniqueDynamic(this, &UDialogueComponent::OnDialogueOptionSelected);
|
|
bDialogueSelectOpen = true;
|
|
SelectedDialogueOptionIndex = 0;
|
|
DialogueWidget->ShowDialogueOptions(true, DialogueOptions);
|
|
}
|
|
|
|
void UDialogueComponent::OnDialogueOptionSelected(int32 Index)
|
|
{
|
|
DialogueWidget->OnDialogueOptionSelected.RemoveDynamic(this, &UDialogueComponent::OnDialogueOptionSelected);
|
|
SelectedDialogueOptionIndex = Index;
|
|
bDialogueSelectOpen = false;
|
|
|
|
if (const FPlayerSpeakToDialogue* PlayerSpeak = MappedDialogueOptions.Find(SelectedDialogueOptionIndex))
|
|
{
|
|
if (PlayerSpeak->GameplayTag.IsValid())
|
|
{
|
|
UDialogueSubsystem::Get(this)->OnDialogueGameplayEvent.Broadcast(PlayerSpeak->GameplayTag);
|
|
}
|
|
|
|
if(!PlayerSpeak->NextSpeechDataAsset.IsNull())
|
|
{
|
|
TriggerDialogue_Async(PlayerSpeak->NextSpeechDataAsset, CurrentDialogueReplacementMap);
|
|
return;
|
|
}
|
|
|
|
if (!PlayerSpeak->bEndDialogueAfterSelecting)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
CloseDialogue();
|
|
}
|
|
|
|
TArray<FText> UDialogueComponent::GetPlayerAsksFromDialogueList(const TArray<USpeechDataAsset*>& DialogueList)
|
|
{
|
|
TArray<FText> PlayerAsks;
|
|
for (const USpeechDataAsset* DataAsset : DialogueList)
|
|
{
|
|
PlayerAsks.Add(DataAsset->PlayerAsk);
|
|
}
|
|
|
|
return PlayerAsks;
|
|
}
|
|
|
|
TArray<FText> UDialogueComponent::GetDialogueOptionsFromPlayerSpeakList(const TArray<FPlayerSpeakToDialogue>& SpeakList)
|
|
{
|
|
TArray<FText> Options;
|
|
for (const FPlayerSpeakToDialogue& Speak : SpeakList)
|
|
{
|
|
Options.Add(Speak.PlayerSpeak);
|
|
}
|
|
|
|
return Options;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|
|
|