Jump to content


Photo

The NPC joining dialogue


  • This topic is locked This topic is locked
No replies to this topic

#1 berelinde

berelinde

    Troublemaker

  • Modder
  • 4916 posts

Posted 07 July 2007 - 05:30 PM

On to the next step: writing the joining dialogue.

This is a tricky dialogue, for both technical reasons and plot reasons. It's tough from a technical standpoint because it is often the first thing you're going to write, so you might not be familiar with everything WeiDU can do for you. It's challenging from a plot perspective because you need to accomplish so much with this dialogue: it has to be original, it has to show a little of the NPC's character, it has to give the PC a reason to take the NPC along, *and* it has to give the PC a chance to bow out if the NPC is not to his or her tastes, if the party is already full, or if they just want to pass on recruiting the NPC at this time.

Here's a very basic joining dialogue, but it isn't very exciting. In fact, it's downright pathetic, but it will let me explain the basics.

When you are done, save this as B!Lyn.d inside the Dialogue folder.
BEGIN ~B!Lyn~

APPEND ~B!Lyn~
IF ~NumTimesTalkedTo(0)~ THEN BEGIN ExampleJoin
SAY ~Well met! I'm Lynneth, a traveling adventuress. If you are more hero than villain, I will join your cause.~
IF ~~ THEN REPLY ~Welcome aboard!~ GOTO LynJoin
IF ~~ THEN REPLY ~Forget it!~ GOTO LynReject
IF ~~ THEN REPLY ~How about later?~ GOTO LynLater
END

IF ~~ THEN BEGIN LynJoin
SAY ~Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END

IF ~~ THEN BEGIN LynReject
SAY ~Ah, well, your loss.~
IF ~~ THEN DO ~EscapeArea()~ EXIT
END

IF ~~ THEN BEGIN LynLater
SAY ~Perhaps.~
IF ~~ THEN EXIT
END

IF ~NumTimesTalkedToGT(0)~ THEN BEGIN SecondChance
SAY ~Have you changed your mind?~
IF ~~ THEN REPLY ~Yes! Please join me!~ GOTO LynJoin
IF ~~ THEN REPLY ~No. I've no use for you.~ GOTO LynReject
IF ~~ THEN REPLY ~This is a bad time. Can we talk later?~ GOTO LynLater
END
END

Now, for the commented code. Hopefully, the comments will make it easier to follow what I'm doing.

// You have to begin the dialogue file. This adds the dialogue file to the list of in-game dialogue files.
BEGIN ~B!Lyn~

// Now, we're going to add to the dialogue file we just began using APPEND. 
APPEND ~B!Lyn~

// In order for the PC to be able to just walk up to an NPC and start talking, there has to be some kind of "condition" in effect. This is called a trigger. In this case, we're using the number of times the NPC is talked to. You don't have to worry about keeping track of this, or incrementing it. The game engine will do it for you. The value is associated with the creature's DV.
// Please note that anything that says REPLY means PC reply.
IF ~NumTimesTalkedTo(0)~ THEN BEGIN ExampleJoin
SAY ~Well met! I'm Lynneth, a traveling adventuress. If you are more hero than villain, I will join your cause.~
IF ~~ THEN REPLY ~Welcome aboard!~ GOTO LynJoin
IF ~~ THEN REPLY ~Forget it!~ GOTO LynReject
IF ~~ THEN REPLY ~How about later?~ GOTO LynLater
END


// Look where we're performing actions here, right before the transition. In this case, the trasition is EXIT. In the previous state, the transitions were GOTO. Setting variables and joining the party are the actions
IF ~~ THEN BEGIN LynJoin
SAY ~Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END


// In this case, the PC has said "Not now, not ever," so there is no reason for Lynneth to hang around. She'll leave the area via EscapeArea(). This essentially removes her from the game. Again, the action takes place right before the transition.
IF ~~ THEN BEGIN LynReject
SAY ~Ah, well, your loss.~
IF ~~ THEN DO ~EscapeArea()~ EXIT
END

