Dialogue Modding – pt 5 – Cloning

Why cloning?

Currently the main limitation on cloning lines in DA2 is the inability to add new or edited lines of dialogue to soundbanks. If someone were to crack that we’d be golden.

Without the ability to add new VO to the game, however, there are other reasons you may wish to clone (aka, duplicate and repurpose) a given line of dialogue that cannot be solved by simply rerouting the conversation.

1) You want to break out a skip line into a separate file so you can have more control when modding the conversation.

2) You want to reuse a line in a different conversation (like stealing lines of Hawke’s dialogue to transplant into unrelated conversations – here’s a proof of concept).

3) You want to reuse a line in the same conversation but in a different branch of dialogue or with different staging (probably the main use for this would be in follower “gen00fl_” conversations which are huge and used throughout the entire game but there are innumerable niche use cases).

4) You want to add a cutscene and want to reuse existing animations and staging, like in @quenched-steel-modding‘s incredible Repeatable Romance Scenes.

5) You want to add new lines of (sadly unvoiced) dialogue and want to reuse the facefx and animations, like I have done in Kidnappapalooza.

General principles

With that said, here are some general principles to keep in mind when cloning:

  • 1) Clone the parts of cinematics that will be most difficult to manually edit

Certain cinematic aspects are easy enough to edit. Swapping actors or dialogue and facefx is incredibly simple. The things that will be difficult and time consuming to try to tweak yourself are things like animations, complex camera movements, etc. As I mentioned in the last post, anything involving curves, keys, and GAD can quickly turn into a headache.

So when you’re deciding what file to clone, choose the file with the best animations for what you’ll need, closest to the length that you’ll need. Animations are the single most difficult thing to work with without a proper editor, and you’ll save yourself a lot of trouble down the line. In most cases, staging is easy enough to edit that it’s irrelevant as well, but in edge cases with complex actor and camera movement, matching staging should be a priority as well.

  • 2) The conversation doesn’t queue the dialogue, the cinematics do

One gets used to thinking of the conversation as being representative of what’s played out on screen but this is not quite correct – the .cnv tells the game which .cl to play (as determined by the string reference in the .cnv) but it is the .cl that tells the game what subtitles to show and what voiceover and facefx to play (as determined by the string reference in the .cl).

This means two things:

  • 2a) Edit the on-screen dialogue wheel in the .cnv, edit voiceover and subtitles in the .cl

Of course, if you’re not doing anything that requires complex line edits then adjusting the order in which the .cnv queues the .cl files without ever touching the cinematics directly is more than fine. But this principle was true for the parts of the tutorial that covered adding local strings, and it will continue to hold true with further advanced edits.

  • 2b) The string reference in the .cnv does not have to be the same as the string reference in the speak line action

This is incredibly useful information because it allows us to clone and reuse lines of dialogue within the same conversation, but with different cinematics (such as staging). Were this principle false this would be impossible, because the game automatically identifies the proper file to play as [conversation][string reference].cl, which would limit us to the use of only one cinematic per string reference per conversation.

As it stands, if you want to reuse a line of dialogue within the same file, you can simply assign a new unique string reference in the .cnv to use for your cloned .cl, and then change string reference for the speak line action to any line of dialogue you want.

Generating string references

String references for dialogue in the base game and all the DLC I’ve checked are in the 6000000-6999999 range (actually 6000000-6299999 but there’s no need to get greedy). Don’t use any string references in or below that range. Every string reference below 6999999 should be considered “reserved” for Bioware’s use to prevent accidental collision.

The first time I need a string reference for a new project I pop over to random.org, generate a random number between 7000000-9999999, and then count up from there for each string reference I need for that specific mod. This saves me the trouble of having to globally track which string references I’ve used across all projects.

This is also how the Origins toolset generates new string references – it generates a random starting integer each time a new module is created. This is such a large range and the number of people modding DA2 is so small that there is an essentially zero chance of two mods conflicting with each other in this way. I strongly suggest sticking to 7-digit integers as you will otherwise be unable to clone facefx.

Cloning cinematics

