Difference between revisions of "A beginner's guide, lesson 7 - Using Scripts in Quests"

Jump to navigation Jump to search
→‎Aleswell Phase: Redoing this section.
imported>Pyrocow2
(Changing topic name. Unecessary and conflicts with the faction name.)
imported>Pyrocow2
(→‎Aleswell Phase: Redoing this section.)
Line 230: Line 230:
==Aleswell Phase==
==Aleswell Phase==


Objectives: '''This is the last section prior to the big show down. We want to set up a disposition based dialogue in which Smith, once he likes you enough, will give you the location and key to the hidden Red Rose Brigade cave system.'''
This is the last section prior to the big show down. We want to set up a disposition based dialogue in which Smith, once he likes you enough, will give you the location and key to the hidden Red Rose Brigade cave system.


We need to create  
We need to create:


* Hideout Key
* Hideout Key
Line 239: Line 239:
* The Cave system (if you are not using the base files)
* The Cave system (if you are not using the base files)


First we want set up our NPC.  
First we want set up our NPC.


We need this so we can add a quest target.  
I used a member of the Thieves Guild as a base. I stripped out his AI, but I left him as a faction member of the Thieves Guild. This will help fellow guild members get a bit of a boost to their disposition.  


I used a member of the thieves guide as a base. I again stripped out his AI, but I left him as a member of the thief’s guild. This will help fellow guild members get a bit of a boost to their disposition.  
I have chosen Aleswell as the location for this part of the quest because it is actually a lousy location to use. Aleswell is the setting for an interesting Miscellaneous Quest. In this quest all the inhabitants of the town are invisible. If the user has completed this quest before they load this mod, there will be no problem. However, if this is the first time a player has entered the inn, they will find themselves immediately involved in this quest. We need to make sure our mod interacts with this quest.  


I have chosen Aleswell as a set for this part of the quest because it is actually a lousy location to use. Aleswell is the setting for an interesting Miscellaneous Quest. In this quest all the inhabitants of the town are invisible. If the user has completed this quest before they load this mod, they will be no problem. However, if this id the first time a player has entered the in, they will find themselves immediately involved in this quest. We need to make sure our mod interacts with this quest.  
We could use some scripts (see lesson 8) to make Smith invisible along with the rest of the citizens. But, as is so often the case, the simplest solution is to just brush over it with a quick bit of dialogue.  


We could of course use some scripts (see lesson 8) that hides Smith in amongst the invisible folk until you solve this one. This in effects gives our quest a bit of a bonus making our storyline even longer.
We can set up a GREETING for Smith. Here we use the quest stage for the miscellaneous quest called MS47 Zero Visibility. This is the stage where the people of Aleswell become visible.  
 
But as is so often the case, the simplest solution, is to just brush over it with a quick bit of dialogue.
 
We can set up a GREETING for Smith. Here we use the quest stage for the miscellaneous quest called MS47 Zero Visibility. This is the stage where the people of Aleswell become visible.  


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''GREETING'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
|  GREETING
* GREETING
|-
|-
!  RESPONSE
!  RESPONSE
|   
"This is so weird. Everyone here is invisible. I came here to blend in with the crowd.. just my luck."
* This is so weird. Everyone is invisible. I came here to blend in with a crowd. Just my luck
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId  BGMSmith == 1
* GetIsId  'BGMSmith' == 1
* GetStage MS47 < 50
* GetStage 'MS47' < 50
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topic''
* (none)
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|   
''No script''
* (none)
|}
|}


Line 288: Line 281:


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGRedRose'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
"Red Rose Brigade"
* BGRedRose
|-
|-
!  RESPONSE
!  RESPONSE
|   
"Hey, I'm done with them. That's all I have to say about that."
* I don't know you, and I don't think I want to talk to you about them
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetDisposition < 90
* GetDisposition [TARGET] < 90
|-
!  OPTIONS
|
*Info Refusal
|-
|-
!  ADD TOPICS
!  ADD TOPICS
Line 307: Line 303:
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|   
''No script''
* (none)
|}
|}