// Here, Lynneth will hang around. The PC doesn't want her right now, but doesn't want to send her away, either.
IF ~~ THEN BEGIN LynLater
SAY ~Perhaps.~
IF ~~ THEN EXIT
END

// If the PC asked her to stay around, this is the dialogue that will show the second time. Note the difference in the trigger. It's got a GT in there. That means "greater than," so this trigger will be valid, i.e. true, whenever the number of times the NPC has been talked to exceeds 0.
// Also note that it's perfectly alright to use states from the previous dialogue.
IF ~NumTimesTalkedToGT(0)~ THEN BEGIN SecondChance
SAY ~Have you changed your mind?~
IF ~~ THEN REPLY ~Yes! Please join me!~ GOTO LynJoin
IF ~~ THEN REPLY ~No. I've no use for you.~ GOTO LynReject
IF ~~ THEN REPLY ~This is a bad time. Can we talk later?~ GOTO LynLater
END

// You need this second END to end the APPEND state.
END

And here's a much more complicated example, the one that will actually be used in the mod. It illustrates how to set a few variables, using conditional replies, and moving a character to a different location.
BEGIN ~B!Lyn~

APPEND ~B!Lyn~
IF ~NumTimesTalkedTo(0)~ THEN BEGIN LynPC0
SAY ~What do you think of this rapier, Danis?~
IF ~~ THEN REPLY ~It's very nice, but I'm not Danis.~ GOTO LynPC0.1
IF ~Class(Player1,FIGHTER_ALL)~ THEN REPLY ~I prefer a broadsword myself.~ GOTO LynPC0.2
IF ~~ THEN REPLY ~Too fancy. That scrollwork at the hilt would catch a point too easily.~ GOTO LynPC0.2
IF ~~ THEN REPLY ~I think you must mean someone else.~ GOTO LynPC0.3
IF ~~ THEN REPLY ~Aren't you a little precious to be shopping for iron-mongery?~ GOTO LynPC0.4
IF ~~ THEN REPLY ~Sorry, but I haven't time to chat with you.~ GOTO LynPC0.5
END

IF ~~ THEN BEGIN LynPC0.1
SAY ~Yes, I can see that.~
IF ~~ THEN GOTO LynPC0.3
END

IF ~~ THEN BEGIN LynPC0.2
SAY ~Do you think so? Oh, wait! You aren't Danis, are you?~
IF ~~ THEN GOTO LynPC0.3
END

IF ~~ THEN BEGIN LynPC0.3
SAY ~Sorry, my mistake. He was just here a moment ago. But I don't recall seeing you here before.~
IF ~~ THEN GOTO LynPC0.6
END

IF ~~ THEN BEGIN LynPC0.4
SAY ~Do you think so? Appearances can be deceiving. I mistook you for a swordsman, just now.~
IF ~~ THEN GOTO LynPC0.6
END

IF ~~ THEN BEGIN LynPC0.5
SAY ~Sorry, my mistake. I thought you were someone else.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.6
SAY ~So what brings you to Athkatla? You don't have the look of a local.~
++ ~You wouldn't believe me if I told you.~ + LynPC0.7
++ ~How is a local supposed to look?~ + LynPC0.8
+ ~Class(Player1,MAGE_ALL)~ + ~No, I've lived here all my life.~ + LynPC0.9
+ ~!Class(Player1,MAGE_ALL)~ + ~No, I've lived here all my life.~ + LynPC0.10
++ ~I'm not. Now if you'll excuse me, I must be leaving.~ + LynPC0.11
END

