Ted's RPG Rant

A place to rant about RPG games, particularly the Temple of Elemental Evil. Co8 members get a free cookie for stopping by. Thats ONE cookie each, no seconds.

Thursday, August 18, 2005

Writing Dialogue for ToEE part 2

Lets jump straight into writing dialogue today. Open up 00275Demo.dlg. Also, open up Phalzyr's thread you downloaded (or copied out somewhere) last time, or go to www.Co8.org and look at it again.

The very first thing on the dlg page is {1}. This is, not surprisingly, a line number. The game accesses the file by line numbers, and the dlg file advances the dialogue by going to different line numbers. Easy, init. You may remember that our script, in py00275Demo.py, will start the dialogue at line 1 each time the player clicks on this character. So lets see what line 1 is.

{1}{G:}{G:}{}{}{}{} // a greetings line from the end, as circumstances dictate.

The stuff beyond the '//' is a comment, you can erase that when you are ready to put this file into action or leave it there, it doesn't matter. Its what goes before it that is the juicy stuff that the game accesses.

So its {--LINE NUMBER--} {--COMMENT TO MALE PC--} {--COMMENT TO FEMALE PC--} {} {--LINE NUMBER AGAIN--} {} {--FUNCTION TO EXECUTE--}

Lets go through those in order.

{--LINE NUMBER--} You will notice that in this template, and in most dlg files in the game, the comments from the NPCs are in 'tens', and the replies from the player are in the unit between. Ie, the NPC comments are in line numbers 10, 20, 30 etc and the player's comments are in 11-15, 21-25, 31-35 etc. This is NOT essential, but is very handy in keeping track of what is happening. It IS necessary that the line numbers be sequential, because the game accesses the file sequentially, it does not parse the file and put all the numbers in order. If there is some catastrophic screw-up in the dlg file somewhere, the game will generally run the dlg file normally until that point, then everything after it will come up blank.

You may notice Phalzyr says, "you are limited to showing 5 PC replies at a time". This means only 5 will show up on the screen at any one time. You can have more than 5 replies, you can have as many as you want if you script them to occur under different circumstances (and, generally speaking, more is better!) But there is only room in the dlg box for 5 to show up at any one time. Don't believe me? Do my mod, and try taking all 8 of Lila's requested items to her at once. When she asks you what you have for her, all 8 (plus a 'never mind' response) will trigger a comment from the PC, but only the first 5 will be seen on screen. As you hand over each item, something else will takes its place in the list until there is room for the 'never mind' response to occur.

{--COMMENT TO MALE PC--}{--COMENT TO FEMALE PC--} Ever wondered how the NPC knows to call your cute little Elven maidens "lass" and your big boofy barbarian blokes "sir"? Simple - they have seperate dlg entries. In the majority of cases they will be identical (and I can tell you from bug-hunting, the writers of ToEE used copy-n-paste a LOT!). But the option is there for them to be different, and indeed they can be wildly different and talking about two completely different things if you like (likewise, you can script the replies to only discuss certain options if the PC is of a particular gender. We will get to that shortly. Its a good example of why you might want to have a lot more than 5 replies available.)

Note: one of the most COMMON mistakes you can make in writing dlg files, is forgetting to do both of these. If there is very little variation between your male and female comments, and you are copy-n-pasting a lot (nothing wrong with that btw), you can easily forget to do it once, and since it will be surrounded on both sides by a number of single comment PC replies, the line looks normal. BUT, when you run the file, it screws up immediately after that point. Why is that?

Lets see how the game views it. The game is looking for:

{--#--}{--COMMENT--}{--COMMENT--}{}{}{}{}
{--#--}{--REPLY--}{}{--#--}{}{--#--}{}
{--#--}{--REPLY--}{}{--#--}{}{--#--}{}
{--#--}{--REPLY--}{}{--#--}{}{--#--}{} etc

What all those other brackets do we will get to in a minute.

BUT, if we leave out a comment, what does the game see?

{--#--}{--COMMENT--}{}{}{}{}{--#--}
{--REPLY--}{}{--#--}{}{--#--}{}{--#--}
{--REPLY--}{}{--#--}{}{--#--}{}{--#--}
{--REPLY--}{}{--#--}{}{--#--}{}{--#--}

When it goes for the missing NPC comment, it accesses the empty brackets in its place, and everything moves forward one. So in the next line number there is instead a comment, nothing where the next line number to go to should be (don't worry, I haven't told you where that is yet, just take my word for it) and so the game can't continue. It will probably just show nothing on the screen, and default the last (blank) line to be an 'exit' comment.

Don't worry if you make this mistake btw, we all have ;-)

Identifying these mistakes is much easier in something like Notepad++ than just normal ol' Notepad. Or, if you are like me and enjoy the spectacular simplicity of Notepad, try opening your .dlg files in Phalzyr's Proto-Ed when bug-hunting. This makes them MUCH easier to see, and also quickly picks up the other easy mistake to make, using the wrong shape brackets. If you are writing a big .dlg file and typing quickly it is all too easy to type '(' instead of '{' and screw everything right up.

Lets move on to those last 4 sets of brackets. In many .dlg files in the game these will all be blank, and the NPC comment line will end with {}{}{}{}. In other files, you may notice the line number gets repeated in the second bracket: eg for our first line, they would be {}{1}{}{}. You can do that or not as you like: I haven't met anyone who is entirely sure why it does or doesn't have to be there. I know I stopped bothering with it a while back and have noticed no ill effects whatsoever. Just be aware that sometimes the game has it.

The last set of brackets are important: here is where you can stick a function or script you want to execute at this point. A good example is from Liv's reworking of the tower encounter:

{366}{To arms my troops!}{To arms my troops!}{}{}{}{}
{367}{[more]}{}{1}{}{368}{}
{368}{Ready your spells! Draw your swords! Mark your targets!}{Ready your spells! Draw your swords! Mark your targets!}{}{}{}{buff_npc(npc,pc)}
{369}{[more]}{}{1}{}{370}{}
{370}{These fools killed Lareth!! Let us avenge his death!}{These fools killed Lareth!! Let us avenge his death!}{}{}{}{buff_npc_two(npc,pc); game.global_flags[833] = 1}

Ok: since this is a pretty linear 'dialogue' where the players only option is to click '[more]', Liv has not bothered spacing the line numbers by 10. For the moment, ignore the odd numbered lines (they are the players replies in this case, we will get to them next) and focus on the NPC comments. You will notice that each one starts with the line number, repeats the comment twice (once for male, once for female) and then has 3 empty sets of brackets, followed by (for the latter two) a command that should remind you of some of the scripts we have already seen in the .py file: buff_npc(npc, pc).

So... what do you suppose happens when the game executes these lines? If you answered "it goes looking for buff_npc and buff_npc_two in the .py file", you are completely correct! Have a cookie! We don't have to go into any detail here as to what these commands do, suffice it to say they execute scripts already put in the .py file. The effect should be obvious: the NPCs will buff themselves for the fight!

They also execute another command, game.global_flags[833] = 1. Again, we will look at global flags and variables in depth later. For now, it is enough to know you can set flags and variables and then check them later. Here, Liv assigns the value 1 to flag 833. There are only two values for a flag, 0 and 1, ie the flag, like a flag on a mailbox, is either up or down. Its default is 0, the flag is not set and gets ignored. Here we are 'setting' the flag (or flagging the encounter, or whatever jargon you want to call it). Later, at a specific situation (probably when you chat to Lareth again) you can have a script to check this flag. If it is 0 or unset, then you haven't been to the tower. If it is 1 or set, (as it would be in this case) then you have been to the tower encounter and your dialogue with Lareth can reflect that.

All make sense? For a list of some of the commands you can execute straight from dialogue like this, look at Phalzyr's thread under the section 'Actual Functions: Those with an * in front are known to work directly from dialog execute field.' Damn but he is a handy fella! Be aware that some only seem to function from the player's replies, not from the NPC's line. We will look at the more common ones in depth later, for now try popping some dlg files in the game and seeing how they are used. (The dialogue files, if I have not mentioned this are in Atari/Temple of Elemental Evil/Data/Dlg).

Now to the player replies. They look very similar but are actually quite different. They begin with a line, follow it with a comment and the last one can execute a command, but in between is where the changes happen.

Lets look at them.

{--LINE NUMBER--} {--REPLY TO NPC--} {} {--INTELLIGENCE OF PC--} {--CONDITION UNDER WHICH THIS LINE APPEARS--} {--LINE NUMBER TO GO TO--} {--FUNCTION TO EXECUTE--}

The first two are fairly obvious. The third bracket is always empty. The fourth is where the interesting stuff starts: it examines the intelligence of the PC, and displays the appropriate reply. There are 3 common parameters for this;

8 - this means anyone above Int of 8 will get this option. This is the normal conversation options.

-7 - this is for players with an Int of 7 or less. This is commonly called the 'dumb PC' option. The same thing might be said, but phrased in such a way that the PC who says it doesn't sound too bright. (In the game, this is often played for laughs).

1 - this is for anyone with Int 1 or over. This is a 'common' reply option, such as we saw with the '[more]' option above, it doesn't matter what the Int of the PC is. If it is under 1, they would be paralyzed and unable to converse, so it covers everyone. It is used for common replies such as 'goodbye'.

You can also script specific stuff for smarter characters if you like, by adding a reply line that has, say, 15 or 17 (or more) here, so that only really intelligent PCs get the chance to explore this part of the dialogue. An example of that would be in Burne's puzzles, where only smarter PCs are given the option of explaining their correct answer (and therefore winning).

Anyway, the meaning of all this is that just as NPC comments come in male and female varietes, so there are usually TWO versions of each reply: one for normal characters, one for dumb characters. But they are shown on seperate lines, and they are not compulsory for the game (as we saw the male and female ones were). Just remember if you dont have 'above 8/ under 7' options, you have to have a '1' option, or you might create a situation where a character with an unexpected Int happens to be in the dialogue and there is no reply that suits them.

Moving on, the next bracket can contain wider conditions. It can also be left blank if you want that reply to always appear. Lets revisit Liv's tower encounter, the scenario has now moved on a bit, the baddies have buffed themselves and the PCs are claiming Lareth is not dead, he has merely run off:

{390}{You lie! Lareth was many things, but not a coward. You will die for your insolence!}{You lie! Lareth was many things, but a coward? No. You will die for your insolence!}{}{}{}{}
{391}{I think not. We crushed Lareth with ease. And now we will crush you and your band of paltry scum.}{}{8}{}{0}{npc.attack( pc )}
{392}{Me gonna bash yer skull!!}{}{-7}{}{0}{npc.attack( pc )}
{393}{I never said Lareth was a coward. He is waiting for us back at our hideout. Let me go get him.}{}{8}{pc.skill_level_get(npc, skill_bluff) >= 10}{500}{}
{394}{Layrest not cowherd. He wate fer us at da cave. @pcname@ brings him to ya.}{}{-7}{pc.skill_level_get(npc, skill_bluff) >= 10}{500}{}
{395}{Look you moron, Lareth is a friend of ours and he is going to be pretty damn angry with your behavior.}{}{8}{pc.skill_level_get(npc, skill_intimidate) >= 10}{400}{}
{396}{Me Layrest friend. He gonna smash ye fer dis bad stuffs.}{}{-7}{pc.skill_level_get(npc, skill_intimidate) >= 10}{400}{}
{397}{Relax, friend. Lareth is our friend. I'll go get him and we can sort this all out. No problem here.}{}{8}{pc.skill_level_get(npc, skill_diplomacy) >= 10}{500}{}
{398}{Calm. @pcname@ is Layrest friend. Me go gets him. Yous sees.}{}{-7}{pc.skill_level_get(npc, skill_diplomacy) >= 10}{500}{}
{399}{[attack]}{}{1}{}{0}{npc.attack( pc )}

Ok: line 390 is the NPC response. After that, the even numbers are for Intelligent PC responses (note the 8) and the odd numbers are for Dumb PCs (note the -7), except for the last line (399) which is a common 'cut the crap lets just attack' response. There are attack options in the first lines (391-392) too, but it is not obvious that combat will immediatley ensue: if the player chooses this in an attempt to bluff the baddies, he or she will get a shock!

Depending on the circumstances, these may be the only ones that show up, as they are 'unconditional' (the brackets after the Int value '1' are empty), so the players will always have the option of fighting their way out.

Getting ahead of ourselves slightly: you may remember I just said that the last brackets for the PC are the same as for the NPC, they are for a command to be executed. Here, the command is 'npc.attack(pc)'. I won't bother explaining what that does! But note this is one of those that can only be executed from the player's reply, since it terminates the dialogue mode. Anything that terminates the dialogue can only be initiated from the player's reply, since if it was done by the NPC, you would not see their comment, it would flash up and terminate simultaneously.

Now, the conditions: we get a smart PC and dumb PC version of each, and they are;

pc.skill_level_get(npc, skill_bluff) >= 10

pc.skill_level_get(npc, skill_intimidate) >= 10

pc.skill_level_get(npc, skill_diplomacy) >= 10

The command 'get' tells the game to fetch the value at a certain point: it might be a critter flag (different to the global flags we just saw) or an attribute or check for a feat or a class or a gender, or other things. Here, it is checking the different skills. If the PC has a skill level equak to or greater than 10 in any of these, that option would appear. Hence if they have greater than 10 in all 3, all 3 will be given. On the screen, for a smart PC that would look like this:

Brigand leader: You lie! Lareth was many things, but not a coward. You will die for your insolence!

1. I think not. We crushed Lareth with ease. And now we will crush you and your band of paltry scum.

2. I never said Lareth was a coward. He is waiting for us back at our hideout. Let me go get him.

3. Look you moron, Lareth is a friend of ours and he is going to be pretty damn angry with your behavior.

4. Relax, friend. Lareth is our friend. I'll go get him and we can sort this all out. No problem here.

5. [attack]


Obviously there will also be the different colours and the little icons to show you are using a skill.

Conditional statements, as Phalzyr says, can have operands such as == (exclusively equal), >= (greater than or equal), <= (less than or equal), > (greater than), < (less than), != (not equal).

Finally, there is the only set of brackets we have not looked at yet - line number. This is straightforward: if the player chooses this reply, then it will go to the line number in this (second last) bracket. In the examples above, it will go to a different line number depending on the skill used, as the Brigand leader reacts differently to each conversational gambit the player attempts. But the line number will be the same for both smart and dumb PCs: that is not essential btw (you could have both smart- or dumb-specific dialogue) but it is normally the case. The line number must of course be an NPC comment, not a PC reply line, or the dialogue will terminate abruptly. A line number of '0' terminates the dialogue, whether because you are saying goodbye, entering combat, teleporting to a different location, the NPC is running off, you are moving to the barter screen or for whatever reason.

Well... that was a mouthful! And we never did write any dialogue :( We never even got to find out what the {G:} means! That's for next time. For your homework, have a look at the template, and look at some .dlg files in the game: note that they will
ALWAYS conform to this pattern described, no matter what the content, ALWAYS ALWAYS ALWAYS.

To go straight to the next chapter, click [THIS].

0 Comments:

Post a Comment

<< Home