We then check the '''Info Refusal''' flag.
The "Info Refusal" flag will make sure that the topic text does not get grayed out, so that the player knows there is still more information available for that topic.
 
This means this topic can be revisited and the response will be re-evaluated.


As long as the disposition to the player is less than 90, Smith will give us the brush off when we talk about the Red Rose Brigade.
As long as the disposition to the player is less than 90, Smith will give us the brush off when we talk about the Red Rose Brigade.


Somehow we will need to get that disposition up. If the PC is a member of the thieves guide that will help. We can bribe the NPC or play the disposition game. Of course PC’s with good speech craft will also get a bonus. However, I have deliberately set the threshold high because I want to use the BRANDY idea we set up in Chorrol.  
Somehow we will need to get that disposition up. If the PC is a member of the Thieves Guild, that will help. We can also bribe the NPC or play the disposition game with him. Of course if the player is good with speech craft, that will also get them a bonus. However, I have deliberately set the threshold high because I want to use the brandy idea we set up in Chorrol.


===Designing an Object Script===
===Using choices in dialogue===
To do this we will set up a bit of dialogue where the player can choose give Smith some brandy.


The first bit of scripting we did was to overcome the lack of an NPC to progress our quest. This time the problem is a little less clear. We want to set the game up so that giving some Brandy to Smith that boosts his disposition towards us.
First, create the choice topics: BGBrandyYes, and BGBrandyNo.
 
It is no great chore to add a choices response to the Brandy topic.
 
Choice 1 – Gives him the brandy and bump disposition via a result script<br />
Choice 2 – Refuses to give him brandy.
 
This is how I initially set it up. However there are two big problems with this solution.
 
The first problem is that it is a one time only action. You can’t keep giving him Brandy because the result script as we have set up the quest only allows this script to run once.
 
The second problem is more serious. If we give him some Brandy we have to remove it from the players inventory. But what happens if the player does not have any Brandy in his inventory? Perhaps he drunk the supply Hubart gave him, or sold it, or put it in a safe place and forgot it. The RemoveItem function does not check if an item is there. If it is not the item is removed and the inventory is set at -1.
 
This is not a good situation. Of course the player can reset it to zero by obtaining some more Brandy, but it is messy. It also is silly that the player hands Smith a bottle of Brandy when he hasn’t got one.
 
We need to have some kind of if statements that check the Brandy is in the inventory, and another option to offer more.
 
The solution is to Script this. Here is a working script that does this. We can use a bit of dialogue to set the value of the variable BrandyTalk. Before we look in detail at the script. Take a look through it. Try to work out what each bit is doing. This is a great way to learn scripting. Scour the forums for examples of scripts and try to work out what is happening. 
 
<pre>Scriptname BGM001SmithScript
 
Short DoOnce
Short Button
Short BrandyTalk
Begin GameMode
 
If (BrandyTalk == 1) && (GetStage BGM001 == 60)
  If (Player.GetItemCount "PotionCyrodiilicBrandy" >=1)
    If (DoOnce==0)
      MessageBox "How many Bottles of brandy would you like to give to Smith",
        "None", "One", "Two", "Three", "Four" ;note that this should not
; be returned, it is only because of page width problems that it is.
      Set DoOnce to 1
    EndIf
  EndIf
Else
  Return
EndIf
 
If (DoOnce == 1) && (GetStage BGM001 == 60)
  Set Button to GetButtonPressed
EndIf
 