IF ~~ THEN BEGIN LynPC0.7
SAY ~Maybe I wouldn't... or maybe I would.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.8
SAY ~A lot less dangerous!~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.9
SAY ~First appearances can be deceiving, but you seem to me to be a practitioner of the arts magical. Considering how few of that vocation roam Athkatla openly, that marks you as unusual, at the very least.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.10
SAY ~First appearances can be deceiving, but you seem to me to be a bit more dangerous than many you meet strolling the Promenade.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.11
SAY ~Er, yes, of course.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.12
SAY ~You have the scent of adventure about you. What cause do you serve?~
++ ~My own, I assure you!~ + LynPC0.13
+ ~GlobalLT("Chapter","GLOBAL",4)~ + ~I seek to rescue my childhood friend.~ + LynPC0.14
++ ~I help out where I can.~ GOTO LynPC0.15
+ ~GlobalLT("Chapter","GLOBAL",4)~ + ~I am in pursuit of the madman who tortured me.~ + LynPC0.14
++ ~Whimsy.~ + LynPC0.13
++ ~None I would care to discuss with you.~ + LynPC0.15
END

IF ~~ THEN BEGIN LynPC0.13
SAY ~Ha! How could it be any other? Yet if you are more hero than villain, I would help you.~
IF ~~ THEN DO ~SetGlobal("B!JoinOffer","GLOBAL",1)~ GOTO LynPC0.16
END

IF ~~ THEN BEGIN LynPC0.14
SAY ~A worthy cause, and one I would gladly assist.~
IF ~~ THEN DO ~SetGlobal("B!LynJoinOffer","GLOBAL",1)~ GOTO LynPC0.16
END

IF ~~ THEN BEGIN LynPC0.15
SAY ~Forgive me. I did not mean to intrude. Farewell, then.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.16
SAY ~My name is Lynneth. Will you accept my offer?~
++ ~Yes. Join with me.~ DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ + LynPC0.17
++ ~Not at this time.~ + LynPC0.18
++ ~What of your companion?~ + LynPC0.19
END

IF ~~ THEN BEGIN LynPC0.17
SAY ~Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END

IF ~~ THEN BEGIN LynPC0.18
SAY ~Very well. I have taken a room at the Mithrest Inn. If you change your mind, I'll be there for a while.~
IF ~~ THEN DO ~EscapeAreaMove("AR0704",526,659,3)~ EXIT
END

IF ~~ THEN BEGIN LynPC0.19
SAY ~Do you mean Danis? He isn't a traveling companion! We were just talking about weapons a moment ago, and I hadn't realized he left.~
++ ~In that case, join with me.~ + LynPC0.17
++ ~Ah, well, I'll be going, then.~ + LynPC0.18
END

IF ~NumTimesTalkedToGT(0) Global("B!LynJoinOffer","GLOBAL",1)~ THEN BEGIN LynPC1
SAY ~So you return! Have you reconsidered my offer?~
++ ~No, we're just passing through.~ + LynPC1.1
++ ~Yes, please join me.~ + LynPC1.2
END

IF ~~ THEN BEGIN LynPC1.1
SAY ~Safe travels, then!~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC1.2
SAY ~Very good! Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END

IF ~NumTimesTalkedToGT(0) !Global("B!LynJoinOffer","GLOBAL",1)~ THEN BEGIN LynPC2
SAY ~Back again? Well, I have been thinking.~
IF ~~ THEN GOTO LynPC0.12
END
END

Now, for the commented version. I'm not going to repeat comments, but you can look them up above.
BEGIN ~B!Lyn~

APPEND ~B!Lyn~

// Again, using the NumTimesTalkedTo(0) trigger. That one is dead useful.
IF ~NumTimesTalkedTo(0)~ THEN BEGIN LynPC0
SAY ~What do you think of this rapier, Danis?~
IF ~~ THEN REPLY ~It's very nice, but I'm not Danis.~ GOTO LynPC0.1

