Compare commits
No commits in common. "1f3e8a09ea862c55747843aa43d3c5b0c34c5db0" and "03d5b80a0b74d03ae6fb7f2e9faca91833f7df2d" have entirely different histories.
1f3e8a09ea
...
03d5b80a0b
BIN
Content/Enemy/BB_Base_Enemy.uasset (Stored with Git LFS)
BIN
Content/Enemy/BB_Base_Enemy.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset (Stored with Git LFS)
BIN
Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset (Stored with Git LFS)
BIN
Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset (Stored with Git LFS)
BIN
Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset (Stored with Git LFS)
BIN
Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Passive_State.uasset (Stored with Git LFS)
BIN
Content/Enemy/BehaviorTrees/BT_Passive_State.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/EQS/AttackTarget.uasset (Stored with Git LFS)
BIN
Content/Enemy/EQS/AttackTarget.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/EQS/EQSTestingPawn.uasset (Stored with Git LFS)
BIN
Content/Enemy/EQS/EQSTestingPawn.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_FindCover.uasset (Stored with Git LFS)
BIN
Content/Enemy/EQS/EQS_FindCover.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_FindIdealRange.uasset (Stored with Git LFS)
BIN
Content/Enemy/EQS/EQS_FindIdealRange.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_Strafe.uasset (Stored with Git LFS)
BIN
Content/Enemy/EQS/EQS_Strafe.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
BIN
Content/Enemy/Tasks/BTTMoveToIdealRange.uasset (Stored with Git LFS)
BIN
Content/Enemy/Tasks/BTTMoveToIdealRange.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/Worker/AIC_Worker.uasset (Stored with Git LFS)
BIN
Content/Enemy/Worker/AIC_Worker.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
BIN
Content/Enemy/Worker/BT_Worker.uasset (Stored with Git LFS)
BIN
Content/Enemy/Worker/BT_Worker.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/Worker/C_Worker.uasset (Stored with Git LFS)
BIN
Content/Enemy/Worker/C_Worker.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Levels/TestLevel.umap (Stored with Git LFS)
BIN
Content/Levels/TestLevel.umap (Stored with Git LFS)
Binary file not shown.
BIN
Content/TestPatrolRoute.uasset (Stored with Git LFS)
BIN
Content/TestPatrolRoute.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Weapons/Pistol/Pistol.uasset (Stored with Git LFS)
BIN
Content/Weapons/Pistol/Pistol.uasset (Stored with Git LFS)
Binary file not shown.
|
@ -1,27 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Decorators/BTDCanSeeTarget.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
|
||||
bool UBTDCanSeeTarget::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
||||
{
|
||||
FHitResult HitResult;
|
||||
|
||||
FVector Start = OwnerComp.GetAIOwner()->GetPawn()->GetActorLocation();
|
||||
|
||||
UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent();
|
||||
AActor* TargetActor = Cast<AActor>(BlackboardComponent->GetValueAsObject(TargetActorKey.SelectedKeyName));
|
||||
FVector End = TargetActor->GetActorLocation();
|
||||
|
||||
GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Pawn);
|
||||
|
||||
if (HitResult.GetActor())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTDecorator.h"
|
||||
#include "BTDCanSeeTarget.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTDCanSeeTarget : public UBTDecorator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Target Actor Key"))
|
||||
FBlackboardKeySelector TargetActorKey;
|
||||
|
||||
protected:
|
||||
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Decorators/BTDHasPatrolRoute.h"
|
||||
|
||||
#include "Nakatomi/EnemyAIController.h"
|
||||
|
||||
bool UBTDHasPatrolRoute::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
||||
{
|
||||
AEnemyAIController* enemyController = Cast<AEnemyAIController>(OwnerComp.GetAIOwner());
|
||||
AEnemyCharacter* enemyPawn = Cast<AEnemyCharacter>(enemyController->GetPawn());
|
||||
|
||||
return enemyPawn->CurrentPatrolRoute ? true : false;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTDecorator.h"
|
||||
#include "BTDHasPatrolRoute.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class NAKATOMI_API UBTDHasPatrolRoute : public UBTDecorator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Decorators/BTDIsHealthBelowThreshold.h"
|
||||
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
|
||||
bool UBTDIsHealthBelowThreshold::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
||||
{
|
||||
UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent();
|
||||
float currentHealth = BlackboardComponent->GetValueAsFloat(CurrentHealthKey.SelectedKeyName);
|
||||
|
||||
return currentHealth <= HealthThreshold ? true : false;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTDecorator.h"
|
||||
#include "BTDIsHealthBelowThreshold.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTDIsHealthBelowThreshold : public UBTDecorator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Current Health Key"))
|
||||
FBlackboardKeySelector CurrentHealthKey;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Health Threshold"))
|
||||
float HealthThreshold = 25.0f;
|
||||
|
||||
protected:
|
||||
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
||||
};
|
|
@ -1,29 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Decorators/BTDIsWithinRange.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "navigationSystem.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "Nakatomi/NakatomiCharacter.h"
|
||||
|
||||
bool UBTDIsWithinRange::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
|
||||
{
|
||||
UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent();
|
||||
float Dist = BlackboardComponent->GetValueAsFloat(DistanceKey.SelectedKeyName);
|
||||
UObject* Target = BlackboardComponent->GetValueAsObject(TargetActorKey.SelectedKeyName);
|
||||
auto TargetLocation = Cast<AActor>(Target)->GetActorLocation();
|
||||
UNavigationSystemV1* NavigationSystem = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
|
||||
|
||||
APawn* pawn = OwnerComp.GetAIOwner()->GetPawn();
|
||||
|
||||
if (pawn && NavigationSystem && TargetLocation != FVector::ZeroVector)
|
||||
{
|
||||
double Distance = -1.0;
|
||||
NavigationSystem->GetPathLength(TargetLocation, pawn->GetTransform().GetLocation(), Distance);
|
||||
return Distance <= Dist ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTDecorator.h"
|
||||
#include "BTDIsWithinRange.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTDIsWithinRange : public UBTDecorator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Target Actor Key"))
|
||||
FBlackboardKeySelector TargetActorKey;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Distance Key"))
|
||||
FBlackboardKeySelector DistanceKey;
|
||||
|
||||
public:
|
||||
|
||||
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
|
||||
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Decorators/BTDWeaponCooldown.h"
|
||||
|
||||
#include "AIController.h"
|
||||
#include "Nakatomi/EnemyCharacter.h"
|
||||
|
||||
void UBTDWeaponCooldown::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
|
||||
{
|
||||
AEnemyCharacter* EnemyCharacter = Cast<AEnemyCharacter>(OwnerComp.GetAIOwner()->GetPawn());
|
||||
|
||||
if (EnemyCharacter && EnemyCharacter->GetCurrentWeapon())
|
||||
{
|
||||
const float Cooldown = EnemyCharacter->GetCurrentWeapon()->GetWeaponProperties()->WeaponCooldown;
|
||||
if (CoolDownTime != Cooldown)
|
||||
{
|
||||
CoolDownTime = Cooldown;
|
||||
}
|
||||
}
|
||||
|
||||
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/Decorators/BTDecorator_Cooldown.h"
|
||||
#include "BTDWeaponCooldown.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTDWeaponCooldown : public UBTDecorator_Cooldown
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "EAIState.h"
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EAIState : uint8
|
||||
{
|
||||
PASSIVE UMETA(DisplayName = "Passive"),
|
||||
ATTACKING UMETA(DisplayName = "Attacking"),
|
||||
FROZEN UMETA(DisplayName = "Frozen"),
|
||||
INVESTIGATING UMETA(DisplayName = "Investigating"),
|
||||
DEAD UMETA(DisplayName = "Dead"),
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "EPatrolMovementEnum.h"
|
|
@ -1,16 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EPatrolMovementEnum : uint8
|
||||
{
|
||||
SLOWWALK UMETA(DisplayName = "Slow Walk"),
|
||||
WALK UMETA(DisplayName = "Walk"),
|
||||
SPRINT UMETA(DisplayName = "Sprint"),
|
||||
};
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "EnemyAIController.h"
|
||||
#include <Kismet/GameplayStatics.h>
|
||||
|
||||
#include "EAIState.h"
|
||||
#include "NakatomiGameInstance.h"
|
||||
#include "BehaviorTree/BehaviorTree.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
|
@ -27,19 +25,8 @@ AEnemyAIController::AEnemyAIController(const FObjectInitializer& object_initiali
|
|||
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
|
||||
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
|
||||
|
||||
HearingConfig = CreateDefaultSubobject<UAISenseConfig_Hearing>(TEXT("Hearing Sense Config"));
|
||||
HearingConfig->HearingRange = 800.0f;
|
||||
HearingConfig->SetMaxAge(3.0f);
|
||||
HearingConfig->DetectionByAffiliation.bDetectEnemies = true;
|
||||
HearingConfig->DetectionByAffiliation.bDetectNeutrals = true;
|
||||
|
||||
DamageConfig = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("Damage Sense Config"));
|
||||
DamageConfig->SetMaxAge(5.0f);
|
||||
|
||||
AIPerception->SetDominantSense(SightConfig->GetSenseImplementation());
|
||||
AIPerception->ConfigureSense(*SightConfig);
|
||||
AIPerception->ConfigureSense(*HearingConfig);
|
||||
AIPerception->ConfigureSense(*DamageConfig);
|
||||
}
|
||||
|
||||
void AEnemyAIController::OnPossess(APawn* InPawn)
|
||||
|
@ -62,11 +49,6 @@ void AEnemyAIController::OnPossess(APawn* InPawn)
|
|||
Blackboard->SetValueAsObject("SelfActor", enemy);
|
||||
}
|
||||
|
||||
Blackboard->SetValueAsEnum("State", static_cast<uint8>(EAIState::PASSIVE));
|
||||
|
||||
Blackboard->SetValueAsFloat("AttackRadius", enemy->AttackRadius);
|
||||
Blackboard->SetValueAsFloat("DefendRadius", enemy->DefendRadius);
|
||||
|
||||
//ensure(enemy->GetMovementComponent()->UseAccelerationForPathFollowing());
|
||||
}
|
||||
|
||||
|
@ -134,7 +116,7 @@ void AEnemyAIController::OnDeath(FDamageInfo info)
|
|||
|
||||
void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
|
||||
{
|
||||
for (AActor* actor : actors)
|
||||
for (auto actor : actors)
|
||||
{
|
||||
if (!actor->GetClass()->IsChildOf(APlayerCharacter::StaticClass()))
|
||||
{
|
||||
|
@ -144,46 +126,13 @@ void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
|
|||
FActorPerceptionBlueprintInfo perceptionInfo;
|
||||
PerceptionComponent->GetActorsPerception(actor, perceptionInfo);
|
||||
|
||||
for (FAIStimulus& stimulus : perceptionInfo.LastSensedStimuli)
|
||||
for (auto& stimulus : perceptionInfo.LastSensedStimuli)
|
||||
{
|
||||
if (!stimulus.IsValid() || stimulus.IsExpired() ||
|
||||
static_cast<EAIState>(Blackboard->GetValueAsEnum("State")) == EAIState::DEAD)
|
||||
if (!stimulus.IsValid() || stimulus.IsExpired())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FAISenseID SightID;
|
||||
FAISenseID HearingID;
|
||||
FAISenseID DamageID;
|
||||
|
||||
if (SightConfig)
|
||||
{
|
||||
SightID = SightConfig->GetSenseID();
|
||||
}
|
||||
|
||||
if (HearingConfig)
|
||||
{
|
||||
HearingID = HearingConfig->GetSenseID();
|
||||
}
|
||||
|
||||
if (DamageConfig)
|
||||
{
|
||||
DamageID = DamageConfig->GetSenseID();
|
||||
}
|
||||
|
||||
if (stimulus.Type == SightID)
|
||||
{
|
||||
SensedSight(actor, stimulus);
|
||||
}
|
||||
else if (stimulus.Type == HearingID)
|
||||
{
|
||||
SensedHearing(actor, stimulus);
|
||||
}
|
||||
else if (stimulus.Type == DamageID)
|
||||
{
|
||||
SensedDamaged(actor, stimulus);
|
||||
}
|
||||
|
||||
Blackboard->SetValueAsObject("TargetActor", actor);
|
||||
|
||||
if (stimulus.IsActive())
|
||||
|
@ -230,51 +179,3 @@ bool AEnemyAIController::GetHasAttackToken()
|
|||
{
|
||||
return HasAttackToken;
|
||||
}
|
||||
|
||||
void AEnemyAIController::SetState(EAIState state)
|
||||
{
|
||||
Blackboard->SetValueAsEnum("State", static_cast<uint8>(state));
|
||||
}
|
||||
|
||||
void AEnemyAIController::SetStateAsPassive()
|
||||
{
|
||||
SetState(EAIState::PASSIVE);
|
||||
}
|
||||
|
||||
void AEnemyAIController::SetStateAsAttacking(AActor* target)
|
||||
{
|
||||
Blackboard->SetValueAsObject("TargetActor", target);
|
||||
SetState(EAIState::ATTACKING);
|
||||
}
|
||||
|
||||
AActor* AEnemyAIController::GetTargetActor()
|
||||
{
|
||||
return Cast<AActor>(Blackboard->GetValueAsObject("TargetActor"));
|
||||
}
|
||||
|
||||
void AEnemyAIController::SensedSight(AActor* actor, FAIStimulus& stimulus)
|
||||
{
|
||||
EAIState CurrentState = static_cast<EAIState>(Blackboard->GetValueAsEnum("State"));
|
||||
|
||||
|
||||
if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING)
|
||||
{
|
||||
SetStateAsAttacking(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemyAIController::SensedHearing(AActor* actor, FAIStimulus& stimulus)
|
||||
{
|
||||
EAIState CurrentState = static_cast<EAIState>(Blackboard->GetValueAsEnum("State"));
|
||||
|
||||
if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING)
|
||||
{
|
||||
SetState(EAIState::INVESTIGATING);
|
||||
Blackboard->SetValueAsVector("InvestigationLocation", stimulus.StimulusLocation);
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemyAIController::SensedDamaged(AActor* actor, FAIStimulus& stimulus)
|
||||
{
|
||||
SetStateAsAttacking(actor);
|
||||
}
|
||||
|
|
|
@ -4,11 +4,8 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AIController.h"
|
||||
#include "EAIState.h"
|
||||
#include "EnemyCharacter.h"
|
||||
#include "PlayerCharacter.h"
|
||||
#include "Perception/AISenseConfig_Damage.h"
|
||||
#include "Perception/AISenseConfig_Hearing.h"
|
||||
#include "Perception/AISenseConfig_Sight.h"
|
||||
#include "EnemyAIController.generated.h"
|
||||
|
||||
|
@ -32,10 +29,6 @@ private:
|
|||
|
||||
UAISenseConfig_Sight* SightConfig;
|
||||
|
||||
UAISenseConfig_Hearing* HearingConfig;
|
||||
|
||||
UAISenseConfig_Damage* DamageConfig;
|
||||
|
||||
bool HasAttackToken = false;
|
||||
|
||||
public:
|
||||
|
@ -66,24 +59,4 @@ public:
|
|||
|
||||
UFUNCTION()
|
||||
bool GetHasAttackToken();
|
||||
|
||||
UFUNCTION()
|
||||
void SetState(EAIState state);
|
||||
|
||||
UFUNCTION()
|
||||
void SetStateAsPassive();
|
||||
|
||||
UFUNCTION()
|
||||
void SetStateAsAttacking(AActor* target);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
AActor* GetTargetActor();
|
||||
|
||||
private:
|
||||
|
||||
void SensedSight(AActor* actor, FAIStimulus& stimulus);
|
||||
|
||||
void SensedHearing(AActor* actor, FAIStimulus& stimulus);
|
||||
|
||||
void SensedDamaged(AActor* actor, FAIStimulus& stimulus);
|
||||
};
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
|
||||
#include "EnemyCharacter.h"
|
||||
#include "EnemyAIController.h"
|
||||
#include "EnemyHealthComponent.h"
|
||||
#include "InteractableComponent.h"
|
||||
#include "BehaviorTree/BehaviorTree.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "BehaviorTree/BlackboardData.h"
|
||||
|
||||
#define COLLISION_WEAPON ECC_GameTraceChannel1
|
||||
|
||||
|
@ -14,10 +10,6 @@ AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer) :
|
|||
{
|
||||
RandomWeaponParameters = CreateDefaultSubobject<URandomWeaponParameters>(TEXT("Random Weapon Parameters"));
|
||||
|
||||
auto healthComponent = CreateDefaultSubobject<UEnemyHealthComponent>(TEXT("Health Component"));
|
||||
SetHealthComponent(healthComponent);
|
||||
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
|
||||
GetHealthComponent()->SetMaxHealth(100.0f);
|
||||
|
||||
this->Tags.Add(FName("Enemy"));
|
||||
|
@ -57,10 +49,6 @@ void AEnemyCharacter::WeaponCooldownHandler()
|
|||
void AEnemyCharacter::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
AEnemyAIController* controller = Cast<AEnemyAIController>(GetController());
|
||||
controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth());
|
||||
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||
}
|
||||
|
||||
void AEnemyCharacter::PlayOnFireAnimations()
|
||||
|
@ -137,12 +125,3 @@ void AEnemyCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemyCharacter::OnDamaged()
|
||||
{
|
||||
Super::OnDamaged();
|
||||
|
||||
AEnemyAIController* controller = Cast<AEnemyAIController>(GetController());
|
||||
controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth());
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NakatomiCharacter.h"
|
||||
#include "PatrolRoute.h"
|
||||
#include "BehaviorTree/BehaviorTreeComponent.h"
|
||||
#include "RandomWeaponParameters.h"
|
||||
#include "EnemyCharacter.generated.h"
|
||||
|
@ -18,16 +17,6 @@ class NAKATOMI_API AEnemyCharacter : public ANakatomiCharacter
|
|||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Meta = (AllowPrivateAccess = "true"))
|
||||
APatrolRoute* CurrentPatrolRoute;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
float AttackRadius = 300.0;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
float DefendRadius = 500.0f;
|
||||
|
||||
private:
|
||||
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
|
||||
UBehaviorTree* BehaviourTree;
|
||||
|
@ -55,7 +44,4 @@ private:
|
|||
virtual void CalculateHits(TArray<FHitResult>* hits) override;
|
||||
|
||||
virtual void ProcessHits(TArray<FHitResult> hits) override;
|
||||
|
||||
protected:
|
||||
virtual void OnDamaged() override;
|
||||
};
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "EnemyHealthComponent.h"
|
||||
|
||||
#include "EnemyAIController.h"
|
||||
#include "EnemyCharacter.h"
|
||||
|
||||
void UEnemyHealthComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
void UEnemyHealthComponent::TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType,
|
||||
AController* instigatedBy, AActor* damageCauser)
|
||||
{
|
||||
if (damagedActor == nullptr || IsDead || !CanDamage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentHealth -= damage;
|
||||
|
||||
AEnemyCharacter* enemyCharacter = Cast<AEnemyCharacter>(damagedActor);
|
||||
UAISense_Damage::ReportDamageEvent(GetWorld(), damagedActor, damageCauser, 1,
|
||||
damageCauser->GetTransform().GetLocation(),
|
||||
damageCauser->GetTransform().GetLocation());
|
||||
|
||||
OnDamaged.ExecuteIfBound({damagedActor, damage, damageType, instigatedBy, damageCauser});
|
||||
|
||||
if (CurrentHealth <= 0.0f)
|
||||
{
|
||||
IsDead = true;
|
||||
OnDeath.ExecuteIfBound({damagedActor, damage, damageType, instigatedBy, damageCauser});
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HealthComponent.h"
|
||||
#include "EnemyHealthComponent.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UEnemyHealthComponent : public UHealthComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy, AActor* damageCauser) override;
|
||||
|
||||
};
|
|
@ -39,7 +39,7 @@ public:
|
|||
FOnDamageDelegate OnDamaged;
|
||||
FOnDeathDelegate OnDeath;
|
||||
|
||||
protected:
|
||||
private:
|
||||
UPROPERTY(EditDefaultsOnly)
|
||||
float MaxHealth = 100.f;
|
||||
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
UHealthComponent();
|
||||
|
||||
UFUNCTION()
|
||||
virtual void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy,
|
||||
void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy,
|
||||
AActor* damageCauser);
|
||||
|
||||
UFUNCTION()
|
||||
|
|
|
@ -19,12 +19,6 @@ void UNakatomiCMC::InitializeComponent()
|
|||
NakatomiCharacterOwner = Cast<ANakatomiCharacter>(GetOwner());
|
||||
}
|
||||
|
||||
void UNakatomiCMC::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
DefaultMaxWalkSpeed = Walk_MaxWalkSpeed;
|
||||
}
|
||||
|
||||
// Checks if we can combine the NewMove with the current move to save on data.
|
||||
// If all the data in a saved move is identical, if true, we cam tell the server to run the existing move instead.
|
||||
bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter,
|
||||
|
@ -277,16 +271,6 @@ bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode
|
|||
return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode;
|
||||
}
|
||||
|
||||
void UNakatomiCMC::SetMaxWalkSpeed(float newMaxSpeed)
|
||||
{
|
||||
Walk_MaxWalkSpeed = newMaxSpeed;
|
||||
}
|
||||
|
||||
void UNakatomiCMC::SetMaxWalkSpeedToDefault()
|
||||
{
|
||||
Walk_MaxWalkSpeed = DefaultMaxWalkSpeed;
|
||||
}
|
||||
|
||||
void UNakatomiCMC::EnterSlide()
|
||||
{
|
||||
Safe_bWantsToSlide = true;
|
||||
|
|
|
@ -108,8 +108,6 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
|||
UPROPERTY(Transient)
|
||||
ANakatomiCharacter* NakatomiCharacterOwner;
|
||||
|
||||
float DefaultMaxWalkSpeed;
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FDashStartDelegate DashStartDelegate;
|
||||
|
@ -120,8 +118,6 @@ public:
|
|||
protected:
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override;
|
||||
|
||||
protected:
|
||||
|
@ -171,12 +167,6 @@ public:
|
|||
UFUNCTION()
|
||||
bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const;
|
||||
|
||||
UFUNCTION()
|
||||
void SetMaxWalkSpeed(float newMaxSpeed);
|
||||
|
||||
UFUNCTION()
|
||||
void SetMaxWalkSpeedToDefault();
|
||||
|
||||
private:
|
||||
void EnterSlide();
|
||||
void ExitSlide();
|
||||
|
|
|
@ -14,12 +14,9 @@ ANakatomiCharacter::ANakatomiCharacter(const FObjectInitializer& ObjectInitializ
|
|||
|
||||
NakatomiCMC = Cast<UNakatomiCMC>(GetCharacterMovement());
|
||||
|
||||
// if (!HealthComponent)
|
||||
// {
|
||||
// HealthComponent = CreateDefaultSubobject<UHealthComponent>(TEXT("Health Component"));
|
||||
// HealthComponent->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||
// HealthComponent->OnDeath.BindUFunction(this, "OnDeath");
|
||||
// }
|
||||
HealthComponent = CreateDefaultSubobject<UHealthComponent>(TEXT("Health Component"));
|
||||
HealthComponent->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||
HealthComponent->OnDeath.BindUFunction(this, "OnDeath");
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PatrolRoute.h"
|
||||
|
||||
// Sets default values
|
||||
APatrolRoute::APatrolRoute()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
|
||||
Spline = CreateDefaultSubobject<USplineComponent>(TEXT("Spline"));
|
||||
Spline->SetupAttachment(RootComponent);
|
||||
}
|
||||
|
||||
void APatrolRoute::IncrementPatrolRoute()
|
||||
{
|
||||
if (PatrolIndex == Spline->GetNumberOfSplinePoints() - 1)
|
||||
{
|
||||
Direction = -1;
|
||||
}
|
||||
else if (PatrolIndex == 0)
|
||||
{
|
||||
Direction = 1;
|
||||
}
|
||||
|
||||
PatrolIndex += Direction;
|
||||
}
|
||||
|
||||
FVector APatrolRoute::GetSplinePointAtWorld()
|
||||
{
|
||||
return GetSplinePointAtWorld(PatrolIndex);
|
||||
}
|
||||
|
||||
FVector APatrolRoute::GetSplinePointAtWorld(int pointIndex)
|
||||
{
|
||||
return Spline->GetLocationAtSplinePoint(pointIndex, ESplineCoordinateSpace::World);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/SplineComponent.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "PatrolRoute.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class NAKATOMI_API APatrolRoute : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
USplineComponent* Spline;
|
||||
|
||||
private:
|
||||
int PatrolIndex = 0;
|
||||
|
||||
int Direction;
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
APatrolRoute();
|
||||
|
||||
void IncrementPatrolRoute();
|
||||
|
||||
FVector GetSplinePointAtWorld();
|
||||
|
||||
FVector GetSplinePointAtWorld(int pointIndex);
|
||||
};
|
|
@ -30,10 +30,6 @@ APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer)
|
|||
//bUseControllerRotationYaw = true;
|
||||
//bUseControllerRotationRoll = false;
|
||||
|
||||
SetHealthComponent(CreateDefaultSubobject<UHealthComponent>(TEXT("Health Component")));
|
||||
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
|
||||
|
||||
// Setup the camera boom
|
||||
CameraSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArmComponent"));
|
||||
CameraSpringArmComponent->SetupAttachment(RootComponent);
|
||||
|
@ -402,7 +398,6 @@ void APlayerCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||
{
|
||||
healthComponent->TakeDamage(Hit.GetActor(), CurrentWeapon->GetWeaponProperties()->WeaponDamage, nullptr,
|
||||
GetController(), this);
|
||||
|
||||
if (!healthComponent->GetIsDead())
|
||||
{
|
||||
OnEnemyHit.ExecuteIfBound();
|
||||
|
@ -442,8 +437,6 @@ void APlayerCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||
true);
|
||||
}
|
||||
}
|
||||
|
||||
MakeNoise(1, this, Hit.Location);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -646,8 +639,6 @@ void APlayerCharacter::OnFire()
|
|||
|
||||
CurrentWeapon->PlayFireSoundAtLocation(this->GetTransform().GetLocation());
|
||||
|
||||
MakeNoise(1,this, this->GetTransform().GetLocation());
|
||||
|
||||
PlayOnFireAnimations();
|
||||
|
||||
CurrentWeapon->SetCurrentWeaponStatus(Cooldown);
|
||||
|
|
|
@ -9,5 +9,6 @@ EBTNodeResult::Type UBTTClearFocus::ExecuteTask(UBehaviorTreeComponent& owner, u
|
|||
{
|
||||
auto enemyController = Cast<AEnemyAIController>(owner.GetAIOwner());
|
||||
enemyController->ClearFocus(EAIFocusPriority::Default);
|
||||
enemyController->SetFocus();
|
||||
return EBTNodeResult::Succeeded;
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Tasks/BTTMoveAlongPatrolRoute.h"
|
||||
|
||||
#include "navigationSystem.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
#include "Nakatomi/EnemyAIController.h"
|
||||
#include "Nakatomi/NakatomiCMC.h"
|
||||
|
||||
EBTNodeResult::Type UBTTMoveAlongPatrolRoute::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory)
|
||||
{
|
||||
AEnemyAIController* enemyController = Cast<AEnemyAIController>(owner.GetAIOwner());
|
||||
AEnemyCharacter* enemyPawn = Cast<AEnemyCharacter>(enemyController->GetPawn());
|
||||
|
||||
if (enemyPawn->CurrentPatrolRoute)
|
||||
{
|
||||
FVector location = enemyPawn->CurrentPatrolRoute->GetSplinePointAtWorld();
|
||||
UBlackboardComponent* blackboardComponent = owner.GetBlackboardComponent();
|
||||
blackboardComponent->SetValueAsVector(PatrolLocationKey.SelectedKeyName, location);
|
||||
|
||||
enemyPawn->CurrentPatrolRoute->IncrementPatrolRoute();
|
||||
|
||||
return EBTNodeResult::Succeeded;
|
||||
}
|
||||
|
||||
return EBTNodeResult::Failed;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "BTTMoveAlongPatrolRoute.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTTMoveAlongPatrolRoute : public UBTTaskNode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Patrol Location Key"))
|
||||
FBlackboardKeySelector PatrolLocationKey;
|
||||
|
||||
public:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override;
|
||||
};
|
|
@ -1,33 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Tasks/BTTSetMovementSpeed.h"
|
||||
|
||||
#include "Nakatomi/EnemyAIController.h"
|
||||
#include "Nakatomi/NakatomiCMC.h"
|
||||
|
||||
enum class EPatrolMovementEnum : uint8;
|
||||
|
||||
EBTNodeResult::Type UBTTSetMovementSpeed::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory)
|
||||
{
|
||||
AEnemyAIController* enemyController = Cast<AEnemyAIController>(owner.GetAIOwner());
|
||||
AEnemyCharacter* enemyPawn = Cast<AEnemyCharacter>(enemyController->GetPawn());
|
||||
|
||||
switch (MaxWalkSpeedKey)
|
||||
{
|
||||
case EPatrolMovementEnum::SLOWWALK:
|
||||
enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(slowWalkSpeed);
|
||||
break;
|
||||
case EPatrolMovementEnum::WALK:
|
||||
enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(walkSpeed);
|
||||
break;
|
||||
case EPatrolMovementEnum::SPRINT:
|
||||
enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(sprintSpeed);
|
||||
break;
|
||||
default:
|
||||
enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeedToDefault();
|
||||
break;
|
||||
}
|
||||
|
||||
return EBTNodeResult::Succeeded;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "Nakatomi/EPatrolMovementEnum.h"
|
||||
#include "BTTSetMovementSpeed.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTTSetMovementSpeed : public UBTTaskNode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "Max Walk Speed Key"))
|
||||
EPatrolMovementEnum MaxWalkSpeedKey;
|
||||
|
||||
private:
|
||||
float slowWalkSpeed = 250.0f;
|
||||
|
||||
float walkSpeed = 500.0f;
|
||||
|
||||
float sprintSpeed = 750.0f;
|
||||
|
||||
public:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override;
|
||||
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "../Tasks/BTTSetState.h"
|
||||
|
||||
#include "Nakatomi/EnemyAIController.h"
|
||||
|
||||
EBTNodeResult::Type UBTTSetState::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory)
|
||||
{
|
||||
if (AEnemyAIController* EnemyController = Cast<AEnemyAIController>(owner.GetAIOwner()))
|
||||
{
|
||||
EnemyController->SetState(NewState);
|
||||
return EBTNodeResult::Succeeded;
|
||||
}
|
||||
|
||||
return EBTNodeResult::Failed;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "Nakatomi/EAIState.h"
|
||||
#include "BTTSetState.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class NAKATOMI_API UBTTSetState : public UBTTaskNode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Options",
|
||||
Meta = (AllowPrivateAccess = "true", DisplayName = "New State"))
|
||||
EAIState NewState;
|
||||
|
||||
public:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override;
|
||||
|
||||
};
|
Loading…
Reference in New Issue