Quest Manager

Table of Contents

  1. Overview
  2. UPulseQuestManager
    1. Adding the component
    2. Auto Avatar Actor
    3. Blueprint delegates
  3. APulseSharedQuestHost
    1. Placing in the world
    2. Managing players
    3. Blueprint delegates (mirroring component delegates)
  4. Manager Parameters
    1. FPulseQuestManagerParams (used by UPulseQuestManager)
    2. FPulseSharedQuestManagerParams (used by APulseSharedQuestHost)
  5. Manager Interface API
    1. Quest lifecycle
    2. Start-quest failure reasons
    3. Objective lifecycle
    4. Reset
    5. Native event hooks
  6. Data Validation
  7. Utility Helpers

Overview

The Quest Manager is the central runtime object that tracks active quests and objectives, processes the event queue, drives quest state trees, and handles replication.

There are two concrete implementations:

Class Base Use case
UPulseQuestManager UGameplayTasksComponent Player-owned quests; owner-only replication
APulseSharedQuestHost AInfo Party/group quests shared across multiple players

Both implement IPulseQuestManagerInterface.


UPulseQuestManager

Adding the component

Attach UPulseQuestManager to any Actor – typically APlayerController or APlayerState.

UPROPERTY(VisibleAnywhere)
UPulseQuestManager* QuestManager;

Auto Avatar Actor

UPROPERTY(EditAnywhere, Category = "Pulse|Quest")
bool bAutoManageAvatarActor = true;

When true, the manager:

  • On APlayerController owner: listens to OnPossessedPawnChanged and updates the avatar.
  • On APlayerState owner: listens to OnPawnSet and updates the avatar.

The avatar actor is used by UGameplayTask and UPulseObjectiveTask instances.

Blueprint delegates

Delegate Signature Fired when
QuestStarted (UPulseQuestManager*, UPulseQuestData*) A quest becomes active
QuestFinished (UPulseQuestManager*, UPulseQuestData*) A quest stops
ObjectiveStarted (UPulseQuestManager*, UPulseQuestObjective*) An objective starts
ObjectiveFinished (UPulseQuestManager*, UPulseQuestObjective*) An objective stops
QuestManagerSaved (UPulseQuestManager*, bool) Save operation completes
QuestManagerLoaded (UPulseQuestManager*, bool) Load operation completes

APulseSharedQuestHost

Placing in the world

Spawn or place in the level. Configure ManagerParams (type FPulseSharedQuestManagerParams).

Managing players

// Add a player (Authority only)
bool AddPlayer(TScriptInterface<IPulseSharedQuestPlayerInterface> NewPlayer);

// Remove a player (Authority only)
bool RemovePlayer(TScriptInterface<IPulseSharedQuestPlayerInterface> PlayerToRemove);

// Queries
bool HasPlayer(TScriptInterface<IPulseSharedQuestPlayerInterface> Player) const;
bool HasPlayerState(const APlayerState* PlayerState) const;
void GetAllPlayers(TArray<FPulseSharedQuestPlayer>& OutPlayers) const;
void GetAllPlayerStates(TArray<APlayerState*>& OutPlayers) const;

Blueprint delegates (mirroring component delegates)

QuestStarted, QuestStopped, ObjectiveStarted, ObjectiveStopped, QuestManagerSaved, QuestManagerLoaded


Manager Parameters

FPulseQuestManagerParamsBase is the common base. Two concrete structs exist:

FPulseQuestManagerParams (used by UPulseQuestManager)

Property Type Description
QuestSet UPulseQuestSet* Pool of quests this manager may start
bAllowMultipleQuests bool Allow more than one active quest simultaneously
QuestManagerDataClass TSubclassOf<UPulseQuestManagerData> Runtime data class
QuestManagerViewModelClass TSubclassOf<UMVVMPulseQuestManager> Optional MVVM class
QuestDirectorClass TSubclassOf<UPulseQuestDirector> Optional Director class

FPulseSharedQuestManagerParams (used by APulseSharedQuestHost)

Same as above but QuestManagerDataClass defaults to UPulseSharedQuestManagerData.


Manager Interface API

Quest lifecycle

// Start a quest. Returns false + OutReason tags if it cannot start.
bool StartQuest(const FPulseQuestAddParams& Quest, FGameplayTagContainer& OutReason);