This is the first step you will take every time you clone a line, and is the only edit that will always be required. Our aim here is to steal a .cl, and add it to the .cnv where we want it to play.

Adding a new single line of dialogue requires adding one or two additional nodes to the conversation, depending on how the speaker > listener > speaker > listener lines in that part of the conversation are structured, and if you can connect your line in with existing listener lines or need to create new ones.

To reduce the amount of editing required, copy lines that are similar to the line you’ll be adding (so if you’re adding a new dialogue response from Hawke, copy another response from the same dialogue wheel), and paste them so that they are added to the bottom of the list. Remember if you’re working in pyGFF you may need to clean up empty conditions in your new lines in the toolset, or they’ll play incorrectly due to pyGFF’s mishandling of null strings.

The only thing you should need to edit here is the string reference on your new line, the child line links to point to your new line and then back to the vanilla lines (and possibly set up your new dialogue wheel entry), and possibly conditions and/or actions on your new line. If you’ve chosen a good node to copy, you won’t have to edit the line type.

If you had to copy empty vanilla listener lines you don’t necessarily have to change the string reference, since those only matter when cinematics exist. It won’t hurt to change the string reference either so it’s up to you.

You should at this point have chosen the line you want to clone for cinematics and extracted it from its archive. The only thing you have to edit here is the file name to reflect the conversation you’re working on and the new string reference you have added to the conversation.

There is a field inside the .cl file that has a space for the string reference as well, but the game doesn’t read it, so I leave it as a quick reference of which file I cloned.

If everything has gone well, you should now be able to test the conversation in game.

From here on out, we are shelving pyGFF to work with .cl files in the toolset.

Swapping out actors and dialogue

If you’re adding existing dialogue to a very different conversation, you’ll frequently end up cloning a line that has neither the desired dialogue nor the desired character. Luckily, these are easy fixes that don’t cover anything that hasn’t already been covered in the previous section on cinematics.

Dialogue and facefx is the realm of the ASLN/speak line action. When repurposing existing audio, you will need to edit the string reference and the lipsynch_set and vobank fields to reflect the original vanilla string reference and conversation of the line you are stealing. This string reference and potentially conversation will differ from your new cloned line. Please note that the audio of ambient lines may not play if you try to add them to a cinematic. I have found no way to fix this so far.

Actors can be swapped out by changing both name and mapping tag. In cases such as when multiple characters can conditionally appear in the same cutscene, actors can also be duplicated within the file, given a new unused cutscene_actor_ID (very important step do not forget!), and THEN swapped, as well (this information brought to you by Kidnappapalooza and the thousand cinematics I had to edit Sebastian into).

Staging, if necessary, can be adjusted to match the surrounding dialogue by editing the cutscene stage name and the AJSP/jump to stage place and AJSC/jump to stage cameraactions. Remember to tweak the default_camera field if changing the camera causes the scene to go screwy on you.

On facefx

If you are migrating lines of dialogue from one conversation to another, the game will struggle to find the proper facefx and the lipsync won’t play, though the audio will. This looks weird and bad. Fortunately, the fix is simple. There are .crf archives for each conversation prefixed “fxe_” which can be found in modulescampaign_baseaudiovoen-usfacialanimations. All you need to do is extract the individual facefx from the archive and drop it in override, and remember to pack it up with your mod when you upload it.

There is one more quirk that need to be addressed with regard to facefx:

Most facefx in the game will be named [string reference]_m.fxe. There are some instances where they have generated separate facefx for fHawke, which will be named [string reference]_f.fxe, but for the most part there’s just the one file. If no *_f.fxe file is found, fHawke will play the *_m.fxe file. But if no *_m.fxe file is found, mHawke will not play the *_f.fxe file. This is a rare occurrence, but you may encounter it.

You may need to clone facefx to fix the above, or perhaps you would like to clone facefx to reuse the facial animations without also playing the associated dialogue – say, if you’re adding unvoiced dialogue with subtitles in a local string.

