Updated Quest System for UI

This commit is contained in:
Philip W 2023-05-04 05:04:37 +01:00
parent 9bb98b314b
commit f24fcc2d25
13 changed files with 166 additions and 10 deletions

Binary file not shown.

BIN
Content/Blueprints/Quest_UI/QuestCompletion_UI.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Blueprints/Quests/Quest_Start2.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/Fonts/DT_RichText.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Levels/Testing/BreakableWall_BP_ExitCave.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -21,6 +21,7 @@ bool UQuest::CheckPreConditions(UWorldState* WorldState) const
void UQuest::ApplyRewards(UInventoryComponent* Inventory)
{
if (Rewards.IsEmpty()) return;
for (UBaseItem* Item : Rewards)
{
Inventory->AddItem(Item);
@ -29,6 +30,7 @@ void UQuest::ApplyRewards(UInventoryComponent* Inventory)
bool UQuest::WorldStateMatch(UWorldState* A, UWorldState* B)
{
if (A->Items.IsEmpty() && !B->Items.IsEmpty()) return false;
for (UBaseItem* Item : B->Items)
{
if (!A->Items.Contains(Item) && Item->StackCount > A->Items[A->Items.Find(Item)]->StackCount)
@ -36,6 +38,8 @@ bool UQuest::WorldStateMatch(UWorldState* A, UWorldState* B)
return false;
}
}
if (A->QuestFlags.IsEmpty() && !B->QuestFlags.IsEmpty()) return false;
for (TTuple<FString, bool> Flag : B->QuestFlags)
{
if (!A->QuestFlags.Contains(Flag.Key) || A->QuestFlags[Flag.Key] != Flag.Value)
@ -43,5 +47,27 @@ bool UQuest::WorldStateMatch(UWorldState* A, UWorldState* B)
return false;
}
}
return true;
}
bool UQuest::FlagTrueMatch(const UWorldState* WorldState, const FString& FlagName)
{
if (!WorldState->QuestFlags.Contains(FlagName)) return false;
return true;
}
FString UQuest::GetItemCountAndGoalAmount(const UWorldState* WorldState, UBaseItem* Item) const
{
FString Result;
if (WorldState->Items.Contains(Item))
{
Result += FString::FromInt(WorldState->Items[WorldState->Items.Find(Item)]->StackCount);
Result += "/";
Result += FString::FromInt(Goals->Items[Goals->Items.Find(Item)]->StackCount);
return Result;
}
Result += "0/";
Result += FString::FromInt(Goals->Items[Goals->Items.Find(Item)]->StackCount);
return Result;
}

View File

@ -31,11 +31,15 @@ public:
UWorldState* Goals;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Instanced)
UWorldState* PreConditions;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, NoClear, Instanced)
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Instanced)
TArray<UBaseItem*> Rewards;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
bool bShowQuestCompletedNotification = true;
bool CheckConditions(UWorldState* WorldState) const;
bool CheckPreConditions(UWorldState* WorldState) const;
void ApplyRewards(UInventoryComponent* Inventory);
static bool WorldStateMatch(UWorldState* A, UWorldState* B);
static bool FlagTrueMatch(const UWorldState* WorldState, const FString& FlagName);
FString GetItemCountAndGoalAmount(const UWorldState* WorldState, UBaseItem* Item) const;
};

View File

@ -2,6 +2,7 @@
#include "QuestSystem.h"
#include "Misc/OutputDeviceNull.h"
// Sets default values for this component's properties
@ -13,6 +14,8 @@ UQuestSystem::UQuestSystem()
static ConstructorHelpers::FClassFinder<UUserWidget> QuestWidgetClass(TEXT("/Game/Blueprints/Quest_UI/Quest_UI"));
QuestWidget = QuestWidgetClass.Class;
static ConstructorHelpers::FClassFinder<UUserWidget> QuestCompletionWidgetClass(TEXT("/Game/Blueprints/Quest_UI/QuestCompletion_UI"));
QuestCompletionWidget = QuestCompletionWidgetClass.Class;
}
@ -22,6 +25,24 @@ void UQuestSystem::BeginPlay()
Super::BeginPlay();
PlayerInventory = GetOwner()->FindComponentByClass<UInventoryComponent>();
PlayerInventory->OnInventoryUpdated.AddDynamic(this, &UQuestSystem::CheckActiveQuestConditions);
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]);
}
}
@ -40,7 +61,20 @@ void UQuestSystem::CheckActiveQuestConditions()
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Quest Completed!"));
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);
}
}
@ -56,6 +90,18 @@ bool UQuestSystem::AddQuest(UQuest* Quest)
{
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;
}
@ -76,3 +122,40 @@ 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<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));
}

View File

@ -9,6 +9,8 @@
#include "Quest.h"
#include "WorldState.h"
#include "../BaseItems/InventoryComponent.h"
#include "Components/Border.h"
#include "Components/RichTextBlock.h"
#include "QuestSystem.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
@ -27,12 +29,21 @@ public:
UPROPERTY(EditAnywhere)
TMap<FString, bool> QuestFlags;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
bool bHasSubQuest = false;
protected:
// Called when the game starts
virtual void BeginPlay() override;
UPROPERTY()
TSubclassOf<UUserWidget> QuestWidget;
UPROPERTY()
UUserWidget* QuestWidgetInstance;
UPROPERTY()
TSubclassOf<UUserWidget> QuestCompletionWidget;
UPROPERTY()
UUserWidget* QuestCompletionWidgetInstance;
FJsonObject WorldStateJsonTemplate;
@ -53,4 +64,24 @@ public:
private:
UInventoryComponent* PlayerInventory;
// Quest Widget
UPROPERTY()
UBorder* MainQuestBorder;
UPROPERTY()
UBorder* SubQuestBorder;
UPROPERTY()
UTextBlock* MainQuestTitle;
UPROPERTY()
UTextBlock* SubQuestTitle;
UPROPERTY()
URichTextBlock* MainQuestGoals;
UPROPERTY()
URichTextBlock* SubQuestGoals;
// Quest Completion Widget
UPROPERTY()
UTextBlock* QuestCompletionTitle;
void UpdateQuestGoalsUI(const UQuest* Quest) const;
};