Merge pull request #2 from Games-Academy-Student-Work-23-24/dev

Dev
This commit is contained in:
RAFAL SWIERCZEK 2023-10-16 16:54:13 +01:00 committed by GitHub Enterprise
commit 370cff50c9
57 changed files with 690 additions and 233 deletions

View File

@ -4,7 +4,7 @@
+EditProfiles=(Name="Trigger",CustomResponses=((Channel=Projectile, Response=ECR_Ignore)))
[/Script/EngineSettings.GameMapsSettings]
EditorStartupMap=/Game/FirstPerson/Maps/GunMechanicTester.GunMechanicTester
EditorStartupMap=/Game/LevelPrototyping/Scenes/TutorialHit.TutorialHit
LocalMapOptions=
TransitionMap=None
bUseSplitscreen=True
@ -13,7 +13,7 @@ ThreePlayerSplitscreenLayout=FavorTop
FourPlayerSplitscreenLayout=Grid
bOffsetPlayerGamepadIds=False
GameInstanceClass=/Script/Engine.GameInstance
GameDefaultMap=/Game/FirstPerson/Maps/GunMechanicTester.GunMechanicTester
GameDefaultMap=/Game/LevelPrototyping/Scenes/TutorialHit.TutorialHit
ServerDefaultMap=/Engine/Maps/Entry.Entry
GlobalDefaultGameMode=/Game/FirstPerson/GunMechanicWorld.GunMechanicWorld_C
GlobalDefaultServerGameMode=None

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -25,7 +25,6 @@ AAICharacter::AAICharacter()
void AAICharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
@ -54,31 +53,7 @@ float AAICharacter::TakeDamage(const float DamageAmount, FDamageEvent const& Dam
CurrentHealth = 0;
UE_LOG(LogTemp, Display, TEXT("%s is dead"), *CharacterName.ToString());
/*const AAI_EnemyController* AIController = Cast<AAI_EnemyController>(GetController());
AIController->GetBrainComponent()->StopLogic(" is dead");*/
this->Tags.Add(FName("Dead"));
//Ragdoll
DetachFromControllerPendingDestroy();
UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore);
GetMesh()->SetCollisionProfileName(TEXT("Ragdoll"));
SetActorEnableCollision(true);
GetMesh()->SetAllBodiesSimulatePhysics(true);
GetMesh()->SetSimulatePhysics(true);
GetMesh()->WakeAllRigidBodies();
GetMesh()->bBlendPhysics = true;
if (UCharacterMovementComponent* CharacterComp = Cast<UCharacterMovementComponent>(GetMovementComponent()))
{
CharacterComp->StopMovementImmediately();
CharacterComp->DisableMovement();
CharacterComp->SetComponentTickEnabled(false);
}
SetLifeSpan(30.0f);
OnDeath();
}
return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}
@ -98,3 +73,31 @@ void AAICharacter::SetupStimuliSourceComponent()
}
}
void AAICharacter::OnDeath()
{
/*const AAI_EnemyController* AIController = Cast<AAI_EnemyController>(GetController());
AIController->GetBrainComponent()->StopLogic(" is dead");*/
this->Tags.Add(FName("Dead"));
//Ragdoll
DetachFromControllerPendingDestroy();
UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore);
GetMesh()->SetCollisionProfileName(TEXT("Ragdoll"));
SetActorEnableCollision(true);
GetMesh()->SetAllBodiesSimulatePhysics(true);
GetMesh()->SetSimulatePhysics(true);
GetMesh()->WakeAllRigidBodies();
GetMesh()->bBlendPhysics = true;
if (UCharacterMovementComponent* CharacterComp = Cast<UCharacterMovementComponent>(GetMovementComponent()))
{
CharacterComp->StopMovementImmediately();
CharacterComp->DisableMovement();
CharacterComp->SetComponentTickEnabled(false);
}
SetLifeSpan(30.0f);
}

View File

@ -35,6 +35,8 @@ protected:
class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent;
void SetupStimuliSourceComponent();
virtual void OnDeath();
public:
// Called every frame
virtual void Tick(float DeltaTime) override;

View File

