FAISenseID UAISense_Blueprint::UpdateSenseID() { #if WITH_EDITOR // ignore skeleton and "old version"-classes if (FKismetEditorUtilities::IsClassABlueprintSkeleton(GetClass()) || GetClass()->HasAnyClassFlags(CLASS_NewerVersionExists) || (GetOutermost() == GetTransientPackage())) { return FAISenseID::InvalidID(); } #endif if (GetClass()->HasAnyClassFlags(CLASS_Abstract) == false) { const NAME_INDEX NameIndex = GetClass()->GetFName().GetDisplayIndex(); const FAISenseID* StoredID = BPSenseToSenseID.Find(NameIndex); if (StoredID != nullptr) { ForceSenseID(*StoredID); } else { const FAISenseID NewSenseID = FAISenseID(GetFName()); ForceSenseID(NewSenseID); BPSenseToSenseID.Add(NameIndex, GetSenseID()); } } return GetSenseID(); }
float UAISense_Team::Update() { AIPerception::FListenerMap& ListenersMap = *GetListeners(); for (AIPerception::FListenerMap::TIterator ListenerIt(ListenersMap); ListenerIt; ++ListenerIt) { FPerceptionListener& Listener = ListenerIt->Value; if (Listener.HasSense(GetSenseID()) == false) { // skip listeners not interested in this sense continue; } for (int32 EventIndex = 0; EventIndex < RegisteredEvents.Num(); ++EventIndex) { const FAITeamStimulusEvent& Event = RegisteredEvents[EventIndex]; // @todo implement some kind of TeamIdentifierType that would supply comparison operator if (Listener.TeamIdentifier != Event.TeamIdentifier || FVector::DistSquared(Event.GetBroadcastLocation(), Listener.CachedLocation) > Event.RangeSq) { continue; } Listener.RegisterStimulus(Event.Enemy, FAIStimulus(*this, Event.Strength, Event.LastKnowLocation, Event.GetBroadcastLocation(), FAIStimulus::SensingSucceeded).SetStimulusAge(Event.InformationAge)); } } RegisteredEvents.Reset(); // return decides when next tick is going to happen return SuspendNextUpdate; }
float UAISense_Touch::Update() { AIPerception::FListenerMap& ListenersMap = *GetListeners(); for (int32 EventIndex = 0; EventIndex < RegisteredEvents.Num(); ++EventIndex) { const FAITouchEvent& Event = RegisteredEvents[EventIndex]; if (Event.TouchReceiver != NULL && Event.OtherActor != NULL) { IAIPerceptionListenerInterface* PerceptionListener = Cast<IAIPerceptionListenerInterface>(Event.TouchReceiver); if (PerceptionListener != NULL) { UAIPerceptionComponent* PerceptionComponent = PerceptionListener->GetPerceptionComponent(); if (PerceptionComponent != NULL && ListenersMap.Contains(PerceptionComponent->GetListenerId())) { // this has to succeed, will assert a failure FPerceptionListener& Listener = ListenersMap[PerceptionComponent->GetListenerId()]; if (Listener.HasSense(GetSenseID())) { Listener.RegisterStimulus(Event.OtherActor, FAIStimulus(*this, 1.f, Event.Location, Event.Location)); } } } } } RegisteredEvents.Reset(); // return decides when next tick is going to happen return SuspendNextUpdate; }
bool UAISense_Sight::RegisterTarget(AActor& TargetActor, FQueriesOperationPostProcess PostProcess) { SCOPE_CYCLE_COUNTER(STAT_AI_Sense_Sight); FAISightTarget* SightTarget = ObservedTargets.Find(TargetActor.GetFName()); if (SightTarget == NULL) { FAISightTarget NewSightTarget(&TargetActor); SightTarget = &(ObservedTargets.Add(NewSightTarget.TargetId, NewSightTarget)); SightTarget->SightTargetInterface = Cast<IAISightTargetInterface>(&TargetActor); } // set/update data SightTarget->TeamId = FGenericTeamId::GetTeamIdentifier(&TargetActor); // generate all pairs and add them to current Sight Queries bool bNewQueriesAdded = false; AIPerception::FListenerMap& ListenersMap = *GetListeners(); const FVector TargetLocation = TargetActor.GetActorLocation(); for (AIPerception::FListenerMap::TConstIterator ItListener(ListenersMap); ItListener; ++ItListener) { const FPerceptionListener& Listener = ItListener->Value; const IGenericTeamAgentInterface* ListenersTeamAgent = Listener.GetTeamAgent(); if (Listener.HasSense(GetSenseID()) && Listener.GetBodyActor() != &TargetActor) { const FDigestedSightProperties& PropDigest = DigestedProperties[Listener.GetListenerID()]; if (FAISenseAffiliationFilter::ShouldSenseTeam(ListenersTeamAgent, TargetActor, PropDigest.AffiliationFlags)) { // create a sight query FAISightQuery SightQuery(ItListener->Key, SightTarget->TargetId); SightQuery.Importance = CalcQueryImportance(ItListener->Value, TargetLocation, PropDigest.SightRadiusSq); SightQueryQueue.Add(SightQuery); bNewQueriesAdded = true; } } } // sort Sight Queries if (PostProcess == Sort && bNewQueriesAdded) { SortQueries(); RequestImmediateUpdate(); } return bNewQueriesAdded; }
void UAISense_Aquaphobia::OnNewListenerImpl(const FPerceptionListener& NewListener) { //Since we have at least one AI actor with this sense this function will fire when the game starts GLog->Log("hello new listener!"); check(NewListener.Listener.IsValid()); //Get the config UAISenseConfig* Config = NewListener.Listener->GetSenseConfig(GetSenseID()); const UAISenseConfig_Aquaphobia* SenseConfig = Cast<const UAISenseConfig_Aquaphobia>(Config); check(SenseConfig); //Consume properties from the sense config FDigestedAquaProperties PropertyDigest(*SenseConfig); DigestedProperties.Add(PropertyDigest); RequestImmediateUpdate(); }
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); } }
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); }