void UAISense_Sight::GenerateQueriesForListener(const FPerceptionListener& Listener, const FDigestedSightProperties& PropertyDigest) { bool bNewQueriesAdded = false; const IGenericTeamAgentInterface* ListenersTeamAgent = Listener.GetTeamAgent(); // create sight queries with all legal targets for (TMap<FName, FAISightTarget>::TConstIterator ItTarget(ObservedTargets); ItTarget; ++ItTarget) { const AActor* TargetActor = ItTarget->Value.GetTargetActor(); if (TargetActor == NULL) { continue; } // @todo this should be configurable - some AI might want to observe Neutrals and Friendlies as well if (ListenersTeamAgent == NULL || ListenersTeamAgent->GetTeamAttitudeTowards(*TargetActor) == ETeamAttitude::Hostile) { // create a sight query FAISightQuery SightQuery(Listener.GetListenerID(), ItTarget->Key); SightQuery.Importance = CalcQueryImportance(Listener, ItTarget->Value.GetLocationSimple(), PropertyDigest.SightRadiusSq); SightQueryQueue.Add(SightQuery); bNewQueriesAdded = true; } } // sort Sight Queries if (bNewQueriesAdded) { SortQueries(); RequestImmediateUpdate(); } }
void UAISense_Sight::RemoveAllQueriesByListener(const FPerceptionListener& Listener, FQueriesOperationPostProcess PostProcess) { SCOPE_CYCLE_COUNTER(STAT_AI_Sense_Sight); if (SightQueryQueue.Num() == 0) { return; } const uint32 ListenerId = Listener.GetListenerID(); bool bQueriesRemoved = false; const FAISightQuery* SightQuery = &SightQueryQueue[SightQueryQueue.Num() - 1]; for (int32 QueryIndex = SightQueryQueue.Num() - 1; QueryIndex >= 0 ; --QueryIndex, --SightQuery) { if (SightQuery->ObserverId == ListenerId) { SightQueryQueue.RemoveAt(QueryIndex, 1, /*bAllowShrinking=*/false); bQueriesRemoved = true; } } if (PostProcess == Sort && bQueriesRemoved) { SortQueries(); } }
void UAISense_Sight::GenerateQueriesForListener(const FPerceptionListener& Listener, const FDigestedSightProperties& PropertyDigest) { bool bNewQueriesAdded = false; const IGenericTeamAgentInterface* ListenersTeamAgent = Listener.GetTeamAgent(); const AActor* Avatar = Listener.GetBodyActor(); // create sight queries with all legal targets for (TMap<FName, FAISightTarget>::TConstIterator ItTarget(ObservedTargets); ItTarget; ++ItTarget) { const AActor* TargetActor = ItTarget->Value.GetTargetActor(); if (TargetActor == NULL || TargetActor == Avatar) { continue; } if (FAISenseAffiliationFilter::ShouldSenseTeam(ListenersTeamAgent, *TargetActor, PropertyDigest.AffiliationFlags)) { // create a sight query FAISightQuery SightQuery(Listener.GetListenerID(), ItTarget->Key); SightQuery.Importance = CalcQueryImportance(Listener, ItTarget->Value.GetLocationSimple(), PropertyDigest.SightRadiusSq); SightQueryQueue.Add(SightQuery); bNewQueriesAdded = true; } } // sort Sight Queries if (bNewQueriesAdded) { SortQueries(); RequestImmediateUpdate(); } }
void UAISense_Sight::OnNewListenerImpl(const FPerceptionListener& NewListener) { check(NewListener.Listener.IsValid()); const UAISenseConfig_Sight* SenseConfig = Cast<const UAISenseConfig_Sight>(NewListener.Listener->GetSenseConfig(GetSenseID())); check(SenseConfig); const FDigestedSightProperties PropertyDigest(*SenseConfig); DigestedProperties.Add(NewListener.GetListenerID(), PropertyDigest); GenerateQueriesForListener(NewListener, PropertyDigest); }
void UAISense_Sight::OnListenerRemovedImpl(const FPerceptionListener& UpdatedListener) { RemoveAllQueriesByListener(UpdatedListener, DontSort); DigestedProperties.FindAndRemoveChecked(UpdatedListener.GetListenerID()); // note: there use to be code to remove all queries _to_ listener here as well // but that was wrong - the fact that a listener gets unregistered doesn't have to // mean it's being removed from the game altogether. }
void UAISense_Sight::OnListenerRemovedImpl(const FPerceptionListener& UpdatedListener) { RemoveAllQueriesByListener(UpdatedListener, DontSort); DigestedProperties.FindAndRemoveChecked(UpdatedListener.GetListenerID()); if (UpdatedListener.Listener.IsValid()) { // see if this listener is a Target as well const FAISightTarget::FTargetId AsTargetId = UpdatedListener.GetBodyActorName(); FAISightTarget* AsTarget = ObservedTargets.Find(AsTargetId); if (AsTarget != NULL) { RemoveAllQueriesToTarget(AsTargetId, Sort); } } else { //@todo quite possible there are left over sight queries with this listener as target } }
void UAISense_Sight::OnListenerUpdateImpl(const FPerceptionListener& UpdatedListener) { SCOPE_CYCLE_COUNTER(STAT_AI_Sense_Sight_ListenerUpdate); // first, naive implementation: // 1. remove all queries by this listener // 2. proceed as if it was a new listener // remove all queries RemoveAllQueriesByListener(UpdatedListener, DontSort); // see if this listener is a Target as well const FAISightTarget::FTargetId AsTargetId = UpdatedListener.GetBodyActorName(); FAISightTarget* AsTarget = ObservedTargets.Find(AsTargetId); if (AsTarget != NULL) { RemoveAllQueriesToTarget(AsTargetId, DontSort); if (AsTarget->Target.IsValid()) { RegisterTarget(*(AsTarget->Target.Get()), DontSort); } } const FPerceptionListenerID ListenerID = UpdatedListener.GetListenerID(); if (UpdatedListener.HasSense(GetSenseID())) { const UAISenseConfig_Sight* SenseConfig = Cast<const UAISenseConfig_Sight>(UpdatedListener.Listener->GetSenseConfig(GetSenseID())); check(SenseConfig); FDigestedSightProperties& PropertiesDigest = DigestedProperties.FindOrAdd(ListenerID); PropertiesDigest = FDigestedSightProperties(*SenseConfig); GenerateQueriesForListener(UpdatedListener, PropertiesDigest); } else { DigestedProperties.FindAndRemoveChecked(ListenerID); } }