WeiDU Documentation

Valerio Bigiani, AKA The Bigg
thebigg@spellholdstudios.net
edited according to the GPL from the original version by
Westley Weimer
weimer@cs.berkley.edu

Contents

1  About WeiDU

The main home page for WeiDU is: http://weidu.org/. I encourage you to download the latest version.

WeiDU is designed to make it easier to write and distribute modifications to Infinity Engine games. It can load and modify Infinity Engine resources according to instructions you provide. WeiDU is ideal for packaging modifications that include dialogue or that want to be compatible with other modifications.

I’ll be honest with you up front: WeiDU is initially harder to use than some of its alternatives. However, most users report that (1) the alternatives are insufficient because they lack features that only WeiDU provides and (2) WeiDU grows on you over time.

You are welcome to use these utilities to make and distribute your own Infinity Engine mods. This utility is covered by the GNU General Public License, but you are also allowed to distribute an unmodified binary copy of WeiDU.EXE (without the source code) with your mod if you like.

I decided to write my own Infinity Engine DLG and TLK utilities because I was unable to get the TeamBG DLG Editor and Mass Converter to work properly. Either they wouldn’t parse the strings or they would mangle the text or they would randomly crash ... it was bad all around. Also, they were all GUIs. As a unix weenie I’m in love with command line utilities and as a PL doctoral student I love making little languages and compilers. WeiDU was originally a family of small programs with unimaginative names like DC, DD and TP. The more appealing term “WeiDU” (which rhymes with “IDU”, Eye-Dee-You) was coined by Jason Compton and Ghreyfain, noted BGII mod authors.

2  Don’t Panic!

Step-By-Step Beginner’s Guide to WeiDU:

  1. Don’t Panic. Many of you are children of the GUI era. But programs that run from the command line can be your friend, and in the long run are often much faster and, yes, easier to use.
  2. The Best Way To Learn How To Write Code In WeiDU’s D Format Is To Read Code Written In WeiDU’s D Format. Start by decompiling existing in-game DLGs that you understand and read through them. Compare how they appear in WeiDU to how they appear in other BG2 editing tools you may be more comfortable with, such as Near Infinity or Infinity Explorer.
  3. The Best Way To Learn How To Write Code In WeiDU’s D Format Is To Read Code Written In WeiDU’s D Format, Part 2. A growing number of BG2 add-on packs are being created using WeiDU. A list is available at http://www.pocketplane.net/modlist/. These can help you understand how WeiDU’s advanced features, such as dialogue appending, script and 2DA patching, and item/spell/creature patching work in a “real-world” setting. Make it a point to download some of them and understand HOW they work.
  4. Take a look at some of the examples in this document. There is a lovely WeiDU tutorial (written by Japheth) available at http://forums.pocketplane.net/index.php?topic=55.0. If you are feeling overwhelmed, start there first. It also covers installation. Ghreyfain also has a “how to create an NPC with WeiDU” tutorial at http://forums.pocketplane.net/index.php?topic=52.0.
  5. There is a WeiDU discussion board at http://forums.pocketplane.net/index.php?board=50.0. The discussion board is the best place to have your WeiDU (and mod-making) questions answered.
  6. Finally, if you are using a Mac and you want to play around with WeiDU, check out http://weidu.org/Mac.html for more information on obtaining a copy of WeiDU that works under OS X.

3  D and DLG File Concepts

This section is a gentle introduction to how Infinity Engine DLG files are structured. First, let’s use WeiDU to create SCSARLES.D and take a look at the dialogue of Sir Sarles.

You may install WeiDU.exe anywhere on your system. However, I recommend that you put it in your Baldur’s Gate 2 installation directory. However, WeiDU will use the Windows Registry to attempt to locate your BG2 game files.

To run the effect described, open up a DOS prompt window and change directories to get to your BGII directory. Then just type in the text in red at the DOS Prompt.

C:\Program Files\Black Isle\BGII - SoA\> weidu SCSARLES.DLG

This will create a text file called SCSARLES.D in the current directory. Open it up with Notepad or Microsoft Word or something. It’s just a text file that describes the game dialogue.

It will look something like:

// creator  : c:\bgate\weidu\weidu.exe
// argument : SCSARLES.DLG
// game     : C:\Program Files\Black Isle\BGII - SoA
// source   : C:\Program Files\Black Isle\BGII - SoA\data\Dialog.bif
// dialog   : C:\Program Files\Black Isle\BGII - SoA\DIALOG.TLK
// dialogF  : (none)

BEGIN ~SCSARLES~

IF ~NumTimesTalkedTo(0)~ THEN BEGIN 0 // from:
  SAY #28655 /* ~Who is it? Might I ask why you have disturbed my
    meditations? My creative muse must be gently awakened, and your
    stomping about is simply not conducive to this.~ [SARLES02] */
  IF ~~ THEN REPLY #28656 /* ~My apologies. I will leave you to your
    thinking.~ */ GOTO 1
  IF ~~ THEN REPLY #28657 /* ~I apologize, but I have come to request your
    talent on a commissioned artwork.~ */ 
      DO ~SetGlobal("TalkedToSarles","GLOBAL",1)~ GOTO 2
