Jump to content

Home

Dialog editing tutorial


Recommended Posts

Mod note: Originally posted in this thread. ~M

 

 

 

I’m going to use my own, terribly written, dialogues as examples to introduce you to the wonderful world of dialogue editing and creation. Below is an overview of what you might see if you opened up a conversation in tk102’s dialogue editor. The way things look is entirely due to whether you have the mode set to KotOR or KotOR II. You can change the mode by clicking on “Mode” then selecting “Toggle Mode: KotOR” or “Toggle Mode: TSL.”

 

overviewk1iv9.th.jpg

An overview of what you might see in K1 mode.

 

overviewk2pg2.th.jpg

An overview of what you might see in K2 mode.

 

The system is simple. Each line you see is called a node. Red coloured nodes are nodes that the NPC will speak and blue ones are the player’s options. If the NPC speaks over multiple nodes a blue (continue) will be in between the nodes, this will be skipped over in the game, allowing the NPC to talk over many nodes before the player can next choose something to say. If (already listed) appears beside a node then it is a link to another node, a copy of it, essentially – these prevent you from having to type out multiple copies of the same line (much handier than you can possibly realise now). You can find the original by right clicking on it and selecting “Jump to original.” or by double-clicking the node ~tk

 

To add an NPC node simply press Ctrl+E or go to “Edit” and click “Add new entry.” To add a player reply node press Ctrl+R or go to “Edit” and click “Add new reply.” You should be able to type what you want the player to see in the large, white text box over to the right hand side of the screen.

 

Scripting and dialogues

 

Scripting can be confusing, especially to newcomers with no background in programming (heck, it still confuses me and I’ve been doing it for two years now). Unfortunately, it’s something you have to learn if you want to create more sophisticated mods for KotOR.

 

There are two types of scripts that can be attached to a KotOR dialogue conditional and action. A conditional script will return TRUE or FALSE. If the conditions are met then the node will be shown to the player (hurrah!) if they are not (boohoo) then the dialogue will drop down to the node beneath it. If there is no node beneath it then the game will exit the dialogue. In this way we can create dialogues with multiple openings, or even change the way an NPC talks to the player depending on the player’s actions.

 

multiplenodesex0.th.jpg

 

If the condition for 1 is not met then the game will try 2. If that doesn’t work then it will go to 3 and so on. It is sometimes useful (for debugging purposes) to create a node right at the bottom with no conditions attached to it saying something like “I SHOULD NOT BE HERE.” This tells you that there is a fault in the checking of or setting of conditions and that nothing else is going wrong. In KotOR dialogue files there is space for just one conditional script; in TSL we have the added luxury of being able to use two. Also, in TSL, we have the “Not” tick-box. This means that if a script returns FALSE then the dialogue will read it as TRUE. For example, if you had a script that checked if the global number “000_FooBar_Talked” was set to 1 and you wanted to check if it was not 1 without creating another script you could just check this box!

 

Action scripts are a little more exciting but not a lot; not when compared to the prospect of finding a real, living gizka in your bathroom – though, admittedly, that may be a little freaky. These are used throughout the game to accomplish a wide variety of tasks ranging from turning the NPC hostile to giving the player the Awesome Lightsaber of +5 Wisdom. Suffice it to say: they’re useful. Again, with KotOR there is space for just one script but there are two fields in TSL.

 

I’m not going to go over the basics of scripting conditionals and actions in this post as it is already on the verge of becoming long enough to make people want to hang themselves after reading it – or during, of course.

 

Writing conversations

 

Well… we’re finally here… writing the conversation. The first stage, and this may seem a little obvious but it’s where I went wrong when attempting to write my first conversation, is to open tk102’s editor and. Go to File --> New to open up a new dialogue. It should be devoid of anything save the root node which in tk’s editor appears as the file pathway or (until the dialogue is saved) “New Dialog.” Click on this wonderful root and add a new node (as we discussed above). Type what you will in there. The first line after the root is always an NPC line.

 

Now click on that entry and add in three responses using Ctrl+R as we discussed above. Every time you add an empty response you’ll have to click on the NPC line again because the editor will switch focus to the new line. Type whatever you wish to fill these lines.

 

