parent
4144aaa60a
commit
86dbaf0037
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -7,6 +7,7 @@
|
|||
#include "Components/CollisionComponent.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "DamageType/AttackDamageType.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "UI/UI_HealthBar.h"
|
||||
|
@ -108,7 +109,8 @@ void ABossEnemy::SetBossHealthVisibility(bool IsVisible)
|
|||
if(!IsValid(BossHealthWidget))
|
||||
return;
|
||||
|
||||
if(IsVisible)
|
||||
FGameplayTagContainer GameplayTagContainer(FCombatGameplayTags::Get().Character_State_Dead);
|
||||
if(IsVisible && !StateManagerComponent->IsCurrentStateEqualToAny(GameplayTagContainer))
|
||||
BossHealthWidget->SetVisibility(ESlateVisibility::Visible);
|
||||
else
|
||||
BossHealthWidget->SetVisibility(ESlateVisibility::Hidden);
|
||||
|
|
|
@ -95,6 +95,9 @@ AMasterAI::AMasterAI()
|
|||
WalkingSpeed = 200.f;
|
||||
JoggingSpeed = 500.f;
|
||||
SprintSpeed = 700.f;
|
||||
|
||||
//Settings OwnedGameplayTags
|
||||
OwnedGameplayTags.AddTag(FCombatGameplayTags::Get().Character_Enemy);
|
||||
|
||||
PelvisBoneName = TEXT("pelvis");
|
||||
}
|
||||
|
@ -215,7 +218,9 @@ float AMasterAI::PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, in
|
|||
{
|
||||
StateManagerComponent->SetCurrentState(StateTag);
|
||||
StateManagerComponent->SetCurrentAction(ActionTag);
|
||||
actionDuration = PlayAnimMontage(actionMontage);
|
||||
if(!IsValid(GetMesh()->GetAnimInstance()))
|
||||
return 0.f;
|
||||
actionDuration = GetMesh()->GetAnimInstance()->Montage_Play(actionMontage);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -250,7 +255,9 @@ float AMasterAI::PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool
|
|||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking);
|
||||
StateManagerComponent->SetCurrentAction(AttackType);
|
||||
|
||||
attackDuration = PlayAnimMontage(attackMontage);
|
||||
if(!IsValid(GetMesh()->GetAnimInstance()))
|
||||
return 0.f;
|
||||
attackDuration = GetMesh()->GetAnimInstance()->Montage_Play(attackMontage);
|
||||
|
||||
int idx = attackIdx + 1;
|
||||
if (idx >= montages.Num())
|
||||
|
@ -424,7 +431,11 @@ void AMasterAI::ApplyImpactEffect(EDamageType InDamageType)
|
|||
void AMasterAI::PerformDeath()
|
||||
{
|
||||
EnableRagdoll();
|
||||
ApplyHitReactionPhysicsVelocity(2000.f); //충돌을 좀 더 그럴싸하게 하기 위해서 뒷방향으로 충격
|
||||
|
||||
if(bHitFront) //충돌을 좀 더 그럴싸하게 하기 위해서 피격방향으로 충격
|
||||
ApplyHitReactionPhysicsVelocity(2000.f);
|
||||
else
|
||||
ApplyHitReactionPhysicsVelocity(-2000.f);
|
||||
|
||||
FTimerHandle deathTimer;
|
||||
GetWorld()->GetTimerManager().SetTimer(deathTimer, FTimerDelegate::CreateLambda([&]()
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagAssetInterface.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
|
@ -12,7 +13,7 @@
|
|||
#include "MasterAI.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class D1_API AMasterAI : public ACharacter, public ICombatInterface, public ITargetingInterface
|
||||
class D1_API AMasterAI : public ACharacter, public ICombatInterface, public ITargetingInterface, public IGameplayTagAssetInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
@ -71,6 +72,9 @@ public:
|
|||
// Inherited via ITargetingInterface
|
||||
virtual bool CanBeTargeted() override;
|
||||
virtual void OnTargeted(bool bIsTargeted) override;
|
||||
|
||||
// Inherited via IGameplayTagAssetInterface
|
||||
virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override { TagContainer = OwnedGameplayTags; }
|
||||
public: //Using Child Class
|
||||
virtual void OnTargetSet(AActor* NewTarget);
|
||||
public:
|
||||
|
@ -152,6 +156,8 @@ private:
|
|||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Patrol", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TObjectPtr<ATargetPoint>> PatrolPoints;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameplayTags", meta = (AllowPrivateAccess = "true"))
|
||||
FGameplayTagContainer OwnedGameplayTags;
|
||||
|
||||
private:
|
||||
FTimerHandle StaminaTimerHandle;
|
||||
|
|
|
@ -102,6 +102,12 @@ ACombatPlayerCharacter::ACombatPlayerCharacter()
|
|||
ChargeAttackTime = 0.18f;
|
||||
PelvisBoneName = TEXT("pelvis");
|
||||
|
||||
//Setting Timeline
|
||||
FOnTimelineFloat CurveFloatCallback;
|
||||
CurveFloatCallback.BindUFunction(this, FName("RotateToTargetUpdate"));
|
||||
RotateToTargetTimeLineComponent = CreateDefaultSubobject<UTimelineComponent>(TEXT("RotateToTargetTimeLineComponent"));
|
||||
RotateToTargetTimeLineComponent->SetTimelineLength(5.0f);
|
||||
RotateToTargetTimeLineComponent->AddInterpFloat(CurveFloatTimeline, CurveFloatCallback);
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::BeginPlay()
|
||||
|
@ -127,6 +133,11 @@ void ACombatPlayerCharacter::BeginPlay()
|
|||
SpawnItem->OnEquipped();
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
}
|
||||
|
||||
float ACombatPlayerCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
|
||||
{
|
||||
float fDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
|
||||
|
@ -282,12 +293,13 @@ float ACombatPlayerCharacter::PerformAction(FGameplayTag ActionTag, FGameplayTag
|
|||
{
|
||||
StateManagerComponent->SetCurrentState(StateTag);
|
||||
StateManagerComponent->SetCurrentAction(ActionTag);
|
||||
actionDuration = PlayAnimMontage(actionMontage);
|
||||
return true;
|
||||
if(!IsValid(GetMesh()->GetAnimInstance()))
|
||||
return 0.f;
|
||||
actionDuration = GetMesh()->GetAnimInstance()->Montage_Play(actionMontage);
|
||||
}
|
||||
else
|
||||
{
|
||||
FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIdx);
|
||||
FString str = FString::Printf(TEXT("Dodge Index %d is NOT VALID!!"), montageIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str);
|
||||
}
|
||||
return actionDuration;
|
||||
|
@ -324,9 +336,11 @@ float ACombatPlayerCharacter::PerformAttack(FGameplayTag AttackType, int32 Attac
|
|||
{
|
||||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking);
|
||||
StateManagerComponent->SetCurrentAction(AttackType);
|
||||
|
||||
attackDuration = PlayAnimMontage(attackMontage);
|
||||
|
||||
|
||||
if(!IsValid(GetMesh()->GetAnimInstance()))
|
||||
return 0.f;
|
||||
attackDuration = GetMesh()->GetAnimInstance()->Montage_Play(attackMontage);
|
||||
|
||||
int idx = attackIdx + 1;
|
||||
if (idx >= montages.Num())
|
||||
idx = 0;
|
||||
|
@ -521,7 +535,9 @@ void ACombatPlayerCharacter::CharacterStateBegin(FGameplayTag CharState)
|
|||
if (FGameplayTag::EmptyTag == CharState)
|
||||
{/*None*/}
|
||||
else if (FCombatGameplayTags::Get().Character_State_Attacking == CharState)
|
||||
{/*None*/}
|
||||
{
|
||||
RotateToTarget();
|
||||
}
|
||||
else if (FCombatGameplayTags::Get().Character_State_Dodging == CharState)
|
||||
{/*None*/}
|
||||
else if (FCombatGameplayTags::Get().Character_State_GeneralActionState == CharState)
|
||||
|
@ -539,7 +555,9 @@ void ACombatPlayerCharacter::CharacterStateEnd(FGameplayTag CharState)
|
|||
if (FGameplayTag::EmptyTag == CharState)
|
||||
{/*None*/}
|
||||
else if (FCombatGameplayTags::Get().Character_State_Attacking == CharState)
|
||||
{/*None*/}
|
||||
{
|
||||
StopRotateToTarget();
|
||||
}
|
||||
else if (FCombatGameplayTags::Get().Character_State_Dodging == CharState)
|
||||
{/*None*/}
|
||||
else if (FCombatGameplayTags::Get().Character_State_GeneralActionState == CharState)
|
||||
|
@ -693,11 +711,39 @@ void ACombatPlayerCharacter::ApplyImpactEffect(EDamageType InDamageType)
|
|||
UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(), HitEmitter, LastHitInfo.Location);
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::RotateToTarget()
|
||||
{
|
||||
RotateToTargetTimeLineComponent->PlayFromStart();
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::StopRotateToTarget()
|
||||
{
|
||||
RotateToTargetTimeLineComponent->Stop();
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::RotateToTargetUpdate(float Output)
|
||||
{
|
||||
if(!IsValid(TargetingComponent))
|
||||
return;
|
||||
|
||||
const FRotator CurrentRotator = GetActorRotation();
|
||||
FRotator TargetRotator = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), TargetingComponent->GetTargetActor()->GetActorLocation());
|
||||
double deltaTime = UGameplayStatics::GetWorldDeltaSeconds(GetOwner());
|
||||
FRotator NewRotator = FMath::RInterpTo(CurrentRotator, TargetRotator, deltaTime, RotateToTargetInterpSpeed);
|
||||
NewRotator.Roll = CurrentRotator.Roll;
|
||||
NewRotator.Pitch = CurrentRotator.Pitch;
|
||||
SetActorRotation(NewRotator);
|
||||
}
|
||||
|
||||
void ACombatPlayerCharacter::PerformDeath()
|
||||
{
|
||||
EnableRagdoll();
|
||||
ApplyHitReactionPhysicsVelocity(2000.f); //충돌을 좀 더 그럴싸하게 하기 위해서 뒷방향으로 충격
|
||||
|
||||
if(bHitFront) //충돌을 좀 더 그럴싸하게 하기 위해서 피격방향으로 충격
|
||||
ApplyHitReactionPhysicsVelocity(2000.f);
|
||||
else
|
||||
ApplyHitReactionPhysicsVelocity(-2000.f);
|
||||
|
||||
if (IsValid(CombatComponent->GetMainWeapon()))
|
||||
CombatComponent->GetMainWeapon()->SimulateWeaponPhysics(); //무기의 충돌킴
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Components/StateManagerComponent.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "Components/TargetingComponent.h"
|
||||
#include "Components/TimelineComponent.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "CombatPlayerCharacter.generated.h"
|
||||
|
||||
|
@ -85,6 +86,7 @@ protected:
|
|||
// APawn interface
|
||||
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
|
||||
virtual void BeginPlay() override;
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
virtual float TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
|
||||
|
||||
public:
|
||||
|
@ -158,6 +160,11 @@ private:
|
|||
void ApplyHitReaction(EDamageType InDamageType);
|
||||
void ApplyImpactEffect(EDamageType InDamageType);
|
||||
|
||||
//Timeline
|
||||
void RotateToTarget();
|
||||
void StopRotateToTarget();
|
||||
void RotateToTargetUpdate(float Output);
|
||||
|
||||
private:
|
||||
void PerformDeath();
|
||||
bool PerformHitStun();
|
||||
|
@ -210,6 +217,13 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage", meta = (AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UAnimMontage> KnockdownBackMontage;
|
||||
|
||||
private: //Timeline
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Timeline", meta = (AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UTimelineComponent> RotateToTargetTimeLineComponent;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Timeline", meta = (AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UCurveFloat> CurveFloatTimeline;
|
||||
const float RotateToTargetInterpSpeed = 9.f;
|
||||
|
||||
private:
|
||||
FTimerHandle StaminaTimerHandle;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ void UCollisionComponent::CollisionTrace()
|
|||
for (auto hitResult : OutHits)
|
||||
{
|
||||
LastHit = hitResult;
|
||||
if (!AlreadyHitActors.Contains(LastHit.GetActor()))
|
||||
if (CanHitActor(LastHit.GetActor()))
|
||||
{
|
||||
HitActor = LastHit.GetActor();
|
||||
AlreadyHitActors.Add(HitActor);
|
||||
|
@ -65,10 +65,14 @@ void UCollisionComponent::ActivateCollision()
|
|||
|
||||
bool UCollisionComponent::CanHitActor(AActor* InActor)
|
||||
{
|
||||
bool result = false;
|
||||
IGameplayTagAssetInterface* tagInterface = Cast<IGameplayTagAssetInterface>(InActor);
|
||||
if(tagInterface)
|
||||
{
|
||||
|
||||
result &= !tagInterface->HasAnyMatchingGameplayTags(GameplayTagsIgnore); //Ignore Tag
|
||||
result &= !AlreadyHitActors.Contains(InActor); //Alread Hit
|
||||
result &= !ActorsToIgnore.Contains(InActor); //Ignore actor
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "CollisionComponent.generated.h"
|
||||
|
@ -48,6 +49,7 @@ public:
|
|||
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; }
|
||||
FORCEINLINE void SetGameplayTagsIgnore(FGameplayTagContainer& InputGameplayTagContainer) { GameplayTagsIgnore = InputGameplayTagContainer; }
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
FORCEINLINE void ActivateCollision();
|
||||
|
@ -58,27 +60,29 @@ public:
|
|||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
float TraceRadius;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
FName StartSocketName;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
FName EndSocketName;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> CollisionObjectTypes;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
TEnumAsByte<EDrawDebugTrace::Type> DrawDebugType;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
FGameplayTagContainer GameplayTagsIgnore;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta = (AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UPrimitiveComponent> CollisionMeshComponent;
|
||||
|
||||
bool bCollisionEnabled;
|
||||
UPROPERTY()
|
||||
TArray<TObjectPtr<AActor>> AlreadyHitActors;
|
||||
UPROPERTY()
|
||||
TArray<TObjectPtr<AActor>> ActorsToIgnore;
|
||||
FHitResult LastHit;
|
||||
UPROPERTY()
|
||||
TObjectPtr<AActor> HitActor;
|
||||
|
||||
bool bCollisionEnabled;
|
||||
FHitResult LastHit;
|
||||
|
||||
public:
|
||||
FOnHit OnHitDelegate;
|
||||
|
|
|
@ -52,7 +52,7 @@ void UStateManagerComponent::ResetState()
|
|||
CurrentState = FGameplayTag::EmptyTag;
|
||||
}
|
||||
|
||||
bool UStateManagerComponent::IsCurrentStateEqualToAny(FGameplayTagContainer StatesToCheck)
|
||||
bool UStateManagerComponent::IsCurrentStateEqualToAny(FGameplayTagContainer& StatesToCheck)
|
||||
{
|
||||
return StatesToCheck.HasTagExact(CurrentState);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ FGameplayTag UStateManagerComponent::GetCurrentAction()
|
|||
return CurrentAction;
|
||||
}
|
||||
|
||||
bool UStateManagerComponent::IsCurrentActionEqualToAny(FGameplayTagContainer ActionToCheck)
|
||||
bool UStateManagerComponent::IsCurrentActionEqualToAny(FGameplayTagContainer& ActionToCheck)
|
||||
{
|
||||
return ActionToCheck.HasTagExact(CurrentAction);
|
||||
}
|
|
@ -34,11 +34,11 @@ public:
|
|||
void SetCurrentState(FGameplayTag NewState);
|
||||
FGameplayTag GetCurrentState();
|
||||
void ResetState();
|
||||
bool IsCurrentStateEqualToAny(FGameplayTagContainer StatesToCheck);
|
||||
bool IsCurrentStateEqualToAny(FGameplayTagContainer& StatesToCheck);
|
||||
|
||||
void SetCurrentAction(FGameplayTag NewAction);
|
||||
FGameplayTag GetCurrentAction();
|
||||
bool IsCurrentActionEqualToAny(FGameplayTagContainer ActionToCheck);
|
||||
bool IsCurrentActionEqualToAny(FGameplayTagContainer& ActionToCheck);
|
||||
|
||||
public: //Delegate
|
||||
FStateBegin OnStateBegin;
|
||||
|
|
|
@ -12,12 +12,17 @@ void FCombatGameplayTags::InitializeNativeGameplayTags()
|
|||
return;
|
||||
|
||||
/**
|
||||
* Player
|
||||
* Character
|
||||
*/
|
||||
GameplayTags.Character_Player = UGameplayTagsManager::Get().AddNativeGameplayTag(
|
||||
FName("Character.Player"),
|
||||
FString("Player")
|
||||
);
|
||||
|
||||
GameplayTags.Character_Enemy = UGameplayTagsManager::Get().AddNativeGameplayTag(
|
||||
FName("Character.Enemy"),
|
||||
FString("Enemy")
|
||||
);
|
||||
|
||||
/**
|
||||
* State
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
public:
|
||||
//Character
|
||||
FGameplayTag Character_Player;
|
||||
FGameplayTag Character_Enemy;
|
||||
|
||||
//State
|
||||
FGameplayTag Character_State_Attacking;
|
||||
|
|
Loading…
Reference in New Issue