Implemented Bounty Director Class Functionality

This commit is contained in:
Rafal Swierczek 2023-09-28 15:19:26 +01:00
parent 5e6f5e4b9e
commit 0fd1b60d52
5 changed files with 211 additions and 14 deletions

View File

@ -3,6 +3,8 @@
#include "BountyDirector.h" #include "BountyDirector.h"
#include "Components/ArrowComponent.h"
// Sets default values // Sets default values
ABountyDirector::ABountyDirector() ABountyDirector::ABountyDirector()
{ {
@ -11,17 +13,139 @@ ABountyDirector::ABountyDirector()
} }
// Called when the game starts or when spawned
void ABountyDirector::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame // Called every frame
void ABountyDirector::Tick(float DeltaTime) void ABountyDirector::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
} }
// Called when the game starts or when spawned
void ABountyDirector::BeginPlay()
{
Super::BeginPlay();
PlayerChar = Cast<AEndlessVendettaCharacter>(GetWorld()->GetFirstPlayerController()->GetCharacter());
if (!IsValid(PlayerChar)) UE_LOG(LogTemp, Fatal, TEXT("Players Character isn't being loaded in BeginPlay() in BountyDirector"));
// Setup a component for bounties to attach to on the player
for (UActorComponent* ActorComp : PlayerChar->GetComponentsByTag(UArrowComponent::StaticClass(), FName("Bounty")))
{
BountyAttachmentPoint = Cast<UArrowComponent>(ActorComp);
if (!IsValid(BountyAttachmentPoint)) UE_LOG(LogTemp, Fatal, TEXT("There's no Bounty Attachment UArrowComponent on Players Char "));
break;
}
// Setup up starting Side Bounty indexes
for (int Index = 0; Index < 3; Index++)
{
CurrentSideBountyIndexes.Add(Index);
}
ActiveSideBounties.SetNum(3);
SpawnBountyAndItsSideBounties();
UpdateBountyDisplay();
}
void ABountyDirector::SpawnBountyAndItsSideBounties()
{
UE_LOG(LogTemp, Warning, TEXT("Spawning Bounty..."));
if (BountyClassArray.IsEmpty()) return;
if (!IsValid(BountyClassArray[CurrentBountyIndex])) UE_LOG(LogTemp, Fatal, TEXT("Missing Bounty at Index: %d"), CurrentBountyIndex);
// Spawn Main Bounty which the current bounty index is pointing to
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
AActor* BountyActor = GetWorld()->SpawnActor<AActor>(BountyClassArray[CurrentBountyIndex], PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams);
const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::SnapToTarget, true);
BountyActor->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules);
ActiveBounty = Cast<ABountyClass>(BountyActor);
if (!IsValid(ActiveBounty)) UE_LOG(LogTemp, Fatal, TEXT("Failed to Cast to Bounty class"));
// WHEN MARCEL STOPS PLAYING WITH THE CHARACTER, ADD THIS BOUNTY TO PLAYERS ARRAY OF ACTIVE BOUNTIES!!!!!
ActiveBounty->CompletedFirstCheckpoint.AddDynamic(this, &ABountyDirector::DestroyActiveSideBounties);
// Spawn in Side Bounties which are linked to the Main Bounty
int ActiveSideBountyIndex = 0;
for (int CurrentSideBountyIndex : CurrentSideBountyIndexes)
{
if (SideBountyClassArray.Num() <= CurrentSideBountyIndex || !IsValid(SideBountyClassArray[CurrentSideBountyIndex])) continue;
AActor* SideBountyActor = GetWorld()->SpawnActor<AActor>(SideBountyClassArray[CurrentSideBountyIndex], PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams);
ASideBountyClass* SideBounty = Cast<ASideBountyClass>(SideBountyActor);
SideBounty->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules);
ActiveSideBounties[ActiveSideBountyIndex] = SideBounty;
SideBounty->ActiveSBC_Index = ActiveSideBountyIndex;
ActiveSideBounties[ActiveSideBountyIndex]->CompletedSideBounty.AddDynamic(this, &ABountyDirector::SideBountyCompleted);
// ONCE AGAIN WHEN MARCEL STOPS PLAYING WITH THE CHARACTER, ADD THIS SIDE BOUNTY TO PLAYERS ARRAY OF ACTIVE BOUNTIES!!!!!
ActiveSideBountyIndex++;
}
}
void ABountyDirector::UpdateBountyProgression()
{
if (!IsValid(ActiveBounty)) return;
if (ActiveBounty->IsCompleted()) FinishActiveBounty();
}
void ABountyDirector::FinishActiveBounty()
{
ActiveBounty->CollectRewards();
// Destroy old Bounties
ActiveBounty->DestroyReturnToShipStep();
ActiveBounty->Destroy();
DestroyActiveSideBounties();
// Increment Main and Side Bounty Indexes
CurrentBountyIndex++;
for (int i = 0; i < 3; i++)
{
CurrentSideBountyIndexes[i] += 3;
}
// Game Completion Check
if (CurrentBountyIndex >= BountyClassArray.Num())
{
UE_LOG(LogTemp, Warning, TEXT("Finished all bounties currently available in the game :)"));
ActiveBounty = nullptr;
UpdateBountyDisplay();
return;
}
SpawnBountyAndItsSideBounties();
UpdateBountyDisplay();
}
void ABountyDirector::DestroyActiveSideBounties()
{
for (ASideBountyClass* SideBounty : ActiveSideBounties)
{
if (!IsValid(SideBounty)) continue;
// WHEN MARCEL STOPS PLAYING WITH PLAYERS CHARACTER, REMOVE THIS SIDE BOUNTY FROM ACTIVE BOUNTIES
SideBounty->DestroyCheckpoints();
SideBounty->Destroy();
}
UpdateBountyDisplay();
}
void ABountyDirector::SideBountyCompleted(int SideBountyIndex)
{
UE_LOG(LogTemp,Warning,TEXT("Updating Main Bounties Checkpoints"));
ActiveBounty->UpdateBountyCheckpoints(ActiveSideBounties[SideBountyIndex]->GetReplacementCheckpoints());
// WHEN MARCEL STOPS PLAYING WITH PLAYER CHAR, REMOVE THIS SIDE BOUNTY FROM ACTIVE BOUNTIES
ActiveSideBounties[SideBountyIndex]->DestroyCheckpoints();
ActiveSideBounties[SideBountyIndex]->Destroy();
UpdateBountyDisplay();
}