@ -74,3 +74,8 @@ void AAIControlHub::SetPlayerLastKnownLocation(FVector Location)
PlayerLastKnownLocation = Location;
}
}
void AAIControlHub::RemoveEnemyActor(AEnemyCharacter* EnemyActor)
{
EnemyActors.Remove(EnemyActor);
}

View File

@ -35,6 +35,7 @@ public:
int GetAlertLevel() const;
void OnAlertLevelChanged();
void SetPlayerLastKnownLocation(FVector Location = FVector(0, 0, 0));
void RemoveEnemyActor(AEnemyCharacter* EnemyActor);
private:
int AlertLevel = 0;

View File

@ -23,6 +23,16 @@ void AEnemyCharacter::BeginPlay()
CharacterName = "Enemy";
}
void AEnemyCharacter::OnDeath()
{
Super::OnDeath();
DelegatedControlHub->AlertLevelEvent.Remove(AlertLevelDelegateHandle);
DelegatedControlHub->HuntPlayerEvent.Remove(HuntPlayerDelegateHandle);
AlertLevelDelegateHandle.Reset();
HuntPlayerDelegateHandle.Reset();
DelegatedControlHub->RemoveEnemyActor(this);
}
// Called every frame
void AEnemyCharacter::Tick(float DeltaTime)
{
@ -38,6 +48,8 @@ void AEnemyCharacter::SubscribeToGroupAIEvents(AAIControlHub* ControlHub)
void AEnemyCharacter::SetAlertLevel(const int NewAlertLevel) const
{
if (!IsValid(this)) return;
if (!IsValid(GetController())) return;
Cast<AAIController>(GetController())->GetBlackboardComponent()->SetValueAsInt("AlertLevel", NewAlertLevel);
}
@ -49,6 +61,8 @@ void AEnemyCharacter::SetLocalAlertLevel(int NewAlertLevel) const
void AEnemyCharacter::HuntPlayer(FVector PlayerLastKnownLocation)
{
if (!IsValid(this)) return;
if (!IsValid(GetController())) return;
SetAlertLevel(2);
Cast<AAIController>(GetController())->GetBlackboardComponent()->SetValueAsVector("LastKnownLocation", PlayerLastKnownLocation);
}

View File

@ -21,6 +21,7 @@ protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
class AAIControlHub* DelegatedControlHub;
virtual void OnDeath() override;
public:
// Called every frame

View File

@ -19,7 +19,7 @@ EBTNodeResult::Type UBTTask_AttackPlayer::ExecuteTask(UBehaviorTreeComponent& Ow
{
FVector const Origin = AIController->GetPawn()->GetActorLocation();
FVector const PlayerLocation = Blackboard->GetValueAsVector("TargetLocation");
DrawDebugLine(GetWorld(), Origin, PlayerLocation, FColor::Green, false, 1.f, 0, 1.f);
//DrawDebugLine(GetWorld(), Origin, PlayerLocation, FColor::Green, false, 1.f, 0, 1.f);
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
return EBTNodeResult::Succeeded;

View File

@ -61,7 +61,7 @@ void ABountyClass::IncrementBountyCheckpoint()
}
// Bounty Completion Condition
if (BountyCheckpoints.Num() <= MinCPsRequiredForCompletion)
if (BountyCheckpoints.Num() <= 1)
{
Completed = true;
BountyCheckpoints[0]->Active = false;
@ -93,38 +93,6 @@ 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);
}
}
}

View File

@ -36,12 +36,6 @@ protected:
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;
@ -61,7 +55,7 @@ public:
{
return Completed;
}
FString GetBountyTitle()
{
return BountyTitle;
@ -72,6 +66,11 @@ public:
return BountyDesc;
}
int GetBountyrewardMoney()
{
return RewardMoney;
}
FVector GetCheckpointLocation()
{
if (BountyCheckpoints.IsEmpty() || BountyCheckpoints[0] == nullptr)
@ -126,17 +125,4 @@ public:
// 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);
};

View File

