// Fill out your copyright notice in the Description page of Project Settings. #include "QuestSystem.h" #include "Misc/OutputDeviceNull.h" // 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; static ConstructorHelpers::FClassFinder QuestWidgetClass(TEXT("/Game/Blueprints/Quest_UI/Quest_UI")); QuestWidget = QuestWidgetClass.Class; static ConstructorHelpers::FClassFinder QuestCompletionWidgetClass(TEXT("/Game/Blueprints/Quest_UI/QuestCompletion_UI")); QuestCompletionWidget = QuestCompletionWidgetClass.Class; } // Called when the game starts void UQuestSystem::BeginPlay() { Super::BeginPlay(); PlayerInventory = GetOwner()->FindComponentByClass(); PlayerInventory->OnInventoryUpdated.AddDynamic(this, &UQuestSystem::CheckActiveQuestConditions); QuestWidgetInstance = CreateWidget(GetWorld(), QuestWidget); QuestWidgetInstance->AddToViewport(); QuestCompletionWidgetInstance = CreateWidget(GetWorld(), QuestCompletionWidget); QuestCompletionWidgetInstance->AddToViewport(); MainQuestBorder = Cast(QuestWidgetInstance->GetWidgetFromName("MainQuest")); SubQuestBorder = Cast(QuestWidgetInstance->GetWidgetFromName("SubQuest")); MainQuestTitle = Cast(QuestWidgetInstance->GetWidgetFromName("MainQuest_Text")); SubQuestTitle = Cast(QuestWidgetInstance->GetWidgetFromName("SubQuest_Text")); MainQuestGoals = Cast(QuestWidgetInstance->GetWidgetFromName("MainGoals_Text")); SubQuestGoals = Cast(QuestWidgetInstance->GetWidgetFromName("SubGoals_Text")); QuestCompletionTitle = Cast(QuestCompletionWidgetInstance->GetWidgetFromName("QuestTitle_Text")); if (!ActiveQuests.IsEmpty()) { MainQuestTitle->SetText(ActiveQuests[0]->Title); UpdateQuestGoalsUI(ActiveQuests[0]); } } // Called every frame void UQuestSystem::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); } void UQuestSystem::CheckActiveQuestConditions() { for (UQuest* Quest : ActiveQuests) { if (Quest->CheckConditions(GetWorldState())) { CompletedQuests.Add(Quest); Quest->ApplyRewards(PlayerInventory); 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); } } UpdateQuestGoalsUI(Quest); } } UWorldState* UQuestSystem::GetWorldState() const { UWorldState* WorldState = NewObject(); WorldState->Items = PlayerInventory->Items; WorldState->QuestFlags = QuestFlags; return WorldState; } bool UQuestSystem::AddQuest(UQuest* Quest) { if (HasActiveQuest(Quest)) return false; if (!Quest->CheckPreConditions(GetWorldState())) return false; ActiveQuests.Add(Quest); 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); } return true; } void UQuestSystem::AddQuestFlag(const FString FlagName, const bool FlagValue) { QuestFlags.Add(FlagName, FlagValue); CheckActiveQuestConditions(); } 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; } void UQuestSystem::UpdateQuestGoalsUI(const UQuest* Quest) const { FString GoalsText; if (!Quest->Goals->QuestFlags.IsEmpty()) { for (TTuple QuestFlag : Quest->Goals->QuestFlags) { if (Quest->FlagTrueMatch(GetWorldState(), QuestFlag.Key)) { GoalsText += FString::Printf(TEXT("- %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("- %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)); }