Make projectiles pooled and use DataAssets

This commit is contained in:
baz 2025-01-13 20:57:08 +00:00
parent 9436d16875
commit 741a41ddfa
36 changed files with 480 additions and 133 deletions

BIN
Content/Gamemode/BP_DefaultGamemode.uasset (Stored with Git LFS)

Binary file not shown.

BIN
Content/Levels/Level.umap (Stored with Git LFS)

Binary file not shown.

BIN
Content/Pickups/C_Pickup.uasset (Stored with Git LFS)

Binary file not shown.

BIN
Content/Pickups/DA_ExamplePickup.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Player/BP_PlayerCharacter.uasset (Stored with Git LFS)

Binary file not shown.

BIN
Content/Weapons/BP_ExampleWeapon.uasset (Stored with Git LFS)

Binary file not shown.

BIN
Content/Weapons/DA_ExampleWeapon.uasset (Stored with Git LFS) Normal file

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.

BIN
Content/Weapons/TestProjectileDataAsset.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Pools.h"
// Add default functionality here for any IPools functions that are not pure virtual.

View File

@ -0,0 +1,31 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Pools.generated.h"
class AObjectPoolManager;
// This class does not need to be modified.
UINTERFACE()
class UPools : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class VAMPIRES_API IPools
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
UFUNCTION(BlueprintNativeEvent)
AObjectPoolManager* GetEnemyObjectPoolManager();
UFUNCTION(BlueprintNativeEvent)
AObjectPoolManager* GetProjectileObjectPoolManager();
};

View File

@ -0,0 +1,7 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Projectilable.h"
// Add default functionality here for any IProjectilable functions that are not pure virtual.

View File

@ -0,0 +1,34 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Projectilable.generated.h"
class UProjectileDataAsset;
// This class does not need to be modified.
UINTERFACE()
class UProjectilable : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class VAMPIRES_API IProjectilable
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
UFUNCTION(BlueprintNativeEvent)
void LoadDataFromDataAsset(UProjectileDataAsset* projectileDataAsset);
UFUNCTION(BlueprintNativeEvent)
void ResetData();
UFUNCTION(BlueprintNativeEvent)
void SetTargetDirection(FVector direction);
};

View File

@ -7,6 +7,7 @@
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "Pickup.generated.h" #include "Pickup.generated.h"
class UPickupDataAsset;
class UTimelineComponent; class UTimelineComponent;
class USphereComponent; class USphereComponent;
class UPaperSpriteComponent; class UPaperSpriteComponent;
@ -17,6 +18,8 @@ class VAMPIRES_API APickup : public AActor
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TObjectPtr<UPickupDataAsset> PickupDataAsset;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
double PickupMovementRange = 500; double PickupMovementRange = 500;

View File

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

View File

@ -0,0 +1,37 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "PickupDataAsset.generated.h"
class UTimelineComponent;
class UPaperSprite;
/**
*
*/
UCLASS(BlueprintType)
class VAMPIRES_API UPickupDataAsset : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
int PickupValue = 1;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
double PickupMovementRange = 500;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
double PickupMovementSpeed = 1000;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
TObjectPtr<UPaperSprite> WeaponSprite = nullptr;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
TObjectPtr<USoundBase> PickupSoundBase = nullptr;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup Properties")
TObjectPtr<UCurveFloat> CurveFloat = nullptr;
};

View File

