(Originally written for magrat, but if it can help you, all the better.)All programmers know this trick: learning from someone else's code is quicker than using heavy textbooks.
So, if you choke on tutorials, your way forward is clear: borrowing code from other modders.
Here's for PC-NPC interaction. For NPC-NPC interaction, watch my hands.
So, you've got a banter between your new NPC and - surprise! - Anomen. Naturally, you want to show this arrogant wannabe where his place is. Right? Right.
Let's call the new NPC Johnny. His banter file will be called BA#John - A# for prefix, so nobody else steals our filename. (But we will steal their code, you remember.)
Anomen: ~Verily, it is fair weather, friends.~
Johnny: ~As if. The sun is stinging my eyes, it's hot, I'm hung over. And I am not your friend.~
Anomen: ~I was not talking to you, Johnny. Helm knows, you need admonishment.~
Johnny: ~Right. And you are our father figure. Be a bad daddy to <CHARNAME>, though, seeing how you keep staring at her butt.~
Anomen: ~Foul beast! If you are going to repeat the word within my earshot, I'll --~
Johnny: ~Gods, Anomen, we were just talking about the weather! Everything is about <CHARNAME> these days, eh?~
EXITFirst and foremost: every banter ends with an
EXIT. Not
END, but
EXIT. Half of my errors are about this sweet word. The other half, of course, is about missing these little beauties:
~. One before, one after:
~Verily, it is fair weather, friends.
~Easy enough? You bet.
Now, you will need one small file:
interdia.2da. Find it in your /override folder, and copy it somewhere, so you can access it at any time.
What do you need it for? Well, you have Johnny's banter file(BA#John, or BA#JOHN, in case you've forgotten), but you need Anomen's banter file, and then, later, Cernd's banter file, and Keldorn's banter file. You can't do a banter without banter files, right? That's why they are called banter files.
interdia.2da will help you.
It looks like this: ANOMEN BANOMEN BANOME25
BANOMEN is Anomen's banter file for SoA, BANOME25 - Anomen's banter file for ToB. We're writing a banter for SoA, so it's BANOMEN.
To tell the compiler what to do, we use
== BANOMEN instead of Anomen:
== BA#JOHN instead of Johnny:
And our banter looks like this:
== BANOMEN ~Verily, it is fair weather, friends.~
== BA#JOHN ~As if. The sun is stinging my eyes, it's hot, I'm hung over. And I am not your friend.~
== BANOMEN ~I was not talking to you, Johnny. Helm knows, you need admonishment.~
== BA#JOHN ~Right. And you are our father figure. Be a bad daddy to <CHARNAME>, though, seeing how you keep staring at her butt.~
== BANOMEN ~Foul beast! If you are going to repeat the word within my earshot, I'll --~
== BA#JOHN ~Gods, Anomen, we were just talking about the weather! Everything is about <CHARNAME> these days, eh?~
EXIT
Sweet. And now, the simplest and the scariest-looking part: the "head" of our banter.
It always looks like a simple logic operator: IF ~many conditions~ THEN. Now, what conditions?
Well, this is simple: Johnny and Anomen have to be in party and able to talk, right? And Anomen, who starts the conversation, has to see Johnny
to let Johnny insult him. So, it's like this:
IF ~InParty("Anomen")
InParty("A#John")
// not "Johnny", but "A#John" - we got to have a unique prefix. There's only one Johnny, right?!StateCheck("Anomen",CD_STATE_NOTVALID)
// "not CD_STATE_NOTVALID" is a cool state that means "able to talk"!StateCheck("A#John",CD_STATE_NOTVALID)
See("A#John")~ //
Anomen starts the banter, so we don't have to write "Anomen sees Johnny", but just "Sees Johnny"THEN
Let's put the head and the rest of our banter together.
We have to call our banter something:
CHAIN IF ~InParty("Anomen")
InParty("A#John")
!StateCheck("Anomen",CD_STATE_NOTVALID)
!StateCheck("A#John",CD_STATE_NOTVALID)
See("A#John")~ THEN
BANOMEN A#AnomenTalksToJohnny1~Verily, it is fair weather, friends.~
== BA#JOHN ~As if. The sun is stinging my eyes, it's hot, I'm hung over. And I am not your friend.~
== BANOMEN ~I was not talking to you, Johnny. Helm knows, you need admonishment.~
== BA#JOHN ~Right. And you are our father figure. Be a bad daddy to <CHARNAME>, though, seeing how you keep staring at her butt.~
== BANOMEN ~Foul beast! If you are going to repeat the word within my earshot, I'll --~
== BA#JOHN ~Gods, Anomen, we were just talking about the weather! Everything is about <CHARNAME> these days, eh?~
EXIT
CHAIN is the word that has to stand in the beginning of each banter. It means "several banter files are going to talk now, pay attention".
Anomen begins the conversation, so we have to put
BANOMEN right after THEN. Note how I deleted
"== BANOMEN" from the first line - we don't need two "BANOMEN"s in a row, do we?
And
A#AnomenTalksToJohnny1 is the unique name of the banter. You can use any name here, as long as it is special(and you see it only once in your banter file).
And this is it? Almost. The last bit is also the most important one: we want this banter to happen exactly ONCE. Not two, five, or ten times - this is called a bug report.
Well, if you read
this tutorial, you know what I am going to do. I am going to set a variable:
CHAIN IF ~InParty("Anomen")
InParty("A#John")
!StateCheck("Anomen",CD_STATE_NOTVALID)
!StateCheck("A#John",CD_STATE_NOTVALID)
Global("A#AnomenTalksToJohnny1","GLOBAL",0)See("A#John")~ THEN BANOMEN A#AnomenTalksToJohnny1
~Verily, it is fair weather, friends.~
DO ~SetGlobal("A#AnomenTalksToJohnny1","GLOBAL",1)~== BA#JOHN ~As if. The sun is stinging my eyes, it's hot, I'm hung over. And I am not your friend.~
== BANOMEN ~I was not talking to you, Johnny. Helm knows, you need admonishment.~
== BA#JOHN ~Right. And you are our father figure. Be a bad daddy to <CHARNAME>, though, seeing how you keep staring at her butt.~
== BANOMEN ~Foul beast! If you are going to repeat the word within my earshot, I'll --~
== BA#JOHN ~Gods, Anomen, we were just talking about the weather! Everything is about <CHARNAME> these days, eh?~
EXIT
- The banter only runs, if "A#AnomenTalksToJohnny1" variable is 0. After Anomen speaks to Johnny, "A#AnomenTalksToJohnny1" is 1. So, the banter will run only once, and will never ever run again. Which is just what we want.
So, this is it! Copy-paste, change name and text, repeat.
P.S. What if Johhny was starting the conversation? Then we'll have
CHAIN IF ~InParty("Anomen")
InParty("A#John")
!StateCheck("Anomen",CD_STATE_NOTVALID)
!StateCheck("A#John",CD_STATE_NOTVALID)
Global("A#JohnnyTalksToAnomen1","GLOBAL",0)
See("Anomen")~ THEN BA#JOHN A#JohnnyTalksToAnomen1 // We check if Johnny sees Anomen, and Johnny starts the conversation~Hey, you, knighty! Say it again!~
DO ~SetGlobal("A#JohnnyTalksToAnomen1","GLOBAL",1)~== BANOMEN ~Verily, it is fair weather, friends.~
== BA#JOHN ~As if. The sun is stinging my eyes, it's hot, I'm hung over. And I am not your friend.~
== BANOMEN ~I was not talking to you, Johnny. Helm knows, you need admonishment.~
== BA#JOHN ~Right. And you are our father figure. Be a bad daddy to <CHARNAME>, though, seeing how you keep staring at her butt.~
== BANOMEN ~Foul beast! If you are going to repeat the word within my earshot, I'll --~
== BA#JOHN ~Gods, Anomen, we were just talking about the weather! Everything is about <CHARNAME> these days, eh?~
EXIT