Jump to content

Banters


Belladonna

Recommended Posts

Looking at the banter dialogue files of some of the game npcs, I think my head will explode. Overload of information. How do you go from one banter to another. Say banter 1 you discuss topic A1 with the npc. Later on in the next banter you talk about topic A1 again, with some new questions but only if you talked about the first topic A1.

 

Timers? How do you use them? Real time, game time. Do you use them in scripts or have them be part of the Global of a dialogue?

Link to comment

The best idea is to take one thing at a time. Look at very small, uncomplicated banters that just happen when they happen. When you understand what's going on there, you move up to a scripted banter that happens when certain conditions are met. When you understand that, you move on to setting up a timed banter or a sequential banter.

 

I'm in the middle of the learning process myself. If you look at the Modding Q&A forum index, you will find it peppered with my "Help me, I'm clueless!" posts.

 

If you viewed even the simplest mod coding in its entirety right away, your head *would* explode. But by looking at it in little pieces, you get there.

 

If you want examples and illustrations, you can check some of the tutorial sites.

 

Check out these links:

 

http://forums.pocketplane.net/index.php/topic,61.0.html

 

http://forums.gibberlings3.net/index.php?showtopic=5886

 

http://forums.gibberlings3.net/index.php?showtopic=2822

Link to comment

OK, I am assuming you have read the G3, PPG, CoM, BWL, SHS, etc. tutorials on this subject, but are still confused a bit. Don't worry, you are in good company - I sure got confused m'self :D

 

 

[EDIT] Posted while berelinde was - she is right. But since I took the time, just in case you have already looked at stuff and are asking about the specifics, the rest of this post is left up for you![/EDIT]

 

Ultra Basics:

Dialogue Files = actor's scripts.

You are asking specific questions about moving between banters, so we will skip ahead to that -

To simplify are two types of dialogues.

  1. B file (BMINSC, etc) "banter file" called randomly by the engine, no need for scripts - just conditions so that they show up after they make sense (for example, if Minsc is in the party. No need to have a banter show up when one of the actors are on break!)
  2. J file (MINSCJ, etc) "joined dialogue file" called specifically by a script (MINSC.BCS says "ok, time for Minsc to talk since we just visited the Giant Space Hamster House of Fun, and Boo needs to say something about staying behind!")

On both B-file banters and J-file dialogue, it is possible to set up conditions that make things make sense. The simplest form is B-file, so let's do that first:

 

CHAIN IF ~conditions I want met~ THEN BEGIN ~banterfile~ NameOfDialogueToAdd

~text for actor 1~

== ~banterfile actor 2~

== ~banterfile actor 1~

== ~banterfile actor 2~

END

IF ~conditions I want met~ THEN REPLY ~PC text reply 1~ DO ~actions I want taken~ EXIT

 

CHAIN IF ~InParty("minsc") InMyArea("minsc") InParty("dynaheir") InMyArea("dynaheir")~ THEN BEGIN ~BMINSC~ MinscAndBooSeeCutie
~Ohohoho, Boo, I saw you looking at that other Giant Space Hamster!~
== ~BDYNAH~ ~I worry for thee, Minsc; dost thou truly hear boo?~
== ~BMINSC~ ~Did you not hear Boo whistle? The Giant Hamster, she was a cutie!~
== ~BDYNAH~ ~*sigh* Mayhap we can find Gavin and get thee healed, Minsc.~
END
IF ~~ THEN REPLY ~I am not sure minsc needs healing, Dynaheir.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",1)~ EXIT
IF ~~ THEN REPLY ~I am sure Minsc needs healing, Dynaheir - we will have to go find Gavin now.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",2)~ EXIT
IF ~~ THEN REPLY ~I think that you should dump Minsc off as soon as possible, Dynaheir.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",3)~ EXIT

There are lots of ways of coding this, but basically now you have a random banter that fires. At the end of it, you have set conditions that you can use to trigger or modify other talks.

 

Here goes banter #2. It won't fire until you have had banter #1, because we say so in the conditions to start the talk. There are lots of really efficient and fun ways of combining this next one into a big responsive chain, but let's keep it really simple at first and just set up a banter that would fire only if PC had replied #2, "We need to find Gavin".

 