END

IF ~~ THEN BEGIN 1 // from: 0.0
  SAY #28661 /* ~Then I shall forget you were ever here. Actually, it is an
    astoundingly easy thing to do.~ */
  IF ~~ THEN DO ~SetNumTimesTalkedTo(0)~ EXIT
END
Dialogues in Infinity Engine games behave like finite state machines. If you aren’t familiar with the concept of a finite state machine, see http://whatis.techtarget.com/definition/0,,sid9_gci213052,00.html or http://www.c3.lanl.gov/mega-math/workbk/machine/mabkgd.html. Each block of the form:
  IF ~Initial Condition~ THEN BEGIN state1
    SAY ~Something~
    IF ~Reply Condition~ THEN REPLY ~Reply Text~ GOTO state2
  END
represents a state (more details below). When the player starts a conversation with an NPC, the game engine scans through all of the states in that NPC’s DLG file in a special WEIGHTed order and picks the one with a non-empty and true "Initial Condition". If no state has a non-empty and true "Initial Condition" then you get that “Bob - has nothing to say to you.” message. Don’t worry about the weighting process for now.

The speaker (in this case, Sir Sarles) then says whatever appears after SAY. The REPLY lines represent responses the PC can say back. If the "Reply Condition" is true, the player is given the option of saying the "Reply Text" and moving to another state in the dialogue (where Sarles will probably say something else).

Remember: SAY is for what the NPC says, REPLY is for what the player says back. If you think carefully, you’ll notice that all dialogue in Infinity Engine games is structed in this manner.

Conditions use the same syntax as triggers do in Infinity Engine BCS scripting. You will need to learn Infinity Engine scripting before too long. Strings are delineated by tildes or %% or "" (your choice, but WeiDU uses the tilde by default). After SAY or REPLY or JOURNAL you may give two Strings instead of one. The first is used with DIALOG.TLK, the second is used with DIALOGF.TLK (foreign language version for when the main character is female). If you do not give two Strings, the one String you gave is used for both.

