Jump to content

how to efficiently add conditional dialogue triggers


Recommended Posts

Okay so the .DLG side of the Weidu readme is a foreign land to me. I spend all my time down in the nuts of bolts of COPY_EXISTING and OFFSET_ARRAY etc. But I would like to patch some dialogues. Specifically, in existing dialogues that have an XP reward, I would like to duplicate the existing reward block, but with a different XP value, and make the original and duplicate blocks dependent on the value of a global variable.

As an example, there is this bit from DAMBERE.DLG in IWD:

IF ~~ THEN BEGIN 9
  SAY #21914 
  IF ~CheckStatGT(LastTalkedToBy,12,CHR)~ 
      THEN REPLY #21915 DO ~SetGlobal("Ambere_Family","GLOBAL",1)
                            AddXP2DA("Level_6_Easy")
                            DisplayStringNoNameDlg(Myself,18518)
                            AddJournalEntry(23781,INFO)~ GOTO 10
  IF ~~ THEN REPLY #21916 GOTO 21
  IF ~~ THEN REPLY #21917 EXIT
END

I would like to duplicate the block with the charisma check, so it looks like this:

IF ~~ THEN BEGIN 9
  SAY #21914 
  IF ~CheckStatGT(LastTalkedToBy,12,CHR)
      Global("D5_IWD_REAL","GLOBAL",0)~ 
      THEN REPLY #21915 DO ~SetGlobal("Ambere_Family","GLOBAL",1)
                            AddXP2DA("Level_2_Easy")
                            DisplayStringNoNameDlg(Myself,18518)
                            AddJournalEntry(23781,INFO)~ GOTO 10
  IF ~CheckStatGT(LastTalkedToBy,12,CHR)
      Global("D5_IWD_REAL","GLOBAL",1)~ 
      THEN REPLY #21915 DO ~SetGlobal("Ambere_Family","GLOBAL",1)
                            AddXP2DA("Level_6_Easy")
                            DisplayStringNoNameDlg(Myself,18518)
                            AddJournalEntry(23781,INFO)~ GOTO 10
  IF ~~ THEN REPLY #21916 GOTO 21
  IF ~~ THEN REPLY #21917 EXIT
END

Is there a straightforward way to get from the 1st version to the 2nd version?

 

Edited by subtledoctor
Link to comment
5 hours ago, subtledoctor said:

Okay so the .DLG side of the Weidu readme is a foreign land to me. I spend all my time down in the nuts of bolts of COPY_EXISTING and OFFSET_ARRAY etc. But I would like to patch some dialogues. Specifically, in existing dialogues that have an XP reward, I would like to duplicate the existing reward block, but with a different XP value, and make the original and duplicate blocks dependent on the value of a global variable.

I'm far from being expert but I would ditch dialogue related actions and use DECOMPILE_AND_PATCH + REPLACE_TEXTUALLY / REPLACE_EVALUATE. The only problem is to find good regexp to match this block. Then should be easy to duplicate if you capture whole block as group you can just replace one occurrence into two occurrences in the row (or event edit second one as you like on the fly).

Link to comment

I’m assuming REPLACE_TEXTUALLY would be prone to failure, since the .DLG I’m actually targeting is a mod-added one, so the .TLK numbers and spacing cannot be predicted. 

I guess I’m wondering if there is some combination of patches using more sophisticated commands like ADD_TRANS_TRIGGER etc. that could manipulate the GOTO 10 response while leaving untouched the GOTO 21 and EXIT responses. 

Link to comment
1 hour ago, subtledoctor said:

I’m assuming REPLACE_TEXTUALLY would be prone to failure, since the .DLG I’m actually targeting is a mod-added one, so the .TLK numbers and spacing cannot be predicted. 

Yes, could be. As I said, it is matter of regexp. It can be more strict but then more chance that it will not match. It can be more liberal and match something that shouldn't be matched. :D But you need to identify this block somehow anyway.

Hoping you will find more elegant solution. Just in case, here is the code that solves example:

OUTER_SPRINT s ~[%TAB% %LNL%%MNL%%WNL%]~

OUTER_SET ok = 0

COPY ~Test/in.d~ ~Test/out.d~
    REPLACE_TEXTUALLY EVALUATE_REGEXP ~%s%+~ ~ ~
    REPLACE_TEXTUALLY EVALUATE_REGEXP ~%s%+~ ~ ~
    REPLACE_EVALUATE "BEGIN 9.*\(IF%s%*~CheckStatGT.*GOTO%s%*10\)" 
    BEGIN 
        SET ok = 1
      	// you can also access %MATCH1% here and do some trasformation
    END ~~~~~
        %MATCH0% 
        %MATCH1%
    ~~~~~

ACTION_IF (NOT ok) BEGIN 
    WARN ~not ok~
END

 

Link to comment

A dialogue state is a state in WeiDU parlance, and replies are transitions. In d code this is trivial:

ADD_TRANS_TRIGGER DAMBERE 9 ~Global("D5_IWD_REAL","GLOBAL",0)~ DO 0

EXTEND_TOP AMBERE 9
  IF ~CheckStatGT(LastTalkedToBy,12,CHR)
      !Global("D5_IWD_REAL","GLOBAL",0)~
      THEN REPLY #21915 DO ~SetGlobal("Ambere_Family","GLOBAL",1)
                            AddXP2DA("Level_2_Easy")
                            DisplayStringNoNameDlg(Myself,18518)
                            AddJournalEntry(23781,INFO)~ GOTO 10
END

EXTEND_TOP isn't the friendliest way to do this, as it re-orders the transition numbers which can impact compatibility with other mods. However, there's no way to avoid this if you want to preserve the reply order.