CHAIN IF ~Global("MinscDynahHealingTalk","GLOBAL",1)  InParty("minsc") InMyArea("minsc") InParty("dynaheir") InMyArea("dynaheir")~ THEN BEGIN ~BMINSC~ MinscAndBooSeeCutie2
~Boo says we should go back and get that Cute Space Hampster's phone number. Can we go back now?~
== ~BDYNAH~ ~<CHARNAME>, Minsc dost truly need healing. Stay thy course, and lead us to Gavin presently.~
== ~BMINSC~ ~What is wrong with me, Dynaheir? Am I making smells again?~
== ~BDYNAH~ ~No, thy odor is appropriate, Minsc. Worry not about such things. I have sworn to find thee a healer anon.~
END
IF ~~ THEN REPLY ~I am sure Minsc does not need healing, Dynaheir. Give him a break and allow him his time with Boo, please.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",4)~ EXIT
IF ~~ THEN REPLY ~OK, let's go find this Gavin dude. I hear he might be ok in the healing department.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",5)~ EXIT

 

 

So now this talk will only trigger if the PC made reply #2, and the responses all make sure that the condition is changed so either something else can happen or so the banter can't repeat.

 

Problem is, it its random. We want all of this to happen at a specific time or place, and follow on after a decent interval. So, let's play with J-files. Pretend we have visited the Cute Space Hamster and set a global that tells us we were there (lots of ways of doing this, but beyond this discussion).

 

We EXTEND_BOTTOM Minsc's script with something like this:

IF
Global("MinscDynahHealingTalkStarts","GLOBAL",0)
Global("VisitedSpaceHamsterCutie","GLOBAL",1) //
InParty("minsc")	
InMyArea("minsc")
InParty("dynaheir")
InMyArea("dynaheir")
THEN RESPONSE #100
SetGlobal("MinscDynahHealingTalkStarts","GLOBAL",1)
StartDialogueNoSet(Player1)
END

We adjust the dialogue conditions we set to reflect the work now done in the script, like this:

CHAIN IF ~Global("MinscDynahHealingTalkStarts","GLOBAL",1)~ THEN BEGIN ~MINSCJ~ MinscAndBooSeeCutie 
DO ~SetGlobal("MinscDynahHealingTalkStarts","GLOBAL",2) //stops repeats
~Ohohoho, Boo, I saw you looking at that other Giant Space Hamster!~
== ~DYNAHJ~ ~I worry for thee, Minsc; dost thou truly hear boo?~
== ~MINSCJ~ ~Did you not hear Boo whistle? The Giant Hamster, she was a cutie!~
== ~DYNAHJ~ ~*sigh* Mayhap we can find Gavin and get thee healed, Minsc.~
END
IF ~~ THEN REPLY ~I am not sure minsc needs healing, Dynaheir.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",1)~ EXIT
IF ~~ THEN REPLY ~I am sure Minsc needs healing, Dynaheir - we will have to go find Gavin now.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",2)~ EXIT
IF ~~ THEN REPLY ~I think that you should dump Minsc off as soon as possible, Dynaheir.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",3)~ EXIT

 

Now we want to make the next talk happen in a short time. For this we have our choice of timers, Real Time or Game Time. Real Time is not changed with sleeping, actions, etc - it is "real" passage of time: what the player experiences. Game Time is internal time, or what the player's *character* experiences. Either one is not really a "timer' like you have in a kitchen - it is just a number that the engine compares against to figure out when to allow stuff to happen (technically this is slightly off, but it works for me :) ).

Timers can be used in either B or J file materials, but they are much more useful on J file (scripted) dialogues. On the B side, they just indicate how long the *minimum* time is before the engine gets to have access to the banter - there is no guarantee that the banter will fire, and it will happen randomly (caveat - this is a gross generalization - moddarz have wayz ). J files, on the other hand, work better and are easier to control:

 

We EXTEND_BOTTOM Minsc's script again with something like this:

IF
Global("MinscDynahHealingTalkStarts","GLOBAL",2) //end condition on script
Global("VisitedSpaceHamsterCutie","GLOBAL",1) 
InParty("minsc")	
InMyArea("minsc")
InParty("dynaheir")
InMyArea("dynaheir")
THEN RESPONSE #100
SetGlobal("MinscDynahHealingTalkStarts","GLOBAL",3)// stops looping
SetGlobalTimer("HealingTalkTimer","GLOBAL",TWO_DAYS) //2 in-game days later
END

IF
Global("MinscDynahHealingTalkStarts","GLOBAL",3)
GlobalTimerExpired("HealingTalkTimer","GLOBAL") //check for timer expiration
InParty("minsc")	
InMyArea("minsc")
InParty("dynaheir")
InMyArea("dynaheir")
THEN RESPONSE #100
SetGlobal("MinscDynahHealingTalkStarts","GLOBAL",4)
StartDialogueNoSet(Player1)
END

 

