diff --git a/EndlessVendetta/Content/StarterContent/Architecture/Floor_400x400.uasset b/EndlessVendetta/Content/StarterContent/Architecture/Floor_400x400.uasset index c2a34afc..d8d11add 100644 --- a/EndlessVendetta/Content/StarterContent/Architecture/Floor_400x400.uasset +++ b/EndlessVendetta/Content/StarterContent/Architecture/Floor_400x400.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c0ecf0ac0702cc2bd355ec050232a61c49e10f102448efbeb735a51824adef6 -size 14948 +oid sha256:c253fc4685a93abd7626303f34194de38d32f2d1549008ec1051e50eff7e5c62 +size 14831 diff --git a/EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset b/EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset index bc2f4981..0f990580 100644 --- a/EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset +++ b/EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d8e13eaeaa5d8a31e974965a0e7f2c7cb546934b4129fe17baa4c26f838a051 -size 66790690 +oid sha256:bc35eb2d43a47427d30aba0196f9eac90d089dd3abca319528c5d25c83510d0d +size 72364642 diff --git a/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.cpp b/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.cpp index 67e12786..9e622442 100644 --- a/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.cpp @@ -3,6 +3,8 @@ #include "BountyDirector.h" +#include "Components/ArrowComponent.h" + // Sets default values ABountyDirector::ABountyDirector() { @@ -11,17 +13,139 @@ ABountyDirector::ABountyDirector() } -// Called when the game starts or when spawned -void ABountyDirector::BeginPlay() -{ - Super::BeginPlay(); - -} - // Called every frame void ABountyDirector::Tick(float DeltaTime) { Super::Tick(DeltaTime); } +// Called when the game starts or when spawned +void ABountyDirector::BeginPlay() +{ + Super::BeginPlay(); + + PlayerChar = Cast(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(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(BountyClassArray[CurrentBountyIndex], PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams); + const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::SnapToTarget, true); + BountyActor->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules); + + ActiveBounty = Cast(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(SideBountyClassArray[CurrentSideBountyIndex], PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams); + ASideBountyClass* SideBounty = Cast(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(); +} + diff --git a/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.h b/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.h index 7192ce21..00b69ef9 100644 --- a/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.h +++ b/EndlessVendetta/Source/EndlessVendetta/BountySystem/BountyDirector.h @@ -3,6 +3,9 @@ #pragma once #include "CoreMinimal.h" +#include "BountyClass.h" +#include "SideBountyClass.h" +#include "EndlessVendetta/EndlessVendettaCharacter.h" #include "GameFramework/Actor.h" #include "BountyDirector.generated.h" @@ -11,16 +14,85 @@ class ENDLESSVENDETTA_API ABountyDirector : public AActor { GENERATED_BODY() -public: - // Sets default values for this actor's properties - ABountyDirector(); + AEndlessVendettaCharacter* PlayerChar; + // Scene Component Used to Attach Bounties to + UArrowComponent* BountyAttachmentPoint; + + // Ordered Array of Main Bounties + UPROPERTY(EditDefaultsOnly, Category = "Bounty") + TArray> BountyClassArray; + + // Ordered Array of Side Bounties, in three's + UPROPERTY(EditDefaultsOnly, Category = "Bounty") + TArray> SideBountyClassArray; + + int CurrentBountyIndex = 0; + + TArray CurrentSideBountyIndexes; + + UPROPERTY(VisibleAnywhere, Category = "Bounty") + ABountyClass* ActiveBounty; + + UPROPERTY(VisibleAnywhere, Category = "Bounty") + TArray 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: // Called when the game starts or when spawned 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: // Called every frame 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(); + } + + }; diff --git a/EndlessVendetta/Source/EndlessVendetta/BountySystem/CheckpointClass.h b/EndlessVendetta/Source/EndlessVendetta/BountySystem/CheckpointClass.h index c182b8cb..6991181a 100644 --- a/EndlessVendetta/Source/EndlessVendetta/BountySystem/CheckpointClass.h +++ b/EndlessVendetta/Source/EndlessVendetta/BountySystem/CheckpointClass.h @@ -27,6 +27,7 @@ class ENDLESSVENDETTA_API ACheckpointClass : public AActor UFUNCTION(BlueprintCallable, Category = "Checkpoint") void BroadcastCompletion() { + UE_LOG(LogTemp, Warning, TEXT("Completed Checkpoint")); CompletedCheckpoint.Broadcast(); }