Quests&Objectives

Build the tracker in your HUD.

Owning-client widgets must read replicated state first. Do not wait for the first event. Do not use bool returns on the client.

The plugin zip does not include a HUD. The sample project includes an example tracker, log, and vendor board.

Get the component

On the local player, get PlayerState, then FindComponentByClass<UQuestComponent>.

Do not use the bool on the owning client to update the HUD. On construct, fill from queries. When the log opens, refresh. Fail and abandon then appear.

void UMyTrackerWidget::NativeConstruct()
{
    Super::NativeConstruct();
    UQuestComponent* QC = GetOwningQuestComponent();
    ActiveQuests = QC->GetQuestsByStatus(EQuestStatus::Active);
    RebuildRows();
    QC->OnObjectiveProgress.AddDynamic(this, &UMyTrackerWidget::OnProgress);
}

Quest tracker

UQuestComponent* QC = PlayerState->FindComponentByClass<UQuestComponent>();
TArray<FQuestRuntimeState> Active = QC->GetQuestsByStatus(EQuestStatus::Active);
if (Active.Num() == 0)
{
    return;
}
const FQuestRuntimeState& State = Active[0];
UQuestDefinition* Def = GetGameInstance()
    ->GetSubsystem<UQuestSubsystem>()
    ->GetQuestById(State.QuestId);

Walk Def->Phases[State.CurrentPhaseIndex].Objectives.

Before you add a row, call UQuestComponent::ShouldDisplayObjective.

Bind the same delegates with AddDynamic. Then rebuild the widget.

Quest log

Call the same GetQuestsByStatus values. Build your Slate or UMG list from the returned array.

For a history of completions, use TimesCompleted on the runtime state.

Vendor / NPC board

TArray<FQuestRuntimeState> Offered = QC->GetQuestsByStatusForGiver(
    EQuestStatus::Available, GiverId);
TArray<UQuestDefinition*> Defs = Subsystem->GetQuestsByVendorId(VendorId);

Icons and sounds

Load UQuestDefinition::Icon, each objective Icon, and each reward Icon in your HUD.

When a quest completes, fails, or an objective completes, load the matching USoundCue from the definition. Then play it in your game.