// © 2025 Naked People Team. All Rights Reserved. #include "NPCAIController.h" #include "NPC.h" #include "Perception/AISense_Sight.h" #include "Perception/AISenseConfig_Sight.h" #include "NakedDesire/Player/NakedDesireCharacter.h" #include "NakedDesire/Stats/StatsManager.h" #include "Perception/AIPerceptionComponent.h" ANPCAIController::ANPCAIController() { UAIPerceptionComponent* Perception = CreateDefaultSubobject(TEXT("PerceptionComponent")); SetPerceptionComponent(*Perception); UAISenseConfig_Sight* SightConfig = CreateDefaultSubobject(TEXT("SightConfig")); SightConfig->DetectionByAffiliation.bDetectEnemies = true; SightConfig->DetectionByAffiliation.bDetectNeutrals = true; SightConfig->DetectionByAffiliation.bDetectFriendlies = true; Perception->ConfigureSense(*SightConfig); Perception->SetDominantSense(SightConfig->GetSenseImplementation()); } void ANPCAIController::OnPossess(APawn* InPawn) { Super::OnPossess(InPawn); PerceptionComponent->OnTargetPerceptionUpdated.AddUniqueDynamic(this, &ANPCAIController::OnTargetPerceptionUpdate); } void ANPCAIController::OnUnPossess() { ClearObservation(); Super::OnUnPossess(); } void ANPCAIController::ClearObservation() { if (bCurrentlyObserving && PlayerCharacter) { PlayerCharacter->StatsManager->SetObserved(false, GetPawn()); bCurrentlyObserving = false; } } float ANPCAIController::GetObservationWeight() const { if (const ANPC* NPC = Cast(GetPawn())) return NPC->GetObservationWeight(); return 1.0f; } void ANPCAIController::OnTargetPerceptionUpdate(AActor* Actor, FAIStimulus Stimulus) { if (Stimulus.Type != UAISense::GetSenseID()) return; ANakedDesireCharacter* SensedPlayer = Cast(Actor); if (!SensedPlayer) return; PlayerCharacter = SensedPlayer; const bool bSensed = Stimulus.WasSuccessfullySensed(); if (bSensed == bCurrentlyObserving) return; bCurrentlyObserving = bSensed; PlayerCharacter->StatsManager->SetObserved(bSensed, GetPawn(), GetObservationWeight()); }