How to script conversation between two or more NPCs
A basic scripted conversation between two NPCs is fairly simple to set up. Getting three or more NPCs to talk to each other, particularly if you want them to do something besides stand still, is more complicated. We'll cover all of these possibilities, starting with the simplest.
Creating a basic scripted conversation between two NPCs
There are two simple ways to get NPCs to talk to each other:
- An NPC with a Find package targeting another NPC will automatically start a conversation with the second NPC, beginning with the HELLO conversation topic. This is the same way that NPCs start random conversations with each other.
- Use StartConversation to trigger the conversation. This can be useful if you want to start the conversation with a custom topic (i.e. something besides HELLO).
In order to force the NPCs to have a particular conversation, you need to set up the dialogue infos that they will use so that they link together into a complete conversation. The basic principles are as follows:
1. The simplest way to make a conversation is to create a new topic for each response on the Conversation tab of the Quest window, create an info under each topic, and use the "Link To" and "Link From" fields to link the infos together in the order that you want them to be spoken. This is fine for a very short conversation, but creating a new topic for each info can become cumbersome for longer conversations.
2. A more sophisiticated way (and the way most conversations in Oblivion were created) is to use a single topic, with the infos conditionalized on a variable which is incremented in the results field of each info. Look at the Conversation tab of the MSConversations quest in the Oblivion master file for some examples of how this is done. The importants steps are as follows:
- You'll need to create the conversation in a quest which is marked to "Allow repeated conversation topics" (see Quest Data Tab) -- normally, the game will not use the same topic twice in the same conversation (as a way to avoid repetition in random conversations), but in this case we want to use the same topic repeatedly in created our scripted conversation. (In our example, MSConversations is a quest created for all miscellaneous quests to use for scripted conversations.)
- On the Conversation tab, create a topic for your conversation (say MS40Conversation). Now create the starting info for your conversation (assuming you are using StartConversation -- if you are using a Find package, the first info will have to be a HELLO, which can then link to your custom topic).
- Create a quest variable to track the progress of the conversation (say MS40.convo). Conditionalize the first info with this variable (GetQuestVariable MS40.convo == 0), plus whatever additional variables are necessary (e.g. GetIsID, GetStage, etc.).
- Make sure the "Run immediately" box is checked. This tells the game to run the results when the conversation is being created, instead of when it is spoken. Without this checkbox, the variable which we are using to conditionalize the conversation will not be incremented and the conversation will not work.
- In the "Link To" field, add your custom converation topic -- we are going to link the topic to itself for the whole conversation. Since this is the start of the conversation, leave the "Link From" field blank.
- In the results field, increment your variable (e.g. set MS40.convo to MS40.convo + 1) so that the next info (which we are about to create) will now pass its conditions.
- Assuming you want the NPCs to trade off speaking, leave the "Next Speaker" as "Target" (if you want an NPC to speak more than one line in a row, you can change that to "Self").
- Now that we've created a good template, copy that info and change the text to the next line in the conversation. We only have to make two other changes to this new info: (a) Add our custom topic to the "Link From" field (so that it can link from the first info), and (b) change the condition (e.g. GetQuestVariable MS40.conv == 1).
- Repeat this process for the rest of the conversation. The final info in the conversation should have its "Link To" field left blank, and have "Goodbye" checked to indicate that it serves as the end of the conversation (otherwise the game will automatically tack on a random GOODBYE).
Creating a speech by a single NPC
Setting up a "speech" by an NPC (where he is the only one talking) is actually a variant of the process given above. You can either use StartConversation to tell him to talk to himself (e.g. BurdRef.Startconversation BurdRef), or set up the conversation so that all the infos are "Next Speaker: Self" (e.g. you have a second NPC present, but he never speaks).
Creating a conversation between multiple NPCs
Getting more than two NPCs to talk to each other, or getting NPCs to talk and move at the same time, requires abandoning the game's conversation generator completely, and handling everything by script. The key commands here are Say and SayTo, in combination with script timers which track when it is time for the next NPC to speak. All the NPC conversations in the character creation sequence were handled in this way.
- Create a quest script to run the main timer, and track the conversation variables (see CharGenQuest script). The main timer is a standard script timer:
begin gamemode ; count down timer if convTimer > 0 set convTimer to convTimer - getSecondsPassed endif end
- Create a variable in the quest script to track whose turn it is to speak. For example, in the CharGenQuest script:
; used by conversation scripts to tell whose turn to speak short speaker short target ; 1 = Baurus ; 2 = Renote ; 3 = Glenroy ; 4 = Emperor ; 5 = player (as target)
- In each NPC's script, add a section which is looking for the quest variable to tell them it is time to speak. Say and SayTo return the time (in seconds) that the specified dialogue will take to speak, so the NPC's script sets the quest timer variable as well. For example, in Glenroy's script:
begin gamemode ; talk when it is time if CharacterGen.speaker == 3 && CharacterGen.convTimer <= 0 set target to CharacterGen.target if target == 0 set CharacterGen.convTimer to Say CharGenMain 1 elseif target == 1 set CharacterGen.convTimer to SayTo BaurusRef, CharGenMain 1 elseif target == 2 set CharacterGen.convTimer to SayTo RenoteRef, CharGenMain 1 elseif target == 3 set CharacterGen.convTimer to SayTo GlenroyRef, CharGenMain 1 elseif target == 4 set CharacterGen.convTimer to SayTo UrielSeptimRef, CharGenMain 1 elseif target == 5 set CharacterGen.convTimer to SayTo player, CharGenMain 1 endif endif end
- The last step is to actually create the dialogue. Each info should be conditionalized both on the speaker and a tracking variable (so that you can use a single topic in your scripts, e.g. CharGenMain). The results field of each info increments the tracking variable, and sets the speaker and target variables (if necessary) for the next speaker. For example:
set characterGen.convCount to characterGen.convCount + 1 set characterGen.speaker to 1 ; Baurus set characterGen.target to 2 ; Renote
See the CharacterGen quest, CharGenMain topic for an extensive example.