View File

@ -3,6 +3,9 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "BountyClass.h"
#include "SideBountyClass.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "BountyDirector.generated.h" #include "BountyDirector.generated.h"
@ -11,16 +14,85 @@ class ENDLESSVENDETTA_API ABountyDirector : public AActor
{ {
GENERATED_BODY() GENERATED_BODY()
public: AEndlessVendettaCharacter* PlayerChar;
// Sets default values for this actor's properties
ABountyDirector();
// Scene Component Used to Attach Bounties to
UArrowComponent* BountyAttachmentPoint;
// Ordered Array of Main Bounties
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<TSubclassOf<ABountyClass>> BountyClassArray;
// Ordered Array of Side Bounties, in three's
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<TSubclassOf<ASideBountyClass>> SideBountyClassArray;
int CurrentBountyIndex = 0;
TArray<int> CurrentSideBountyIndexes;
UPROPERTY(VisibleAnywhere, Category = "Bounty")
ABountyClass* ActiveBounty;
UPROPERTY(VisibleAnywhere, Category = "Bounty")
TArray<ASideBountyClass*> ActiveSideBounties;
// Checks if completed the bounty, and moves onto the next if so
UFUNCTION(BlueprintCallable, Category = "Bounty")
void UpdateBountyProgression();
void SpawnBountyAndItsSideBounties();
// Collect reward for current Bounty and prepare for the next
void FinishActiveBounty();
protected: protected:
// Called when the game starts or when spawned // Called when the game starts or when spawned
virtual void BeginPlay() override; virtual void BeginPlay() override;
/** Blueprint implemented function called from c++, handles aesthetic changes to bounty display
based on data from ActiveBC and ActiveSBC */
UFUNCTION(BlueprintImplementableEvent, Category = "bounty")
void UpdateBountyDisplay();
// Ran when a Side Bounty is completed and wants to update the active bounties checkpoints
UFUNCTION()
void SideBountyCompleted(int SideBountyIndex);
UFUNCTION()
void DestroyActiveSideBounties();
public: public:
// Called every frame // Called every frame
virtual void Tick(float DeltaTime) override; virtual void Tick(float DeltaTime) override;
// Sets default values for this actor's properties
ABountyDirector();
// ------ Getters ------
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetBountyTitle()
{
return IsValid(ActiveBounty) ? FString("N/A") : ActiveBounty->GetBountyTitle();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetBountyDescription()
{
return IsValid(ActiveBounty) ? FString("N/A") : ActiveBounty->GetBountyDesc();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetSideBountyTitle(int SideBountyIndex)
{
return (SideBountyIndex > 2 || SideBountyIndex < 0 || IsValid(ActiveSideBounties[SideBountyIndex])) ? FString("N/A") : ActiveSideBounties[SideBountyIndex]->GetBountyTitle();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetSideBountyDescription(int SideBountyIndex)
{
return (SideBountyIndex > 2 || SideBountyIndex < 0 || IsValid(ActiveSideBounties[SideBountyIndex])) ? FString("N/A") : ActiveSideBounties[SideBountyIndex]->GetBountyDesc();
}
}; };

View File

@ -27,6 +27,7 @@ class ENDLESSVENDETTA_API ACheckpointClass : public AActor
UFUNCTION(BlueprintCallable, Category = "Checkpoint") UFUNCTION(BlueprintCallable, Category = "Checkpoint")
void BroadcastCompletion() void BroadcastCompletion()
{ {
UE_LOG(LogTemp, Warning, TEXT("Completed Checkpoint"));
CompletedCheckpoint.Broadcast(); CompletedCheckpoint.Broadcast();
} }