using WeiDU. Hopefully it's not too difficult to understand for a totally new
user. This tutorial has been updated as of 19/11/2004, in an attempt to clarify some previously confusing spots, and to update the WeiDU syntax as necessary. I'll add the new additions in blue text, at least until I decide it looks bad.
Table of Contents
First off, a checklist of everything that needs to be done to get your NPC into the
game.
I. Making the dialogue (.dlg) files for your NPC.
II. Making a creature (.cre) file of your actual NPC, with stats and equipment.
III. (optional) Making a script (.bcs) for your creature.
IV. Making a WeiDU installation script (.tp2) to install your NPC on other's PCs
Section I: .D and .DLG files
The first thing to do is make a .dlg file for your NPC. This will be what allows
your NPC to talk to the PC, and thus join the party. First off, make a blank .d
file, which you can do by making a blank .txt and re-naming it. I'll name mine
J#Vondo.d. The first line of code we should right is "BEGIN J#Vondo", which means
that at the time of compilation, it will create a file called *J#Vondo.dlg.
* Note that you don't need to use the prefix "J#", this is just a naming convention
I use for all my files to keep them from overwriting other people's custom files. Your
prefix could be TJ or 01 or y6 or something along that vein.
The code should look like this so far:
Code:
BEGIN J#Vondo
The basic parts of our dialogue should have two States. One is for the first
time the PC and NPC meet, and the second for when the PC has refused their initial
offer to join and has returned. Here's how to write the first state...
IF ~NumTimesTalkedTo(0)~ FirstMeeting
(This is the trigger for the first state. If ~Vondo hasn't talked yet~ then start
the block named "FirstMeeting". Get it?)
SAY ~Greetings good <SIRMAAM>! My name is Vondo the Just.~
(This is what Vondo says. The next block is all the possible responses to his
words.)
IF ~GlobalLT("Chapter","GLOBAL",3)~ THEN REPLY ~Hey Vondo, you seen Irenicus around here?~ GOTO InquireIrenicus
IF ~~ THEN REPLY ~Heya.~ GOTO Greet
+ ~Class(Player1,PALADIN)~ + ~I know a paladin when I see one!~ + BothPaladins
++ ~Go away.~ + GoAway
(These are all the possible options players can choose. Option 1 is only available
if the player is in chapter 1 or 2. Option 2 and 4 are always available (IF ~~),
and option 3 is available if the PC is a Paladin.)
Notice how the syntax of each reply is a bit different. The first two are using the long form, while the second two use a newer, shortened format. The first "+" means "IF". The second "+" is "THEN REPLY". The third "+" is for "GOTO". This saves quite a lot of time.
END
(This terminates this block of dialogue.)
So now our .d file should look like this:
Code:
BEGIN J#Vondo
IF ~NumTimesTalkedTo(0)~ THEN BEGIN FirstMeeting
SAY ~Greetings good <SIRMAAM>! My name is Vondo the Just.~
+ ~GlobalLT("Chapter","GLOBAL",3)~ + ~Hey Vondo, you seen Irenicus around here?~ + InquireIrenicus
++ ~Heya.~ + Greet
IF ~Class(Player1,PALADIN)~ THEN REPLY ~I know a paladin when I see one!~ GOTO BothPaladins
IF ~~ THEN REPLY ~Go away.~ GOTO GoAway
END
Now we need to make the entirely new states that our previous replies link to.
IF ~~ THEN BEGIN InquireIrenicus
(This is after the PC chose to ask about Irenicus.)
SAY ~Nope, but I can help you look for him. I'm a paladin!~
(Vondo's response)
++ ~Sure. Join the party~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
(This will set a variable for Vondo that means he's joined the party. The action
"JoinParty()" obviously makes him join the party. EXIT ends the dialogue.)
IF ~~ THEN REPLY ~Nah, go away.~ EXIT
(This will terminate the dialogue, and Vondo will still be standing around.)
END
Now for the rest of the blocks.
Code:
IF ~~ THEN BEGIN Greet
SAY ~So, you need a paladin in your group?~
IF ~~ THEN REPLY ~Yes, as a matter of fact we do.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Nah, go away.~ GOTO GoAway
END
IF ~~ THEN BEGIN BothPaladins
SAY ~Another paladin! Hail and well met brother. Let us journey together and smite evil.~
IF ~~ THEN REPLY ~Sounds like a plan.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Nah, go away.~ GOTO GoAway
END
IF ~~ THEN BEGIN GoAway
SAY ~Very well my <LADYLORD>, I will await the day when you return, so that we might smite evil!~
IF ~~ THEN EXIT
END
(The "GoAway" block demonstrates a situation where the player simply presses Enter
to continue the dialogue. In this case it ends the dialogue entirely.)
So that's all we need for the "First meeting" state. Now to make a follow up
dialogue for when the PC returns to talk to Vondo.
Code:
IF ~NumTimesTalkedToGT(0)~ THEN BEGIN ReturnDialogue
SAY ~I see you have returned, my friend.~
IF ~~ THEN REPLY ~Yep, come and join the party.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Yeah, but I still don't want you in the party.~ GOTO RefusedAgain
END
IF ~~ THEN BEGIN RefusedAgain
SAY ~Ah, once again you refuse my offer. No matter, I will amuse myself with this magical device I have purchased. It was given to be by a gnome named John Johnson, or something similar.~
IF ~~ THEN EXIT
END
And that's the initial dialogue the NPC will start with. The next file that is
absolutely essential is the *P.dlg file, or the dialogue file that runs when you
kick your NPC out of the party.
Here's what I mean; Vondo joins the party (using J#Vondo.dlg), and is automatically
assigned three dialogues by various .2da files (Pdialog.2da and Interdia.2da). When
you kick him out, his *P.dlg file runs, and looks for the first state that is true.
So since we're starting a new .dlg file, we need to include the line...
BEGIN J#VondoP
Now, J#VondoP is what will be entered in the pdialog.2da file, since that's what our finished .dlg file's name will be. As to the actual contents of
this .dlg file, the code will look like this:
IF ~Global("VondoJoined","LOCALS",1)~ THEN BEGIN KickOut
(This is the variable that was set when Vondo joined the party. If it's at 1, it
means he is currently in the party, and so is being kicked out when the *P.dlg if
being run.)
SAY ~You are now kicking me out.~
IF ~~ THEN REPLY ~Oops, I meant to boot that twit Anomen, not you. Sorry.~ DO ~JoinParty()~ EXIT
(The P.dlg automatically "kicks" the NPC, so when you want him to not be kicked,
just have him use the JoinParty() command.)
IF ~~ THEN REPLY ~That's right, I don't want you in the party.~ DO ~SetGlobal("VondoJoined","LOCALS",0)~ EXIT
(This sets the "VondoJoined" variable to 0, meaning he has been kicked out.)
END
The block should look like this:
Code:
IF ~Global("VondoJoined","LOCALS",1)~ THEN BEGIN KickOut
SAY ~You are now kicking me out.~
IF ~~ THEN REPLY ~Oops, I meant to boot that twit Anomen, not you. Sorry.~ DO ~JoinParty()~ EXIT
IF ~~ THEN REPLY ~That's right, I don't want you in the party.~ DO ~SetGlobal("VondoJoined","LOCALS",0)~ EXIT
END
And that's all you need to kick him out. To have him rejoin once he's been kicked
out, you would write the following:
Code:
IF ~Global("VondoJoined","LOCALS",0)~ THEN BEGIN Rejoin
SAY ~You want me to rejoin?~
IF ~~ THEN REPLY ~That's right Vondo, get back in formation.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~That's right, I don't want you in the party.~ EXIT
END
And now THAT is all the necessary dialogue you need for an NPC. The rest is smooth
sailing. The final product of your .d should look like this...
Code:
BEGIN J#Vondo
IF ~NumTimesTalkedTo(0)~ THEN BEGIN FirstMeeting
SAY ~Greetings good <SIRMAAM>! My name is Vondo the Just.~
IF ~GlobalLT("Chapter","GLOBAL",3)~ THEN REPLY ~Hey Vondo, you seen Irenicus around here?~ GOTO InquireIrenicus
IF ~~ THEN REPLY ~Heya.~ GOTO Greet
IF ~Class(Player1,PALADIN)~ THEN REPLY ~I know a paladin when I see one!~ GOTO BothPaladins
IF ~~ THEN REPLY ~Go away.~ GOTO GoAway
END
IF ~~ THEN BEGIN InquireIrenicus
SAY ~Nope, but I can help you look for him. I'm a paladin!~
IF ~~ THEN REPLY ~Sure. Join the party~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Nah, go away.~ EXIT
END
IF ~~ THEN BEGIN Greet
SAY ~So, you need a paladin in your group?~
IF ~~ THEN REPLY ~Yes, as a matter of fact we do.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Nah, go away.~ EXIT
END
IF ~~ THEN BEGIN BothPaladins
SAY ~Another paladin! Hail and well met brother. Let us journey together and smite evil.~
IF ~~ THEN REPLY ~Sounds like a plan.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~Nah, go away.~ EXIT
END
IF ~~ THEN BEGIN GoAway
SAY ~Very well my <LADYLORD>, I will await the day when you return, so that we might smite evil!~
IF ~~ THEN EXIT
END
BEGIN J#VondoP
IF ~Global("VondoJoined","LOCALS",1)~ THEN BEGIN KickOut
SAY ~You are now kicking me out.~
IF ~~ THEN REPLY ~Oops, I meant to boot that twit Anomen, not you. Sorry~ DO ~JoinParty()~ EXIT
IF ~~ THEN REPLY ~That's right, I don't want you in the party.~ DO ~SetGlobal("VondoJoined","LOCALS",0)~ EXIT
END
IF ~Global("VondoJoined","LOCALS",0)~ THEN BEGIN Rejoin
SAY ~You want me to rejoin?~
IF ~~ THEN REPLY ~That's right Vondo, get back in formation.~ DO ~SetGlobal("VondoJoined","LOCALS",1)
JoinParty()~ EXIT
IF ~~ THEN REPLY ~That's right, I don't want you in the party.~ EXIT
END
It seems tough at first, but it's really quite easy once you get the hang of it.
Congratulations, you've just finished reading the entirety of Section I! The rest
are a whole lot shorter, so don't worry. Smiley
Section II: Making the .CRE
This is an easy step. Simply start a multi-player game of BG2 (no need to get onto
the internet, just a LAN game with one player in it is fine), and create a
character.
Cheat to give him whatever XP, hit points, equipment, and stats you want, then export him.
Make any last minute changes to his .chr with Shadow Keeper, DLTCEP, or NearInfinity if you like, and then
open up NearInfinity. From there, scroll down to the "characters" tab, find your new character, and open it. In the File menu, select "Convert CHR to CRE".
Once it's in .cre format, you can assign it it's Death Variable, Dialogue file,
Scripts, and unset certain Flags.
Now, for the Death Variable (More properly known as the Script Name, but I'm old Fashioned), one should scroll down to offset 0x2e4. In real english, this means about 2/3s of the way down the file, as shown by NI. This will be what identifies your NPC in the game. Other Death Variables include "Minsc", "Jaheira", and "Imoen2". I recommend using a unique prefix for this field. We shall set Vondo's DV to j#vondothejust.
This field can be the same as the filename of your CRE, but does not have to be. To keep this clear for our example, we will make the DV j#vondothejust, so you see the difference between filename and script name/death variable.
Scripts at the moment are unimportant, but for now you should set the override script slot to "J#Vondo". This means that when we create a J#Vondo.bcs file, it will be assigned to our .cre file. You should also blank out the leftovers from your .chr file (which should be dplayer3.bcs), and set that to none. If you want your PC to initiate dialogue as soon as they see the PC, use shoutdl2.bcs. If you want them to walk up to the PC to start a conversation, use initdlg.bcs. A basic combat script for them to use would be WTASIGHT.bcs, or WTARSGT.bcs for ranged weapons. So now we should have J#Vondo assigned to override, initidlg.bcs assigned to a slot further down, and wtasight or wtarsgt.bcs below that.
The dialogue assignment is at 0x330, or in the same area as the Script Name/Death Variable, just a bit further down. Right-click the field, choose "Edit as String", and type in J#Vondo. This means when our finished product is installed, and our dialogue compiled, J#Vondo.cre will use J#Vondo.dlg initially.
The following step is important. Read it! - Ghreyfain, 07/30/05
Finally, a small change that many people forget, but which is responsible for numerous headaches. Scroll to the top of your .cre file, and find the Flags field. In a newly converted .cre file, the flag "Export allowed" is still checked. Uncheck that. Odd side-effects that could crop up include scripts and dialogues behaving like those of a multi-player NPC. Not what we want at all.
Whew, and that's that for the .cre.
Section III: Scripts
The next bit is already covered by our addition of initdlg.bcs to our .cre file.
Possibly the shortest step. If you want your NPC to walk up to your PC when they
first meet, you'd write this script as a .baf file, i.e. J#Vondo.baf:
Code:
IF
See([PC])
NumTimesTalkedTo(0)
THEN
RESPONSE #100
Dialogue(Nearest([PC]))
END
You don't need to compile it yet. You can leave it in .baf format (that's the
source code for BioWare's script files). Assign it to your NPC's .cre file. To do
this in NI, right-click the script field and chose "Edit as String", then type in
your scripts name without the .bcs extension.
Then the method to get your NPC into the area is to append a small portion of
script to an existing area script. Let's say we want to add him to the Government
District. We'd need to append a bit to AR1000.bcs. For now let's create a script
called AR1000.baf with the bits we want to add.
Code:
IF
Global("J#VondoExists","AR1000",0)
THEN
RESPONSE #100
SetGlobal("J#VondoExists","AR1000",1)
CreateCreature("J#Vondo",[1137.2046],3) // 1137.2046 are the x.y coordinates that will cause him to show up. 3 is the direction he's facing. It ranges from 0 (South), to 15, going clockwise.
END
This portion of script will be going into our installation package, and will be
appended to AR1000.bcs by WeiDU when the time is right. See section IV for details
on how this is done.
Section IV: The WeiDU .TP2
The .tp2 is the installation script that installs your NPC on another's computer, by compiling dialogues, scripts, and by assigning text to their dialog.tlk file and matching the new text to the .cre files. The following has been shamelessly taken from a follow-up on this very tutorial, written by Domi, since I was too lazy to update it.
DO the following:
1) Open you BG2 Main Directory
2) Create a folder called VondoTheNPC
3) Open the folder called VondoTheNPC and within it create a subfolder called backup
4) In the folder called VondoTheNPC copy you cre, your baf's and your d's
5) Go back to your main BG2 directory
6) Copy/paste WeiDU.exe there and re-name it VondoTheNPC-setup.exe
7) in the main BG2 directory create a file called VondoTheNPC-setup.tp2
OPEN the TP2 file in your text editor and keep reading to see what needs to be included for your NPC mod to work.
Thanks, Domi, whether or not you see this.
Code:
BACKUP ~VondoTheNPC\backup~
AUTHOR ~ghreyfain@pocketplane.net~
BEGIN ~Vondo the NPC for BG2:ToB~
// The following is the copying of Vondo's .cre file, as well as assigning his sound-set. See the file sndslot.ids for a listing of sounds you can add.
COPY ~VondoTheNPC\J#Vondo.cre~ ~override\J#Vondo.cre~
SAY NAME1 ~Vondo~
SAY NAME2 ~Vondo~
SAY SELECT_COMMON4 ~Blah blah blah.~ [Vondo1] // [Vondo1] is the name of the .wav
file for this sound
SAY SELECT_COMMON5 ~Give the word.~ [Vondo2]
SAY SELECT_COMMON6 ~Point the way.~ [Vondo3]
SAY SELECT_ACTION1 ~I'm on the job.~ [Vondo4]
SAY SELECT_ACTION2 ~As you wish.~ [Vondo5]
// The following is telling WeiDU to compile the following .d files
COMPILE ~VondoTheNPC\J#Vondo.d~
// The following is compilling the script and placing it in the override. We haven't actually made a script yet, though, so this isn't necessary.
COMPILE ~VondoTheNPC\J#Vondo.baf~
// The following is appending what we wrote in AR1000.baf to the bottom of
// AR1000.bcs
EXTEND_TOP ~Ar1000.bcs~ ~VondoTheNPC\ar1000.baf~
The following is some .2DA appending for Vondo, which goes into the .tp2 as well.
I should detail exactly what this means. Pdialog, basically, is a 2-d array (.2da) that assigns various scripts and dialogue to an NPC.
The first field is our NPCs Script Name/Death Variable, j#vondothejust.
The second is the "post" dialogue file, for when the NPC has been removed from the party.
The "J" is for interjections and dialogue while in-party, such as flirts or PC-initiated discussions.
J#VondoD is actually the dream script file. This acts as any normal script, only it basically adds the condition "the player has just clicked the Sleep button" to all trigger blocks.
The next four fields are as above, only for the ToB expansion. It's recommended to add them even if your NPC only has SoA content, because it won't do any harm to have it there, but to change it later is a little bit of a hassle.
The UNLESS line is a WeiDU command telling the program to only append this text if J#VondoTheJust doesn't already exist in the file.
Code:
APPEND ~pdialog.2da~
~J#VondoTheJust J#VondoP J#VondoJ J#VondoD J#Von25P J#Von25J J#Von25D J#Vond25~
UNLESS ~J#VondoTheJust~
// interdia.2da is a bit simpler, but acts the same as pdialog.2da. It adds the NPCs banter file, which is used for inter-party banter, and romance dialogues.
Code:
APPEND ~interdia.2da~
~J#VondoTheJust J#VondoB J#VonB25~
UNLESS ~J#VondoTheJust~
And that's the end of it, I hope it was clear and not too confusing.
Send any comments on this tutorial to ghreyfain@yahoo.ca, and visit the WeiDU site at http://www.weidu.org.
Other sites of interest for IE editing are:
http://www.idi.ntnu.no/~joh/ni/ - Home of NearInfinity