@ -3,6 +3,7 @@
#include "BountyDirector.h"
#include "Blueprint/UserWidget.h"
#include "Components/ArrowComponent.h"
// Sets default values
@ -34,16 +35,8 @@ void ABountyDirector::BeginPlay()
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()
@ -61,27 +54,22 @@ void ABountyDirector::SpawnBountyAndItsSideBounties()
const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::SnapToTarget, true);
BountyActor->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules);
ActiveBounty = Cast<ABountyClass>(BountyActor);
ActiveBounty = Cast<AMainBountyClass>(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)
ActiveSideBounties.Reset();
for (TSubclassOf<ASideBountyClass> SideBountyClass : ActiveBounty->GetSideBountiesToSpawn())
{
if (SideBountyClassArray.Num() <= CurrentSideBountyIndex || !IsValid(SideBountyClassArray[CurrentSideBountyIndex])) continue;
AActor* SideBountyActor = GetWorld()->SpawnActor<AActor>(SideBountyClassArray[CurrentSideBountyIndex], PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams);
if (!IsValid(SideBountyClass)) continue;
AActor* SideBountyActor = GetWorld()->SpawnActor<AActor>(SideBountyClass, PlayerChar->GetActorLocation(), PlayerChar->GetActorRotation(), SpawnParams);
SideBountyActor->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules);
ASideBountyClass* SideBounty = Cast<ASideBountyClass>(SideBountyActor);
SideBounty->AttachToComponent(BountyAttachmentPoint, AttachmentTransformRules);
ActiveSideBounties[ActiveSideBountyIndex] = SideBounty;
SideBounty->ActiveSBC_Index = ActiveSideBountyIndex;
ActiveSideBounties[ActiveSideBountyIndex]->CompletedSideBounty.AddDynamic(this, &ABountyDirector::SideBountyCompleted);
if (!IsValid(SideBounty)) UE_LOG(LogTemp, Fatal, TEXT("A SideBounty for %s has been set to a wrong type"), *ActiveBounty->GetBountyTitle());
int i = ActiveSideBounties.Add(SideBounty);
ActiveSideBounties[i]->CompletedSideBounty.AddDynamic(this, &ABountyDirector::EarnFavours);
// ONCE AGAIN WHEN MARCEL STOPS PLAYING WITH THE CHARACTER, ADD THIS SIDE BOUNTY TO PLAYERS ARRAY OF ACTIVE BOUNTIES!!!!!
ActiveSideBountyIndex++;
}
}
@ -97,28 +85,21 @@ 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()
@ -132,21 +113,169 @@ void ABountyDirector::DestroyActiveSideBounties()
SideBounty->DestroyCheckpoints();
SideBounty->Destroy();
}
UpdateBountyDisplay();
}
void ABountyDirector::SideBountyCompleted(int SideBountyIndex)
// ----------- Favour Shop ---------------
void ABountyDirector::EarnFavours(int FavoursEarned)
{
UE_LOG(LogTemp,Warning,TEXT("Updating Main Bounties Checkpoints"));
ActiveBounty->UpdateBountyCheckpoints(ActiveSideBounties[SideBountyIndex]->GetReplacementCheckpoints());
Favours += FavoursEarned;
}
// WHEN MARCEL STOPS PLAYING WITH PLAYER CHAR, REMOVE THIS SIDE BOUNTY FROM ACTIVE BOUNTIES
ActiveSideBounties[SideBountyIndex]->CollectRewards();
ActiveSideBounties[SideBountyIndex]->DestroyCheckpoints();
ActiveSideBounties[SideBountyIndex]->Destroy();
UpdateBountyDisplay();
void ABountyDirector::BuyCustomBountyAlteration_1()
{
if (!IsValid(ActiveBounty)) return;
int Cost = ActiveBounty->GetCustomBountyAlteration_1_Cost();
if (Cost == 0 || Favours < Cost || ActiveBounty->ActivatedCBA_1) return;
Favours -= Cost;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivatedCBA_1 = true;
ActiveBounty->ActivateCustomBountyAlteration_1();
}
void ABountyDirector::BuyCustomBountyAlteration_2()
{
if (!IsValid(ActiveBounty)) return;
int Cost = ActiveBounty->GetCustomBountyAlteration_2_Cost();
if (Cost == 0 || Favours < Cost || ActiveBounty->ActivatedCBA_2) return;
Favours -= Cost;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivatedCBA_2 = true;
ActiveBounty->ActivateCustomBountyAlteration_2();
}
void ABountyDirector::BuyCustomBountyAlteration_3()
{
if (!IsValid(ActiveBounty)) return;
int Cost = ActiveBounty->GetCustomBountyAlteration_3_Cost();
if (Cost == 0 || Favours < Cost || ActiveBounty->ActivatedCBA_3) return;
Favours -= Cost;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivatedCBA_3 = true;
ActiveBounty->ActivateCustomBountyAlteration_3();
}
void ABountyDirector::BuyAmmoDrop()
{
if (!IsValid(ActiveBounty)) return;
if (Favours < 1 || ActiveBounty->ActivateAmmoDrops) return;
Favours--;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivateAmmoDrops = true;
ActiveBounty->SpawnAmmoDrops();
}
void ABountyDirector::BuyHealthDrop()
{
if (!IsValid(ActiveBounty)) return;
if (Favours < 1 || ActiveBounty->ActivatedHealthDrops) return;
Favours--;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivatedHealthDrops = true;
ActiveBounty->SpawnHealthDrops();
}
void ABountyDirector::BuyEnemyRadio()
{
if (!IsValid(ActiveBounty)) return;
if (Favours < 1 || ActiveBounty->ActivatedRadio) return;
Favours--;
PC_Display->UpdateFavourCount(Favours);
ActiveBounty->ActivatedRadio = true;
ActiveBounty->ActivateEnemyRadio();
}
void ABountyDirector::BuyFavours()
{
if (PlayerChar->Money < FavourCost) return;
PlayerChar->Money -= FavourCost;
Favours++;
PC_Display->UpdateFavourCount(Favours);
}
// ----------- PC Display ---------------
void ABountyDirector::Interact()
{
UpdateBountyProgression();
FInputModeUIOnly InputMode;
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
PC_DisplayWidget = CreateWidget<UUserWidget>(GetWorld(), PC_DisplayWidgetClass);
PC_DisplayWidget->AddToViewport(3);
PlayerController->SetInputMode(InputMode);
PlayerController->bShowMouseCursor = true;
PlayerController->bEnableClickEvents = true;
PlayerController->bEnableMouseOverEvents = true;
PC_Display = Cast<UPC_Display>(PC_DisplayWidget);
bool GameOver = !IsValid(ActiveBounty);
PC_Display->PC_Display_Info.IsGameOver = GameOver;
PC_Display->LogoutFromBountyDirectorPC.AddDynamic(this, &ABountyDirector::DestroyBountyDirectorPCWidget);
if (GameOver)
{
PC_Display->LoadOS();
return;
}
// Info about main bounty
PC_Display->PC_Display_Info.MB_Title = GetBountyTitle();
PC_Display->PC_Display_Info.MB_Desc = GetBountyDescription();
PC_Display->PC_Display_Info.MB_Reward = GetBountyReward();
// Info about side bounties
PC_Display->PC_Display_Info.SB_Title.Reset();
PC_Display->PC_Display_Info.SB_Icon.Reset();
PC_Display->PC_Display_Info.SB_Desc.Reset();
PC_Display->PC_Display_Info.SB_Reward.Reset();
for (ASideBountyClass* SideBounty : ActiveSideBounties)
{
if (!IsValid(SideBounty) || SideBounty->IsCompleted()) continue;
PC_Display->PC_Display_Info.SB_Title.Add(SideBounty->GetBountyTitle());
PC_Display->PC_Display_Info.SB_Icon.Add(SideBounty->GetActiveWaypointIcon());
PC_Display->PC_Display_Info.SB_Desc.Add(SideBounty->GetBountyDesc());
PC_Display->PC_Display_Info.SB_Reward.Add(SideBounty->GetRewardInFavours());
}
// Info about main bounty alterations
PC_Display->PC_Display_Info.CustomBountyAlteration_Desc.Reset();
PC_Display->PC_Display_Info.CustomBountyAlteration_Cost.Reset();
PC_Display->PC_Display_Info.CustomBountyAlteration_Desc.Add(ActiveBounty->GetCustomBountyAlteration_1_Description());
PC_Display->PC_Display_Info.CustomBountyAlteration_Desc.Add(ActiveBounty->GetCustomBountyAlteration_2_Description());
PC_Display->PC_Display_Info.CustomBountyAlteration_Desc.Add(ActiveBounty->GetCustomBountyAlteration_3_Description());
PC_Display->PC_Display_Info.CustomBountyAlteration_Cost.Add(ActiveBounty->GetCustomBountyAlteration_1_Cost());
PC_Display->PC_Display_Info.CustomBountyAlteration_Cost.Add(ActiveBounty->GetCustomBountyAlteration_2_Cost());
PC_Display->PC_Display_Info.CustomBountyAlteration_Cost.Add(ActiveBounty->GetCustomBountyAlteration_3_Cost());
PC_Display->PC_Display_Info.PlayersFavourAmount = Favours;
// Button Delegates
PC_Display->BuyCba_1.AddDynamic(this, &ABountyDirector::BuyCustomBountyAlteration_1);
PC_Display->BuyCba_2.AddDynamic(this, &ABountyDirector::BuyCustomBountyAlteration_2);
PC_Display->BuyCba_3.AddDynamic(this, &ABountyDirector::BuyCustomBountyAlteration_3);
PC_Display->BuyAmmoDrop.AddDynamic(this, &ABountyDirector::BuyAmmoDrop);
PC_Display->BuyHealthDrop.AddDynamic(this, &ABountyDirector::BuyHealthDrop);
PC_Display->BuyRadio.AddDynamic(this, &ABountyDirector::BuyEnemyRadio);
PC_Display->BuyFavour.AddDynamic(this, &ABountyDirector::BuyFavours);
PC_Display->LoadOS();
}
void ABountyDirector::DestroyBountyDirectorPCWidget()
{
if (IsValid(PC_DisplayWidget)) PC_DisplayWidget->RemoveFromParent();
FInputModeGameOnly InputMode;
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
PlayerController->SetInputMode(InputMode);
PlayerController->bShowMouseCursor = false;
PlayerController->bEnableClickEvents = false;
PlayerController->bEnableMouseOverEvents = false;
}