You will need to rename the facefx file to [new string reference]_m.fxe, but unlike the .cl, the facefx file also has to be edited internally with a hex editor. It’s pretty simple. I use HxD, which is free and lightweight. You’ll see in the text view where you can overwrite the old string reference with your new one of the same length.

Splitting up bundled skip lines

This can be done but it’s not going to be easy. The reason you would want to break up a cinematic file with multiple lines is so that you can alter the flow of the conversation in the .cnv around them. Maybe you want some of the lines to only play conditionally – adding a condition to the .cl may cause the line to not play, but won’t change the overall length of the line, leaving a weird silence.

Keep in mind that if you can accomplish what you want by merely editing the .cl and not restructuring that part of the conversation in the .cnv, then by all means don’t make things more complicated than they need to be. My Gayer Cassandra edit doesn’t touch the .cnv at all because the lines I wanted to edit were bundled up in a single file and I didn’t need to do anything more complex than swapping a single always-play line with another. Likewise, I’ve had to edit the .cnv for the MOTA “to the rescue!” cutscenes to add connective tissue to trigger my new Bethany/Carver versions, but any other edits to the mini cutscenes themselves are done strictly within the cinematic file. Think carefully about when .cnv edits are required and when .cl edits will serve your purpose.

Anyway, let’s say we have a cinematic with two lines, and we want the second line split out into its own file so we can get creative with it. To do so, we will need to find that line in the .cnv and edit its line type by subtracting 8 so that it is no longer skipped. Then we will need to clone the bundled lines by renaming it with its own exiting string reference.

That’s the easy part.

As a general guideline, you will need to note the overall cutscene run time, as well as the start time of the second line. We will want the second line to start at 0, so subtract the start time from the cutscene run time and write this number down – this is your delta.

In the cinematics for the first line – delete the second speak line action, and subtract the delta from the cutscene run time. This may or may not be the only edit you need.

In the cinematics for the second line – you’re pretty much just gonna want to subtract the delta from everything. Start and end times of speak lines, of animations, of camera jumps. If you miss anything, it will be obvious. Go ahead and delete anything that ends up fully in the negative. Just careful not to subtract the delta from this cutscene run time – instead, it should be the difference, which will end up pretty close to the speak line’s end time. Or if you need to split out a third line, recalculate your new delta and start over. Oh, and if there are curves anywhere you’re going to want to adjust the timing on those too.

What makes this even more complicated to deal with is that usually the only reason they bundle lines up like this is to get – for lack of a better term – “artistic” with complex animations or camera movements. This will likely show very visible seams and slight jumps when queued up as separate lines, which is why they don’t do it that way. You may have to compensate by simplifying and shifting things around. If there’s a camera jump, move it to 0 to cover the line change. If there are long running animations, you can possibly move or truncate or remove them. If there’s a camera pan, feel free to make it a stable shot instead.

Or consider saving yourself a lot of hassle by cloning a different line closer to the proper length to start out with.

This is a pain in the ass so really think long and hard about whether it’ll be worth it.

On erfpacking

Many people package up their DA2 mods into .erfs whether it’s necessary or not. The only time it’s really necessary to distribute a mod as an .erf is when you’re modding models, textures, animations, or any similar files which have to be located by their full filepath. Filetypes such as .gda, .cnv, .cut, .cl, .fxe, .mor, .ncs, .utc, .uti, or any of the many many other files that aren’t referenced by its full filepath can be shipped as loose files in a folder, and sometimes it’s desirable to do so. It can make it much easier for the end user to tweak the mod on their end or search filenames for mod conflicts. I’m very in favor of shipping most .gda and headmorph mods loose, for example.

When editing cutscenes and dialogue, this means that you can test your mod in progress without having to run it through an erfpacker (I still use gibbed’s) every single time, which is a huge time saver. However, you will notice that once your override starts filling with a lot of small loose files (particularly .cl) you may start encountering extended load times while testing your modded conversations.

The big benefit to packing small files into archives is that it greatly reduces load times for the game. This is likely the reason the Origins toolset always packs files when exporting modules. The last step before shipping any complex dialogue mod should be to pack up the loose files, to save load times for both you and your users.