// This is a conditional response. I want this option to be open only to fighters and fighter multiclasses. Look at the syntax for the condition (trigger). It's got the trigger, Class, the object, Player1, and the class, FIGHTER_ALL.
// It's perfectly all right to have more than one transition go to the same state. In fact, it makes life a lot easier. Please see the illustration that follows for the difference between "state" and "transition."
IF ~Class(Player1,FIGHTER_ALL)~ THEN REPLY ~I prefer a broadsword myself.~ GOTO LynPC0.2
IF ~~ THEN REPLY ~Too fancy. That scrollwork at the hilt would catch a point too easily.~ GOTO LynPC0.2
IF ~~ THEN REPLY ~I think you must mean someone else.~ GOTO LynPC0.3
IF ~~ THEN REPLY ~Aren't you a little precious to be shopping for iron-mongery?~ GOTO LynPC0.4
IF ~~ THEN REPLY ~Sorry, but I haven't time to chat with you.~ GOTO LynPC0.5
END

IF ~~ THEN BEGIN LynPC0.1
SAY ~Yes, I can see that.~
IF ~~ THEN GOTO LynPC0.3
END

IF ~~ THEN BEGIN LynPC0.2
SAY ~Do you think so? Oh, wait! You aren't Danis, are you?~
IF ~~ THEN GOTO LynPC0.3
END

IF ~~ THEN BEGIN LynPC0.3
SAY ~Sorry, my mistake. He was just here a moment ago. But I don't recall seeing you here before.~
IF ~~ THEN GOTO LynPC0.6
END

IF ~~ THEN BEGIN LynPC0.4
SAY ~Do you think so? Appearances can be deceiving. I mistook you for a swordsman, just now.~
IF ~~ THEN GOTO LynPC0.6
END

IF ~~ THEN BEGIN LynPC0.5
SAY ~Sorry, my mistake. I thought you were someone else.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.6
SAY ~So what brings you to Athkatla? You don't have the look of a local.~

// WeiDU allows you to abbreviate, under certain circumstances. Here, the first + stands for IF, the second, for THEN REPLY, and the third, for GOTO. That third + *always* stands for GOTO. Something to remember when we move on to CHAIN. I'll be using the shorthand, because I hate typing out IF ~~ THEN REPLY all the time.
++ ~You wouldn't believe me if I told you.~ + LynPC0.7
++ ~How is a local supposed to look?~ + LynPC0.8
+ ~Class(Player1,MAGE_ALL)~ + ~No, I've lived here all my life.~ + LynPC0.9

// Here, the ! is means everything *but* the condition specified. This is why I must use tildes around my dialogue file names, as my prefix contains a !. If yours doesn't, you can leave off the tildes around ~FILE~.
+ ~!Class(Player1,MAGE_ALL)~ + ~No, I've lived here all my life.~ + LynPC0.10
++ ~I'm not. Now if you'll excuse me, I must be leaving.~ + LynPC0.11
END

IF ~~ THEN BEGIN LynPC0.7
SAY ~Maybe I wouldn't... or maybe I would.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.8
SAY ~A lot less dangerous!~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.9
SAY ~First appearances can be deceiving, but you seem to me to be a practitioner of the arts magical. Considering how few of that vocation roam Athkatla openly, that marks you as unusual, at the very least.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.10
SAY ~First appearances can be deceiving, but you seem to me to be a bit more dangerous than many you meet strolling the Promenade.~
IF ~~ THEN GOTO LynPC0.12
END

IF ~~ THEN BEGIN LynPC0.11
SAY ~Er, yes, of course.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.12
SAY ~You have the scent of adventure about you. What cause do you serve?~
++ ~My own, I assure you!~ + LynPC0.13

// As with GT meaning "greater than," LT means "less than." This means this PC response option will only be available in chapters 1 through 3. Not 4.
+ ~GlobalLT("Chapter","GLOBAL",4)~ + ~I seek to rescue my childhood friend.~ + LynPC0.14
++ ~I help out where I can.~ + LynPC0.15
+ ~GlobalLT("Chapter","GLOBAL",4)~ + ~I am in pursuit of the madman who tortured me.~ + LynPC0.14
++ ~Whimsy.~ + LynPC0.13
++ ~None I would care to discuss with you.~ + LynPC0.15
END

