Compare commits
No commits in common. "98f0dbdce5b96697efdf705f8c263a1a9871d0c0" and "59a23e61db86dc7e6e154ad2c2cf0d317e59e886" have entirely different histories.
98f0dbdce5
...
59a23e61db
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -227,12 +227,8 @@ void UPS_AI_Behavior_BTTask_Attack::TickTask(
|
||||
{
|
||||
// No LOS and idle → find a firing position
|
||||
// Check if investigation (last known position) is active
|
||||
// ClearValue sets vectors to FAISystem::InvalidLocation, not zero — must check both
|
||||
const FVector LastKnownPos = BB->GetValueAsVector(PS_AI_Behavior_BB::LastKnownTargetPosition);
|
||||
const bool bHasLastKnown = !LastKnownPos.IsZero() &&
|
||||
!LastKnownPos.ContainsNaN() &&
|
||||
LastKnownPos.X < 1e30f; // Filter out FLT_MAX / InvalidLocation
|
||||
if (bHasLastKnown)
|
||||
if (!LastKnownPos.IsZero())
|
||||
{
|
||||
// Investigation mode: go to last known position
|
||||
AIC->MoveToLocation(
|
||||
@ -340,7 +336,6 @@ void UPS_AI_Behavior_BTTask_Attack::TickTask(
|
||||
*AIC->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EBTNodeResult::Type UPS_AI_Behavior_BTTask_Attack::AbortTask(
|
||||
@ -432,9 +427,20 @@ void UPS_AI_Behavior_BTTask_Attack::OnFiringPositionQueryFinished(
|
||||
|
||||
AActor* Target = WeakTarget.Get();
|
||||
|
||||
// Fallback lambda: advance directly toward target
|
||||
auto FallbackAdvance = [&](const TCHAR* Reason)
|
||||
if (Result.IsValid() && Result->IsSuccessful())
|
||||
{
|
||||
const FVector FiringPos = Result->GetItemAsLocation(0);
|
||||
AIC->MoveToLocation(
|
||||
FiringPos, 50.0f, /*bStopOnOverlap=*/true,
|
||||
/*bUsePathfinding=*/true, /*bProjectGoal=*/false, /*bCanStrafe=*/false);
|
||||
Memory->bSeekingFiringPos = true;
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS found firing position %s"),
|
||||
*AIC->GetName(), *FiringPos.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// EQS found nothing — fallback: advance toward target
|
||||
if (Target)
|
||||
{
|
||||
const float MidRange = (Memory->MinRange + Memory->MaxRange) * 0.5f;
|
||||
@ -443,32 +449,9 @@ void UPS_AI_Behavior_BTTask_Attack::OnFiringPositionQueryFinished(
|
||||
/*bUsePathfinding=*/true, /*bProjectGoal=*/true, /*bCanStrafe=*/false);
|
||||
Memory->bSeekingFiringPos = true;
|
||||
}
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: %s, fallback advance toward target"),
|
||||
*AIC->GetName(), Reason);
|
||||
};
|
||||
|
||||
if (Result.IsValid() && Result->IsSuccessful())
|
||||
{
|
||||
const FVector FiringPos = Result->GetItemAsLocation(0);
|
||||
const EPathFollowingRequestResult::Type MoveResult = AIC->MoveToLocation(
|
||||
FiringPos, 50.0f, /*bStopOnOverlap=*/true,
|
||||
/*bUsePathfinding=*/true, /*bProjectGoal=*/true, /*bCanStrafe=*/false);
|
||||
|
||||
if (MoveResult == EPathFollowingRequestResult::RequestSuccessful)
|
||||
{
|
||||
Memory->bSeekingFiringPos = true;
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS moving to firing position %s"),
|
||||
*AIC->GetName(), *FiringPos.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// AlreadyAtGoal or Failed — EQS position is too close or unreachable
|
||||
FallbackAdvance(TEXT("EQS position unreachable or too close"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FallbackAdvance(TEXT("EQS no result"));
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS no result, fallback advance"),
|
||||
*AIC->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -178,17 +178,6 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::AtCover));
|
||||
|
||||
// Crouch if the cover point requires it
|
||||
if (Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Verbose, TEXT("[%s] CoverShootCycle: at cover, ducking for %.1fs"),
|
||||
*AIC->GetName(), Memory->PhaseDuration);
|
||||
}
|
||||
@ -251,12 +240,13 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
}
|
||||
else
|
||||
{
|
||||
// No better cover found and no LOS → abandon cover, fall back to Attack task
|
||||
UE_LOG(LogPS_AI_Behavior, Log,
|
||||
TEXT("[%s] CoverShootCycle: no LOS and no advancing cover → abandoning cover for Attack fallback"),
|
||||
*AIC->GetName());
|
||||
FinishLatentTask(OwnerComp, EBTNodeResult::Failed);
|
||||
return;
|
||||
// No better cover → stay, retry next cycle
|
||||
Memory->SubState = EPS_AI_Behavior_CombatSubState::AtCover;
|
||||
Memory->PhaseDuration = FMath::RandRange(Memory->EffCoverMin, Memory->EffCoverMax);
|
||||
Memory->Timer = Memory->PhaseDuration;
|
||||
Memory->CycleCount = 0;
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::AtCover));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -265,15 +255,13 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
Memory->SubState = EPS_AI_Behavior_CombatSubState::Peeking;
|
||||
Memory->PhaseDuration = FMath::RandRange(Memory->EffPeekMin, Memory->EffPeekMax);
|
||||
Memory->Timer = Memory->PhaseDuration;
|
||||
Memory->LOSCheckTimer = 0.3f;
|
||||
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::Peeking));
|
||||
|
||||
// Stand up to shoot
|
||||
// Start attacking
|
||||
if (Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, false);
|
||||
IPS_AI_Behavior_Interface::Execute_BehaviorStartAttack(Pawn, Target);
|
||||
}
|
||||
|
||||
@ -286,40 +274,6 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
// ─── PEEKING: Shooting at target ────────────────────────────────
|
||||
case EPS_AI_Behavior_CombatSubState::Peeking:
|
||||
{
|
||||
// Continuous LOS check while peeking — stop shooting if target hides
|
||||
Memory->LOSCheckTimer -= DeltaSeconds;
|
||||
if (Memory->LOSCheckTimer <= 0.0f)
|
||||
{
|
||||
Memory->LOSCheckTimer = 0.3f; // check every 0.3s
|
||||
const bool bStillHasLOS = UPS_AI_Behavior_Statics::HasLineOfSight(
|
||||
Pawn->GetWorld(), Pawn, Target, 150.0f);
|
||||
if (!bStillHasLOS)
|
||||
{
|
||||
// Target hid — stop shooting, crouch back to cover
|
||||
if (Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_BehaviorStopAttack(Pawn);
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Log,
|
||||
TEXT("[%s] CoverShootCycle: lost LOS during peek → back to cover"),
|
||||
*AIC->GetName());
|
||||
|
||||
Memory->SubState = EPS_AI_Behavior_CombatSubState::AtCover;
|
||||
Memory->PhaseDuration = FMath::RandRange(Memory->EffCoverMin, Memory->EffCoverMax);
|
||||
Memory->Timer = Memory->PhaseDuration;
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::AtCover));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Memory->Timer -= DeltaSeconds;
|
||||
if (Memory->Timer <= 0.0f)
|
||||
{
|
||||
@ -399,17 +353,6 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::AtCover));
|
||||
|
||||
// Re-crouch if cover requires it
|
||||
if (Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Verbose,
|
||||
TEXT("[%s] CoverShootCycle: ducking back (cycle %d/%d)"),
|
||||
*AIC->GetName(), Memory->CycleCount, Memory->EffMaxCycles);
|
||||
@ -432,17 +375,6 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::TickTask(
|
||||
BB->SetValueAsEnum(PS_AI_Behavior_BB::CombatSubState,
|
||||
static_cast<uint8>(EPS_AI_Behavior_CombatSubState::AtCover));
|
||||
|
||||
// Crouch if the new cover point requires it
|
||||
if (Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Verbose, TEXT("[%s] CoverShootCycle: arrived at new cover, ducking"),
|
||||
*AIC->GetName());
|
||||
}
|
||||
@ -459,12 +391,11 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_CoverShootCycle::AbortTask(
|
||||
{
|
||||
AIC->StopMovement();
|
||||
|
||||
// Stop attacking and stand up if we were peeking/crouching
|
||||
// Stop attacking if we were peeking
|
||||
APawn* Pawn = AIC->GetPawn();
|
||||
if (Pawn && Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_BehaviorStopAttack(Pawn);
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,12 +408,11 @@ void UPS_AI_Behavior_BTTask_CoverShootCycle::OnTaskFinished(
|
||||
APS_AI_Behavior_AIController* AIC = Cast<APS_AI_Behavior_AIController>(OwnerComp.GetAIOwner());
|
||||
if (AIC)
|
||||
{
|
||||
// Stop attacking and stand up
|
||||
// Stop attacking
|
||||
APawn* Pawn = AIC->GetPawn();
|
||||
if (Pawn && Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_BehaviorStopAttack(Pawn);
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, false);
|
||||
}
|
||||
|
||||
// Release cover point
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "BT/PS_AI_Behavior_BTTask_FindCover.h"
|
||||
#include "PS_AI_Behavior_AIController.h"
|
||||
#include "PS_AI_Behavior_Interface.h"
|
||||
#include "PS_AI_Behavior_CoverPoint.h"
|
||||
#include "PS_AI_Behavior_PersonalityComponent.h"
|
||||
#include "PS_AI_Behavior_Definitions.h"
|
||||
@ -12,7 +11,6 @@
|
||||
#include "CollisionQueryParams.h"
|
||||
#include "Engine/World.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "EnvironmentQuery/EnvQueryManager.h"
|
||||
|
||||
UPS_AI_Behavior_BTTask_FindCover::UPS_AI_Behavior_BTTask_FindCover()
|
||||
{
|
||||
@ -122,16 +120,7 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindCover::ExecuteTask(
|
||||
|
||||
BB->SetValueAsVector(PS_AI_Behavior_BB::CoverLocation, BestCoverPos);
|
||||
|
||||
FCoverMemory* Memory = reinterpret_cast<FCoverMemory*>(NodeMemory);
|
||||
|
||||
// If we have a refinement EQS query and a manual CoverPoint, refine the position
|
||||
if (RefinementQuery && ChosenPoint)
|
||||
{
|
||||
RunRefinementQuery(OwnerComp, NodeMemory, AIC->GetPawn(), BestCoverPos);
|
||||
return EBTNodeResult::InProgress;
|
||||
}
|
||||
|
||||
// Navigate to cover directly (no refinement)
|
||||
// Navigate to cover
|
||||
const EPathFollowingRequestResult::Type Result = AIC->MoveToLocation(
|
||||
BestCoverPos, AcceptanceRadius, /*bStopOnOverlap=*/true,
|
||||
/*bUsePathfinding=*/true, /*bProjectDestinationToNavigation=*/true,
|
||||
@ -147,6 +136,7 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindCover::ExecuteTask(
|
||||
return EBTNodeResult::Succeeded;
|
||||
}
|
||||
|
||||
FCoverMemory* Memory = reinterpret_cast<FCoverMemory*>(NodeMemory);
|
||||
Memory->bMoveRequested = true;
|
||||
return EBTNodeResult::InProgress;
|
||||
}
|
||||
@ -155,7 +145,6 @@ void UPS_AI_Behavior_BTTask_FindCover::TickTask(
|
||||
UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
|
||||
{
|
||||
FCoverMemory* Memory = reinterpret_cast<FCoverMemory*>(NodeMemory);
|
||||
if (Memory->bEQSRunning) return; // Waiting for EQS callback
|
||||
if (!Memory->bMoveRequested) return;
|
||||
|
||||
APS_AI_Behavior_AIController* AIC = Cast<APS_AI_Behavior_AIController>(OwnerComp.GetAIOwner());
|
||||
@ -164,23 +153,6 @@ void UPS_AI_Behavior_BTTask_FindCover::TickTask(
|
||||
if (AIC->GetMoveStatus() == EPathFollowingStatus::Idle)
|
||||
{
|
||||
Memory->bMoveRequested = false;
|
||||
|
||||
// Crouch at cover if the point requires it
|
||||
APawn* Pawn = AIC->GetPawn();
|
||||
if (Pawn && Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
UBlackboardComponent* BB = OwnerComp.GetBlackboardComponent();
|
||||
if (BB)
|
||||
{
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
|
||||
}
|
||||
}
|
||||
@ -193,13 +165,6 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindCover::AbortTask(
|
||||
{
|
||||
AIC->StopMovement();
|
||||
|
||||
// Stand up if crouching
|
||||
APawn* Pawn = AIC->GetPawn();
|
||||
if (Pawn && Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, false);
|
||||
}
|
||||
|
||||
// Release any claimed cover point
|
||||
UBlackboardComponent* BB = OwnerComp.GetBlackboardComponent();
|
||||
if (BB)
|
||||
@ -208,7 +173,7 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindCover::AbortTask(
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (Point)
|
||||
{
|
||||
if (Pawn) Point->Release(Pawn);
|
||||
Point->Release(AIC->GetPawn());
|
||||
BB->ClearValue(PS_AI_Behavior_BB::CoverPoint);
|
||||
}
|
||||
}
|
||||
@ -321,108 +286,9 @@ float UPS_AI_Behavior_BTTask_FindCover::EvaluateCoverQuality(
|
||||
|
||||
FString UPS_AI_Behavior_BTTask_FindCover::GetStaticDescription() const
|
||||
{
|
||||
return FString::Printf(TEXT("Find cover within %.0fcm\nManual %s + Procedural (%d candidates)\nBonus: +%.0f%%\nRefinement: %s"),
|
||||
return FString::Printf(TEXT("Find cover within %.0fcm\nManual %s + Procedural (%d candidates)\nBonus: +%.0f%%"),
|
||||
SearchRadius,
|
||||
CoverPointType == EPS_AI_Behavior_CoverPointType::Cover ? TEXT("Cover") : TEXT("Hiding"),
|
||||
NumCandidates,
|
||||
ManualPointBonus * 100.0f,
|
||||
RefinementQuery ? *RefinementQuery->GetName() : TEXT("None"));
|
||||
}
|
||||
|
||||
// ─── EQS Refinement ────────────────────────────────────────────────────────
|
||||
|
||||
void UPS_AI_Behavior_BTTask_FindCover::RunRefinementQuery(
|
||||
UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory,
|
||||
APawn* Pawn, const FVector& CoverCenter)
|
||||
{
|
||||
FCoverMemory* Memory = reinterpret_cast<FCoverMemory*>(NodeMemory);
|
||||
|
||||
UWorld* World = Pawn->GetWorld();
|
||||
UEnvQueryManager* EQSManager = UEnvQueryManager::GetCurrent(World);
|
||||
if (!EQSManager)
|
||||
{
|
||||
// Fallback: move directly to the cover center
|
||||
APS_AI_Behavior_AIController* AIC = Cast<APS_AI_Behavior_AIController>(OwnerComp.GetAIOwner());
|
||||
if (AIC)
|
||||
{
|
||||
AIC->MoveToLocation(CoverCenter, AcceptanceRadius, true, true, true, false);
|
||||
Memory->bMoveRequested = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Memory->bEQSRunning = true;
|
||||
|
||||
FEnvQueryRequest Request(RefinementQuery, Pawn);
|
||||
Request.Execute(EEnvQueryRunMode::SingleResult,
|
||||
FQueryFinishedSignature::CreateUObject(this,
|
||||
&UPS_AI_Behavior_BTTask_FindCover::OnRefinementQueryFinished,
|
||||
&OwnerComp, NodeMemory, CoverCenter));
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Verbose, TEXT("[%s] FindCover: EQS refinement query launched around %s"),
|
||||
*Pawn->GetName(), *CoverCenter.ToString());
|
||||
}
|
||||
|
||||
void UPS_AI_Behavior_BTTask_FindCover::OnRefinementQueryFinished(
|
||||
TSharedPtr<FEnvQueryResult> Result,
|
||||
UBehaviorTreeComponent* OwnerComp, uint8* NodeMemory,
|
||||
FVector OriginalCoverPos)
|
||||
{
|
||||
if (!OwnerComp || !NodeMemory) return;
|
||||
|
||||
FCoverMemory* Memory = reinterpret_cast<FCoverMemory*>(NodeMemory);
|
||||
Memory->bEQSRunning = false;
|
||||
|
||||
APS_AI_Behavior_AIController* AIC = Cast<APS_AI_Behavior_AIController>(OwnerComp->GetAIOwner());
|
||||
if (!AIC || !AIC->GetPawn()) return;
|
||||
|
||||
FVector FinalPos = OriginalCoverPos; // Fallback to original position
|
||||
|
||||
if (Result.IsValid() && Result->IsSuccessful())
|
||||
{
|
||||
FinalPos = Result->GetItemAsLocation(0);
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] FindCover: EQS refined position %s (was %s)"),
|
||||
*AIC->GetName(), *FinalPos.ToString(), *OriginalCoverPos.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] FindCover: EQS refinement failed, using original cover position"),
|
||||
*AIC->GetName());
|
||||
}
|
||||
|
||||
// Update BB with refined position
|
||||
UBlackboardComponent* BB = OwnerComp->GetBlackboardComponent();
|
||||
if (BB)
|
||||
{
|
||||
BB->SetValueAsVector(PS_AI_Behavior_BB::CoverLocation, FinalPos);
|
||||
}
|
||||
|
||||
// Navigate to the refined (or original) position
|
||||
const EPathFollowingRequestResult::Type MoveResult = AIC->MoveToLocation(
|
||||
FinalPos, AcceptanceRadius, true, true, true, false);
|
||||
|
||||
if (MoveResult == EPathFollowingRequestResult::Failed)
|
||||
{
|
||||
FinishLatentTask(*OwnerComp, EBTNodeResult::Failed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MoveResult == EPathFollowingRequestResult::AlreadyAtGoal)
|
||||
{
|
||||
// Crouch at cover if needed
|
||||
APawn* Pawn = AIC->GetPawn();
|
||||
if (Pawn && Pawn->Implements<UPS_AI_Behavior_Interface>())
|
||||
{
|
||||
const APS_AI_Behavior_CoverPoint* CoverPt =
|
||||
Cast<APS_AI_Behavior_CoverPoint>(BB->GetValueAsObject(PS_AI_Behavior_BB::CoverPoint));
|
||||
if (CoverPt && CoverPt->bCrouch)
|
||||
{
|
||||
IPS_AI_Behavior_Interface::Execute_SetBehaviorCrouch(Pawn, true);
|
||||
}
|
||||
}
|
||||
FinishLatentTask(*OwnerComp, EBTNodeResult::Succeeded);
|
||||
return;
|
||||
}
|
||||
|
||||
Memory->bMoveRequested = true;
|
||||
ManualPointBonus * 100.0f);
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ public:
|
||||
UPROPERTY(EditAnywhere, Category = "Attack|LOS", meta = (ClampMin = "0.1", ClampMax = "1.0"))
|
||||
float LOSCheckInterval = 0.2f;
|
||||
|
||||
|
||||
/**
|
||||
* EQS query asset for finding a firing position with clear LOS.
|
||||
* Compose in editor: OnCircle generator + LineOfSight filter + Distance tests.
|
||||
|
||||
@ -87,7 +87,6 @@ private:
|
||||
float PhaseDuration = 0.0f;
|
||||
int32 CycleCount = 0;
|
||||
bool bMoveRequested = false;
|
||||
float LOSCheckTimer = 0.0f; // cooldown for LOS checks during Peeking
|
||||
|
||||
// Effective durations (modulated by personality)
|
||||
float EffPeekMin = 2.0f;
|
||||
|
||||
@ -4,12 +4,10 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BehaviorTree/BTTaskNode.h"
|
||||
#include "EnvironmentQuery/EnvQueryTypes.h"
|
||||
#include "PS_AI_Behavior_Definitions.h"
|
||||
#include "PS_AI_Behavior_BTTask_FindCover.generated.h"
|
||||
|
||||
class APS_AI_Behavior_CoverPoint;
|
||||
class UEnvQuery;
|
||||
|
||||
/**
|
||||
* BT Task: Find a cover position and navigate to it.
|
||||
@ -72,19 +70,6 @@ public:
|
||||
UPROPERTY(EditAnywhere, Category = "Cover|Advancement", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
||||
float AdvancementBias = 0.0f;
|
||||
|
||||
/**
|
||||
* Optional EQS query to refine the exact cover position around a selected CoverPoint.
|
||||
* The query runs centered on the chosen CoverPoint and picks the best nearby spot.
|
||||
* Use OnCircle generator (small radius ~200cm) + CoverQuality test + Distance tests.
|
||||
* If null, the NPC goes directly to the CoverPoint's location (no refinement).
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, Category = "Cover|EQS Refinement")
|
||||
TObjectPtr<UEnvQuery> RefinementQuery;
|
||||
|
||||
/** Radius around the CoverPoint for EQS refinement search (cm). */
|
||||
UPROPERTY(EditAnywhere, Category = "Cover|EQS Refinement", meta = (ClampMin = "100.0", ClampMax = "500.0"))
|
||||
float RefinementRadius = 200.0f;
|
||||
|
||||
protected:
|
||||
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
|
||||
virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
|
||||
@ -95,7 +80,6 @@ private:
|
||||
struct FCoverMemory
|
||||
{
|
||||
bool bMoveRequested = false;
|
||||
bool bEQSRunning = false;
|
||||
};
|
||||
|
||||
virtual uint16 GetInstanceMemorySize() const override { return sizeof(FCoverMemory); }
|
||||
@ -114,13 +98,4 @@ private:
|
||||
APS_AI_Behavior_CoverPoint* FindBestManualCoverPoint(
|
||||
const UWorld* World, const FVector& NpcLoc, const FVector& ThreatLoc,
|
||||
EPS_AI_Behavior_NPCType NPCType, float& OutScore) const;
|
||||
|
||||
/** Run EQS refinement query around the chosen CoverPoint. */
|
||||
void RunRefinementQuery(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory,
|
||||
APawn* Pawn, const FVector& CoverCenter);
|
||||
|
||||
/** Callback when the refinement EQS query completes. */
|
||||
void OnRefinementQueryFinished(TSharedPtr<FEnvQueryResult> Result,
|
||||
UBehaviorTreeComponent* OwnerComp, uint8* NodeMemory,
|
||||
FVector OriginalCoverPos);
|
||||
};
|
||||
|
||||
@ -142,18 +142,6 @@ public:
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
bool CanBehaviorAttack(AActor* Target) const;
|
||||
|
||||
// ─── Stance ─────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Order the Pawn to crouch or stand up.
|
||||
* Called by the cover system when entering/leaving a cover point with bCrouch set.
|
||||
* The Pawn implements this however it wants (CharacterMovement->Crouch, animation, etc.).
|
||||
*
|
||||
* @param bCrouch True = crouch, False = stand up.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
void SetBehaviorCrouch(bool bCrouch);
|
||||
|
||||
// ─── Combat Style ───────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user