If (Button >= -1) && (GetStage BGM001 == 60)
  If (Button == 0)
    Set BGM001.BrandyTalk to 0
    Return
  EndIf
 
  If (Button == 1)
    If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 1)
      Player.RemoveItem "PotionCyrodiilicBrandy" 1
      ModDisposition player 15
      Set BrandyTalk to 0
    Else
      Message "You don't have enough Brandy"
    EndIf
  EndIf
 
  If (Button == 2)
    If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 2)
      Player.RemoveItem "PotionCyrodiilicBrandy" 2
      ModDisposition player 30
      Set BrandyTalk to 0
    Else
      Message "You don't have enough Brandy"
    EndIf
  EndIf
 
  If (Button == 3)
    If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 3)
      Player.RemoveItem "PotionCyrodiilicBrandy" 3
      ModDisposition player 45
      Set BrandyTalk to 0
    Else
      Message "You don't have enough Brandy"
    EndIf
  EndIf
 
  If (Button == 4)
    If(Player.GetItemCount "PotionCyrodiilicBrandy" >= 4)
      Player.RemoveItem "PotionCyrodiilicBrandy" 4
      ModDisposition player 60
      Set BrandyTalk to 0
    Else
      Message "You don't have enough Brandy"
    EndIf
  EndIf
EndIf
 
End</pre>
 
We attach this script once compiled to the NPC character BGMsmith using the script box in the character interface.
 
Let’s look more closely at this script.
We use the top section to declare variables.
 
The script is broken into 3 sections contained in a Begin GameMode Block.
 
Firstly
 
<pre>  If (BGM001.BrandyTalk == 1) && (GetStage BGM001 == 60)
    If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 1)
      If (DoOnce==0)
        MessageBox "How many Bottles of brandy would you like to give to Smith",
          "None", "One", "Two", "Three", "Four" ;should not return
        Set DoOnce to 1
      EndIf
    EndIf
  Else
    Return
  EndIf</pre>
 
(Note the MessageBox statement should all be on one line, it is only the result of wrap around text in this document that produces the look above . It should be
 
MessageBox "How many Bottles of brandy would you like to give to Smith", "None", "One", "Two", "Three", "Four"
 
This is the control part of the script. It checks that a number of conditions are true.
Firstly it checks the status of a variable called BrandyTalk. We set this to 1 using a conversation between the PC and Smith. Until this happens the script will fail it conditions and skip to the
 
  Else
    Return
 
This terminates the script and prevents any further processing.
 
The second check is the GetStage check. This will prevent the script from running later in the quests progress.
 
If we have talked to Smith about Brandy, the core bit of this check runs.
 
<pre>  If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 1)
    If (DoOnce == 0)
      MessageBox "How many Bottles of brandy would you like to give to Smith",
        "None", "One", "Two", "Three", "Four" ;should not return
      Set DoOnce to 1
    EndIf
  EndIf</pre>
 
We again carry out some relevant tests. The first checks that the player does indeed have Brandy in his inventory. This uses the GetItemCount function.  We then set up a DoOnce loop to prevent the message box from being displayed again and again.
 
MessageBox is one of the two communication functions. It displays the text in the form of a pop-up box which will also produce a number of labelled buttons. We will look in more detail at some other functions of MessageBox in a later lesson.
 
The second block will only run once the value of DoOnce has been set to one in the above block
 
  If (DoOnce == 1) &&(GetStage BGM001 == 60)
    Set Button to GetButtonPressed
  EndIf
 
GetButtonPressed returns a value equivalent to the ‘buttons’ position in the message box list. It is normally set at -1 but takes the values 0-9 depending on the button selected.
 
MessageBox "Some Message that appears in the Box”, Option A, OptionB, OptionC
 
* ''OptionA selected GetButtonPressed=0''
* ''OptionB selected GetButtonPressed=1''
* ''OptionC selected GetButtonPressed=2''
 
The value selected and assigned to the variable Button is then used in the third part of the script.
 
This is a little longer. It begins with a check that we have assigned a value by pressing the button.
 
  If (Button >= -1) && (GetStage BGM001 == 60)
 
Then we move onto the working parts of the script.
 
If we select none, the script resets the value of BrandyTalk and DoOnce to zero. We are then able to use the script again later.
<pre>  If (Button == 0)
    Set BGM001.BrandyTalk to 0
    Set DoOnce to 0
    Return
  EndIf</pre>
 
If we select one bottle. Then the next bit of script checks if we have enough brandy in our inventory to give Smith one bottle. It takes the bottle from your inventory. It then increases Smiths Disposition towards you by 15.
 