So we're basically adding a new trigger to the original transition 0 in state 9, and then using EXTEND to add a brand new transition.

Link to comment

…But would that ADD_TRANS_TRIGGER add the trigger to all of the transitions in state 9?

Or, I can’t figure out what that “DO 0” is doing. Does it limit the ADD_TRANS_TRIGGER to the first transition?

E.g. I would want to do the same thing here:

IF ~NumTimesTalkedToGT(0)
    Global("K_Done","GLOBAL",0)~ THEN BEGIN 17
  SAY @8393
  IF ~~ THEN REPLY @8394 GOTO 5
  IF ~~ THEN REPLY @8395 GOTO 8
  IF ~GlobalGT("SPRITE_IS_DEADSH_Warrior_Dead","GLOBAL",24)
      Global("KaylessaQuest","GLOBAL",1)
      Global("K_Done","GLOBAL",0)~ THEN REPLY @8396 DO ~AddXP2DA("ID1EX8H")
                                                        DisplayStringNoNameDlg(LastTalkedToBy,@8142)
                                                        SetGlobal("K_Done","GLOBAL",1)
                                                        EraseJournalEntry(@14416)
                                                        AddJournalEntry(@14417,QUEST_DONE)~ GOTO 18
  IF ~~ THEN REPLY @8397 EXIT
END

Here I would only want to ADD_TRANS_TRIGGER the variable condition to the transition that already has the three triggers, i.e. the third transition from the top.

Edited by subtledoctor
Link to comment
6 hours ago, subtledoctor said:

Or, I can’t figure out what that “DO 0” is doing. Does it limit the ADD_TRANS_TRIGGER to the first transition?

Yes, the 'DO' clause is how you target individual transitions. In this case it's 'DO 0' so it'll only add the specified trigger to the first transition (numbered starting with 0). If you omit the DO clause it will indeed add the trigger to all transitions.

6 hours ago, subtledoctor said:

Here I would only want to ADD_TRANS_TRIGGER the variable condition to the transition that already has the three triggers, i.e. the third transition from the top.

Yep:

ADD_TRANS_TRIGGER dialogue_name 17 ~newtrigger~ DO 2

 

Link to comment

You can't rely on transition numbers being like in the original game and at the same time add reply options via EXTEND_TOP.

Meaning, you can't expect all other nods not to shift reply options around but then do it yourself with your mod. Duh?

Please don't use EXTEND_TOP. There is so many mods that do not check when using ADD_TRANS_xx.

Link to comment

Well, it seems like a situation where you have to pick your poison? I mean, even using REPLACE_TEXTUALLY to capture one transition and turn it into two alternative ones will still change transition numbers, no? 

Frankly I don’t want to use EXTEND_TOP anyway because it involves adding the full content of the new transition, and the string numbers should match… but I’m not sure I can make them match. I was hoping I could copy the transition, to make sure the strings are identical, and then edit the two copies. But it doesn’t seem like COPY_TRANS is designed for that. 

If I can’t make the strings match, I have to add my own strings, which creates potential localization problems. Maybe that can’t be avoided; in which case I might as well just overwrite the dialogue with my own curated version. That’s what the mod does now and I was hoping to change. 

In particular: this mod is in an environment where tipun’s IWD has been added to an EET install. My mod enables the IWD campaign to be played right from the game menus; but also enables access to certain areas of IWD within a BG2 game. The appropriate size of XP awards differs depending on which campaign you are playing; so I need to make alternative copies of various dialogue transitions that include XP grants. 

There may be a better way to distinguish these XP awards. Like, maybe I should 1) delete the XP grant from the existing transition; 2) add a new state for the sole purpose of awarding XP, structured as needed; and 3) route the existing transition through the new state before returning to the original next state. That sounds like it would be more compatible. 

But for now, there are no mods out there that alter IWD content like Ambere Dunn’s dialogue, in a BG2 game. And my current localization matches tipun’s, so for now that part is okay. 

Edited by subtledoctor
Link to comment
7 minutes ago, subtledoctor said:

But it doesn’t seem like COPY_TRANS is designed for that. 

Exactly. COPY_TRANS copies states complete with their transition lists. There's no command in .D code to copy a reply with its transitions. That's what would make this easier; if the reply could be copied and then modified, that would be ideal.

So, anything we can do? Well, regular WeiDU can open up .DLG files. Still, editing directly is not easy; the one time I do that in my tweak mod, it's followed by a DECOMPILE_AND_PATCH so I do the actual work on .D versions. A REPLACE_TEXTUALLY, specifically, to swap one experience award for another. Without that ... states, responses, state triggers, response triggers, and actions are all fixed-size elements, but the last three do this by storing the scripting text later and putting pointers to it in the main element. If you insert anything, you end up having to reindex basically everything that comes later. Not practical.

There are still some tricks; you can open up the DLG, decompile it, and apply the usual text-parsing commands to find stuff. Anyone think they can write a clone_response function?

Link to comment

If I understand correctly facts are that (1) methods that are included in WeiDU relay on transition order and (2) we have already many mods that use them so it makes sense to me that good practice would be to add new transitions on the bottom (ofc any rule can have exceptions if case justifies it, I didn't want to imply with my question that @subtledoctor is doing something wrong).

I believe creating function that clones transition and add it at the end of state isn't that complicated (if it doesn't need to be super efficient). One regexp to find transition and one to find end of state and insert. Unless I'm missing something.

I guess there are also many mods that extend top so I personally have a feeling that textual matching instead of relaying on order is safer (and it is easier to detect if something is wrong and act accordingly).

Edited by marchitek
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...