parent
126c50c567
commit
51505f13cf
|
@ -138,4 +138,6 @@ ManualIPAddress=
|
|||
+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.CombatCharacter.ToggleCombatAction",NewName="/Script/D1.CombatCharacter.ToggleCombatInputAction")
|
||||
+FunctionRedirects=(OldName="/Script/D1.BaseWeapon.ToggleCombat",NewName="/Script/D1.BaseWeapon.ToggleWeaponCombat")
|
||||
+FunctionRedirects=(OldName="/Script/D1.BaseWeapon.ToggleCombat",NewName="/Script/D1.BaseWeapon.ToggleWeaponCombat")
|
||||
+PropertyRedirects=(OldName="/Script/D1.S_UpdateBehavior.AttackingRange",NewName="/Script/D1.S_UpdateBehavior.TotalAttackingDistance")
|
||||
+PropertyRedirects=(OldName="/Script/D1.S_UpdateBehavior.TotalAttackingDistanceRange",NewName="/Script/D1.S_UpdateBehavior.TotalAttackingDistance")
|
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.
|
@ -0,0 +1,14 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/BehaviorTreeNodes/D_ChanceCondition.h"
|
||||
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
bool UD_ChanceCondition::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
||||
{
|
||||
if(!Super::CalculateRawConditionValue(OwnerComp, NodeMemory))
|
||||
return false;
|
||||
|
||||
return (ChangePercentage >= UKismetMathLibrary::RandomIntegerInRange(0, 100));
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTDecorator.h"
|
||||
#include "D_ChanceCondition.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API UD_ChanceCondition : public UBTDecorator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true", UIMin = "0", UIMax = "100", ClampMin = "0", ClampMax = "100"))
|
||||
int ChangePercentage;
|
||||
};
|
|
@ -1,8 +1,8 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/S_UpdateBehavior.h"
|
||||
#include "MasterAI.h"
|
||||
#include "AI/BehaviorTreeNodes/S_UpdateBehavior.h"
|
||||
#include "AI/MasterAI.h"
|
||||
#include "AIController.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "BehaviorTree/BTFunctionLibrary.h"
|
||||
|
@ -58,13 +58,24 @@ void US_UpdateBehavior::UpdateBehavior()
|
|||
|
||||
CanSeeEnemy = true;
|
||||
float dist = targetActor->GetDistanceTo(ControlledMasterAI);
|
||||
if(dist <= AttackingRange)
|
||||
if(dist <= TotalAttackingDistance)
|
||||
{
|
||||
SetBehavior(EAIBehavior::Attack);
|
||||
if(dist <= CloseRangeAttackingDistance)
|
||||
SetAttackingRangeType(EAIAttackRange::CloseRange);
|
||||
else
|
||||
SetAttackingRangeType(EAIAttackRange::MediumRange);
|
||||
}
|
||||
else
|
||||
SetBehavior(EAIBehavior::Chase);
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::SetBehavior(EAIBehavior NewBehavior)
|
||||
{
|
||||
BlackboardComponent->SetValueAsEnum(BlackboardKey_BehaviorKey.SelectedKeyName, (uint8)NewBehavior);
|
||||
BlackboardComponent->SetValueAsEnum(BlackboardKey_BehaviorKey.SelectedKeyName, static_cast<uint8>(NewBehavior));
|
||||
}
|
||||
|
||||
void US_UpdateBehavior::SetAttackingRangeType(EAIAttackRange NewAttackRange)
|
||||
{
|
||||
BlackboardComponent->SetValueAsEnum(BlackboardKey_AttackingRangeType.SelectedKeyName, static_cast<uint8>(NewAttackRange));
|
||||
}
|
|
@ -23,13 +23,18 @@ protected:
|
|||
public:
|
||||
void UpdateBehavior();
|
||||
void SetBehavior(EAIBehavior NewBehavior);
|
||||
void SetAttackingRangeType(EAIAttackRange NewAttackRange);
|
||||
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;
|
||||
FBlackboardKeySelector BlackboardKey_AttackingRangeType;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BlackBoard", meta=(AllowPrivateAccess="true"))
|
||||
float TotalAttackingDistance;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="BlackBoard", meta=(AllowPrivateAccess="true"))
|
||||
float CloseRangeAttackingDistance;
|
||||
|
||||
private:
|
||||
TObjectPtr<class UBlackboardComponent> BlackboardComponent;
|
|
@ -1,9 +1,9 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_FindNextPatrolPoint.h"
|
||||
#include "AI/BehaviorTreeNodes/T_FindNextPatrolPoint.h"
|
||||
#include "AIController.h"
|
||||
#include "MasterAI.h"
|
||||
#include "AI/MasterAI.h"
|
||||
#include "NavigationSystem.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_PerformAction.h"
|
||||
#include "AI/BehaviorTreeNodes/T_PerformAction.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "Interface/CombatInterface.h"
|
|
@ -1,7 +1,7 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_PerformAttack.h"
|
||||
#include "AI/BehaviorTreeNodes/T_PerformAttack.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "Interface/CombatInterface.h"
|
|
@ -1,7 +1,7 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/T_SetMovementSpeed.h"
|
||||
#include "AI/BehaviorTreeNodes/T_SetMovementSpeed.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "AIController.h"
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/BossEnemy.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_BossHealth.h"
|
||||
#include "UI/UI_HealthBar.h"
|
||||
|
||||
ABossEnemy::ABossEnemy()
|
||||
{
|
||||
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)
|
||||
{
|
||||
HealthBarComponent->SetWidgetClass(WidgetRef.Class);
|
||||
HealthBarComponent->SetWidgetSpace(EWidgetSpace::Screen);
|
||||
HealthBarComponent->SetDrawSize({150.f, 10.f});
|
||||
HealthBarComponent->SetupAttachment(GetMesh());
|
||||
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, &ABossEnemy::OnHit);
|
||||
|
||||
//Setting CombatComponent
|
||||
//Setting others is Parents
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &ABossEnemy::OnCombatToggled);
|
||||
}
|
||||
|
||||
void ABossEnemy::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
MainWeaponCollisionComponent->SetCollisionMeshComponent(WeaponMeshComponent);
|
||||
MainWeaponCollisionComponent->AddActorToIgnore(this);
|
||||
|
||||
APlayerController* playerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
|
||||
if(!playerController)
|
||||
return;
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if (World)
|
||||
{
|
||||
APlayerController* Contorller = World->GetFirstPlayerController();
|
||||
if(Controller)
|
||||
{
|
||||
UUI_BossHealth* BossHealthRef = CreateWidget<UUI_BossHealth>(Contorller, UUI_BossHealth::StaticClass());
|
||||
if (BossHealthRef) //ExposeOnSpawn 대용으로 사용
|
||||
{
|
||||
BossHealthWidget = BossHealthRef;
|
||||
BossHealthWidget->InitializeWidget(StatsComponent);
|
||||
BossHealthRef->AddToViewport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ABossEnemy::OnTargetSet(AActor* NewTarget)
|
||||
{
|
||||
Super::OnTargetSet(NewTarget);
|
||||
SetBossHealthVisibility(IsValid(NewTarget));
|
||||
}
|
||||
|
||||
void ABossEnemy::OnTargeted(bool bIsTargeted)
|
||||
{
|
||||
Super::OnTargeted(bIsTargeted);
|
||||
}
|
||||
|
||||
void ABossEnemy::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 ABossEnemy::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 ABossEnemy::PerformDeath()
|
||||
{
|
||||
//TODO : 죽었을 때 무기에 Collision이 남아있는 버그 있음
|
||||
Super::PerformDeath();
|
||||
SimulateWeaponPhysics();
|
||||
SetBossHealthVisibility(false);
|
||||
}
|
||||
|
||||
void ABossEnemy::SimulateWeaponPhysics()
|
||||
{
|
||||
WeaponMeshComponent->SetCollisionProfileName(TEXT("PhysicsActor"), true);
|
||||
WeaponMeshComponent->SetSimulatePhysics(true);
|
||||
}
|
||||
|
||||
void ABossEnemy::SetBossHealthVisibility(bool IsVisible)
|
||||
{
|
||||
if(!IsValid(BossHealthWidget))
|
||||
return;
|
||||
|
||||
if(IsVisible)
|
||||
BossHealthWidget->SetVisibility(ESlateVisibility::Visible);
|
||||
else
|
||||
BossHealthWidget->SetVisibility(ESlateVisibility::Hidden);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AI/MasterAI.h"
|
||||
#include "BossEnemy.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API ABossEnemy : public AMasterAI
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
ABossEnemy();
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
// Inherited via AMasterAI
|
||||
virtual void OnTargetSet(AActor* NewTarget) override;
|
||||
|
||||
// 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();
|
||||
void SetBossHealthVisibility(bool IsVisible);
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, Blueprintable, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
FName AttachSocketName;
|
||||
UPROPERTY(EditAnywhere, Blueprintable, Category="Initialization", meta=(AllowPrivateAccess="true"))
|
||||
FName WeaponHandSocketName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UUI_BossHealth> BossHealthWidget;
|
||||
|
||||
};
|
|
@ -25,7 +25,7 @@ ACombatAIController::ACombatAIController()
|
|||
AffiliationFilter.bDetectFriendlies = true;
|
||||
AffiliationFilter.bDetectNeutrals = true;
|
||||
SightConfig->DetectionByAffiliation = AffiliationFilter;
|
||||
SightConfig->AutoSuccessRangeFromLastSeenLocation = 500.f;
|
||||
SightConfig->AutoSuccessRangeFromLastSeenLocation = 1000.f;
|
||||
PerceptionComponent->ConfigureSense(*SightConfig);
|
||||
|
||||
DamageConfig = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("DamageConfig"));
|
||||
|
@ -66,22 +66,24 @@ void ACombatAIController::OnUpdatePerception(const TArray<AActor*>& PerceivedAct
|
|||
{
|
||||
if(Info.WasSuccessfullySensed())
|
||||
{
|
||||
if(Cast<IGameplayTagAssetInterface>(SensoredActor)->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
|
||||
{
|
||||
Blackboard->SetValueAsObject(TEXT("Target"), SensoredActor);
|
||||
}
|
||||
IGameplayTagAssetInterface* CurActor = Cast<IGameplayTagAssetInterface>(SensoredActor);
|
||||
if(!CurActor)
|
||||
continue;
|
||||
if(CurActor->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
|
||||
SetTargetActor(SensoredActor);
|
||||
}
|
||||
else
|
||||
Blackboard->SetValueAsObject(TEXT("Target"), nullptr);
|
||||
SetTargetActor(SensoredActor);
|
||||
}
|
||||
else if(SensedClass == UAISense_Damage::StaticClass())
|
||||
{
|
||||
if(Info.WasSuccessfullySensed() && !Info.IsExpired()) //After DamageConfig->GetMaxAge then Expired
|
||||
{
|
||||
if(Cast<IGameplayTagAssetInterface>(SensoredActor)->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
|
||||
{
|
||||
Blackboard->SetValueAsObject(TEXT("Target"), SensoredActor);
|
||||
}
|
||||
IGameplayTagAssetInterface* CurActor = Cast<IGameplayTagAssetInterface>(SensoredActor);
|
||||
if(!CurActor)
|
||||
continue;
|
||||
if(CurActor->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
|
||||
SetTargetActor(SensoredActor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,3 +94,10 @@ void ACombatAIController::OnCombatToggle(bool IsCombatEnabled)
|
|||
{
|
||||
Blackboard->SetValueAsBool(TEXT("bCombatEnabled"), IsCombatEnabled);
|
||||
}
|
||||
|
||||
void ACombatAIController::SetTargetActor(AActor* NewTargetActor)
|
||||
{
|
||||
Blackboard->SetValueAsObject(TEXT("Target"), NewTargetActor);
|
||||
if(IsValid(MasterAI))
|
||||
MasterAI->OnTargetSet(NewTargetActor);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ public: //Delegate Func
|
|||
|
||||
//UCombatComponent Delegate
|
||||
void OnCombatToggle(bool IsCombatEnabled);
|
||||
public:
|
||||
void SetTargetActor(AActor* NewTargetActor);
|
||||
private:
|
||||
UPROPERTY()
|
||||
TObjectPtr<class AMasterAI> MasterAI;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/HumanoidEnemy.h"
|
||||
#include "AI/HeavyMobEnemy.h"
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "Components/CollisionComponent.h"
|
||||
|
@ -11,7 +11,7 @@
|
|||
#include "Kismet/GameplayStatics.h"
|
||||
#include "UI/UI_HealthBar.h"
|
||||
|
||||
AHumanoidEnemy::AHumanoidEnemy()
|
||||
AHeavyMobEnemy::AHeavyMobEnemy()
|
||||
{
|
||||
TargetingWidgetComponent->SetRelativeLocation(FVector(0.f, 0.f, 132.f));
|
||||
|
||||
|
@ -40,14 +40,14 @@ AHumanoidEnemy::AHumanoidEnemy()
|
|||
|
||||
//Setting MainWeaponCollisionComponent
|
||||
//Setting others is Parents
|
||||
MainWeaponCollisionComponent->OnHitDelegate.BindUObject(this, &AHumanoidEnemy::OnHit);
|
||||
MainWeaponCollisionComponent->OnHitDelegate.BindUObject(this, &AHeavyMobEnemy::OnHit);
|
||||
|
||||
//Setting CombatComponent
|
||||
//Setting others is Parents
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &AHumanoidEnemy::OnCombatToggled);
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &AHeavyMobEnemy::OnCombatToggled);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::BeginPlay()
|
||||
void AHeavyMobEnemy::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
|
@ -65,13 +65,13 @@ void AHumanoidEnemy::BeginPlay()
|
|||
}
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::OnTargeted(bool bIsTargeted)
|
||||
void AHeavyMobEnemy::OnTargeted(bool bIsTargeted)
|
||||
{
|
||||
Super::OnTargeted(bIsTargeted);
|
||||
HealthBarComponent->SetVisibility(bIsTargeted);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::OnHit(FHitResult hitResult)
|
||||
void AHeavyMobEnemy::OnHit(FHitResult hitResult)
|
||||
{
|
||||
ICombatInterface* pActor = Cast<ICombatInterface>(hitResult.GetActor());
|
||||
if (pActor)
|
||||
|
@ -81,7 +81,7 @@ void AHumanoidEnemy::OnHit(FHitResult hitResult)
|
|||
}
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::OnCombatToggled(bool IsCombatEnabled)
|
||||
void AHeavyMobEnemy::OnCombatToggled(bool IsCombatEnabled)
|
||||
{
|
||||
FName SocketName;
|
||||
if(IsCombatEnabled)
|
||||
|
@ -92,14 +92,14 @@ void AHumanoidEnemy::OnCombatToggled(bool IsCombatEnabled)
|
|||
WeaponMeshComponent->AttachToComponent(GetMesh(), rules, SocketName);
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::PerformDeath()
|
||||
void AHeavyMobEnemy::PerformDeath()
|
||||
{
|
||||
//TODO : 죽었을 때 무기에 Collision이 남아있는 버그 있음
|
||||
Super::PerformDeath();
|
||||
SimulateWeaponPhysics();
|
||||
}
|
||||
|
||||
void AHumanoidEnemy::SimulateWeaponPhysics()
|
||||
void AHeavyMobEnemy::SimulateWeaponPhysics()
|
||||
{
|
||||
WeaponMeshComponent->SetCollisionProfileName(TEXT("PhysicsActor"), true);
|
||||
WeaponMeshComponent->SetSimulatePhysics(true);
|
|
@ -4,17 +4,17 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AI/MasterAI.h"
|
||||
#include "HumanoidEnemy.generated.h"
|
||||
#include "HeavyMobEnemy.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API AHumanoidEnemy : public AMasterAI
|
||||
class D1_API AHeavyMobEnemy : public AMasterAI
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
AHumanoidEnemy();
|
||||
AHeavyMobEnemy();
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="UI", meta=(AllowPrivateAccess="true"))
|
|
@ -71,6 +71,12 @@ AMasterAI::AMasterAI()
|
|||
// Setting StatsComponent
|
||||
StatsComponent = CreateDefaultSubobject<UStatsComponent>(TEXT("StatsComponent"));
|
||||
StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &AMasterAI::CharacterCurrentStatValueUpdated);
|
||||
StatsComponent->SetBaseStatValue(EStats::Health, 100.f);
|
||||
StatsComponent->SetMaxStatValue(EStats::Health, 100.f);
|
||||
StatsComponent->SetBaseStatValue(EStats::Armor, 0.f);
|
||||
StatsComponent->SetMaxStatValue(EStats::Armor, 100.f);
|
||||
StatsComponent->SetBaseStatValue(EStats::Damage, 25.f);
|
||||
StatsComponent->SetMaxStatValue(EStats::Damage, 300.f);
|
||||
|
||||
// Setting MainWeaponCollisionComponent
|
||||
// Setting OnHit Func is Child Class
|
||||
|
@ -269,6 +275,10 @@ void AMasterAI::OnTargeted(bool bIsTargeted)
|
|||
TargetingWidgetComponent->SetVisibility(bIsTargeted);
|
||||
}
|
||||
|
||||
void AMasterAI::OnTargetSet(AActor* NewTarget)
|
||||
{
|
||||
}
|
||||
|
||||
void AMasterAI::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode)
|
||||
{
|
||||
if (NewSpeedMode == MovementSpeedMode)
|
||||
|
@ -540,6 +550,10 @@ TArray<UAnimMontage*> AMasterAI::GetActionMontage(FGameplayTag characterAction)
|
|||
|
||||
if (FCombatGameplayTags::Get().Character_Action_Attack_CloseRange == characterAction)
|
||||
outputArr = CloseRangeAttackMontage;
|
||||
else if (FCombatGameplayTags::Get().Character_Action_Attack_MediumRange == characterAction)
|
||||
outputArr = MediumRangeAttackMontage;
|
||||
else if (FCombatGameplayTags::Get().Character_Action_Attack_RareAttack == characterAction)
|
||||
outputArr = RareAttackMontage;
|
||||
else if (FCombatGameplayTags::Get().Character_Action_Dodge == characterAction)
|
||||
outputArr = DodgeMontage;
|
||||
else if (FCombatGameplayTags::Get().Character_Action_EnterCombat == characterAction)
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
// Inherited via ITargetingInterface
|
||||
virtual bool CanBeTargeted() override;
|
||||
virtual void OnTargeted(bool bIsTargeted) override;
|
||||
public: //Using Child Class
|
||||
virtual void OnTargetSet(AActor* NewTarget);
|
||||
public:
|
||||
void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode);
|
||||
FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; }
|
||||
|
@ -140,6 +142,10 @@ private:
|
|||
TObjectPtr<UAnimMontage> KnockdownBackMontage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage|Attacks", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TObjectPtr<UAnimMontage>> CloseRangeAttackMontage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage|Attacks", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TObjectPtr<UAnimMontage>> MediumRangeAttackMontage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage|Attacks", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TObjectPtr<UAnimMontage>> RareAttackMontage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage|Actions", meta = (AllowPrivateAccess = "true"))
|
||||
TArray<TObjectPtr<UAnimMontage>> DodgeMontage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Montage|Actions", meta = (AllowPrivateAccess = "true"))
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "AI/MobEnemy.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"
|
||||
|
||||
AMobEnemy::AMobEnemy()
|
||||
{
|
||||
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)
|
||||
{
|
||||
HealthBarComponent->SetWidgetClass(WidgetRef.Class);
|
||||
HealthBarComponent->SetWidgetSpace(EWidgetSpace::Screen);
|
||||
HealthBarComponent->SetDrawSize({150.f, 10.f});
|
||||
HealthBarComponent->SetupAttachment(GetMesh());
|
||||
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, &AMobEnemy::OnHit);
|
||||
|
||||
//Setting CombatComponent
|
||||
//Setting others is Parents
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &AMobEnemy::OnCombatToggled);
|
||||
}
|
||||
|
||||
void AMobEnemy::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
MainWeaponCollisionComponent->SetCollisionMeshComponent(WeaponMeshComponent);
|
||||
MainWeaponCollisionComponent->AddActorToIgnore(this);
|
||||
|
||||
if(APlayerController* playerController = UGameplayStatics::GetPlayerController(GetWorld(), 0))
|
||||
{
|
||||
UUI_HealthBar* HealthBarRef = Cast<UUI_HealthBar>(HealthBarComponent->GetWidget());
|
||||
if(HealthBarRef) //ExposeOnSpawn 대용으로 사용
|
||||
{
|
||||
HealthBarRef->InitializeHealthBar(this->StatsComponent, EStats::Health);
|
||||
HealthBarComponent->SetWidget(HealthBarRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AMobEnemy::OnTargeted(bool bIsTargeted)
|
||||
{
|
||||
Super::OnTargeted(bIsTargeted);
|
||||
HealthBarComponent->SetVisibility(bIsTargeted);
|
||||
}
|
||||
|
||||
void AMobEnemy::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 AMobEnemy::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 AMobEnemy::PerformDeath()
|
||||
{
|
||||
//TODO : 죽었을 때 무기에 Collision이 남아있는 버그 있음
|
||||
Super::PerformDeath();
|
||||
SimulateWeaponPhysics();
|
||||
}
|
||||
|
||||
void AMobEnemy::SimulateWeaponPhysics()
|
||||
{
|
||||
WeaponMeshComponent->SetCollisionProfileName(TEXT("PhysicsActor"), true);
|
||||
WeaponMeshComponent->SetSimulatePhysics(true);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AI/MasterAI.h"
|
||||
#include "MobEnemy.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API AMobEnemy : public AMasterAI
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
AMobEnemy();
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
|
@ -12,7 +12,6 @@
|
|||
#include "Components/StatsComponent.h"
|
||||
#include "Components/TargetingComponent.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "Interface/CombatGameplayTag.h"
|
||||
#include "CombatCharacter.generated.h"
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "Components/StatsComponent.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "Math/UnrealMathUtility.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UStatsComponent::UStatsComponent()
|
||||
|
@ -153,11 +152,23 @@ void UStatsComponent::SetBaseStatValue(EStats stat, float value)
|
|||
{
|
||||
if (BaseStats.Contains(stat))
|
||||
BaseStats.Find(stat)->BaseValue = value;
|
||||
else
|
||||
{
|
||||
FBaseStat fStat;
|
||||
fStat.BaseValue = value;
|
||||
BaseStats.Add(stat, fStat);
|
||||
}
|
||||
}
|
||||
|
||||
void UStatsComponent::SetMaxStatValue(EStats stat, float value)
|
||||
{
|
||||
if (BaseStats.Contains(stat))
|
||||
BaseStats.Find(stat)->MaxValue = value;
|
||||
else
|
||||
{
|
||||
FBaseStat fStat;
|
||||
fStat.MaxValue = value;
|
||||
BaseStats.Add(stat, fStat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,4 +99,14 @@ void FCombatGameplayTags::InitializeNativeGameplayTags()
|
|||
FName("Character.Action.Attack.CloseRange"),
|
||||
FString("Action Attack CloseRange")
|
||||
);
|
||||
|
||||
GameplayTags.Character_Action_Attack_MediumRange = UGameplayTagsManager::Get().AddNativeGameplayTag(
|
||||
FName("Character.Action.Attack.MediumRange"),
|
||||
FString("Action Attack MediumRange")
|
||||
);
|
||||
|
||||
GameplayTags.Character_Action_Attack_RareAttack = UGameplayTagsManager::Get().AddNativeGameplayTag(
|
||||
FName("Character.Action.Attack.RareAttack"),
|
||||
FString("Action Attack RareAttack")
|
||||
);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
FGameplayTag Character_Action_Attack_LightAttack;
|
||||
FGameplayTag Character_Action_Attack_SprintAttack;
|
||||
FGameplayTag Character_Action_Attack_CloseRange;
|
||||
FGameplayTag Character_Action_Attack_MediumRange;
|
||||
FGameplayTag Character_Action_Attack_RareAttack;
|
||||
|
||||
private:
|
||||
static FCombatGameplayTags GameplayTags;
|
||||
|
|
|
@ -45,4 +45,11 @@ enum class EAIBehavior : uint8
|
|||
Chase UMETA(DisplayName = "Chase"),
|
||||
Patrol UMETA(DisplayName = "Patrol"),
|
||||
Hit UMETA(DisplayName = "Hit"),
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EAIAttackRange : uint8
|
||||
{
|
||||
CloseRange UMETA(DisplayName = "CloseRange"),
|
||||
MediumRange UMETA(DisplayName = "MediumRange"),
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/UI_BossHealth.h"
|
||||
|
||||
#include "UI_HealthBar.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
|
||||
UUI_BossHealth::UUI_BossHealth()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UUI_BossHealth::InitializeWidget(UStatsComponent* InputStatsComponent)
|
||||
{
|
||||
HealthBar->InitializeHealthBar(InputStatsComponent, EStats::Health);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "UI_BossHealth.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API UUI_BossHealth : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UUI_BossHealth();
|
||||
void InitializeWidget(class UStatsComponent* InputStatsComponent);
|
||||
private:
|
||||
/*
|
||||
* TODO :
|
||||
* 해당 파일은 Blueprint Widget을 사용하는데
|
||||
* UUI_HealthBar는 C++ 파일이라서 서로 매칭이 안됨.
|
||||
* 어떻게 해야하는지 물어봐야됨
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget, AllowPrivateAccess="true"))
|
||||
TSubclassOf<class UUI_HealthBar> HealthBar;
|
||||
};
|
Loading…
Reference in New Issue