@ -4,8 +4,13 @@
#include "Projectile.h" #include "Projectile.h"
#include "EnemyCharacter.h" #include "EnemyCharacter.h"
#include "ObjectPoolManager.h"
#include "ProjectileDataAsset.h"
#include "Components/SphereComponent.h" #include "Components/SphereComponent.h"
#include "GameFramework/GameModeBase.h"
#include "GameFramework/ProjectileMovementComponent.h" #include "GameFramework/ProjectileMovementComponent.h"
#include "Interfaces/Pools.h"
#include "Kismet/GameplayStatics.h"
#include "Weapons/ProjectileWeapon.h" #include "Weapons/ProjectileWeapon.h"
// Sets default values // Sets default values
@ -19,6 +24,14 @@ AProjectile::AProjectile()
ProjectileMovement->ProjectileGravityScale = 0.0f; ProjectileMovement->ProjectileGravityScale = 0.0f;
ProjectileMovement->Friction = 0.0f; ProjectileMovement->Friction = 0.0f;
ProjectileMovement->bIsSliding = true; ProjectileMovement->bIsSliding = true;
ProjectileMovement->InitialSpeed = 0;
ProjectileMovement->MaxSpeed = 0;
StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Static Mesh Component"));
StaticMeshComponent->AttachToComponent(SphereComponent, FAttachmentTransformRules::KeepRelativeTransform);
StaticMeshComponent->SetEnableGravity(false);
StaticMeshComponent->SetGenerateOverlapEvents(false);
StaticMeshComponent->SetCollisionProfileName(TEXT("NoCollision"));
} }
// Called when the game starts or when spawned // Called when the game starts or when spawned
@ -27,14 +40,39 @@ void AProjectile::BeginPlay()
Super::BeginPlay(); Super::BeginPlay();
SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AProjectile::OnProjectileBeginOverlap); SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AProjectile::OnProjectileBeginOverlap);
}
void AProjectile::SetActorHiddenInGame(bool bNewHidden)
{
Super::SetActorHiddenInGame(bNewHidden);
if (bNewHidden)
{
ResetData_Implementation();
}
}
void AProjectile::SetTargetDirection_Implementation(FVector direction)
{
SetActorLocation(UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetCharacter()->GetActorLocation());
SetActorRotation(FRotator(0, 0, 0));
TargetDirection = direction;
ProjectileMovement->SetVelocityInLocalSpace(TargetDirection * ProjectileSpeed);
}
void AProjectile::LoadDataFromDataAsset_Implementation(UProjectileDataAsset* projectileDataAsset)
{
ProjectileSpeed = projectileDataAsset->ProjectileSpeed;
StaticMeshComponent->SetStaticMesh(projectileDataAsset->StaticMesh);
ProjectileSpeed = projectileDataAsset->ProjectileSpeed;
ProjectileMovement->InitialSpeed = ProjectileSpeed; ProjectileMovement->InitialSpeed = ProjectileSpeed;
ProjectileMovement->MaxSpeed = ProjectileSpeed; ProjectileMovement->MaxSpeed = ProjectileSpeed;
} }
void AProjectile::SetTargetDirection(FVector direction) void AProjectile::ResetData_Implementation()
{ {
TargetDirection = direction; ProjectileSpeed = NULL;
ProjectileMovement->SetVelocityInLocalSpace(TargetDirection * ProjectileSpeed); StaticMeshComponent->SetStaticMesh(nullptr);
} }
void AProjectile::OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, void AProjectile::OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
@ -56,7 +94,15 @@ void AProjectile::OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedCompon
AProjectileWeapon* ownerWeapon = Cast<AProjectileWeapon>(GetOwner()); AProjectileWeapon* ownerWeapon = Cast<AProjectileWeapon>(GetOwner());
EnemyHealthComponent->TakeDamage(Enemy, ownerWeapon->Damage, nullptr, ownerController, this); EnemyHealthComponent->TakeDamage(Enemy, ownerWeapon->Damage, nullptr, ownerController, this);
OverlappedComponent->GetAttachmentRootActor()->Destroy(); AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
{
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
{
objectPoolManager->ReturnObject(this);
}
}
} }
} }
} }

View File

@ -4,13 +4,15 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "Interfaces/Projectilable.h"
#include "Projectile.generated.h" #include "Projectile.generated.h"
class UProjectileMovementComponent; class UProjectileMovementComponent;
class USphereComponent; class USphereComponent;
class UProjectileDataAsset;
UCLASS() UCLASS()
class VAMPIRES_API AProjectile : public AActor class VAMPIRES_API AProjectile : public AActor, public IProjectilable
{ {
GENERATED_BODY() GENERATED_BODY()
@ -26,7 +28,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite) UPROPERTY(EditAnywhere, BlueprintReadWrite)
float ProjectileSpeed = 500.0f; float ProjectileSpeed = 500.0f;
public: UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent* StaticMeshComponent = nullptr;
// Sets default values for this actor's properties // Sets default values for this actor's properties
AProjectile(); AProjectile();
@ -35,11 +39,17 @@ protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
public: public:
virtual void SetActorHiddenInGame(bool bNewHidden) override;
void SetTargetDirection(FVector direction); virtual void SetTargetDirection_Implementation(FVector direction) override;
virtual void LoadDataFromDataAsset_Implementation(UProjectileDataAsset* projectileDataAsset) override;
virtual void ResetData_Implementation() override;
private: private:
UFUNCTION() UFUNCTION()
void OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, void OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
}; };

