Add reworked Worker Enemy AI #3
BIN
Content/Enemy/BB_Base_Enemy.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BB_Base_Enemy.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/BehaviorTrees/BT_Passive_State.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/BehaviorTrees/BT_Passive_State.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/EQS/AttackTarget.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/EQS/AttackTarget.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/EQS/EQSTestingPawn.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/EQS/EQSTestingPawn.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_FindCover.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/EQS/EQS_FindCover.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_FindIdealRange.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/EQS/EQS_FindIdealRange.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/EQS/EQS_Strafe.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/EQS/EQS_Strafe.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/FireWeaponTasks.uasset
(Stored with Git LFS)
BIN
Content/Enemy/FireWeaponTasks.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Enemy/Tasks/BTTMoveToIdealRange.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/Tasks/BTTMoveToIdealRange.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/Worker/AIC_Worker.uasset
(Stored with Git LFS)
Normal file
BIN
Content/Enemy/Worker/AIC_Worker.uasset
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Enemy/Worker/BB_Worker.uasset
(Stored with Git LFS)
BIN
Content/Enemy/Worker/BB_Worker.uasset
(Stored with Git LFS)
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)
Normal file
BIN
Content/TestPatrolRoute.uasset
(Stored with Git LFS)
Normal file
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.
27
Source/Nakatomi/Decorators/BTDCanSeeTarget.cpp
Normal file
27
Source/Nakatomi/Decorators/BTDCanSeeTarget.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
24
Source/Nakatomi/Decorators/BTDCanSeeTarget.h
Normal file
24
Source/Nakatomi/Decorators/BTDCanSeeTarget.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
14
Source/Nakatomi/Decorators/BTDHasPatrolRoute.cpp
Normal file
14
Source/Nakatomi/Decorators/BTDHasPatrolRoute.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
19
Source/Nakatomi/Decorators/BTDHasPatrolRoute.h
Normal file
19
Source/Nakatomi/Decorators/BTDHasPatrolRoute.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
14
Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.cpp
Normal file
14
Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
29
Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.h
Normal file
29
Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
29
Source/Nakatomi/Decorators/BTDIsWithinRange.cpp
Normal file
29
Source/Nakatomi/Decorators/BTDIsWithinRange.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
31
Source/Nakatomi/Decorators/BTDIsWithinRange.h
Normal file
31
Source/Nakatomi/Decorators/BTDIsWithinRange.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
};
|
23
Source/Nakatomi/Decorators/BTDWeaponCooldown.cpp
Normal file
23
Source/Nakatomi/Decorators/BTDWeaponCooldown.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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);
|
||||||
|
}
|
19
Source/Nakatomi/Decorators/BTDWeaponCooldown.h
Normal file
19
Source/Nakatomi/Decorators/BTDWeaponCooldown.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
5
Source/Nakatomi/EAIState.cpp
Normal file
5
Source/Nakatomi/EAIState.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "EAIState.h"
|
||||||
|
|
18
Source/Nakatomi/EAIState.h
Normal file
18
Source/Nakatomi/EAIState.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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"),
|
||||||
|
};
|
4
Source/Nakatomi/EPatrolMovementEnum.cpp
Normal file
4
Source/Nakatomi/EPatrolMovementEnum.cpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "EPatrolMovementEnum.h"
|
16
Source/Nakatomi/EPatrolMovementEnum.h
Normal file
16
Source/Nakatomi/EPatrolMovementEnum.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// 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,6 +2,8 @@
|
|||||||
|
|
||||||
#include "EnemyAIController.h"
|
#include "EnemyAIController.h"
|
||||||
#include <Kismet/GameplayStatics.h>
|
#include <Kismet/GameplayStatics.h>
|
||||||
|
|
||||||
|
#include "EAIState.h"
|
||||||
#include "NakatomiGameInstance.h"
|
#include "NakatomiGameInstance.h"
|
||||||
#include "BehaviorTree/BehaviorTree.h"
|
#include "BehaviorTree/BehaviorTree.h"
|
||||||
#include "BehaviorTree/BlackboardComponent.h"
|
#include "BehaviorTree/BlackboardComponent.h"
|
||||||
@ -25,8 +27,19 @@ AEnemyAIController::AEnemyAIController(const FObjectInitializer& object_initiali
|
|||||||
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
|
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
|
||||||
SightConfig->DetectionByAffiliation.bDetectNeutrals = 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->SetDominantSense(SightConfig->GetSenseImplementation());
|
||||||
AIPerception->ConfigureSense(*SightConfig);
|
AIPerception->ConfigureSense(*SightConfig);
|
||||||
|
AIPerception->ConfigureSense(*HearingConfig);
|
||||||
|
AIPerception->ConfigureSense(*DamageConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEnemyAIController::OnPossess(APawn* InPawn)
|
void AEnemyAIController::OnPossess(APawn* InPawn)
|
||||||
@ -48,6 +61,11 @@ void AEnemyAIController::OnPossess(APawn* InPawn)
|
|||||||
BehaviorTree->StartTree(*behaviourTree);
|
BehaviorTree->StartTree(*behaviourTree);
|
||||||
Blackboard->SetValueAsObject("SelfActor", enemy);
|
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());
|
//ensure(enemy->GetMovementComponent()->UseAccelerationForPathFollowing());
|
||||||
}
|
}
|
||||||
@ -116,7 +134,7 @@ void AEnemyAIController::OnDeath(FDamageInfo info)
|
|||||||
|
|
||||||
void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
|
void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
|
||||||
{
|
{
|
||||||
for (auto actor : actors)
|
for (AActor* actor : actors)
|
||||||
{
|
{
|
||||||
if (!actor->GetClass()->IsChildOf(APlayerCharacter::StaticClass()))
|
if (!actor->GetClass()->IsChildOf(APlayerCharacter::StaticClass()))
|
||||||
{
|
{
|
||||||
@ -126,13 +144,46 @@ void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
|
|||||||
FActorPerceptionBlueprintInfo perceptionInfo;
|
FActorPerceptionBlueprintInfo perceptionInfo;
|
||||||
PerceptionComponent->GetActorsPerception(actor, perceptionInfo);
|
PerceptionComponent->GetActorsPerception(actor, perceptionInfo);
|
||||||
|
|
||||||
for (auto& stimulus : perceptionInfo.LastSensedStimuli)
|
for (FAIStimulus& stimulus : perceptionInfo.LastSensedStimuli)
|
||||||
{
|
{
|
||||||
if (!stimulus.IsValid() || stimulus.IsExpired())
|
if (!stimulus.IsValid() || stimulus.IsExpired() ||
|
||||||
|
static_cast<EAIState>(Blackboard->GetValueAsEnum("State")) == EAIState::DEAD)
|
||||||
{
|
{
|
||||||
continue;
|
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);
|
Blackboard->SetValueAsObject("TargetActor", actor);
|
||||||
|
|
||||||
if (stimulus.IsActive())
|
if (stimulus.IsActive())
|
||||||
@ -179,3 +230,51 @@ bool AEnemyAIController::GetHasAttackToken()
|
|||||||
{
|
{
|
||||||
return HasAttackToken;
|
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,8 +4,11 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "AIController.h"
|
#include "AIController.h"
|
||||||
|
#include "EAIState.h"
|
||||||
#include "EnemyCharacter.h"
|
#include "EnemyCharacter.h"
|
||||||
#include "PlayerCharacter.h"
|
#include "PlayerCharacter.h"
|
||||||
|
#include "Perception/AISenseConfig_Damage.h"
|
||||||
|
#include "Perception/AISenseConfig_Hearing.h"
|
||||||
#include "Perception/AISenseConfig_Sight.h"
|
#include "Perception/AISenseConfig_Sight.h"
|
||||||
#include "EnemyAIController.generated.h"
|
#include "EnemyAIController.generated.h"
|
||||||
|
|
||||||
@ -29,6 +32,10 @@ private:
|
|||||||
|
|
||||||
UAISenseConfig_Sight* SightConfig;
|
UAISenseConfig_Sight* SightConfig;
|
||||||
|
|
||||||
|
UAISenseConfig_Hearing* HearingConfig;
|
||||||
|
|
||||||
|
UAISenseConfig_Damage* DamageConfig;
|
||||||
|
|
||||||
bool HasAttackToken = false;
|
bool HasAttackToken = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -59,4 +66,24 @@ public:
|
|||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
bool GetHasAttackToken();
|
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,7 +2,11 @@
|
|||||||
|
|
||||||
#include "EnemyCharacter.h"
|
#include "EnemyCharacter.h"
|
||||||
#include "EnemyAIController.h"
|
#include "EnemyAIController.h"
|
||||||
|
#include "EnemyHealthComponent.h"
|
||||||
#include "InteractableComponent.h"
|
#include "InteractableComponent.h"
|
||||||
|
#include "BehaviorTree/BehaviorTree.h"
|
||||||
|
#include "BehaviorTree/BlackboardComponent.h"
|
||||||
|
#include "BehaviorTree/BlackboardData.h"
|
||||||
|
|
||||||
#define COLLISION_WEAPON ECC_GameTraceChannel1
|
#define COLLISION_WEAPON ECC_GameTraceChannel1
|
||||||
|
|
||||||
@ -10,8 +14,12 @@ AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer) :
|
|||||||
{
|
{
|
||||||
RandomWeaponParameters = CreateDefaultSubobject<URandomWeaponParameters>(TEXT("Random Weapon Parameters"));
|
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);
|
GetHealthComponent()->SetMaxHealth(100.0f);
|
||||||
|
|
||||||
this->Tags.Add(FName("Enemy"));
|
this->Tags.Add(FName("Enemy"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +57,10 @@ void AEnemyCharacter::WeaponCooldownHandler()
|
|||||||
void AEnemyCharacter::BeginPlay()
|
void AEnemyCharacter::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
AEnemyAIController* controller = Cast<AEnemyAIController>(GetController());
|
||||||
|
controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth());
|
||||||
|
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEnemyCharacter::PlayOnFireAnimations()
|
void AEnemyCharacter::PlayOnFireAnimations()
|
||||||
@ -125,3 +137,12 @@ void AEnemyCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AEnemyCharacter::OnDamaged()
|
||||||
|
{
|
||||||
|
Super::OnDamaged();
|
||||||
|
|
||||||
|
AEnemyAIController* controller = Cast<AEnemyAIController>(GetController());
|
||||||
|
controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "NakatomiCharacter.h"
|
#include "NakatomiCharacter.h"
|
||||||
|
#include "PatrolRoute.h"
|
||||||
#include "BehaviorTree/BehaviorTreeComponent.h"
|
#include "BehaviorTree/BehaviorTreeComponent.h"
|
||||||
#include "RandomWeaponParameters.h"
|
#include "RandomWeaponParameters.h"
|
||||||
#include "EnemyCharacter.generated.h"
|
#include "EnemyCharacter.generated.h"
|
||||||
@ -17,6 +18,16 @@ class NAKATOMI_API AEnemyCharacter : public ANakatomiCharacter
|
|||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(EditAnywhere, Meta = (AllowPrivateAccess = "true"))
|
||||||
|
APatrolRoute* CurrentPatrolRoute;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere)
|
||||||
|
float AttackRadius = 300.0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere)
|
||||||
|
float DefendRadius = 500.0f;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
|
UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true"))
|
||||||
UBehaviorTree* BehaviourTree;
|
UBehaviorTree* BehaviourTree;
|
||||||
@ -44,4 +55,7 @@ private:
|
|||||||
virtual void CalculateHits(TArray<FHitResult>* hits) override;
|
virtual void CalculateHits(TArray<FHitResult>* hits) override;
|
||||||
|
|
||||||
virtual void ProcessHits(TArray<FHitResult> hits) override;
|
virtual void ProcessHits(TArray<FHitResult> hits) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnDamaged() override;
|
||||||
};
|
};
|
||||||
|
36
Source/Nakatomi/EnemyHealthComponent.cpp
Normal file
36
Source/Nakatomi/EnemyHealthComponent.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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});
|
||||||
|
}
|
||||||
|
}
|
22
Source/Nakatomi/EnemyHealthComponent.h
Normal file
22
Source/Nakatomi/EnemyHealthComponent.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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;
|
FOnDamageDelegate OnDamaged;
|
||||||
FOnDeathDelegate OnDeath;
|
FOnDeathDelegate OnDeath;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
UPROPERTY(EditDefaultsOnly)
|
UPROPERTY(EditDefaultsOnly)
|
||||||
float MaxHealth = 100.f;
|
float MaxHealth = 100.f;
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ public:
|
|||||||
UHealthComponent();
|
UHealthComponent();
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy,
|
virtual void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy,
|
||||||
AActor* damageCauser);
|
AActor* damageCauser);
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
|
@ -19,6 +19,12 @@ void UNakatomiCMC::InitializeComponent()
|
|||||||
NakatomiCharacterOwner = Cast<ANakatomiCharacter>(GetOwner());
|
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.
|
// 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.
|
// 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,
|
bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter,
|
||||||
@ -271,6 +277,16 @@ bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode
|
|||||||
return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode;
|
return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UNakatomiCMC::SetMaxWalkSpeed(float newMaxSpeed)
|
||||||
|
{
|
||||||
|
Walk_MaxWalkSpeed = newMaxSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UNakatomiCMC::SetMaxWalkSpeedToDefault()
|
||||||
|
{
|
||||||
|
Walk_MaxWalkSpeed = DefaultMaxWalkSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
void UNakatomiCMC::EnterSlide()
|
void UNakatomiCMC::EnterSlide()
|
||||||
{
|
{
|
||||||
Safe_bWantsToSlide = true;
|
Safe_bWantsToSlide = true;
|
||||||
|
@ -108,6 +108,8 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
|||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
ANakatomiCharacter* NakatomiCharacterOwner;
|
ANakatomiCharacter* NakatomiCharacterOwner;
|
||||||
|
|
||||||
|
float DefaultMaxWalkSpeed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(BlueprintAssignable)
|
UPROPERTY(BlueprintAssignable)
|
||||||
FDashStartDelegate DashStartDelegate;
|
FDashStartDelegate DashStartDelegate;
|
||||||
@ -118,6 +120,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void InitializeComponent() override;
|
virtual void InitializeComponent() override;
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override;
|
virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -167,6 +171,12 @@ public:
|
|||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const;
|
bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void SetMaxWalkSpeed(float newMaxSpeed);
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void SetMaxWalkSpeedToDefault();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnterSlide();
|
void EnterSlide();
|
||||||
void ExitSlide();
|
void ExitSlide();
|
||||||
|
@ -14,9 +14,12 @@ ANakatomiCharacter::ANakatomiCharacter(const FObjectInitializer& ObjectInitializ
|
|||||||
|
|
||||||
NakatomiCMC = Cast<UNakatomiCMC>(GetCharacterMovement());
|
NakatomiCMC = Cast<UNakatomiCMC>(GetCharacterMovement());
|
||||||
|
|
||||||
HealthComponent = CreateDefaultSubobject<UHealthComponent>(TEXT("Health Component"));
|
// if (!HealthComponent)
|
||||||
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
|
// Called when the game starts or when spawned
|
||||||
|
37
Source/Nakatomi/PatrolRoute.cpp
Normal file
37
Source/Nakatomi/PatrolRoute.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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);
|
||||||
|
}
|
34
Source/Nakatomi/PatrolRoute.h
Normal file
34
Source/Nakatomi/PatrolRoute.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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,6 +30,10 @@ APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer)
|
|||||||
//bUseControllerRotationYaw = true;
|
//bUseControllerRotationYaw = true;
|
||||||
//bUseControllerRotationRoll = false;
|
//bUseControllerRotationRoll = false;
|
||||||
|
|
||||||
|
SetHealthComponent(CreateDefaultSubobject<UHealthComponent>(TEXT("Health Component")));
|
||||||
|
GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged");
|
||||||
|
GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath");
|
||||||
|
|
||||||
// Setup the camera boom
|
// Setup the camera boom
|
||||||
CameraSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArmComponent"));
|
CameraSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArmComponent"));
|
||||||
CameraSpringArmComponent->SetupAttachment(RootComponent);
|
CameraSpringArmComponent->SetupAttachment(RootComponent);
|
||||||
@ -398,6 +402,7 @@ void APlayerCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||||||
{
|
{
|
||||||
healthComponent->TakeDamage(Hit.GetActor(), CurrentWeapon->GetWeaponProperties()->WeaponDamage, nullptr,
|
healthComponent->TakeDamage(Hit.GetActor(), CurrentWeapon->GetWeaponProperties()->WeaponDamage, nullptr,
|
||||||
GetController(), this);
|
GetController(), this);
|
||||||
|
|
||||||
if (!healthComponent->GetIsDead())
|
if (!healthComponent->GetIsDead())
|
||||||
{
|
{
|
||||||
OnEnemyHit.ExecuteIfBound();
|
OnEnemyHit.ExecuteIfBound();
|
||||||
@ -437,6 +442,8 @@ void APlayerCharacter::ProcessHits(TArray<FHitResult> hits)
|
|||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MakeNoise(1, this, Hit.Location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,6 +646,8 @@ void APlayerCharacter::OnFire()
|
|||||||
|
|
||||||
CurrentWeapon->PlayFireSoundAtLocation(this->GetTransform().GetLocation());
|
CurrentWeapon->PlayFireSoundAtLocation(this->GetTransform().GetLocation());
|
||||||
|
|
||||||
|
MakeNoise(1,this, this->GetTransform().GetLocation());
|
||||||
|
|
||||||
PlayOnFireAnimations();
|
PlayOnFireAnimations();
|
||||||
|
|
||||||
CurrentWeapon->SetCurrentWeaponStatus(Cooldown);
|
CurrentWeapon->SetCurrentWeaponStatus(Cooldown);
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
// Fill out your copyright notice in the Description page of Project Settings.
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
#include "Tasks/BTTClearFocus.h"
|
#include "../Tasks/BTTClearFocus.h"
|
||||||
|
|
||||||
|
#include "Nakatomi/EnemyAIController.h"
|
||||||
|
|
||||||
|
EBTNodeResult::Type UBTTClearFocus::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory)
|
||||||
|
{
|
||||||
|
auto enemyController = Cast<AEnemyAIController>(owner.GetAIOwner());
|
||||||
|
enemyController->ClearFocus(EAIFocusPriority::Default);
|
||||||
|
return EBTNodeResult::Succeeded;
|
||||||
|
}
|
||||||
|
@ -13,5 +13,8 @@ UCLASS()
|
|||||||
class NAKATOMI_API UBTTClearFocus : public UBTTaskNode
|
class NAKATOMI_API UBTTClearFocus : public UBTTaskNode
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
28
Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.cpp
Normal file
28
Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
24
Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.h
Normal file
24
Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
33
Source/Nakatomi/Tasks/BTTSetMovementSpeed.cpp
Normal file
33
Source/Nakatomi/Tasks/BTTSetMovementSpeed.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
34
Source/Nakatomi/Tasks/BTTSetMovementSpeed.h
Normal file
34
Source/Nakatomi/Tasks/BTTSetMovementSpeed.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
};
|
17
Source/Nakatomi/Tasks/BTTSetState.cpp
Normal file
17
Source/Nakatomi/Tasks/BTTSetState.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
27
Source/Nakatomi/Tasks/BTTSetState.h
Normal file
27
Source/Nakatomi/Tasks/BTTSetState.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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…
x
Reference in New Issue
Block a user