2023-03-13 05:19:13 +00:00
|
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "QuestSystem.h"
|
2023-05-04 04:04:37 +00:00
|
|
|
|
#include "Misc/OutputDeviceNull.h"
|
2023-03-13 05:19:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Sets default values for this component's properties
|
|
|
|
|
UQuestSystem::UQuestSystem()
|
|
|
|
|
{
|
|
|
|
|
// 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 03:26:14 +00:00
|
|
|
|
static ConstructorHelpers::FClassFinder<UUserWidget> QuestWidgetClass(TEXT("/Game/Blueprints/Quest_UI/Quest_UI"));
|
2023-03-13 18:11:42 +00:00
|
|
|
|
QuestWidget = QuestWidgetClass.Class;
|
2023-05-04 04:04:37 +00:00
|
|
|
|
static ConstructorHelpers::FClassFinder<UUserWidget> QuestCompletionWidgetClass(TEXT("/Game/Blueprints/Quest_UI/QuestCompletion_UI"));
|
|
|
|
|
QuestCompletionWidget = QuestCompletionWidgetClass.Class;
|
2023-03-13 05:19:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Called when the game starts
|
|
|
|
|
void UQuestSystem::BeginPlay()
|
|
|
|
|
{
|
|
|
|
|
Super::BeginPlay();
|
2023-05-02 04:42:48 +00:00
|
|
|
|
PlayerInventory = GetOwner()->FindComponentByClass<UInventoryComponent>();
|
|
|
|
|
PlayerInventory->OnInventoryUpdated.AddDynamic(this, &UQuestSystem::CheckActiveQuestConditions);
|
2023-05-04 04:04:37 +00:00
|
|
|
|
QuestWidgetInstance = CreateWidget<UUserWidget>(GetWorld(), QuestWidget);
|
|
|
|
|
QuestWidgetInstance->AddToViewport();
|
|
|
|
|
QuestCompletionWidgetInstance = CreateWidget<UUserWidget>(GetWorld(), QuestCompletionWidget);
|
|
|
|
|
QuestCompletionWidgetInstance->AddToViewport();
|
|
|
|
|
|
|
|
|
|
MainQuestBorder = Cast<UBorder>(QuestWidgetInstance->GetWidgetFromName("MainQuest"));
|
|
|
|
|
SubQuestBorder = Cast<UBorder>(QuestWidgetInstance->GetWidgetFromName("SubQuest"));
|
|
|
|
|
MainQuestTitle = Cast<UTextBlock>(QuestWidgetInstance->GetWidgetFromName("MainQuest_Text"));
|
|
|
|
|
SubQuestTitle = Cast<UTextBlock>(QuestWidgetInstance->GetWidgetFromName("SubQuest_Text"));
|
|
|
|
|
MainQuestGoals = Cast<URichTextBlock>(QuestWidgetInstance->GetWidgetFromName("MainGoals_Text"));
|
|
|
|
|
SubQuestGoals = Cast<URichTextBlock>(QuestWidgetInstance->GetWidgetFromName("SubGoals_Text"));
|
|
|
|
|
|
|
|
|
|
QuestCompletionTitle = Cast<UTextBlock>(QuestCompletionWidgetInstance->GetWidgetFromName("QuestTitle_Text"));
|
|
|
|
|
if (!ActiveQuests.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
MainQuestTitle->SetText(ActiveQuests[0]->Title);
|
|
|
|
|
UpdateQuestGoalsUI(ActiveQuests[0]);
|
|
|
|
|
}
|
2023-03-13 05:19:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Called every frame
|
|
|
|
|
void UQuestSystem::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
|
|
|
{
|
|
|
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 16:36:24 +00:00
|
|
|
|
void UQuestSystem::CheckActiveQuestConditions()
|
|
|
|
|
{
|
|
|
|
|
for (UQuest* Quest : ActiveQuests)
|
|
|
|
|
{
|
|
|
|
|
if (Quest->CheckConditions(GetWorldState()))
|
|
|
|
|
{
|
2023-05-02 04:42:48 +00:00
|
|
|
|
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Quest Completed!"));
|
2023-03-29 16:36:24 +00:00
|
|
|
|
CompletedQuests.Add(Quest);
|
2023-05-02 04:42:48 +00:00
|
|
|
|
Quest->ApplyRewards(PlayerInventory);
|
2023-05-04 04:04:37 +00:00
|
|
|
|
QuestCompletionTitle->SetText(Quest->Title);
|
|
|
|
|
if (Quest->QuestLine == EQuestLine::Sub)
|
|
|
|
|
{
|
|
|
|
|
bHasSubQuest = false;
|
|
|
|
|
SubQuestBorder->SetVisibility(ESlateVisibility::Hidden);
|
|
|
|
|
}
|
|
|
|
|
if (Quest->bShowQuestCompletedNotification)
|
|
|
|
|
{
|
|
|
|
|
FOutputDeviceNull AR;
|
|
|
|
|
const FString Command = FString::Printf(TEXT("PlayCompletedQuestAnimation"));
|
|
|
|
|
QuestCompletionWidgetInstance->CallFunctionByNameWithArguments(*Command, AR, nullptr, true);
|
|
|
|
|
}
|
2023-03-29 16:36:24 +00:00
|
|
|
|
}
|
2023-05-04 04:04:37 +00:00
|
|
|
|
UpdateQuestGoalsUI(Quest);
|
2023-03-29 16:36:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 04:42:48 +00:00
|
|
|
|
UWorldState* UQuestSystem::GetWorldState() const
|
2023-03-29 16:36:24 +00:00
|
|
|
|
{
|
2023-05-02 04:42:48 +00:00
|
|
|
|
UWorldState* WorldState = NewObject<UWorldState>();
|
|
|
|
|
WorldState->Items = PlayerInventory->Items;
|
|
|
|
|
WorldState->QuestFlags = QuestFlags;
|
2023-03-29 16:36:24 +00:00
|
|
|
|
return WorldState;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 06:16:40 +00:00
|
|
|
|
bool UQuestSystem::AddQuest(UQuest* Quest)
|
2023-05-02 04:42:48 +00:00
|
|
|
|
{
|
2023-05-02 06:16:40 +00:00
|
|
|
|
if (!Quest->CheckPreConditions(GetWorldState())) return false;
|
2023-05-02 04:42:48 +00:00
|
|
|
|
ActiveQuests.Add(Quest);
|
2023-05-04 04:04:37 +00:00
|
|
|
|
if (Quest->QuestLine == EQuestLine::Sub)
|
|
|
|
|
{
|
|
|
|
|
bHasSubQuest = true;
|
|
|
|
|
SubQuestBorder->SetVisibility(ESlateVisibility::Visible);
|
|
|
|
|
SubQuestTitle->SetText(Quest->Title);
|
|
|
|
|
UpdateQuestGoalsUI(Quest);
|
|
|
|
|
}
|
|
|
|
|
else if (Quest->QuestLine == EQuestLine::Main)
|
|
|
|
|
{
|
|
|
|
|
MainQuestTitle->SetText(Quest->Title);
|
|
|
|
|
UpdateQuestGoalsUI(Quest);
|
|
|
|
|
}
|
2023-05-02 06:16:40 +00:00
|
|
|
|
return true;
|
2023-05-02 04:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UQuestSystem::AddQuestFlag(const FString FlagName, const bool FlagValue)
|
|
|
|
|
{
|
|
|
|
|
QuestFlags.Add(FlagName, FlagValue);
|
|
|
|
|
CheckActiveQuestConditions();
|
|
|
|
|
}
|
2023-05-02 06:16:40 +00:00
|
|
|
|
|
|
|
|
|
bool UQuestSystem::CheckPreConditions(UQuest* Quest) const
|
|
|
|
|
{
|
|
|
|
|
if (Quest->CheckPreConditions(GetWorldState())) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UQuestSystem::HasActiveQuest(UQuest* Quest) const
|
|
|
|
|
{
|
|
|
|
|
if (ActiveQuests.Contains(Quest)) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-05-04 04:04:37 +00:00
|
|
|
|
|
|
|
|
|
void UQuestSystem::UpdateQuestGoalsUI(const UQuest* Quest) const
|
|
|
|
|
{
|
|
|
|
|
FString GoalsText;
|
|
|
|
|
if (!Quest->Goals->QuestFlags.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
for (TTuple<FString, bool> QuestFlag : Quest->Goals->QuestFlags)
|
|
|
|
|
{
|
|
|
|
|
if (Quest->FlagTrueMatch(GetWorldState(), QuestFlag.Key))
|
|
|
|
|
{
|
|
|
|
|
GoalsText += FString::Printf(TEXT("- <Strike>%s</>\n"), *QuestFlag.Key);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GoalsText += FString::Printf(TEXT("- %s\n"), *QuestFlag.Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!Quest->Goals->Items.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
for (UBaseItem* Item : Quest->Goals->Items)
|
|
|
|
|
{
|
|
|
|
|
FString Left, Right;
|
|
|
|
|
Quest->GetItemCountAndGoalAmount(GetWorldState(), Item).Split("/", &Left, &Right);
|
|
|
|
|
if (FCString::Atoi(*Left) >= FCString::Atoi(*Right))
|
|
|
|
|
{
|
|
|
|
|
GoalsText += FString::Printf(TEXT("- <Strike>%s %s</>\n"), *Quest->GetItemCountAndGoalAmount(GetWorldState(), Item), *Item->ItemDisplayName.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GoalsText += FString::Printf(TEXT("- %s %s\n"), *Quest->GetItemCountAndGoalAmount(GetWorldState(), Item), *Item->ItemDisplayName.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Quest->QuestLine == EQuestLine::Main) MainQuestGoals->SetText(FText::FromString(GoalsText));
|
|
|
|
|
else if (Quest->QuestLine == EQuestLine::Sub) SubQuestGoals->SetText(FText::FromString(GoalsText));
|
|
|
|
|
}
|