Dialogue Modding – pt 6 – Plots
✱ updated September 2024
Hmmm. So. Plots are extremely important, not just in dialogue, but to anything that happens in the game. They’re the backbone of the game, the structure that connects everything together, and are used heavily in both entry level and advanced modding. And yet there’s a reason I’ve been putting off dealing with them until last.
This is not exactly entry level stuff.
The entry level stuff
Plots have been covered briefly in parts one and two, but only as far as necessary to understand the roles of actions and conditions in dialogue. It’s time to revisit our basic understanding of plots as their own entity.
Each plot, as an individual unit, is really just a container for plot flags along with a little extra information. This information will always include:
- A GUID by which each plot is identified
- A plot script, for all the unique behavior the plot may have to handle
- A plot entry type
- 1 = Plot
- This is the default type when no special UI behavior is required
- 2 = Story So Far
- Story So Far plots update the text that appears when loading a save game
- 3 = Codex: Creatures
- 4 = Codex: Items
- 5 = Codex: Places
- 6 = Codex: Lore
- 7 = Codex: Characters
- 8 = Codex: Letters and Notes
- 11 = Codex: Art of War
- 12 = Letter
- I believe these are letters delivered to Hawke’s desk, as opposed to the codex category
- 14 = Plot Group
- These appear as category headers in the journal, i.e. Main Plot, Companions, Rumors, etc.
- 1 = Plot
Plots may also use the following fields:
- The plot name, which is a string reference for the title of the in-game journal or codex category, journal or codex entry, job board posting, or letter
- The parent plot. If the parent plot is a plot group, the journal entry for this plot will be found under that heading. If the parent plot is a quest, this plot can display as a subquest that must be checked off individually before the full quest can be completed
- The plot priority, default value 1. Theoretically this should control the sort order of plots in the journals per the toolset wiki but having done only minimal testing I cannot confirm what affect if any this has in game.
What makes editing plots difficult in DA2 compared to Origins is that in some cases the internal structure of plot files has been radically changed from Origins. Two notable difficulties:
- The plain text name of each plot flag is exported to the GFF in Origins plots. In DA2, this is missing, which makes it impossible to guess the purpose of each plot flag by just looking at the file.
- When DA2 plots were restructured, rather than adding new GFF fields (as they did in conversations), they reused existing fields. This means the labels when viewed in pyGFF are incorrect. They should be labeled as follows:
- 0 PLOT 3 TEMPLATERESREF ECString seb221pt_repentance 13000 PLOTGUID ECString 2AA50907F15F47A094C9835F9A5195F3 13001 PLOT_NAME TlkString 6185016, 0 13002 PLOT_SCRIPT ECString seb221pt_repentance 13003 PLOT_PRIORITY INT32 1 13004 ECString ? 13005 PLOT_PARENT_PLOT ECString dae00pt_followers 13006 PLOT_ENTRYTYPE INT32 1 13007 UINT8 0 13008 PLOT_PARENT_GUID ECString 380459474ED24FFCB9A2BC1EB47E34AD 13050 UINT32 0 13051 UINT32 0 13052 UINT32 0 13053 UINT32 0
Types of plot flags
The truly important part of plots are the flags. Plot flags are either true or false. They cannot store non-binary data. They are written to the save game with a GUID identifying the plot, plus four fields representing plot flags 0-31, 32-63, 64-95, and 96-127 via bitwise flag.
- 0 GFF V4.1 SAVE V2.0 PC - 16003 SAVEGAME_PARTYLIST PRTY - 16400 SAVEGAME_PLOT_MANAGER PLMR - 16401 SAVEGAME_PLOT_LIST [PLEN] - 0 PLEN 16402 SAVEGAME_PLOT_GUID ECString 5FDEFF4F87044A6E8E84965764A1C4B2 16403 SAVEGAME_PLOT_FLAGS_1 UINT32 3252882145 16404 SAVEGAME_PLOT_FLAGS_2 UINT32 20117 16405 SAVEGAME_PLOT_FLAGS_3 UINT32 115605952 16406 SAVEGAME_PLOT_FLAGS_4 UINT32 62
Standard plot flags (0–127) can be actively set by the game to be true (or set back to false). Standard plot flags are often set within a conversation, particularly at the end of a conversation branch to indicate that stage of the conversation has been played and to trigger whatever behavior is required to progress the quest. These behaviors are coded in the plot script, and can cover a vast array of functions.
Defined plot flags (which start at 256) cannot be actively set. Instead, they are scripted if-statements that will return true or false depending on other factors. While standard flags can be used as either conditions or actions, defined flags can only be used as conditions.
To give an example, gen00pt_party has a number of standard flags that can be used in conversations to add or remove various followers to and from the party (using the SetFollowerState() script function), and a number of defined flags that check to see if each follower is in the active party or not (using the GetFollowerState() script function). These defined flags are checked whenever party members can interrupt with dialogue reacting to the current conversation, or whenever they can add or lose approval, so that these things only happen if that follower is actually actually present.
File-defined plot flags
Dragon Age 2 also added additional fields within the plot file that can define plot flags without the use of scripting. Both script-defined and file-defined plot flags can be used within the same plot, though not for the same flag. If a flag is defined in both locations then only the definition in the file will be considered, not the script.
These new fields can only 1) check if other plot flags are true or false and 2) combine them with simple boolean logic.
Logic has never been my strongest suit so please bear with me. I’ll try to break this down as best I can.
File-defined plot flags consist of two parts: 1) a list of zero-indexed plot flags, and 2) a list of logical functions. The first number in a logical function defines what type of function it is.
- 0 is a plot flag
- 1 is the AND operator
- 2 is the OR operator
- 3 is the NOT operator
The second number in a logical function either defines which plot flag to check from the first list, or how many arguments that function accepts.
So if the logic list looks like the following:
- 13501 [COMP] - 0 COMP 13200 PLOT_FLAG_ID UINT16 256 - 13502 [PFLG] (2 items) + 0 PFLG 478CEED95AD54937ACD9594206E57642, 261 + 1 PFLG 96F97AD3A07A4A3794B0089BF8D0C302, 14 - 13520 [CLAS] (3 items) + 0 CLAS 1, 2 (AND) + 1 CLAS 0, 0 (PFLG) + 2 CLAS 0, 1 (PFLG)
That AND function (1) accepts two arguments, so it will return true if the two plot flags on the preceding list both return true.
If the logic list instead looks like the following:
- 13520 [CLAS] (4 items) + 0 CLAS 2, 3 (OR) + 1 CLAS 0, 0 (PFLG) + 2 CLAS 0, 1 (PFLG) + 3 CLAS 0, 2 (PFLG)
That OR function (2) accepts three arguments, so it will return true if any of the three plot flags return true.
These have been simple examples, but they can get far more complex when nesting is involved. Here’s an example of that:
- 13501 [COMP] - 0 COMP 13200 PLOT_FLAG_ID 261 - 13502 [PFLG] (4 items) + 0 PFLG 18854EB329424101AAD5D80BD648D445, 268 + 1 PFLG 96F97AD3A07A4A3794B0089BF8D0C302, 19 + 2 PFLG 96F97AD3A07A4A3794B0089BF8D0C302, 15 + 3 PFLG 96F97AD3A07A4A3794B0089BF8D0C302, 16 - 13520 [CLAS] (8 items) + 0 CLAS 1, 2 (AND) + 1 CLAS 0, 0 (PFLG) + 2 CLAS 2, 2 (OR) + 3 CLAS 3, 1 (NOT) + 4 CLAS 0, 1 (PFLG) + 5 CLAS 1, 2 (AND) + 6 CLAS 0, 2 (PFLG) + 7 CLAS 0, 3 (PFLG)
The first AND function accepts two arguments, but the second argument is an OR function, which itself accepts two arguments. These are the NOT function (3, which takes the next argument) and the following AND function (which takes the last two)
Here’s one way to think of the nesting:
And here’s how it would look if it were instead defined in dascript:
if( FLAG_0 == TRUE
&&( FLAG_1 == FALSE
||( FLAG_2 == TRUE && FLAG_3 == TRUE )))
return TRUE;
if( FLAG_0 && ( !FLAG_1 || ( FLAG_2 && FLAG_3 )))
return TRUE;
Plot assist
Standard flags can also use special fields used to automate some common behaviors. While plot assist technically refers only to the quest markers, I’m going to generalize the term to refer to the entire collection of custom fields available to standard flags.
- 13300 [SIMP] - 0 SIMP 13009 UINT8 0 13200 PLOT_FLAG_ID UINT8 5 13301 PLOT_FLAG_ENDS_PLOT UINT8 1 13302 PLOT_FLAG_REWARD INT32 800220 13303 PLOT_FLAG_JOURNAL TlkString 6185022, 0 13304 PLOT_FLAG_AREA_LOCATION_TAG ECString dae221ar_chantry 13305 ECString ? 13306 [PFLG] - 0 PFLG 13100 ECString E952278C059E408E88278E00F1B3C36E 13101 UINT16 0 13320 PLOTASSIST_LIST [ASIS] - 0 ASIS 13321 PLOTASSIST_TAG ECString seb221ip_at_hightown 13322 PLOTASSIST_STATUS UINT8 2
- Plot flag ID is an obvious field
- Ends plot: If set to 1, setting this plot flag will mark the quest or subquest complete and update the journal entry accordingly.
- Reward: An ID for an entry in rewards.gda to be granted when this plot flag is set
- Journal: A string ID for the description to be shown in the journal or codex. If this is a journal entry, the most recent flag set will replace any existing text in the journal entry. If this is a codex entry, any flag set will add new text to the current entry if it exists. Codex entry segments display sorted numerically by plot flag. Codex text can kind of be removed by setting the flag false… with the caveat that it may continue to appear in the codex until the game is reloaded from a save.
- Area location tag: If this is set, it will show the quest active at this location on the travel map.
- Plot flag list: When the flag is set, any flags in this list will also be set.
- Plot assist: The tag can be any type of object you want: a creature, a placeable (like a chest or a door), a waypoint, etc. The markers will appear in game and on the area map as follows:
- 0: removes a previously set marker
- 1: sets the “❗” plot giver marker
- 2: sets the “⏬” plot assist marker
The next steps
Any upcoming entry in this tutorial series will revisit information and resources published elsewhere about how to create modded scripts and plots for DA2 and expand it to cover custom plot scripting. The most recent information I have on adding custom plots is in my Automatic Item Delivery tutorial.