Finally It resets the control variables to allow the script to run again later.
Note in this version we don’t actually give Smith the brandy. There is no technical need to do so.
 
If you don’t have enough you get a message and then it  resets the controlling  variables.
 
<pre>  If (Button == 1)
    If (Player.GetItemCount "PotionCyrodiilicBrandy" >= 1)
      Player.RemoveItem "PotionCyrodiilicBrandy" 1
      ModDisposition player 15
      Set BGM001.BrandyTalk to 0
      Set DoOnce to 0
    Else
      Message "You don't have enough Brandy"
      Set BGM001.BrandyTalk to 0
      Set DoOnce to 0
    EndIf
  EndIf</pre>
 
The remainder of the script is a repeat of this for the options 2 bottles, 3 bottles, and 4 bottles.
 
The trick with any script is to exercise some control over when the script runs. We are controlling this script using a key quest variable called BrandyTalk. Before we can compile our script we will have to add this variable to the quest script.
 
We adjust its value using  topics called BGBrandy, BGBrandyChoice1, and BGBrandyChoice2


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGBrandyNo'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
"No, sorry."
* BGBrandy
|-
|-
!  RESPONSE
!  RESPONSE
|   
"Aw, that's a shame..."
* Yeah, I love the stuff. Have you  any to spare?
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetStage BGM001 == 60
* GetStage 'BGM001' == 60
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topics''
* (none)
|-
!  CHOICES
* BGBrandyChoice1
* BGBrandyChoice2
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|   
''No result script''
* (none)
|}
|}


We can then use the choices to set our control variable to 1.
This is just a simple piece of dialogue.
 
But the problem still remains that this result script will only be carried out once.
 
The solution is simply to make copies of the response and use another variable to increment through them so that each one becomes valid.
 
You can do this as many times as you like.
 
I settled for 4. I think it is unlikely you will need more than three turns but the option is there.


Add another quest variable to the quest script called DoNextBrandy
The "Yes" choice will be more complicated. We will have to check the player's inventory to see if they have any brandy, and if they do, run a script to change the player's disposition.


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGBrandyYes'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
"I sure do. Here, have some!"
* BGBrandyChoice1(Yes, I might have)
|-
|-
!  RESPONSE
!  RESPONSE
|   
"Wonderful! Uh.. what? Oh no! Has the brandy turned invisible, too?!"
* I think I might warm to you.
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetStage BGM001 == 60
* GetStage 'BGM001' == 60
* GetQuestVariable BGM001.DoNextBrandy == 0
* '''GetItemCount 'PotionCyrodiilicBrandy' == 0 (RUN ON TARGET)'''
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topics''
* (none)
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|   
''No result script''
<pre>Set BGMSmith.BrandyTalk to 1
Set BGM001. DoNextBrandy to 1</pre>
|}
|}


The second response info reads
This is the response that the player will get if they have no brandy. You MUST check the "Run on Target" box for the [[GetItemCount]] condition in order for this to work. Otherwise, the GetItemCount will check the Smith NPC's inventory! (The player is the target in this case.)
 
Before making the next response, quickly go back the Smith NPC that you dropped in AleswellInn. Open up the details for the one you dropped - the reference, not the base NPC itself - and name it ''BGMSmithREF''. The ''Persistent Reference'' box should also be checked already.


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGBrandyYes'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
"I sure do. Here, have some!"
* BGBrandyChoice1(Yes, I might have)
|-
|-
!  RESPONSE
!  RESPONSE
|   
"Wonderful! Cheers!"
* I think I might warm to you.
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetStage BGM001 == 60
* GetStage 'BGM001' == 60
* GetQuestVariable BGM001.DoNextBrandy == 1
* '''GetItemCount 'PotionCyrodiilicBrandy' >= 1 (RUN ON TARGET)'''
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topics''
* (none)
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|
|
<pre>Set BrandyTalk to 1
<pre>
Set DoNextBrandy to 2</pre>
BGMSmithREF.ModDisposition Player 15
Player.RemoveItem "PotionCyrodiilicBrandy" 1
</pre>
|}
|}


