We use the terms CK, response, topic, branch, view, info and mod. CK is the Creation Kit, the tool used to modify Skyrim, and a mod is a modification to the game. Information about responses, topics, branches, views, and infos can be be found by searching their name on creationkit.com.
This is part 2 of a guide on making a basic quest. Part 1 can be found here. Part 3 can be found here.
This is part 2 of a guide on making a basic quest. Part 1 can be found here. Part 3 can be found here.
If you find any phrases colored any of the following colors, refer to this key to understand their purpose.
Red text denotes phrases or words of great import. Read sentences in this color carefully, and more than once.
Orange text signifies a section of text that applies only to certain readers/modders. Skim over this to see if it applies to you, and if it does, read it. Otherwise, you can skip it.
Purple/pink text is a sidenote, or a useful bit of information. Skip them if you want, but you may find useful information if you read them properly, especially if you're an advanced modder.
Now, let's continue from where we left off.
11) First, we want to set up conditions. Conditions are the things that dictate when this line of dialogue can be said. As long as the response meets the specified conditions, it is said. If it doesn't, it won't be said. We want to set up one thing before we make conditions. An alias.
"Aliases are names or tags assigned to actors, objects, and locations used by the quest. This allows various data elements (script, packages, dialogue) to be tagged to the alias rather than to a specific object in the world, allowing quests to specify their aliases at runtime instead of being predefined" -- Creationkit.com
So essentially it's a name for something in the world. There's much more to it than that, but for our purposes, that's all it is. So head over to the Quest Alias tab, and right click to create a new reference alias. (Right clicking and pressing New is generally how you make new anythings in the CK.) In the top left, there is an Alias Name: box. I'm going to put in Sam, but you can put in whatever you want. Don't begin it with Alias, since it ends up being redundant when you start to use properties. If the new alias window is too large for your screen, that's all right. It's a common problem. If this is the case, when you have to close it, select Alias Name and press Shift+TAB twice. Then press enter to exit the screen. Tick the Allow Disabled box in the upper right corner. (This allows the alias to be disabled, otherwise nothing would happen.)
Now we have to make the alias point to Sam. So click the circle next to Unique Actor (since he is a unique actor). Look through the list of references until you find him. If he's not there, go open his NPC record and make sure his Unique checkbox is ticked. Then press OK to exit the alias window.
Create another Reference Alias, and name it SamList. This time, make it a Quest Object, and then click the circle next to create reference to object (this is creating the object where we want it to, rather than pointing to a pre-existing object). Ignore the level, but where it says NONE, choose the list we made earlier. Choose Create In, and choose the Sam alias. This will create the list in Sam's inventory when the quest starts, which is what we want (so he can give it to us).
12) Go back to the Player Dialogue, and open up the info we made (it should be the only possible selection under the starting topic we made). Make a new condition, and find GetIsAliasRef under Condition Function. If you type in GetIsAli while the entry under Condition Function is blue, it should scroll right to it. It should automatically select the alias you made, since we only have one so far. If it doesn't, click on the box saying INVALID ALIAS and change it to the right alias. (Under parameters.) The value should automatically be set to == 1.000. If it isn't, then set it to 1. Press OK. Now, there should be a condition in the Conditions box. Good job! You've made your first condition. (If there isn't a condition there, try again.)
13) Make a new condition, and instead of GetIsAliasRef, search GetStage. Change the parameter to your quest (search the prefix you made, if you followed the naming conventions guide, which you should have) by searching it's editorID. Change the value to == 0. What does all this mean? Well, this response will only be available for an alias called Sam (so in our case, the actor Sam is the only one who can say it), and only when our quest is at stage 0. Wait... Where did the stages come from? We're about to find out. Always be sure that your response has a GetIsAliasRef or a GetIsID attached to it. Otherwise, recording dialogue, or even silence, will record it for every single actor in the game.
In the future, it's probably better to do the next step before Step 6. But then you would need to do the Papyrus Fragments after you created the Aliases. It's really a matter of preference.
14) Go over to the Quest Stages tab, and make a new quest stage. It should default to 0. That's good. Keep it that way. Don't touch the log entry section for stage 0. Then make a stage 5, again with no log entry. Then make stage 10, and create a new log entry under the Log Entry section. In the white box below that, type in something suitable, like this:
Today, I met a man named Sam. He wanted me to retrieve 3 items. He gave me a list to help me remember the items.
In the Papyrus Fragment next to that, type in the following:
Game.GetPlayer().AddItem(Alias_SamList.GetReference(), 1)
This is a basic form of scripting. It means that when this stage is reached (stage 10), all the things within the Papyrus Fragment will be executed. AddItem adds the item in parentheses, and Alias.SamList.GetReference() finds the actual reference of the alias, SamList (our list), and gives 1 of it to the player (Game.GetPlayer()). Be sure to keep all the parentheses! Without them, errors will pop up.
Now make one more stage, and give it a log entry that looks like this (the things in quotations):
100 - "I brought the items back to Sam. He rewarded me with the same items I had just given him. What a strange man..."
(You can make the reward whatever you want.) For the log entry, put in (replace the thing in the parentheses after AddItem with whatever your reward's editorID is):
Game.GetPlayer().AddItem(MountainFlower01Blue, 1)
Game.GetPlayer().AddItem(MudcrabChitin, 1)
Game.GetPlayer().AddItem(Firewood01, 1)
There will be a compilation error. Ignore it for now. It's because we haven't defined those properties, but we will soon.
15) Make two objectives (objectives are the goals that show up on the screen). Number them 10 and 20. Put in the following (without the numbers or the dashes):
10 - Get the items for Sam.
20 - Bring the items back to Sam.
Underneath this, in the Target Ref section, create a new target ref. Make it the alias, Sam. (Do this only for objective 20.)
16) Now it's time to do the scripting. Go over to the Scripts tab in your quest, and right click to Add a Script, or click the Add button (in the white box, which should have one script in it, with a super long nonsensical name). Choose [New Script] in the button that pops up, and name your script something like: YourQuestNameScript. In this case, mine would be TQSamQuestScript. Once it's been created, highlight it by clicking it once, and hit the Properties button to the right of it.
Make three properties: Item1, Item2, and Item3. (Click the Add Property button.) Make them the Type each of your items is. If you don't know what it is, look it up. Most of them are fairly easy to guess, and if you guess wrong, then the Edit Value list won't have it's name. For me, these are the fields I entered for each reward:
Name: Item1
Type: Ingredient
Documentation String: Mudcrab Chitin (I was saying what it was, for further reference)
Name: Item2
Type: MiscObject (it says MiscItem in the Object Window Filter, but it is of MiscObject type)
Documentation String: Firewood
Name: Item3
Type: Ingredient
Documentation String: Blue mountain flower
Then create one more property of type Quest. Name it "YourQuestName". Press Auto-Fill All after you've created those properties (hit OK to exit each one). The Quest one should fill, but the others won't. For the Item1, 2 and 3, you have to click Edit Value when they're highlighted to change them to the item they should point to. For example, I edited Item1's value to point to the ingredient MudcrabChitin. Close the Properties once you're done.
Create three properties for your other script, the one with the really long name. Name them the same thing as the things you put in for Stage 100. Then, mine was MountainFlower01Blue, Firewood01, and MudcrabChitin, so I would create three properties: Two ingredient ones, which I could auto-fill, because I used the same names as their EditorIDs (if you didn't, then edit the value accordingly) and one MiscObject, which I can auto-fill because I used the same EditorID as firewood has.
Now, open up your first script, the one called "YourQuestNameScript".
Either right click it and choose "Open in External Editor" (if you have Notepad++ or SublimeText), or right click your script and choose "Edit Source" if you don't have an external editor.
17) We're going to create a function in this script. I'm going to show you the script I made, and then I'll walk you through it so you can create your own. Mine is called TQSamQuestScript2 because I messed up the first one while I was playing around with it. Yours shouldn't have a number at the end.
Scriptname TQSamQuestScript2 extends Quest Conditional
Quest Property TQSamQuest Auto
Int Property CountTotaled Auto Conditional
Ingredient Property Item1 Auto
{Mudcrab Chitin}
MiscObject Property Item2 Auto
{Firewood}
Ingredient Property Item3 Auto
{Blue mountain flower}
Function SamQuestItemCount()
Float CurrentCountMC = Game.GetPlayer().GetItemCount(Item1)
Float CurrentCountFW = Game.GetPlayer().GetItemCount(Item2)
Float CurrentCountBF = Game.GetPlayer().GetItemCount(Item3)
If CurrentCountFW >= 3 && CurrentCountBF >= 3 && CurrentCountMC >= 3
TQSamQuest.SetObjectiveDisplayed(20,1)
TQSamQuest.SetObjectiveCompleted(10,1)
CountTotaled = 1
Else
TQSamQuest.SetObjectiveDisplayed(10,true,true)
CountTotaled = 0
EndIf
EndFunction
So let's go through this. First off, there is the scriptname, and the properties. I expect you to know what those are, because if you don't, you didn't follow the instructions of the tutorial. If that is the case, go to the top and read the scripting tutorials by Sjogga. There is a link to them. The scriptname is conditional so the property CountTotaled can be conditional. If you have a property that is Conditional within a script, the Scriptname must be flagged Conditional as well. I'm not sure why, but that's the way it is.
Then there's the function. This is a function that is not part of the default game, so we had to define it ourselves. It starts with the name of the Function. It doesn't have any parameters like some functions, because they aren't necessary. This function wasn't created for multiple uses, just for this quest, so we can afford to have it specific to this quest. The name is TQSamQuestItemCount, which lists the quest it is part of, as well as the purpose - counting items.
You can see that I manually declared several variables, of type float. Which means that it can count decimals, as well as things like 1 (though it converts it to 1.000). We used float just to catch any extra numbers. There's no reason there would be 1.278 of a mudcrab chitin in our inventory, but the CK is strange sometimes, so it's probably best to use Float here. In case you were wondering, the two letters at the end of each variable stands for MudcrabChitin, Firewood and Blueflower. I made the variables separately count how many of each item is in your inventory. Ignore the "Conditional" flag for now. Then, below, we made the actual function of the Function.
It states that if, and only if, all three variables I declared are above 3 (so if you have 1 or more of each item), it shows the objective we made saying "Bring the items back to Sam", and completes the one saying "Get the items for Sam". Else (otherwise), show the "Get the items for Sam", and don't display "Bring the items back to Sam". Please note that 1 is the same as true, and 0 is the same as false. Since integers can be typecast as booleans (true and false) easily, this works without a hitch.
I created the property CountTotaled for later use. Ignore the fact that it's conditional. Just know that having it set to 1, as I do when you have all three items, is a way I can check if we have three items later. Otherwise, I'd have to use globals, and those are a bit more advanced so I don't want to get in to them now. I set it to 0 when we don't have all the items.
And of course, I have to end the if statement, as well as the function. Feel free to copy and paste that script in, and then change it according to your quest. There is a better way to go about this entire objective/scripting process, so you could see things like "Get Mudcrab Chitin. (0/1)", but it requires globals, and I'm trying to keep this tutorial about basic quest-making. I may cover globals and formlists in a later post.
18) So now we've got our function set up. But we still need to have something that causes that function to happen. So highlight the other script (the name should have a lot of numbers in it). Mine is called: QF_TQSamQuest_02000D62, but yours is probably something different. Open it up (via Edit Source or Edit With External Editor). We're going to add a property, but we have to do it manually. So go to the very bottom of the script you just opened, all the way to the last line. Then press enter once or twice. Now, type in the following:
YourOtherScriptName Property AbbreviatedVersion Auto
By this, I mean type in the exact name of the script with the function. Mine is TQSamQuestScript2, in this case (since I had to redo the script). Property you leave the same, since you're declaring a property. "Abbreviated Version" is an abbreviated version of YourOtherScriptName (if your other script name is short, you can leave it as is). I might do TQSQS2, or TQSamQS (I recommend this one, since it's a bit easier to remember). Auto you leave the same, also. For example, my property declaration would look like this:
TQSamQuestScript2 Property TQSamQS Auto
19) So we've got that over with. Now, go back to the Quest Stages tab, and go to the Papyrus Fragment for Stage 10. Type in the following:
AbbreviatedVersion.YourFunctionName()
So, you type in the name of the property you just made, which is the text between Property and Auto. For me, this would be TQSamQS. And then, you add a period, with no spaces in between. The period signifies that the Function we're about to use comes from the property we created, which is the script we created. What we're doing is drawing from the script we created, to use the function. And then you write in the name of your function, followed by the parameters. Since we didn't have any parameters, we just put in two parentheses. My example would look like this:
TQSamQS.TQSamQuestItemCount()
Remember not to just copy and paste what I did. Use your property name, and your function name.
Congratulations! We finished the scripting section. But we're not done yet... See part 3 to finish the guide.