A Simple Quest
This tutorial will show you how to make a simple quest in Neverwinter Nights. It is perhaps the easiest quest of all to imagine - PC meets NPC, NPC has lost item, PC fetches item, NPC is happy, and rewards PC. It should be trivial to do this in the NWN Toolset. But wait! It looks like it needs scripting! Yikes! I know no programming!! What can I do? Who can help? There's no documentation! PANIC!
Fear not - help is at hand!
The NWN Toolset has a set of Wizards that automate simple scripting tasks, so you don't need to know how to script to create dynamic NPC interactions, and create quests. To get you started, this tutorial aims to describe how you would set up a simple 'Go fetch!' quest using only the Wizards, and not writing a single line of code.
Important Note: tutorial has been reformatted from one I put up in the NWN Scripting Forum the week after NWN was published. It contains several opinions that are mine alone... don't blame the Lexicon. Feedback in the talk page, please.
Like any Tutorial, I have to assume some knowledge. I've tried to pitch it for everyone, but there are some concepts I can't get by without. For example, I assume that you know a little bit about scripting - you don't have to know how to script, but you should be at least familiar with:
- Variables - Learn what variables are. If you've never programmed a lick in your life, this is going to be a bit challenging. Review the elementary material on the NWN Lexicon, which is a great introduction to programming/scripting in general.
- Tags - Objects in NWN have tags. The tag name is case sensitive, and need not be unique. In this tutorial, yours should be.
- The NWN Toolset - You need to know how to paint areas and add NPCs and Items to your areas.
- The Conversation Editor - Most of what you do will be in the Conversation Editor, you should know how to add nodes and understand what "root", "parent", and "child" mean in this context.
If you're already daunted, don't be! Read on, and see if you follow what I'm talking about. Concepts that you're a little hazy on might be clearer the further you get into the tutorial.
You're going to construct a quest for an NPC, Plott deVice. He's lost his Doohickey of Destruction, and wants you to go fetch it for him. Before we start, create Plott and the Doohickey, and place Plott in an Area. Paint a Doohickey in the Area too, and set its Tag to itemPlottsDoohickey. We're also going to need a variable to keep track of our quest's state, so let's decide now that it is going to be an integer, iPlottQuest.
It may be a trivial quest, but we still need to do some planning. We need to know what the different stages of the quest are, and how we will represent them in our quest state variable. We'll decide ahead of time that iPlottQuest will have three potential values:
- 0 - The PC hasn't been given the quest (default).
- 100 - The PC has been given the quest, but hasn't completed it.
- 200 - The PC has finished the quest, and can't do it again.
Starting The Conversation
The core of the quest is the conversation the PC has with Plott deVice. Normally, you would plan the conversation tree in advance, and build all the dialogue nodes before adding scripts with the Wizards. We'll do it in two steps, however, for illustrative purposes. To get started, edit Plott's Properties, and press "Edit" next to the Conversation field on the "Basic" tab to open the Conversation Editor with a new Conversation file. Add these three nodes to the root:
Note that the lines of dialogue seem backwards because when faced with multiple choices for an NPC at the same conversation level, the engine will choose the first line of dialogue that either has no "Text Appears When..." script, or whose "Text Appears When..." script evaluates to TRUE. (If you have no idea what that last bit meant... don't worry, the Wizard will take care of it). What this means, in practice, is that your conversations will frequently start with the end of a quest, and work back towards the start.
To vary the text that appears when the NPC is spoken to, we need to set conditionals on the first two dialogue nodes. In other words, we need to describe the conditions that have to be true for the text to appear. The first node should only appear when the quest is complete, and that's when the iPlottQuest variable is equal to 200. Let's configure that with the wizard:
- Select the first node (Thank you again...).
- Click on the "Text Appears When..." tab in the bottom right of the Conversation Editor.
- Click on the Wizard Hat button to start the Script Wizard.
- Check the "Local Variable" box, and click "Next".
- Type the name of the local variable (iPlottQuest) in the top right box.
- Type the value that iPlottQuest must be (200) in the bottom left box.
- Click "Add". You should get a line of code appearing in the "Local Expressions" box, that says: GetLocalInt(GetPCSpeaker(), "iPlottQuest") == 200
- Click "Next", call the script "dlg_plott_01" and save it.
The wizard has generated a script so that the first line of dialogue will only show up when the PC has completed the quest. You don't need to edit this script, but when you want to learn more about scripting, a good place to start is reading the Wizard's scripts, and figuring out how they do what they do. To fix our conversation up for the intermediate quest state, repeat the process above with the Have you found... line, setting the value to 100 instead of 200.
Filling out the Quest
Now you need to flesh out the conversation to give the PC some paths of response. PC's got to be able to accept the quest, and say 'Yes' when he's got the item. Add lines of dialogue to the conversation so it looks like this the tree below. You can vary the text as much as you like, but for the time being, leave the tree structure exactly as shown.
It is time to trigger the quest - to change the PC's quest state from "Not started" to "Incomplete", or to put it another way, to set iPlottQuest to 100. We already know when to do this, because we've go the conversation right there. The line Yep. Be right back. is begging for the start of the quest (and a rewrite... but that's not my problem). So far, we've only tested for the value of iPlottQuest, now we're going to set it. Unsurprisingly, we'll do it in the 'Actions Taken' tab. Here's how:
- Select the Yep. Be right back. node.
- Click on the "Actions Taken" tab.
- Click on the Wizard Hat button to start the Script Wizard.
- Check the "Set Local Variables" box, and click "Next".
- Type the variable name in the top right box.
- In the bottom left box, fill in the value for our "Quest Started" state.
- Click "Add". You should get a line of code appearing in the "Local Expressions" box, that says: SetLocalInt(GetPCSpeaker(), "iPlottQuest") = 100
- Click "Next", call the script "dlg_plott_02" and save it.
So far, so good. We've just arranged it so the PC can start the quest, and we've already got the mechanics worked out for the different conversation paths, so let's complete the quest, and dole out the rewards. Everything's in place for the PC to come back after the quest has started, and get asked Have you found the Doohickey of Destruction?. We have to assume that the PC is fundamentally dishonest, and will try to get something for nothing, so when the PC chooses Yes, we should check that they really have got Plott's Doohickey. By now, you should have a pretty good idea how to check this with a wizard. It is just a variation on checking the iPlottQuest, only easier. Full instructions are hidden below, highlight the text with your mouse to reveal them.
- Select the "Thank you, thank you, thank you..." node.
- Click on the "Text Appears When..." tab in the bottom right of the Conversation Editor
- Click on the Wizard Hat button to start the Script Wizard.
- Check the "Item in Inventory" box, and click "Next".
- Type the Tag of the Doohickey of Destruction ("itemPlottsDoohickey") top box.
- Click "Add". The Tag should appear in the 'Currently required item tags' box.
- Click "Next", call the script "dlg_plott_03" and save it.
Finally, we get to mark the quest as complete for this PC, and dish out some rewards. Still on the Thank you, thank you line, use the "Actions Taken" tab's Script Wizard. You will need to check the "Give Rewards", "Take from Player", and "Set Local Variable", and each will give you it is own page in the Wizard. This should, by now, be familiar territory, so I'll leave it as an exercise for you to figure the rewards out. Just don't forget to set iPlottsQuest to the "Quest Finished" state. If you're still hopelessly lost, there's a step-by-step description hidden below.
That's right... if you're still with me, by now you have a miniature quest of your own, and - with luck - an understanding of how it to make your own. All that remains is for you to save your module, load it into single-player, and go chat to your NPC. Be sure to test every conversation path... good testing is the secret to good code!
This is an elementary "Go fetch!" quest, without a single line of script-writing necessary. You do need to understand a little bit about variables, and tags, and you need to be aware that the Conversation Editor and the Script Wizard is writing a bunch of little scripts behind the scenes (you'll see they've been added to your module already). But you don't need to write the scripts yourself. Which is cool.
Exercises for the reader!
Here are some variations, all achievable with the wizards, that you might like to try:
- You've given the PC money and experience... how about improving his reputation with the NPC's faction?
- Give the PC the chance to insult the NPC, and have that change the PC's reputation with the NPC's faction for the worse.
- Add a "[Keep the Doohickey] Nope... couldn't find it, honest!" line of dialogue to the "Have you found..." tree. Make it appear only when the PC has the Doohickey... and add some consequences to the theft.
- Make the NPC xenophobic: only start the quest if the PC is the same race.
- Add a Persuade option for PCs to try and get the quest from the xenophobic NPC.
- Make it so that the Persuade check doesn't appear for PCs with low Charisma.
- How would you make it a "Go kill!" quest? (Hint: Bandit scalp)
...and some that will need some scripting:
- Should Plott keep losing his Doohickey? After destruction, respawn it in a new location.
- Create a blueprint of the Doohickey, and spawn it to a random location when the quest starts.
- Set up a multiplayer Easter Egg hunt.
Some Conversation Editor Tips
- Returning to earlier nodes: To get a conversation to loop back to an earlier node, use linking. Copy the node you want to return to, and then right-click the node you want to come from, and select "Paste as link". (Note that you can't paste links from a speaker onto its own dialogue)
- To break long NPC descriptions up into multiple nodes, add a single child conversation node, and delete all of its text. Add a child to the empty node, and the empty node will change from "[END DIALOGUE]" to "[CONTINUE]" in the editor. The PC will then get the familiar "[CONTINUE]" option in the conversation.
I hope this is of use in getting you started on the path of NWN Toolset Wizardry, and Script Sourcery (man, I'm corny). If you find an error or typo, or want to publish this somewhere, please let me, Iskander, know through the Bioware Boards (http://nwn.bioware.com/forums/).
Assigning rewards... the secrets revealed!
Highlight this box with your mouse to reveal the hidden text.
- Highlight the 'Thank you, thank you, thank you...' node
- Go to the 'Actions Taken' tab
- Check 'Give Rewards', 'Take from Player', and 'Set Local Variable', and click 'Next'.
- In the 'Give what rewards?' screen... give rewards, and decide whether the party or just the PC gets the benefits. Click 'Next'.
- In the 'Take what?' screen, type 'iPlottsDoohickey' into the 'Take item (by Tag)' box, and leave 'Destroy' selected. Click 'Next'.
- Finally, we need to set our flag variable for the last time. Set 'iPlottsQuest' to 200, click 'Add', 'Next', save the script, and you're done.
author: Iskander Merriman, editor: Charles Feduke