View File

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

View File

@ -0,0 +1,23 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "ProjectileDataAsset.generated.h"
/**
*
*/
UCLASS()
class VAMPIRES_API UProjectileDataAsset : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float ProjectileSpeed = 500.0f;
UPROPERTY(EditAnywhere)
TObjectPtr<UStaticMesh> StaticMesh;
};

View File

@ -7,6 +7,7 @@
#include "HealthComponent.h" #include "HealthComponent.h"
#include "ObjectPoolManager.h" #include "ObjectPoolManager.h"
#include "PlayerCharacter.h" #include "PlayerCharacter.h"
#include "Projectile.h"
#include "VampirePlayerController.h" #include "VampirePlayerController.h"
#include "Components/CapsuleComponent.h" #include "Components/CapsuleComponent.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
@ -77,7 +78,7 @@ void AVampireGameMode::SpawnEnemy()
FActorSpawnParameters SpawnParameters; FActorSpawnParameters SpawnParameters;
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
if (AActor* object = GetEnemyObjectPoolManager()->GetObject()) if (AActor* object = GetEnemyObjectPoolManager_Implementation()->GetObject())
{ {
AEnemyCharacter* Actor = Cast<AEnemyCharacter>(object); AEnemyCharacter* Actor = Cast<AEnemyCharacter>(object);
Actor->SetActorTransform(Transform); Actor->SetActorTransform(Transform);
@ -96,11 +97,10 @@ void AVampireGameMode::SpawnEnemy()
{ {
Actor->GetHealthComponent()->OnDeath.AddDynamic(this, &AVampireGameMode::HandleOnEnemyDeath); Actor->GetHealthComponent()->OnDeath.AddDynamic(this, &AVampireGameMode::HandleOnEnemyDeath);
} }
} }
} }
AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager() AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager_Implementation()
{ {
if (EnemyObjectPoolManager == nullptr) if (EnemyObjectPoolManager == nullptr)
{ {
@ -112,6 +112,18 @@ AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager()
return EnemyObjectPoolManager; return EnemyObjectPoolManager;
} }
AObjectPoolManager* AVampireGameMode::GetProjectileObjectPoolManager_Implementation()
{
if (ProjectileObjectPoolManager == nullptr)
{
ProjectileObjectPoolManager = GetWorld()->SpawnActor<AObjectPoolManager>();
TSubclassOf<AActor> projectileTemplate = ProjectileTemplate;
ProjectileObjectPoolManager->InitializeObjectPool(projectileTemplate);
}
return ProjectileObjectPoolManager;
}
void AVampireGameMode::IncrementEnemyDeathCount() void AVampireGameMode::IncrementEnemyDeathCount()
{ {
EnemyDeathCount++; EnemyDeathCount++;

View File

@ -5,8 +5,10 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "HealthComponent.h" #include "HealthComponent.h"
#include "GameFramework/GameMode.h" #include "GameFramework/GameMode.h"
#include "Interfaces/Pools.h"
#include "VampireGameMode.generated.h" #include "VampireGameMode.generated.h"
class AProjectile;
class AObjectPoolManager; class AObjectPoolManager;
class AVampirePlayerController; class AVampirePlayerController;
class APlayerCharacter; class APlayerCharacter;
@ -15,7 +17,7 @@ class AEnemyCharacter;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEnemyDeathCountIncrementDelegate, int, level); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEnemyDeathCountIncrementDelegate, int, level);
UCLASS() UCLASS()
class VAMPIRES_API AVampireGameMode : public AGameMode class VAMPIRES_API AVampireGameMode : public AGameMode, public IPools
{ {
GENERATED_BODY() GENERATED_BODY()
@ -23,6 +25,9 @@ public:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TSubclassOf<AEnemyCharacter> EnemyTemplate; TSubclassOf<AEnemyCharacter> EnemyTemplate;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<AProjectile> ProjectileTemplate;
FOnEnemyDeathCountIncrementDelegate OnEnemyDeathCountIncrementDelegate; FOnEnemyDeathCountIncrementDelegate OnEnemyDeathCountIncrementDelegate;
private: private:
@ -36,6 +41,8 @@ private:
TObjectPtr<AObjectPoolManager> EnemyObjectPoolManager = nullptr; TObjectPtr<AObjectPoolManager> EnemyObjectPoolManager = nullptr;
TObjectPtr<AObjectPoolManager> ProjectileObjectPoolManager = nullptr;
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
@ -49,7 +56,9 @@ public:
UFUNCTION() UFUNCTION()
void IncrementEnemyDeathCount(); void IncrementEnemyDeathCount();
AObjectPoolManager* GetEnemyObjectPoolManager(); virtual AObjectPoolManager* GetEnemyObjectPoolManager_Implementation() override;
virtual AObjectPoolManager* GetProjectileObjectPoolManager_Implementation() override;
protected: protected:
UFUNCTION() UFUNCTION()

View File

@ -6,6 +6,8 @@
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "Weapon.generated.h" #include "Weapon.generated.h"
class UWeaponDataAsset;
UCLASS() UCLASS()
class VAMPIRES_API AWeapon : public AActor class VAMPIRES_API AWeapon : public AActor
{ {
@ -18,6 +20,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon Properties") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon Properties")
float Damage; float Damage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon Properties")
TObjectPtr<UWeaponDataAsset> WeaponDataAsset;
private: private:
FTimerHandle WeaponTimerHandle; FTimerHandle WeaponTimerHandle;
@ -30,7 +35,6 @@ protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
public: public:
UFUNCTION(BlueprintNativeEvent) UFUNCTION(BlueprintNativeEvent)
void FireWeaponAction(); void FireWeaponAction();
virtual void FireWeaponAction_Implementation(); virtual void FireWeaponAction_Implementation();

View File

@ -3,7 +3,11 @@
#include "FireWandWeapon.h" #include "FireWandWeapon.h"
#include "GameFramework/GameModeBase.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
#include "vampires/ObjectPoolManager.h"
#include "vampires/Interfaces/Pools.h"
#include "vampires/Projectile.h" #include "vampires/Projectile.h"
AFireWandWeapon::AFireWandWeapon() AFireWandWeapon::AFireWandWeapon()
@ -19,15 +23,20 @@ void AFireWandWeapon::FireWeaponAction_Implementation()
{ {
Super::FireWeaponAction_Implementation(); Super::FireWeaponAction_Implementation();
if (IsValid(ProjectileTemplate) && OverlappedEnemies.Num() > 0) if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
{ {
FActorSpawnParameters actorSpawnParameters; AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
actorSpawnParameters.Owner = this;
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
actorSpawnParameters); {
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
{
AActor* projectile = objectPoolManager->GetObject();
if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
{
IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
projectile->SetOwner(this);
AActor* target = OverlappedEnemies[FMath::RandRange(0, OverlappedEnemies.Num() - 1)]; AActor* target = OverlappedEnemies[FMath::RandRange(0, OverlappedEnemies.Num() - 1)];
FVector direction = UKismetMathLibrary::GetDirectionUnitVector( FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
@ -35,6 +44,9 @@ void AFireWandWeapon::FireWeaponAction_Implementation()
direction.Z = 0.0; direction.Z = 0.0;
direction.Normalize(); direction.Normalize();
projectile->SetTargetDirection(direction); IProjectilable::Execute_SetTargetDirection(projectile, direction);
}
}
}
} }
} }

View File

@ -3,11 +3,14 @@
#include "GunWeapon.h" #include "GunWeapon.h"
#include "GameFramework/GameModeBase.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
#include "vampires/ObjectPoolManager.h"
#include "vampires/PlayerCharacter.h" #include "vampires/PlayerCharacter.h"
#include "vampires/Projectile.h" #include "vampires/Projectile.h"
#include "vampires/VampirePlayerController.h" #include "vampires/VampirePlayerController.h"
#include "vampires/Interfaces/Pools.h"
AGunWeapon::AGunWeapon() AGunWeapon::AGunWeapon()
{ {
@ -22,12 +25,19 @@ void AGunWeapon::FireWeaponAction_Implementation()
{ {
Super::FireWeaponAction_Implementation(); Super::FireWeaponAction_Implementation();
if (IsValid(ProjectileTemplate)) if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
{
AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
{
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
{ {
FVector2d ViewportSize; FVector2d ViewportSize;
GEngine->GameViewport->GetViewportSize(ViewportSize); GEngine->GameViewport->GetViewportSize(ViewportSize);
APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0)); APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(
UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
AVampirePlayerController* PlayerController = Cast<AVampirePlayerController>( AVampirePlayerController* PlayerController = Cast<AVampirePlayerController>(
UGameplayStatics::GetPlayerController(PlayerCharacter, 0)); UGameplayStatics::GetPlayerController(PlayerCharacter, 0));
@ -39,7 +49,8 @@ void AGunWeapon::FireWeaponAction_Implementation()
PlayerController->DeprojectScreenPositionToWorld(0, 0, TopLeft, TopLeftDir); PlayerController->DeprojectScreenPositionToWorld(0, 0, TopLeft, TopLeftDir);
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, 0, TopRight, TopRightDir); PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, 0, TopRight, TopRightDir);
PlayerController->DeprojectScreenPositionToWorld(0, ViewportSize.Y, BottomLeft, BottomLeftDir); PlayerController->DeprojectScreenPositionToWorld(0, ViewportSize.Y, BottomLeft, BottomLeftDir);
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, ViewportSize.Y, BottomRight, BottomRightDir); PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, ViewportSize.Y, BottomRight,
BottomRightDir);
FVector actorLocation = GetActorLocation(); FVector actorLocation = GetActorLocation();
TopLeft.Z = actorLocation.Z; TopLeft.Z = actorLocation.Z;
@ -47,25 +58,25 @@ void AGunWeapon::FireWeaponAction_Implementation()
BottomLeft.Z = actorLocation.Z; BottomLeft.Z = actorLocation.Z;
BottomRight.Z = actorLocation.Z; BottomRight.Z = actorLocation.Z;
FActorSpawnParameters actorSpawnParameters; AActor* projectile = objectPoolManager->GetObject();
actorSpawnParameters.Owner = this; SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopLeft));
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; projectile = objectPoolManager->GetObject();
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot; SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopRight));
projectile = objectPoolManager->GetObject();
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomLeft));
actorSpawnParameters); projectile = objectPoolManager->GetObject();
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopLeft)); SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomRight));
}
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), }
actorSpawnParameters); }
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopRight)); }
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), void AGunWeapon::SpawnProjectile(AActor* projectile, FVector direction)
actorSpawnParameters); {
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomLeft)); if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
{
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
actorSpawnParameters); projectile->SetOwner(this);
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomRight)); IProjectilable::Execute_SetTargetDirection(projectile, direction);
} }
} }