// Stop a quest immediately.
bool StopQuest(const FGameplayTag Quest, EPulseQuestFinishResult Result = Stopped);

// Send a StateTree event directly to a running quest.
bool SendEventToQuest(const FGameplayTag Quest, const FStateTreeEvent& Event);

// Query
bool IsQuestActive(const FGameplayTag Quest) const;
UPulseQuestData* GetQuestData(const FGameplayTag Quest) const;
void GetActiveQuests(TArray<FGameplayTag>& Tags, TArray<UPulseQuestData*>& Data) const;
void GetActiveQuestTags(TArray<FGameplayTag>& Tags) const;
int32 GetNumActiveQuests() const;

Start-quest failure reasons

These GameplayTag values are placed in OutReason when StartQuest returns false:

Tag Meaning
Pulse.Quest.Failure.QuestNotFound Quest tag not found in the Quest Set
Pulse.Quest.Failure.InvalidQuest StateTree asset on the quest is invalid
Pulse.Quest.Failure.DuplicateQuest A quest with this tag is already active
Pulse.Quest.Failure.AlreadyActive Another quest is running and bAllowMultipleQuests = false

Objective lifecycle

// Start an objective explicitly (StateTree tasks usually handle this).
FPulseObjectiveHandle StartObjective(const FPulseQuestObjectiveAddParams& Params);

// Query
UPulseQuestObjective* GetObjective(const FPulseObjectiveHandle Handle) const;
void GetActiveObjectives(TArray<UPulseQuestObjective*>& Out) const;
void GetObjectivesForQuest(const FGameplayTag Quest, TArray<UPulseQuestObjective*>& Out) const;
bool IsObjectiveActive(const FGameplayTag Quest, TSubclassOf<UPulseQuestObjective> Class) const;
int32 GetNumActiveObjectives() const;

Reset

// Stops all active quests/objectives and clears all state.
// Broadcasts OnResetEvent() when complete.
void ResetQuestManager(const FSimpleQuestManagerDelegate& OnComplete = {});

Reset does not restart the Director. Restart it manually if needed.

Native event hooks

C++ code can subscribe via the event accessors on IPulseQuestManagerInterface:

Manager->OnQuestStartedEvent().AddUObject(this, &AMyClass::HandleQuestStarted);
Manager->OnQuestFinishedEvent().AddUObject(this, &AMyClass::HandleQuestFinished);
Manager->OnObjectiveStartedEvent().AddUObject(this, &AMyClass::HandleObjectiveStarted);
Manager->OnObjectiveFinishedEvent().AddUObject(this, &AMyClass::HandleObjectiveFinished);
Manager->OnResetEvent().AddUObject(this, &AMyClass::HandleReset);
Manager->OnSavedEvent().AddUObject(this, &AMyClass::HandleSaved);
Manager->OnLoadedEvent().AddUObject(this, &AMyClass::HandleLoaded);

Data Validation

UPulseQuestManager::IsDataValid (editor) checks:

  • QuestSet is assigned (warning if missing at non-CDO).
  • Owning actor implements IGameplayTaskOwnerInterface (required for objective Gameplay Tasks).

Utility Helpers

UPulseQuestUtils (Blueprint Function Library):

// Get the ViewModel for a manager interface
static UMVVMPulseQuestManager* GetQuestManagerViewModel(Manager);

// Check authority / local control
static bool IsLocalQuestManager(Manager);
static bool IsAuthorityQuestManager(Manager);

// Low-level serialization helpers (e.g. for custom save systems)
static bool SerializeObjectToBytes(UObject* Object, TArray<uint8>& OutBytes);
static bool DeserializeObjectFromBytes(UObject* Object, const TArray<uint8>& Bytes);

Pulse::Quest namespace helpers:

bool IsQuestManagerAuthority(const TScriptInterface<IPulseQuestManagerInterface>&);
bool IsQuestManagerLocallyControlled(const TScriptInterface<IPulseQuestManagerInterface>&);
IPulseQuestManagerInterface* GetQuestManagerInterface(UObject* Object);
TScriptInterface<IPulseQuestManagerInterface> GetQuestManagerInterfaceScript(UObject* Object);

Back to top

Copyright © 2026 LuQ Studios. Distributed under the MIT License.

This site uses Just the Docs, a documentation theme for Jekyll.