We just spoke about the dialogue dropping down to the node below and we’re about to use it. Imagine the power at your fingertips! You may cackle evilly if you wish… just no wearing spandex and dressing up like Darth Malak, please. Click on our stylish root node and add a new entry as we discussed above and type something for the NPC to say the second time the player comes to speak to them and add in your beautifully crafted player responses.

 

Now… we’re going to attach some global scripts. These are standard game resources. We’re using them to check if the player has spoken to the NPC beforehand. If your dialogue if for KotOR then type “k_act_talktrue” in the “Script that fires when spoken” field on your first speaker node and then type “k_con_talkedto” in the “Script that determines availability” field. In TSL the principle is the same. Set conditional #1 to “c_talkedto” and set the script #1 field to “a_talktrue.” Any scripts that you ever place in these fields should not have the extension attached.

 

Creating links is another thing we touched on above. These are very useful… so much so that I could marry them if the state would allow it but alas… we’re a bit behind the times in these parts. To create a link simply copy a node and paste it elsewhere in the dialogue – simple as that!

 

Shockingly… that’s it for basic conversations – hope that wasn’t too soul destroying to read through.

 

Other interesting thingmobobs

 

Click on your root node and revealed to you will be an entirely new set of options – the fun just doesn’t stop, does it? The fields of interest here are mainly grouped in the area shown below:

 

propertiesbo6.th.jpg

 

Script that fires when conversation ends – As it says… this is the script to have the game execute when the dialogue ends

Ambient track – the name of a music file in the streammusic folder that you want to play over the dialogue (without the extension, as ever). It is, however, advisable to stop the area music via a script when using this feature.

Camera model – the name of the animated camera your dialogue will use.

Skippable – Please, unless you’re dealing with a plot essential cutscene, always check this. There is nothing more annoying than a pazaak player with an “unskippable” dialogue.

Animated Cut – Sets whether or not this is uses an animated camera – this must be checked to make use of the camera you specified in the “Camera model” field.

UnequipHItem – Unequip headgear from all NPCs for the duration of this dialogue, they will be added back later.

UnequipItems – Unequip all other items from NPCs for the duration of the dialogue. Again, they will be returned at the end of the conversation.

 

Apologies for the ridiculous size of this post... I just got a little carried away. I'm also not sure if any of this is of use to you but I was a little bored, you see.

Link to comment
Share on other sites

  • 1 month later...

-How would I make it so that once you've trigged a dialog option (and any connected scripts), you don't get the dialog option again? I get the feeling this has to do with globals/booleans, which I've never really understood.

 

You'd usually use either local or global variables for this.

  • Local variables are stored on a particular object (like a creature, placeable, trigger, area or module) and can only be accessed when that object is present in the active game world (i.e. exists in the same module as the player currently is in). There are a fixed number of available local variable slots for each object.
     
    In TSL there are 160 boolean slots (numbered 0-159) and 32 number slots (numbered 0-31) for each object. A boolean variable is like an on/off switch and can only contain either the value FALSE (0) or not FALSE (true). A number variable can contain a value between 0 and 255.
     
    Note: As far as I can tell you can't reliably set local variables on inventory items (weapons, robes, armbands etc).
     
     
  • Global variables can be accessed from anywhere in the game and are not set for a particular object. Unlike local variables they are accessed by a text tag/name instead of a slot number, and they must be added to the globalcat.2da file for the game to recognize them.

 

Which type you choose to use is generally up to you, but just tracking dialog stages of a single NPC is often best to set as either a local number variable, or a series of local boolean variables, on that NPC, since the info is only needed by that NPC thus reducing the amount of global data the game need to keep track of, and you won't have to modify any 2DA files for them to work.

 

For things like plot progress, quests and the like you usually use global variables, since those can be checked from anywhere and aren't associated with one particular NPC or object.

 

In TSL there are a number of ready-made scripts you can use to set and check both global and local variables in dialogs.

 