View File

@ -22,4 +22,7 @@ protected:
public: public:
virtual void FireWeaponAction_Implementation() override; virtual void FireWeaponAction_Implementation() override;
private:
void SpawnProjectile(AActor* projectile, FVector direction);
}; };

View File

@ -3,9 +3,12 @@
#include "KnifeWeapon.h" #include "KnifeWeapon.h"
#include "GameFramework/GameModeBase.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "vampires/ObjectPoolManager.h"
#include "vampires/PlayerCharacter.h" #include "vampires/PlayerCharacter.h"
#include "vampires/Projectile.h" #include "vampires/Projectile.h"
#include "vampires/Interfaces/Pools.h"
AKnifeWeapon::AKnifeWeapon() AKnifeWeapon::AKnifeWeapon()
{ {
@ -22,19 +25,29 @@ void AKnifeWeapon::FireWeaponAction_Implementation()
if (UKismetSystemLibrary::DoesImplementInterface(GetOwner(), UInputable::StaticClass())) if (UKismetSystemLibrary::DoesImplementInterface(GetOwner(), UInputable::StaticClass()))
{ {
if (IsValid(ProjectileTemplate)) if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
{ {
FActorSpawnParameters actorSpawnParameters; AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
actorSpawnParameters.Owner = this;
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(), if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
actorSpawnParameters); {
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
{
AActor* projectile = objectPoolManager->GetObject();
FVector direction = FVector(IInputable::Execute_Input_GetPreviousMovementDirection(GetOwner()), 0.0); if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
{
IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
projectile->SetOwner(this);
FVector direction = FVector(IInputable::Execute_Input_GetPreviousMovementDirection(GetOwner()),
0.0);
direction.Normalize(); direction.Normalize();
projectile->SetTargetDirection(direction);
IProjectilable::Execute_SetTargetDirection(projectile, direction);
}
}
}
} }
} }
} }

