Implemented Bounty Class Functionality
This commit is contained in:
parent
44e0a6bc2d
commit
52af66afec
BIN
EndlessVendetta/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset
(Stored with Git LFS)
BIN
EndlessVendetta/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset
(Stored with Git LFS)
Binary file not shown.
@ -11,17 +11,120 @@ ABountyClass::ABountyClass()
|
||||
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
void ABountyClass::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
SpawnCheckpoints();
|
||||
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void ABountyClass::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
}
|
||||
|
||||
void ABountyClass::SpawnCheckpoints()
|
||||
{
|
||||
// Spawn all checkpoints associated with this bounty and store them in order
|
||||
FActorSpawnParameters SpawnParameters;
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
|
||||
for(TSubclassOf<ACheckpointClass> CheckpointClass : CheckpointsToSpawn)
|
||||
{
|
||||
if (CheckpointClass == nullptr)
|
||||
{
|
||||
// An unassigned checkpoint class can lead to undefined behaviour, hence the fatal log
|
||||
UE_LOG(LogTemp, Fatal, TEXT("A checkpoint class wasn't set for %s"), *BountyTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
FVector Loc = CheckpointClass.GetDefaultObject()->GetCheckpointSpawnTransform().GetLocation();
|
||||
FRotator Rot = CheckpointClass.GetDefaultObject()->GetCheckpointSpawnTransform().GetRotation().Rotator();
|
||||
ACheckpointClass* SpawnedCheckpoint = Cast<ACheckpointClass>(GetWorld()->SpawnActor<AActor>(CheckpointClass, Loc, Rot, SpawnParameters));
|
||||
BountyCheckpoints.Add(SpawnedCheckpoint);
|
||||
}
|
||||
|
||||
// Activate the first checkpoint and listen for its completion
|
||||
BountyCheckpoints[0]->Active = true;
|
||||
BountyCheckpoints[0]->CompletedCheckpoint.AddDynamic(this, &ABountyClass::IncrementBountyCheckpoint);
|
||||
}
|
||||
|
||||
void ABountyClass::IncrementBountyCheckpoint()
|
||||
{
|
||||
// Broadcast that the first Checkpoint has been completed so that side bounties can be destroyed
|
||||
if (!BountyStarted)
|
||||
{
|
||||
BountyStarted = true;
|
||||
CompletedFirstCheckpoint.Broadcast();
|
||||
}
|
||||
|
||||
// Bounty Completion Condition
|
||||
if (BountyCheckpoints.Num() <= MinCPsRequiredForCompletion)
|
||||
{
|
||||
Completed = true;
|
||||
BountyCheckpoints[0]->Active = false;
|
||||
BountyCheckpoints[0]->Destroy();
|
||||
BountyCheckpoints.RemoveAt(0);
|
||||
UE_LOG(LogTemp, Warning, TEXT(" You've Completed the Bounty!! Well done"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (BountyCheckpoints[0] == nullptr)
|
||||
{
|
||||
UE_LOG(LogTemp, Fatal, TEXT("Missing checkpoint in bounty checkpoints, could've failed to spawn or cast"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy Actor and Shrink Array
|
||||
BountyCheckpoints[0]->Active = false;
|
||||
BountyCheckpoints[0]->Destroy();
|
||||
BountyCheckpoints.RemoveAt(0);
|
||||
|
||||
// Set the new checkpoint in pos 0 to be active and listen for it's completion
|
||||
BountyCheckpoints[0]->Active = true;
|
||||
BountyCheckpoints[0]->CompletedCheckpoint.AddDynamic(this, &ABountyClass::IncrementBountyCheckpoint);
|
||||
|
||||
}
|
||||
|
||||
void ABountyClass::CollectRewards_Implementation()
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("The player has gained $%d for completing the bounty!"), RewardMoney);
|
||||
}
|
||||
|
||||
void ABountyClass::UpdateBountyCheckpoints(TMap<int, TSubclassOf<ACheckpointClass>> ReplacementCheckpoints)
|
||||
{
|
||||
if (ReplacementCheckpoints.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("No Replacement Steps found"));
|
||||
return;
|
||||
}
|
||||
|
||||
FActorSpawnParameters SpawnParameters;
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
|
||||
for (auto ReplacementCheckpoint : ReplacementCheckpoints)
|
||||
{
|
||||
BountyCheckpoints[ReplacementCheckpoint.Key]->Destroy();
|
||||
ReplacementCheckpointClass = ReplacementCheckpoint.Value;
|
||||
|
||||
FVector Loc = ReplacementCheckpointClass.GetDefaultObject()->GetCheckpointSpawnTransform().GetLocation();
|
||||
FRotator Rot = ReplacementCheckpointClass.GetDefaultObject()->GetCheckpointSpawnTransform().GetRotation().Rotator();
|
||||
ACheckpointClass* SpawnedCheckpoint = Cast<ACheckpointClass>(GetWorld()->SpawnActor<AActor>(ReplacementCheckpoint.Value, Loc, Rot, SpawnParameters));
|
||||
|
||||
if (SpawnedCheckpoint == nullptr)
|
||||
{
|
||||
UE_LOG(LogTemp, Fatal, TEXT("The new checkpoint hasn't spawned in properly or can't be cast to"));
|
||||
return;
|
||||
}
|
||||
|
||||
BountyCheckpoints[ReplacementCheckpoint.Key] = SpawnedCheckpoint;
|
||||
if (ReplacementCheckpoint.Key == 0)
|
||||
{
|
||||
BountyCheckpoints[ReplacementCheckpoint.Key]->Active = true;
|
||||
BountyCheckpoints[ReplacementCheckpoint.Key]->CompletedCheckpoint.AddDynamic(this, &ABountyClass::IncrementBountyCheckpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,24 +3,140 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CheckpointClass.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "BountyClass.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCompletedFirstCheckpoint)
|
||||
|
||||
UCLASS()
|
||||
class ENDLESSVENDETTA_API ABountyClass : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
ABountyClass();
|
||||
// Used to temp store value of incoming replacement checkpoint class
|
||||
TSubclassOf<ACheckpointClass> ReplacementCheckpointClass;
|
||||
|
||||
bool BountyStarted = false;
|
||||
|
||||
protected:
|
||||
// ------- Properties Set in Editor --------------
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
|
||||
TArray<TSubclassOf<ACheckpointClass>> CheckpointsToSpawn;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
|
||||
int RewardMoney = 0;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
|
||||
FString BountyTitle;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
|
||||
FString BountyDesc;
|
||||
// -----------------------------------------------
|
||||
|
||||
bool Completed = false;
|
||||
|
||||
/**
|
||||
* Default is 2 as final step in most Bounties is to return to ship,
|
||||
* which can't be completed. Change to 1 if that's not the case.
|
||||
*/
|
||||
int MinCPsRequiredForCompletion = 2;
|
||||
|
||||
// Spawned in Checkpoints for this Bounty
|
||||
TArray<ACheckpointClass*> BountyCheckpoints;
|
||||
|
||||
// Spawns and stores this Bounties Checkpoints in order
|
||||
void SpawnCheckpoints();
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
public:
|
||||
// Broadcast when first checkpoint from this bounty is completed
|
||||
FCompletedFirstCheckpoint CompletedFirstCheckpoint;
|
||||
|
||||
// ------ Getters for Bounty and Checkpoint Properties ------
|
||||
bool IsCompleted()
|
||||
{
|
||||
return Completed;
|
||||
}
|
||||
|
||||
FString GetBountyTitle()
|
||||
{
|
||||
return BountyTitle;
|
||||
}
|
||||
|
||||
FString GetBountyDesc()
|
||||
{
|
||||
return BountyDesc;
|
||||
}
|
||||
|
||||
FVector GetCheckpointLocation()
|
||||
{
|
||||
if (BountyCheckpoints.IsEmpty() || BountyCheckpoints[0] == nullptr)
|
||||
{
|
||||
return FVector(0, 0, 0);
|
||||
}
|
||||
|
||||
return BountyCheckpoints[0]->GetCheckpointSpawnTransform().GetLocation();
|
||||
}
|
||||
|
||||
FVector GetActiveWaypointLocation()
|
||||
{
|
||||
if (BountyCheckpoints.IsEmpty() || BountyCheckpoints[0] == nullptr)
|
||||
{
|
||||
return FVector(0, 0, 0);
|
||||
}
|
||||
|
||||
return BountyCheckpoints[0]->GetWaypointLoc();
|
||||
}
|
||||
|
||||
UTexture2D* GetActiveWaypointIcon()
|
||||
{
|
||||
if (BountyCheckpoints.IsEmpty() || BountyCheckpoints[0] == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return BountyCheckpoints[0]->GetWaypointIcon();
|
||||
}
|
||||
|
||||
FString GetCheckpointDescription()
|
||||
{
|
||||
if (BountyCheckpoints.IsEmpty() || BountyCheckpoints[0] == nullptr)
|
||||
{
|
||||
return FString("No more Bounty checkpoints, check BountyClass.h GetCheckpointDescription()");
|
||||
}
|
||||
|
||||
return BountyCheckpoints[0]->GetCheckpointDesc();
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// Sets default values for this actor's properties
|
||||
ABountyClass();
|
||||
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
// Called when a checkpoint is completed, handles moving onto next checkpoint and discarding the old one
|
||||
UFUNCTION()
|
||||
virtual void IncrementBountyCheckpoint();
|
||||
|
||||
// Collect Money in C++, any other special reward will be implemented in BP if neccessary
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void CollectRewards();
|
||||
|
||||
void DestroyReturnToShipStep()
|
||||
{
|
||||
if (BountyCheckpoints.Num() > 1)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Didn't Destroy final step as more than one steps still left in Bounty"));
|
||||
}
|
||||
|
||||
BountyCheckpoints[0]->Destroy();
|
||||
}
|
||||
|
||||
// Called by Bounty Director, replaces specified checkpoints to alter Bounty when player completes a side bounty
|
||||
void UpdateBountyCheckpoints(TMap<int, TSubclassOf<ACheckpointClass>> ReplacementCheckpoints);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user