// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "GameFeatureStateChangeObserver.h" #include "GameplayTagContainer.h" #include "Subsystems/WorldSubsystem.h" #include "ConversationRegistry.generated.h" #define UE_API COMMONCONVERSATIONRUNTIME_API class UConversationNode; class UConversationRegistry; class UGameFeatureData; class UConversationDatabase; class UWorld; struct FStreamableHandle; // Container for safely replicating script struct references (constrained to a specified parent struct) USTRUCT() struct FNetSerializeScriptStructCache_ConvVersion { GENERATED_BODY() UE_API void InitForType(UScriptStruct* InScriptStruct); // Serializes reference to given script struct (must be in the cache) UE_API bool NetSerialize(FArchive& Ar, UScriptStruct*& Struct); UPROPERTY() TMap, int32> ScriptStructsToIndex; UPROPERTY() TArray> IndexToScriptStructs; }; /** * These handles are issued when someone requests a conversation entry point be streamed in. * As long as this handle remains active, we were continue to keep it keep those elements streamed * in, as well as if new game feature plugins activate, we will stream in additional assets * or let previous ones expire. */ struct FConversationsHandle : public TSharedFromThis { static UE_API TSharedPtr Create(const UConversationRegistry* InOwningRegistry, const TSharedPtr& InStreamableHandle, const TArray& InEntryTags); private: // Private token only allows members or friends to call MakeShared struct FPrivateToken { explicit FPrivateToken() = default; }; public: UE_API FConversationsHandle(FPrivateToken, UConversationRegistry* InOwningRegistry, const TSharedPtr& InStreamableHandle, const TArray& InEntryTags); private: void Initialize(); void HandleAvailableConversationsChanged(); private: TSharedPtr StreamableHandle; TArray ConversationEntryTags; TWeakObjectPtr OwningRegistryPtr; }; DECLARE_MULTICAST_DELEGATE(FAvailableConversationsChangedEvent); /** * A registry that can answer questions about all available dialogue assets */ UCLASS(MinimalAPI) class UConversationRegistry : public UWorldSubsystem, public IGameFeatureStateChangeObserver { GENERATED_BODY() public: UE_API UConversationRegistry(); static UE_API UConversationRegistry* GetFromWorld(const UWorld* World); /** UWorldSubsystem Begin */ UE_API virtual void Initialize(FSubsystemCollectionBase& Collection) override; UE_API virtual void Deinitialize() override; /** UWorldSubsystem End */ UE_API UConversationNode* GetRuntimeNodeFromGUID(const FGuid& NodeGUID, const UConversationDatabase* Graph = nullptr) const; UE_API UConversationNode* TryGetRuntimeNodeFromGUID(const FGuid& NodeGUID, const UConversationDatabase* Graph = nullptr) const; UE_API TArray GetEntryPointGUIDs(const FGameplayTag& EntryPoint) const; UE_API TArray GetOutputLinkGUIDs(const FGameplayTag& EntryPoint) const; UE_API TArray GetOutputLinkGUIDs(const FGuid& SourceGUID) const; UE_API TArray GetOutputLinkGUIDs(const TArray& SourceGUIDs) const; UE_API TArray GetOutputLinkGUIDs(const UConversationDatabase* Graph, const FGameplayTag& EntryPoint, const FString& EntryIdentifier) const; UE_API TArray GetOutputLinkGUIDs(const UConversationDatabase* Graph, const FGuid& SourceGUID) const; UE_API TSharedPtr LoadConversationsFor(const FGameplayTag& ConversationEntryTag) const; UE_API TSharedPtr LoadConversationsFor(const TArray& ConversationEntryTags) const; UE_API TArray GetPrimaryAssetIdsForEntryPoint(FGameplayTag EntryPoint) const; // If a conversation database links to other conversaton assets, the tags of those conversations can be obtained here UE_API TArray GetLinkedExitConversationEntryTags(const UConversationDatabase* ConversationDatabase) const; UPROPERTY(Transient) FNetSerializeScriptStructCache_ConvVersion ConversationChoiceDataStructCache; FAvailableConversationsChangedEvent AvailableConversationsChanged; private: UConversationDatabase* GetConversationFromNodeGUID(const FGuid& NodeGUID) const; void BuildDependenciesGraph(); void GetAllDependenciesForConversation(const FSoftObjectPath& Parent, TSet& OutConversationsToLoad) const; void GameFeatureStateModified(); UE_API virtual void OnGameFeatureActivated(const UGameFeatureData* GameFeatureData, const FString& PluginURL) override; UE_API virtual void OnGameFeatureDeactivating(const UGameFeatureData* GameFeatureData, FGameFeatureDeactivatingContext& Context, const FString& PluginURL) override; private: TMap> RuntimeDependencyGraph; TMap> EntryTagToConversations; TMap> EntryTagToEntryList; TMap NodeGuidToConversation; private: bool bDependenciesBuilt = false; }; #undef UE_API