jastey Posted June 26, 2020 Share Posted June 26, 2020 In SoD, the demon Thrix plays a game with the PC for one of the joined NPCs' soul. For the original game this is done by random transactions that call 4 different state triggers where the order of the possible (original) NPCs is switched, so the NPC that gets picked will not be the same for every load/playthrough. Example: Thrix stated his game. The player gets one out of four different reply options: Spoiler IF ~~ THEN BEGIN 19 // from: 15.6 15.7 15.8 15.9 15.10 SAY #38891 /* ~Thrix is glad to hear it, though you should have let Thrix finish telling you the terms before agreeing. For if you lose the bet, you will also lose one of your friends to Thrix's service.~ */ IF ~ RandomNum(4,1) ~ THEN REPLY #38892 /* ~What? No, no, I can't accept that. The bet is off.~ */ GOTO 21 IF ~ RandomNum(4,2) ~ THEN REPLY #38892 /* ~What? No, no, I can't accept that. The bet is off.~ */ GOTO 22 IF ~ RandomNum(4,3) ~ THEN REPLY #38892 /* ~What? No, no, I can't accept that. The bet is off.~ */ GOTO 23 IF ~ RandomNum(4,4) ~ THEN REPLY #38892 /* ~What? No, no, I can't accept that. The bet is off.~ */ GOTO 24 Looking at states 21-24 we see that it's supposed to be the same reaction from Thrix, the only difference is the order of the following call of joined NPCs: Spoiler IF ~~ THEN BEGIN 21 // from: 19.0 19.5 SAY #38895 /* ~Aha. Thrix does not know how this sort of thing works in the Prime Material Plane. But in Avernus, a contract is a contract. The wager is made. Win and one of these items will be yours. Lose and Thrix takes one of your friends.~ [BD38895] */ IF ~~ THEN GOTO 10 IF ~ Global("BD_Saved_Rasaad","bd4500",0) IsValidForPartyDialogue("RASAAD") ~ THEN GOTO 103 IF ~ Global("BD_Saved_Safana","bd4500",0) IsValidForPartyDialogue("SAFANA") ~ THEN GOTO 104 IF ~ Global("BD_Saved_Edwin","bd4500",0) IsValidForPartyDialogue("EDWIN") ~ THEN GOTO 105 IF ~ Global("BD_Saved_Baeloth","bd4500",0) IsValidForPartyDialogue("BAELOTH") ~ THEN GOTO 106 IF ~ Global("BD_Saved_Mkhiin","bd4500",0) IsValidForPartyDialogue("MKHIIN") ~ THEN GOTO 107 IF ~ Global("BD_Saved_Glint","bd4500",0) IsValidForPartyDialogue("GLINT") ~ THEN GOTO 108 IF ~ Global("BD_Saved_Dorn","bd4500",0) IsValidForPartyDialogue("DORN") ~ THEN GOTO 109 IF ~ Global("BD_Saved_Neera","bd4500",0) IsValidForPartyDialogue("NEERA") ~ THEN GOTO 110 IF ~ Global("BD_Saved_Viconia","bd4500",0) IsValidForPartyDialogue("VICONIA") ~ THEN GOTO 111 IF ~ Global("BD_Saved_Voghiln","bd4500",0) IsValidForPartyDialogue("VOGHILN") ~ THEN GOTO 112 IF ~ Global("BD_Saved_Dynaheir","bd4500",0) IsValidForPartyDialogue("DYNAHEIR") ~ THEN GOTO 95 IF ~ Global("BD_Saved_Minsc","bd4500",0) IsValidForPartyDialogue("MINSC") ~ THEN GOTO 101 IF ~ Global("BD_Saved_Khalid","bd4500",0) IsValidForPartyDialogue("KHALID") ~ THEN GOTO 97 IF ~ Global("BD_Saved_Jaheira","bd4500",0) IsValidForPartyDialogue("JAHEIRA") ~ THEN GOTO 99 IF ~ Global("BD_Saved_Corwin","bd4500",0) IsValidForPartyDialogue("CORWIN") ~ THEN GOTO 94 END IF ~~ THEN BEGIN 22 // from: 19.1 19.6 SAY #38895 /* ~Aha. Thrix does not know how this sort of thing works in the Prime Material Plane. But in Avernus, a contract is a contract. The wager is made. Win and one of these items will be yours. Lose and Thrix takes one of your friends.~ [BD38895] */ IF ~~ THEN GOTO 10 IF ~ Global("BD_Saved_Neera","bd4500",0) IsValidForPartyDialogue("NEERA") ~ THEN GOTO 110 IF ~ Global("BD_Saved_Viconia","bd4500",0) IsValidForPartyDialogue("VICONIA") ~ THEN GOTO 111 IF ~ Global("BD_Saved_Voghiln","bd4500",0) IsValidForPartyDialogue("VOGHILN") ~ THEN GOTO 112 IF ~ Global("BD_Saved_Dynaheir","bd4500",0) IsValidForPartyDialogue("DYNAHEIR") ~ THEN GOTO 95 IF ~ Global("BD_Saved_Minsc","bd4500",0) IsValidForPartyDialogue("MINSC") ~ THEN GOTO 101 IF ~ Global("BD_Saved_Khalid","bd4500",0) IsValidForPartyDialogue("KHALID") ~ THEN GOTO 97 IF ~ Global("BD_Saved_Jaheira","bd4500",0) IsValidForPartyDialogue("JAHEIRA") ~ THEN GOTO 99 IF ~ Global("BD_Saved_Corwin","bd4500",0) IsValidForPartyDialogue("CORWIN") ~ THEN GOTO 94 IF ~ Global("BD_Saved_Rasaad","bd4500",0) IsValidForPartyDialogue("RASAAD") ~ THEN GOTO 103 IF ~ Global("BD_Saved_Safana","bd4500",0) IsValidForPartyDialogue("SAFANA") ~ THEN GOTO 104 IF ~ Global("BD_Saved_Edwin","bd4500",0) IsValidForPartyDialogue("EDWIN") ~ THEN GOTO 105 IF ~ Global("BD_Saved_Baeloth","bd4500",0) IsValidForPartyDialogue("BAELOTH") ~ THEN GOTO 106 IF ~ Global("BD_Saved_Mkhiin","bd4500",0) IsValidForPartyDialogue("MKHIIN") ~ THEN GOTO 107 IF ~ Global("BD_Saved_Glint","bd4500",0) IsValidForPartyDialogue("GLINT") ~ THEN GOTO 108 IF ~ Global("BD_Saved_Dorn","bd4500",0) IsValidForPartyDialogue("DORN") ~ THEN GOTO 109 END IF ~~ THEN BEGIN 23 // from: 19.2 19.7 SAY #38895 /* ~Aha. Thrix does not know how this sort of thing works in the Prime Material Plane. But in Avernus, a contract is a contract. The wager is made. Win and one of these items will be yours. Lose and Thrix takes one of your friends.~ [BD38895] */ IF ~~ THEN GOTO 10 IF ~ Global("BD_Saved_Glint","bd4500",0) IsValidForPartyDialogue("GLINT") ~ THEN GOTO 108 IF ~ Global("BD_Saved_Dorn","bd4500",0) IsValidForPartyDialogue("DORN") ~ THEN GOTO 109 IF ~ Global("BD_Saved_Minsc","bd4500",0) IsValidForPartyDialogue("MINSC") ~ THEN GOTO 101 IF ~ Global("BD_Saved_Khalid","bd4500",0) IsValidForPartyDialogue("KHALID") ~ THEN GOTO 97 IF ~ Global("BD_Saved_Neera","bd4500",0) IsValidForPartyDialogue("NEERA") ~ THEN GOTO 110 IF ~ Global("BD_Saved_Viconia","bd4500",0) IsValidForPartyDialogue("VICONIA") ~ THEN GOTO 111 IF ~ Global("BD_Saved_Voghiln","bd4500",0) IsValidForPartyDialogue("VOGHILN") ~ THEN GOTO 112 IF ~ Global("BD_Saved_Dynaheir","bd4500",0) IsValidForPartyDialogue("DYNAHEIR") ~ THEN GOTO 95 IF ~ Global("BD_Saved_Jaheira","bd4500",0) IsValidForPartyDialogue("JAHEIRA") ~ THEN GOTO 99 IF ~ Global("BD_Saved_Corwin","bd4500",0) IsValidForPartyDialogue("CORWIN") ~ THEN GOTO 94 IF ~ Global("BD_Saved_Rasaad","bd4500",0) IsValidForPartyDialogue("RASAAD") ~ THEN GOTO 103 IF ~ Global("BD_Saved_Safana","bd4500",0) IsValidForPartyDialogue("SAFANA") ~ THEN GOTO 104 IF ~ Global("BD_Saved_Edwin","bd4500",0) IsValidForPartyDialogue("EDWIN") ~ THEN GOTO 105 IF ~ Global("BD_Saved_Baeloth","bd4500",0) IsValidForPartyDialogue("BAELOTH") ~ THEN GOTO 106 IF ~ Global("BD_Saved_Mkhiin","bd4500",0) IsValidForPartyDialogue("MKHIIN") ~ THEN GOTO 107 END IF ~~ THEN BEGIN 24 // from: 19.3 19.8 SAY #38895 /* ~Aha. Thrix does not know how this sort of thing works in the Prime Material Plane. But in Avernus, a contract is a contract. The wager is made. Win and one of these items will be yours. Lose and Thrix takes one of your friends.~ [BD38895] */ IF ~~ THEN GOTO 10 IF ~ Global("BD_Saved_Mkhiin","bd4500",0) IsValidForPartyDialogue("MKHIIN") ~ THEN GOTO 107 IF ~ Global("BD_Saved_Edwin","bd4500",0) IsValidForPartyDialogue("EDWIN") ~ THEN GOTO 105 IF ~ Global("BD_Saved_Baeloth","bd4500",0) IsValidForPartyDialogue("BAELOTH") ~ THEN GOTO 106 IF ~ Global("BD_Saved_Jaheira","bd4500",0) IsValidForPartyDialogue("JAHEIRA") ~ THEN GOTO 99 IF ~ Global("BD_Saved_Corwin","bd4500",0) IsValidForPartyDialogue("CORWIN") ~ THEN GOTO 94 IF ~ Global("BD_Saved_Rasaad","bd4500",0) IsValidForPartyDialogue("RASAAD") ~ THEN GOTO 103 IF ~ Global("BD_Saved_Viconia","bd4500",0) IsValidForPartyDialogue("VICONIA") ~ THEN GOTO 111 IF ~ Global("BD_Saved_Voghiln","bd4500",0) IsValidForPartyDialogue("VOGHILN") ~ THEN GOTO 112 IF ~ Global("BD_Saved_Minsc","bd4500",0) IsValidForPartyDialogue("MINSC") ~ THEN GOTO 101 IF ~ Global("BD_Saved_Khalid","bd4500",0) IsValidForPartyDialogue("KHALID") ~ THEN GOTO 97 IF ~ Global("BD_Saved_Glint","bd4500",0) IsValidForPartyDialogue("GLINT") ~ THEN GOTO 108 IF ~ Global("BD_Saved_Dorn","bd4500",0) IsValidForPartyDialogue("DORN") ~ THEN GOTO 109 IF ~ Global("BD_Saved_Neera","bd4500",0) IsValidForPartyDialogue("NEERA") ~ THEN GOTO 110 IF ~ Global("BD_Saved_Dynaheir","bd4500",0) IsValidForPartyDialogue("DYNAHEIR") ~ THEN GOTO 95 IF ~ Global("BD_Saved_Safana","bd4500",0) IsValidForPartyDialogue("SAFANA") ~ THEN GOTO 104 END My question is: how would I add a mod NPC to these trees so that it is a. also random enough and b. compatible with other mods? Possibility 1: The mod NPC gets assigned not at the bottom of the transaction list but also via EXTEND_TOP #X at other places, for example after the same original NPC for all four states. Disadvantage: the count number of the transaction shifts which is bad if a mod tries to add actions or transtrigger for certain original NPCs. Possibility 2: Add the mod NPC to the end of the list but add a RandomNum(X,Y) trigger which lets the mod NPC be skipped randomly. Disadvantage: it's possible that the mod NPC is not chosen even though they are the only joined NPC in the group. Possibility 3 which I am trying to avoid: Add the mod NPC to teh bottom always. Great disadvantage: the last installed mod NPC will be the one that it chosen always. Any suggestions? Quote Link to comment
Ardanis Posted June 26, 2020 Share Posted June 26, 2020 (edited) I would read the number of transitions in each state, divide it by 4, and insert mod transitions at (trans_num / 4) * (state_ind - 21) points. EDIT So basically, what you suggest in 1, it seems. As for compatibility... You might have a point, but imo it's the least evil nonetheless - because in order to break something it requires another mod to 1) try to edit vanilla transitions and 2) do it without reading data first. PPS ...and also 3) be willing to poke the awful mess that is Thrix dialog file with a ten foot pole. This dialog was the worst in the entire SoD by a huge margin, because writers wanted to have random element added. In retrospect, may we should've added small cutscene effect and move all the rng calculations in there Edited June 26, 2020 by Ardanis Quote Link to comment
DavidW Posted June 26, 2020 Share Posted June 26, 2020 You could simulate adding an entry in the middle by adding it at the end but with a bunch of ~OR(2)!Global("BD_Saved_[NPC]",bd4500",0)!IsValidForPartyDialogue([NPC])~ added. Messy, though. Quote Link to comment
Ardanis Posted June 26, 2020 Share Posted June 26, 2020 The original dialog is already twice, if not thrice, as messy, so... I'd be cautious about making it even worse. Looking at it again, I recall you can refuse Thrix his choice of a party member and have him choose again. So technically you can go with 3rd idea and append NPC at the bottom - even if two mods will conflict there, you can still write "nope, choose someone else" option to stay in line with the original, and get the previous NPC mod as a next choice. Quote Link to comment
jastey Posted June 27, 2020 Author Share Posted June 27, 2020 Thank you for your suggestions! 11 hours ago, Ardanis said: This dialog was the worst in the entire SoD by a huge margin You think? .. What @DavidW suggested sounds like something I'd do, to be honest. (Not that I'd be smart enough to think of it, though, so thanks!). But the problem is that I will include this into my SoD-NPC tutorial, so maybe making every NPC mod add 10+ more reply options to 72 dialogue states in bdthrix does sound like an unfortunate idea. 11 hours ago, Ardanis said: I would read the number of transitions in each state, divide it by 4, and insert mod transitions at (trans_num / 4) * (state_ind - 21) points. I understand the concept but I have no idea how to code that. Suggestions very welcome. 8 hours ago, Ardanis said: I recall you can refuse Thrix his choice of a party member and have him choose again. So technically you can go with 3rd idea and append NPC at the bottom - even if two mods will conflict there, you can still write "nope, choose someone else" option to stay in line with the original, and get the previous NPC mod as a next choice. Although it is tempting and would probably be the best compatibility wise, still it restricts the options for mod NPCs quite a bit. Besides, I already wrote "You gambled with my soul?!11!!!!" reactions for 5 NPCs so I want to make this work. 11 hours ago, Ardanis said: in order to break something it requires another mod to 1) try to edit vanilla transitions and 2) do it without reading data first. This was not the topic of this post but I'll grab this while it's hot: I do ADD_TRANS_TRIGGER a lot for Imoen4Ever but I have no idea how to read in the correct reply option first so I do it blindly. How would I make sure I add to the correct reply option even if its number count was shifted by another mod? Quote Link to comment
Ardanis Posted June 27, 2020 Share Posted June 27, 2020 (edited) 13 hours ago, jastey said: You think? .. Almost the entire dialog consists of "choose party member" states, four initial and then four per each party member if PC refuses to bet them. 13 hours ago, jastey said: I understand the concept but I have no idea how to code that. Suggestions very welcome. I'm a little rusty to give you an actually working piece, but the logic would be like: COPY_EXISTING - bdthrix.dlg override READ_LONG 0xc states x = 0 FOR (i=21; i<24; ++i) BEGIN READ_LONG states + i * 16 + 8 trans_num SET insert%i% = ( (trans_num - 1) / 4) * x x = (x<3) ? x+1 : 0 END FOR (i=30; i<85; ++i) BEGIN READ_LONG states + i * 16 + 8 trans_num SET insert%i% = ( (trans_num - 1) / 4) * x x = (x<3) ? x+1 : 0 END Then in your .d use for each state EXTEND_BOTTOM bdthrix 21 #%insert21% /* trans list */ END You'll probably need to EVAL the .d 13 hours ago, jastey said: How would I make sure I add to the correct reply option even if its number count was shifted by another mod? I think this may do https://weidu.org/~thebigg/README-WeiDU.html#dActionWhen Otherwise, you'd have to read the .dlg structure, similar to above. Edited June 27, 2020 by Ardanis Quote Link to comment
jastey Posted June 27, 2020 Author Share Posted June 27, 2020 Thank you for the suggestions! 13 minutes ago, Ardanis said: Almost the entire dialog consists of "choose party member" states, four initial and then four per each party member if PC refuses to bet them. I know, my question was sarcasm. ^^ Quote Link to comment
DavidW Posted June 27, 2020 Share Posted June 27, 2020 Reflecting on this, and on the need for something to be iterated across multiple mods, I might be inclined to do something simpler. There are four lots of NPC orderings, yes, with 15 NPCs in each? Insert the new NPC transition at the top of the first one, the bottom of the second, at position 5 of the third, and position 10 of the fourth. That's enough randomness to achieve what you want, I think. The idea isn't to make sure that each NPC is equally likely to be selected, irrespective of party mix (the original script doesn't do that for the original NPCs) - it's just to mix it up a bit so that mod-added NPCs aren't guaranteed to be first or last, and so that the order isn't predictable. I think that suggestion will do it fine, and is (relatively) easy to implement. Quote Link to comment
jastey Posted July 14, 2020 Author Share Posted July 14, 2020 On 6/27/2020 at 10:31 PM, DavidW said: Reflecting on this, and on the need for something to be iterated across multiple mods, I might be inclined to do something simpler. There are four lots of NPC orderings, yes, with 15 NPCs in each? Insert the new NPC transition at the top of the first one, the bottom of the second, at position 5 of the third, and position 10 of the fourth. That's enough randomness to achieve what you want, I think. The idea isn't to make sure that each NPC is equally likely to be selected, irrespective of party mix (the original script doesn't do that for the original NPCs) - it's just to mix it up a bit so that mod-added NPCs aren't guaranteed to be first or last, and so that the order isn't predictable. I think that suggestion will do it fine, and is (relatively) easy to implement. Late reply: I like this idea very much. Thank you! Quote Link to comment
Recommended Posts
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.