You may also use raw numbers prefaced with a number sign (like #1234) to specify a strref inside DIALOG.TLK directly. This is useful when modifying existing dialogues (say, the Fate Spirit in ToB) so that you if a foreign user installs your dialogue they will retain all of the foreign versions of the strings you didn’t change or add. Normally the string reference numbers are put right after the SAY keyword and the string text is put in comments. The --text command-line option causes string text to be emitted with the string number in comments.

You may also indicate that a sound file (WAV/WAVC) should be associated with a given String by including its up-to-8-letter resource name in [brackets] after the string, as in:

  SAY ~Hello~ [HELLO]
Comments are C/C++ style: everything from // to the end of the line is a comment, as is /* everything in these star-slash things */. Comments are ignored by WeiDU. They are there for your benefit. Example:
  SAY ~Hello~ [HELLO]   // this is a comment        ... way out to here!
  IF /* this is also a comment */ ~~ THEN EXIT
Replies can also contain actions (using the DO keyword) which behave just like Infinity Engine BCS script actions. They can also add Journal entries, end the dialogue or transfer to another speaker.

Examples:

  IF ~~ THEN BEGIN 2 // from: 0.1
This line marks the beginning of state 2 in a dialogue. The comment tells you that it can be reached by the first reply transition from state 0.
  IF ~~ THEN REPLY ~My apologies. I will leave you to your thinking.~ // #28656
      GOTO 1
This REPLY can always be chosen and involves the spoken text "My apologies...". That text is string reference number 28656. If the PC chooses that reply, it transitions to state 1.

Finally, a transition may also take the form:

  COPY_TRANS filename label
During processing, COPY_TRANS will be replaced by all of the transitions from state "label" of file "filename". The copying takes place before all other D actions.

4  D Dialogue File Format

The D file format is a way of describing Infinity Engine dialogues and modifications to Infinity Engine Dialogues in a portable, easy-to-understand format. It supports foreign language translations and allows you to describe extensions to existing game dialogues without forcing you to describe their content. This allows you to write mods that work with mods written by others.

The D file format is presented here in an extended context-free grammar notation. If you are unfamiliar with CFGs, take a look http://www.wikipedia.com/wiki/Context-free_grammar, http://cs.wpi.edu/~kal/PLT/PLT2.1.2.html or http://www.cs.rochester.edu/users/faculty/nelson/courses/csc_173/grammars/cfg.html. You don’t really need to understand a CFG formally, though.

To get a real idea of how they work, use WeiDU to create JAHEIRA.D for yourself and look at it in a text editor. You can also browse the examples and test directories that come with WeiDU.

All of the syntax keywords are given in a UPPERCASE COURIER. All other keywords are symbolic. Notes:

D File  A D file is a text file that contains a number of D Actions. D Files tell WeiDU how to create and modify Infinity Engine DLG files.
isD Action list A D File is a list of D Actions. Typically the first and only one is BEGIN, which defines the content of a new dialogue. Other D Actions can be used to modify existing dialogues.
 
D Action  A D Action tells WeiDU how to create or modify Infinity Engine DLG files.
isBEGIN filename [ nonPausing ] state list BEGIN tells WeiDU that you are creating a new DLG file from scratch. Any existing DLG file with the same name will be overwriten. The new DLG file contains exactly the states in the list. If you set nonPausing to a non-zero integer, the game will not “stop time” while the conversation takes place. By default time stops during conversations.
orAPPEND [ IF_FILE_EXISTS ] filename state list END This tells WeiDU to place the given states at the end of the already-existing dialogue filename.DLG. If there is IF_FILE_EXISTS and the file doesn’t exists, this action is skipped.
orAPPEND_EARLY [ IF_FILE_EXISTS ] filename state list END Works like APPEND, but the states are added early on in the compilation timeline (just after BEGIN is processed). Thus they can be the targets for INTERJECT_COPY_TRANS and friends.
orCHAIN [ IF [ WEIGHT #weight ] stateTriggerString THEN ] [ IF_FILE_EXISTS ] entryFilename entryLabel chainText list chainEpilogue This instructs WeiDU to make a long conversation in which the PC can say nothing. This is useful when you want the NPCs to talk among themselves for a long time. It and its friends, INTERJECT and INTERJECT_COPY_TRANS can incredible time-savers when you’re writing non-trivial dialogue. See the examples for ideas. CHAIN will only append to existing dialogues. You cannot use CHAIN to create a new DLG. If the entryFilename file is missing and there is IF_FILE_EXISTS, the whole CHAIN is not compiled.
orINTERJECT entryFilename entryLabel globalVariable chainText list chainEpilogue Behaves like CHAIN except that all of the chainText is additionally guarded by the transition predicate Global("globalVariable","GLOBAL",0) and accompanied by the action SetGlobal("globalVariable","GLOBAL",1). If you pick globalVariable to be unique, this will ensure that the chainText is only ever seen once per game. This is useful for making interjections.
orINTERJECT_COPY_TRANS entryFilename entryLabel globalVariable chainText list This behaves just like INTERJECT except that the exitFilename and exitLabel are not present. Instead, whenever the dialogue would pass out of the chainText it follows a copy of the transitions that were at the state with stateLabel originally. This is convenient for making quick interjections from NPCs that do not actually change the true flow of the conversation. See the transition COPY_TRANS and the INTERJECT_COPY_TRANS tutorial for more information about this idea.
orINTERJECT_COPY_TRANS2 entryFilename entryLabel globalVariable chainText list This works just like INTERJECT_COPY_TRANS, except that any actions taken in the transitions of the state specified by entryFilename and entryLabel are preserved and kept with the speaker associated with entryFilename (rather than being mistakenly performed by your new speaker). See the INTERJECT_COPY_TRANS2 tutorial.
orINTERJECT_COPY_TRANS3 entryFilename entryLabel globalVariable chainText list This works just like INTERJECT_COPY_TRANS, except that all states in chainText get a link in the entry state, rather than only the first one. Expecting documentation.
orINTERJECT_COPY_TRANS4 entryFilename entryLabel globalVariable chainText list This is either INTERJECT_COPY_TRANS3 with INTERJECT_COPY_TRANS2-style action handling, or INTERJECT_COPY_TRANS2 with the extended INTERJECT_COPY_TRANS3 state creation rules, depending at how you look at it.
or EXTEND_TOP filename stateLabel list [ #positionNumber ] transition list END This instructs WeiDU to add the transitions in list to the top of the transition list for the specified states in filename.DLG (which must already exist).

If a positionNumber is given, WeiDU to insert the transitions just between already-existing transitions #positionNumber and #positionNumber+1 in the given states for the given file. The first transition is number 1.

orEXTEND_BOTTOM filename stateNumber list [ #positionNumber ] transition list END Behaves just like EXTEND_TOP but adds the transitions to the bottom of the list instead.
orADD_STATE_TRIGGER filename stateNumber stateTriggerString [ stateNumber list ] This instructs WeiDU to add the stateTriggerString to all of the states with the given stateNumbers in the file filename.DLG (which must already exist). This is handy for adding extra conditions to an existing dialogue state.
orADD_TRANS_TRIGGER filename stateNumber transTriggerString [ moreStateNumbers list ] [ DO transNumber list ] This instructs WeiDU to add the transTriggerString to all of the transitions in all of the states with the given stateNumbers in the file filename.DLG (which must already exist). This is often used in conjunction with EXTEND_BOTTOM to make a new branch in an existing state. Use ADD_TRANS_TRIGGER to add the negation of some predicate to all of the existing transitions, then use EXTEND_BOTTOM to add a transition with that predicate to that state. If a list of transNumbers is specified, only those transitions will have transTriggerString added to them. If such a list is not specified, every transition in every specified state will be modified. Note that the “first” transition is number 0.
orADD_TRANS_ACTION filename BEGIN stateNumber list END BEGIN transNumber list END transActionString This instructs WeiDU to add the transActionString to all of the actions in all the transitions in all of the states specified by the stateNumber list and the transNumber list. You may use state labels in the stateNumber list. If the transNumber list is empty, the text added to all transitions on all listed states. Note that the BEGIN and END keywords must be present, even if you specify an empty list of transNumbers. The “first” transition is number 0. Any out-of-bounds transNumbers are silently ignored. The transActionString is prepended to any existing action text on a per-transition, per-state basis.
orREPLACE_TRANS_ACTION filename BEGIN stateNumber list END BEGIN transNumber list END oldText newText This instructs WeiDU to replace all instances of oldText in newText to all of the actions in all the transitions in all of the states specified by the stateNumber list and the transNumber list. You may use state labels in the stateNumber list. If the transNumber list is empty, the text added to all transitions on all listed states. Note that the BEGIN and END keywords must be present, even if you specify an empty list of transNumbers. The “first” transition is number 0. Any out-of-bounds transNumbers are silently ignored.
orREPLACE_TRANS_TRIGGER filename BEGIN stateNumber list END BEGIN transNumber list END oldText newText This instructs WeiDU to replace all instances of oldText in newText to all of the triggers in all of the transitions in all of the states specified by the stateNumber list and the transNumber list. You may use state labels in the stateNumber list. If the transNumber list is empty, the text added to all transitions on all listed states. Note that the BEGIN and END keywords must be present, even if you specify an empty list of transNumbers. The “first” transition is number 0. Any out-of-bounds transNumbers are silently ignored.
orALTER_TRANS filename BEGIN stateNumber list END BEGIN transNumber list END BEGIN changeWhat changeInto list END Fine altering of a single transition. See the ALTER_TRANS tutorial.
orREPLACE filename state list END This instructs WeiDU to load filename.DLG and replace some of its states with the new ones described in the state list. All of the states should have numeric stateLabels (e.g., "5" or "67"). A new state with label X will replace the old state number X.
orSET_WEIGHT filename stateLabel #stateWeight This instructcs WeiDU to destructively change the WEIGHT of the given state in filename.DLG (which must exist). This should only be used to patch or workaround existing dialogues. Never use SET_WEIGHT if you can help it.
orREPLACE_SAY filename stateLabel sayString This instructs WeiDU to destructively change the sayString of the given state in filename.DLG (which must exist). This should only be used to patch or workaround existing dialogues. Never use REPLACE_SAY if you can help it.
orREPLACE_STATE_TRIGGER filename stateNumber stateTriggerString [ stateNumber list ] This instructs WeiDU to destructively set the stateTriggerString of all of the states with the given stateNumbers in the file filename.DLG (which must already exist). It should be used with caution.
orREPLACE_TRIGGER_TEXT filename oldText newText This instructs WeiDU to destructively replace every occurrence of oldText (which may be a regexp) in the stateTriggerStrings and transTriggerStrings of filename.DLG (which must exist). This should only be used to patch or workaround existing dialogues. Never use this if you can help it.
orREPLACE_TRIGGER_TEXT_REGEXP filenameRegexp oldText newText Just like REPLACE_TRIGGER_TEXT but the filename is a regexp. The .DLG is implied. Do not use this.
orREPLACE_ACTION_TEXT filename oldText newText [ moreFilenames ] This instructs WeiDU to destructively replace every occurrence of oldText (which may be a regexp) in the stateActionStrings of filename.DLG (which must exist). This should only be used to patch or workaround existing dialogues. Never use this if you can help it.
orREPLACE_ACTION_TEXT_REGEXP filenameRegexp oldText newText [ moreFilenameRegexps ] Just like REPLACE_ACTION_TEXT but the filenames are regexps. The .DLG is implied, do not include it in your regexps. Do not use this.
orREPLACE_ACTION_TEXT_PROCESS filename oldText newText [ moreFilenames ] This instructs WeiDU to destruveily replace every occurrence of oldText (which may be a regexp) in the stateActionStrings of filename.DLG (which must exist) with newText. However, newText is first compiled as a BAF action list. In particular, this means that replacing with commands like:
  ~DisplayString(Myself,@123)~
  
... will do what you expect. This should only be used to patch or workaround existing dialogues. Never use this if you can help it.
orR_A_T_P_R filenameRegexp oldText newText [ moreFilenameRegexps ] Just like REPLACE_ACTION_TEXT_PROCESS, but the filenames are regexps. The .DLG is implied. Do not use this. R_A_T_P_R is shortand for REPLACE_ACTION_TEXT_PROCESS_REGEXP (to avoid undue scrollbars in the readme on a 1024x768 monitor).
 
chainEpilogue Determines where the dialogue should flow at the end of the CHAIN.
isEND filename stateNumberTransfer to the given state in the given dialogue file.
orEXTERN filename stateNumberTransfer to the given state in the given dialogue file.
orCOPY_TRANS filename stateNumberAt the end of the CHAIN text, copy all transitions from the given state in the given file. This is useful for interjections (see INTERJECT).
orEXITAt the end of the CHAIN text, exit the dialogue.
orEND transition list Execute the given transitions after the final state in the CHAIN.
 
state In Infinity Engine games, this is the fundamental unit of dialogue.
isIF [ WEIGHT #weightNumber ] stateTriggerString [ THEN ] [ BEGIN ] stateLabel SAY sayText [ = sayText ... ] transition list END When you start conversing with a creature that uses a DLG file, the Infinity Engine searches through all of the states in that file in order of increasing WEIGHT and selects the first one it finds for which the stateTriggerString is both true and not empty. The creature then says all of the associated sayText. Finally, the transitions are evaluted in bottom-up (i.e., reverse) order. If a transition is found with a transTriggerString that evaluates to True and no replyText, that transition is immediately executed. Otherwise, all of the transitions are presented as options to the PC.

If a stateLabel is an integer it is called a stateNumber. All of the states in the DLG files that come with the original game use stateNumbers. Only D files use symbolic strings for stateLabels.

Including more than one bit of sayText here is often called Multisay.

Finally, once you are familiar with the syntax you may omit the THEN and BEGIN keywords if you like.

orAPPENDI filename state list END This is legacy syntax that behaves just like the D Action APPEND but is considered a state. Avoid it.
orCHAIN2 entryFilename entryLabel chain2Text list exitFilename exitLabel This is legacy syntax that behaves somewhat like the D Action CHAIN but is considered a state. In addition, chain2Text is slightly different from chainText. Avoid this construction.
 
sayText sayText and replyText are displayed to the user as part of a dialogue.
istextsayText and replyText are both text.
 
transition Transitions determine how dialogue flows from one state to another.
isIF transTriggerString [ THEN ] transFeature list transNext If the transTriggerString evaluates to true or is empty, this transition is viable. If it contains no replyText within its transFeature list, it is immediately taken. Otherwise, the replyText is presented as an option to the user. If the transition is taken, any actions in the transFeature list are performed and the dialogue flows to the point indicated by the transNext. transitions are evaluated in "reverse order". That is, the "bottom" or "last" response for a state is checked first. If its transTriggerString evaluates to true and it has no REPLY text, that transition is immediately taken. See SAREV25A state 1 for an example of a state with all kinds of transitions.
or+ [ transTriggerString ] + replyText transFeature list transNext This abbreviated syntax for transitions that would contain REPLY (which is by far the most common case) allows you to save yourself some time and typing. It behaves like the full form above.
orCOPY_TRANS filename stateLabel This instructs WeiDU to copy all of the transitions from the state with the given stateLabel in filename.DLG. This copying takes place before all other D Actions. For example, this is a valid transition list:
IF ~Before()~ THEN GOTO my_state
COPY_TRANS PLAYER1 33
IF ~After()~ THEN EXTERN SOLA 55
 
transFeature These are features or actions associated with taking a transition.
isREPLY replyText If this transition is taken, the PC says the replyText.
orDO stateActionString If this transition is taken, the stateActionString is executed.
orJOURNAL text If this transition is taken, the text is added to the PC’s journal.
orSOLVED_JOURNAL text If this transition is taken, the text is added to the “solved” section of the PC’s journal.
orUNSOLVED_JOURNAL text If this transition is taken, the text is added to the “unsolved” section of the PC’s journal.
orFLAGS integer This allows you to set the features associated with a transition directly using the binary format of DLG files. Do not use this!
 
transNext This determines where dialogue flows after a transition has been taken.
isGOTO stateLabel The dialogue continues at the state with label stateLabel in the same DLG file as the current state.
orEXTERN [ IF_FILE_EXISTS ] filename stateLabel The dialogue continues at the state with label stateLabel in the file filename.DLG. The whole transition is not compiled if there’s IF_FILE_EXISTS and the file filename doesn’t exist.
orEXIT The conversation ends.
or+ stateLabel This is a synonym for GOTO.
 
chainText This is a rapid shorthand for chaining together many little bits of dialogue when the PC is not saying anything.
is [ IF transTriggerString THEN ] sayText = sayText ... 
followed by [ == [ IF_FILE_EXISTS ] fileName [ IF transTriggerString THEN ] sayText = sayText ... ] The == (that’s two consecutive equal signs) marks the beginning of a new speaker (indicated by fileName). If the transTriggerString is true or if it is not present, this new speaker says all of its sayText in order. If the IF_FILE_EXISTS part is present, these lines are not compiled at all if the current file is not missing.
or followed by BRANCH transTriggerString BEGIN [ == [ IF_FILE_EXISTS ] fileName [ IF transTriggerString THEN ] sayText = sayText ... ] END As above, except that the first transTriggerString is appended to all existing dialogue units.
 
text This represents strings that are shown to the player, rather than strings that the game uses internally for predicates and actions.
isString [ [WAVEFILE] ] The given string is used for both male and female players. The optional [WAVEFILE] is the associated sound.
orString [ [WAVEFILE] ] String [ [WAVEFILE] ] The first string and sound file are used if the PC is male, the second string and sound file are used if the PC is female. This is useful mainly for international versions of Infinity Engine games.
or#integerThe string with reference number #integer from DIALOG.TLK should be used unchanged.
or@integerThe last definition of the translation string @integer given in any TRA file should be used.
or!integer textForced String Reference. As with text in general, but rather than being assigned a new, previously-unused DIALOG.TLK string entry (or merging with an existing one that has the same text), this text is written over DIALOG.TLK string entry #integer. Do not use this feature.
 
String This is how you tell WeiDU what text you want shown to the player. For international mods or international translations, you may use any encoding you like (that is, you are not restricted to 7-bit characters or Latin-1 or anything like that).
is"abcdef"A string can be any sequence of characters not including a " that is enclosed in ""s.
or~abcdef~A string can be any sequence of characters not including a ~ that is enclosed in ~~s.
or%abcdef%A string can be any sequence of characters not including a % that is enclosed in %%s. This is handy for Big5 translations, since " and ~ can be part of Big5-encoded characters.
or~~~~~abcdef~~~~~That’s five consequtive tildes on each side. A string can be any sequence of characters not including ~~~~~ that is enclosed in ~~~~~s. For example, string #8750 is ~!@#$\%^&*()_+-=[]{}\|;:'",<.>/? and can be given to WeiDU as ~~~~~~!@#$\%^&*()_+-=[]{}\|;:'",<.>/?~~~~~ (the content of the string is shown in red for clarity).
orString ^ StringString literal concatenation. The second string is appended to the first string. No whitespace is added. Thus "hello" ^ "World" is the same as "helloWorld".

5  Command Line Options

WeiDU is a command-line utility. GUIs are available, but this document only describes command-line invocation. Use the DOS Shell ("command" or "cmd") to run WeiDU. You control its behavior by passing arguments to it on the command line.

You invoke WeiDU by typing WeiDU and then any number of options and files, as described below.

Note: since it may not be obvious, if an option accepts ’X’ and says to be cumulative, if you want to apply it multiple times you have to use the following hideousness:

weidu --string 1 --string 2 --string 3

This does not apply to *-rest commands like --biff-get-rest and --force-install-rest.

Moreover, *-rest commands must be the last, EG

weidu --biff-get-rest sw1h01.itm --out foo

will try to extract sw1h01.itm, --out and foo from the biffs; you have to express the above as

weidu --out foo --biff-get-rest sw1h01.itm

*-list commands work like the -rest variants, except that they stop parsing for the current switch once they find an option starting with ’-’. Basically, this works like you’d expect:

weidu --biff-get-list sw1h01.itm --out foo
Compiling And Decompiling
FILE.DCompile FILE to a DLG (dialogue file).
FILE.DLGDecompile FILE to a D (dialogue text file).
numberWhen decompiling a DLG file to a D file, emit only state number. You may specify this multiple times and only the states you specify will be emitted.
numberA-numberBWhen decompiling a DLG file to a D file, emit only states between numberA and numberB (inclusive). You may specify this multiple times and only the states you specify will be emitted.
FILE.BAFCompile FILE to a BCS (script file).
FILE.BCSDecompile FILE to a BAF (script text file).
--script-style XUse the given BAF/BCS scripting style. X must be BG or BG1 or BG2 or PST or IWD or IWD1 or IWD2.
--transin XUse FILE as a source of translation strings when processing D and BAF files.
FILE.TRAEquivalent to --transin FILE.TRA.
 
Module Packaging Input And Control
FILE.TP or FILE.TP2Read FILE and ask the user whether to install, reinstall or uninstall its TP2 Components.
--yesAnswer all TP2 questions with ’Yes’ and do not prompt for a key to be pressed at the end of TP2 processing.
--uninstall Answer all TP2 questions with ’Uninstall’ and do not prompt for a key to be pressed at the end of TP2 processing.
--reinstall Re-install all TP2 components that are already installed and do not promtp for a key to be pressed at the end of TP2 processing.
--languagem XSets the TP2 Language to the one passed here. Has no effect if the value is bigger than the language count (I.E. you’ll get asked for the language, unless you gave --uninstall, --reinstall or --force-uninstall).
--force-install Xinstalls component number X, skips the others (cumulative).
--force-uninstall Xuninstalls component number X, skips the others (cumulative). If there is no --force-install, you don’t get asked for the language.
--force-install-rest X Y...installs component number X Y..., skips the others (cumulative).
--force-uninstall-rest X Y...uninstalls component number X Y..., skips the others (cumulative).
--force-install-list X Y...installs component number X Y..., skips the others (cumulative).
--force-uninstall-list X Y...uninstalls component number X Y..., skips the others (cumulative).
--skip-at-viewAT_*  VIEW this  actions (and the extra chromosome versions like  NOTEPAD this ) aren’t processed, while still processing batch files and similia.
--ask-everyBehave as if ASK_EVERY_COMPONENT were present for all TP2 components.
--continueContinue TP2 processing despite TP2 Action errors.
--args XX will be stored in the tp2 variable %argv[n]%, where n is 0 for the first argument, 1 for the second, etc.

If the installation is non-interactive, said variables will be loaded from the last interactive session.

--args-rest X Y...X Y Z will be stored in the tp2 variables %argv[n]%, where n is 0 for the first argument, 1 for the second, etc.

If the installation is non-interactive, said variables will be loaded from the last interactive session.

--args-list X Y...X Y Z will be stored in the tp2 variables %argv[n]%, where n is 0 for the first argument, 1 for the second, etc.

If the installation is non-interactive, said variables will be loaded from the last interactive session.

--debug-assignPrint out all values assigned to TP2 variables (even implicit ones created by WeiDU).
--debug-valuePrint out all values encountered in TP2 processing and the results they evaluate to. Among other things, this is useful for catching parenthesis errors in your values.
--clear-memorycalls CLEAR_MEMORY after every TP2 action.
Automatic Updating Options
--update-allAuto-update all WeiDU setup files (e.g., Setup-MyMod.exe) in the current directory.
--noautoupdateIf you are running WeiDU as Setup-MyMod.exe, do not attempt to update yourself or any other mod.
--noselfupdatemsgIf you are running WeiDU as Setup-MyMod.exe and it automatically updates itself, do not display a message or ask the user to press return.
 
Infinity Engine Game Location Options
--game X Set main game directory to X. WeiDU looks for CHITIN.KEY and DIALOG.TLK and the override directory in the main game directory (but see --tlkin and --search). WeiDU will look in the current directory and use the registry to find your game. If this fails, you will need to run WeiDU using the --game switch to define the full path to the BG2 directory. WeiDU will also search for BG1, IWD and PST.
--nogameDo not load any default game files. Unless you also specified --tlkin, no DIALOG.TLK will be loaded. Unless you also specified --search, no override directory will be used.
--search X Look in X for input files (cumulative). X is treated as an override directory and is given priority over the default override directory.
 
Game Text (TLK) File Input
--tlkin X Use X as DIALOG.TLK (instead of looking for DIALOG.TLK in the game directory).
--ftlkin XUse X as DIALOGF.TLK (instead of looking for DIALOGF.TLK in the game directory).
FILE.TLKEquivalent to --tlkin X.
--tlkmerge X Merge strings from X over the strings from any other loaded DIALOG.TLK.
 
General Output Options
--out X Emit most output files generated by command-line options (e.g., D, DLG, kits, --biff-get, BAF, BCS, --automate, --traify-tlk, --extract-kits, --list-biff, --cmp-from, --dcmp-from, etc.) to file X. If X is a directory, certain commands (e.g., D, DLG, --biff-get, etc.) will place their output there. Does not affect TP2 processing.
--append XLike --out, but if X is an existing file then the result will be appended to it instead of overwriting it.
--backup X Backup files to directory X before overwriting. Does not affect TP2 processing.
--tlkout X If any strings were added to or changed in the loaded DIALOG.TLK, emit X as an updated version that reflects those changes. Many operations (e.g., compiling D files, --tlkmerge, STRING_SET) can add to or modify DIALOG.TLK.
--ftlkout XIf any strings were added to or changed in the loaded DIALOGF.TLK, emit X as an updated version that reflects those changes.
 
Dialogue Text File (D) Options
--noheader Do not emit D header comments.
--nofrom Do not emit D // from: comments.
--full-fromGenerate complete // from: comments with a slower two-pass process.
--nocomDo not emit ANY D or BAF comments.
--textEmit string text with string references in comments.
--transitiveFollow EXTERN links when making D files. See the tutorial on --transitive.
--toplevelEmit only top-level dialogue states -- that is, states with non-empty triggers.
 
Translation Options
--traify XConvert X (which should be a D or TP2 or BAF) so that it uses translation references instead of literal strings. Use --out Y to specify a name for the transformed version of X and its new TRA file.
--traify# X Use with --traify and --traify-tlk. Start the newly-created TRA file at translation string @X instead of @0.
--traify-old-tra XAssumes file X to contain strings already in .tra format. Use this over --traify# for merging new strings in an already traified D or TP2 or BAF file.
--untraify-d Xconvert .D file X to use hardcoded strings...
--untraify-tra X...from TRA file X. Please note that the outcoming file could not work properly (if baf code embedded in a d file contains @ references, or if a string contains the~ character).
--transEmit coupled D and TRA files when decompiling a DLG.
--transref Emit string reference numbers in TRA files when using --trans.
--traify-tlkEmit a TRA file for the loaded TLK file (see --tlkin, --out, --min and --traify#).
--make-tlk XCreate a TLK file from TRA file X (cumulative, see --tlkout).
--testtrans Test all specified TRA translation files to see if any of them use text that is already in the loaded DIALOG.TLK. If they do you can save translation effort by using string references instead.
--forceify XConvert the given D file to use forced strrefs (see --out, SAY, Forced String Reference).
 
Game Text Repository (TLK) Options
--string X Display string reference #X (cumulative). If you also specify --min or --max, all string references between --min (or 0) and --max (or infinity) will be displayed.
--strfind X Display strings that contain X (cumulative, regexp allowed).
--strapp X Append string X to DIALOG.TLK (cumulative).
 
Game Archive (BIFF) Options
--list-biffs Enumerate all BIFF files in CHITIN.KEY.
--list-files Enumerate all resource files in CHITIN.KEY
--biff XEnumerate contents of BIFF file X (cumulative).
--biff-get X Extract resource X from game BIFFs (cumulative, regexp allowed).
--biff-get-rest X Y ...Every argument given on the command line after --biff-get-rest is treated as if it were preceeded by --biff-get. Use this command to extract multiple different files (or regexps) at once.
--biff-get-list X Y ...Every argument given on the command line after --biff-get-rest is treated as if it were preceeded by --biff-get, with the -list exception. Use this command to extract multiple different files (or regexps) at once.
--biff-str X Search all game BIFFs for files containing X (regexp allowed).
--biff-value XSearch all game BIFFs for files containing value X at offset ADDR. Must be used with --biff-value-at.
--biff-value-at ADDRGives the offset address for a --biff-value search.
--biff-type X Limit --biff-str or --biff-value searches to resources of type X (cumulative).
--biff-name X When a --biff-str or --biff-value search finds a matching file, assume it has a strref name at offset X and print that name out as well.
--make-biff XCreate data/X.bif from all files in folder X and destructively update CHITIN.KEY. Do not use this feature. Do not even think of using this feature without backing up CHITIN.KEY.
--remove-biff XRemove references to BIFF X and all of its resources from CHITIN.KEY. Do not use this feature.
 
Comparison Options (see --out)
--cmp-from X Emit WRITE_BYTEs to turn this file ...
--cmp-to X ... into this one.
--dcmp-fromX Emit REPLACEs to turn this DLG file ...
--dcmp-to X ... into this one.
--tcmp-fromX Compare this TRA file (or directory of TRA files)...
--tcmp-to X ... with this one (or this directory).
--tlkcmp-fromX Emit STRING_SETs to convert this TLK file ...
--tlkcmp-toX ... into this one.
--tlkcmp-use-stringsWhen using --tlkcmp-from, emit commands of the form STRING_SET "Hello" @1 instead of STRING_SET #1 @1.
--bcmp-from XEmit APPLY_BCS_PATCH to turn this BCS file ...
--bcmp-to X... into this one.
--bcmp-orig XOriginal file X to apply ...
--bcmp-patch X... this patch to.
 
Range Options
--min XLower range for some commands. See --traify-tlk, --tlkcmp-from and --string.
--max XUpper range for some commands.
 
Automatic Module Packaging Options
--automate XAutomatically create a TP2 file for resources in folder X. See --out.
--automate-min XOnly --automate string references above X. If not specified, it is assumed as 62169 (that is, the number of strings in unmodded SoA).
--extract-kits XExtract all kits starting with kit #X and create TP2 actions to install those kits as part of a module.
 
Resouce Exploration Options
--list-eff X List effects in resource X. See --out.
F.ITM or F.EFF or F.SPLEquivalent to --list-eff F.EXT.
 
Logging Options
--log X Log output and details to X.
--autolog Log output and details to WSETUP.DEBUG.
--logapp Append to log file instead of overwriting it.

Finally, note that WeiDU will not add duplicate strings to DIALOG.TLK. If you instruct WeiDU to make use of the string “Imoen” (via SAY or --strapp or whatever) it will re-use any existing definition of “Imoen” instead. Two strings are equivalent in this sense only if they have the same text and the same associated sounds (normally strings have no associated sounds).

6  Example Uses

7  WeiDU Tutorials

This section includes tutorials on specific parts of WeiDU. Many of them were contributed by users like you.

7.1  Multisay

This tutorial was thoughtfully provided by Jason Compton.

Although a single SAY line can be of any length, for style purposes (particularly in BG2) it is considered good form to break up very large lines into smaller chunks.

One can easily create a series of simple SAY blocks, one doing GOTO to the next, but if there are no special conditions being checked or actions being taken, you can very easily string several lines together.

Let’s say you have a scenery NPC teaching a lesson about the Bill of Rights to the US Constitution.

BEGIN TEACHER

IF ~NumTimesTalkedTo(0)~ THEN BEGIN constitution_1
  SAY ~On September 25, 1789, the First Congress of the United States
    therefore proposed to the state legislatures 12 amendments to the
    Constitution that met arguments most frequently advanced against it. The
    first two proposed amendments, which concerned the number of constituents
    for each Representative and the compensation of Congressmen, were not
    ratified. Articles 3 to 12, however, ratified by three- fourths of the
    state legislatures, constitute the first 10 amendments of the
    Constitution, known as the Bill of Rights.~
  IF ~~ THEN EXIT
END 
This is a perfectly valid block of dialogue, but it is extremely long, and would likely scroll out of the text window for players with lower resolution.

Rather than break each sentence up into a new explicit state, we can use Multisay and save a lot of typing. Multisay is invoked with the = (equals) sign, which tells WeiDU that, "the current speaker should say another line here."

Here’s how that D state would look with Multisay:

IF ~NumTimesTalkedTo(0)~ THEN BEGIN constitution_1