parent
418e5a08b7
commit
8fcba9fa77
|
@ -136,4 +136,6 @@ ManualIPAddress=
|
|||
+PropertyRedirects=(OldName="/Script/D1.MasterAI.TargetingWidget",NewName="/Script/D1.MasterAI.TargetingWidgetComponent")
|
||||
+PropertyRedirects=(OldName="/Script/D1.HumanoidEnemy.HealthBar",NewName="/Script/D1.HumanoidEnemy.HealthBarComponent")
|
||||
+PropertyRedirects=(OldName="/Script/D1.T_FindNextPatrolPoint.TargetLocation",NewName="/Script/D1.T_FindNextPatrolPoint.BlackboardKey_TargetLocation")
|
||||
+PropertyRedirects=(OldName="/Script/D1.T_FindNextPatrolPoint.PatrolIndex",NewName="/Script/D1.T_FindNextPatrolPoint.BlackboardKey_PatrolIndex")
|
||||
+PropertyRedirects=(OldName="/Script/D1.T_FindNextPatrolPoint.PatrolIndex",NewName="/Script/D1.T_FindNextPatrolPoint.BlackboardKey_PatrolIndex")
|
||||
+PropertyRedirects=(OldName="/Script/D1.CombatCharacter.ToggleCombatAction",NewName="/Script/D1.CombatCharacter.ToggleCombatInputAction")
|
||||
+FunctionRedirects=(OldName="/Script/D1.BaseWeapon.ToggleCombat",NewName="/Script/D1.BaseWeapon.ToggleWeaponCombat")
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -6,6 +6,8 @@
|
|||
#include "GameplayTagAssetInterface.h"
|
||||
#include "MasterAI.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "Definitions/CombatGameplayTags.h"
|
||||
#include "Perception/AIPerceptionComponent.h"
|
||||
#include "Perception/AISenseConfig_Damage.h"
|
||||
#include "Perception/AISenseConfig_Sight.h"
|
||||
|
@ -38,11 +40,15 @@ void ACombatAIController::OnPossess(APawn* InPawn)
|
|||
Super::OnPossess(InPawn);
|
||||
|
||||
AMasterAI* AIpawn = Cast<AMasterAI>(InPawn);
|
||||
if(AIpawn)
|
||||
{
|
||||
MasterAI = AIpawn;
|
||||
RunBehaviorTree(MasterAI->GetBeHaviorTree());
|
||||
}
|
||||
if(!AIpawn)
|
||||
return;
|
||||
|
||||
MasterAI = AIpawn;
|
||||
UCombatComponent* combatComponent = MasterAI->GetComponentByClass<UCombatComponent>();
|
||||
combatComponent->OnCombatToggled.AddUObject(this, &ACombatAIController::OnCombatToggle);
|
||||
|
||||
RunBehaviorTree(MasterAI->GetBeHaviorTree());
|
||||
|
||||
}
|
||||
|
||||
void ACombatAIController::OnUpdatePerception(const TArray<AActor*>& PerceivedActors)
|
||||
|
@ -81,3 +87,8 @@ void ACombatAIController::OnUpdatePerception(const TArray<AActor*>& PerceivedAct
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatAIController::OnCombatToggle(bool IsCombatEnabled)
|
||||
{
|
||||
Blackboard->SetValueAsBool(TEXT("bCombatEnabled"), IsCombatEnabled);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,12 @@ public:
|
|||
protected: //Inherited Func
|
||||
virtual void OnPossess(APawn* InPawn) override;
|
||||
public: //Delegate Func
|
||||
//UAIPerceptionComponent Delegate
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void OnUpdatePerception(const TArray<AActor*>& PerceivedActors);
|
||||
|
||||
//UCombatComponent Delegate
|
||||
void OnCombatToggle(bool IsCombatEnabled);
|
||||
private:
|
||||
UPROPERTY()
|
||||
TObjectPtr<class AMasterAI> MasterAI;
|
||||
|
|
|
@ -4,14 +4,22 @@
|
|||
#include "AI/HumanoidEnemy.h"
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "Components/CollisionComponent.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "DamageType/AttackDamageType.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "UI/UI_HealthBar.h"
|
||||
|
||||
AHumanoidEnemy::AHumanoidEnemy()
|
||||
{
|
||||
TargetingWidgetComponent->SetRelativeLocation(FVector(0.f, 0.f, 132.f));
|
||||
|
||||
|
||||
//Setting SocketName
|
||||
AttachSocketName = TEXT("SwordHipAttachSocket");
|
||||
WeaponHandSocketName = TEXT("RightWeaponSocket");
|
||||
|
||||
//Setting UWidgetComponent
|
||||
HealthBarComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("HealthBar"));
|
||||
static ConstructorHelpers::FClassFinder<UUserWidget> WidgetRef(TEXT("/Game/CombatSystem/UI/WBP_HealthBar.WBP_HealthBar_C"));
|
||||
if(WidgetRef.Class)
|
||||
|
@ -23,11 +31,28 @@ AHumanoidEnemy::AHumanoidEnemy()
|
|||
HealthBarComponent->SetRelativeLocation(FVector(0.f, 0.f, 200.f));
|
||||
HealthBarComponent->SetVisibility(false);
|
||||
}
|
||||
|
||||
//Setting WeaponMeshComponent
|
||||
WeaponMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMeshComponent"));
|
||||
WeaponMeshComponent->SetRelativeLocationAndRotation(FVector(0.f, 0.f, 0.f), FRotator(0.f, 0.f, 0.f));
|
||||
WeaponMeshComponent->SetupAttachment(GetMesh(), AttachSocketName);
|
||||
WeaponMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
|
||||
//Setting MainWeaponCollisionComponent
|
||||
//Setting others is Parents
|
||||
MainWeaponCollisionComponent->OnHitDelegate.BindUObject(this, &AHumanoidEnemy::OnHit);
|
||||
|
||||
//Setting CombatComponent
|
||||
//Setting others is Parents
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &AHumanoidEnemy::OnCombatToggled);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
MainWeaponCollisionComponent->SetCollisionMeshComponent(WeaponMeshComponent);
|
||||
MainWeaponCollisionComponent->AddActorToIgnore(this);
|
||||
|
||||
if(APlayerController* playerController = UGameplayStatics::GetPlayerController(GetWorld(), 0))
|
||||
{
|
||||
|
@ -45,3 +70,36 @@ void AHumanoidEnemy::OnTargeted(bool bIsTargeted)
|
|||
Super::OnTargeted(bIsTargeted);
|
||||
HealthBarComponent->SetVisibility(bIsTargeted);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::OnHit(FHitResult hitResult)
|
||||
{
|
||||
ICombatInterface* pActor = Cast<ICombatInterface>(hitResult.GetActor());
|
||||
if (pActor)
|
||||
{
|
||||
if (pActor->Execute_CanReceiveDamage(hitResult.GetActor()))
|
||||
UGameplayStatics::ApplyPointDamage(hitResult.GetActor(), StatsComponent->GetCurrentStatValue(EStats::Damage), this->GetActorForwardVector(), hitResult, GetController(), this, UAttackDamageType::StaticClass());
|
||||
}
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::OnCombatToggled(bool IsCombatEnabled)
|
||||
{
|
||||
FName SocketName;
|
||||
if(IsCombatEnabled)
|
||||
SocketName = WeaponHandSocketName;
|
||||
else
|
||||
SocketName = AttachSocketName;
|
||||
FAttachmentTransformRules rules(EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, true);
|
||||
WeaponMeshComponent->AttachToComponent(GetMesh(), rules, SocketName);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::PerformDeath()
|
||||
{
|
||||
Super::PerformDeath();
|
||||
SimulateWeaponPhysics();
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::SimulateWeaponPhysics()
|
||||
{
|
||||
WeaponMeshComponent->SetCollisionProfileName(TEXT("PhysicsActor"), true);
|
||||
WeaponMeshComponent->SetSimulatePhysics(true);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public:
|
|||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="UI", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UWidgetComponent> HealthBarComponent;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Component", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UStaticMeshComponent> WeaponMeshComponent;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
@ -26,4 +28,19 @@ protected:
|
|||
protected:
|
||||
// Inherited via ITargetingInterface
|
||||
virtual void OnTargeted(bool bIsTargeted) override;
|
||||
|
||||
public: // Delegate
|
||||
//UCollisionComponent
|
||||
void OnHit(FHitResult hitResult);
|
||||
//UCombatComponent
|
||||
void OnCombatToggled(bool IsCombatEnabled);
|
||||
public:
|
||||
virtual void PerformDeath() override;
|
||||
void SimulateWeaponPhysics();
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, Blueprintable, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
FName AttachSocketName;
|
||||
UPROPERTY(EditAnywhere, Blueprintable, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
FName WeaponHandSocketName;
|
||||
};
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
#include "Components/InputComponent.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "GameFramework/Controller.h"
|
||||
#include "Actor/BaseWeapon.h"
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "Definitions/CombatGameplayTags.h"
|
||||
#include "Engine/DamageEvents.h"
|
||||
#include "NiagaraFunctionLibrary.h"
|
||||
#include "Components/CollisionComponent.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "DamageType/AttackDamageType.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
@ -71,6 +72,17 @@ AMasterAI::AMasterAI()
|
|||
StatsComponent = CreateDefaultSubobject<UStatsComponent>(TEXT("StatsComponent"));
|
||||
StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &AMasterAI::CharacterCurrentStatValueUpdated);
|
||||
|
||||
// Setting MainWeaponCollisionComponent
|
||||
// Setting OnHit Func is Child Class
|
||||
MainWeaponCollisionComponent = CreateDefaultSubobject<UCollisionComponent>(TEXT("CollisionComponent"));
|
||||
MainWeaponCollisionComponent->SetTraceRaius(20.f);
|
||||
MainWeaponCollisionComponent->SetStartSocketName(TEXT("WeaponStart"));
|
||||
MainWeaponCollisionComponent->SetEndSocketName(TEXT("WeaponEnd"));
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> InputCollisionObjectTypes;
|
||||
InputCollisionObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
|
||||
MainWeaponCollisionComponent->SetCollisionObjectTypes(InputCollisionObjectTypes);
|
||||
MainWeaponCollisionComponent->SetDrawDebugType(EDrawDebugTrace::None);
|
||||
|
||||
//Setting MovementSpeed
|
||||
MovementSpeedMode = EMovementSpeedMode::Jogging;
|
||||
WalkingSpeed = 200.f;
|
||||
|
@ -164,6 +176,90 @@ void AMasterAI::SetCanMove_Implementation(bool inputCanMove)
|
|||
bCanMove = inputCanMove;
|
||||
}
|
||||
|
||||
void AMasterAI::ActivateCollision_Implementation(ECollisionPart CollisionPart)
|
||||
{
|
||||
if(StateManagerComponent->GetCurrentState() != FCombatGameplayTags::Get().Character_State_Dead) //TODO : 마지막 틱에서 충돌활성화 되는 이슈 방지...가 안됨.
|
||||
MainWeaponCollisionComponent->ActivateCollision();
|
||||
}
|
||||
|
||||
void AMasterAI::DeactivateCollision_Implementation(ECollisionPart CollisionPart)
|
||||
{
|
||||
MainWeaponCollisionComponent->DeactivateCollision();
|
||||
}
|
||||
|
||||
void AMasterAI::ToggleCombat_Implementation()
|
||||
{
|
||||
if (!IsValid(CombatComponent))
|
||||
return;
|
||||
CombatComponent->SetCombatEnabled(!CombatComponent->GetCombatEnabled());
|
||||
}
|
||||
|
||||
float AMasterAI::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex)
|
||||
{
|
||||
TArray<UAnimMontage*> montages = GetActionMontage(ActionTag);
|
||||
int32 montageIdx = MontageIndex;
|
||||
|
||||
if(bRandomIndex)
|
||||
montageIdx = FMath::RandRange(0, montages.Num() - 1);
|
||||
else if (montages.Num() <= montageIdx)
|
||||
montageIdx = 0;
|
||||
|
||||
if (!montages.IsValidIndex(montageIdx))
|
||||
return false;
|
||||
|
||||
UAnimMontage* actionMontage = montages[montageIdx];
|
||||
|
||||
float actionDuration = 0.f;
|
||||
if (IsValid(actionMontage))
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(StateTag);
|
||||
StateManagerComponent->SetCurrentAction(ActionTag);
|
||||
actionDuration = PlayAnimMontage(actionMontage);
|
||||
}
|
||||
else
|
||||
{
|
||||
FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str);
|
||||
}
|
||||
return actionDuration;
|
||||
}
|
||||
|
||||
float AMasterAI::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex)
|
||||
{
|
||||
TArray<UAnimMontage*> montages = GetActionMontage(AttackType);
|
||||
int32 attackIdx = AttackIndex;
|
||||
|
||||
if(bRandomIndex)
|
||||
attackIdx = FMath::RandRange(0, montages.Num() - 1);
|
||||
else if (montages.Num() <= attackIdx)
|
||||
attackIdx = 0;
|
||||
|
||||
if (!montages.IsValidIndex(attackIdx))
|
||||
return 0.f;
|
||||
|
||||
UAnimMontage* attackMontage = montages[attackIdx];
|
||||
float attackDuration = 0.f;
|
||||
if (!IsValid(attackMontage))
|
||||
{
|
||||
FString debugStr = FString::Printf(TEXT("Index %d Is NOT VALID!!"), attackIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking);
|
||||
StateManagerComponent->SetCurrentAction(AttackType);
|
||||
|
||||
attackDuration = PlayAnimMontage(attackMontage);
|
||||
|
||||
int idx = attackIdx + 1;
|
||||
if (idx >= montages.Num())
|
||||
idx = 0;
|
||||
|
||||
CombatComponent->SetAttackCount(idx);
|
||||
}
|
||||
return attackDuration;
|
||||
}
|
||||
|
||||
bool AMasterAI::CanBeTargeted()
|
||||
{
|
||||
return (StateManagerComponent->GetCurrentState() != FCombatGameplayTags::Get().Character_State_Dead);
|
||||
|
@ -239,32 +335,13 @@ void AMasterAI::CharacterCurrentStatValueUpdated(EStats statType, float value)
|
|||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Dead);
|
||||
}
|
||||
|
||||
void AMasterAI::ToggleCombatEvent()
|
||||
{
|
||||
if (!CanPerformToggleCombat())
|
||||
return;
|
||||
|
||||
if (!CombatComponent->GetCombatEnabled())
|
||||
PerformAction(FCombatGameplayTags::Get().Character_State_GeneralActionState, FCombatGameplayTags::Get().Character_Action_EnterCombat, 0);
|
||||
else
|
||||
PerformAction(FCombatGameplayTags::Get().Character_State_GeneralActionState, FCombatGameplayTags::Get().Character_Action_ExitCombat, 0);
|
||||
}
|
||||
|
||||
void AMasterAI::AttackEvent()
|
||||
{
|
||||
if (!CanPerformAttack())
|
||||
return;
|
||||
|
||||
if (CombatComponent->GetCombatEnabled())
|
||||
PerformAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount());
|
||||
else
|
||||
ToggleCombatEvent();
|
||||
}
|
||||
|
||||
void AMasterAI::ChargeAttackEvent()
|
||||
{
|
||||
if (CanPerformAttack())
|
||||
PerformAttack(FCombatGameplayTags::Get().Character_Action_Attack_ChargedAttack, CombatComponent->GetAttackCount());
|
||||
PerformCombatAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount(), false);
|
||||
}
|
||||
|
||||
void AMasterAI::ApplyHitReactionPhysicsVelocity(float InitialSpeed)
|
||||
|
@ -339,64 +416,6 @@ void AMasterAI::ApplyImpactEffect(EDamageType InDamageType)
|
|||
UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(), HitEmitter, LastHitInfo.Location);
|
||||
}
|
||||
|
||||
void AMasterAI::PerformAttack(FGameplayTag attackType, int32 attackIndex)
|
||||
{
|
||||
TArray<UAnimMontage*> montages = GetActionMontage(attackType);
|
||||
int32 attackIdx = attackIndex;
|
||||
|
||||
if (montages.Num() <= attackIdx)
|
||||
attackIdx = 0;
|
||||
if (!montages.IsValidIndex(attackIdx))
|
||||
return;
|
||||
|
||||
UAnimMontage* attackMontage = montages[attackIdx];
|
||||
if (!IsValid(attackMontage))
|
||||
{
|
||||
FString debugStr = FString::Printf(TEXT("Index %d Is NOT VALID!!"), attackIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking);
|
||||
StateManagerComponent->SetCurrentAction(attackType);
|
||||
|
||||
PlayAnimMontage(attackMontage);
|
||||
|
||||
int idx = attackIdx + 1;
|
||||
if (idx >= montages.Num())
|
||||
idx = 0;
|
||||
|
||||
CombatComponent->SetAttackCount(idx);
|
||||
}
|
||||
}
|
||||
|
||||
bool AMasterAI::PerformAction(FGameplayTag characterState, FGameplayTag characterAction, int32 montageIndex)
|
||||
{
|
||||
TArray<UAnimMontage*> montages = GetActionMontage(characterAction);
|
||||
int32 montageIdx = montageIndex;
|
||||
|
||||
if (montages.Num() <= montageIdx)
|
||||
montageIdx = 0;
|
||||
if (!montages.IsValidIndex(montageIdx))
|
||||
return false;
|
||||
|
||||
UAnimMontage* actionMontage = montages[montageIdx];
|
||||
if (IsValid(actionMontage))
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(characterState);
|
||||
StateManagerComponent->SetCurrentAction(characterAction);
|
||||
PlayAnimMontage(actionMontage);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AMasterAI::PerformDeath()
|
||||
{
|
||||
EnableRagdoll();
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "Components/TargetingComponent.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "Engine/TargetPoint.h"
|
||||
#include "Interface/TargetingInterface.h"
|
||||
|
@ -28,9 +26,12 @@ protected:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UCombatComponent> CombatComponent;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<UStateManagerComponent> StateManagerComponent;
|
||||
TObjectPtr<class UStateManagerComponent> StateManagerComponent;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<UStatsComponent> StatsComponent;
|
||||
TObjectPtr<class UStatsComponent> StatsComponent;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UCollisionComponent> MainWeaponCollisionComponent;
|
||||
|
||||
protected:
|
||||
// APawn interface
|
||||
virtual void BeginPlay() override;
|
||||
|
@ -56,9 +57,20 @@ public:
|
|||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void SetCanMove(bool inputCanMove);
|
||||
virtual void SetCanMove_Implementation(bool inputCanMove) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ActivateCollision(ECollisionPart CollisionPart);
|
||||
virtual void ActivateCollision_Implementation(ECollisionPart CollisionPart) override;
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void DeactivateCollision(ECollisionPart CollisionPart);
|
||||
virtual void DeactivateCollision_Implementation(ECollisionPart CollisionPart) override;
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ToggleCombat();
|
||||
virtual void ToggleCombat_Implementation() override;
|
||||
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); }
|
||||
|
||||
virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex);
|
||||
virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex);
|
||||
|
||||
// Inherited via ITargetingInterface
|
||||
virtual bool CanBeTargeted() override;
|
||||
virtual void OnTargeted(bool bIsTargeted) override;
|
||||
|
@ -72,9 +84,7 @@ private://Delegate
|
|||
void CharacterCurrentStatValueUpdated(EStats statType, float value);
|
||||
|
||||
private:
|
||||
void ToggleCombatEvent();
|
||||
void AttackEvent();
|
||||
void ChargeAttackEvent();
|
||||
void ApplyHitReactionPhysicsVelocity(float InitialSpeed);
|
||||
void EnableRagdoll();
|
||||
void DisableSprint();
|
||||
|
@ -82,10 +92,8 @@ private:
|
|||
void ApplyHitReaction(EDamageType InDamageType);
|
||||
void ApplyImpactEffect(EDamageType InDamageType);
|
||||
|
||||
private:
|
||||
void PerformAttack(FGameplayTag attackType, int32 attackIndex);
|
||||
bool PerformAction(FGameplayTag characterState, FGameplayTag characterAction, int32 montageIndex);
|
||||
void PerformDeath();
|
||||
protected:
|
||||
virtual void PerformDeath();
|
||||
bool PerformHitStun();
|
||||
bool PerformKnockdown();
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/S_UpdateBehavior.h"
|
||||
#include "MasterAI.h"
|
||||
#include "AIController.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "BehaviorTree/BTFunctionLibrary.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "Definitions/CombatGameplayTags.h"
|
||||
|
||||
void US_UpdateBehavior::OnSearchStart(FBehaviorTreeSearchData& SearchData)
|
||||
{
|
||||
Super::OnSearchStart(SearchData);
|
||||
|
||||
ControlledMasterAI = Cast<AMasterAI>(SearchData.OwnerComp.GetAIOwner()->GetPawn());
|
||||
check(ControlledMasterAI);
|
||||
|
||||
BlackboardComponent = SearchData.OwnerComp.GetBlackboardComponent();
|
||||
|
||||
OwnerController = Cast<AAIController>(ControlledMasterAI->GetController());
|
||||
check(OwnerController);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
|
||||
{
|
||||
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
|
||||
UpdateBehavior();
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
|
||||
{
|
||||
Super::OnBecomeRelevant(OwnerComp, NodeMemory);
|
||||
SetBehavior(EAIBehavior::Patrol);
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::UpdateBehavior()
|
||||
{
|
||||
if(!IsValid(ControlledMasterAI) || !IsValid(OwnerController))
|
||||
return;
|
||||
UStateManagerComponent* StateManagerComponent = ControlledMasterAI->GetComponentByClass<UStateManagerComponent>();
|
||||
if(!StateManagerComponent)
|
||||
return;
|
||||
if(StateManagerComponent->GetCurrentState() == FCombatGameplayTags::Get().Character_State_Dead)
|
||||
{
|
||||
SetBehavior(EAIBehavior::Nothing);
|
||||
return;
|
||||
}
|
||||
|
||||
const AActor* targetActor = Cast<AActor>(BlackboardComponent->GetValueAsObject(BlackboardKey_TargetKey.SelectedKeyName));
|
||||
if(!targetActor)
|
||||
{
|
||||
SetBehavior(EAIBehavior::Patrol);
|
||||
return;
|
||||
}
|
||||
|
||||
CanSeeEnemy = true;
|
||||
float dist = targetActor->GetDistanceTo(ControlledMasterAI);
|
||||
if(dist <= AttackingRange)
|
||||
SetBehavior(EAIBehavior::Attack);
|
||||
else
|
||||
SetBehavior(EAIBehavior::Chase);
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::SetBehavior(EAIBehavior NewBehavior)
|
||||
{
|
||||
BlackboardComponent->SetValueAsEnum(BlackboardKey_BehaviorKey.SelectedKeyName, (uint8)NewBehavior);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTService.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "S_UpdateBehavior.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API US_UpdateBehavior : public UBTService
|
||||
{
|
||||
GENERATED_BODY()
|
||||
protected:
|
||||
virtual void OnSearchStart(FBehaviorTreeSearchData& SearchData) override;
|
||||
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
|
||||
virtual void OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
|
||||
|
||||
public:
|
||||
void UpdateBehavior();
|
||||
void SetBehavior(EAIBehavior NewBehavior);
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BlackBoard", meta=(AllowPrivateAccess="true"))
|
||||
FBlackboardKeySelector BlackboardKey_BehaviorKey;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BlackBoard", meta=(AllowPrivateAccess="true"))
|
||||
FBlackboardKeySelector BlackboardKey_TargetKey;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BlackBoard", meta=(AllowPrivateAccess="true"))
|
||||
float AttackingRange;
|
||||
|
||||
private:
|
||||
TObjectPtr<class UBlackboardComponent> BlackboardComponent;
|
||||
TObjectPtr<class AMasterAI> ControlledMasterAI;
|
||||
TObjectPtr<class AAIController> OwnerController;
|
||||
bool CanSeeEnemy;
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_PerformAction.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
|
||||
EBTNodeResult::Type UT_PerformAction::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
|
||||
{
|
||||
EBTNodeResult::Type result = Super::ExecuteTask(OwnerComp, NodeMemory);
|
||||
if(result == EBTNodeResult::Failed)
|
||||
return EBTNodeResult::Failed;
|
||||
|
||||
APawn* ControllingPawn = OwnerComp.GetAIOwner()->GetPawn();
|
||||
if(ControllingPawn == nullptr)
|
||||
return EBTNodeResult::Failed;
|
||||
ICombatInterface* CombatInterface = Cast<ICombatInterface>(ControllingPawn);
|
||||
if(!CombatInterface)
|
||||
return EBTNodeResult::Failed;
|
||||
|
||||
float actionDuration = CombatInterface->PerformCombatAction(ActionTag, StateTag, MontageIndex, RandomIndex);
|
||||
actionDuration += ActionDurationModifier;
|
||||
FTimerHandle ActionTimer;
|
||||
GetWorld()->GetTimerManager().SetTimer(ActionTimer, FTimerDelegate::CreateLambda([&]()
|
||||
{
|
||||
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
|
||||
}), actionDuration, false);
|
||||
|
||||
return EBTNodeResult::InProgress;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "T_PerformAction.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API UT_PerformAction : public UBTTaskNode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
FGameplayTag ActionTag;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
FGameplayTag StateTag;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
int32 MontageIndex;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
bool RandomIndex;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
float ActionDurationModifier;
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_PerformAttack.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
|
||||
EBTNodeResult::Type UT_PerformAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
|
||||
{
|
||||
EBTNodeResult::Type result = Super::ExecuteTask(OwnerComp, NodeMemory);
|
||||
if(result == EBTNodeResult::Failed)
|
||||
return EBTNodeResult::Failed;
|
||||
|
||||
APawn* ControllingPawn = OwnerComp.GetAIOwner()->GetPawn();
|
||||
if(ControllingPawn == nullptr)
|
||||
return EBTNodeResult::Failed;
|
||||
ICombatInterface* CombatInterface = Cast<ICombatInterface>(ControllingPawn);
|
||||
if(!CombatInterface)
|
||||
return EBTNodeResult::Failed;
|
||||
|
||||
float actionDuration = CombatInterface->PerformCombatAttack(AttackTypeTag, AttackIndex, RandomIndex);
|
||||
actionDuration += ActionDurationModifier;
|
||||
FTimerHandle ActionTimer;
|
||||
GetWorld()->GetTimerManager().SetTimer(ActionTimer, FTimerDelegate::CreateLambda([&]()
|
||||
{
|
||||
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
|
||||
}), actionDuration, false);
|
||||
|
||||
return EBTNodeResult::InProgress;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "T_PerformAttack.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API UT_PerformAttack : public UBTTaskNode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
FGameplayTag AttackTypeTag;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
int32 AttackIndex;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
bool RandomIndex;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
float ActionDurationModifier;
|
||||
};
|
|
@ -94,9 +94,9 @@ void ABaseDualWeapon::DeactivateCollision(ECollisionPart CollsionPart)
|
|||
}
|
||||
}
|
||||
|
||||
void ABaseDualWeapon::ToggleCombat(bool EnableCombat)
|
||||
void ABaseDualWeapon::ToggleWeaponCombat(bool EnableCombat)
|
||||
{
|
||||
Super::ToggleCombat(EnableCombat);
|
||||
Super::ToggleWeaponCombat(EnableCombat);
|
||||
|
||||
if(EnableCombat)
|
||||
AttachOffhandWeapon(SecondWeaponHandSocket);
|
||||
|
|
|
@ -24,7 +24,7 @@ protected:
|
|||
virtual void OnEquipped() override;
|
||||
virtual void ActivateCollision(ECollisionPart CollisionPart) override;
|
||||
virtual void DeactivateCollision(ECollisionPart CollsionPart) override;
|
||||
virtual void ToggleCombat(bool EnableCombat) override;
|
||||
virtual void ToggleWeaponCombat(bool EnableCombat) override;
|
||||
|
||||
public: //Delegate
|
||||
void OnHit_OffhandWeapon(FHitResult HitResult);
|
||||
|
|
|
@ -115,7 +115,7 @@ void ABaseWeapon::DeactivateCollision(ECollisionPart CollsionPart)
|
|||
CollisionComponent->DeactivateCollision();
|
||||
}
|
||||
|
||||
void ABaseWeapon::ToggleCombat(bool EnableCombat)
|
||||
void ABaseWeapon::ToggleWeaponCombat(bool EnableCombat)
|
||||
{
|
||||
if(!CombatComponent)
|
||||
return;
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
UFUNCTION(BlueprintCallable)
|
||||
virtual void DeactivateCollision(ECollisionPart CollsionPart);
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual void ToggleCombat(bool EnableCombat);
|
||||
virtual void ToggleWeaponCombat(bool EnableCombat);
|
||||
|
||||
public:
|
||||
TArray<UAnimMontage*> GetActionMontage(FGameplayTag characterAction);
|
||||
|
|
|
@ -214,7 +214,7 @@ void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerIn
|
|||
EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &ACombatCharacter::Interact);
|
||||
|
||||
//ToggleCombat
|
||||
EnhancedInputComponent->BindAction(ToggleCombatAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleCombat);
|
||||
EnhancedInputComponent->BindAction(ToggleCombatInputAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleCombatAction);
|
||||
|
||||
//LightAttack
|
||||
EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Triggered, this, &ACombatCharacter::LightChargeAttack);
|
||||
|
@ -243,6 +243,106 @@ void ACombatCharacter::SetCanMove_Implementation(bool inputCanMove)
|
|||
bCanMove = inputCanMove;
|
||||
}
|
||||
|
||||
void ACombatCharacter::ActivateCollision_Implementation(ECollisionPart CollisionPart)
|
||||
{
|
||||
ABaseWeapon* weapon = CombatComponent->GetMainWeapon();
|
||||
if(IsValid(weapon))
|
||||
weapon->ActivateCollision(CollisionPart);
|
||||
}
|
||||
|
||||
void ACombatCharacter::DeactivateCollision_Implementation(ECollisionPart CollisionPart)
|
||||
{
|
||||
ABaseWeapon* weapon = CombatComponent->GetMainWeapon();
|
||||
if(IsValid(weapon))
|
||||
weapon->DeactivateCollision(CollisionPart);
|
||||
}
|
||||
|
||||
void ACombatCharacter::ToggleCombat_Implementation()
|
||||
{
|
||||
ABaseWeapon* weapon = CombatComponent->GetMainWeapon();
|
||||
if (IsValid(weapon))
|
||||
weapon->ToggleWeaponCombat(!CombatComponent->GetCombatEnabled());
|
||||
}
|
||||
|
||||
float ACombatCharacter::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex)
|
||||
{
|
||||
//TODO : 나중에 이 함수로 바꿔서 쓰기 혹시 몰라 구현만 해놓음
|
||||
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
|
||||
if (!CurrentWeapon)
|
||||
return false;
|
||||
|
||||
TArray<UAnimMontage*> montages = CurrentWeapon->GetActionMontage(ActionTag);
|
||||
int32 montageIdx = MontageIndex;
|
||||
|
||||
if(bRandomIndex)
|
||||
montageIdx = FMath::RandRange(0, montages.Num() - 1);
|
||||
else if (montages.Num() <= montageIdx)
|
||||
montageIdx = 0;
|
||||
|
||||
if (!montages.IsValidIndex(montageIdx))
|
||||
return false;
|
||||
|
||||
UAnimMontage* actionMontage = montages[montageIdx];
|
||||
float actionDuration = 0.f;
|
||||
if (IsValid(actionMontage))
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(StateTag);
|
||||
StateManagerComponent->SetCurrentAction(ActionTag);
|
||||
actionDuration = PlayAnimMontage(actionMontage);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str);
|
||||
}
|
||||
return actionDuration;
|
||||
}
|
||||
|
||||
float ACombatCharacter::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex)
|
||||
{
|
||||
//TODO : 나중에 이 함수로 바꿔서 쓰기 혹시 몰라 구현만 해놓음
|
||||
if(!CombatComponent->GetCombatEnabled())
|
||||
return 0.f;
|
||||
|
||||
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
|
||||
if (!CurrentWeapon)
|
||||
return 0.f;
|
||||
|
||||
TArray<UAnimMontage*> montages = CurrentWeapon->GetActionMontage(AttackType);
|
||||
int32 attackIdx = AttackIndex;
|
||||
|
||||
if(bRandomIndex)
|
||||
attackIdx = FMath::RandRange(0, montages.Num() - 1);
|
||||
else if (montages.Num() <= attackIdx)
|
||||
attackIdx = 0;
|
||||
|
||||
if (!montages.IsValidIndex(attackIdx))
|
||||
return 0.f;
|
||||
|
||||
UAnimMontage* attackMontage = montages[attackIdx];
|
||||
float attackDuration = 0.f;
|
||||
if (!IsValid(attackMontage))
|
||||
{
|
||||
FString debugStr = FString::Printf(TEXT("Index %d Is NOT VALID!!"), attackIdx);
|
||||
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking);
|
||||
StateManagerComponent->SetCurrentAction(AttackType);
|
||||
|
||||
attackDuration = PlayAnimMontage(attackMontage);
|
||||
|
||||
int idx = attackIdx + 1;
|
||||
if (idx >= montages.Num())
|
||||
idx = 0;
|
||||
|
||||
CombatComponent->SetAttackCount(idx);
|
||||
}
|
||||
return attackDuration;
|
||||
}
|
||||
|
||||
void ACombatCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode)
|
||||
{
|
||||
if (NewSpeedMode == MovementSpeedMode)
|
||||
|
@ -340,7 +440,7 @@ void ACombatCharacter::Interact(const FInputActionValue& Value)
|
|||
}
|
||||
}
|
||||
|
||||
void ACombatCharacter::ToggleCombat(const FInputActionValue& Value)
|
||||
void ACombatCharacter::ToggleCombatAction(const FInputActionValue& Value)
|
||||
{
|
||||
bool bInput = Value.Get<bool>();
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class ACombatCharacter : public ACharacter, public ICombatInterface, public IGam
|
|||
|
||||
/* ToggleCombat Input Action */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||
class UInputAction* ToggleCombatAction;
|
||||
class UInputAction* ToggleCombatInputAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||
class UInputAction* LightAttackAction;
|
||||
|
@ -108,9 +108,20 @@ public:
|
|||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void SetCanMove(bool inputCanMove);
|
||||
virtual void SetCanMove_Implementation(bool inputCanMove) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ActivateCollision(ECollisionPart CollisionPart);
|
||||
virtual void ActivateCollision_Implementation(ECollisionPart CollisionPart) override;
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void DeactivateCollision(ECollisionPart CollisionPart);
|
||||
virtual void DeactivateCollision_Implementation(ECollisionPart CollisionPart) override;
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ToggleCombat();
|
||||
virtual void ToggleCombat_Implementation() override;
|
||||
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); }
|
||||
|
||||
virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex);
|
||||
virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex);
|
||||
|
||||
// Inherited via IGameplayTagAssetInterface
|
||||
virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override { TagContainer = OwnedGameplayTags; }
|
||||
public:
|
||||
|
@ -123,7 +134,7 @@ protected:
|
|||
void Look(const FInputActionValue& Value);
|
||||
void Jumping(const FInputActionValue& Value);
|
||||
void Interact(const FInputActionValue& Value);
|
||||
void ToggleCombat(const FInputActionValue& Value);
|
||||
void ToggleCombatAction(const FInputActionValue& Value);
|
||||
void LightAttack(const FInputActionValue& Value);
|
||||
void LightChargeAttack(const FInputActionInstance& Instance);
|
||||
void HeavyAttack(const FInputActionValue& Value);
|
||||
|
|
|
@ -67,7 +67,7 @@ private:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> CollisionObjectTypes;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Initialization", meta = (AllowPrivateAccess = "true"))
|
||||
TEnumAsByte<EDrawDebugTrace::Type> DrawDebugType;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta = (AllowPrivateAccess = "true"))
|
||||
|
|
|
@ -15,6 +15,7 @@ enum class EStats : uint8
|
|||
Health UMETA(DisplayName = "Health"),
|
||||
Stamina UMETA(DisplayName = "Stamina"),
|
||||
Armor UMETA(DisplayName = "Armor"),
|
||||
Damage UMETA(DisplayName = "Damage"),
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
|
|
|
@ -36,3 +36,13 @@ enum class EDamageType : uint8
|
|||
MeleeDamage UMETA(DisplayName = "MeleeDamage"),
|
||||
KnockdownDamage UMETA(DisplayName = "KnockdownDamage"),
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EAIBehavior : uint8
|
||||
{
|
||||
Nothing UMETA(DisplayName = "Nothing"),
|
||||
Attack UMETA(DisplayName = "Attack"),
|
||||
Chase UMETA(DisplayName = "Chase"),
|
||||
Patrol UMETA(DisplayName = "Patrol"),
|
||||
Hit UMETA(DisplayName = "Hit"),
|
||||
};
|
|
@ -4,3 +4,13 @@
|
|||
#include "Interface/CombatInterface.h"
|
||||
|
||||
// Add default functionality here for any ICombatInterface functions that are not pure virtual.
|
||||
float ICombatInterface::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex,
|
||||
bool bRandomIndex)
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float ICombatInterface::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex)
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "CombatInterface.generated.h"
|
||||
|
@ -35,6 +36,19 @@ public:
|
|||
bool CanReceiveDamage();
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void SetCanMove(bool inputCanMove);
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ActivateCollision(ECollisionPart CollisionPart);
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void DeactivateCollision(ECollisionPart CollisionPart);
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void ToggleCombat();
|
||||
|
||||
|
||||
UFUNCTION()
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() = 0;
|
||||
UFUNCTION(Category="CombatActions")
|
||||
virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex);
|
||||
UFUNCTION(Category="CombatActions")
|
||||
virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex);
|
||||
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue