[박치영] 충돌 및 히트판정 작업 중
parent
4a9c04e1ca
commit
bb659ad091
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.
|
|
@ -31,6 +31,14 @@ void ABaseEquippable::AttachActor(const FName SocketName)
|
|||
}
|
||||
}
|
||||
|
||||
UPrimitiveComponent* ABaseEquippable::GetItemMesh()
|
||||
{
|
||||
if (IsValid(ItemStaticMesh->GetStaticMesh()))
|
||||
return ItemStaticMesh;
|
||||
else
|
||||
return ItemSkeletalMesh;
|
||||
}
|
||||
|
||||
void ABaseEquippable::OnEquipped()
|
||||
{
|
||||
SetIsEquipped(true);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public:
|
|||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void AttachActor(const FName SocketName);
|
||||
UPrimitiveComponent* GetItemMesh();
|
||||
virtual void OnEquipped();
|
||||
virtual void OnUnequipped();
|
||||
virtual void SetIsEquipped(bool IsEquipped);
|
||||
|
|
|
|||
|
|
@ -4,11 +4,22 @@
|
|||
#include "Actor/BaseWeapon.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Components/CollisionComponent.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
ABaseWeapon::ABaseWeapon()
|
||||
{
|
||||
CollisionComponent = CreateDefaultSubobject<UCollisionComponent>(TEXT("CollisionComponent"));
|
||||
CollisionComponent->OnHitDelegate.BindUObject(this, &ABaseWeapon::OnHit);
|
||||
CollisionComponent->SetTraceRaius(20.f);
|
||||
CollisionComponent->SetStartSocketName(TEXT("WeaponStart"));
|
||||
CollisionComponent->SetEndSocketName(TEXT("WeaponEnd"));
|
||||
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> InputCollisionObjectTypes;
|
||||
InputCollisionObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
|
||||
CollisionComponent->SetCollisionObjectTypes(InputCollisionObjectTypes);
|
||||
CollisionComponent->SetDrawDebugType(EDrawDebugTrace::None);
|
||||
}
|
||||
|
||||
void ABaseWeapon::OnEquipped()
|
||||
|
|
@ -30,17 +41,23 @@ void ABaseWeapon::OnEquipped()
|
|||
UCombatAnimInstance* animInstance = Cast<UCombatAnimInstance>(character->GetMesh()->GetAnimInstance());
|
||||
animInstance->UpdateCombatType(CombatType);
|
||||
}
|
||||
|
||||
CollisionComponent->SetCollisionMeshComponent(GetItemMesh());
|
||||
CollisionComponent->AddActorToIgnore(GetOwner());
|
||||
}
|
||||
|
||||
void ABaseWeapon::OnHit(FHitResult hitResult)
|
||||
{
|
||||
//float UGameplayStatics::ApplyPointDamage(
|
||||
// AActor * DamagedActor, float BaseDamage, FVector const& HitFromDirection,
|
||||
// FHitResult const& HitInfo, AController * EventInstigator, AActor * DamageCauser,
|
||||
// TSubclassOf<UDamageType> DamageTypeClass)
|
||||
|
||||
if (true) // TODO : Interface CanReceiveDamage
|
||||
ICombatInterface* pActor = Cast<ICombatInterface>(hitResult.GetActor());
|
||||
if (pActor)
|
||||
{
|
||||
UGameplayStatics::ApplyPointDamage(hitResult.GetActor(), Damage, GetOwner()->GetActorForwardVector(), hitResult, GetInstigatorController(), this, TSubclassOf<UDamageType>(UDamageType::StaticClass()));
|
||||
if (pActor->Execute_CanReceiveDamage(hitResult.GetActor()))
|
||||
UGameplayStatics::ApplyPointDamage(hitResult.GetActor(), Damage, GetOwner()->GetActorForwardVector(), hitResult, GetInstigatorController(), this, TSubclassOf<UDamageType>(UDamageType::StaticClass()));
|
||||
}
|
||||
}
|
||||
|
||||
void ABaseWeapon::SimulateWeaponPhysics()
|
||||
{
|
||||
GetItemMesh()->SetCollisionProfileName(TEXT("PhysicsActor"), true);
|
||||
GetItemMesh()->SetSimulatePhysics(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,15 @@ public:
|
|||
ABaseWeapon();
|
||||
|
||||
public:
|
||||
//override
|
||||
void OnEquipped() override;
|
||||
|
||||
public:
|
||||
//Delegate
|
||||
void OnHit(FHitResult hitResult);
|
||||
public:
|
||||
//Normal
|
||||
void SimulateWeaponPhysics();
|
||||
public:
|
||||
FORCEINLINE UAnimMontage* GetEnterCombat() const { return EnterCombat; }
|
||||
FORCEINLINE UAnimMontage* GetExitCombat() const { return ExitCombat; }
|
||||
|
|
@ -42,6 +46,9 @@ protected:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components")
|
||||
TObjectPtr<class UCombatComponent> CombatComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components")
|
||||
TObjectPtr<class UCollisionComponent> CollisionComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
|
||||
TObjectPtr<UAnimMontage> EnterCombat;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@
|
|||
#include "GameFramework/SpringArmComponent.h"
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "Interface/Interact.h"
|
||||
#include "Actor/BaseWeapon.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "Engine/DamageEvents.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ACombatCharacter
|
||||
|
|
@ -60,6 +62,16 @@ ACombatCharacter::ACombatCharacter()
|
|||
CombatEnabled = false;
|
||||
IsTogglingCombat = false;
|
||||
IsDodge = false;
|
||||
IsDisabled = false;
|
||||
IsDead = false;
|
||||
Health = 100.f;
|
||||
|
||||
PelvisBoneName = TEXT("pelvis");
|
||||
|
||||
//³ªÁß¿¡ ¼öÁ¤ÇÒ ¼ö ÀÖÀ½
|
||||
static ConstructorHelpers::FObjectFinder<UAnimMontage> findHitMontage(TEXT("/Script/Engine.AnimMontage'/Game/CombatSystem/CourseFiles/Animations/HitReactions/Standing_React_Large_Front_Montage.Standing_React_Large_Front_Montage'"));
|
||||
if (findHitMontage.Succeeded())
|
||||
HitMontage = findHitMontage.Object;
|
||||
}
|
||||
|
||||
void ACombatCharacter::BeginPlay()
|
||||
|
|
@ -85,6 +97,29 @@ void ACombatCharacter::BeginPlay()
|
|||
SpawnItem->OnEquipped();
|
||||
}
|
||||
|
||||
float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
|
||||
{
|
||||
float fDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
|
||||
|
||||
if (DamageEvent.IsOfType(FPointDamageEvent::ClassID))
|
||||
{
|
||||
const FPointDamageEvent* PointDamageEvent = static_cast<const FPointDamageEvent*>(&DamageEvent);
|
||||
|
||||
CharacterTakeDamage(fDamage);
|
||||
|
||||
//TODO : Sound, Effect Emitter, Play anim montage
|
||||
//static void PlaySoundAtLocation(
|
||||
// const UObject * WorldContextObject, USoundBase * Sound, FVector Location,
|
||||
// float VolumeMultiplier = 1.f, float PitchMultiplier = 1.f, float StartTime = 0.f,
|
||||
// class USoundAttenuation* AttenuationSettings = nullptr, USoundConcurrency * ConcurrencySettings = nullptr,
|
||||
// const UInitialActiveSoundParams * InitialParams = nullptr)
|
||||
//UGameplayStatics::PlaySoundAtLocation(this, HitSound, PointDamageEvent->HitInfo.Location);
|
||||
PlayAnimMontage(HitMontage);
|
||||
IsDisabled = true;
|
||||
}
|
||||
return fDamage;
|
||||
}
|
||||
|
||||
void ACombatCharacter::ContinueAttack_Implementation()
|
||||
{
|
||||
CombatComponent->SetIsAttacking(false);
|
||||
|
|
@ -116,6 +151,11 @@ FRotator ACombatCharacter::GetDesiredRotation_Implementation()
|
|||
return UKismetMathLibrary::MakeRotFromX(GetLastMovementInputVector());
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanReceiveDamage_Implementation()
|
||||
{
|
||||
return !IsDead;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Input
|
||||
|
||||
|
|
@ -249,6 +289,36 @@ void ACombatCharacter::AttackEvent()
|
|||
ToggleCombatEvent();
|
||||
}
|
||||
|
||||
void ACombatCharacter::CharacterTakeDamage(float InDamage)
|
||||
{
|
||||
float tmp = Health - InDamage;
|
||||
Health = UKismetMathLibrary::Clamp(tmp, 0, Health);
|
||||
|
||||
if (Health <= 0)
|
||||
PerformDeath();
|
||||
}
|
||||
|
||||
void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed)
|
||||
{
|
||||
if (!GetMesh())
|
||||
return;
|
||||
|
||||
GetMesh()->SetPhysicsLinearVelocity(GetActorForwardVector() * -InitialSpeed, false, PelvisBoneName);
|
||||
}
|
||||
|
||||
void ACombatCharacter::EnableRagdoll()
|
||||
{
|
||||
GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None, 0);
|
||||
GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
|
||||
GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
|
||||
FAttachmentTransformRules rules(EAttachmentRule::KeepWorld, EAttachmentRule::KeepWorld, EAttachmentRule::KeepWorld, true);
|
||||
GetCameraBoom()->AttachToComponent(GetMesh(), rules, PelvisBoneName);
|
||||
GetCameraBoom()->bDoCollisionTest = false;
|
||||
GetMesh()->SetCollisionProfileName(TEXT("ragdoll"), true);
|
||||
GetMesh()->SetAllBodiesBelowSimulatePhysics(PelvisBoneName, true, true);
|
||||
GetMesh()->SetAllBodiesBelowPhysicsBlendWeight(PelvisBoneName, 1.f);
|
||||
}
|
||||
|
||||
void ACombatCharacter::PerformAttack(int32 attackIndex)
|
||||
{
|
||||
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
|
||||
|
|
@ -296,19 +366,70 @@ void ACombatCharacter::PerformDodge()
|
|||
}
|
||||
}
|
||||
|
||||
void ACombatCharacter::PerformDeath()
|
||||
{
|
||||
IsDead = true;
|
||||
EnableRagdoll();
|
||||
ApplyHitReactionPhysicsVelocity(2000.f);
|
||||
|
||||
if (IsValid(CombatComponent->GetMainWeapon()))
|
||||
CombatComponent->GetMainWeapon()->SimulateWeaponPhysics();
|
||||
|
||||
FTimerHandle deathTimer;
|
||||
GetWorld()->GetTimerManager().SetTimer(deathTimer, FTimerDelegate::CreateLambda([&]()
|
||||
{
|
||||
if (IsValid(CombatComponent->GetMainWeapon()))
|
||||
CombatComponent->GetMainWeapon()->Destroy();
|
||||
this->Destroy();
|
||||
}), 4.f, false);
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanPerformToggleCombat()
|
||||
{
|
||||
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat);
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanPerformAttack()
|
||||
{
|
||||
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat);
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanPerformDodge()
|
||||
{
|
||||
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat && !IsDodge);
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanJumping()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,9 @@ public:
|
|||
protected:
|
||||
// APawn interface
|
||||
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
|
||||
virtual void BeginPlay();
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
virtual float TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
|
||||
|
||||
public:
|
||||
// Inherited via ICombatInterface
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
|
|
@ -79,27 +80,34 @@ public:
|
|||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
FRotator GetDesiredRotation();
|
||||
virtual FRotator GetDesiredRotation_Implementation() override;
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
bool CanReceiveDamage();
|
||||
virtual bool CanReceiveDamage_Implementation() override;
|
||||
|
||||
protected:
|
||||
/** Called for movement input */
|
||||
//Input Funcs
|
||||
void Move(const FInputActionValue& Value);
|
||||
|
||||
/** Called for looking input */
|
||||
void Look(const FInputActionValue& Value);
|
||||
|
||||
void Interact(const FInputActionValue& Value);
|
||||
void ToggleCombat(const FInputActionValue& Value);
|
||||
void LightAttack(const FInputActionValue& Value);
|
||||
void Dodge(const FInputActionValue& Value);
|
||||
|
||||
|
||||
private:
|
||||
void ToggleCombatEvent();
|
||||
void AttackEvent();
|
||||
void CharacterTakeDamage(float InDamage);
|
||||
void ApplyHitReactionPhysicsVelocity(float InitialSpeed);
|
||||
void EnableRagdoll();
|
||||
|
||||
void PerformAttack(int32 attackIndex);
|
||||
void PerformDodge();
|
||||
void PerformDeath();
|
||||
|
||||
bool CanPerformToggleCombat();
|
||||
bool CanPerformAttack();
|
||||
bool CanPerformDodge();
|
||||
bool CanJumping();
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UCombatComponent> CombatComponent;
|
||||
|
|
@ -107,9 +115,19 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true"))
|
||||
TSubclassOf<class ABaseEquippable> Weapon;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
|
||||
FName PelvisBoneName;
|
||||
|
||||
private:
|
||||
//TODO : particle, sound Ãß°¡
|
||||
//class USoundWave* HitSound;
|
||||
TObjectPtr<UAnimMontage> HitMontage;
|
||||
private:
|
||||
bool CombatEnabled;
|
||||
bool IsTogglingCombat;
|
||||
bool IsDodge;
|
||||
bool IsDisabled;
|
||||
bool IsDead;
|
||||
float Health;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void UCollisionComponent::TickComponent(float DeltaTime, ELevelTick TickType, FA
|
|||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (IsCollisionEnabled)
|
||||
if (bCollisionEnabled)
|
||||
CollisionTrace();
|
||||
}
|
||||
|
||||
|
|
@ -56,12 +56,14 @@ void UCollisionComponent::CollisionTrace()
|
|||
{
|
||||
HitActor = LastHit.GetActor();
|
||||
AlreadyHitActors.Add(HitActor);
|
||||
OnHit.ExecuteIfBound(LastHit);
|
||||
OnHitDelegate.ExecuteIfBound(LastHit); //Multi면 변경해야됨
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UCollisionComponent::EnableCollision()
|
||||
{
|
||||
ClearHitActors();
|
||||
bCollisionEnabled = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "CollisionComponent.generated.h"
|
||||
|
||||
DECLARE_DELEGATE_OneParam(FOnHit, FHitResult hitResult);
|
||||
//DECLARE_MULTICAST_DELEGATE_OneParam ·Î º¯°æ ÇÊ¿ä
|
||||
DECLARE_DELEGATE_OneParam(FOnHit, FHitResult);
|
||||
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
class D1_API UCollisionComponent : public UActorComponent
|
||||
|
|
@ -29,11 +30,30 @@ public:
|
|||
public:
|
||||
void CollisionTrace();
|
||||
public:
|
||||
FORCEINLINE void SetCollisionMesh(UPrimitiveComponent* InputComponent) { CollisionMeshComponent = InputComponent; }
|
||||
FORCEINLINE void EnableCollision();
|
||||
FORCEINLINE void DisableCollision() { IsCollisionEnabled = false; }
|
||||
TArray<AActor*> GetAlreadyHitActors() { return AlreadyHitActors; }
|
||||
FORCEINLINE void ClearHitActors() { AlreadyHitActors.Empty(); }
|
||||
|
||||
FHitResult GetLastHit() { return LastHit; }
|
||||
|
||||
UPrimitiveComponent* GetCollisionMeshComponent() { return CollisionMeshComponent; }
|
||||
FORCEINLINE void SetCollisionMeshComponent(UPrimitiveComponent* InputComponent) { CollisionMeshComponent = InputComponent; }
|
||||
|
||||
FORCEINLINE void AddActorToIgnore(AActor* inputActor) { ActorsToIgnore.Add(inputActor); }
|
||||
void RemoveActorToIgnore(AActor* inputActor) { ActorsToIgnore.Remove(inputActor); }
|
||||
TArray<AActor*> GetActorToIgnore() { return ActorsToIgnore; }
|
||||
|
||||
//Initialize
|
||||
FORCEINLINE void SetTraceRaius(float inputTrace) { TraceRadius = inputTrace; }
|
||||
FORCEINLINE void SetStartSocketName(FName InputStartSocketName) { StartSocketName = InputStartSocketName; }
|
||||
FORCEINLINE void SetEndSocketName(FName InpuEndSocketName) { EndSocketName = InpuEndSocketName; }
|
||||
FORCEINLINE void SetCollisionObjectTypes(TArray<TEnumAsByte<EObjectTypeQuery>> InputCollisionObjectTypes) { CollisionObjectTypes = InputCollisionObjectTypes; }
|
||||
FORCEINLINE void SetDrawDebugType(TEnumAsByte<EDrawDebugTrace::Type> InputDrawDebugType) { DrawDebugType = InputDrawDebugType; }
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
FORCEINLINE void EnableCollision();
|
||||
UFUNCTION(BlueprintCallable)
|
||||
FORCEINLINE void DisableCollision() { bCollisionEnabled = false; }
|
||||
bool IsCollisionEnabled() { return bCollisionEnabled; }
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
float TraceRadius;
|
||||
|
|
@ -53,11 +73,12 @@ private:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta = (AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UPrimitiveComponent> CollisionMeshComponent;
|
||||
|
||||
bool IsCollisionEnabled;
|
||||
bool bCollisionEnabled;
|
||||
TArray<TObjectPtr<AActor>> AlreadyHitActors;
|
||||
TArray<TObjectPtr<AActor>> ActorsToIgnore;
|
||||
FHitResult LastHit;
|
||||
TObjectPtr<AActor> HitActor;
|
||||
|
||||
FOnHit OnHit;
|
||||
public:
|
||||
FOnHit OnHitDelegate;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,4 +30,6 @@ public:
|
|||
void ResetCombat();
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
FRotator GetDesiredRotation();
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
bool CanReceiveDamage();
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue