Make projectiles pooled and use DataAssets
This commit is contained in:
parent
9436d16875
commit
741a41ddfa
BIN
Content/Gamemode/BP_DefaultGamemode.uasset (Stored with Git LFS)
BIN
Content/Gamemode/BP_DefaultGamemode.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Levels/Level.umap (Stored with Git LFS)
BIN
Content/Levels/Level.umap (Stored with Git LFS)
Binary file not shown.
BIN
Content/Pickups/C_Pickup.uasset (Stored with Git LFS)
BIN
Content/Pickups/C_Pickup.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
BIN
Content/Player/BP_PlayerCharacter.uasset (Stored with Git LFS)
BIN
Content/Player/BP_PlayerCharacter.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/BP_ExampleWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/BP_ExampleWeapon.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
BIN
Content/Weapons/FireWand/BP_FireWandWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/FireWand/BP_FireWandWeapon.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/Garlic/BP_GarlicWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/Garlic/BP_GarlicWeapon.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/Knife/BP_KnifeWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/Knife/BP_KnifeWeapon.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/MagicWand/BP_MagicWandProjectile.uasset (Stored with Git LFS)
BIN
Content/Weapons/MagicWand/BP_MagicWandProjectile.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/MagicWand/BP_MagicWandWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/MagicWand/BP_MagicWandWeapon.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/PhieraDerTuphello/BP_PhieraDerTuphelloWeapon.uasset (Stored with Git LFS)
BIN
Content/Weapons/PhieraDerTuphello/BP_PhieraDerTuphelloWeapon.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
|
@ -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.
|
|
@ -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();
|
||||
};
|
|
@ -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.
|
|
@ -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);
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include "GameFramework/Actor.h"
|
||||
#include "Pickup.generated.h"
|
||||
|
||||
class UPickupDataAsset;
|
||||
class UTimelineComponent;
|
||||
class USphereComponent;
|
||||
class UPaperSpriteComponent;
|
||||
|
@ -17,19 +18,21 @@ class VAMPIRES_API APickup : public AActor
|
|||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TObjectPtr<UPickupDataAsset> PickupDataAsset;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
double PickupMovementRange = 500;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
double PickupMovementSpeed = 1000;
|
||||
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
USphereComponent* InnerSphereComponent = nullptr;
|
||||
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
USphereComponent* OuterSphereComponent = nullptr;
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
UPaperSpriteComponent* SpriteComponent = nullptr;
|
||||
|
||||
|
@ -47,8 +50,8 @@ private:
|
|||
FOnTimelineEventStatic onTimelineFinishedCallback;
|
||||
|
||||
FVector PickupLocation;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
APickup();
|
||||
|
||||
|
@ -58,13 +61,13 @@ protected:
|
|||
|
||||
UFUNCTION()
|
||||
virtual void OnInnerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||
const FHitResult& SweepResult);
|
||||
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||
const FHitResult& SweepResult);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void OnOuterBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||
const FHitResult& SweepResult);
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||
const FHitResult& SweepResult);
|
||||
|
||||
UFUNCTION()
|
||||
void TimelineCallback(float val);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PickupDataAsset.h"
|
|
@ -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;
|
||||
};
|
|
@ -4,8 +4,13 @@
|
|||
#include "Projectile.h"
|
||||
|
||||
#include "EnemyCharacter.h"
|
||||
#include "ObjectPoolManager.h"
|
||||
#include "ProjectileDataAsset.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "GameFramework/ProjectileMovementComponent.h"
|
||||
#include "Interfaces/Pools.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Weapons/ProjectileWeapon.h"
|
||||
|
||||
// Sets default values
|
||||
|
@ -19,22 +24,55 @@ AProjectile::AProjectile()
|
|||
ProjectileMovement->ProjectileGravityScale = 0.0f;
|
||||
ProjectileMovement->Friction = 0.0f;
|
||||
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
|
||||
void AProjectile::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
|
||||
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->MaxSpeed = ProjectileSpeed;
|
||||
}
|
||||
|
||||
void AProjectile::SetTargetDirection(FVector direction)
|
||||
void AProjectile::ResetData_Implementation()
|
||||
{
|
||||
TargetDirection = direction;
|
||||
ProjectileMovement->SetVelocityInLocalSpace(TargetDirection * ProjectileSpeed);
|
||||
ProjectileSpeed = NULL;
|
||||
StaticMeshComponent->SetStaticMesh(nullptr);
|
||||
}
|
||||
|
||||
void AProjectile::OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
|
@ -52,11 +90,19 @@ void AProjectile::OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedCompon
|
|||
{
|
||||
ownerController = character->GetController();
|
||||
}
|
||||
|
||||
|
||||
AProjectileWeapon* ownerWeapon = Cast<AProjectileWeapon>(GetOwner());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Interfaces/Projectilable.h"
|
||||
#include "Projectile.generated.h"
|
||||
|
||||
class UProjectileMovementComponent;
|
||||
class USphereComponent;
|
||||
class UProjectileDataAsset;
|
||||
|
||||
UCLASS()
|
||||
class VAMPIRES_API AProjectile : public AActor
|
||||
class VAMPIRES_API AProjectile : public AActor, public IProjectilable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
@ -20,13 +22,15 @@ public:
|
|||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
UProjectileMovementComponent* ProjectileMovement = nullptr;
|
||||
|
||||
|
||||
FVector TargetDirection = FVector::ZeroVector;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
float ProjectileSpeed = 500.0f;
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
UStaticMeshComponent* StaticMeshComponent = nullptr;
|
||||
|
||||
// Sets default values for this actor's properties
|
||||
AProjectile();
|
||||
|
||||
|
@ -34,12 +38,18 @@ protected:
|
|||
// Called when the game starts or when spawned
|
||||
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:
|
||||
UFUNCTION()
|
||||
void OnProjectileBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||
const FHitResult& SweepResult);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ProjectileDataAsset.h"
|
|
@ -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;
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include "HealthComponent.h"
|
||||
#include "ObjectPoolManager.h"
|
||||
#include "PlayerCharacter.h"
|
||||
#include "Projectile.h"
|
||||
#include "VampirePlayerController.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
@ -77,7 +78,7 @@ void AVampireGameMode::SpawnEnemy()
|
|||
FActorSpawnParameters SpawnParameters;
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
|
||||
if (AActor* object = GetEnemyObjectPoolManager()->GetObject())
|
||||
if (AActor* object = GetEnemyObjectPoolManager_Implementation()->GetObject())
|
||||
{
|
||||
AEnemyCharacter* Actor = Cast<AEnemyCharacter>(object);
|
||||
Actor->SetActorTransform(Transform);
|
||||
|
@ -91,16 +92,15 @@ void AVampireGameMode::SpawnEnemy()
|
|||
{
|
||||
Actor->SpawnDefaultController();
|
||||
}
|
||||
|
||||
|
||||
if (!Actor->GetHealthComponent()->OnDeath.IsAlreadyBound(this, &AVampireGameMode::HandleOnEnemyDeath))
|
||||
{
|
||||
Actor->GetHealthComponent()->OnDeath.AddDynamic(this, &AVampireGameMode::HandleOnEnemyDeath);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager()
|
||||
AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager_Implementation()
|
||||
{
|
||||
if (EnemyObjectPoolManager == nullptr)
|
||||
{
|
||||
|
@ -112,6 +112,18 @@ AObjectPoolManager* AVampireGameMode::GetEnemyObjectPoolManager()
|
|||
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()
|
||||
{
|
||||
EnemyDeathCount++;
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
#include "CoreMinimal.h"
|
||||
#include "HealthComponent.h"
|
||||
#include "GameFramework/GameMode.h"
|
||||
#include "Interfaces/Pools.h"
|
||||
#include "VampireGameMode.generated.h"
|
||||
|
||||
class AProjectile;
|
||||
class AObjectPoolManager;
|
||||
class AVampirePlayerController;
|
||||
class APlayerCharacter;
|
||||
|
@ -15,7 +17,7 @@ class AEnemyCharacter;
|
|||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEnemyDeathCountIncrementDelegate, int, level);
|
||||
|
||||
UCLASS()
|
||||
class VAMPIRES_API AVampireGameMode : public AGameMode
|
||||
class VAMPIRES_API AVampireGameMode : public AGameMode, public IPools
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
@ -23,6 +25,9 @@ public:
|
|||
UPROPERTY(EditDefaultsOnly)
|
||||
TSubclassOf<AEnemyCharacter> EnemyTemplate;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
TSubclassOf<AProjectile> ProjectileTemplate;
|
||||
|
||||
FOnEnemyDeathCountIncrementDelegate OnEnemyDeathCountIncrementDelegate;
|
||||
|
||||
private:
|
||||
|
@ -36,6 +41,8 @@ private:
|
|||
|
||||
TObjectPtr<AObjectPoolManager> EnemyObjectPoolManager = nullptr;
|
||||
|
||||
TObjectPtr<AObjectPoolManager> ProjectileObjectPoolManager = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
|
@ -45,11 +52,13 @@ public:
|
|||
|
||||
UFUNCTION()
|
||||
void HandleOnEnemyDeath(FDamageInfo damageInfo);
|
||||
|
||||
|
||||
UFUNCTION()
|
||||
void IncrementEnemyDeathCount();
|
||||
|
||||
AObjectPoolManager* GetEnemyObjectPoolManager();
|
||||
virtual AObjectPoolManager* GetEnemyObjectPoolManager_Implementation() override;
|
||||
|
||||
virtual AObjectPoolManager* GetProjectileObjectPoolManager_Implementation() override;
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "GameFramework/Actor.h"
|
||||
#include "Weapon.generated.h"
|
||||
|
||||
class UWeaponDataAsset;
|
||||
|
||||
UCLASS()
|
||||
class VAMPIRES_API AWeapon : public AActor
|
||||
{
|
||||
|
@ -18,6 +20,9 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon Properties")
|
||||
float Damage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon Properties")
|
||||
TObjectPtr<UWeaponDataAsset> WeaponDataAsset;
|
||||
|
||||
private:
|
||||
FTimerHandle WeaponTimerHandle;
|
||||
|
||||
|
@ -30,7 +35,6 @@ protected:
|
|||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent)
|
||||
void FireWeaponAction();
|
||||
virtual void FireWeaponAction_Implementation();
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
#include "FireWandWeapon.h"
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "vampires/ObjectPoolManager.h"
|
||||
#include "vampires/Interfaces/Pools.h"
|
||||
#include "vampires/Projectile.h"
|
||||
|
||||
AFireWandWeapon::AFireWandWeapon()
|
||||
|
@ -18,23 +22,31 @@ void AFireWandWeapon::BeginPlay()
|
|||
void AFireWandWeapon::FireWeaponAction_Implementation()
|
||||
{
|
||||
Super::FireWeaponAction_Implementation();
|
||||
|
||||
if (IsValid(ProjectileTemplate) && OverlappedEnemies.Num() > 0)
|
||||
|
||||
if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
|
||||
{
|
||||
FActorSpawnParameters actorSpawnParameters;
|
||||
actorSpawnParameters.Owner = this;
|
||||
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
||||
|
||||
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
|
||||
|
||||
AActor* target = OverlappedEnemies[FMath::RandRange(0, OverlappedEnemies.Num() - 1)];
|
||||
FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
|
||||
GetActorLocation(), target->GetActorLocation());
|
||||
direction.Z = 0.0;
|
||||
direction.Normalize();
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
|
||||
{
|
||||
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
|
||||
{
|
||||
AActor* projectile = objectPoolManager->GetObject();
|
||||
|
||||
projectile->SetTargetDirection(direction);
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
|
||||
{
|
||||
IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
|
||||
projectile->SetOwner(this);
|
||||
|
||||
AActor* target = OverlappedEnemies[FMath::RandRange(0, OverlappedEnemies.Num() - 1)];
|
||||
FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
|
||||
GetActorLocation(), target->GetActorLocation());
|
||||
direction.Z = 0.0;
|
||||
direction.Normalize();
|
||||
|
||||
IProjectilable::Execute_SetTargetDirection(projectile, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
|
||||
#include "GunWeapon.h"
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "vampires/ObjectPoolManager.h"
|
||||
#include "vampires/PlayerCharacter.h"
|
||||
#include "vampires/Projectile.h"
|
||||
#include "vampires/VampirePlayerController.h"
|
||||
#include "vampires/Interfaces/Pools.h"
|
||||
|
||||
AGunWeapon::AGunWeapon()
|
||||
{
|
||||
|
@ -22,50 +25,58 @@ void AGunWeapon::FireWeaponAction_Implementation()
|
|||
{
|
||||
Super::FireWeaponAction_Implementation();
|
||||
|
||||
if (IsValid(ProjectileTemplate))
|
||||
if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
|
||||
{
|
||||
FVector2d ViewportSize;
|
||||
GEngine->GameViewport->GetViewportSize(ViewportSize);
|
||||
AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
|
||||
|
||||
APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
AVampirePlayerController* PlayerController = Cast<AVampirePlayerController>(
|
||||
UGameplayStatics::GetPlayerController(PlayerCharacter, 0));
|
||||
|
||||
FVector TopLeft, TopLeftDir;
|
||||
FVector TopRight, TopRightDir;
|
||||
FVector BottomLeft, BottomLeftDir;
|
||||
FVector BottomRight, BottomRightDir;
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
|
||||
{
|
||||
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
|
||||
{
|
||||
FVector2d ViewportSize;
|
||||
GEngine->GameViewport->GetViewportSize(ViewportSize);
|
||||
|
||||
PlayerController->DeprojectScreenPositionToWorld(0, 0, TopLeft, TopLeftDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, 0, TopRight, TopRightDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(0, ViewportSize.Y, BottomLeft, BottomLeftDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, ViewportSize.Y, BottomRight, BottomRightDir);
|
||||
|
||||
FVector actorLocation = GetActorLocation();
|
||||
TopLeft.Z = actorLocation.Z;
|
||||
TopRight.Z = actorLocation.Z;
|
||||
BottomLeft.Z = actorLocation.Z;
|
||||
BottomRight.Z = actorLocation.Z;
|
||||
|
||||
FActorSpawnParameters actorSpawnParameters;
|
||||
actorSpawnParameters.Owner = this;
|
||||
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
||||
|
||||
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopLeft));
|
||||
APlayerCharacter* PlayerCharacter = Cast<APlayerCharacter>(
|
||||
UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
AVampirePlayerController* PlayerController = Cast<AVampirePlayerController>(
|
||||
UGameplayStatics::GetPlayerController(PlayerCharacter, 0));
|
||||
|
||||
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopRight));
|
||||
FVector TopLeft, TopLeftDir;
|
||||
FVector TopRight, TopRightDir;
|
||||
FVector BottomLeft, BottomLeftDir;
|
||||
FVector BottomRight, BottomRightDir;
|
||||
|
||||
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomLeft));
|
||||
PlayerController->DeprojectScreenPositionToWorld(0, 0, TopLeft, TopLeftDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, 0, TopRight, TopRightDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(0, ViewportSize.Y, BottomLeft, BottomLeftDir);
|
||||
PlayerController->DeprojectScreenPositionToWorld(ViewportSize.X, ViewportSize.Y, BottomRight,
|
||||
BottomRightDir);
|
||||
|
||||
projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
projectile->SetTargetDirection(UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomRight));
|
||||
FVector actorLocation = GetActorLocation();
|
||||
TopLeft.Z = actorLocation.Z;
|
||||
TopRight.Z = actorLocation.Z;
|
||||
BottomLeft.Z = actorLocation.Z;
|
||||
BottomRight.Z = actorLocation.Z;
|
||||
|
||||
AActor* projectile = objectPoolManager->GetObject();
|
||||
SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopLeft));
|
||||
projectile = objectPoolManager->GetObject();
|
||||
SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, TopRight));
|
||||
projectile = objectPoolManager->GetObject();
|
||||
SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomLeft));
|
||||
projectile = objectPoolManager->GetObject();
|
||||
SpawnProjectile(projectile, UKismetMathLibrary::GetDirectionUnitVector(actorLocation, BottomRight));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGunWeapon::SpawnProjectile(AActor* projectile, FVector direction)
|
||||
{
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(projectile, UProjectilable::StaticClass()))
|
||||
{
|
||||
IProjectilable::Execute_LoadDataFromDataAsset(projectile, ProjectileTemplate);
|
||||
projectile->SetOwner(this);
|
||||
IProjectilable::Execute_SetTargetDirection(projectile, direction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void FireWeaponAction_Implementation() override;
|
||||
|
||||
private:
|
||||
void SpawnProjectile(AActor* projectile, FVector direction);
|
||||
};
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
|
||||
#include "KnifeWeapon.h"
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "vampires/ObjectPoolManager.h"
|
||||
#include "vampires/PlayerCharacter.h"
|
||||
#include "vampires/Projectile.h"
|
||||
#include "vampires/Interfaces/Pools.h"
|
||||
|
||||
AKnifeWeapon::AKnifeWeapon()
|
||||
{
|
||||
|
@ -22,19 +25,29 @@ void AKnifeWeapon::FireWeaponAction_Implementation()
|
|||
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(GetOwner(), UInputable::StaticClass()))
|
||||
{
|
||||
if (IsValid(ProjectileTemplate))
|
||||
if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
|
||||
{
|
||||
FActorSpawnParameters actorSpawnParameters;
|
||||
actorSpawnParameters.Owner = this;
|
||||
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
||||
AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
|
||||
|
||||
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
|
||||
{
|
||||
if (AObjectPoolManager* objectPoolManager = IPools::Execute_GetProjectileObjectPoolManager(gamemode))
|
||||
{
|
||||
AActor* projectile = objectPoolManager->GetObject();
|
||||
|
||||
FVector direction = FVector(IInputable::Execute_Input_GetPreviousMovementDirection(GetOwner()), 0.0);
|
||||
direction.Normalize();
|
||||
projectile->SetTargetDirection(direction);
|
||||
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();
|
||||
|
||||
IProjectilable::Execute_SetTargetDirection(projectile, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
|
||||
#include "MagicWandWeapon.h"
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "vampires/ObjectPoolManager.h"
|
||||
#include "vampires/Projectile.h"
|
||||
#include "vampires/Interfaces/Pools.h"
|
||||
|
||||
AMagicWandWeapon::AMagicWandWeapon()
|
||||
{
|
||||
|
@ -20,25 +23,35 @@ void AMagicWandWeapon::FireWeaponAction_Implementation()
|
|||
{
|
||||
Super::FireWeaponAction_Implementation();
|
||||
|
||||
if (IsValid(ProjectileTemplate))
|
||||
if (ProjectileTemplate && OverlappedEnemies.Num() > 0)
|
||||
{
|
||||
float distance = 0.0f;
|
||||
AActor* nearestActor = UGameplayStatics::FindNearestActor(GetActorLocation(), OverlappedEnemies, distance);
|
||||
|
||||
if (nearestActor)
|
||||
{
|
||||
FActorSpawnParameters actorSpawnParameters;
|
||||
actorSpawnParameters.Owner = this;
|
||||
actorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
actorSpawnParameters.TransformScaleMethod = ESpawnActorScaleMethod::MultiplyWithRoot;
|
||||
|
||||
AProjectile* projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileTemplate, GetOwner()->GetTransform(),
|
||||
actorSpawnParameters);
|
||||
FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
|
||||
GetActorLocation(), nearestActor->GetActorLocation());
|
||||
direction.Z = 0.0;
|
||||
direction.Normalize();
|
||||
projectile->SetTargetDirection(direction);
|
||||
AGameModeBase* gamemode = UGameplayStatics::GetGameMode(GetWorld());
|
||||
|
||||
if (UKismetSystemLibrary::DoesImplementInterface(gamemode, UPools::StaticClass()))
|
||||
{
|
||||
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);
|
||||
|
||||
FVector direction = UKismetMathLibrary::GetDirectionUnitVector(
|
||||
GetActorLocation(), nearestActor->GetActorLocation());
|
||||
direction.Z = 0.0;
|
||||
direction.Normalize();
|
||||
|
||||
IProjectilable::Execute_SetTargetDirection(projectile, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "vampires/Weapon.h"
|
||||
#include "ProjectileWeapon.generated.h"
|
||||
|
||||
class UProjectileDataAsset;
|
||||
class AProjectile;
|
||||
class UBoxComponent;
|
||||
|
||||
|
@ -22,7 +23,7 @@ public:
|
|||
UBoxComponent* BoxComponent = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Weapon Properties")
|
||||
TSubclassOf<AProjectile> ProjectileTemplate = nullptr;
|
||||
TObjectPtr<UProjectileDataAsset> ProjectileTemplate = nullptr;
|
||||
|
||||
protected:
|
||||
TArray<AActor*> OverlappedEnemies = TArray<AActor*>();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "WeaponDataAsset.h"
|
|
@ -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>();
|
||||
};
|
Loading…
Reference in New Issue