Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

147 lines
5.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/Object.h"
#include "Templates/SubclassOf.h"
#include "Perception/AIPerceptionTypes.h"
#include "AISense.generated.h"
class APawn;
class FGameplayDebuggerCategory;
class UAIPerceptionSystem;
class UAISenseEvent;
DECLARE_DELEGATE_OneParam(FOnPerceptionListenerUpdateDelegate, const FPerceptionListener&);
UCLASS(ClassGroup = AI, abstract, config = Engine, MinimalAPI)
class UAISense : public UObject
{
GENERATED_UCLASS_BODY()
static AIMODULE_API const float SuspendNextUpdate;
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "AI Perception", config)
EAISenseNotifyType NotifyType;
/** whether this sense is interested in getting notified about new Pawns being spawned
* this can be used for example for automated sense sources registration */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "AI Perception", config)
uint32 bWantsNewPawnNotification : 1;
/** If true all newly spawned pawns will get auto registered as source for this sense. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "AI Perception", config)
uint32 bAutoRegisterAllPawnsAsSources : 1;
/** this sense has some internal logic that requires it to be notified when
* a listener wants to forget an actor*/
uint32 bNeedsForgettingNotification : 1;
private:
UPROPERTY()
TObjectPtr<UAIPerceptionSystem> PerceptionSystemInstance;
/** then this count reaches 0 sense will be updated */
float TimeUntilNextUpdate;
FAISenseID SenseID;
protected:
/** Called when a new FPerceptionListener registers with AIPerceptionSystem */
FOnPerceptionListenerUpdateDelegate OnNewListenerDelegate;
/** Called when a registered FPerceptionListener changes */
FOnPerceptionListenerUpdateDelegate OnListenerUpdateDelegate;
/** Called when a FPerceptionListener is removed from AIPerceptionSystem */
FOnPerceptionListenerUpdateDelegate OnListenerRemovedDelegate;
public:
AIMODULE_API virtual UWorld* GetWorld() const override;
/** use with caution! Needs to be called before any senses get instantiated or listeners registered. DOES NOT update any perceptions system instances */
static AIMODULE_API void HardcodeSenseID(TSubclassOf<UAISense> SenseClass, FAISenseID HardcodedID);
static FAISenseID GetSenseID(const TSubclassOf<UAISense> SenseClass) { return SenseClass ? ((const UAISense*)SenseClass->GetDefaultObject())->SenseID : FAISenseID::InvalidID(); }
template<typename TSense>
static FAISenseID GetSenseID()
{
return GetDefault<TSense>()->GetSenseID();
}
inline FAISenseID GetSenseID() const { return SenseID; }
inline bool WantsUpdateOnlyOnPerceptionValueChange() const { return (NotifyType == EAISenseNotifyType::OnPerceptionChange); }
AIMODULE_API virtual void PostInitProperties() override;
/**
* @return should this sense be ticked now
*/
bool ProgressTime(float DeltaSeconds)
{
TimeUntilNextUpdate -= DeltaSeconds;
return TimeUntilNextUpdate <= 0.f;
}
void Tick()
{
if (TimeUntilNextUpdate <= 0.f)
{
TimeUntilNextUpdate = Update();
}
}
//virtual void RegisterSources(TArray<AActor&> SourceActors) {}
virtual void RegisterSource(AActor& SourceActors){}
virtual void UnregisterSource(AActor& SourceActors){}
AIMODULE_API virtual void RegisterWrappedEvent(UAISenseEvent& PerceptionEvent);
AIMODULE_API virtual FAISenseID UpdateSenseID();
bool NeedsNotificationOnForgetting() const { return bNeedsForgettingNotification; }
virtual void OnListenerForgetsActor(const FPerceptionListener& Listener, AActor& ActorToForget) {}
virtual void OnListenerForgetsAll(const FPerceptionListener& Listener) {}
inline void OnNewListener(const FPerceptionListener& NewListener) { OnNewListenerDelegate.ExecuteIfBound(NewListener); }
inline void OnListenerUpdate(const FPerceptionListener& UpdatedListener) { OnListenerUpdateDelegate.ExecuteIfBound(UpdatedListener); }
inline void OnListenerRemoved(const FPerceptionListener& RemovedListener) { OnListenerRemovedDelegate.ExecuteIfBound(RemovedListener); }
virtual void OnListenerConfigUpdated(const FPerceptionListener& UpdatedListener) { OnListenerUpdate(UpdatedListener); }
bool WantsNewPawnNotification() const { return bWantsNewPawnNotification; }
bool ShouldAutoRegisterAllPawnsAsSources() const { return bAutoRegisterAllPawnsAsSources; }
#if WITH_GAMEPLAY_DEBUGGER_MENU
AIMODULE_API virtual void DescribeSelfToGameplayDebugger(const UAIPerceptionSystem& PerceptionSystem, FGameplayDebuggerCategory& DebuggerCategory) const;
#endif // WITH_GAMEPLAY_DEBUGGER_MENU
protected:
friend UAIPerceptionSystem;
/** gets called when perception system gets notified about new spawned pawn.
* @Note: do not call super implementation. It's used to detect when subclasses don't override it */
AIMODULE_API virtual void OnNewPawn(APawn& NewPawn);
/** @return time until next update */
virtual float Update() { return FLT_MAX; }
/** will result in updating as soon as possible */
inline void RequestImmediateUpdate() { TimeUntilNextUpdate = 0.f; }
/** will result in updating in specified number of seconds */
inline void RequestUpdateInSeconds(float UpdateInSeconds) { TimeUntilNextUpdate = UpdateInSeconds; }
inline UAIPerceptionSystem* GetPerceptionSystem() { return PerceptionSystemInstance; }
AIMODULE_API void SetSenseID(FAISenseID Index);
/** returning pointer rather then a reference to prevent users from
* accidentally creating copies by creating non-reference local vars */
AIMODULE_API AIPerception::FListenerMap* GetListeners();
/** To be called only for BP-generated classes */
AIMODULE_API void ForceSenseID(FAISenseID SenseID);
};