IF ~~ THEN BEGIN LynPC0.13
SAY ~Ha! How could it be any other? Yet if you are more hero than villain, I would help you.~

// Here, I set a global variable. This will allow me to track whether or not Lynneth has already offered to join the party. Setting a variable is an action. It goes right before the transition.
IF ~~ THEN DO ~SetGlobal("B!JoinOffer","GLOBAL",1)~ GOTO LynPC0.16
END

IF ~~ THEN BEGIN LynPC0.14
SAY ~A worthy cause, and one I would gladly assist.~
IF ~~ THEN DO ~SetGlobal("B!LynJoinOffer","GLOBAL",1)~ GOTO LynPC0.16
END

IF ~~ THEN BEGIN LynPC0.15
SAY ~Forgive me. I did not mean to intrude. Farewell, then.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC0.16
SAY ~My name is Lynneth. Will you accept my offer?~
++ ~Yes. Join with me.~ DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ + LynPC0.17
++ ~Not at this time.~ + LynPC0.18
++ ~What of your companion?~ + LynPC0.19
END

IF ~~ THEN BEGIN LynPC0.17
SAY ~Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END

IF ~~ THEN BEGIN LynPC0.18
SAY ~Very well. I have taken a room at the Mithrest Inn. If you change your mind, I'll be there for a while.~

// It really isn't practical for a character to stand around a shop forever. Here, I'm moving her to an inn to wait. EscapeAreaMove means that she will leave via the door, and then vanish. If the party has her surrounded and she can't get to the door, she'll bump off the characters for a while, then just vanish. The format for this syntax is EscapeAreaMove("Area",x-coordinate,y-coordinate,face-direction) of the destination. In this case, she'll go to the Mithrest Inn, to the spot indicated, and face west. Face directions start at 0 (due south) and move through 15.
IF ~~ THEN DO ~EscapeAreaMove("AR0704",526,659,3)~ EXIT
END

IF ~~ THEN BEGIN LynPC0.19
SAY ~Do you mean Danis? He isn't a traveling companion! We were just talking about weapons a moment ago, and I hadn't realized he left.~
++ ~In that case, join with me.~ + LynPC0.17
++ ~Ah, well, I'll be going, then.~ + LynPC0.18
END

// This is the dialogue that happens if the PC has heard her initial offer, but rejected it. This will happen in the Mithrest Inn.
IF ~NumTimesTalkedToGT(0) Global("B!LynJoinOffer","GLOBAL",1)~ THEN BEGIN LynPC1
SAY ~So you return! Have you reconsidered my offer?~
++ ~No, we're just passing through.~ + LynPC1.1
++ ~Yes, please join me.~ + LynPC1.2
END

IF ~~ THEN BEGIN LynPC1.1
SAY ~Safe travels, then!~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN LynPC1.2
SAY ~Very good! Well met and well joined!~
IF ~~ THEN DO ~SetGlobal("B!LynnethJoined","GLOBAL",1) JoinParty()~ EXIT
END

// If the global variable says the PC never heard the offer before. In this case, she'll still be in the shop. I loop back into the first dialogue with the PC, and that's fine.
IF ~NumTimesTalkedToGT(0) !Global("B!LynJoinOffer","GLOBAL",1)~ THEN BEGIN LynPC2
SAY ~Back again? Well, I have been thinking.~
IF ~~ THEN GOTO LynPC0.12
END
END

Comments and suggestions go here.

Attached Images

  • StateTransition.jpg

Edited by berelinde, 08 July 2007 - 07:11 AM.

"Imagination is given to man to console him for what he is not; a sense of humor, for what he is." - Oscar Wilde

berelinde's mods
TolkienAcrossTheWater website
TolkienAcrossTheWater Forum