Setting:

  • a_global_dec - decreases the global number variable whose tag is set in the String Param field by the number set in the P1 field.
  • a_global_inc - increases the global number variable whose tag is set in the String Param field by the number set in the P1 field.
  • a_global_set - sets the global number variable whose tag is set in the String Param field to the number set in the P1 field.
  • a_global_bool_set - sets the global boolean variable whose tag is set in the String Param field to the value set in the P1 field. ( 0 = false, 1 = true )
     
     
     
  • a_localn_dec - decreases the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, by the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
  • a_localn_inc - increases the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, by the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
  • a_localn_set - sets the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, to the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
  • a_local_set - sets the local boolean variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter. (leave the String Param field blank to use the object running the script = the conversation owner)

 

Getting:

  • c_global_eq - returns true if the global number specified by the String Param field equals the number set in the P1 field.
  • c_global_gt - returns true if the global number specified by the String Param field is greater than the number set in the P1 field.
  • c_global_lt - returns true if the global number specified by the String Param field is lower than the number set in the P1 field.
  • c_global_bet - returns true if the global number specified by the String Param field is higher than the number set in the P1 field and lower than the number set in the P2 field.
  • c_global_set - returns true if the global boolean specified by the String Param field is set (true).
     
     
     
  • c_localn_eq - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, matches the value in the P2 field.
  • c_localn_gt - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is greater than the value in the P2 field.
  • c_localn_lt - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is lower than the value in the P2 field.
  • c_local_set - returns true if the local boolean set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is true (i.e. not FALSE).
  • c_local_notset - returns true if the local boolean set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is FALSE (0).

 

P1, P2 and String Param above refer to the input fields listed to the right of the script name field in tk102's DLG Editor.

 

Some local numbers and booleans are already used by generic scripts such as the Random Loot and AI scripts, and as such should be avoided for any objects of that type that have AI scripts/loot scripts. Here is a likely incomplete list of some locals already used:

[u]Creatures:[/u]
Boolean 1-3 - Creature AI, ambient NPC settings.
Boolean 10 - Dialogs, used to set that the creature has been talked to once.
Boolean 20-28 - Creature AI, used to activate userdefined script events.
Boolean 29 - Creature AI, used to set if NPC should play ambient animations when idle.
Boolean 30-64 - Reserved range for scenario/plot specific uses, some NPCs use them, most do not.
Boolean 65 - Creature AI, used to set of the NPC should walk around randomly when idle.
Boolean 66-86 - Creature AI, various settings set in the NPC spawn scripts.
Boolean 87 - Creature AI, blocks out the AI for this creature if set.
Boolean 88 - Creature AI defined, but likely unused in K2:TSL.
Boolean 89 - Creature AI, sets the creature to use the Boss Combat AI, overriding their normal AI style.
Boolean 90 - Creature AI, sets that the creature has activated their energy shield in combat.
Boolean 91 - Creature AI, toggles userdefined event for the OnDialogEnd event handler.
Boolean 92 - Creature AI, sets that a force using NPC has buffed with Resist/Immunity at start of battle.
Boolean 94 - Creature AI, sets that the creature has entered combat.
Boolean 95 - Creature AI, sets the creature to use the KotOR1 Malak end fight AI.
Boolean 96 - Creature AI, sets creature to use a zone controller to determine their combat zone.
Boolean 97 - Creature AI, setting for the OnDialog event.
Boolean 98-109 - Creature AI, used by the waypoint walking/ambient animation system.
Boolean 110-159 - Generally unused as far as I can tell.

Number 0-2 - Creature AI, used by the waypoint walking/ambient animation system.
Number 3-6 - Creature AI, internal state info for last attack used, chosen attack pattern etc.
Number 7 - Creature AI, Zone Controller this creature is attached to, if any.
Number 8-9 - Creature AI, settings for healer AI, how much to heal and how often.
Number 10-11 - Creature AI, used for turrets to determine rate of fire.
Number 12-31 - Generally unused as far as I can tell.


[u]Placeables:[/u]
Boolean 10-19 - Security terminals, used to set the user's choice of action.
Boolean 55 - Containers, container has been bashed and broken item substituted.
Boolean 57 - Containers, used to set that random loot has been spawned.


[u]Triggers:[/u]
Boolean 40 - Used to set that the trigger has been tripped for one-shot triggers.

For more about local variables: see this thread ~tk

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...