D1/Source/D1/AI/CombatAIController.cpp

95 lines
3.2 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "AI/CombatAIController.h"
#include "GameplayTagAssetInterface.h"
#include "MasterAI.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Components/CombatComponent.h"
#include "Definitions/CombatGameplayTags.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Damage.h"
#include "Perception/AISenseConfig_Sight.h"
ACombatAIController::ACombatAIController()
{
PerceptionComponent = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("PerceptionComponent"));
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("SightConfig"));
SightConfig->SightRadius = 3000.f;
SightConfig->LoseSightRadius = 3500.f;
SightConfig->PeripheralVisionAngleDegrees = 45.f;
FAISenseAffiliationFilter AffiliationFilter;
AffiliationFilter.bDetectEnemies = true;
AffiliationFilter.bDetectFriendlies = true;
AffiliationFilter.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation = AffiliationFilter;
SightConfig->AutoSuccessRangeFromLastSeenLocation = 2500.f;
PerceptionComponent->ConfigureSense(*SightConfig);
DamageConfig = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("DamageConfig"));
DamageConfig->SetMaxAge(3.f); // Expired 3 Seconds
PerceptionComponent->ConfigureSense(*DamageConfig);
PerceptionComponent->OnPerceptionUpdated.AddDynamic(this, &ACombatAIController::OnUpdatePerception);
}
void ACombatAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
AMasterAI* AIpawn = Cast<AMasterAI>(InPawn);
if(!AIpawn)
return;
MasterAI = AIpawn;
UCombatComponent* combatComponent = MasterAI->GetComponentByClass<UCombatComponent>();
combatComponent->OnCombatToggled.AddUObject(this, &ACombatAIController::OnCombatToggle);
RunBehaviorTree(MasterAI->GetBeHaviorTree());
}
void ACombatAIController::OnUpdatePerception(const TArray<AActor*>& PerceivedActors)
{
for (auto SensoredActor : PerceivedActors) //탐지된 Actor
{
IGameplayTagAssetInterface* CurActor = Cast<IGameplayTagAssetInterface>(SensoredActor); //Player가 아닌 Actor는 탐지되도 반응 없게 함
if(!CurActor)
continue;
if(!CurActor->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
continue;
FActorPerceptionBlueprintInfo PerceptionInfo;
GetPerceptionComponent()->GetActorsPerception(SensoredActor, PerceptionInfo);
for(int i = 0; i < PerceptionInfo.LastSensedStimuli.Num(); i++) //탐지방식에 따른 for문
{
auto Info = PerceptionInfo.LastSensedStimuli[i];
auto SensedClass = UAIPerceptionSystem::GetSenseClassForStimulus(this, Info);
if(SensedClass == UAISense_Sight::StaticClass())
{
SetTargetActor(SensoredActor);
}
else if(SensedClass == UAISense_Damage::StaticClass())
{
if(Info.WasSuccessfullySensed() && !Info.IsExpired()) //After DamageConfig->GetMaxAge then Expired
SetTargetActor(SensoredActor);
}
}
}
}
void ACombatAIController::OnCombatToggle(bool IsCombatEnabled)
{
Blackboard->SetValueAsBool(TEXT("bCombatEnabled"), IsCombatEnabled);
}
void ACombatAIController::SetTargetActor(AActor* NewTargetActor)
{
Blackboard->SetValueAsObject(TEXT("Target"), NewTargetActor);
if(IsValid(MasterAI))
MasterAI->OnTargetSet(NewTargetActor);
}