View File

@ -3,9 +3,12 @@
#include "MagicWandWeapon.h" #include "MagicWandWeapon.h"
#include "GameFramework/GameModeBase.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
#include "vampires/ObjectPoolManager.h"
#include "vampires/Projectile.h" #include "vampires/Projectile.h"
#include "vampires/Interfaces/Pools.h"
AMagicWandWeapon::AMagicWandWeapon() AMagicWandWeapon::AMagicWandWeapon()
{ {
@ -20,25 +23,35 @@ void AMagicWandWeapon::FireWeaponAction_Implementation()
{ {
Super::FireWeaponAction_Implementation(); Super::FireWeaponAction_Implementation();
if (IsValid(ProjectileTemplate)) if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
{ {
float distance = 0.0f; float distance = 0.0f;
AActor* nearestActor = UGameplayStatics::FindNearestActor(GetActorLocation(), OverlappedEnemies, distance); AActor* nearestActor = UGameplayStatics::FindNearestActor(GetActorLocation(), OverlappedEnemies, distance);
if (nearestActor) if (nearestActor)
{ {
FActorSpawnParameters actorSpawnParameters; AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
actorSpawnParameters.Owner = this;
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot; {
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
{
AActor* projectile = objectPoolManager->GetObject();
if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
{
IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
projectile->SetOwner(this);
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
actorSpawnParameters);
FVector direction = UKismetMathLibrary::GetDirectionUnitVector( FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
GetActorLocation(), nearestActor->GetActorLocation()); GetActorLocation(), nearestActor->GetActorLocation());
direction.Z = 0.0; direction.Z = 0.0;
direction.Normalize(); direction.Normalize();
projectile->SetTargetDirection(direction);
IProjectilable::Execute_SetTargetDirection(projectile, direction);
}
}
}
} }
} }
} }