Add another couple of responses, make all of them goodbyes using the Good bye flag. this ends the dialogue automatically, closes the topic menu and forces the now active script to run.
The ModDisposition function will simply increase the NPCs disposition towards the player by 15. Then one bottle of brandy will be taken from the player's inventory. Then we'll set up the dialogue that leads to these two choices:


We also need to add a negative response. Note there is no result for this one, and you don’t need to make it a goodbye.


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGBrandy'''
|-
|-
!  TOPIC
!  TOPIC TEXT
|   
"Brandy"
* BGBrandyChoice2 (No sorry I’m out)
|-
|-
!  RESPONSE
!  RESPONSE
|   
"Yeah, I love the stuff. Have you any to spare?"
* Pity, I might have liked you more if you did.
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetStage BGM001 == 60
* GetStage 'BGM001' == 60
|-
!  CHOICES
|
*BGBrandyYes
*BGBrandyNo
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topics''
* (none)
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
|   
''No result script''
* (none)
|}
|}


By a combination of speech craft, factions, bribes disposition games and brandy gifts the Player should be able to raise the disposition to 90 eventually. This will trigger the next bit of dialogue and send us towards the quest climax. Return to the BGRedRose topic and add this
The ''Choices'' list is right under the ''Add Topics'' list. Add the choice topics in the same way you would add an add topic in.
 
By a combination of speech craft, factions, bribes disposition games and brandy gifts the Player should be able to raise the disposition to 90 eventually. This will trigger the next bit of dialogue and send us towards the quest climax. Return to the BGRedRose topic and add this:


{| border="1" cellpadding="5"
{| border="1" cellpadding="5"
!colspan=2| '''BGRedRose'''
|-
|-
!  TOPIC
!  TOPIC
|   
"Red Rose Brigade"
* BGRedRose
|-
|-
!  RESPONSE
!  RESPONSE
|   
|   
* Ok, the truth is I've fallen out with the gang. They've threatened to kill me for leaving.
* Ok, the truth is I've fallen out with the gang. They've threatened to kill me for leaving."
* You look like you can take care of them.
* "You look like you can take care of them."
* Watch out for Blair he is a nasty bit of work.
* "Watch out for Blair, though, he's a nasty bit of work."
* Here's the hideout key, and I'll mark the hideouts location on your map.
* "I'll mark the hideouts location on your map. And here's my old key... I hope it still works."
* Mind you I am surprised at Brown. He was a decent chap when I was in the gang.
* "Mind you, I'm surprised at Brown. He was a decent chap when I was in the gang..."
|-
|-
!  CONDITIONS
!  CONDITIONS
|   
|   
* GetIsId BGMSmith == 1
* GetIsId 'BGMSmith' == 1
* GetStage BGM001 == 60
* GetStage 'BGM001' == 60
* GetDisposition >= 90
* GetDisposition [TARGET] >= 90
|-
|-
!  ADD TOPICS
!  ADD TOPICS
|   
''No add topic''
* (none)
|-
|-
!  RESULT SCRIPT
!  RESULT SCRIPT
Line 679: Line 463:
Drop in a MapMarker and give it a Suitable reference name like BGCaveMapMarker.  
Drop in a MapMarker and give it a Suitable reference name like BGCaveMapMarker.  


Journal entry
Journal entry:
''Smith has given me a key for the Red Rose Brigades hideout. I should go to the hideout and see if I can recover my uncle's Key and House Deed.''
''Smith has given me a key for the Red Rose Brigades hideout. I should go to the hideout and see if I can recover my uncle's key and house deed.''


RESULT SCRIPT
Result Script:
<ul><li><pre>Player.Additem "BGHideoutKey" 1
<pre>
ShowMap BGCaveMapMarker</pre></ul>
Player.Additem "BGHideoutKey" 1
ShowMap BGCaveMapMarker
</pre>


==Red Rose Hideout Phase==
==Red Rose Hideout Phase==
Anonymous user

Navigation menu