Update Enemy AI for Patrol Pathing

This commit is contained in:
Philip W 2023-10-09 01:31:01 +01:00
parent c58c400d43
commit df7ca8b0db
27 changed files with 220 additions and 29 deletions

View File

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders>
<Path>../../Endless-Vendetta</Path>
</attachedFolders>
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

Binary file not shown.

Binary file not shown.

BIN
EndlessVendetta/Content/AI/Enemy/Basic/BP_PatrolPath.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -80,6 +80,11 @@ float AAICharacter::TakeDamage(const float DamageAmount, FDamageEvent const& Dam
return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}
APatrolPath* AAICharacter::GetPatrolPath() const
{
return PatrolPath;
}
void AAICharacter::SetupStimuliSourceComponent()
{
StimuliSourceComponent = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Stimuli Source Component"));

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "PatrolPath.h"
#include "BehaviorTree/BehaviorTree.h"
#include "GameFramework/Character.h"
#include "AICharacter.generated.h"
@ -30,9 +31,6 @@ protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTree;
UPROPERTY()
class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent;
void SetupStimuliSourceComponent();
@ -49,4 +47,14 @@ public:
UFUNCTION(BlueprintCallable, Category = "Damage Control")
virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
UFUNCTION()
APatrolPath* GetPatrolPath() const;
private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true"))
UBehaviorTree* BehaviorTree;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true"))
APatrolPath* PatrolPath;
};

View File

@ -0,0 +1,22 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PatrolPath.h"
// Sets default values
APatrolPath::APatrolPath()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
}
FVector APatrolPath::GetPatrolPoint(int const Index) const
{
return PatrolPoint[Index];
}
int APatrolPath::Num() const
{
return PatrolPoint.Num();
}

View File

@ -0,0 +1,24 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PatrolPath.generated.h"
UCLASS()
class ENDLESSVENDETTA_API APatrolPath : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APatrolPath();
FVector GetPatrolPoint(int const Index) const;
int Num() const;
private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (MakeEditWidget = "true", AllowPrivateAccess = "true"))
TArray<FVector> PatrolPoint;
};

View File

@ -3,7 +3,7 @@
#include "BTTask_AttackPlayer.h"
#include "AI_EnemyController.h"
#include "EndlessVendetta/AI/AI_EnemyController.h"
#include "BehaviorTree/BlackboardComponent.h"
UBTTask_AttackPlayer::UBTTask_AttackPlayer(FObjectInitializer const& ObjectInitializer)

View File

@ -0,0 +1,34 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTTask_FindPathPoint.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "EndlessVendetta/AI/AI_EnemyController.h"
#include "EndlessVendetta/AI/EnemyCharacter.h"
UBTTask_FindPathPoint::UBTTask_FindPathPoint(FObjectInitializer const& ObjectInitializer)
{
NodeName = TEXT("Find Path Point");
}
EBTNodeResult::Type UBTTask_FindPathPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
if (const AAI_EnemyController* const AIEnemyController = Cast<AAI_EnemyController>(OwnerComp.GetAIOwner()))
{
if (UBlackboardComponent* const BlackboardComponent = OwnerComp.GetBlackboardComponent())
{
int const Index = BlackboardComponent->GetValueAsInt(GetSelectedBlackboardKey());
if (const AEnemyCharacter* const EnemyCharacter = Cast<AEnemyCharacter>(AIEnemyController->GetPawn()))
{
FVector const RelativePatrolPoint = EnemyCharacter->GetPatrolPath()->GetPatrolPoint(Index);
FVector const GlobalPointLocation = EnemyCharacter->GetPatrolPath()->GetActorTransform().TransformPosition(RelativePatrolPoint);
BlackboardComponent->SetValueAsVector(PatrolPathVectorKey.SelectedKeyName, GlobalPointLocation);
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
return EBTNodeResult::Succeeded;
}
}
}
return EBTNodeResult::Failed;
}

View File

@ -0,0 +1,24 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FindPathPoint.generated.h"
/**
*
*/
UCLASS()
class ENDLESSVENDETTA_API UBTTask_FindPathPoint : public UBTTask_BlackboardBase
{
GENERATED_BODY()
public:
explicit UBTTask_FindPathPoint(FObjectInitializer const& ObjectInitializer);
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
private:
UPROPERTY(EditAnywhere, Category = "Blackboard", meta=(AllowPrivateAccess = "true"))
FBlackboardKeySelector PatrolPathVectorKey;
};

View File

@ -3,7 +3,7 @@
#include "BTTask_FindRandomLocation.h"
#include "AI_EnemyController.h"
#include "EndlessVendetta/AI/AI_EnemyController.h"
#include "NavigationSystem.h"
#include "BehaviorTree/BlackboardComponent.h"

View File

@ -0,0 +1,47 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTTask_IncrementPathIndex.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "EndlessVendetta/AI/AI_EnemyController.h"
#include "EndlessVendetta/AI/EnemyCharacter.h"
UBTTask_IncrementPathIndex::UBTTask_IncrementPathIndex(FObjectInitializer const& ObjectInitializer)
{
NodeName = TEXT("Increment Path Index");
}
EBTNodeResult::Type UBTTask_IncrementPathIndex::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
if (AAI_EnemyController* const EnemyController = Cast<AAI_EnemyController>(OwnerComp.GetOwner()))
{
if (AEnemyCharacter* const EnemyCharacter = Cast<AEnemyCharacter>(EnemyController->GetPawn()))
{
if (UBlackboardComponent* const BlackboardComponent = OwnerComp.GetBlackboardComponent())
{
int const NumberOfPoints = EnemyCharacter->GetPatrolPath()->Num();
int const MinIndex = 0;
int const MaxIndex = NumberOfPoints - 1;
int CurrentIndex = BlackboardComponent->GetValueAsInt(GetSelectedBlackboardKey());
if (bBiDirectional)
{
if (CurrentIndex >= MaxIndex && DirectionType == Forward)
{
DirectionType = Backward;
}
else if (CurrentIndex == MinIndex && DirectionType == Backward)
{
DirectionType = Forward;
}
}
BlackboardComponent->SetValueAsInt(GetSelectedBlackboardKey(), (DirectionType == Forward ? ++CurrentIndex : --CurrentIndex) % NumberOfPoints);
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
return EBTNodeResult::Succeeded;
}
}
}
return EBTNodeResult::Failed;
}

View File

@ -0,0 +1,32 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_IncrementPathIndex.generated.h"
/**
*
*/
UCLASS()
class ENDLESSVENDETTA_API UBTTask_IncrementPathIndex : public UBTTask_BlackboardBase
{
GENERATED_BODY()
public:
explicit UBTTask_IncrementPathIndex(FObjectInitializer const& ObjectInitializer);
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
private:
enum EPathFollowType
{
Forward,
Backward
};
EPathFollowType DirectionType = Forward;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true"))
bool bBiDirectional = false;
};