[ PROJECT F ]
오늘의 구현 목록
[ 수류탄 코드 구현 ]
< PFGrenade >
더보기
< 헤더 파일 >
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "PFGameMode.generated.h"
/**
*
*/
class APFGameState;
class APFLevelPortal;
class APFBaseItem;
UCLASS()
class PROJECTF_API APFGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
APFGameMode();
void OnMonsterKilled();
void ProceedToNextLevel();
// 게임오버 이동
void GameOver();
UFUNCTION(BlueprintCallable, Category = "Item|Drop")
void HandleMonsterDeath(const FVector& SpawnLocation);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI")
TSubclassOf<class UUserWidget> LoadingWidgetClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Classes")
TSubclassOf<APFBaseItem> HealingItemClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Classes")
TSubclassOf<APFBaseItem> PistolAmmoClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Classes")
TSubclassOf<APFBaseItem> RifleAmmoClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Classes")
TSubclassOf<APFBaseItem> GrenadeItemClass;
// 기본 드랍 확률 (20%)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|DropSettings")
float OverallDropChance = 0.2f;
void RegisterLevelPortal(class APFLevelPortal* Portal) { LevelPortalInstance = Portal; }
protected:
virtual void BeginPlay() override;
void TimerCountDown();
void StartWave();
void WaveClear();
void LevelClear();
private:
void SpawnRandomItem(const FVector& SpawnLocation, int32 CurrentLevel);
UPROPERTY(VisibleAnywhere, Category = "Game Data")
APFGameState* PFGameState;
FTimerHandle PFTimerHandle;
UPROPERTY()
class APFWaveManager* PFWaveManager;
UPROPERTY()
class APFSpawnManager* PFSpawnManager;
UPROPERTY(EditAnywhere, Category = "Wave Data")
UDataTable* WaveDataTableAsset;
class APFLevelPortal* LevelPortalInstance;
};
< 소스 파일 >
#include "Weapon/PFGrenade.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Kismet/GameplayStatics.h"
#include "NiagaraComponent.h"
#include "DrawDebugHelpers.h"
#include "Monster/PFMonsterCharacter.h"
APFGrenade::APFGrenade()
{
PrimaryActorTick.bCanEverTick = false;
CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
CollisionComponent->InitSphereRadius(10.0f);
CollisionComponent->SetCollisionProfileName(TEXT("BlockAll"));
RootComponent = CollisionComponent;
GrenadeMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("GrenadeMesh"));
GrenadeMesh->SetupAttachment(RootComponent);
ExplosionSphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionSphereComponent"));
ExplosionSphereComponent->SetupAttachment(RootComponent);
ExplosionSphereComponent->InitSphereRadius(400.0f);
ExplosionSphereComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
ExplosionSphereComponent->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
ExplosionEffect = CreateDefaultSubobject<UNiagaraComponent>(TEXT("ExplosionEffect"));
ExplosionEffect->SetupAttachment(RootComponent);
ExplosionEffect->bAutoActivate = false;
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovement"));
ProjectileMovement->UpdatedComponent = CollisionComponent;
ProjectileMovement->InitialSpeed = 1500.f;
ProjectileMovement->MaxSpeed = 1500.f;
ProjectileMovement->bRotationFollowsVelocity = true;
ProjectileMovement->bShouldBounce = true;
ProjectileMovement->Bounciness = 0.3f;
}
void APFGrenade::BeginPlay()
{
Super::BeginPlay();
// 타이머 설정
GetWorldTimerManager().SetTimer(ExplodeTimerHandle, this, &APFGrenade::Explode, FuseTime, false);
}
void APFGrenade::Explode()
{
FVector ExplodeLocation = GetActorLocation();
// 나이아가라 이펙트 on(활성화)
if (ExplosionEffect)
{
ExplosionEffect->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
ExplosionEffect->Activate(true);
}
// 청각 효과 (사운드 재생)
if (ExplosionSound)
{
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplosionSound, ExplodeLocation);
}
if (ExplosionSphereComponent)
{
TArray<AActor*> OverlappingActors;
// ExplosionSphereComponent 이랑 overlap된 액터 탐색
ExplosionSphereComponent->GetOverlappingActors(OverlappingActors);
for (AActor* HitActor : OverlappingActors)
{
if (HitActor)
{
// 몬스터만 피격
APFMonsterCharacter* Monster = Cast<APFMonsterCharacter>(HitActor);
if (Monster)
{
Monster->TakeDamageFromMonster(ExplosionDamage, GetOwner());
UE_LOG(LogTemp, Log, TEXT("[Grenade] %s 몬스터에게 수류탄 데미지 %f 적용 완료!"),
*Monster->GetName(), ExplosionDamage);
}
}
}
}
// 이후 처리
if (GrenadeMesh)
{
GrenadeMesh->SetHiddenInGame(true);
}
if (CollisionComponent)
{
CollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
if (ProjectileMovement)
{
ProjectileMovement->StopMovementImmediately();
}
FTimerHandle DestroyTimerHandle;
GetWorldTimerManager().SetTimer(DestroyTimerHandle, [this]()
{this->Destroy();}, 5.0f, false);
}
< 이 후 BP 래핑 >
< 수류탄 효과 (TakeDamageFromMonster)는 적용되는데 나이아가라 이펙트가 나오지않는 이슈 발생 >
더보기

해결 방법

CombatComponent 에서의 Grenade Class 를 작성한 BP_PFGrenade_N으로 교체
< 테스트 화면 >
[ 몬스터 스폰 포탈, Level포탈/보스 포탈 나이아가라 이펙트 수정 ]
더보기

몬스터 포탈

보스/레벨 포탈



