Tutorials¶
Creating a Quest-Giving NPC¶
This tutorial walks you through building a complete quest-giving NPC -- from creating a dialogue tree with condition checks (quest state, item requirements) to triggering quest start and item rewards through dialogue actions.
What You Will Build¶
An NPC named "Elder Miraya" who:
- Greets the player and offers a quest to retrieve a stolen relic
- Checks if the player already has the quest or has completed it
- Requires the player to have the relic item before accepting it
- Starts the quest, gives a reward, and changes dialogue after completion
Prerequisites¶
- FWDialogueSystem installed and compiling (see Installation)
- Basic understanding of dialogue trees (see Quick Start)
- An NPC Blueprint with a Dialogue Component
Part 1 -- Designing the Conversation Flow¶
Before creating data assets, plan the conversation on paper:
[Node 0: Greeting - branches based on quest state]
|
+-- "What quest do you have?" (Condition: Quest NOT started)
| --> Node 1: Quest Offer
|
+-- "I found the relic." (Condition: Quest InProgress AND HasItem)
| --> Node 3: Turn In
|
+-- "I am still searching." (Condition: Quest InProgress AND NOT HasItem)
| --> Node 2: Reminder
|
+-- "Hello again, Elder." (Condition: Quest Completed)
| --> Node 4: Post-Quest
|
+-- "Farewell."
--> -1 (end)
[Node 1: Quest Offer]
+-- "I accept." (Action: StartQuest) --> Node 5: Accepted
+-- "Not right now." --> -1
[Node 2: Reminder]
+-- "I will keep looking." --> -1
[Node 3: Turn In]
+-- "Here it is." (Action: GiveItem to NPC, GiveCurrency reward) --> Node 6: Reward
+-- "Not yet, I want to hold onto it." --> -1
[Node 4: Post-Quest]
+-- "Farewell, Elder." --> -1
[Node 5: Accepted]
+-- "I will return with the relic." --> -1
[Node 6: Reward]
+-- "Thank you, Elder." --> -1
Part 2 -- Creating the Dialogue Tree Asset¶
- In the Content Browser, navigate to
Content/Data/Dialogues/ElderMiraya/. - Create a Data Asset of type
FWDialogueTree. - Name it
DA_Dialogue_ElderMiraya.
Now add each node:
Node 0 -- Greeting¶
| Field | Value |
|---|---|
| NodeId | 0 |
| SpeakerName | Elder Miraya |
| DialogueText | Ah, a visitor. These are troubled times. The ancient relic of our village has been stolen by bandits in the northern caves. |
| EntryActions | (none) |
Add five responses:
Response 0 -- Offer the quest (player has not started it)
| Field | Value |
|---|---|
| ResponseText | What can I do to help? |
| NextNodeId | 1 |
Add one condition:
| Condition | Class | Properties |
|---|---|---|
| [0] | FWDlgCondition_QuestState |
QuestId: QST_StolenRelic, RequiredState: NotStarted |
Response 1 -- Turn in (player has the relic)
| Field | Value |
|---|---|
| ResponseText | I recovered the relic from the caves. |
| NextNodeId | 3 |
Add two conditions (both must pass):
| Condition | Class | Properties |
|---|---|---|
| [0] | FWDlgCondition_QuestState |
QuestId: QST_StolenRelic, RequiredState: InProgress |
| [1] | FWDlgCondition_HasItem |
ItemId: ITEM_AncientRelic, RequiredCount: 1 |
Response 2 -- Still searching (quest active, no relic)
| Field | Value |
|---|---|
| ResponseText | I am still searching for the relic. |
| NextNodeId | 2 |
Add one condition:
| Condition | Class | Properties |
|---|---|---|
| [0] | FWDlgCondition_QuestState |
QuestId: QST_StolenRelic, RequiredState: InProgress |
Condition Evaluation Order
Response 1 and Response 2 both check for InProgress. Response 1 additionally checks for the item. Since both responses are always evaluated independently, they will correctly show the right option: Response 1 only appears when the player has the item, and Response 2 appears whenever the quest is in progress. If the player has the item, both responses will appear -- which is fine, as the player can choose either path.
If you want Response 2 to only appear when the player does NOT have the item, you would need a custom FWDlgCondition_NotHasItem condition (see Configuration for how to create custom conditions).
Response 3 -- Post-quest greeting
| Field | Value |
|---|---|
| ResponseText | Good to see you, Elder. How are things? |
| NextNodeId | 4 |
Add one condition:
| Condition | Class | Properties |
|---|---|---|
| [0] | FWDlgCondition_QuestState |
QuestId: QST_StolenRelic, RequiredState: Completed |
Response 4 -- Farewell (always available)
| Field | Value |
|---|---|
| ResponseText | Farewell. |
| NextNodeId | -1 |
No conditions. This response is always available as a way to exit the conversation.
Node 1 -- Quest Offer¶
| Field | Value |
|---|---|
| NodeId | 1 |
| SpeakerName | Elder Miraya |
| DialogueText | Travel to the northern caves and retrieve the relic from the bandits. Be careful -- they are dangerous folk. I will reward you handsomely for its return. |
Response 0 -- Accept
| Field | Value |
|---|---|
| ResponseText | I accept. I will bring back the relic. |
| NextNodeId | 5 |
Add one action:
| Action | Class | Properties |
|---|---|---|
| [0] | FWDlgAction_StartQuest |
QuestId: QST_StolenRelic |
Response 1 -- Decline
| Field | Value |
|---|---|
| ResponseText | I am not ready for that. Perhaps later. |
| NextNodeId | -1 |
Node 2 -- Reminder¶
| Field | Value |
|---|---|
| NodeId | 2 |
| SpeakerName | Elder Miraya |
| DialogueText | The caves lie to the north. Please hurry -- every day without the relic weakens our village's protection. |
Response 0:
| Field | Value |
|---|---|
| ResponseText | I will not rest until I find it. |
| NextNodeId | -1 |
Node 3 -- Turn In¶
| Field | Value |
|---|---|
| NodeId | 3 |
| SpeakerName | Elder Miraya |
| DialogueText | You found it! The relic... I can feel its power. You have saved our village. Please, accept this reward. |
Response 0 -- Complete the quest
| Field | Value |
|---|---|
| ResponseText | Thank you, Elder. It was a difficult journey. |
| NextNodeId | 6 |
Add two actions:
| Action | Class | Properties |
|---|---|---|
| [0] | FWDlgAction_GiveItem |
ItemId: ITEM_EldersBlessingAmulet, Quantity: 1 |
| [1] | FWDlgAction_GiveCurrency |
CurrencyType: Gold, Amount: 500 |
Quest Completion
The quest system handles marking the quest as completed when the turn-in conditions are met. The dialogue actions here handle the reward side. Your quest system and dialogue system work together but remain decoupled.
Node 4 -- Post-Quest¶
| Field | Value |
|---|---|
| NodeId | 4 |
| SpeakerName | Elder Miraya |
| DialogueText | The village thrives once more, thanks to you. You are always welcome here. |
Response 0:
| Field | Value |
|---|---|
| ResponseText | Take care, Elder. |
| NextNodeId | -1 |
Node 5 -- Quest Accepted¶
| Field | Value |
|---|---|
| NodeId | 5 |
| SpeakerName | Elder Miraya |
| DialogueText | May the spirits guide your path. Return to me when you have the relic. |
Response 0:
| Field | Value |
|---|---|
| ResponseText | I will return soon. |
| NextNodeId | -1 |
Node 6 -- Reward Given¶
| Field | Value |
|---|---|
| NodeId | 6 |
| SpeakerName | Elder Miraya |
| DialogueText | Here -- the Elder's Blessing Amulet and 500 gold. You have earned every coin. Our village is in your debt. |
Response 0:
| Field | Value |
|---|---|
| ResponseText | Farewell, Elder Miraya. |
| NextNodeId | -1 |
Part 3 -- Setting Up the NPC Blueprint¶
3.1 Create the NPC Actor¶
- Create a new Actor Blueprint:
BP_NPC_ElderMiraya. - Add a Skeletal Mesh Component with the Elder's mesh.
- Add a FW Dialogue Component.
- Add a Sphere Collision component for interaction range.
3.2 Implement the Interaction¶
In the Event Graph:
Event BeginPlay
|
+-- Sphere Collision > On Component Begin Overlap
|
+-- Cast to Player Character
|
+-- Store Player Reference
|
+-- Show "Talk to Elder Miraya" prompt
Sphere Collision > On Component End Overlap
|
+-- Hide Prompt
On Interact Input (while in range)
|
+-- Dialogue Component > Is Dialogue Active?
|
+-- Branch:
+-- False:
| Dialogue Component > Start Dialogue
| Tree: DA_Dialogue_ElderMiraya
| Interactor: Stored Player Reference
|
+-- True:
(do nothing -- already talking)
3.3 Bind UI Events¶
Event BeginPlay
|
+-- Dialogue Component > Bind Event to On Dialogue Started
| --> Show Dialogue Widget
|
+-- Dialogue Component > Bind Event to On Node Changed
| --> Update Dialogue Widget (speaker, text, responses)
|
+-- Dialogue Component > Bind Event to On Dialogue Ended
--> Hide Dialogue Widget
Part 4 -- Building the Dialogue UI Widget¶
Create WBP_DialoguePanel with this layout:
+--------------------------------------------+
| [Portrait] Elder Miraya |
+--------------------------------------------+
| |
| "Ah, a visitor. These are troubled |
| times..." |
| |
+--------------------------------------------+
| > What can I do to help? |
| > Farewell. |
+--------------------------------------------+
Key Implementation Details¶
Populating responses:
On Node Changed (NewNode)
|
+-- Set Speaker Text = NewNode.SpeakerName
+-- Set Body Text = NewNode.DialogueText
+-- Clear Response List
|
+-- Responses = Dialogue Component > Get Available Responses
|
+-- For Each Response (with Index):
+-- Create Response Button Widget
+-- Set Text = Response.ResponseText
+-- Bind On Clicked:
Dialogue Component > Select Response (Index)
Use GetAvailableResponses, Not Raw Responses
Always call GetAvailableResponses to get the filtered list. The raw Responses array from GetCurrentNode includes responses whose conditions have not passed. Using the raw array will show options the player should not see and will cause index mismatches with SelectResponse.
Part 5 -- Testing the Full Flow¶
Test each conversation path:
| Test Case | Initial State | Expected Behavior |
|---|---|---|
| First visit | Quest not started | Shows "What can I do to help?" and "Farewell" |
| Accept quest | After selecting accept | StartQuest action fires, sees acceptance dialogue |
| Return without relic | Quest in progress, no item | Shows "I am still searching" response |
| Return with relic | Quest in progress, has item | Shows "I recovered the relic" response |
| Turn in relic | Select turn-in response | GiveItem and GiveCurrency actions fire |
| Post-quest visit | Quest completed | Shows post-quest greeting |
Testing Conditions
Use console commands or cheat functions to grant items and change quest states during testing. This lets you quickly verify all dialogue branches without playing through the full game loop.
Summary¶
| Step | What You Built |
|---|---|
| Part 1 | Designed the conversation flow on paper |
| Part 2 | Created the dialogue tree data asset with 7 nodes, conditions, and actions |
| Part 3 | Set up the NPC Blueprint with interaction and event binding |
| Part 4 | Built the dialogue UI widget driven by component events |
| Part 5 | Tested all conversation branches |
Next Steps¶
- Add more NPCs with their own dialogue trees.
- Create custom conditions for game-specific checks (player level, faction reputation, time of day).
- Create custom actions for game-specific effects (play cinematic, teleport player, change weather).
- Chain multiple quests through the same NPC by using different dialogue trees per quest state.