The original response to #2 still works, with some modification:

CHAIN IF ~Global("MinscDynahHealingTalk","GLOBAL",1)~ THEN BEGIN ~MINSCJ~ MinscAndBooSeeCutie2
~Boo says we should go back and get that Cute Space Hampster's phone number. Can we go back now?~
== ~DYNAHJ~ ~<CHARNAME>, Minsc dost truly need healing. Stay thy course, and lead us to Gavin presently.~
== ~MINSCJ~ ~What is wrong with me, Dynaheir? Am I making smells again?~
== ~DYNAHJ~ ~No, thy odor is appropriate, Minsc. Worry not about such things. I have sworn to find thee a healer anon.~
END
IF ~~ THEN REPLY ~I am sure Minsc does not need healing, Dynaheir. Give him a break and allow him his time with Boo, please.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",4)~ EXIT
IF ~~ THEN REPLY ~OK, let's go find this Gavin dude. I hear he might be ok in the healing department.~ DO ~SetGlobal("MinscDynahHealingTalk","GLOBAL",5)~ EXIT

 

There are certainly ways of setting timers from within dialogue, but this gives you the basic rundown of how a single banter could work as both B file and J file, and how you use timers and conditions to flow dialogue from one actor to another, and from one set of conditions to another.

Link to comment
The best idea is to take one thing at a time. Look at very small, uncomplicated banters that just happen when they happen.

 

I'd also advise forbanters in particular do not look at extracted bio's files. They extract as EXTERNs structure that in modding was replaced relatively early on by much simpler CHAIN. Check out the links Berelinde provided and it will start making sense real soon!

Link to comment
It would appear I will be doing a lot of reading. What did I get myself into? :D

 

Something that will make you think and will make you learn. Both of these are desirable. :)

 

There are going to be moments when you beat your head against your keyboard. And then there will be moments of silent satisfaction when you realize that you have finally figured out how to do something you would never have been able to do even a week before.

 

There are going to be times when you are stumped and post a question or a bit of code only to spot the really obvious mistake as soon as you hit "post." You will invariably have forgotten to sign in, so you will be unable to delete it. But at least it will have been anonymous.

 

And then there is that moment of utter joy, the first time you see your NPC on the screen and that first dialog window opens.

 

That will invariably be followed within seconds by your first bugfixing. Don't feel bad about staring at the code you thought would work and didn't, wondering how you're ever going to find what went wrong. You will.

 

As I said, I'm going through that process myself. I consider it a major accomplishment if I can get a 500-line file to compile without any parsing errors. I actually keep track of how many lines I get through before hitting the first one, just to see if I'm getting any better, just because I like the challenge of self-improvement.

 

All I can say is that it's been a roller-coaster ride.

Link to comment
I consider it a major accomplishment if I can get a 500-line file to compile without any parsing errors.

 

And if you just added a new file and the mod compiles without errors, that generally means you forgot to put it on tp2 :D

Link to comment

Did I tell you about that one? I was up until 2 am trying to figure out why none of the new content was there!

 

But it did compile OK. Got a new method that avoids my most common parse error: now if I've just written a state with a number of transitions, I put up blank IF ~~ THEN BEGIN etc states for all the transitions with nothing after the SAY but ~~ and an IF ~~ THEN EXIT END at the end of it, then go back and fill them in, making the necessary addtions. That way I don't have any "cannot resolve state" errors on compiling. This is probably the oldest trick in the book, but it's new to me.

Link to comment

The best way to learn is in trial and error, plus reading another person's mod files. Well provided that person knew what they were doing.

 

She will see. :D

 

I am getting some practice making a mini mod right now. It was an idea that I had for the longest time, time to put it to the test.

Link to comment
Got a new method that avoids my most common parse error: now if I've just written a state with a number of transitions, I put up blank IF ~~ THEN BEGIN etc states for all the transitions with nothing after the SAY but ~~ and an IF ~~ THEN EXIT END at the end of it, then go back and fill them in, making the necessary addtions. That way I don't have any "cannot resolve state" errors on compiling. This is probably the oldest trick in the book, but it's new to me.

 

Heh, I'm a lazy bastard-ess who prefers to write in D to start with and then just deal with parses. But by whatever reason I don't get unresolved states too often. I guess my iron-rule to keep every dialogue under 30 states and uses numeric only tags helps :D

 

@Belladonna:

 

Have fun! It'll work out, you'll see. :)

Link to comment

Archived

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

×
×
  • Create New...