View File

@ -6,6 +6,7 @@
#include "vampires/Weapon.h" #include "vampires/Weapon.h"
#include "ProjectileWeapon.generated.h" #include "ProjectileWeapon.generated.h"
class UProjectileDataAsset;
class AProjectile; class AProjectile;
class UBoxComponent; class UBoxComponent;
@ -22,7 +23,7 @@ public:
UBoxComponent* BoxComponent = nullptr; UBoxComponent* BoxComponent = nullptr;
UPROPERTY(EditAnywhere, Category = "Weapon Properties") UPROPERTY(EditAnywhere, Category = "Weapon Properties")
TSubclassOf<AProjectile> ProjectileTemplate = nullptr; TObjectPtr<UProjectileDataAsset> ProjectileTemplate = nullptr;
protected: protected:
TArray<AActor*> OverlappedEnemies = TArray<AActor*>(); TArray<AActor*> OverlappedEnemies = TArray<AActor*>();

View File

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

View File

@ -0,0 +1,50 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "WeaponDataAsset.generated.h"
class UPaperSprite;
class AProjectile;
USTRUCT(BlueprintType)
struct FWeaponLevelUpgrades
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float WeaponCooldownMultiplier;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float WeaponDamageMultiplier;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float WeaponRangeMultiplier;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FText WeaponUpgradeText;
};
/**
*
*/
UCLASS(BlueprintType)
class VAMPIRES_API UWeaponDataAsset : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, Category = "Weapon Properties")
TSubclassOf<AProjectile> ProjectileTemplate = nullptr;
UPROPERTY(EditDefaultsOnly, Category = "Weapon Properties")
USoundBase* WeaponActivatedSoundBase = nullptr;
UPROPERTY(EditDefaultsOnly, Category = "Weapon Properties")
TObjectPtr<UPaperSprite> WeaponSprite = nullptr;
UPROPERTY(EditDefaultsOnly, Category = "Weapon Upgrades")
TArray<FWeaponLevelUpgrades> WeaponLevelUpgrades = TArray<FWeaponLevelUpgrades>();
};