Dialogue Modding – pt 1 – Orientation
✱ updated August 2024
Modding Dialogues Without The Toolset Editor
This introductory tutorial will explain how to get started modding dialogue files that aren’t accessible in the toolset dialogue editor—specifically those from DA2 or from Origins DLC.
Which tool you will prefer to do most of your work in is up to you, but for the purposes of modding dialogue, the following tools are both required:
- pyGFF is required to extract files from DA2’s ERFs. It’s also my personal tool of choice for editing GFF files like Dragon Age’s DLG/CNV files.
- The Dragon Age Origins Toolset is required for a few specific edits that cannot be accomplished with pyGFF, such as deleting conditionals and editing DA2’s CL files. I recommend applying the LAA patch to DragonAgeToolset.exe to expand the amount of memory it can use.
Another general purpose tool I recommend, which is by no means required:
- xoreos tools has a number of command line utilities that can decompose GFFs, talktables, scripts, and more into more readable and searchable formats such as XML.
Extracting the dialogues
Dialogues for each campaign are located in module resources, not in core resources. So for example, the path for Awakening dialogues is Dragon Age\
Without the toolset we won’t be able to recalculate animation blend trees (.dlb) so this is the only file we’ll need to edit.
A note on encrypted DLC
Modding exists within the grace of legal grey areas, and that area gets a lot greyer when DRM is brought into the mix. Bioware’s official stance on modding from 2011 indicates that DLC assets are fair game to use in mods for the series as long as the modder 1) legally owns the DLC and 2) does not create a mod which reproduces the DLC for those who don’t own it. Given that Bioware points were phased out in 2022 and since that point all DLC has been available completely free for all players who bought the game on a summer sale for $3… I mean…
Orientation to dialogue structure
This is what a file looks like in the dialogue editor. Lines always alternate between red owner/speaker/NTRY and blue player/listener/RPLY lines. The owner of this dialogue is Duncan, but other speakers can be tagged on individual lines.
Empty listener lines appear as [CONTINUE] (or [END DIALOGUE]) nodes and allow the conversation to continue uninterrupted by player input. Empty owner nodes also continue the conversation but in the toolset usually display as green [COMMENT] nodes.
In the toolset, grey linked lines show where one line is used in multiple dialogue branches. This doesn’t create a duplicate of the line, but instead allows it to be linked to from anywhere else in the conversation structure. This is as true in the exported file as it is in the Toolset. Outside of the Toolset, all child lines are “linked lines.”
Any line can have one or more children or child lines. The game selects which of these child lines should come next based on associated conditions.
A condition is composed of a plot, a flag, and a boolean (true/false) value. For owner/speaker lines, the game checks the condition for the first child line against the plot flags stored in the save game. If the condition fails, then it moves down to evaluate the next, until it finds a line that is valid to play. There is usually a default line at the bottom of the list with no condition set—otherwise it’s possible to be ejected from the conversation early. For player/listener lines, the game checks the condition for every line in the list and displays the valid responses as dialogue options.
Actions, on the other hand, set or clear a specific plot flag when that line plays. This can be used to advance a particular plot quest, add or remove companion approval, move creatures and objects around in the scene, or any number of other scripted behaviors.
Note that there is also a (rarely-used) script field that can also be used to check the validity of a line or fire upon line completion.
One of the more important things to note is the ID, which is visible in the very bottom corner of the dialogue editor. This ID—the string reference—is used to locate the subtitle (in the module talktable), the voiceover audio, and the faceFX (lip sync) for each line that plays. The string reference is separate from the sequential line ID that is given to each line when a file is exported.
Understanding the basic structure of a dialogue makes it pretty easy to get at what’s going on once the conversation has been exported into GFF format.
Orientation to GFF structure
A DAO conversation will look something like this:
- 0 GFF V4.0 CONV V0.1 PC CONV ... - 12000 CONVERSATION_STARTING_LIST [UINT32] (5 items) 0 UINT32 0 1 UINT32 10 2 UINT32 28 3 UINT32 64 4 UINT32 205 + 12002 CONVERSATION_LINE_LIST [*] (508 items) + 12003 CONVERSATION_END ENDA ?, -1, 255, ?, 0 12004 CONVERSATION_VOBANK STRING gxa000_anders
This differs slightly from the DA2 version, which will look something like this:
- 0 GFF V4.0 CONV 3.0 PC CONV ... 30000 UINT8 255 - 30001 CONVERSATION_STARTING_LIST [LINK] (4 items) + 0 LINK 0, ... + 1 LINK 4, ... + 2 LINK 99, ... + 3 LINK 102, ... + 30002 CONVERSATION_LINE_LIST [*] (211 items) + 30003 CONVERSATION_END PLOT ?, -1, 255 30004 FLOAT32 -1.0 30005 FLOAT32 -1.0
Files from DAO are generally easier to read at first than those from DA2 because there’s more readable text, but the idea is basically the same (and I have labeled certain DA2 fields in the examples here). You can see both files have a starting list, indicating which lines of dialogue mark the beginning of separate branches of the conversation tree.
Expanding the line list to view the contents of a line of dialogue reveals where the real differences lie. A line in DAO will look something like this:
- 12 NTRY 12100 CONVERSATION_STAGE_NAME STRING 2p_200_bronze_r 12104 CONVERSATION_STAGE_AT_CURRENT_LOCATION UINT8 255 12201 CONVERSATION_LINE_TEXT TLKSTRING 428168 12202 CONVERSATION_LINE_SPEAKER STRING OWNER 12203 CONVERSATION_LINE_LISTENER STRING PLAYER 12204 CONVERSATION_LINE_GAME_LANGUAGE INT32 0 12205 CONVERSATION_LINE_ICON INT32 0 12206 CONVERSATION_LINE_VISIBILITY INT32 0 12207 CONVERSATION_LINE_AMBIENT UINT8 0 + 12208 CONVERSATION_LINE_COND PLOT + 12209 CONVERSATION_LINE_ACTION PLOT 12211 CONVERSATION_LINE_CUTSCENE CUT 12213 CONVERSATION_LINE_ANIMATION UINT32 4294967295 12214 CONVERSATION_LINE_SKIP UINT8 0 12215 CONVERSATION_LINE_FASTPATH UINT8 0 12216 CONVERSATION_LINE_NOVOINGAME UINT8 0 12217 CONVERSATION_LINE_REVERT_ANIM UINT8 0 12218 CONVERSATION_LINE_SLIDE_SHOW_TEXTURE STRING - 12400 CONVERSATION_LINE_CHILDREN_LIST [UINT32] (3 items) 0 UINT32 243 1 UINT32 245 2 UINT32 247 12500 CONVERSATION_LINE_ACTIVE [IMAP] (2 items)
The file structure for DA2 is very different. Two lines will look more like this:
- 5 LINE 30200 UINT16 10 30201 CONVERSATION_LINE_TEXT TLKSTRING 6071418 + 30202 CONVERSATION_LINE_COND PLOT + 30203 CONVERSATION_LINE_ACTION PLOT - 30204 CONVERSATION_LINE_CHILDREN_LIST [LINK] (2 items) - 0 LINK 30100 UINT16 6 30101 CONVERSATION_WHEEL_PARAPHRASE TLKSTRING 4294967295 30301 CONVERSATION_WHEEL_CATEGORY UINT8 255 30300 CONVERSATION_WHEEL_ICON UINT8 255 30303 CONVERSATION_WHEEL_FOLLOWER UINT32 4294967295 - 1 LINK 30100 UINT16 61 30101 TLKSTRING 4294967295 30301 UINT8 255 30300 UINT8 255 30303 UINT32 4294967295 - 6 LINE 30200 UINT16 257 30201 TLKSTRING 6071479 + 30202 PLOT + 30203 PLOT + 30204 [LINK] (1 item)
As you can see, each line in a DAO dialogue file contains a large number of fields not present in DA2 conversation files. Some of these fields concern animations/cinematics, which in DA2 have been moved to external .cl files. Others are options which in DA2 have been converted to a single bitwise flag. (Both of these concepts are explored in further depth in later parts of the tutorial series). A few fields I’m pretty sure are only used in the Toolset but never in game.
On the other hand, DA2 child lines have several more fields than DAO, to accommodate the dialogue wheel (which also has its own dedicated writeup in this tutorial series).
For basic edits, everything we really want is present in both: the tlk string reference, the condition, and the list of child lines.
Lines of dialogue export reasonably in order. One thing to note while unraveling the structure of the specific conversation you’re working with is that in DA2, speaker and player lines export alternating in sequence, while Origins exports all speaker lines first (NTRY) followed by all player lines second (RPLY).
Finally, let’s take a look at the structure of conditions and actions, starting with DAO:
- 12208 CONVERSATION_LINE_COND PLOT 12300 CONVERSATION_PLOT_GUID STRING 6526F8E770484223A6FD7B72C1DE70C8 12301 CONVERSATION_PLOT_FLAG INT32 1 12302 CONVERSATION_PLOT_TEST UINT8 255 12303 CONVERSATION_SCRIPT STRING ? 12304 CONVERSATION_SCRIPT_PARAMETER INT32 0 - 12209 CONVERSATION_LINE_ACTION PLOT 12300 CONVERSATION_PLOT_GUID STRING ? 12301 CONVERSATION_PLOT_FLAG INT32 -1 12302 CONVERSATION_PLOT_TEST UINT8 255 12303 CONVERSATION_SCRIPT STRING ? 12304 CONVERSATION_SCRIPT_PARAMETER INT32 0
And in DA2:
- 30202 CONVERSATION_LINE_COND PLOT 30400 CONVERSATION_PLOT_GUID STRING 6F4E853DF7EE4DE3841C31928BF663C3 30401 CONVERSATION_PLOT_FLAG INT32 8 30402 CONVERSATION_PLOT_TEST UINT8 255 - 30203 CONVERSATION_LINE_ACTION PLOT 30400 STRING ? 30401 INT32 -1 30402 UINT8 255
You’ll note the script field in DAO files is not present in DA2, but everything else is the same. There’s a plot GUID, a plot flag, and the plot test, which will be either 255 (true) or 0 (false).
Identifying plot flags
For the most part, you’ll be able to guess plot flags from context, but if you’re concerned with specific flags available in the DAO base game, you can find the flags and GUID in the toolset.
If you want to confirm a plot flag in DAO DLC you can find the same information in the .plo file.
Unfortunately the file structure of DA2 plot flags is very different, and none of it in human-readable format. Determining what plot flags you may need is a feat that requires a post all to itself (upcoming in a future update…).
Accessing the talktable
Of course all of this is pointless if we can’t see what each individual line is. That’s where the tlk string reference comes into play. Each string reference corresponds with an entry in the talktable.
Again, conversation data is located in module resources, not core resources. So the English language Awakening talktable, for example, is in Dragon Age\
For an option that works for both DAO and DA2 talktables, use tlk2xml in xoreos tools to convert the talktable to XML format.
For a different command line option for DA2 talktables, download DA2 Tlk Converter (GitHub). To convert the talktable to plaintext format, copy the talktable into the same folder as the program. Copy the following into an empty text file and save it with the .bat extension in the same location, then double click the batch file to run the script.
for %%a in (*.tlk) do da2tlkconv.exe -d -i %%a %%a.txt
For a solution for DAO talktables which does not require the use of the command line, download DAOTlkEdit (ModDB mirror). When you open the talktable, sort by StrRef (string reference). In the bottom right corner is a field where you can search for strings or string references.
String references export to the talktable somewhat in order, as they are generated the first time that line is saved in the toolset. If you search for a string reference and it can’t be found, that means it’s an empty string and that line functions as a [CONTINUE].
Finally! If you don’t want to mess with any of that, you can download my DA2 TLK Dump below or from my Dialogue Mini Mods on the Nexus. I’ve formatted these files to suit my preferences when searching them.
Visualizing conversations from DA2
While you cannot open DLC dialogues or DA2 conversations in the toolset’s native conversation editor, some noble soul on the now-deleted Bioware forums did create a conversation viewer (archive.org mirror) for DA2, and archive.org managed to snag most of it. This can be a helpful way to get an idea of the flow of a conversation before diving into the muddled mess that is GFF for yourself. Please read the installation instructions carefully. I barely remember how I got the SQL database working myself so I’m not going to help anyone troubleshooting. I’ve mirrored missing content here:
da2_content.zip (393 downloads )