View File

@ -3,14 +3,16 @@
#pragma once
#include "CoreMinimal.h"
#include "BountyClass.h"
#include "MainBountyClass.h"
#include "SideBountyClass.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "EndlessVendetta/InteractableActor.h"
#include "EndlessVendetta/UserWidgets/PC_Display.h"
#include "GameFramework/Actor.h"
#include "BountyDirector.generated.h"
UCLASS()
class ENDLESSVENDETTA_API ABountyDirector : public AActor
class ENDLESSVENDETTA_API ABountyDirector : public AInteractableActor
{
GENERATED_BODY()
@ -20,48 +22,76 @@ class ENDLESSVENDETTA_API ABountyDirector : public AActor
UArrowComponent* BountyAttachmentPoint;
// Ordered Array of Main Bounties
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<TSubclassOf<ABountyClass>> BountyClassArray;
UPROPERTY(EditDefaultsOnly, Category = "Bounty Director")
TArray<TSubclassOf<AMainBountyClass>> BountyClassArray;
// Ordered Array of Side Bounties, in three's
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<TSubclassOf<ASideBountyClass>> SideBountyClassArray;
UPROPERTY(EditDefaultsOnly, Category = "Bounty Director")
int FavourCost = 500;
UPROPERTY(EditDefaultsOnly, Category = "Bounty Director")
TSubclassOf<UPC_Display> PC_DisplayWidgetClass;
UUserWidget* PC_DisplayWidget;
UPC_Display* PC_Display;
int CurrentBountyIndex = 0;
TArray<int> CurrentSideBountyIndexes;
UPROPERTY(VisibleAnywhere, Category = "Bounty")
ABountyClass* ActiveBounty;
AMainBountyClass* 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();
// Opens up Bounty Director PC Interface
void Interact() override;
protected:
int Favours = 20;
// 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();
UFUNCTION()
void DestroyBountyDirectorPCWidget();
// Listens for when a side bounty is completed
UFUNCTION()
void EarnFavours(int FavoursEarned);
// -------- Buy Buttons --------
UFUNCTION()
void BuyCustomBountyAlteration_1();
UFUNCTION()
void BuyCustomBountyAlteration_2();
UFUNCTION()
void BuyCustomBountyAlteration_3();
UFUNCTION()
void BuyAmmoDrop();
UFUNCTION()
void BuyHealthDrop();
UFUNCTION()
void BuyEnemyRadio();
UFUNCTION()
void BuyFavours();
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
@ -70,29 +100,24 @@ public:
ABountyDirector();
// ------ Getters ------
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetBountyTitle()
{
return !IsValid(ActiveBounty) ? FString("N/A") : ActiveBounty->GetBountyTitle();
return !IsValid(ActiveBounty) ? FString("") : ActiveBounty->GetBountyTitle();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
UTexture2D* GetBountyIcon()
{
return !IsValid(ActiveBounty) ? nullptr : ActiveBounty->GetActiveWaypointIcon();
}
FString GetBountyDescription()
{
return !IsValid(ActiveBounty) ? FString("N/A") : ActiveBounty->GetBountyDesc();
return !IsValid(ActiveBounty) ? FString("") : ActiveBounty->GetBountyDesc();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetSideBountyTitle(int SideBountyIndex)
int GetBountyReward()
{
return (SideBountyIndex > 2 || SideBountyIndex < 0 || !IsValid(ActiveSideBounties[SideBountyIndex])) ? FString("N/A") : ActiveSideBounties[SideBountyIndex]->GetBountyTitle();
return !IsValid(ActiveBounty) ? 0 : ActiveBounty->GetBountyrewardMoney();
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetSideBountyDescription(int SideBountyIndex)
{
return (SideBountyIndex > 2 || SideBountyIndex < 0 || !IsValid(ActiveSideBounties[SideBountyIndex])) ? FString("N/A") : ActiveSideBounties[SideBountyIndex]->GetBountyDesc();
}
};

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainBountyClass.h"
void AMainBountyClass::SpawnAmmoDrops()
{
UE_LOG(LogTemp, Display, TEXT("Bought Ammo Drops, but its not implemented yet"));
// FActorSpawnParameters SpawnParameters;
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
// for (FTransform Spawn : AmmoDropSpawnTransforms)
// {
// GetWorld()->SpawnActor<AActor>(AmmoDropClass, Spawn.GetLocation(), Spawn.GetRotation().Rotator(), SpawnParameters);
// }
}
void AMainBountyClass::SpawnHealthDrops()
{
UE_LOG(LogTemp, Display, TEXT("Bought Health Drops, but its not implemented yet"));
// FActorSpawnParameters SpawnParameters;
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
// for (FTransform Spawn : HealthDropSpawnTransforms)
// {
// GetWorld()->SpawnActor<AActor>(HealthDropClass, Spawn.GetLocation(), Spawn.GetRotation().Rotator(), SpawnParameters);
// }
}

View File

@ -0,0 +1,122 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BountyClass.h"
#include "SideBountyClass.h"
#include "MainBountyClass.generated.h"
/**
*
*/
UCLASS()
class ENDLESSVENDETTA_API AMainBountyClass : public ABountyClass
{
GENERATED_BODY()
protected:
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<TSubclassOf<ASideBountyClass>> SideBountiesToSpawn;
// ---------------- Bounty Alterations ----------------
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<FString> CustomBountyAlteration_Description;
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<int> CustomBountyAlteration_Cost;
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<FTransform> AmmoDropSpawnTransforms;
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TSubclassOf<AActor> AmmoDropClass;
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TArray<FTransform> HealthDropSpawnTransforms;
UPROPERTY(EditDefaultsOnly, Category = "Bounty")
TSubclassOf<AActor> HealthDropClass;
bool HasEnemyRadio = false;
public:
TArray<TSubclassOf<ASideBountyClass>> GetSideBountiesToSpawn()
{
return SideBountiesToSpawn;
}
// ------------- Custom Bounty Alterations -------------
UFUNCTION(BlueprintImplementableEvent, Category = "Bounty")
void ActivateCustomBountyAlteration_1();
UFUNCTION(BlueprintImplementableEvent, Category = "Bounty")
void ActivateCustomBountyAlteration_2();
UFUNCTION(BlueprintImplementableEvent, Category = "Bounty")
void ActivateCustomBountyAlteration_3();
bool ActivatedCBA_1 = false;
bool ActivatedCBA_2 = false;
bool ActivatedCBA_3 = false;
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetCustomBountyAlteration_1_Description()
{
return CustomBountyAlteration_Description.IsEmpty() ? FString("") : CustomBountyAlteration_Description[0];
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetCustomBountyAlteration_2_Description()
{
return CustomBountyAlteration_Description.Num() <= 1 ? FString("") : CustomBountyAlteration_Description[1];
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
FString GetCustomBountyAlteration_3_Description()
{
return CustomBountyAlteration_Description.Num() <= 2 ? FString("") : CustomBountyAlteration_Description[2];
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
int GetCustomBountyAlteration_1_Cost()
{
return CustomBountyAlteration_Cost.IsEmpty() ? 0 : CustomBountyAlteration_Cost[0];
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
int GetCustomBountyAlteration_2_Cost()
{
return CustomBountyAlteration_Cost.Num() <= 1 ? 0 : CustomBountyAlteration_Cost[1];
}
UFUNCTION(BlueprintCallable, Category = "Bounty")
int GetCustomBountyAlteration_3_Cost()
{
return CustomBountyAlteration_Cost.Num() <= 2 ? 0 : CustomBountyAlteration_Cost[2];
}
// ------------- Simple Bounty Alterations -------------
void SpawnAmmoDrops();
bool ActivateAmmoDrops = false;
void SpawnHealthDrops();
bool ActivatedHealthDrops = false;
void ActivateEnemyRadio()
{
UE_LOG(LogTemp, Display, TEXT("Bought Radio, but it's not implemented yet"));
HasEnemyRadio = true;
}
bool ActivatedRadio = false;
// Concerned Enemies will call this function, if true, play funny poop voice line and stop enemies from being concerned
bool CheckIfHasEnemyRadio()
{
return HasEnemyRadio;
};
};

View File

@ -6,8 +6,7 @@
void ASideBountyClass::BeginPlay()
{
Super::BeginPlay();
MinCPsRequiredForCompletion = 1;
}
void ASideBountyClass::IncrementBountyCheckpoint()
@ -16,8 +15,7 @@ void ASideBountyClass::IncrementBountyCheckpoint()
if (Completed)
{
CompletedSideBounty.Broadcast(ActiveSBC_Index);
CompletedSideBounty.Broadcast(FavoursEarnedForCompletion);
}
}

View File

@ -6,30 +6,26 @@
#include "BountyClass.h"
#include "SideBountyClass.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCompletedSideBounty, int, SB_Index);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCompletedSideBounty, int, FavoursEarned);
UCLASS()
class ENDLESSVENDETTA_API ASideBountyClass : public ABountyClass
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, Category = "Side Bounty")
TMap<int, TSubclassOf<ACheckpointClass>> ReplacementCheckpoints;
protected:
UPROPERTY(EditDefaultsOnly, Category = "Side Bounty")
int FavoursEarnedForCompletion = 1;
virtual void BeginPlay() override;
public:
FCompletedSideBounty CompletedSideBounty;
int ActiveSBC_Index;
TMap<int, TSubclassOf<ACheckpointClass>> GetReplacementCheckpoints()
{
return ReplacementCheckpoints;
}
virtual void IncrementBountyCheckpoint() override;
void DestroyCheckpoints();
int GetRewardInFavours()
{
return FavoursEarnedForCompletion;
}
};

View File

@ -6,6 +6,7 @@
#include "Components/CapsuleComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InteractableActor.h"
#include "AI/EnemyCharacter.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Kismet/GameplayStatics.h"
@ -102,9 +103,29 @@ void AEndlessVendettaCharacter::SetupPlayerInputComponent(class UInputComponent*
//Crouching
EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::SetCrouch);
EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AEndlessVendettaCharacter::SetUnCrouch);
//Interacting
EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::Interact);
}
}
void AEndlessVendettaCharacter::Interact()
{
FHitResult OutHit;
FCollisionQueryParams QueryParams = FCollisionQueryParams::DefaultQueryParam;
QueryParams.AddIgnoredActor(this);
FVector LT_Start = FirstPersonCameraComponent->GetComponentLocation();
FVector LT_End = LT_Start + (FirstPersonCameraComponent->GetForwardVector() * InteractionRange);
if (!GetWorld()->LineTraceSingleByChannel(OutHit, LT_Start, LT_End, ECC_Camera, QueryParams)) return;
AActor* HitActor = OutHit.GetActor();
AInteractableActor* InteractableActor = Cast<AInteractableActor>(HitActor);
if (!IsValid(InteractableActor)) return;
InteractableActor->Interact();
}
void AEndlessVendettaCharacter::SetCrouch()
{
Crouch();

View File

@ -68,6 +68,9 @@ class AEndlessVendettaCharacter : public ACharacter
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* CrouchAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* InteractAction;
public:
AEndlessVendettaCharacter();
@ -86,6 +89,8 @@ protected:
AGadgetManager* GadgetManager;
public:
int Money = 2000;
/** Look Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* LookAction;
@ -144,6 +149,9 @@ protected:
void EquipPrimary();
void EquipSecondary();
UPROPERTY(EditDefaultsOnly, Category = "Interaction")
float InteractionRange = 250;
void Interact();
protected:
// APawn interface

View File

@ -0,0 +1,33 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "InteractableActor.h"
// Sets default values
AInteractableActor::AInteractableActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void AInteractableActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AInteractableActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AInteractableActor::Interact()
{
UE_LOG(LogTemp, Warning, TEXT("Interacted with %s"), *GetName());
}

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "InteractableActor.generated.h"
UCLASS()
class ENDLESSVENDETTA_API AInteractableActor : public AActor
{
GENERATED_BODY()
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Sets default values for this actor's properties
AInteractableActor();
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void Interact();
};

View File

@ -0,0 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PC_Display.h"

View File

@ -0,0 +1,93 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "PC_Display.generated.h"
USTRUCT(BlueprintType)
struct FPC_Display_Info
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
bool IsGameOver;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
FString MB_Title;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
FString MB_Desc;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
int MB_Reward;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<FString> SB_Title;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<UTexture2D*> SB_Icon;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<FString> SB_Desc;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<int> SB_Reward;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<FString> CustomBountyAlteration_Desc;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
TArray<int> CustomBountyAlteration_Cost;
UPROPERTY(BlueprintReadWrite, Category = "PC_Display_Info")
int PlayersFavourAmount;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FLogoutFromBountyDirectorPC);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyCBA_1);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyCBA_2);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyCBA_3);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyAmmoDrop);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyHealthDrop);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyRadio);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBuyFavour);
UCLASS()
class ENDLESSVENDETTA_API UPC_Display : public UUserWidget
{
GENERATED_BODY()
public:
// Button Delegates
UPROPERTY(BlueprintCallable, Category = PC_Display)
FLogoutFromBountyDirectorPC LogoutFromBountyDirectorPC;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyCBA_1 BuyCba_1;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyCBA_2 BuyCba_2;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyCBA_3 BuyCba_3;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyAmmoDrop BuyAmmoDrop;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyHealthDrop BuyHealthDrop;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyRadio BuyRadio;
UPROPERTY(BlueprintCallable, Category = PC_Display)
FBuyFavour BuyFavour;
// USTRUCT
UPROPERTY(BlueprintReadOnly)
FPC_Display_Info PC_Display_Info;
// Takes USTRUCT and uses its values to fill in widget
UFUNCTION(BlueprintImplementableEvent, Category = "PC_Display")
void LoadOS();
UFUNCTION(BlueprintImplementableEvent, Category = "PC_Display")
void UpdateFavourCount(int NewFavourCount);
};