Difference between revisions of "A beginner's guide, lesson 6 - Quest Dialogue"

imported>Qazaaq
(ready to be wikified)
 
Tag: Manual revert
 
(95 intermediate revisions by 15 users not shown)
Line 1: Line 1:
[url=http://www.elderscrolls.com/forums/index.php?showtopic=517001]Index Page[/url]
{{Featured}}
{{ABGContents}}


[b]TES IV: Oblivion Modding for Beginners
==Preamble==


B. Scripts, Quests and NPC’s
This is the Sixth in a proposed series of Tutorial Lessons aimed at teaching how to mod TES IV: Oblivion aimed at beginners. It will build up into a complete modding course. Don't worry, there are no exams (though, there is some homework). This version was written for use on the forum. The RTF version contains additional material that was left out due to formatting limitations.
Lesson Six: Quest Focus; Dialogue
[/b][b]


[b]Preamble[/b]
===Files===


This is the Sixth in a proposed series of Tutorial Lessons aimed at teaching how to mod TES IV: Oblivion aimed at beginners. It will build up into a Complete Modding Course. Don't worry there are no exams, though there is some homework. This version has been written for use on the forum. The RTF version contains additional material left out due to formatting limitations
I have uploaded some files in a .zip which will be used to accompany the next few tutorials.  


[b]Files[/b]
It contains:


I have uploaded some files in a zip which we will used to accompany the next few tutorials.  
'''A. BGModTutBase.esp:''' This contains a building, a farmhouse, and a dungeon that we will use as sets in lessons 6, 7 and 8. This file is referred to in the text as the BASE file.
It contains


[i]A. BGModTutBase.esp:  
'''B. BGModTutPlayTest.esp:''' This is the interim quest mod illustrating the stage you should have reached prior to polishing the mod. This is referred to in the text as the PLAYTEST file.
This contains a building, a farmhouse, and a dungeon that we will use as sets in lessons 6, 7 and 8. This file is referred to in the text as the BASE files


B BGModTutPlayTest.esp
'''C. BGModAnvilCheat.esp:''' This is a small optional cheat mod to give users 5000 Septims to allow them to follow this tutorial if they have not yet completed the quest. (See [[A_beginner's_guide,_lesson_4_-_Anatomy_of_a_quest,_part_1#Introduction|Introduction to Lesson 4]])
This is the interim quest mod illustrating the stage you should have reached prior to polishing the mod. This is referred to in the text as the PLAYTEST files


B. BGModAnvilCheat.esp:
'''D.''' An RTF document containing the text for the first 7 lessons (as requested).
This is a small optional cheat mod to give users 5000 septims to allow them to follow this tutorial if they have not completed the quest. (See Introduction to lesson 4)


C. A RTF document containing the text for the first 7 lessons (as requested).
[http://www.tesnexus.com/downloads/file.php?id=4865 Download the mod files]
[/i]


[url=http://www.tessource.net/files/cache/4865.html]Mod Files are Here[/url]


or URL
===Using this Tutorial===


www.tessource.net/files/cache/4865.html
I suggest that you modify the CS configuration file to allow you to open multiple copies at the same time. (See [[A_beginner's_guide,_lesson_3_-_The_external_world#Introduction|Introduction to Lesson 3]])
Open one CS window for the '''PLAYTEST''' version. You can use this to look at the expected results of the mod. We will not edit this mod.
Open a second window for the '''BASE''' version (unless you want to make your own buildings - then just make a new file). This window is for your working file.


[b]Using this Tutorial[/b]
==Introduction==


Can I suggest you operate in the following way to make the most of these tutorials?
Well, we come to it at last. It is time for us to begin to create our own quest, to design our own [[NPC]]s, and to write our own [[Named Scripts|scripts]].  
If you have not already altered the CS ini. file to allow you to open two copies at the same time do so now. (See lesson Three)
Of course it's ridiculous to suggest that these tutorials alone will teach you everything you need to know. However, I hope by the time you finish the next few lessons you will be more comfortable with the key skills needed to create your own great works. The example [[quest]] that I am using is not intended as an example of ‘Good Practice'. I have designed it to illustrate techniques, not good quest writing. The actual details of this quest are fairly unimportant. What matters are the techniques we are using.
Open one version of the CS with the [b]PLAYTEST [/b]version. We can use this to look at the expected results of the mod. We will not edit this mod. (Unless you want to of course)
Open a second version with the[b]BASE[/b] version loaded. This is your working files. If you don’t want to use my version, and have your own buildings and dungeons then load this version here.


[b]Introduction[/b]
The next three lessons will work to develop a quality version of a quest. While we will do this exercise, I have designed the quest to allow us to focus on key skills as we go on. This lesson deals with the creation of dialogue.  In lesson seven we will really turn our focus to scripting, although you will begin scripting in this lesson. The eighth lesson will complete the quest by focusing on AI and Audio.


Well, we come to it at last. It is time for us to begin to create our own quest, to design our own NPC’s, and to write our own scripts.
I assume that you have completed lessons one to three, and that that you have at least read through the [[A_beginner's_guide_-_Appendix_1|appendix section on the Quest Interface]].
Of course it’s ridiculous to suggest that these tutorials alone will teach you everything you need to know. However, I hope by the time you finish the next few lessons you will be more comfortable with the key skills needed to create your own great works. The exemplar quest that I am using is not intended as an example of ‘Good Practice’. I have designed it. to illustrate techniques, not good quest writing. The actual details of this quest are fairly unimportant. What matters are the techniques we are using?


The next three lessons will work to develop a release quality version of a quest. While we will do this as whole exercise, I have designed the quest to allow us to focus on key skills as we go on. This lesson deals with the creation of dialogue.  In lesson seven we will turn our focus to scripting, although you will begin scripting in this lesson. The eighth lesson will complete the quest by focusing on AI and Audio.
==Our Plot==


I have assumed, that you have completed lessons one to three, and that that you have at least read through the appendix section on the Quest Interface.
Quests are the bedrock of Oblivion's game mechanics. We established a basic technique to progress quests in the quest walkthrough


[b]Our Plot[/b]
*Action
 
*Set Stage
Quests are the bedrock of Oblivion’s game mechanics. We established in the quest walkthrough a basic technique to progress quests
*Set Conditions for next action.
 
*Hiatus
[i]Action
Set Stage
Set Conditions for next action.
Hiatus[/i]


We will try to use this wherever possible.
We will try to use this wherever possible.
   
   
We need to tell a story. I have read lots forum posts that begin with the phrase ‘I have this great idea for a quest’. They then go on to explain an elaborate plot which is impossible to implement, especially for a beginner. Keep it simple to start with.  
We need to tell a story. I have read lots forum posts that begin with the phrase ‘I have this great idea for a quest'. They then go on to explain an elaborate plot which is impossible to implement, especially for a beginner. Keep it simple to start with.  
The designers of the game have used simple plot devices again and again in their quests. These are
The designers of the game have used simple plot devices again and again in their quests. These are


Go find an item and bring it back.
*Go find an item and bring it back.
Go find a person and bring them back
*Go find a person and bring them back
Go find a person and kill them
*Go find a person and kill them


and the really complex
and the really complex


Go find a person take him with you, then you kill another person, who has an item which you should then bring back.
*Go find a person take him with you, then you kill another person, who has an item which you should then bring back.


All of these ideas are clichéd and obvious. But one of the reasons a plot become clichéd is because they work.  
All of these ideas are clichéd and obvious. But one of the reasons a plot become clichéd is because they work.  


So here is my clichéd ‘recover the item’ plot line.
So here is my clichéd 'recover the item' plot line.


[b]The player discovers that their uncle has sadly passed away. The terrible news is softened by the fact that the Uncle has left the player some property in his will. Unfortunately the courier bringing the details of where the property, is along with the key and deed has disappeared. The player has to investigate the disappearance. This will lead him to an encounter with a gang of thieves who the player will have to defeat to recover his house key and deed. [/b]
:''The player discovers that their uncle has sadly passed away. The terrible news is softened by the fact that the Uncle has left the player some property in his will. Unfortunately the courier bringing the details of where the property, is along with the key and deed has disappeared. The player has to investigate the disappearance. This will lead him to an encounter with a gang of thieves who the player will have to defeat to recover his house key and deed.


This is not the greatest plot ever, but it should allow us to cover all the main points. I have chosen to make this quest as close to the Bethusda ‘Oblivion’ model as I can.  
This is not the greatest plot ever, but it should allow us to cover all the main points. I have chosen to make this quest as close to the Bethesda's 'Oblivion' model as I can.  


This means setting up lots of ‘hand holding’ journal entries and message boxes. I personally would leave a lot of these out in a ‘real’ mod, but that is a personal choice. For every player who wants more freedom of choice and a more obscure progress there are others who want as much help as possible.  
This means setting up lots of 'hand holding' journal entries and message boxes. I personally would leave a lot of these out in a 'real' mod, but that is a personal choice. For every player who wants more freedom of choice and a more obscure progress there are others who want as much help as possible.  


This is at the extreme end of the hand holding scale. Please feel free to add or change any bit of the quest you feel is too helpful to the PC. Remember this is a way to write a quest, but it is NOT the ONLY way. This tutorial illustrates techniques. I do not intend it to be a click by click guide. In fact I will as the tutorial progresses, be feeding you less and less information, and asking you to ‘fill in the blanks’
This is at the extreme end of the hand holding scale. Please feel free to add or change any bit of the quest you feel is too helpful to the PC. Remember, this is a way to write a quest, but it is NOT the ONLY way. This tutorial illustrates techniques. I do not intend it to be a click by click guide. In fact I will as the tutorial progresses, be feeding you less and less information, and asking you to ‘fill in the blanks'
[b]
Pre-Production
[/b]
Let’s get started then. You can use the base files I have provided or you can create your own. Don’t forget to make the file active in the CS


You will need the following props or sets
==Pre-Production==


A house, which will be our quest reward. Of course you can change the plot detail to make this reward anything you please.
Let's get started then. You can use the base files I have provided or you can create your own. Don't forget to make the file active in the CS


A cave system, to act as the HQ for our baddies. Again I choose a cave system. You could just as easily make it a house, a castle or even an open air camp.
You will need the following props or sets


A cottage, to house the dead courier in. This could just as easily be a camp, a house or a room in an inn.
*A house, which will be our quest reward. Of course you can change the plot detail to make this reward anything you please.
*A cave system, to act as the HQ for our baddies. Again I choose a cave system. You could just as easily make it a house, a castle or even an open air camp.
*A cottage, to house the dead courier in. This could just as easily be a camp, a house or a room in an inn.


If you are using the base files these have already been added. If you are designing your own you can add these props now, or as and when you need them.
If you are using the base files these have already been added. If you are designing your own you can add these props now, or as and when you need them.
Line 100: Line 86:
The quest is set in 6 locations
The quest is set in 6 locations


1. In and around the Imperial City
#In and around the Imperial City
2. In and around Chorrol
#In and around Chorrol
3. The Courier Cottage close to Chorrol
#The Courier Cottage close to Chorrol
4. The Village of Aleswell
#The Village of Aleswell
5. The Hideout of the Baddies
#The Hideout of the Baddies
6. Our Reward Home.
#Our Reward Home.


We will also need 5 named NPC’s plus a few generic goons for our hero to fight.
We will also need 5 named NPCs plus a few generic goons for our hero to fight.


[b]
==Imperial City, Phase One==
Imperial City, Phase One.[/b]


For convenience we will split the quest into a series of phases. These are artificial divisions, and are not a technical requirement
For convenience we will split the quest into a series of phases. These are artificial divisions, and are not a technical requirement


Phase Objectives: - [i]In this phase we want to set up a dialogue which introduces the quest to the player character. We want the PC to visit an NPC called Vilanus Villa who will in turn give some exposition, before directing the PC to visit Chorrol. [/i]
;Phase Objectives: - In this phase we want to set up a dialogue which introduces the quest to the player character. We want the PC to visit an NPC called Vilanus Villa who will in turn give some exposition, before directing the PC to visit Chorrol.


If we breakdown the first section of the story to see what we need to do.
If we breakdown the first section of the story to see what we need to do.


Create an NPC ‘Lawyer’ who I have chosen to call Vilanus Villa.  
*Create an NPC ‘Lawyer' who I have chosen to call Vilanus Villa.  
Add a Topic/Responses that will direct the player to Villa
*Add a Topic/Responses that will direct the player to Villa
Add Topic/ Responses for Villa that will direct the player to Chorrol.
*Add Topic/ Responses for Villa that will direct the player to Chorrol.
Add a ‘letter’ prop to help sell the introduction.
*Add a ‘letter' prop to help sell the introduction.


We can add these in an order, as long as we link them correctly. There is no one way to do things.
We can add these in any order, as long as we link them correctly. There is no one way to do things.


However, one thing to consider is that any reference objects we wish to use in condition statements or scripts must exist before we can use them. For this reason it is probably best to start by adding out NPC into the game, because we will be using him as reference in some conditions.
However, one thing to consider is that any reference objects we wish to use in condition statements or scripts must exist before we can use them. For this reason it is probably best to start by adding our NPC to the game, because we will be using him as reference in some conditions.


[b]
==Adding an NPC==
Adding an NPC[/b]


You can of course create an NPC from scratch. If you right click in the Actor section of the object menu and select NEW a new NPC interface pops up. However, I cannot see any good reason to do this, and since you will have to add every aspect of your NEW NPC, including animations, there are many good reasons not to do this.  
You can, of course, create an NPC from scratch. If you right click in the Actor section of the object menu and select NEW a new NPC interface pops up. However, you will have to edit every aspect of your new NPC, including [[animation]]s, so there are many good reasons not to do this.  


It is far easier to edit an existing NPC. We want Vilanus to be an Imperial, so let’s select an existing NPC who is an imperial. We don’t actually have to choose an Imperial, but it saves us a job. Avoid NPC’s with scripts attached. Again you can do so but you will need to remove the script which is an extra job. I usually look for NPC’s who have either a 1 or better still a 0 in the user column. This means they are hardly used in the game. Let’s chose the actor called TestORMale as our base.  
It is far easier to edit an existing NPC. We want Vilanus to be an Imperial, so let's select an existing NPC who is an Imperial. We don't actually have to choose an Imperial, but it saves us a job. Avoid NPCs with scripts attached. Again, you can do so but you will need to remove the script, which is an extra job. I usually look for NPCs who have either a 1 or a 0, preferably a 0, in the user column. This means they are hardly ever used in the game. Let's choose the actor called ''TestORMale'' as our base.  


We will place our NPC in the Foyer of the Imperial Hotel in the Talos District. Again this is an arbitrary choice, based on the fact that Taverns, Inns, and hotels contain public spaces which are ideal for casual contacts. We could of course if we wished to use this NPC again build him a house or office to work from.  
We will place our NPC in the Foyer of the Imperial Hotel in the Talos District (''ICTalosPlazaTheTiberSeptimHotel'' in the ''Interiors'' world space). Again this is an arbitrary choice, based on the fact that Taverns, Inns, and hotels contain public spaces which are ideal for casual contacts. If we wished to use this NPC again, we could build him a house or office to work from.  


Drag and Drop the base NPC into Render window. F key him to get him in position.
Drag and Drop the base NPC into [[Render Window]]. F key him to get him in position.


Now double click on him to open up his details.  
Now double click on him to open up the details for this NPC [[reference]]. Then click "Edit Base" to edit the NPC itself.


Let's briefly look at the properties on the far left of this interface.
Let's briefly look at the properties on the far left of this interface.


ID -Editor ID for this NPC. Must be unique.  
{| class="wikitable" border="1" cellpadding="5"
 
!colspan=2| '''NPC Properties'''
Name  
|-
-NPC name as it will appear in-game
| ''ID'' || Editor ID for this NPC. Must be unique.
 
|-
Script  
| ''Name'' || NPC name as it will appear in-game.
-Scripts can be attached to NPCs here.
|-
| ''Script'' || Scripts can be attached to NPCs here.
Class  
|-
-Can be defined using the class interface from the menu bar.
| ''Class'' || Can be defined using the [[class]] interface from the menu bar.
 
|-
Summonable  
| ''Summonable'' || Mainly used for creatures and defines them as able to be summoned.
-Mainly used for creatures and defines them as able to be summoned.
|-
 
| ''Offset/PC Level Offset'' || Used to set NPC level. Either a fixed value within a defined range, or offset against PC level.
Offset/PC Level Offset  
|-
-Used to set NPC level. Either a fixed value, within a defined range or offset against PC level.
| ''Calc Min/Max'' || These check boxes determine minimum and maximum levels for the NPC.
 
|-
Calc Min/Max  
| ''Race'' || Choose the NPC's [[race]] from the drop-down menu
These check boxes determine minimum and maximum levels for the NPC.  
|-
 
| ''Female'' || Used to toggle gender.
Race  
|-
Straightforward - choose a race from the drop-down menu
| ''Combat Style'' || [[Combat Style]]s influence NPC choices during a fight. (see [[A_beginner's_guide,_lesson_8_-_Audio_and_AI|lesson eight]])
 
|-
Female  
| ''Death Item'' || Used for special loot items that we don't want to show up until after an NPC is dead.
Used to toggle gender
|-
 
| ''Essential'' || Essential NPCs cannot be killed and are only knocked unconscious.
combat Style  
|-
combat styles influence NPC choices during a fight. (see lesson eight)
| ''Respawn'' || This NPC will respawn when the cell reloads if you check this.
 
|}
Death Item  
Used for special loot items that we don't want to show up until after an NPC is dead.  
 
Essential  
-Essential NPC’s cannot be killed and are only knocked unconscious.  
 
Respawn  
-This NPC will respawn when the cell reloads if you check this


Selecting  "PC Level Offset" will lock or unlock the details in the stats tab.
Selecting  "PC Level Offset" will lock or unlock the details in the stats tab.


First alter the NPC’s ID to [b]BGVilanusVilla[/b] and the name to [b]Vilanus Villa[/b].  
First alter the NPC's ID to ''BGVilanusVilla'' and the name to ''Vilanus Villa''.  


We tend to prefix all items added by a mod with a suitable prefix, like BG or BGM. This help avoid any conflicts, in the unlikely event that another mod adds a character called Vilanus Villa.
We tend to prefix all items added by a mod with a suitable prefix, like ''BG'' or ''BGM''. This help avoid any conflicts, in the unlikely event that another mod adds a character called Vilanus Villa.


This character is classed as a Barbarian. The actual class of a NPC will only affect auto generated statistics and has little bearing on the interaction between PC and NPC. However, it is an easy job to change this, using the drop down list under class.
This NPC's class is Barbarian. The actual class of a NPC will only affect auto-generated statistics, and has little bearing on the interaction between PC and NPC. However, it is easy to change this setting using the drop down list under class.


We will look at levels later in these tutorial for now leave it at level 8. The levelness of a character is only really relevant in action sequences.  
We will look at levels later on in this tutorial; for now leave it at level 8. The level of a character is only relevant in combat.  


For now we want to get rid of all existing AI packages. We are deleting the whole AI because it makes initial play testing much easier. Without these AI’s the guy will stay put and we want have to walk across half of Tamriel to find him when we test the mod.
For now we want to get rid of all existing AI packages. We are deleting the AI because it makes initial play testing much easier. Without any AI the guy will stay put. We don't want to have to walk halfway across Tamriel to find him when we test the mod!


Open up the AI section by clicking on the AI button.  
Open up the AI section by clicking on the AI button.  


Delete all the AI packages using right click delete. (This actually removes from this PC rather than delete the whole AI package from the CS).
Delete all the AI packages using right-click + delete. (This only removes them from the NPC's list, it doesn't delete the actual package)


Now select and check the ESSENTIAL flag. We want to keep Vilanus alive for now.
Now select and check the ESSENTIAL flag. We want to keep Vilanus alive for now.


We can also alter the inventory if we wish. Again by careful pre-selection we can save ourselves a job. Remember to scroll across the information in the object window to select suitable characters that match your requirements as closely as possible, to reduce how much work you need to do.
We can also alter the inventory if we wish. Again, by careful pre-selection we can save ourselves a job. Remember to scroll across the information in the object window to select suitable characters that match your requirements as closely as possible, to reduce the amount of work you need to do.


We want Vilanus to be a rich merchant so he should have some decent clothes, and TestORmale fit’s the bill. We should also remove any weapons and armour from him as he is supposed to be a lawyer. (Note the Hammer may show up in the render window until you reload the window, but will not show up in the game.  
We want Vilanus to be a rich merchant, so he should have some decent clothes. TestORmale fits the bill. We should also remove any weapons and armor from him, as he is supposed to be a lawyer. (Note that the Hammer may show up in the render window until you reload the window, but will not show up in the game.)


We can leave his faction details alone for now.
We can leave his faction details alone for now.


Finally you can play around with the face to get the look you want. For now don’t spend too long. Use the Auto generator to get a rough look. You can tidy this up in the polishing phase.
Finally you can play around with the face to get the look you want. For now, don't spend too much time on it. You can use the auto-generator to get a rough look. You can tidy this up later in the polishing phase.
 
Exit and create a new form by clicking yes. We now have a brand new NPC. We will have to do some work on him later, but he is in the game.


Exit and create a new form by saying yes. We now have a brand new NPC. We will have to do some work on him later, but he is in the game.
==Creating the Quest==
[b]
Creating the Quest[/b]


In the top menu select CHARACTER.
In the top menu select CHARACTER.
Then from the drop down menu select QUEST
Then from the drop down menu select QUEST.


The quest window will open.
The quest window will open.
Line 218: Line 194:
On the left hand side is the list of all the quests in the game.
On the left hand side is the list of all the quests in the game.
Place your pointer over this section and right click. A small selection window appears.  
Place your pointer over this section and right click. A small selection window appears.  
From this select NEW.
Select NEW.


Another window pops up called New Form Editor ID
Another window pops up called New Form Editor ID
This is the prompt for us to enter our Quest ID.
This is the prompt for us to enter our Quest ID.


This should be a short alpha-numeric name, with no spaces, that we can readily identify as our mod. It must of course be unique. I choose to name mine BGM001 (Beginners Guide Mod 1). When you’re done select OK.  
The ID is NOT the same as the quest name which will appear in the player's journal. This should be a short alpha-numeric name, with no spaces, that we can readily identify as a part of our mod. It must also be unique. I chose to name mine ''BGM001'' (Beginners Guide Mod 1). When you're done, select OK.  


We now have a quest.
We now have a quest. Let's look at out quest data tab.  
Let’s look at out quest data tab.  


We want to give our quest a name. This is the name that appears in the in-game journal entries. You can call it pretty much what you like. You can even duplicate names, which although legal could be a bit confusing. I’ve chosen to call mine
We want to give our quest a name. This is the name that appears in the in-game journal entries. You can call it pretty much what you like. You can even use duplicate names, but that would be a bit confusing. I've chosen to call mine ''The Inheritance Denied.''


[i]The Inheritance Denied.[/i]
If you remember from lesson 4, we need to choose an appropriate priority value.  


If you remember from lesson 4 we need to choose an appropriate priority.  
We will select 50, as this is a miscellaneous quest.


We will select 50 as this is a miscellaneous quest.
The next set of decisions involves the three flags which were discussed in the appendix:


The next set of decisions involves the three flags which were discussed in the appendix
*Start Game Enabled
*Allow Repeated Conversation Topics
*Allow Repeated Stages


Start Game Enabled
These three tags control when and how often scripts are run.
Allow Repeated Conversation Topics
Allow Repeated Stages


These three tags principally control when and how often scripts are run.
For now let's go ahead and select the standard ''Start Game Enabled'' and leave blank the ''Repeated Conversations'' & ''Stages''. Now have a look at the table at the below, which contains quest conditions.


For now let’s go ahead and select the standard Start Game Enabled and leave blank  the repeat conversions or Stages. Now have a look at the table at the bottom which contains any quest conditions
==Quest Conditions==


[b]Quest Conditions [/b]
At the moment this is blank. We are going to input a [[condition]] which has the effect of limiting any conversations and dialogue topics we create in this quest to characters we would expect to speak, thereby excluding those we wouldn't (e.g. goblins and horses).
 
At the moment this is blank. We are going to input a generic conditions which has the effect of limiting any conversations and dialogue topic we create in this quest to characters we would expect to speak, and exclude those we don’t like Goblins and Horses.


The conditions are applied to the person speaking the line, called the object. Click the NEW button at the bottom of the page.  
The conditions are applied to the person speaking the line, called the object. Click the NEW button at the bottom of the page.  


The interface to enter conditions is split into four areas and is surrounded by some flag selectors. (We will look at the flags later)
The interface to enter conditions is split into four areas: Condition Function, Function Parameters, Comparison, and Value. There are also some flag selectors, which we will look at later.


Condition Function
===Condition Function===


This is the basis of you condition. It initially defaults to the condition GetDisposition, but clicking on this opens up a long list in a drop down window. This contains the valid functions that can be used in a conditional statement. (See later for IF-ENDIF BLOCKS)
This is the basis of your condition. It initially defaults to the condition [[GetDisposition]], but clicking on this opens up a long list in a drop down window. This contains the valid functions that can be used in a conditional statement. (See later for IF-ENDIF BLOCKS)


These can be divided into sets of similar functions which I have chosen to call families.
These can be divided into sets of similar functions which I have chosen to call families.


CAN Family: - Tests if something can happen  
:'''CAN Family:''' Tests if something can happen  
HAS Family: - Tests if something has occurred  
:'''HAS Family:''' Tests if something has occurred  
IS Family: - Tests if something IS true  
:'''IS Family:''' Tests if something is true  
SAME family: - test if two things are the same  
:'''SAME family:''' Test if two things are the same  
GET family: - retrieves information from game for comparison  
:'''GET family:''' Retrieves information from game for comparison  


Clearly I cannot go through each of these in turn. In truth most of their general functions are self explanatory even if their specific use is not.
Clearly I cannot go through each of these in turn. In truth most of their general functions are self explanatory, even if their specific use is not.


Function parameters
===Function parameters===


Several functions require a valid parameter to work. Several don’t. It depends on the function.
Some functions require a parameter to work, and some don't. It depends on the function.


For Example the Function GetRace requires you to select a valid race from a drop down menu for it to make sense. While GetIsPlayableRace has no parameters.
For example, the function [[GetRace]] requires you to select a valid race from a drop down menu for it to make sense, while [[GetIsPlayableRace]] has no parameters.


Comparison
===Comparison===


All conditional statements are in effect arithmetical functions. They are all about comparing two numbers. This is because Functions produce or return numerical value when we use them. The function GetRace ‘Imperial’ returns a numerical value of one if the speaker of the line is an Imperial. If not the value is set at zero.  
All conditional statements result in boolean values: true or false. They are all about comparing values. Each "conditional function" returns some value which we can then compare to our own set value in a few different ways: less than, more than, equivalent to, not equivalent to, etc. The comparison of those two values will turn out to be either true or false. (e.g.: Either A is more than B, or it isn't. The player has less than or equal to 5000 gold, or he/she doesn't.)


We compare this using standard maths expressions like equals (==), not equals (! =), greater than (>), less than (<) etc.
===Value===
 
Value


This is the value we compare the conditional function value with. This can be a number or a variable.
This is the value we compare the conditional function value with. This can be a number or a variable.


We want to set up a conditional function that check that the speaker is of the right type. I.e. it is one of the playable races.
===Our condition===
We want to set up a conditional function that checks whether the speaker is of the right type. I.e., that it is one of the playable races (Imperial, High Elf, etc.).


We select from the list, the Function GetIsPlayableRace.
From the ''Condition Function'' list, we choose [[GetIsPlayableRace]].


This has no valid function parameter. (The NPC is either of a playable race or not)
This function does not require a parameter, as it already knows exactly which races are or aren't valid player races. It will return a value of 1 if the object is a playable race, and a value of 0 if not.


From the list of comparisons we choose equals. This is represented by a double equals ==.  
From the list of comparisons we choose equals. This is represented by ==.  


In the value box we select 1.000.
In the value box we select 1.000.
Line 296: Line 268:
We now have the condition
We now have the condition


GetIsPlayableRace == 1.  
GetIsPlayableRace == 1.  


This is in effect the equivalent to the instruction
This is in effect the equivalent to the instruction


Find out if the actor is from a playable race. IF this is true carry on. If it is not true, stop the actor from speaking any lines in this quest.
Find out if the actor is from a playable race. IF this is true, carry on. IF NOT, stop the actor from speaking any of the lines from this quest.


We have completed the basic set up for our quest.
We have completed the basic set up for our quest.


Now let’s select the Quest Stage tab.
==Quest Stages==
Now let's select the [[Quest Stages Tab]].


Again this is blank. We can add stages in the same way as we added the quest. In the column marked Quest Stages, right click and select new. The pop-up expects a number between 0-255. We tend to use 10, 20 30 etc to allow room for extra stages. Go ahead and enter 10.  
Again, this is blank. We can add stages in the same way as we added the quest. In the column marked ''Quest Stages'', right click and select new. The pop-up expects a number between 0-255. We tend to use 10, 20, 30, etc. to allow room for extra stages. Go ahead and enter 10.  
Now select new again and enter 100. We now have two stages 10 and 100. Right click and enter 20. Initially the list reads 10, 100, and 20.  
Now select new again, and enter 100. We now have two stages: 10 and 100. Now make one more stage and enter 20. Initially the list reads 10, 100, 20.  
But if you go back to the quest data tab, and then return to the stage tab again the list will have updated to read 10,20 100. The CS sorts them for us.
But if you go back to the quest data tab and then return to the stage tab again, the list will have updated to read 10, 20, 100. The CS sorted them for us.


(Note that although the CS lists the stages in numerical order, you do not have to work through the stages in that order. Each stage is discrete and exists in its own right without reference to the other stages)
(Note that although the CS lists the stages in numerical order, you do not have to work through the stages in that order. Each stage is discrete and exists in its own right without reference to the other stages.)


These three stages are blank. Don’t worry about this. Until we set the game up to call these stages they do nothing. If we do call a blank stage nothing will happen.
These three stages are blank. Don't worry about this. Until we set the game up to call these stages, they do nothing. If we do call a blank stage nothing will happen.


==Quest Targets==
The next tab is called TARGETS. We will add all the targets at the end of lesson 7. We can add them at any stage. I found it easier to do this at the end.  
The next tab is called TARGETS. We will add all the targets at the end of lesson 7. We can add them at any stage. I found it easier to do this at the end.  


We are now ready to get down to the fun bit of mod building.
We are now ready to get down to the fun bit of mod building.


[b]Topics[/b]
==Topics==
 
Remember we have set this quest up as start enabled, but it has no content.
Let’s add some.
 
Select the Topic tab, from the Quest pop up. DO NOT use filtered dialogue to add topics. This can lead to conflict issues.


Again this is blank to begin with. We will add a topic which will be used at the start of the quest.
Let's add some content.


In the topic column to left hand side of the tab, right click again and select add topic.
Select the [[Topics Tab]] from the Quest pop up. DO NOT use filtered dialogue to add topics: this can lead to mod confliction issues.
A pop-up appears listing all available topics for all the quests in the game. Again we use right click and again we use new to get another pop-up. We need to add a one word unique topic descriptor.  


[i]( I will admit that I made a mistake here. It is good practice to use a set of common letters as a prefix for all mod items. I should have added a topic called BGMMessage4u, but I forgot the prefix. It’s not a disastrous mistake, but it does mean this mod might have a few conflict issues with other mods that add a topic called message4u as well. Sorry about that. Also while I‘m apologising, ignore the deleted empty info)[/i]
Again, this is blank to begin with. We will add a topic which will be used at the start of the quest.


You should add a topic called BGMMessage4u, to show how much better at this thing you are than me.
In the topic column to left hand side of the tab, right-click and select Add Topic.
A pop-up appears listing all available topics for all of the quests in the game. Again we use right-click and New to get another pop-up. We need to add a one word unique topic descriptor.  


The Topic BGMMessage4u has now been added.  
You should add a topic called BGMMessage4u. ''(In the TutPlayTest file, the topic was accidentally named message4u - you should continue using the quest prefix.)''


If you look at the top this also appears at the top of the screen. This is the topic as it will appear in the dialogue menu when you activate a suitable NPC. Try to keep these fairly short, as they will take up too much room in the game. Let’s change this to something like Message for you.  
If you look at the top this also appears at the top of the screen, in the 'Topic Text' box. This is the topic as it will appear in the dialogue menu when you activate a suitable NPC. Try to keep these fairly short, as they will otherwise take up too much space in the topic selection menu. Let's change this to something like "Message for you."


Great! We have a topic, now we need a response or info. The idea here is to create an exchange where when we click on the topic MESSAGE FOR YOU we get a response that let’s us know that an NPC who I have named Vilanus Villa is looking for us. Of course the name is entirely up to you. Just change any reference I make to Vilanus Villa to suit your characters.
Great! We have a topic, now we need a response. The idea here is to create an exchange where when we click on the topic "Message for you" we get a response that lets us know that an NPC - who I named Vilanus Villa - is looking for us. Of course the name is entirely up to you. Just change any reference I make to "Vilanus Villa" to suit your characters.


To add a response it is the same procedure. Right click in the info section, select new. A new pop-up interface appears. Ignore the bottom for now. In the upper section type
Right-click in the response section (underneath the ''Topic Text'' filed), and select new. A new pop-up interface appears. Ignore the bottom part for now. In the upper section type:


I hear a Lawyer called Vilanus Villa is looking for you.
I hear a Lawyer named Vilanus Villa is looking for you.


Hit Ok to save.
Hit Ok to save.


So we now have a topic and a response info. However, if you tested this mod you would not see this topic on any NPC at all. Why?  
So we now have a topic and a response. However, if you tested this mod you would not see this topic on any NPC at all. Why?  


There are an awful lot of topics in the game list. If the game added every topic to every character the scrolling list of topics would be ridiculously long. So the game works like this. It only adds topic which  
There are an awful lot of topics in the game list. If the game added every topic to every character the scrolling list of topics would be ridiculously long. So the game works like this. It only adds topics which:


a) Have a valid response (one whose conditions are met)  
A) Have a valid response (one whose conditions are met)  


And
And


B) Your character has learned about that topic.
B) Your character knows about


Characters can learn topics in all sorts of ways. They may as in the walkthrough quest in lessons 4-5 hear a conversation. They may talk to NPC’s and pick up topics that way. They may witness events that add topics. Or as in the case of this mod we teach them the topic by doing a bit of scripting.
Players can learn new topics in all sorts of ways. They may, as in the walkthrough quest in lessons 4-5, pick one up from an overheard conversation. They may talk to NPCs and pick up topics that way. They may witness events that add topics. Or, as in the case of this mod, we teach them the topic by doing a bit of scripting.


So are you ready to write a script.
So are you ready to write a script?


[b]Our First Script[/b]
==Our First Script==


We are going to write a bit of script which will add a topic to the players learned list and thus allow NPC’s to use that topic when we activate them.
We are going to write a bit of script which will add a topic to the players learned list and thus allow NPCs to use that topic when we activate them.


Before we go further it might be useful to give you a bit of a glossary.  
Before we go further it might be useful to give you a bit of a glossary.  
I have assumed that you have never programmed before in writing this tutorial. If you have you will be at an advantage when it comes to writing scripts.
I have assumed that you have never programmed before in writing this tutorial. If you have you will be at an advantage when it comes to writing scripts.


Commands and Functions:  
[[Command]]s and [[Function]]s:  


These are the formal instructions that you place in the script to tell the game what you want it to do. The Wiki makes a distinction between these do. The difference for beginners is very slight
These are the formal instructions that you place in the script to tell the game what you want it to do. The Wiki makes a distinction between what these do. It should be noticed, the differences for beginners may appear very slight.


The commands are
The commands are:


Scriptname:
;[[Scriptname]]
Used to identify the script obviously
-Used to identify the script obviously


Declarations:
;[[Variable|Declarations]]
These are a set of descriptors which identify the VARIABLES used in a script
-These are a set of descriptors which identify the VARIABLES used in a script


Begin-End:
;[[Begin|Begin-End]]
Used in conjunction with each other to create BLOCKS of script.
-Used in conjunction with each other to create BLOCKS of script.


If-EndIf:
;[[If|If-EndIf]]
Used together with optional ElseIf and Else commands to form CONDITIONAL blocks.
-Used together with optional ElseIf and Else commands to form CONDITIONAL blocks.


Return:
;[[Return]]
Use to break a scripts running for that run only.
-Use to break a scripts running for that run only.


Set:
;[[Set]]
Used to assign new values to variables
-Used to assign new values to variables


“.” or Use Reference:
;“.” or [[UseReference|Use Reference]]
The full stop or period “.” is a command which identifies the REFERENCE that a FUNCTION should use.
The full stop or period “.” is a command which identifies the REFERENCE that a FUNCTION should use.


There are a large number of functions, each of which does a unique job. There is not enough space to look at each of these in turn. However, many of the functions do group together to form ‘families’, for example  
There are a large number of functions, each of which does a unique job. There is not enough space to look at each of these in turn. However, many of the functions do group together to form ‘families', for example  
 
ADDsomething
FORCEsomething
GETsomething
ISsomething
MODsomething
SAMEsomething
SETsomething
SHOWsomething


Variables:
*ADDsomething
*FORCEsomething
*GETsomething
*ISsomething
*MODsomething
*SAMEsomething
*SETsomething
*SHOWsomething


;[[Variable]]s
One way to think of variables is as a container which stores a number. The different variables types, Short, Long etc. determined how big a container will be assigned to that variable name.
One way to think of variables is as a container which stores a number. The different variables types, Short, Long etc. determined how big a container will be assigned to that variable name.


So for example
So for example


Short BOB
  Short BOB
Long BILL
  Long BILL


This assigns a small section of the computers memory to a variable called bob (note capitalisation is purely a matter of personal clarity and style and is not important to the script compiling or running), and a larger part of the memory is assigned to a variable called Bill. The more variables the game has to remember the larger the amount of memory we use, and the slower the game runs. We want to minimise the impact by declaring as small a variable type as possible.
This assigns a small section of the computers memory to a variable called bob (note capitalisation is purely a matter of personal clarity and style and is not important to the script compiling or running), and a larger part of the memory is assigned to a variable called Bill. The more variables the game has to remember the larger the amount of memory we use, and the slower the game runs. We want to minimise the impact by declaring as small a variable type as possible.


Parameters:
;Parameters
 
Many functions accept or need you to include extra bits of information called a parameter.  
Many functions accept or need you to include extra bits of information called a parameter.  


Player.additem gold001 100
  Player.additem gold001 100


The 100 is a parameter that lets the game know how much gold to add.
The 100 is a parameter that lets the game know how much gold to add.
Line 426: Line 393:
Object ID: Several functions work by doing something to a game object. Remember all the objects are listed in the object window, so objects include Actors.  
Object ID: Several functions work by doing something to a game object. Remember all the objects are listed in the object window, so objects include Actors.  


Player.additem gold001 100
  Player.additem gold001 100


Here gold001 is the object id
Here gold001 is the object id


Reference ID:
;[[Reference]] ID
 
Several functions work by changing a specific example of an object. There may be many chests of a particular object type in the game and you want to add gold to only one of them. The reference ID is a unique identifier for that instance of an object. You add the reference by double clicking on the example in the render window (or by selecting edit from the cell objects window). In the object pop up dialogue box you add a unique name to the reference id box. Note that for this to happen the object must be placed in a cell. To use this reference in a script you will need to click the persistent reference check box. This tells the game to always remember that object even if the PC leaves the cell that it is in.
Several functions work by changing a specific example of an object. There may be many chests of a particular object type in the game and you want to add gold to only one of them. The reference ID is a unique identifier for that instance of an object. You add the reference by double clicking on the example in the render window (or by selecting edit from the cell objects window). In the object pop up dialogue box you add a unique name to the reference id box. Note that for this to happen the object must be placed in a cell. To use this reference in a script you will need to click the persistent reference check box. This tells the game to always remember that object even if the PC leaves the cell that it is in.


  Player.additem gold001 100
  Player.additem gold001 100
Line 438: Line 404:
In this example the player (a constant reference) is the reference id.
In this example the player (a constant reference) is the reference id.


Okay let’s move on
Okay let's move on


The FUNCTION we will use is called AddTopic. Its syntax (the way the computer needs it to be written so it works) is this
The FUNCTION we will use is called AddTopic. Its syntax (the way the computer needs it to be written so it works) is this


[i]AddTopic TopicID[/i]
  AddTopic TopicID


Firstly the use of capitals in any function is optional  
Firstly the use of capitals in any function is optional  
Line 451: Line 417:
aDdToPiC
aDdToPiC


All work, and all do the same thing. It’s just that AddTopic looks neater so you tend to see this used most. But don’t get worried if you forget or come across script that uses capitals in another way.
All work, and all do the same thing. It's just that AddTopic looks neater so you tend to see this used most. But don't get worried if you forget or come across script that uses capitals in another way.


The TopicID is the id name we added in the topic list. This is why it has to be unique.
The TopicID is the id name we added in the topic list. This is why it has to be unique.
Line 457: Line 423:
Take a deep breath. Now go back to the quest Data tab. Next to the quest script box is a button with three dots … Click this and the script editing window opens up.
Take a deep breath. Now go back to the quest Data tab. Next to the quest script box is a button with three dots … Click this and the script editing window opens up.


[b]The Script Editing Window[/b]
==The Script Editing Window==


The script editor is in essence, a very basic text editor, used for writing and editing scripts. Many scripter use external text editors like, word, works, WordPad and notepad to develop long scripts. One reason for this is that the script editor will only save compiled scripts which must be 100% correct. It also allows you to keep a back-up version.  
The [[Edit Scripts|script editor]] is in essence a very basic text editor, used for writing and editing scripts. Many scripters use external text editors like Notepad, Notepad++, Crimson Editor, etc. to write their scripts. One reason for this is that the script editor will only save compiled scripts, which must be 100% free of errors. External editors also allow you to keep a back-up versions of your scripts.


I personally keep a large library of scripts. Some that I have written, and loads copied from forums and other mods. I can then refer to these when I need a solution to a problem.
I personally keep a large library of scripts. Some that I have written, and loads copied from forums and other mods. I can then refer to these when I need a solution to a problem.


On the menu bar at the top of the editor you will find two options plus the standard help files.
On the menu bar at the top of the editor you will find two options, plus the standard help files.


Script
===Script===


This menu has the following options available  
This menu has the following options available  


New:
;New
Creates a new, empty script.
Creates a new, empty script.
   
   
Open:
;Open
Presents a list of existing scripts. Choose from the drop down list for one to edit.
Presents a list of existing scripts. Choose from the drop down list for one to edit.
   
   
Next Script:
;Next Script
Switches to the next script in alphabetical order. If you changed the current script, or the current scripts needs to be recompiled for some other reason (e.g. changed variables in another script) you'll be asked if you want to save the changes.
Switches to the next script in alphabetical order. If you changed the current script, or the current scripts needs to be recompiled for some other reason (e.g. changed variables in another script) you'll be asked if you want to save the changes.
   
   
Previous Script:
;Previous Script
Switches to the previous script in alphabetical order. You'll be asked if you want to save/recompile.  
Switches to the previous script in alphabetical order. You'll be asked if you want to save/recompile.  


Save:
;Save
Compiles and saves the script. If it fails to compile, the script is not saved.  
Compiles and saves the script. If it fails to compile, the script is not saved.  


Delete:
;Delete
Shows the list of all scripts. Choose one to delete
Shows the list of all scripts. Choose one to delete


WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!  
  WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!  


;Recompile All
Recompiles all scripts in game. This will store all scripts from any currently loaded ESM's or ESP's into your active ESP, so it's only useful for working on total conversions. In other words '''DON'T USE THIS''' unless you know exactly what you are doing. '''EVER!'''
The resulting esp. will be
a) Huge and
b) In conflict with the original files.
 
  WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!


WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
===Edit===
Edit


Undo: Standard undo function that restores the script to its state before the last change.  
;Undo
Redo: Standard redo function that restores the last change to the script if it has been undone.  
Standard undo function that restores the script to its state before the last change.  
Find Text: Standard find function.  
;Redo: Standard redo function that restores the last change to the script if it has been undone.  
Find Next: Standard find next function that repeats the last find from the current cursor location.  
;Find Text
Go To Line: Compile errors list the error by line number. Use this command to go directly to that line number.  
Standard find function.  
;Find Next
Standard find next function that repeats the last find from the current cursor location.  
;Go To Line
Compile errors list the error by line number. Use this command to go directly to that line number.  


Next is a line of icons which give you shorthand ways to do some of the menu actions. In order from left to right they are.  
Next is a line of icons which give you shorthand ways to do some of the menu actions. In order from left to right they are.  
Open, Save, Next, Previous, Compile All, Delete, Exit
Open, Save, Next, Previous, Compile All, Delete, Exit


Script Type:
===Script Type===
Finally there is a drop down menu. This allows you to select the script type. There are 4 types of script, but results scripts are not edited or compiled in the script editor. We will see this shortly.  
Finally there is a ''Script Type'' drop down menu. There are 4 types of script, but "Results" scripts are not edited or compiled in the script editor. We will see this shortly.  


The scripts written in this editor can be Object, Quest, or Magic effect. This setting determines which objects in the editor the script can be attached to. Each script type is run in a slightly different way and it is important to let the game know which one you want your script to be.  
The scripts written in this editor can be [[Object scripts|Object]], [[Quest scripts|Quest]], or [[Magic effect scripts|Magic effect]]. This setting determines which objects in the editor the script can be attached to. Each script type is run in a slightly different way and it is important to let the game know which one you want your script to be.  
You can edit or change this at a later date if you make an error.
You can edit or change this at a later date if you make an error.


Okay we want to write a quest script, so select Quest from the Script Type drop-down window.
Okay, we want to write a quest script, so select Quest from the Script Type drop-down window.


Scripting
==Scripting==


Scripting is a set of instructions to the game telling it to do certain tasks which cannot normally be done by the usual game play interaction. It has much in common with programming languages but is not a true language in its self. We do need to use a formal structure called syntax to ensure that the game can understand what we want it to do.  
A script is a set of instructions for the game to run during gameplay. It has much in common with programming languages, but is not a true language per se. We do need to use a formal structure called syntax to ensure that the game can understand what we want it to do.  


Let’s add a bit of script then
Let's add a bit of script then.


We need to give each script a name, and like all naming that we have covered so far it has the same basic rules. The name must be a single alpha-numeric, which is unique.  
We need to give each script a name, and like all naming conventions that we have covered so far, it has the same basic rules. The name must unique, alpha-numeric, and free of whitespace (spaces, tabs, etc.).  
There is a convention that you should add a prefix to help identify your scripts.  
You should also continue to use your quest prefix (e.g. BGM) while naming your scripts.  


Let’s name the script BGM001QuestScript
Let's name the script ''BGM001QuestScript''.


(Note: This should be done on the BASE version if you have loaded Both Tutorial Mods at the same time.)
(Note: This should be done on the BASE version if you have loaded Both Tutorial Mods at the same time.)


We write this in the editor like this  
We write this in the editor like this:


Scriptname BGM001QuestScript
Scriptname BGM001QuestScript


(We could also use a shorthand version
We could also use a shorthand version:


Scn BGM001QuestScript
Scn BGM001QuestScript


Many functions and command have shorthand versions. In this tutorial I will always use the full version.)
Many functions and command have shorthand versions. In this tutorial I will always use the full version.


Now select save.  
Now select save.  
Line 538: Line 513:
The editor compiles the script.
The editor compiles the script.


Begin Statements
==Begin Statements==


First we start by adding a Begin statement.  
First we start by adding a Begin statement.  
Line 547: Line 522:
There are lots of BLOCK types available.
There are lots of BLOCK types available.


[url=http://cs.elderscrolls.com/constwiki/index.php/Begin]Wiki Block Types Page[/url]
[[Begin|Wiki Block Types Page]]


The vast majority of begin blocks run only once.  
The vast majority of begin blocks run only once.  
Line 555: Line 530:
So lets type  
So lets type  


Begin GameMode
  Begin GameMode


(Remember the capitals are purely for clarity)
(Remember the capitals are purely for clarity)


Now let’s add the instruction
Now let's add the instruction


AddTopic Message4U
  AddTopic BGMMessage4U


And finally the
And finally the


End
  End


Command
Command


So our script reads
So our script reads
  Scriptname BGM001QuestScript
  Begin GameMode
  AddTopic BGMMessage4U
  End
We can again save our script.
We can again save our script.


(Please not the quest script in the PLAYTEST file shows the script in its finished state and quite long. We will add small snippets of working script as we progress)
(Please note, the quest script in the PLAYTEST file shows the script in its finished state and quite long. We will add small snippets of working script as we progress)


Once of the most common mistakes that beginners make is to assume that because a script complies (saves), that it will work. This is not the case. The editor checks to see that your script has obeyed all the rules to make sure the game can try to carry out your instructions. It does not mean that these instructions will do the job you expect them to do. If you do make a syntax error the editor will put a pop up window detailing the error, together with a disconcerting alarm ring. It also asks you to select whether you should continue. Always say yes or you will lose scripts.
One of the most common mistakes that beginners make is to assume that because a script complies (saves), that it will work. This is not the case. The editor checks to see that your script has obeyed all the rules to make sure the game can try to carry out your instructions. It does not mean that these instructions will do the job you expect them to do. If you do make a syntax error the editor will display a pop up window detailing the error, together with a disconcerting alarm ring. It also asks you to select whether you should continue. Always say yes or you will lose your scripts.
   
   
It is always a good idea to back up scripts in notepad or WordPad. Remember you can copy a script using CTRL -C.  
It is always a good idea to back up scripts in notepad or WordPad. Remember you can copy a script by selecting it, and then using the shortcut CTRL-C.  


Now we need to attach the script to our quest.  
Now we need to attach the script to our quest.  


Open up the Quest data Tab for our quest.   
Open up the [[Quest Data Tab]] for our quest.   
Where it says script open the drop down menu and scroll down to find the BGM001QuestScript. Click on this and you’re done.  
Where it says script open the drop down menu and scroll down to find the BGM001QuestScript. Click on this and you're done.  


Save the mod (you will need to close all pop up windows to do this)
Save the mod (you will need to close all pop up windows to do this)
Line 587: Line 566:
You can now test this mod in the game, but it might be best not to SAVE the game in Oblivion as we will be changing things.
You can now test this mod in the game, but it might be best not to SAVE the game in Oblivion as we will be changing things.


Three Problems
==Two Problems==


There are 3 problems with the mod as it stands, (other than the fact it is not finished).
There are two problems with the mod as it stands:


The first problem you may have noticed is that the text does not stay on the screen very long and our NPC will, just look at us. This is due to the way the game handles speech.  
The first problem is that the text does not stay on the screen very long, and our NPC will just look at us. This is due to the way the game handles speech.  
It expects to find for each dialogue response files which we have not created. One is an MP3 which contains the sound files the others control are lip synch files used to animate the actor face as we carry out the dialogue. The text onscreen is set to appear on screen for the duration of these files.  
It expects to find for each dialogue response files, which we have not created. One is an MP3 which contains the sound files, and the others are lip synch files used to animate the actor's face as we carry out the dialogue. The text is supposed to appear on screen for the duration of these files.  
Since we don’t have them yet the text runs very quickly. In later tutorials we will look at polishing this mod to include these files. For now these are cosmetic problems. It’s irritating not to see the text for any length of time but it can’t be helped, until we add those MP3’s.  
Since we don't have them yet, the text runs very quickly. In later tutorials we will look at polishing this mod to include these files. For now, these are cosmetic problems. It's irritating not to see the text for any length of time, but it can't be helped until we add those MP3's.  
It doesn’t stop the quest running. You can repeatedly play the on-screen text by selecting the topic message for you until you get the message
It doesn't stop the quest running. You can repeatedly play the on-screen text by selecting the topic message for you until you get the message. (Alternatively, you could install a mod like [http://www.tesnexus.com/downloads/file.php?id=16622 Universal Silent Voice].)


The second problem deals with the script as it currently stands and may not be so obvious to a non-scripter. Remember the quest script works every 5 seconds. That means that every 5 seconds this script adds the topic message4u to the players list. I don’t honestly know the effect of repeatedly adding a topic to the player list. I suspect that having done this the first time the rest of the time the script is ignored.  
The second problem deals with the script as it currently stands and may not be so obvious to a non-scripter. A quest script runs every 5 seconds. That means that every 5 seconds this script tries to add the topic BGMMessage4u to the players topic list. I don't honestly know what the effect of repeatedly adding a topic to the player's list is, but I suspect that extra requests to add the topic are simply ignored.  


However, this is still an untidy way to script. If we only want the script to do something once we should write script that does this.
However, this is still an untidy way to script. If we only want something to happen once, we should write our script that way!


This leads us to one of the most important and common scripting ideas. A do once loop.
This leads us to one of the most important and common scripting ideas: a do once loop.


This uses an.
==If-EndIf Blocks==
 
[b]If-EndIf Blocks.[/b]


No other command is more important to good quality functional scripts than the if command. Again those with programming experience will be at a slight advantage as you will have used these before.
No other command is more important to good quality functional scripts than the if command. Again those with programming experience will be at a slight advantage as you will have used these before.
Line 616: Line 593:
The structure of the if block can be summarised as this
The structure of the if block can be summarised as this


[b]If [/b](a set of mathematically based conditions)  
'''If''' (a set of mathematically based conditions)  
 
:RUN THE SCRIPT INSTRUCTIONS LOCATED HERE IF THE CONDITIONS ARE TRUE


          RUN THE SCRIPT INSTRUCTIONS LOCATED HERE IF THE CONDITIONS ARE TRUE
'''ElseIf''' (a second set of OPTIONAL conditions)


[b]ElseIf [/b](a second set of OPTIONAL conditions)
:SCRIPT THAT RUNS IF THE SECOND SET IS TRUE. THE CONDITION WILL ONLY BE TESTED IF THE ORIGINAL IF STATEMENT SET OF CONDITIONS ARE FALSE.


          SCRIPT THAT RUNS IF THE SECOND SET IS TRUE. THE CONDITION WILL ONLY BE TESTED IF THE ORIGINAL IF STATEMENT SET OF CONDITIONS ARE FALSE.
'''Else''' (No Conditions)


[b]Else[/b] (No Conditions)
:OPTIONAL SCRIPT THAT RUNS IF ALL OTHER CONDITIONS ARE FALSE.
:IF THE ELSEIF AND ELSE COMMANDS ARE OMITTED THE BLOCK DOES NOTHING IF THE ORIGINAL CONDITIONS ATTACHED TO THE IF STAEMENT ARE NOT MET.


            OPTIONAL SCRIPT THAT RUNS IF ALL OTHER CONDITIONS ARE FALSE.
'''EndIf'''
IF THE ELSEIF AND ELSE COMMANDS ARE OMITTED THE BLOCK DOES NOTHING IF THE ORIGINAL CONDITIONS ATTACHED TO THE IF STAEMENT ARE NOT MET.


[b]EndIf[/b]
So all IF blocks, must contain an IF command, a set of conditions, some instructions and an EndIf command. The ElseIf and Else commands are optional, and add versatility to the block.
So all IF blocks, must contain an IF command, a set of conditions, some instructions and an EndIf command. The ElseIf and Else commands are optional, and add versatility to the block.


Line 649: Line 627:
So add the line
So add the line


Short DoOnce1
  Short DoOnce1


Just after the script name line. You can leave lines to help clarity. Again these are ignored by the program when it runs the script.
Just after the script name line. You can leave lines to help clarity. Again these are ignored by the program when it runs the script.


Now let’s add the if block
Now let's add the if block


Change the Begin block to look like this.
Change the Begin block to look like this.


Begin GameMode
If (DoOnce1 == 0)
AddTopic BGMMessage4U
Set DoOnce1 to 1
EndIf
End
This is perfectly fine but it can get a little hard to read, when these if statements get long and complex. So again we use an optional convention. We indent using the tab key all lines after an IF statement, to make clear what is going on.
<pre>
Begin GameMode
Begin GameMode
If (DoOnce1 == 0)
  If (DoOnce1 == 0)
AddTopic Message4U
    AddTopic BGMMessage4U
Set DoOnce1 to 1
    Set DoOnce1 to 1
EndIf
  EndIf
End
End
</pre>


This is perfectly fine but it can get a little hard to read, when these if statements get long and complex. So again we use an optional convention. We indent using the tab key all lines after an IF statement, to make clear what is going on. So
So this script uses another new command called SET-TO.
This script uses another new command called SET-TO.


Whenever you declare variables they are automatically assigned a value of Zero.  
Whenever you declare variables they are automatically assigned a value of Zero.  
Line 672: Line 660:


The format is  
The format is  
Set VARIABLE to VALUE
  Set VARIABLE to VALUE


The VALUE can be any number which fit’s the pattern of the variable. So for a short variable it can be any integer or whole number between (-32768) and (32767).  
The VALUE can be any number which fit's the pattern of the variable. So for a short variable it can be any integer or whole number between (-32768) and (32767).  


This can take the form of
This can take the form of
- A fixed number like our script.
*A fixed number like our script.
- The result of a mathematical calculation.
*The result of a mathematical calculation.
- The value of another variable
*The value of another variable
- Or the outcome of a comparison statement.  
*Or the outcome of a comparison statement.  


IF statements and Set statements both use standard mathematical comparisons  
IF statements and Set statements both use standard mathematical comparisons  


Comparison Operators  
===Comparison Operators===
An IF statement may contain one or more comparison operators.  
An IF statement may contain one or more comparison operators.  
Below is a table of valid comparison operators:  
Below is a table of valid comparison operators:  


Operator Description  
  '''Operator'''  '''Description'''
== Exactly equal to  
    ==     Exactly equal to  
!= Not equal to  
    !=   Not equal to  
> Greater than  
    >   Greater than  
>= Greater than or equal to  
    >=   Greater than or equal to  
< Less than  
    <   Less than  
<= Less than or equal to  
    <=   Less than or equal to  


Combining Comparisons  
===Combining Comparisons===


Comparisons can be linked together using the following logical operators:  
Comparisons can be linked together using the following logical operators:  


Operator Description Example  
  '''Operator''' '''Description''' '''Example '''
&&           Logical AND   If x == 1 && y == 1; considered true only if both x and y equal 1.  
  &&         Logical AND If x == 1 && y == 1; considered true only if both x and y equal 1.  
||             Logical OR   If x == 1 || y == 1; considered true unless both x and y equal 0.  
  ||         Logical OR If x == 1 || y == 1; considered true unless both x and y equal 0.  


(Note that "||" is evaluated before "&&")
(Note that "||" is evaluated before "&&")
Line 708: Line 696:
So this script we have written works this way.
So this script we have written works this way.


The first time the script runs the variable DoOnce is set up and given the value ZERO).  
The first time the script runs the variable DoOnce is set up and given the value ZERO.  


The game runs through the script to the IF statement.
The game runs through the script to the IF statement.


It tests to see if it is TRUE that DoOnce equal zero.  
It tests to see if it is TRUE that DoOnce equal zero.  
In this case it is true. So it runs the script, adding the topic message4u to the players learned list. It then sets the value stored in doonce1 to the number one.  
In this case it is true. So it runs the script, adding the topic BGMMessage4u to the players learned list. It then sets the value stored in doonce1 to the number one.  
It then ends the IF statement and ends the scripts begin end block.  
It then ends the IF statement and ends the scripts begin end block.  
Since this is the end of the script it stops running.  
Since this is the end of the script it stops running.  
Line 723: Line 711:
We have added the topic once and once only.
We have added the topic once and once only.


The third major problem is that this topic has been added to every NPC in the game. It is just about conceivable that if you complete every quest in the game and then some that you might meet every NPC there is, but I don’t see how it’s logical to suggest that they all might know Vilanus Villa and know he has a message for you. We need to limit who speaks to you on this topic. We must set some response conditions.
==A third problem==
The third major problem is that this topic has been added to every NPC in the game. It is just about conceivable that if you complete every quest in the game and then some that you might meet every NPC there is, but I don't see how it's logical to suggest that they all might know Vilanus Villa and know he has a message for you. We need to limit who speaks to you on this topic. We must set some response conditions.


[b]Conditions[/b]
==Conditions==


The conditions box in the Topic Tab is used to limit who gets to say a particular response.
The conditions box in the Topics Tab is used to limit who gets to say a particular response. We can limit this in many ways.


We can limit this in many ways
For example, Restrict by group ([[GetInFaction]]), race ([[GetRace]]) or limit to only one NPC ([[GetIsID]]), Restrict by Worldspace, City, Cell or distance from a particular chair, Restrict by Game Time, Season, Weather or progress of quest.


For example, Restrict by group (GetInFaction), race (GetRace) or limit to only one NPC (GetIsID),Restrict by Worldspace, City, Cell or distance from a particular chair, Restrict by Game Time, Season, Weather or progress of quest
Open up the topics tab, select the BGMMessage4u topic and highlight the response we added earlier.
 
Open up the topic tab, select the message4u topic and highlight the response we have added earlier.


At the bottom of the window is the condition box.  
At the bottom of the window is the condition box.  
Again we can use Right Click-New to add conditions or we can click on the new button at the bottom of the tab page.
Again we can use Right-click + New to add conditions, or we can click on the New button at the bottom of the tab page.


The organisation of these is the same as the quest conditions we set before.
These conditions are just like the ones we used in Quest Data before.


The default position is to add a topic to all NPC’s and we need to use the conditions to reduce this number.  
By default, all NPCs will have our new topic available. We need to use conditions to choose which NPCs can or can't display our topic.
 
Again what conditions you apply is up to you, and the nature of the topic and response.
This particular topic is a general one and we want to set some general conditions just to reduce the number of NPCs that can use it.  
This particular topic is a general one and we want to set some general conditions just to reduce the number of NPC’s that can say it.  


First let’s get rid of a number of races. Why?  
First let's get rid of a number of races. Why?  
Well in the middle part of the window is the response box.  
Well, in the middle part of the window is the response box.  
Double click on the response to the message4u topic to re-open the pop-up response dialog box.  
Double click on the response to the BGMMessage4u topic to re-open the pop-up response dialog box.  
Have a look at the lower section and you can see a long list.
Have a look at the lower section and you can see a long list.
   
   
This is the list of expected MP3 files which we would need to create. It is very long.
This is the list of expected MP3 files which we would need to create. It is very long; it expects both a male and female response for every single race.  
It expects both a male and female response for every race.  


We can remove some of these to make our life easier later on
We can remove some of these to make our life easier later on, when it's time to record.


Select new in the condition box with this response highlighted.
Select New in the condition box with the response "I hear a lawyer named..." highlighted.


In the function drop down menu, scroll down to the function GetInRace.
In the ''Condition Function'' drop down menu, scroll down to the function [[GetIsRace]].  
The function parameter box now reads invalid.  
Click on the ''Function Parameter'' box and a list of races will be displayed. These are the valid parameters for this function.  
Click on this and a list of playable races is display.  
Select "Argonian" from the list.  
Select Argonian from the list.  
The comparison reads == by default, so you can leave that unchanged.
The comparison reads == which is correct.  
The value current reads 1.0000. This is value the function [[GetIsRace]] would give if the character's race was in fact "Argonian".  
The value current reads 1.000. This is mathematic speak for a true response.  
We want to change this to the negative response: 0.0000.
We want to change this to the false response 0.000.


The Condition now reads
In English this means:
In English this means.


Look at the Actor who might say this response. Check what race they are in. If they are not an Argonian (Argonian== 0.000) then carry on.  
Look at the Actor who might use this response. Check what race they are. If they are not an Argonian, then carry on.
If they are an Argonian they fail this condition and they cannot say this line.
Otherwise, they are an Argonian and should not be able to use this line.


(Note the condition Argonian == 0 is mathematically the same as Argonian != 1)
(Note that the condition Argonian == 0 is logically equivalent to Argonian != 1)


Now, let’s add a few more Race conditions.  
Now, let's add a few more Race-based conditions.  
Right click in the condition box.
Right-click on the condition we just created and copy it using the Copy option from the menu.
Select the condition and copy it using the options in the menu.  
Now right-click again and paste.  
Now right click and paste.  
We now have an exact copy of our condition.  
We now have an exact copy of our condition.  


In the parameter box click on it and change the race to Elf.  
Click on the parameter box and now choose "Elf".
We now have two races excluded.  
We now have two races excluded.


Repeat this process to exclude the other races, until we are left with Bretons, Redguards Imperials and Nords. (I.e. the Human Races).  
Repeat this process to exclude the other races, until we are left with Bretons, Redguards, Imperialsm and Nords (i.e. the Human races).


Is this some sort of cultural imperialism on my part?  
Is this some sort of cultural imperialism on my part? No, it's just that I reckon I could add an MP3 file which might sound passable for those races. Orcs, Argonians, and Khajiits have unique voice types that are harder to replicate. It is a matter of style and choice. If you want to extend the range, do so.


No It’s just I reckon I could add an MP3 file which might sound passable in these races. Orcs, Argonians, and Khajiits have unique voice types that are harder to replicate. It is a matter of style and choice. If you want to extend the range do so.  
We call these conditions "exclusive conditions" because they exclude a group or individual from using that response.


We call conditions set to == 0 as exclusive conditions since they exclude a group or individual from being in that response.
We also want to limit the in-game locations where these lines are valid.  


We also want to limit the places that these lines are valid.  
All major locations, including the cities, have special "dummy cells" created to allow us to use a single condition on many individual locations. The game searches for cells with a given text string at the beginning of its name. So if we select a cell called "IC", it actually triggers every cell that begins with "IC". Everything from ''ICPalaceLibrary'' to ''ICTalosPlazeTheTiberSeptimHotelUpstairs''.


Again I could have chosen any number of locations.  
If you called a cell Icnatta or something else that also begins with "IC", even though this cell might have nothing to do with the Imperial City, the catch all nature of the "IC" description means that that cell will also be triggered. This would conflict with the Imperial City's naming prefix. This means we do need to be careful when naming cells.
It also means that we can use this trick ourselves. If we create huge mods that add towns or cities, we can use prefixes in the same way. By carefully naming all my external and interior cells VeronaHouseSomethingorOther, we could then create a "dummy" (i.e., completely empty and unused) cell called VeronaHouse, which would allow us to use VeronaHouse in condition statements and identify if something was anywhere in the Verona House area.


I choose the Imperial City because it is after all the Capital, and most PC’s will at some time visit the City. It is as ever about style rather than technique and you are free to choose your own path. All major locations, including the Cities have special cells created to allow us to do conditions easier.  
I choose the Imperial City (again, I could have chosen any number of locations) because it is the Capital, and most players will at one point or another visit the City. It is as ever about style rather than technique and you are free to choose your own path.  


The game then searches for cells with that text string at the beginning. So by selecting a cell called IC, it actually triggers every cell which begins IC even if that cell then has a lot of other text after it.  
In the condition box select New.  


If you called a cell Icnatta or some such, even though this cell might be nothing to do with the Imperial City the catch all nature of the ‘IC’ description means it will be considered as part of the Imperial City. This means we do need to be careful when naming cells.  
Now select condition function [[GetInCell]].
It also means of course that we can use this trick if we create huge mods that add towns or cities. By carefully naming all my external and interior cells VeronaHouseSomethingorOther, I could then create a dummy, or completely empty cell called VeronaHouse, which would allow me to use VeronaHouse in condition statements and identify if an event or character was taking place in the Verona House area.
The parameter for this is initially invalid until we click on it select a cell from the menu. You can only select cells that are named and unique. Notice that all those exterior cells called "Wilderness" don't show up. If you wish to use an exterior cell, you must give it a unique name.  


In the condition box select new.  
Set the condition to test. (This is an inclusive condition, since it includes a group in that response.)


Now select condition function GetInCell.
Another way to select groups is by using [[faction]]s (see lesson 7 for more details on creating a Faction)
The parameter for this is again initially invalid until we click on it and from the drop down menu select a cell. You can only select cells that are named and unique. Notice all those exterior cells called wilderness don’t show up.If you wish to use an exterior cell you must give it a unique name.  
One such faction is the ICFaction. It groups all the NPCs who are considered citizens of this city. It is a useful way to distinguish between the merchants, soldiers, and workers of the capital and a tourist from Chorrol who is passing through.


Set the condition to test
Set up a new condition.  
This is an inclusive condition, since it includes a group in that response.  


Another way to select groups is by using factions (see lesson 7 for more details on creating a Faction)
Choose the [[GetInFaction]] function, and then choose the ''ICFaction'' from the list to get a new condition.
Finally, we want to exclude our NPC Vilanus Villa from using these lines. It would be awfully silly if Vilanus himself told us, "I hear a lawyer named Vilanus Villa is looking for you."
One such faction is the ICFaction. It groups all the NPC’s who are considered citizens of this city. It is a useful way to distinguish between the merchants’, soldiers, and workers of the capital and a tourist from Chorrol who is passing through. We can use this to again include or exclude factions
To do this we use the condition function [[GetIsID]].  
Then from the parameter list we select BGVilanusVilla.
Remember to set the value to == 0 (or != 1) so that your condition EXCLUDES him.


Set up a NEW condition.  
Finally, we want to set a condition that removes this topic from all potential speakers once we have met Villa.


Choose the GetInFaction function, and then choose the ICFaction from the list to get a new condition
Create a new condition.  
Finally we want to exclude our NPC Vilanus Villa from saying these lines. This is why we added him to the game first.
Choose the [[GetStage]] Function, then select our quest (BGM001) from the list. Change the 'Comparison' to < (less than), and the value to ten.
To do this we use the condition function GetIsID.
This runs a check to ensure the PC hasn't advanced at all in the quest, effectively removing it from all NPC's if it has.
Then from the parameter list select BGVilanusVilla.
We can then set the value to 0 to get
Finally we want to set a condition that removes this topic from all potential speakers once we have met Villa.  


Try this yourself
==Adding Topics==
[b]Adding Topics[/b]


We also want to add a new topic as a result of this response.  
We also want to add a new topic as a result of this response.  


First create a new topic called BGVilanusVilla using the method we have just used (Right Click-New). You can leave the response blank for now.
First create a new topic called BGMVilanusVilla using the method we have just used (Right Click-New). You can leave the response blank for now.


On the Right hand side of the Topic Tab window are three boxes called
On the Right hand side of the [[Topics Tab]] window are three boxes called


Add Topic:
;Add Topic
This is used to add a topic to the players learned list. Once added it can be accessed using the topic menu when we click on an NPC. The player can then decide whether or not to click on this.
This is used to add a topic to the players learned list. Once added it can be accessed using the topic menu when we click on an NPC. The player can then decide whether or not to click on this.


Add Choices:
;Add Choices
This adds a list of FORCED choices to the topic menu. All other options are removed, and the player must make a choice to proceed.
This adds a list of FORCED choices to the topic menu. All other options are removed, and the player must make a choice to proceed.


Add Links from:
;Add Links from
This adds a single FORCED topic which again forces the player to select that option to proceed. It links to a previous response. By using this we can set up long forced conversations.
This adds a single FORCED topic which again forces the player to select that option to proceed. It links to a previous response. By using this we can set up long forced conversations.


It is probably best to use the Add Topic box, on this occasion, so we can use the topic several times. Again a bit of preplanning will allow you to use the same topic for several purposes.  
It is probably best to use the Add Topic box, on this occasion, so we can use the topic several times. Again a bit of preplanning will allow you to use the same topic for several purposes.  


Now go back to the Message4u topic and in the Add Topic box to the right, right click and add the BGVilanusVilla topic. Now when we talk to an NPC about the message we will have a new topic added to our learned list called BGVilanusVilla. It won’t show up in the game right now as we have no valid responses.
Now go back to the BGMMessage4u topic and in the Add Topic box to the right, right click and add the BGVilanusVilla topic. Now when we talk to an NPC about the message we will have a new topic added to our learned list called BGVilanusVilla. It won't show up in the game right now as we have no valid responses.


Finally in the result script box type the following.
Finally in the result script box type the following:
Now click the COMPLILE button.
<pre>SetStage BGM001 10</pre>
Now click the COMPILE button.


This executes a stage bump. The quest is now set at STAGE 10
This executes a stage bump. The quest is now set at STAGE 10


Let’s summarise what we have for this first topic
Let's summarise what we have for this first topic
I’ll use these summaries throughout these tutorials as a direction for you to use. I have used this table as a template when planning my own quests and found them really useful. Remember if you get stuck refer to the PLAY TEST version to see how it should look.
{| class="wikitable" border="1" cellpadding="5"
!colspan=2|'''BGMMessage4u'''
|-
!  TOPIC
|  Message for you
|-
!  RESPONSE
|  I hear a lawyer named Vilanus Villa is looking for you.
|-
!  CONDITIONS
|
* GetIsRace 'Argonian' == 0, etc.<br>
* GetInCell 'IC' == 1<br>
* GetInFaction 'ICFaction' == 1<br>
* GetIsID 'BGVilanusVilla' == 0<br>
* GetStage 'BGM001' < 10<br>
|-
!  ADD TOPICS
|
* BGVilanusVilla
|-
!  RESULT SCRIPT
|
SetStage BGM001 10
|} 
I'll use these summaries throughout these tutorials. I have used this table as a template when planning my own quests, and I find it really useful. Remember, if you get stuck refer to the PLAY TEST (BGModTutPlayTest) version to see how it should look.


[b]Stage Update[/b]
==Stage Update==


Now return to the quest stage tab.
Now return to the quest stages tab.


We have now progressed through the quest to stage 10. We can of course leave this blank. Sometimes we want to stage bump simple to activate/deactivate conditions that use the GetStage function.  
We have now progressed through the quest to stage 10. We can of course leave this blank. Sometimes we want to stage bump simply to activate/deactivate conditions that use the GetStage function.  
However, we can also use this stage bump to do a few things. We can add a quest stage result script to carry out some script instructions relating to the quest and we can add a Journal entry.  
However, we can also use this stage bump to do a few things. We can add a quest stage result script to carry out some script instructions relating to the quest and we can add a Journal entry.  
Let’s do this. It’s the same old routine. Right Click and new in the Log Entry box. Add a suitable bit of text like.
Let's do this. It's the same old routine. Right Click and new in the Log Entry box. Add a suitable bit of text like:


I have been told a lawyer called Vilanus Villa is looking for me. I should find out where he is staying. He may have important news for me.
''I have been told a lawyer called Vilanus Villa is looking for me. I should find out where he is staying. He may have important news for me.''


Ok we have now added a topic called [b]Messgae4u.[/b]
Ok, we have now added a topic called ''BGMMessage4u''.


For now save and go test.  
For now, save and go test.  


You should now find that this topic only appears for human characters in the Imperial City. Try in other locals like Anvil etc to make sure. When your down come back and we can move on.
You should now find that this topic only appears for human characters in the Imperial City. Try in other locales like Anvil, etc. to make sure. When you're done, come back and we can move on.


When you click on the Message for you topic in the game the topic Vilanus Villa will now automatically be added.  
When you click on the ''BGMMessage4u'' topic in the game the topic Vilanus Villa will now automatically be added.  


I don’t intend to continue to give you a click by click method fro every topic and response. Remember the basic idea of right click and select.
I don't intend to continue to give you a click-by-click method for every topic and response. Remember the basic idea of right click and select.


Let’s move on.
Let's move on.


Select the BGVilanusVilla topic we added earlier and add a response (See table below). This response should direct the player to the Talos District of the Imperial City.  
Select the ''BGVilanusVilla'' topic we added earlier and add a response (See table below). This response should direct the player to the Talos District of the Imperial City.  


We need some conditions.  
We need some conditions.  


Since this is a direct follow-on from message for you, we can use the same conditions to do the job.  
Since this is a direct follow-up from'BGMMessage4u'', we can use the same conditions to do the job.  
In the Message for you condition box, right click and select copy all conditions and then paste these into the BGVilanusVilla response.  
In the ''BGMMessage4u'' condition box, right click and select copy all conditions and then paste these into the ''BGVilanusVilla'' response.  


This response is fine unless of course we are already in the Talos district.
This response is fine, unless we're talking to someone who's already in Talos Plaza.
   
   
We need to add one more condition to account for this using the GetInCell function.
We need to add one more condition to account for this by using the [[GetInCell]] function. We also need to update the stage values that [[GetStage]] checks for.
For this topic we need to add another response.
Right click and select new in the info box.
This one should direct the player to the Imperial Hotel where we placed Vilanus Villa. Again we can copy the conditions across by using the copy and paste method, and then change the last condition to 1


{| class="wikitable" border="1" cellpadding="5"
If you wanted to get really flashy we could add another response for the occasions when we ask NPC’s about Vilanus Villa in the hotel itself.  
!colspan=2| '''BGMVilanusVilla'''
However, I have not done this to save a bit of time. Feel free to try this yourself. A response like ‘Yeah I’ve seen him around here.’ would do.  
|-
Don’t forget to copy the conditions and alter the GetInCell parameter.
!  TOPIC TEXT
|  "Vilanus Villa"
|-
!  RESPONSE
|  "I believe he's staying in Talos Plaza."
|-
!  CONDITIONS
|
*GetIsRace 'Argonian' == 0, etc.
*GetInCell 'IC' == 1
*GetInFaction 'ICFaction' == 1
*GetIsId 'BGVilanusVilla' == 0
*'''GetStage 'BGM001' < 20'''
*'''GetInCell 'ICTalosPlaza' == 0'''
|-
!  ADD TOPICS
|  ''No add topic''
|-
!  RESULT SCRIPT
|  ''No script''
|}


[b]Using the GREETING topic[/b]
We should also add responses that only work inside Talos Plaza. This next one should direct the player to the Imperial Hotel where we placed Vilanus Villa. Again, we can copy the conditions by using the copy and paste method, and then change the last condition (GetInCell 'ICTalosPlaza') to 1. (You could also duplicate the entire response by right-clicking and selecting copy, and then edit the duplicate from there.)


Another way to pass on information via dialogues is to use the GREETING topic. If you remember the discussion in lesson four about how conversations work, all dialogues begin with a GREETING, which is selected by the game from the GREETING topic.  
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGMVilanusVilla'''
|-
!  TOPIC TEXT
|  "Vilanus Villa"
|-
!  RESPONSE
|  "I believe he is staying in the Tiber Septim Hotel."
|-
!  CONDITIONS
|
*GetIsRace 'Argonian' == 0, etc.
*GetInCell 'IC' == 1
*GetInFaction 'ICFaction' == 1
*GetIsID 'BGVilanusVilla' == 0
*'''GetStage 'BGM001' < 20'''
*'''GetInCell 'ICTalosPlaza' == 1'''
|-
!  ADD TOPICS
|  ''No add topic''
|-
!  RESULT SCRIPT
|  ''No script''
|}
 
If you wanted to get really flashy you could add another response for the occasions when we ask NPCs about Vilanus Villa inside the hotel itself. However, I have not done this to save a bit of time. Feel free to try this yourself. A response like "Yeah I've seen him around here." would do. Don't forget to copy the conditions and alter the GetInCell parameter. Also remember that [[GetInCell]] matches the beginning of the cell strings, so you should add another [[GetInCell]] condition to the second response which excludes the Hotel cell (so that the response "I believe he is staying in the Imperial Hotel." shows up everywhere in Talos Plaza EXCEPT for the hotel itself).
 
==Using the GREETING topic==
 
Another way to pass on information via dialogues is to use the GREETING topic. If you remember the discussion in Lesson 4 about how conversations work, all dialogues begin with a GREETING, which is selected by the game from the GREETING topic.  
If we add our own greeting and set the right conditions we can force a start to a dialogue.  
If we add our own greeting and set the right conditions we can force a start to a dialogue.  
In the topic tab select Right Click-Add and add GREETINGS. This already exists so you will not need to create a new topic when the list appears.
In the topics tab add GREETING. This topic already exists, so you will not need to create a new topic when the list appears.


We can now add Vilanus Villa’s little speech.  
We can now add Vilanus Villa's little speech.  
This is quite along response so we should split it up.
This is quite a long response so we should split it up to reduce the amount of text that appears on the screen at any given time.  
This reduces the amount of text that appears on the screen at any one time.  
Add this response first to the GREETING topic. Note this is blank because there are no GREETING responses added by this quest yet.
Add this response first to the GREETING topic. Note this is blank because there are no GREETING responses added by this quest yet.


[i]Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news[/i]
''Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news.''


Now click OK to add the response.
Now click OK to add the response.


Then in the centre response details box, not the upper info box, right click and add a new response. You’ll get a new interface to write in.
Then in the ''Response Details'' box (not the upper info box), add a new line of response text. You'll get a new interface to write in.


[i]Your uncle has passed away peacefully in his sleep.[/i]
''Your uncle passed away peacefully in his sleep.''


Then add another
Then add another:


[i]I have been asked to look after his last will and testament[/i]
''I have been asked to look after his last will and testament.''


We can go adding new lines to this response info if we wish. In the top box we can see the number of responses increments to 3. The text appears in the top box as.
We can go on adding new lines to this response info if we wish. In the top box we can see the number of responses increments to 3. The text appears in the top box as:


Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news||
''Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news. || Your uncle passed away peacefully in his sleep. || I have been asked to look after his last will and testament.''
Your uncle has passed away peacefully in his sleep. || I have been asked to look after his last will and testament


With the || indicating the separate lines of this single response info
With the || indicating separate lines of this single response.


We need to add some conditions, to control who says these lines. This is very important when using the GREETINGS topic as this is so wide spread within the game. While it is silly that every character could respond to Message4u, it is dangerous to have an unconditional greeting as this might override evry other Greeting in the game and prevent other quests from running as intended.
We need to add some conditions, to control who says these lines. This is very important when using the GREETINGS topic as this is so wide spread within the game. While it is silly that every character could respond to ''BGMMessage4u'', it is dangerous to have an unconditional greeting, as this might override every other greeting in the game and prevent other quests from working properly.


Limiting a response to just one character is easier than using groups.  
Limiting a response to just one character is easier than using groups.  


We can use the GetIsID function.  
We can use the [[GetIsID]] function for this.  


We need to have an NPC reference which is why we built BGVilanusVilla first. We will also restrict this response to the opening stage of our quest.
We need to have an NPC reference, which is why we built ''BGVilanusVilla'' first. We will also restrict this response to the opening stage of our quest.


[b]QuestStage BGM001==10
* '''GetStage 'BGM001' <= 10'''
GetIsID BGVilanusVilla==1
* '''GetIsID 'BGVilanusVilla' == 1'''
[/b]


Now we want to add a new topic called BGWill. However, there is an issue, and many thanks to Hecks for pointing this out, when adding topics to the GREETING or indeed any existing Bethusda topic. For technical reasons, the topic might not get added if more than one plug-in is attempting to use GREETING to add a topic.
Now we want to add a new topic called ''BGWill''. However, there is an issue (and many thanks to Hecks for pointing this out) when adding topics to the GREETING or indeed any existing Bethesda topic. For technical reasons, the topic might not get added if more than one plug-in is attempting to use GREETING to add a topic.
i'll be honest and say I don't know why this happens. It's not difficult to work around once you know the issue exists. When I found out it took me thirty seconds in the CS to fix.
I'll be honest and say I don't know why this happens. It's not difficult to work around once you know the issue exists. When I found out it took me thirty seconds in the CS to fix.


First create a new topic which we can reference called BGWill (Right Click etc).  
First create a new topic called ''BGWill''.  


Now add this by now familiar script function to the result script for this info response.
Now add this to the result script for the GREETING response.


AddTopic BGWill
AddTopic BGWill


Job Done.
Job Done.


The speech that Villa gives contains a lot of exposition, and we don’t want to force the player to repeat this every time.  
The speech that Villa gives contains a lot of exposition, and we don't want to force the player to repeat this every time.  


We can stop this by setting up what I call a conditional pair of responses.
We can stop this by setting up a pair of conditional responses.


[b]Conditional Pairs[/b]
==Conditional Pairs==


These are a very common device used throughout the official quests. We set up two response infos to the same topic. We then use a quest variable or a function condition to control which of the two responses is said.  
These are a very common device used throughout the official quests. We set up two response infos to the same topic. We then use a quest variable or a function condition to control which of the two responses is said.  


These might take the form
These might take the form
<pre>
Response 1: Long Explanation
Response 2: Short Explanation


Response 1:- Long Explanation
Response 1: Female PC Response ‘Morning Ma'am'
Response 2:- Short Explanation
Response 2: Male PC Response ‘Morning Sir'


Response 1:- Female PC Response ‘Morning Ma’am’
Response 1: ‘Ah you've found the widget my friend'
Response 2:- Male PC Response ‘Morning Sir’
Response 2: ‘You must find the widget my friend'
</pre>
Let's try this


Response 1:- ‘Ah you’ve found the widget my friend’
Add a new variable called MetVilla to the top of the Quest Script (under the quest data tab). We should declare any variables used by the quest in the Quest-type script.
Response 2:- ‘You must find the widget my friend’


Let’s try this
<pre>
SCN BGM001QuestScript
Short DoOnce1
Short MetVilla


Add a new variable called MetVilla to the top of the Quest Script (under the quest data tab). We need to declare any variables used in results scripts in the quest script . Think of the results scripts as children of the parent quest script. We declare the childs variables in the parent script.
Begin GameMode
 
If (DoOnce1 == 0)
AddTopic BGMMessage4U
Set DoOnce1 to 1
EndIf
 
End
</pre>


This is automatically set at zero. We can use the response result box to bump this up to one after speech with this bit of script .
This variable will be automatically set to zero. We can use the response result box to bump this up to one after the speech with a bit of script. Add this in after "AddTopic BGWill".


[b]Set BGM001.MetVilla to 1[/b]
  Set BGM001.MetVilla to 1
 
Don't forget to click the compile button!
 
Summarising the first response:
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''GREETING'''
|-
!  TOPIC TEXT
|  GREETING
|-
!  RESPONSE
* "Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news."
* "Your uncle has passed away peacefully in his sleep."
* "I have been asked to look after his last will and testament."
|-
!  CONDITIONS
|
*GetStage 'BGM001' <= 10
*GetIsID 'BGVilanusVilla' == 1
*'''GetQuestVariable 'BGM001.MetVilla' == 0'''
|-
!  ADD TOPICS
| ''No add topic''
|-
!  RESULT SCRIPT
|
AddTopic BGWill
Set BGM001.MetVilla to 1
|}
 
 
We can then add this alternative response info to the GREETING topic:
 
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''GREETING'''
|-
!  TOPIC TEXT
|  GREETING
|-
!  RESPONSE
|  "Whenever you want to talk about your uncle's will, let me know."
|-
!  CONDITIONS
|
*GetStage 'BGM001' <= 10
*GetIsID 'BGVilanusVilla' == 1
*'''GetQuestVariable 'BGM001.MetVilla' == 1'''
|-
!  ADD TOPICS
|  ''No add topic''
|-
!  RESULT SCRIPT
|  ''No script''
|}


Don’t forget to click the compile button.


Summarising the first response
We can then add this alternative response info to the GREETING topic
The first time we greet him he gives the longer speech, the second time a shorter one.
The first time we greet him he gives the longer speech, the second time a shorter one.


We can now add another multi line response info to the BGWill topic added by the first response.  
We can now add response info to the ''BGWill'' topic.


Try this one yourself using this summary to guide you.  
Try this one yourself using this summary to guide you.  
Don’t forget the quest bump script.  
Don't forget the quest bump script.  
You will need to add a new topic called BGHubart.
You will need to add a new topic called ''BGHubart''.
Again we have a stage bump, this time to Stage 20
{| class="wikitable" border="1" cellpadding="5"
Add to the Quest Stage a journal update
!colspan=2| '''BGWill'''
|-
!  TOPIC TEXT
|  "My uncle's will"
|-
!  RESPONSE
* "Apparently your uncle had some property here in Cyrodiil. I'm not sure where, though."
* "I was expecting a courier to deliver the details, but she hasn't shown up."
* "Captain Hubart of the Chorrol Guard notified me that the courier never made it to her stop in Chorrol."
* "You will have to visit him in Chorrol to find out more about what's going on. Here's the letter he sent me."
|-
!  CONDITIONS
|
*GetStage 'BGM001' <= 10
*GetIsID 'BGVilanusVilla' == 1
|-
!  ADD TOPICS
|
*BGHubart
*BGMVilanusVilla (In case the player talked to Vilanus before using the "Message for you" topic)
|-
!  RESULT SCRIPT
|
SetStage BGM001 20
|}
 
Again we have a stage bump, this time to stage 20.
In the Quest Stages tab, add a journal entry for stage 20.


[i]I have been told that I may have inherited some property, but the courier carrying the details has gone missing. I will need to go to Chorrol and speak to a Captain Hubart of the Chorrol guard to get more details
''I've been told that I may have inherited some property from my late uncle, but the courier carrying the details has gone missing. I will need to go to Chorrol and speak to a Captain Hubart of the Chorrol Guard to get more information.''
[/i]


We will also add a Quest Stage Result Script.
We will also add a Quest Stage Result Script.
Line 994: Line 1,138:
But first we need to create a prop letter, so we can refer to it in the script.
But first we need to create a prop letter, so we can refer to it in the script.


Again we can create a ‘new’ item, but it means trying to add artwork to the game, and unless we want the letter or scroll to look completely unique, and have some talent in that direction, it is a chore we don’t need to do.
Again we can create a new item from scratch, but it means trying to add artwork to the game. Unless we want the letter or scroll to look completely unique, and have some talent in that direction, it is a chore we don't need to do.
 
Instead, select any letter from the Items->Book list in the object window, change its ID to something meaningful like ''BGHubartLetter''.


Instead select any letter from the object/items/books list in the object window, change its ID to something meaningful like ‘BGHubartLetter’
The text on the right hand side indicates the content of the letter. We can edit this. I will look at the precise details and syntax needed to produce text in another lesson. It uses standard HTML tags.
For now, the key command is <nowiki><br></nowiki>, which produces a 'line break' or 'new line'. The font face can be left alone.


The text on the right hand side indicates the content of the letter. We can edit this. I will look at the precise details and syntax needed to produce text in  another lesson.  
'''BGHubartLetter'''
It uses standard HTML instructions.
<pre><nowiki>
For now the key command is <br> which produces a line break, or new line. Leave the font face alone.
<font face=5><br>
Dear Vilanus,
<br>
<br>
I regret to inform you that the White Horse courier Janus Jakobs, who you asked me to meet, has not arrived for her expected rendezvous. I know you were expecting some important documents to arrive.<br>
<br>
I don't have enough man power to launch a search; perhaps you could find someone willing to assist me in finding Jakobs?
<br>
<br>
I look forward to hearing from you, old friend.
<br>
<br>
Yours,
<br>
Captain Hubart
</nowiki></pre>
Save the letter, AND MAKE SURE YOU CLICK 'YES' TO CREATE A NEW FORM.


BGHubartLetter
Now, type this in the results script box for stage 20:
Save the letter as a new form.
Of course you are free to use your own text instead.


Now type this in the results script box for Stage 20 and compile it using the button below.
  Player.AddItem "BGHubartLetter" 1
[i]
Player.additem "BGHubartLetter" 1[/i]


We can also add a new response info to the topic called BGHubart, to direct the player to Chorrol
Then click the "Compile Result" button.


We can also add a new response info to the topic called ''BGHubart'', to direct the player to Chorrol:
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGHubart'''
|-
!  TOPIC TEXT
|  Captain Hubart
|-
!  RESPONSE
|  "You’ll find him in Chorrol."
|-
!  CONDITIONS
|
*GetStage 'BGM001' == 20
*GetIsID 'BGVilanusVilla' == 1
|-
!  ADD TOPICS
|  ''No add topic''
|-
!  RESULT SCRIPT
|  ''No script''
|}


Try this for yourself. You can always refer to the PLAYTEST version if you get stuck.  
Try this for yourself. You can always refer to the PLAYTEST version if you get stuck.  


We have completed phase one, now we move to Chorrol.
We have completed phase one. You should stop to test everything out before moving on. Just test a few conditions to make sure that everything is working, and that you haven't made any small mistakes.
 
==Chorrol Phase==
 
In this phase of the quest we want to use a new NPC called Captain Hubart to direct the player to solve a mystery. He will direct the player to a cottage, where they will discover a mysterious medallion and the dead body of the courier. Hubart will then be able to help us move on to Aleswell and the next phase.
 
For this phase, we will need to create:
*NPC Captain Hubart
*NPC Dead Courier
*NPC DummyPlayer
*A document
*A medallion
*A cottage to house courier.
 
Again, we need to add the NPC first so we can reference him in conditions.
 
As always, we could use a new NPC object, but it really saves a lot of time and effort if we simply change the name and ID of an existing one. This time we can just copy a Chorrol Guard NPC, such as ''ChorrolGuardPatrolNight01''. Change the ID to ''BGCptHubart'', and save it as a new form.
Strip out the AI, but leave his inventory as is, since the Chorrol guard's inventory already contains all we need. We can also leave the factions alone. I placed Hubart outside the Fire and Steel shop in Chorrol (worldspace ''ChorrolWorld'').<br />
''Hint: a fast way to get to an exterior cell is to select the interior cell, and then click on the teleport marker by the door.''<br />
This is only his starting position. We can add AI packages later to move the character about.
 
We have to set up a new response to the ''BGHubart'' topic.
 
We could add a new topic but it is always a good idea to try to limit how many new topics we add. This reduces the ‘footprint' of the mod, and helps avoid possible conflicts with other mods.
 
We want to set up a response so that when any Chorrol based NPCs are questioned they will direct the PC toward the likely location of the captain. Add conditions to limit the race to human again (saving all that MP3 work), and the location to the ''Chorrol'' dummy cell (thereby including all cells within Chorrol). We can also limit the ‘timescale' to the current quest stage (20). Try this yourself. You can always refer to the PLAYTEST version if you get stuck.
 
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGHubart'''
|-
!  TOPIC TEXT
|  "Captain Hubart"
|-
!  RESPONSE
|  "He's usually on duty near the Fire and Steel."
|-
!  CONDITIONS
|
*GetIsRace 'Argonian' == 0, etc.
*GetInCell 'Chorrol' == 1
*GetInFaction 'ChorrolFaction' == 1
*GetIsID 'BGCptHubart' == 0
*GetStage 'BGM001' >= 20
|-
!  ADD TOPICS
|  ''No add topic''
|-
!  RESULT SCRIPT
|  ''No script''
|}
 
We can now add some dialogue for Hubart himself.
 
The first can be attached to Vilanus Villa topic, to reduce the ‘footprint'.
 
First, add a TOPIC called ''BGCourier''.
 
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGMVilanusVilla'''
|-
!  TOPIC TEXT
|  "Missing courier"
|-
!  RESPONSE
|  "Vilanus has sent you to investigate the courier's disappearance?"
|-
!  CONDITIONS
|
*GetIsID 'BGCptHubart' == 1
*GetStage 'BGM001' == 20
|-
!  ADD TOPICS
*BGCourier
|-
!  RESULT SCRIPT
|  ''No script''
|}
 
Stop to test this out, and then refer to the PLAYTEST version if you are stuck.
 
Before we go any farther, we need to set the scene at the cottage.
 
==Locating the Cottage==
 
''If you are using BGModTutBase.esp, you can use these cells: BGModCourierCottage in the Interiors [[world space]], and CourierCottageExt in the Tamriel world space. The exterior building that matches the cottage is LeyawiinHouseLower03, and the door is LeyawiinLowerLoadDoor01.''
 
The cottage could be located anywhere in Tamriel. I think I've looked at just about every [[cell]] in compiling these tutorials and working on my mods. When selecting the location for this cottage, I took into account several factors. I wanted it to be West of Chorrol. I wanted it to be close to the main road. I knew I couldn't go too far as the road abruptly ends by a cliff, marking the edge of the world space. I also decided to use the game to give me a little bonus or two.
 
Around this location, is a dungeon with some external guardians, some bandits and an oblivion gate. This means any NPC will be harassed by bad guys that we don't have to work too hard to create.
 
We want to set the internal scene in readiness for the PC's arrival. I have used a copy of the White Stallion Lodge as a base. We want to customise this. Again we can work on this in more detail when we polish the quest prior to release.
 
We want to remove some of the clutter. We also want to give the impression a fight has taken place. Tips some chairs and tables over (Y=90). Remember this set will be locked at the start and you will only use it for a short time, so don't go overboard. We also want to place some props. We need an amulet to trigger the next phase. Why an amulet? It's small enough that you have to look for it, but not so small that it becomes hard to find. Copy an existing item of jewelry from Items->Clothing->Amulet as a base and edit it. Change the ID to ''BGEmbossedAmulet''. Check off the ''Quest Item'' box. The player can not drop or sell quest items.
 
We also want to create a custom letter called ''BGPartialLetter''. Set the letter as a quest item. We will refer to it in some scripts.
<pre><nowiki>
<br>
<font face=5><br>
Dear Vilanus,
<br>
<br>
The client wishes his only living heir in Cyrodiil to inherit his house. I have enclosed the deed and key. The location of the house is registered at the Imperial City Land Offices...<br>
<br>
<br>
<br>
LETTER IS RIPPED HERE
<br>
<br>
</nowiki></pre>
Of course it would look really cool if we could create a custom texture for a torn scroll, but that is beyond the scope of this tutorial.
 
Finally we need to place the body of the unfortunate courier.
 
Bodies are NPCs who just happen to be dead. You will need to create another NPC. Use ''Courier1'' as the base.
 
Place this character in the render window, set its ID to ''BGDeadCourierRef'', and position the corpse in a suitable place. I put her in a side room so you don't see her right away. I also left a nice blood trail to lead you to her. Initially, the NPC will be standing up.
 
Next click ''Edit Base'' to open the NPC window. Change the NPC's ID to ''BGDeadCourier''. Edit the NPC's health to read zero (0). (To access this stat, uncheck the ''PC Level Offset'' and ''Auto calc stats'' boxes.)
 
Now, the awkward thing is the fact that she is just standing there. She will stay standing in the game unless we make her fall first. To get her to fall, click on the WORLD menu and select ''Run Havok Sim'' (with the bouncing red ball). Down she goes.
 
We can now drag her about to get the position right.
 
I also placed a sword which pointed directly at the amulet.
 
Next, we have to add the letter to the dead courier's inventory. Open the NPC window for ''BGDeadCourier'' and click on the ''Inventory'' tab. Then drag ''BGPartialLetter'' from the objects window over into the inventory list. You will be warned that the letter is a quest item. Just click OK.
 
Another useful technique is to create an NPC called something like ''BGDummyPlayer''. We will not place this NPC in the world, so don't bother to edit anything other than the object ID.
 
We can now set the ownership of the door and cell ([[A_beginner's_guide,_lesson_3_-_The_external_world#Matching_Interiors|Lesson 3]]) to ''BGDummyPlayer''. This means that all items in the cottage will display the red hand, with the exception of the embossed amulet. This is a handy way to set ownership without having to create detailed NPCs. We can use ''BGDummyPlayer'' to set the ownership of all the doors and sets we want to prohibit our player from entering.
 
Now create a key called ''BGCourierKey''. Select an existing key and change the editor ID. Also check the ''Quest Item'' box. Edit the cottage door to set its lock status to "Needs a key", and use our new object as the key.
 
We need to add two other items to the cottage.
 
We need to add an [[XMarker]] to the interior, and a [[map marker]] to the exterior.
 
We will find these under the Static Objects.
 
Drop an XMarker or an [[XMarkerHeading]] object inside the cottage and give it a reference name like ''BGCourierLodgeXMarker''.
 
Now select a MapMarker and drop it just outside the cottage door, in the exterior cell. It looks a bit like a door teleport marker, but it's pink rather than yellow.
 
Edit its details to give it a reference name like ''BGCourierLodgeMapMarker''.
 
Open up the MapMarker Data tab, check the marker data tick box and select settlement.
Theses flags control what type of icon appears on the players map.
 
Finally in the name box call it Courier Cottage. This is the name that will appear on the map.
 
We need to add a bit of script to enable it. First we need to add a bit more conversation.
 
Add stage 30 in the stage tab, and create a topic named ''BGCluesFound'' (which we won't be editing just yet).
Then create the following topic.
 
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGCourier'''
|-
!  TOPIC TEXT
|  Courier
|-
!  RESPONSE
* "She's usually very reliable, but she failed to turn up for our usual meeting."
* "She sometimes stays in a small cottage just west of here. I'll mark it on your map."
* "Here's a key to get you in. Let me know what you find out."
|-
!  CONDITIONS
|
*GetIsId 'BGCptHubart' == 1
*'''GetStage 'BGM001' == 20'''
|-
!  ADD TOPICS
|
*BGCluesFound
|-
!  RESULT SCRIPT
|
SetStage BGM001 30
|}
 
Add one more response to this topic in case the player tries to talk to Hubart again after they've been given the key to the cottage, but before they've found it.
{| class="wikitable" border="1" cellpadding="5"
!colspan=2| '''BGCourier'''
|-
!  TOPIC TEXT
|  Courier
|-
!  RESPONSE
"Did you check out the cottage?"
|-
!  CONDITIONS
|
*GetIsId 'BGCptHubart' == 1
*'''GetStage 'BGM001' == 30'''
|-
!  ADD TOPICS
| ''No add topic''
|-
!  RESULT SCRIPT
| ''No script''
|}
 
Now in the stage tab for stage 30, add this to the journal:
 
''Hubart told me that the courier sometimes stays in a small cottage just west of Chorrol. He marked its location on my map and gave me a key to the door. I should go check it out.''
 
And add this to the stage result script:
 
Player.AddItem "BGCourierKey" 1
ShowMap BGCourierLodgeMapMarker
 
This gives the player the key to the cottage and activates the map marker.
 
The syntax for the [[ShowMap]] Function is
 
ShowMap MapMarkerID, enableFastTravel (optional)
 
The MapMarker ID is the reference id for the map marker.
The enableFastTravel is an optional parameter which takes the value 1 if you want to be able to fast travel immediately to that location.
 
If enableFastTravel is not given (or set to 0) then you can not fast travel to that location until you've found it once.
 
We still need to add all the quest targets, and we'll use the XMarkerHeading for that.
 
Up 'til now we have been using dialogue to control progression, but now we need to begin using scripts more continue.
 
In [[A beginner's guide, lesson 7 - Using Scripts in Quests|Lesson 7]] we will complete the quest and focus on SCRIPTING.


This has been EDITED to take account of the add topic iss
[[Category:A beginner's guide]]

Latest revision as of 14:28, 21 December 2023


PreambleEdit

This is the Sixth in a proposed series of Tutorial Lessons aimed at teaching how to mod TES IV: Oblivion aimed at beginners. It will build up into a complete modding course. Don't worry, there are no exams (though, there is some homework). This version was written for use on the forum. The RTF version contains additional material that was left out due to formatting limitations.

FilesEdit

I have uploaded some files in a .zip which will be used to accompany the next few tutorials.

It contains:

A. BGModTutBase.esp: This contains a building, a farmhouse, and a dungeon that we will use as sets in lessons 6, 7 and 8. This file is referred to in the text as the BASE file.

B. BGModTutPlayTest.esp: This is the interim quest mod illustrating the stage you should have reached prior to polishing the mod. This is referred to in the text as the PLAYTEST file.

C. BGModAnvilCheat.esp: This is a small optional cheat mod to give users 5000 Septims to allow them to follow this tutorial if they have not yet completed the quest. (See Introduction to Lesson 4)

D. An RTF document containing the text for the first 7 lessons (as requested).

Download the mod files


Using this TutorialEdit

I suggest that you modify the CS configuration file to allow you to open multiple copies at the same time. (See Introduction to Lesson 3) Open one CS window for the PLAYTEST version. You can use this to look at the expected results of the mod. We will not edit this mod. Open a second window for the BASE version (unless you want to make your own buildings - then just make a new file). This window is for your working file.

IntroductionEdit

Well, we come to it at last. It is time for us to begin to create our own quest, to design our own NPCs, and to write our own scripts. Of course it's ridiculous to suggest that these tutorials alone will teach you everything you need to know. However, I hope by the time you finish the next few lessons you will be more comfortable with the key skills needed to create your own great works. The example quest that I am using is not intended as an example of ‘Good Practice'. I have designed it to illustrate techniques, not good quest writing. The actual details of this quest are fairly unimportant. What matters are the techniques we are using.

The next three lessons will work to develop a quality version of a quest. While we will do this exercise, I have designed the quest to allow us to focus on key skills as we go on. This lesson deals with the creation of dialogue. In lesson seven we will really turn our focus to scripting, although you will begin scripting in this lesson. The eighth lesson will complete the quest by focusing on AI and Audio.

I assume that you have completed lessons one to three, and that that you have at least read through the appendix section on the Quest Interface.

Our PlotEdit

Quests are the bedrock of Oblivion's game mechanics. We established a basic technique to progress quests in the quest walkthrough

  • Action
  • Set Stage
  • Set Conditions for next action.
  • Hiatus

We will try to use this wherever possible.

We need to tell a story. I have read lots forum posts that begin with the phrase ‘I have this great idea for a quest'. They then go on to explain an elaborate plot which is impossible to implement, especially for a beginner. Keep it simple to start with. The designers of the game have used simple plot devices again and again in their quests. These are

  • Go find an item and bring it back.
  • Go find a person and bring them back
  • Go find a person and kill them

and the really complex

  • Go find a person take him with you, then you kill another person, who has an item which you should then bring back.

All of these ideas are clichéd and obvious. But one of the reasons a plot become clichéd is because they work.

So here is my clichéd 'recover the item' plot line.

The player discovers that their uncle has sadly passed away. The terrible news is softened by the fact that the Uncle has left the player some property in his will. Unfortunately the courier bringing the details of where the property, is along with the key and deed has disappeared. The player has to investigate the disappearance. This will lead him to an encounter with a gang of thieves who the player will have to defeat to recover his house key and deed.

This is not the greatest plot ever, but it should allow us to cover all the main points. I have chosen to make this quest as close to the Bethesda's 'Oblivion' model as I can.

This means setting up lots of 'hand holding' journal entries and message boxes. I personally would leave a lot of these out in a 'real' mod, but that is a personal choice. For every player who wants more freedom of choice and a more obscure progress there are others who want as much help as possible.

This is at the extreme end of the hand holding scale. Please feel free to add or change any bit of the quest you feel is too helpful to the PC. Remember, this is a way to write a quest, but it is NOT the ONLY way. This tutorial illustrates techniques. I do not intend it to be a click by click guide. In fact I will as the tutorial progresses, be feeding you less and less information, and asking you to ‘fill in the blanks'

Pre-ProductionEdit

Let's get started then. You can use the base files I have provided or you can create your own. Don't forget to make the file active in the CS

You will need the following props or sets

  • A house, which will be our quest reward. Of course you can change the plot detail to make this reward anything you please.
  • A cave system, to act as the HQ for our baddies. Again I choose a cave system. You could just as easily make it a house, a castle or even an open air camp.
  • A cottage, to house the dead courier in. This could just as easily be a camp, a house or a room in an inn.

If you are using the base files these have already been added. If you are designing your own you can add these props now, or as and when you need them.

The quest is set in 6 locations

  1. In and around the Imperial City
  2. In and around Chorrol
  3. The Courier Cottage close to Chorrol
  4. The Village of Aleswell
  5. The Hideout of the Baddies
  6. Our Reward Home.

We will also need 5 named NPCs plus a few generic goons for our hero to fight.

Imperial City, Phase OneEdit

For convenience we will split the quest into a series of phases. These are artificial divisions, and are not a technical requirement

Phase Objectives
- In this phase we want to set up a dialogue which introduces the quest to the player character. We want the PC to visit an NPC called Vilanus Villa who will in turn give some exposition, before directing the PC to visit Chorrol.

If we breakdown the first section of the story to see what we need to do.

  • Create an NPC ‘Lawyer' who I have chosen to call Vilanus Villa.
  • Add a Topic/Responses that will direct the player to Villa
  • Add Topic/ Responses for Villa that will direct the player to Chorrol.
  • Add a ‘letter' prop to help sell the introduction.

We can add these in any order, as long as we link them correctly. There is no one way to do things.

However, one thing to consider is that any reference objects we wish to use in condition statements or scripts must exist before we can use them. For this reason it is probably best to start by adding our NPC to the game, because we will be using him as reference in some conditions.

Adding an NPCEdit

You can, of course, create an NPC from scratch. If you right click in the Actor section of the object menu and select NEW a new NPC interface pops up. However, you will have to edit every aspect of your new NPC, including animations, so there are many good reasons not to do this.

It is far easier to edit an existing NPC. We want Vilanus to be an Imperial, so let's select an existing NPC who is an Imperial. We don't actually have to choose an Imperial, but it saves us a job. Avoid NPCs with scripts attached. Again, you can do so but you will need to remove the script, which is an extra job. I usually look for NPCs who have either a 1 or a 0, preferably a 0, in the user column. This means they are hardly ever used in the game. Let's choose the actor called TestORMale as our base.

We will place our NPC in the Foyer of the Imperial Hotel in the Talos District (ICTalosPlazaTheTiberSeptimHotel in the Interiors world space). Again this is an arbitrary choice, based on the fact that Taverns, Inns, and hotels contain public spaces which are ideal for casual contacts. If we wished to use this NPC again, we could build him a house or office to work from.

Drag and Drop the base NPC into Render Window. F key him to get him in position.

Now double click on him to open up the details for this NPC reference. Then click "Edit Base" to edit the NPC itself.

Let's briefly look at the properties on the far left of this interface.

NPC Properties
ID Editor ID for this NPC. Must be unique.
Name NPC name as it will appear in-game.
Script Scripts can be attached to NPCs here.
Class Can be defined using the class interface from the menu bar.
Summonable Mainly used for creatures and defines them as able to be summoned.
Offset/PC Level Offset Used to set NPC level. Either a fixed value within a defined range, or offset against PC level.
Calc Min/Max These check boxes determine minimum and maximum levels for the NPC.
Race Choose the NPC's race from the drop-down menu
Female Used to toggle gender.
Combat Style Combat Styles influence NPC choices during a fight. (see lesson eight)
Death Item Used for special loot items that we don't want to show up until after an NPC is dead.
Essential Essential NPCs cannot be killed and are only knocked unconscious.
Respawn This NPC will respawn when the cell reloads if you check this.

Selecting "PC Level Offset" will lock or unlock the details in the stats tab.

First alter the NPC's ID to BGVilanusVilla and the name to Vilanus Villa.

We tend to prefix all items added by a mod with a suitable prefix, like BG or BGM. This help avoid any conflicts, in the unlikely event that another mod adds a character called Vilanus Villa.

This NPC's class is Barbarian. The actual class of a NPC will only affect auto-generated statistics, and has little bearing on the interaction between PC and NPC. However, it is easy to change this setting using the drop down list under class.

We will look at levels later on in this tutorial; for now leave it at level 8. The level of a character is only relevant in combat.

For now we want to get rid of all existing AI packages. We are deleting the AI because it makes initial play testing much easier. Without any AI the guy will stay put. We don't want to have to walk halfway across Tamriel to find him when we test the mod!

Open up the AI section by clicking on the AI button.

Delete all the AI packages using right-click + delete. (This only removes them from the NPC's list, it doesn't delete the actual package)

Now select and check the ESSENTIAL flag. We want to keep Vilanus alive for now.

We can also alter the inventory if we wish. Again, by careful pre-selection we can save ourselves a job. Remember to scroll across the information in the object window to select suitable characters that match your requirements as closely as possible, to reduce the amount of work you need to do.

We want Vilanus to be a rich merchant, so he should have some decent clothes. TestORmale fits the bill. We should also remove any weapons and armor from him, as he is supposed to be a lawyer. (Note that the Hammer may show up in the render window until you reload the window, but will not show up in the game.)

We can leave his faction details alone for now.

Finally you can play around with the face to get the look you want. For now, don't spend too much time on it. You can use the auto-generator to get a rough look. You can tidy this up later in the polishing phase.

Exit and create a new form by clicking yes. We now have a brand new NPC. We will have to do some work on him later, but he is in the game.

Creating the QuestEdit

In the top menu select CHARACTER. Then from the drop down menu select QUEST.

The quest window will open. We should be familiar with this from lessons four and five.

On the left hand side is the list of all the quests in the game. Place your pointer over this section and right click. A small selection window appears. Select NEW.

Another window pops up called New Form Editor ID This is the prompt for us to enter our Quest ID.

The ID is NOT the same as the quest name which will appear in the player's journal. This should be a short alpha-numeric name, with no spaces, that we can readily identify as a part of our mod. It must also be unique. I chose to name mine BGM001 (Beginners Guide Mod 1). When you're done, select OK.

We now have a quest. Let's look at out quest data tab.

We want to give our quest a name. This is the name that appears in the in-game journal entries. You can call it pretty much what you like. You can even use duplicate names, but that would be a bit confusing. I've chosen to call mine The Inheritance Denied.

If you remember from lesson 4, we need to choose an appropriate priority value.

We will select 50, as this is a miscellaneous quest.

The next set of decisions involves the three flags which were discussed in the appendix:

  • Start Game Enabled
  • Allow Repeated Conversation Topics
  • Allow Repeated Stages

These three tags control when and how often scripts are run.

For now let's go ahead and select the standard Start Game Enabled and leave blank the Repeated Conversations & Stages. Now have a look at the table at the below, which contains quest conditions.

Quest ConditionsEdit

At the moment this is blank. We are going to input a condition which has the effect of limiting any conversations and dialogue topics we create in this quest to characters we would expect to speak, thereby excluding those we wouldn't (e.g. goblins and horses).

The conditions are applied to the person speaking the line, called the object. Click the NEW button at the bottom of the page.

The interface to enter conditions is split into four areas: Condition Function, Function Parameters, Comparison, and Value. There are also some flag selectors, which we will look at later.

Condition FunctionEdit

This is the basis of your condition. It initially defaults to the condition GetDisposition, but clicking on this opens up a long list in a drop down window. This contains the valid functions that can be used in a conditional statement. (See later for IF-ENDIF BLOCKS)

These can be divided into sets of similar functions which I have chosen to call families.

CAN Family: Tests if something can happen
HAS Family: Tests if something has occurred
IS Family: Tests if something is true
SAME family: Test if two things are the same
GET family: Retrieves information from game for comparison

Clearly I cannot go through each of these in turn. In truth most of their general functions are self explanatory, even if their specific use is not.

Function parametersEdit

Some functions require a parameter to work, and some don't. It depends on the function.

For example, the function GetRace requires you to select a valid race from a drop down menu for it to make sense, while GetIsPlayableRace has no parameters.

ComparisonEdit

All conditional statements result in boolean values: true or false. They are all about comparing values. Each "conditional function" returns some value which we can then compare to our own set value in a few different ways: less than, more than, equivalent to, not equivalent to, etc. The comparison of those two values will turn out to be either true or false. (e.g.: Either A is more than B, or it isn't. The player has less than or equal to 5000 gold, or he/she doesn't.)

ValueEdit

This is the value we compare the conditional function value with. This can be a number or a variable.

Our conditionEdit

We want to set up a conditional function that checks whether the speaker is of the right type. I.e., that it is one of the playable races (Imperial, High Elf, etc.).

From the Condition Function list, we choose GetIsPlayableRace.

This function does not require a parameter, as it already knows exactly which races are or aren't valid player races. It will return a value of 1 if the object is a playable race, and a value of 0 if not.

From the list of comparisons we choose equals. This is represented by ==.

In the value box we select 1.000.

We now have the condition

GetIsPlayableRace == 1. 

This is in effect the equivalent to the instruction

Find out if the actor is from a playable race. IF this is true, carry on. IF NOT, stop the actor from speaking any of the lines from this quest.

We have completed the basic set up for our quest.

Quest StagesEdit

Now let's select the Quest Stages Tab.

Again, this is blank. We can add stages in the same way as we added the quest. In the column marked Quest Stages, right click and select new. The pop-up expects a number between 0-255. We tend to use 10, 20, 30, etc. to allow room for extra stages. Go ahead and enter 10. Now select new again, and enter 100. We now have two stages: 10 and 100. Now make one more stage and enter 20. Initially the list reads 10, 100, 20. But if you go back to the quest data tab and then return to the stage tab again, the list will have updated to read 10, 20, 100. The CS sorted them for us.

(Note that although the CS lists the stages in numerical order, you do not have to work through the stages in that order. Each stage is discrete and exists in its own right without reference to the other stages.)

These three stages are blank. Don't worry about this. Until we set the game up to call these stages, they do nothing. If we do call a blank stage nothing will happen.

Quest TargetsEdit

The next tab is called TARGETS. We will add all the targets at the end of lesson 7. We can add them at any stage. I found it easier to do this at the end.

We are now ready to get down to the fun bit of mod building.

TopicsEdit

Let's add some content.

Select the Topics Tab from the Quest pop up. DO NOT use filtered dialogue to add topics: this can lead to mod confliction issues.

Again, this is blank to begin with. We will add a topic which will be used at the start of the quest.

In the topic column to left hand side of the tab, right-click and select Add Topic. A pop-up appears listing all available topics for all of the quests in the game. Again we use right-click and New to get another pop-up. We need to add a one word unique topic descriptor.

You should add a topic called BGMMessage4u. (In the TutPlayTest file, the topic was accidentally named message4u - you should continue using the quest prefix.)

If you look at the top this also appears at the top of the screen, in the 'Topic Text' box. This is the topic as it will appear in the dialogue menu when you activate a suitable NPC. Try to keep these fairly short, as they will otherwise take up too much space in the topic selection menu. Let's change this to something like "Message for you."

Great! We have a topic, now we need a response. The idea here is to create an exchange where when we click on the topic "Message for you" we get a response that lets us know that an NPC - who I named Vilanus Villa - is looking for us. Of course the name is entirely up to you. Just change any reference I make to "Vilanus Villa" to suit your characters.

Right-click in the response section (underneath the Topic Text filed), and select new. A new pop-up interface appears. Ignore the bottom part for now. In the upper section type:

I hear a Lawyer named Vilanus Villa is looking for you.

Hit Ok to save.

So we now have a topic and a response. However, if you tested this mod you would not see this topic on any NPC at all. Why?

There are an awful lot of topics in the game list. If the game added every topic to every character the scrolling list of topics would be ridiculously long. So the game works like this. It only adds topics which:

A) Have a valid response (one whose conditions are met)

And

B) Your character knows about

Players can learn new topics in all sorts of ways. They may, as in the walkthrough quest in lessons 4-5, pick one up from an overheard conversation. They may talk to NPCs and pick up topics that way. They may witness events that add topics. Or, as in the case of this mod, we teach them the topic by doing a bit of scripting.

So are you ready to write a script?

Our First ScriptEdit

We are going to write a bit of script which will add a topic to the players learned list and thus allow NPCs to use that topic when we activate them.

Before we go further it might be useful to give you a bit of a glossary. I have assumed that you have never programmed before in writing this tutorial. If you have you will be at an advantage when it comes to writing scripts.

Commands and Functions:

These are the formal instructions that you place in the script to tell the game what you want it to do. The Wiki makes a distinction between what these do. It should be noticed, the differences for beginners may appear very slight.

The commands are:

Scriptname

-Used to identify the script obviously

Declarations

-These are a set of descriptors which identify the VARIABLES used in a script

Begin-End

-Used in conjunction with each other to create BLOCKS of script.

If-EndIf

-Used together with optional ElseIf and Else commands to form CONDITIONAL blocks.

Return

-Use to break a scripts running for that run only.

Set

-Used to assign new values to variables

“.” or Use Reference

The full stop or period “.” is a command which identifies the REFERENCE that a FUNCTION should use.

There are a large number of functions, each of which does a unique job. There is not enough space to look at each of these in turn. However, many of the functions do group together to form ‘families', for example

  • ADDsomething
  • FORCEsomething
  • GETsomething
  • ISsomething
  • MODsomething
  • SAMEsomething
  • SETsomething
  • SHOWsomething
Variables

One way to think of variables is as a container which stores a number. The different variables types, Short, Long etc. determined how big a container will be assigned to that variable name.

So for example

 Short BOB
 Long BILL

This assigns a small section of the computers memory to a variable called bob (note capitalisation is purely a matter of personal clarity and style and is not important to the script compiling or running), and a larger part of the memory is assigned to a variable called Bill. The more variables the game has to remember the larger the amount of memory we use, and the slower the game runs. We want to minimise the impact by declaring as small a variable type as possible.

Parameters

Many functions accept or need you to include extra bits of information called a parameter.

 Player.additem gold001 100

The 100 is a parameter that lets the game know how much gold to add.

Object ID: Several functions work by doing something to a game object. Remember all the objects are listed in the object window, so objects include Actors.

 Player.additem gold001 100

Here gold001 is the object id

Reference ID

Several functions work by changing a specific example of an object. There may be many chests of a particular object type in the game and you want to add gold to only one of them. The reference ID is a unique identifier for that instance of an object. You add the reference by double clicking on the example in the render window (or by selecting edit from the cell objects window). In the object pop up dialogue box you add a unique name to the reference id box. Note that for this to happen the object must be placed in a cell. To use this reference in a script you will need to click the persistent reference check box. This tells the game to always remember that object even if the PC leaves the cell that it is in.

Player.additem gold001 100

In this example the player (a constant reference) is the reference id.

Okay let's move on

The FUNCTION we will use is called AddTopic. Its syntax (the way the computer needs it to be written so it works) is this

 AddTopic TopicID

Firstly the use of capitals in any function is optional

addtopic ADDTOPIC AddTopic aDdToPiC

All work, and all do the same thing. It's just that AddTopic looks neater so you tend to see this used most. But don't get worried if you forget or come across script that uses capitals in another way.

The TopicID is the id name we added in the topic list. This is why it has to be unique.

Take a deep breath. Now go back to the quest Data tab. Next to the quest script box is a button with three dots … Click this and the script editing window opens up.

The Script Editing WindowEdit

The script editor is in essence a very basic text editor, used for writing and editing scripts. Many scripters use external text editors like Notepad, Notepad++, Crimson Editor, etc. to write their scripts. One reason for this is that the script editor will only save compiled scripts, which must be 100% free of errors. External editors also allow you to keep a back-up versions of your scripts.

I personally keep a large library of scripts. Some that I have written, and loads copied from forums and other mods. I can then refer to these when I need a solution to a problem.

On the menu bar at the top of the editor you will find two options, plus the standard help files.

ScriptEdit

This menu has the following options available

New

Creates a new, empty script.

Open

Presents a list of existing scripts. Choose from the drop down list for one to edit.

Next Script

Switches to the next script in alphabetical order. If you changed the current script, or the current scripts needs to be recompiled for some other reason (e.g. changed variables in another script) you'll be asked if you want to save the changes.

Previous Script

Switches to the previous script in alphabetical order. You'll be asked if you want to save/recompile.

Save

Compiles and saves the script. If it fails to compile, the script is not saved.

Delete

Shows the list of all scripts. Choose one to delete

 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! 
Recompile All

Recompiles all scripts in game. This will store all scripts from any currently loaded ESM's or ESP's into your active ESP, so it's only useful for working on total conversions. In other words DON'T USE THIS unless you know exactly what you are doing. EVER! The resulting esp. will be a) Huge and b) In conflict with the original files.

 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! 

EditEdit

Undo

Standard undo function that restores the script to its state before the last change.

Redo
Standard redo function that restores the last change to the script if it has been undone.
Find Text

Standard find function.

Find Next

Standard find next function that repeats the last find from the current cursor location.

Go To Line

Compile errors list the error by line number. Use this command to go directly to that line number.

Next is a line of icons which give you shorthand ways to do some of the menu actions. In order from left to right they are. Open, Save, Next, Previous, Compile All, Delete, Exit

Script TypeEdit

Finally there is a Script Type drop down menu. There are 4 types of script, but "Results" scripts are not edited or compiled in the script editor. We will see this shortly.

The scripts written in this editor can be Object, Quest, or Magic effect. This setting determines which objects in the editor the script can be attached to. Each script type is run in a slightly different way and it is important to let the game know which one you want your script to be. You can edit or change this at a later date if you make an error.

Okay, we want to write a quest script, so select Quest from the Script Type drop-down window.

ScriptingEdit

A script is a set of instructions for the game to run during gameplay. It has much in common with programming languages, but is not a true language per se. We do need to use a formal structure called syntax to ensure that the game can understand what we want it to do.

Let's add a bit of script then.

We need to give each script a name, and like all naming conventions that we have covered so far, it has the same basic rules. The name must unique, alpha-numeric, and free of whitespace (spaces, tabs, etc.). You should also continue to use your quest prefix (e.g. BGM) while naming your scripts.

Let's name the script BGM001QuestScript.

(Note: This should be done on the BASE version if you have loaded Both Tutorial Mods at the same time.)

We write this in the editor like this:

Scriptname BGM001QuestScript

We could also use a shorthand version:

Scn BGM001QuestScript

Many functions and command have shorthand versions. In this tutorial I will always use the full version.

Now select save.

The editor compiles the script.

Begin StatementsEdit

First we start by adding a Begin statement.

This comes in two parts. The first is the word BEGIN followed by a space. Followed by the BLOCK type statement. There are lots of BLOCK types available.

Wiki Block Types Page

The vast majority of begin blocks run only once.

This is both an advantage and a disadvantage. Many forum posts deal with scripts that need to run continuously, but because of the block type only run once. Selecting the correct block type is a skill you will only develop by practice and observation. For the most part you will be using GameMode, OnActivate and MenuMode.

So lets type

 Begin GameMode

(Remember the capitals are purely for clarity)

Now let's add the instruction

 AddTopic BGMMessage4U

And finally the

 End

Command

So our script reads

 Scriptname BGM001QuestScript
 Begin GameMode
 AddTopic BGMMessage4U
 End

We can again save our script.

(Please note, the quest script in the PLAYTEST file shows the script in its finished state and quite long. We will add small snippets of working script as we progress)

One of the most common mistakes that beginners make is to assume that because a script complies (saves), that it will work. This is not the case. The editor checks to see that your script has obeyed all the rules to make sure the game can try to carry out your instructions. It does not mean that these instructions will do the job you expect them to do. If you do make a syntax error the editor will display a pop up window detailing the error, together with a disconcerting alarm ring. It also asks you to select whether you should continue. Always say yes or you will lose your scripts.

It is always a good idea to back up scripts in notepad or WordPad. Remember you can copy a script by selecting it, and then using the shortcut CTRL-C.

Now we need to attach the script to our quest.

Open up the Quest Data Tab for our quest. Where it says script open the drop down menu and scroll down to find the BGM001QuestScript. Click on this and you're done.

Save the mod (you will need to close all pop up windows to do this)

You can now test this mod in the game, but it might be best not to SAVE the game in Oblivion as we will be changing things.

Two ProblemsEdit

There are two problems with the mod as it stands:

The first problem is that the text does not stay on the screen very long, and our NPC will just look at us. This is due to the way the game handles speech. It expects to find for each dialogue response files, which we have not created. One is an MP3 which contains the sound files, and the others are lip synch files used to animate the actor's face as we carry out the dialogue. The text is supposed to appear on screen for the duration of these files. Since we don't have them yet, the text runs very quickly. In later tutorials we will look at polishing this mod to include these files. For now, these are cosmetic problems. It's irritating not to see the text for any length of time, but it can't be helped until we add those MP3's. It doesn't stop the quest running. You can repeatedly play the on-screen text by selecting the topic message for you until you get the message. (Alternatively, you could install a mod like Universal Silent Voice.)

The second problem deals with the script as it currently stands and may not be so obvious to a non-scripter. A quest script runs every 5 seconds. That means that every 5 seconds this script tries to add the topic BGMMessage4u to the players topic list. I don't honestly know what the effect of repeatedly adding a topic to the player's list is, but I suspect that extra requests to add the topic are simply ignored.

However, this is still an untidy way to script. If we only want something to happen once, we should write our script that way!

This leads us to one of the most important and common scripting ideas: a do once loop.

If-EndIf BlocksEdit

No other command is more important to good quality functional scripts than the if command. Again those with programming experience will be at a slight advantage as you will have used these before. For the newbie let me explain little about the premise behind IF blocks.

These useful bits of code set up the ability to run selected bits of script at selected times.

We control when they run by setting conditions which must be met for the code to run. The conditions are based on mathematical relationships, and are based on numerical values.

The structure of the if block can be summarised as this

If (a set of mathematically based conditions)

RUN THE SCRIPT INSTRUCTIONS LOCATED HERE IF THE CONDITIONS ARE TRUE

ElseIf (a second set of OPTIONAL conditions)

SCRIPT THAT RUNS IF THE SECOND SET IS TRUE. THE CONDITION WILL ONLY BE TESTED IF THE ORIGINAL IF STATEMENT SET OF CONDITIONS ARE FALSE.

Else (No Conditions)

OPTIONAL SCRIPT THAT RUNS IF ALL OTHER CONDITIONS ARE FALSE.
IF THE ELSEIF AND ELSE COMMANDS ARE OMITTED THE BLOCK DOES NOTHING IF THE ORIGINAL CONDITIONS ATTACHED TO THE IF STAEMENT ARE NOT MET.

EndIf

So all IF blocks, must contain an IF command, a set of conditions, some instructions and an EndIf command. The ElseIf and Else commands are optional, and add versatility to the block.

We are going to write an IF block to limit the number of times our script runs to one.

It is call a DoOnce (do once) loop and is used hundreds of times by the developers, and is a standard tool for all scripters.

First we need to declare a variable. Open up the quest script using the … button next to the quest script.

We can declare a variable anywhere in a script before it is used but by convention we usually do this at the beginning of the script before any Begin Blocks.

The variable we want will only ever have two values 0 or 1. So we can use the smallest possible variable type, which is short. We will call it DoOnce1 for convenience. You can call variable what you like as long as it is a single text string. But again it helps to make them descriptive to help sort out mistakes (Debugging) Remember Capitals are only for show.

So add the line

 Short DoOnce1

Just after the script name line. You can leave lines to help clarity. Again these are ignored by the program when it runs the script.

Now let's add the if block

Change the Begin block to look like this.

Begin GameMode
If (DoOnce1 == 0)
AddTopic BGMMessage4U
Set DoOnce1 to 1
EndIf
End

This is perfectly fine but it can get a little hard to read, when these if statements get long and complex. So again we use an optional convention. We indent using the tab key all lines after an IF statement, to make clear what is going on.

Begin GameMode
  If (DoOnce1 == 0)
    AddTopic BGMMessage4U
    Set DoOnce1 to 1
  EndIf
End

So this script uses another new command called SET-TO.

Whenever you declare variables they are automatically assigned a value of Zero. We can alter this by using the SET-To commands. (Note basic programmers that it is SET x TO y not SET x = y)

The format is

 Set VARIABLE to VALUE

The VALUE can be any number which fit's the pattern of the variable. So for a short variable it can be any integer or whole number between (-32768) and (32767).

This can take the form of

  • A fixed number like our script.
  • The result of a mathematical calculation.
  • The value of another variable
  • Or the outcome of a comparison statement.

IF statements and Set statements both use standard mathematical comparisons

Comparison OperatorsEdit

An IF statement may contain one or more comparison operators. Below is a table of valid comparison operators:

 Operator  Description 
   ==      Exactly equal to 
   != 	   Not equal to 
   > 	   Greater than 
   >= 	   Greater than or equal to 
   < 	   Less than 
   <= 	   Less than or equal to 

Combining ComparisonsEdit

Comparisons can be linked together using the following logical operators:

 Operator 	Description 	Example 
 && 	        Logical AND 	If x == 1 && y == 1; considered true only if both x and y equal 1. 
 || 	        Logical OR 	If x == 1 || y == 1; considered true unless both x and y equal 0. 

(Note that "||" is evaluated before "&&")

So this script we have written works this way.

The first time the script runs the variable DoOnce is set up and given the value ZERO.

The game runs through the script to the IF statement.

It tests to see if it is TRUE that DoOnce equal zero. In this case it is true. So it runs the script, adding the topic BGMMessage4u to the players learned list. It then sets the value stored in doonce1 to the number one. It then ends the IF statement and ends the scripts begin end block. Since this is the end of the script it stops running. About 5 seconds later this Quest script runs again. Again it comes to the test. But this time DoOnce1 is not equal to 0. So the program skips the instructions and ends the IF statement. From now on this bit of script will not run. We have added the topic once and once only.

A third problemEdit

The third major problem is that this topic has been added to every NPC in the game. It is just about conceivable that if you complete every quest in the game and then some that you might meet every NPC there is, but I don't see how it's logical to suggest that they all might know Vilanus Villa and know he has a message for you. We need to limit who speaks to you on this topic. We must set some response conditions.

ConditionsEdit

The conditions box in the Topics Tab is used to limit who gets to say a particular response. We can limit this in many ways.

For example, Restrict by group (GetInFaction), race (GetRace) or limit to only one NPC (GetIsID), Restrict by Worldspace, City, Cell or distance from a particular chair, Restrict by Game Time, Season, Weather or progress of quest.

Open up the topics tab, select the BGMMessage4u topic and highlight the response we added earlier.

At the bottom of the window is the condition box. Again we can use Right-click + New to add conditions, or we can click on the New button at the bottom of the tab page.

These conditions are just like the ones we used in Quest Data before.

By default, all NPCs will have our new topic available. We need to use conditions to choose which NPCs can or can't display our topic.

This particular topic is a general one and we want to set some general conditions just to reduce the number of NPCs that can use it.

First let's get rid of a number of races. Why? Well, in the middle part of the window is the response box. Double click on the response to the BGMMessage4u topic to re-open the pop-up response dialog box. Have a look at the lower section and you can see a long list.

This is the list of expected MP3 files which we would need to create. It is very long; it expects both a male and female response for every single race.

We can remove some of these to make our life easier later on, when it's time to record.

Select New in the condition box with the response "I hear a lawyer named..." highlighted.

In the Condition Function drop down menu, scroll down to the function GetIsRace. Click on the Function Parameter box and a list of races will be displayed. These are the valid parameters for this function. Select "Argonian" from the list. The comparison reads == by default, so you can leave that unchanged. The value current reads 1.0000. This is value the function GetIsRace would give if the character's race was in fact "Argonian". We want to change this to the negative response: 0.0000.

In English this means:

Look at the Actor who might use this response. Check what race they are. If they are not an Argonian, then carry on.
Otherwise, they are an Argonian and should not be able to use this line.

(Note that the condition Argonian == 0 is logically equivalent to Argonian != 1)

Now, let's add a few more Race-based conditions. Right-click on the condition we just created and copy it using the Copy option from the menu. Now right-click again and paste. We now have an exact copy of our condition.

Click on the parameter box and now choose "Elf". We now have two races excluded.

Repeat this process to exclude the other races, until we are left with Bretons, Redguards, Imperialsm and Nords (i.e. the Human races).

Is this some sort of cultural imperialism on my part? No, it's just that I reckon I could add an MP3 file which might sound passable for those races. Orcs, Argonians, and Khajiits have unique voice types that are harder to replicate. It is a matter of style and choice. If you want to extend the range, do so.

We call these conditions "exclusive conditions" because they exclude a group or individual from using that response.

We also want to limit the in-game locations where these lines are valid.

All major locations, including the cities, have special "dummy cells" created to allow us to use a single condition on many individual locations. The game searches for cells with a given text string at the beginning of its name. So if we select a cell called "IC", it actually triggers every cell that begins with "IC". Everything from ICPalaceLibrary to ICTalosPlazeTheTiberSeptimHotelUpstairs.

If you called a cell Icnatta or something else that also begins with "IC", even though this cell might have nothing to do with the Imperial City, the catch all nature of the "IC" description means that that cell will also be triggered. This would conflict with the Imperial City's naming prefix. This means we do need to be careful when naming cells. It also means that we can use this trick ourselves. If we create huge mods that add towns or cities, we can use prefixes in the same way. By carefully naming all my external and interior cells VeronaHouseSomethingorOther, we could then create a "dummy" (i.e., completely empty and unused) cell called VeronaHouse, which would allow us to use VeronaHouse in condition statements and identify if something was anywhere in the Verona House area.

I choose the Imperial City (again, I could have chosen any number of locations) because it is the Capital, and most players will at one point or another visit the City. It is as ever about style rather than technique and you are free to choose your own path.

In the condition box select New.

Now select condition function GetInCell. The parameter for this is initially invalid until we click on it select a cell from the menu. You can only select cells that are named and unique. Notice that all those exterior cells called "Wilderness" don't show up. If you wish to use an exterior cell, you must give it a unique name.

Set the condition to test. (This is an inclusive condition, since it includes a group in that response.)

Another way to select groups is by using factions (see lesson 7 for more details on creating a Faction)

One such faction is the ICFaction. It groups all the NPCs who are considered citizens of this city. It is a useful way to distinguish between the merchants, soldiers, and workers of the capital and a tourist from Chorrol who is passing through.

Set up a new condition.

Choose the GetInFaction function, and then choose the ICFaction from the list to get a new condition. Finally, we want to exclude our NPC Vilanus Villa from using these lines. It would be awfully silly if Vilanus himself told us, "I hear a lawyer named Vilanus Villa is looking for you." To do this we use the condition function GetIsID. Then from the parameter list we select BGVilanusVilla. Remember to set the value to == 0 (or != 1) so that your condition EXCLUDES him.

Finally, we want to set a condition that removes this topic from all potential speakers once we have met Villa.

Create a new condition. Choose the GetStage Function, then select our quest (BGM001) from the list. Change the 'Comparison' to < (less than), and the value to ten. This runs a check to ensure the PC hasn't advanced at all in the quest, effectively removing it from all NPC's if it has.

Adding TopicsEdit

We also want to add a new topic as a result of this response.

First create a new topic called BGMVilanusVilla using the method we have just used (Right Click-New). You can leave the response blank for now.

On the Right hand side of the Topics Tab window are three boxes called

Add Topic

This is used to add a topic to the players learned list. Once added it can be accessed using the topic menu when we click on an NPC. The player can then decide whether or not to click on this.

Add Choices

This adds a list of FORCED choices to the topic menu. All other options are removed, and the player must make a choice to proceed.

Add Links from

This adds a single FORCED topic which again forces the player to select that option to proceed. It links to a previous response. By using this we can set up long forced conversations.

It is probably best to use the Add Topic box, on this occasion, so we can use the topic several times. Again a bit of preplanning will allow you to use the same topic for several purposes.

Now go back to the BGMMessage4u topic and in the Add Topic box to the right, right click and add the BGVilanusVilla topic. Now when we talk to an NPC about the message we will have a new topic added to our learned list called BGVilanusVilla. It won't show up in the game right now as we have no valid responses.

Finally in the result script box type the following:

SetStage BGM001 10

Now click the COMPILE button.

This executes a stage bump. The quest is now set at STAGE 10

Let's summarise what we have for this first topic

BGMMessage4u
TOPIC Message for you
RESPONSE I hear a lawyer named Vilanus Villa is looking for you.
CONDITIONS
  • GetIsRace 'Argonian' == 0, etc.
  • GetInCell 'IC' == 1
  • GetInFaction 'ICFaction' == 1
  • GetIsID 'BGVilanusVilla' == 0
  • GetStage 'BGM001' < 10
ADD TOPICS
  • BGVilanusVilla
RESULT SCRIPT
SetStage BGM001 10

I'll use these summaries throughout these tutorials. I have used this table as a template when planning my own quests, and I find it really useful. Remember, if you get stuck refer to the PLAY TEST (BGModTutPlayTest) version to see how it should look.

Stage UpdateEdit

Now return to the quest stages tab.

We have now progressed through the quest to stage 10. We can of course leave this blank. Sometimes we want to stage bump simply to activate/deactivate conditions that use the GetStage function. However, we can also use this stage bump to do a few things. We can add a quest stage result script to carry out some script instructions relating to the quest and we can add a Journal entry. Let's do this. It's the same old routine. Right Click and new in the Log Entry box. Add a suitable bit of text like:

I have been told a lawyer called Vilanus Villa is looking for me. I should find out where he is staying. He may have important news for me.

Ok, we have now added a topic called BGMMessage4u.

For now, save and go test.

You should now find that this topic only appears for human characters in the Imperial City. Try in other locales like Anvil, etc. to make sure. When you're done, come back and we can move on.

When you click on the BGMMessage4u topic in the game the topic Vilanus Villa will now automatically be added.

I don't intend to continue to give you a click-by-click method for every topic and response. Remember the basic idea of right click and select.

Let's move on.

Select the BGVilanusVilla topic we added earlier and add a response (See table below). This response should direct the player to the Talos District of the Imperial City.

We need some conditions.

Since this is a direct follow-up from'BGMMessage4u, we can use the same conditions to do the job. In the BGMMessage4u condition box, right click and select copy all conditions and then paste these into the BGVilanusVilla response.

This response is fine, unless we're talking to someone who's already in Talos Plaza.

We need to add one more condition to account for this by using the GetInCell function. We also need to update the stage values that GetStage checks for.

BGMVilanusVilla
TOPIC TEXT "Vilanus Villa"
RESPONSE "I believe he's staying in Talos Plaza."
CONDITIONS
  • GetIsRace 'Argonian' == 0, etc.
  • GetInCell 'IC' == 1
  • GetInFaction 'ICFaction' == 1
  • GetIsId 'BGVilanusVilla' == 0
  • GetStage 'BGM001' < 20
  • GetInCell 'ICTalosPlaza' == 0
ADD TOPICS No add topic
RESULT SCRIPT No script

We should also add responses that only work inside Talos Plaza. This next one should direct the player to the Imperial Hotel where we placed Vilanus Villa. Again, we can copy the conditions by using the copy and paste method, and then change the last condition (GetInCell 'ICTalosPlaza') to 1. (You could also duplicate the entire response by right-clicking and selecting copy, and then edit the duplicate from there.)

BGMVilanusVilla
TOPIC TEXT "Vilanus Villa"
RESPONSE "I believe he is staying in the Tiber Septim Hotel."
CONDITIONS
  • GetIsRace 'Argonian' == 0, etc.
  • GetInCell 'IC' == 1
  • GetInFaction 'ICFaction' == 1
  • GetIsID 'BGVilanusVilla' == 0
  • GetStage 'BGM001' < 20
  • GetInCell 'ICTalosPlaza' == 1
ADD TOPICS No add topic
RESULT SCRIPT No script

If you wanted to get really flashy you could add another response for the occasions when we ask NPCs about Vilanus Villa inside the hotel itself. However, I have not done this to save a bit of time. Feel free to try this yourself. A response like "Yeah I've seen him around here." would do. Don't forget to copy the conditions and alter the GetInCell parameter. Also remember that GetInCell matches the beginning of the cell strings, so you should add another GetInCell condition to the second response which excludes the Hotel cell (so that the response "I believe he is staying in the Imperial Hotel." shows up everywhere in Talos Plaza EXCEPT for the hotel itself).

Using the GREETING topicEdit

Another way to pass on information via dialogues is to use the GREETING topic. If you remember the discussion in Lesson 4 about how conversations work, all dialogues begin with a GREETING, which is selected by the game from the GREETING topic. If we add our own greeting and set the right conditions we can force a start to a dialogue. In the topics tab add GREETING. This topic already exists, so you will not need to create a new topic when the list appears.

We can now add Vilanus Villa's little speech. This is quite a long response so we should split it up to reduce the amount of text that appears on the screen at any given time. Add this response first to the GREETING topic. Note this is blank because there are no GREETING responses added by this quest yet.

Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news.

Now click OK to add the response.

Then in the Response Details box (not the upper info box), add a new line of response text. You'll get a new interface to write in.

Your uncle passed away peacefully in his sleep.

Then add another:

I have been asked to look after his last will and testament.

We can go on adding new lines to this response info if we wish. In the top box we can see the number of responses increments to 3. The text appears in the top box as:

Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news. || Your uncle passed away peacefully in his sleep. || I have been asked to look after his last will and testament.

With the || indicating separate lines of this single response.

We need to add some conditions, to control who says these lines. This is very important when using the GREETINGS topic as this is so wide spread within the game. While it is silly that every character could respond to BGMMessage4u, it is dangerous to have an unconditional greeting, as this might override every other greeting in the game and prevent other quests from working properly.

Limiting a response to just one character is easier than using groups.

We can use the GetIsID function for this.

We need to have an NPC reference, which is why we built BGVilanusVilla first. We will also restrict this response to the opening stage of our quest.

  • GetStage 'BGM001' <= 10
  • GetIsID 'BGVilanusVilla' == 1

Now we want to add a new topic called BGWill. However, there is an issue (and many thanks to Hecks for pointing this out) when adding topics to the GREETING or indeed any existing Bethesda topic. For technical reasons, the topic might not get added if more than one plug-in is attempting to use GREETING to add a topic. I'll be honest and say I don't know why this happens. It's not difficult to work around once you know the issue exists. When I found out it took me thirty seconds in the CS to fix.

First create a new topic called BGWill.

Now add this to the result script for the GREETING response.

AddTopic BGWill

Job Done.

The speech that Villa gives contains a lot of exposition, and we don't want to force the player to repeat this every time.

We can stop this by setting up a pair of conditional responses.

Conditional PairsEdit

These are a very common device used throughout the official quests. We set up two response infos to the same topic. We then use a quest variable or a function condition to control which of the two responses is said.

These might take the form

Response 1: Long Explanation
Response 2: Short Explanation

Response 1: Female PC Response ‘Morning Ma'am'
Response 2: Male PC Response ‘Morning Sir'

Response 1: ‘Ah you've found the widget my friend'
Response 2: ‘You must find the widget my friend'

Let's try this

Add a new variable called MetVilla to the top of the Quest Script (under the quest data tab). We should declare any variables used by the quest in the Quest-type script.

SCN BGM001QuestScript
Short DoOnce1
Short MetVilla

Begin GameMode

	If (DoOnce1 == 0)	
		AddTopic BGMMessage4U
		Set DoOnce1 to 1
	EndIf

End

This variable will be automatically set to zero. We can use the response result box to bump this up to one after the speech with a bit of script. Add this in after "AddTopic BGWill".

 Set BGM001.MetVilla to 1

Don't forget to click the compile button!

Summarising the first response:

GREETING
TOPIC TEXT GREETING
RESPONSE
  • "Hello, my name is Vilanus Villa and I've been looking for you. I'm afraid I have some bad news."
  • "Your uncle has passed away peacefully in his sleep."
  • "I have been asked to look after his last will and testament."
CONDITIONS
  • GetStage 'BGM001' <= 10
  • GetIsID 'BGVilanusVilla' == 1
  • GetQuestVariable 'BGM001.MetVilla' == 0
ADD TOPICS No add topic
RESULT SCRIPT
AddTopic BGWill
Set BGM001.MetVilla to 1


We can then add this alternative response info to the GREETING topic:

GREETING
TOPIC TEXT GREETING
RESPONSE "Whenever you want to talk about your uncle's will, let me know."
CONDITIONS
  • GetStage 'BGM001' <= 10
  • GetIsID 'BGVilanusVilla' == 1
  • GetQuestVariable 'BGM001.MetVilla' == 1
ADD TOPICS No add topic
RESULT SCRIPT No script


The first time we greet him he gives the longer speech, the second time a shorter one.

We can now add response info to the BGWill topic.

Try this one yourself using this summary to guide you. Don't forget the quest bump script. You will need to add a new topic called BGHubart.

BGWill
TOPIC TEXT "My uncle's will"
RESPONSE
  • "Apparently your uncle had some property here in Cyrodiil. I'm not sure where, though."
  • "I was expecting a courier to deliver the details, but she hasn't shown up."
  • "Captain Hubart of the Chorrol Guard notified me that the courier never made it to her stop in Chorrol."
  • "You will have to visit him in Chorrol to find out more about what's going on. Here's the letter he sent me."
CONDITIONS
  • GetStage 'BGM001' <= 10
  • GetIsID 'BGVilanusVilla' == 1
ADD TOPICS
  • BGHubart
  • BGMVilanusVilla (In case the player talked to Vilanus before using the "Message for you" topic)
RESULT SCRIPT
SetStage BGM001 20

Again we have a stage bump, this time to stage 20. In the Quest Stages tab, add a journal entry for stage 20.

I've been told that I may have inherited some property from my late uncle, but the courier carrying the details has gone missing. I will need to go to Chorrol and speak to a Captain Hubart of the Chorrol Guard to get more information.

We will also add a Quest Stage Result Script.

But first we need to create a prop letter, so we can refer to it in the script.

Again we can create a new item from scratch, but it means trying to add artwork to the game. Unless we want the letter or scroll to look completely unique, and have some talent in that direction, it is a chore we don't need to do.

Instead, select any letter from the Items->Book list in the object window, change its ID to something meaningful like BGHubartLetter.

The text on the right hand side indicates the content of the letter. We can edit this. I will look at the precise details and syntax needed to produce text in another lesson. It uses standard HTML tags. For now, the key command is <br>, which produces a 'line break' or 'new line'. The font face can be left alone.

BGHubartLetter

<font face=5><br>
Dear Vilanus,
<br>
<br>
I regret to inform you that the White Horse courier Janus Jakobs, who you asked me to meet, has not arrived for her expected rendezvous. I know you were expecting some important documents to arrive.<br>
<br>
I don't have enough man power to launch a search; perhaps you could find someone willing to assist me in finding Jakobs?
<br>
<br>
I look forward to hearing from you, old friend.
<br>
<br>
Yours,
<br>
Captain Hubart

Save the letter, AND MAKE SURE YOU CLICK 'YES' TO CREATE A NEW FORM.

Now, type this in the results script box for stage 20:

 Player.AddItem "BGHubartLetter" 1

Then click the "Compile Result" button.

We can also add a new response info to the topic called BGHubart, to direct the player to Chorrol:

BGHubart
TOPIC TEXT Captain Hubart
RESPONSE "You’ll find him in Chorrol."
CONDITIONS
  • GetStage 'BGM001' == 20
  • GetIsID 'BGVilanusVilla' == 1
ADD TOPICS No add topic
RESULT SCRIPT No script

Try this for yourself. You can always refer to the PLAYTEST version if you get stuck.

We have completed phase one. You should stop to test everything out before moving on. Just test a few conditions to make sure that everything is working, and that you haven't made any small mistakes.

Chorrol PhaseEdit

In this phase of the quest we want to use a new NPC called Captain Hubart to direct the player to solve a mystery. He will direct the player to a cottage, where they will discover a mysterious medallion and the dead body of the courier. Hubart will then be able to help us move on to Aleswell and the next phase.

For this phase, we will need to create:

  • NPC Captain Hubart
  • NPC Dead Courier
  • NPC DummyPlayer
  • A document
  • A medallion
  • A cottage to house courier.

Again, we need to add the NPC first so we can reference him in conditions.

As always, we could use a new NPC object, but it really saves a lot of time and effort if we simply change the name and ID of an existing one. This time we can just copy a Chorrol Guard NPC, such as ChorrolGuardPatrolNight01. Change the ID to BGCptHubart, and save it as a new form. Strip out the AI, but leave his inventory as is, since the Chorrol guard's inventory already contains all we need. We can also leave the factions alone. I placed Hubart outside the Fire and Steel shop in Chorrol (worldspace ChorrolWorld).
Hint: a fast way to get to an exterior cell is to select the interior cell, and then click on the teleport marker by the door.
This is only his starting position. We can add AI packages later to move the character about.

We have to set up a new response to the BGHubart topic.

We could add a new topic but it is always a good idea to try to limit how many new topics we add. This reduces the ‘footprint' of the mod, and helps avoid possible conflicts with other mods.

We want to set up a response so that when any Chorrol based NPCs are questioned they will direct the PC toward the likely location of the captain. Add conditions to limit the race to human again (saving all that MP3 work), and the location to the Chorrol dummy cell (thereby including all cells within Chorrol). We can also limit the ‘timescale' to the current quest stage (20). Try this yourself. You can always refer to the PLAYTEST version if you get stuck.

BGHubart
TOPIC TEXT "Captain Hubart"
RESPONSE "He's usually on duty near the Fire and Steel."
CONDITIONS
  • GetIsRace 'Argonian' == 0, etc.
  • GetInCell 'Chorrol' == 1
  • GetInFaction 'ChorrolFaction' == 1
  • GetIsID 'BGCptHubart' == 0
  • GetStage 'BGM001' >= 20
ADD TOPICS No add topic
RESULT SCRIPT No script

We can now add some dialogue for Hubart himself.

The first can be attached to Vilanus Villa topic, to reduce the ‘footprint'.

First, add a TOPIC called BGCourier.

BGMVilanusVilla
TOPIC TEXT "Missing courier"
RESPONSE "Vilanus has sent you to investigate the courier's disappearance?"
CONDITIONS
  • GetIsID 'BGCptHubart' == 1
  • GetStage 'BGM001' == 20
ADD TOPICS
  • BGCourier
RESULT SCRIPT No script

Stop to test this out, and then refer to the PLAYTEST version if you are stuck.

Before we go any farther, we need to set the scene at the cottage.

Locating the CottageEdit

If you are using BGModTutBase.esp, you can use these cells: BGModCourierCottage in the Interiors world space, and CourierCottageExt in the Tamriel world space. The exterior building that matches the cottage is LeyawiinHouseLower03, and the door is LeyawiinLowerLoadDoor01.

The cottage could be located anywhere in Tamriel. I think I've looked at just about every cell in compiling these tutorials and working on my mods. When selecting the location for this cottage, I took into account several factors. I wanted it to be West of Chorrol. I wanted it to be close to the main road. I knew I couldn't go too far as the road abruptly ends by a cliff, marking the edge of the world space. I also decided to use the game to give me a little bonus or two.

Around this location, is a dungeon with some external guardians, some bandits and an oblivion gate. This means any NPC will be harassed by bad guys that we don't have to work too hard to create.

We want to set the internal scene in readiness for the PC's arrival. I have used a copy of the White Stallion Lodge as a base. We want to customise this. Again we can work on this in more detail when we polish the quest prior to release.

We want to remove some of the clutter. We also want to give the impression a fight has taken place. Tips some chairs and tables over (Y=90). Remember this set will be locked at the start and you will only use it for a short time, so don't go overboard. We also want to place some props. We need an amulet to trigger the next phase. Why an amulet? It's small enough that you have to look for it, but not so small that it becomes hard to find. Copy an existing item of jewelry from Items->Clothing->Amulet as a base and edit it. Change the ID to BGEmbossedAmulet. Check off the Quest Item box. The player can not drop or sell quest items.

We also want to create a custom letter called BGPartialLetter. Set the letter as a quest item. We will refer to it in some scripts.

<br>
<font face=5><br>
Dear Vilanus,
<br>
<br>
The client wishes his only living heir in Cyrodiil to inherit his house. I have enclosed the deed and key. The location of the house is registered at the Imperial City Land Offices...<br>
<br>
<br>
<br>
LETTER IS RIPPED HERE
<br>
<br>

Of course it would look really cool if we could create a custom texture for a torn scroll, but that is beyond the scope of this tutorial.

Finally we need to place the body of the unfortunate courier.

Bodies are NPCs who just happen to be dead. You will need to create another NPC. Use Courier1 as the base.

Place this character in the render window, set its ID to BGDeadCourierRef, and position the corpse in a suitable place. I put her in a side room so you don't see her right away. I also left a nice blood trail to lead you to her. Initially, the NPC will be standing up.

Next click Edit Base to open the NPC window. Change the NPC's ID to BGDeadCourier. Edit the NPC's health to read zero (0). (To access this stat, uncheck the PC Level Offset and Auto calc stats boxes.)

Now, the awkward thing is the fact that she is just standing there. She will stay standing in the game unless we make her fall first. To get her to fall, click on the WORLD menu and select Run Havok Sim (with the bouncing red ball). Down she goes.

We can now drag her about to get the position right.

I also placed a sword which pointed directly at the amulet.

Next, we have to add the letter to the dead courier's inventory. Open the NPC window for BGDeadCourier and click on the Inventory tab. Then drag BGPartialLetter from the objects window over into the inventory list. You will be warned that the letter is a quest item. Just click OK.

Another useful technique is to create an NPC called something like BGDummyPlayer. We will not place this NPC in the world, so don't bother to edit anything other than the object ID.

We can now set the ownership of the door and cell (Lesson 3) to BGDummyPlayer. This means that all items in the cottage will display the red hand, with the exception of the embossed amulet. This is a handy way to set ownership without having to create detailed NPCs. We can use BGDummyPlayer to set the ownership of all the doors and sets we want to prohibit our player from entering.

Now create a key called BGCourierKey. Select an existing key and change the editor ID. Also check the Quest Item box. Edit the cottage door to set its lock status to "Needs a key", and use our new object as the key.

We need to add two other items to the cottage.

We need to add an XMarker to the interior, and a map marker to the exterior.

We will find these under the Static Objects.

Drop an XMarker or an XMarkerHeading object inside the cottage and give it a reference name like BGCourierLodgeXMarker.

Now select a MapMarker and drop it just outside the cottage door, in the exterior cell. It looks a bit like a door teleport marker, but it's pink rather than yellow.

Edit its details to give it a reference name like BGCourierLodgeMapMarker.

Open up the MapMarker Data tab, check the marker data tick box and select settlement. Theses flags control what type of icon appears on the players map.

Finally in the name box call it Courier Cottage. This is the name that will appear on the map.

We need to add a bit of script to enable it. First we need to add a bit more conversation.

Add stage 30 in the stage tab, and create a topic named BGCluesFound (which we won't be editing just yet). Then create the following topic.

BGCourier
TOPIC TEXT Courier
RESPONSE
  • "She's usually very reliable, but she failed to turn up for our usual meeting."
  • "She sometimes stays in a small cottage just west of here. I'll mark it on your map."
  • "Here's a key to get you in. Let me know what you find out."
CONDITIONS
  • GetIsId 'BGCptHubart' == 1
  • GetStage 'BGM001' == 20
ADD TOPICS
  • BGCluesFound
RESULT SCRIPT
SetStage BGM001 30

Add one more response to this topic in case the player tries to talk to Hubart again after they've been given the key to the cottage, but before they've found it.

BGCourier
TOPIC TEXT Courier
RESPONSE

"Did you check out the cottage?"

CONDITIONS
  • GetIsId 'BGCptHubart' == 1
  • GetStage 'BGM001' == 30
ADD TOPICS No add topic
RESULT SCRIPT No script

Now in the stage tab for stage 30, add this to the journal:

Hubart told me that the courier sometimes stays in a small cottage just west of Chorrol. He marked its location on my map and gave me a key to the door. I should go check it out.

And add this to the stage result script:

Player.AddItem "BGCourierKey" 1
ShowMap BGCourierLodgeMapMarker

This gives the player the key to the cottage and activates the map marker.

The syntax for the ShowMap Function is

ShowMap MapMarkerID, enableFastTravel (optional)

The MapMarker ID is the reference id for the map marker. The enableFastTravel is an optional parameter which takes the value 1 if you want to be able to fast travel immediately to that location.

If enableFastTravel is not given (or set to 0) then you can not fast travel to that location until you've found it once.

We still need to add all the quest targets, and we'll use the XMarkerHeading for that.

Up 'til now we have been using dialogue to control progression, but now we need to begin using scripts more continue.

In Lesson 7 we will complete the quest and focus on SCRIPTING.