DalreiDal Posted September 2 Share Posted September 2 All right, so I'm not a modder but I'm definitely a nosy end-user, and I was looking at the .tra and .d files for Romantic Encounters and thought, there has to be a better way to read those than painstakingly going from number to number in a side-by-side notepad. I thought, how hard can it be? So I started writing a tiny little text-base dialog "stepper". Answer is, it would be easier if I understood the scripting in .d better. Now most of the stuff is self-explanatory or I can ignore it for my uses at the start, but I'm a bit confused about CHAIN, or perhaps about the firing of dialog in general. I looked around the tutorials forums a bit, but only found a reference to CHAIN in a pdf and did not understand the explanation given there. So. When there is CHAIN above a dialog "step", you know the block between IF ~~THEN file talk.number ... END, does that mean that talk will always fire immediately after the one above it? Or does the ~~, which usually contains conditions, if I understood right, mean that it will always fire? But then why isn't that the first thing out of the NPC's mouth? Are the blocks processed in order from top to bottom? I suppose I'm looking for a bit of context. I think the .d gets compiled by WeiDU? When does it get called, by what? Does it execute sequentially top to bottom, following the "gotos", until it reaches an END? But there's CHAINs after ENDs so I'm not sure how that works? I'm happy to read an introduction on .d language if you point me to one (or to use some other tool I don't know about to nose about dialog trees if one exists). Thanks a lot! Quote Link to comment
moggadeet Posted September 2 Share Posted September 2 This doesn't answer your primary question, but if you're just looking to read mod dialogue, you might find it easier to set up a dummy install so that you can read with nearinfinity - no back and forth required. Quote Link to comment
DalreiDal Posted September 2 Author Share Posted September 2 I admit I'm not sure how to set up a dummy install, or how to use nearinfinity to read mod dialog from a dummy install. Quote Link to comment
moggadeet Posted Monday at 10:44 PM Share Posted Monday at 10:44 PM If you're using the EE, you can copy your game folder to another location, install mods to it, and then point NearInfinity to that new folder (maybe label it differently so that you know which is which). Quote Link to comment
Shadowfire_Angel Posted Tuesday at 05:23 AM Share Posted Tuesday at 05:23 AM I'm still learning the nuisances of modding myself, but from my understanding so far; CHAIN is used to start the chain of a dialogue then to chain multiple NPC dialogue responses together. Example below; Spoiler CHAIN IF~GLOBAL("RandomGlobal","GLOBAL/LOCALS",1)~ THEN DIALOGUESTRING1 (NPC response here) END IF~~THEN REPLY @# EXTERN DIALOGUESTRING2 CHAIN DIALOGUESTRING2 etc. etc. The first line of CHAIN IF~GLOBAL("RandomGlobal","GLOBAL/LOCALS",1)~ THEN DIALOGUESTRING1 starts the dialogue chain providing the GLOBAL condition is true. The NPC will then start their first line of dialogue which starts at DIALOGUESTRING1 in this case. You then have any possible replies from the PC (this can be different again if the NPC is talking for several lines). EXTERN DIALOGUESTRING2 is where the dialogue will go next based on the PC response chosen. CHAIN DIALOGUESTRING2 is essentially the next 'link' in the dialogue chain which will only display if that particular dialogue is selected. So if there was an IF~~THEN REPLY @# EXTERN DIALOGUESTRING3 as well, selecting that would chain to DIALOGUESTRING3 next instead. That will then usually continue until the end of said chain where there are no dialogue options, and/or the dialogue hits an EXIT trigger. It can get a lot more complicated than that because a lot of dialogues rely on a GlobalTimer before it triggers or if using other variables instead of a GLOBAL variable. I think I explained that right. If I didn't, I'm sure someone will correct me but I've been playing with dialogues a lot recently, so it is relatively fresh for me. I also hope that made relative sense as well. Quote Link to comment
DalreiDal Posted Wednesday at 09:52 PM Author Share Posted Wednesday at 09:52 PM But, but, if CHAIN just starts the dialog, why is there not a CHAIN everywhere? Why is there a need for CHAIN sometimes, and sometimes not? For example, here, 1.8 doesn't need a chain, but 1.9 does? What's the difference? IF ~~ THEN BEGIN Laran1.8 SAY @17 ++ @18 + Laran1.23 ++ @19 + Laran1.24 END END CHAIN IF ~~ THEN ~B!LARAN~ Laran1.9 @20 == ~BANOMEN~ IF ~InParty("Anomen") InMyArea("Anomen") !StateCheck("Anomen",CD_STATE_NOTVALID)~ THEN @21 (and also I have no idea what the second END there does. all the IFs are ENDed) Quote Link to comment
Shadowfire_Angel Posted Wednesday at 11:27 PM Share Posted Wednesday at 11:27 PM That part I do not know sorry. I've only seen and used instances of CHAIN at the start and throughout the dialogue. My assumption would be that it might have something to do with whether or not there is a Global trigger or some other trigger. I've seen CHAIN IF to start dialogue chains the most as they generally rely on some kind of Global being of some value. I don't know why there would be two ENDs either. Quote Link to comment
DalreiDal Posted Thursday at 02:05 PM Author Share Posted Thursday at 02:05 PM These files are compiled by WeiDu, if I understand right? Is the parser code used by WeiDU open source? Quote Link to comment
jastey Posted Thursday at 02:37 PM Share Posted Thursday at 02:37 PM CHAIn doesn't start a dialogue. A state with a trigger variable does. CHAIN is just a way to code dialogue. It is very helpful if you have more than one NPC / character who should say something, or different lines for different conditions (romance / not in romance for example). Thus: if there is a trigger variable before the statename, it can start a dialogue. if not, it's somewhere in the middle of a dialogue. The end of a dialogue is marked by EXIT, btw. All the ENDs in a d-file are just syntax. Quote Link to comment
jastey Posted Thursday at 02:45 PM Share Posted Thursday at 02:45 PM 16 hours ago, DalreiDal said: Why is there a need for CHAIN sometimes, and sometimes not? For example, here, 1.8 doesn't need a chain, but 1.9 does? What's the difference? IF ~~ THEN BEGIN Laran1.8 SAY @17 ++ @18 + Laran1.23 ++ @19 + Laran1.24 END END CHAIN IF ~~ THEN ~B!LARAN~ Laran1.9 @20 == ~BANOMEN~ IF ~InParty("Anomen") InMyArea("Anomen") !StateCheck("Anomen",CD_STATE_NOTVALID)~ THEN @21 (and also I have no idea what the second END there does. all the IFs are ENDed) To explain in short your code snippet: The first END is from the state "Laran1.8". The second END is to end a section where probably ~B!Laran.dlg~ was appended, there is probably an APPEND ~B!Laran~ above somewhere where all following states should go into (the installer needs to know this). With the END, the installer knows that now appending to this dlg is done. After that there is a CHAIN, because now Anomen will make an interjection into the dialogue if he is present and it's much simpler to code this way than with single states. You'll see that with the CHAIN, there is again the definition where the first line should go into - ~B!Laran.dlg~ again. The line afterwards (@21) is from Anomen. That is what I meant, with CHAIN this is very simple to code. Without CHAIN, the state "Laran1.9" would have to be closed, there would have to be an EXTERN to Anomen's dlg wrappend in an APPEND - END, and back to ~B!Laran.dlg~ etc... CHAIN is just a simple way of letting lots of differently flagged dlgs talk, either from different cres or for different conditions. Hope it makes sense. In case you speak German or do not shy from using e.g. DeepL for translation, I wrote a little CHAIn tutorial here. Not sure whether this clears things up a litlle. Quote Link to comment
DalreiDal Posted Thursday at 05:25 PM Author Share Posted Thursday at 05:25 PM I'm sorry, I tried reading the translation of your german text, but I think it translated the code as well, and I, ah, didn't really understand it. But thanks for your insight here. Let me rephrase to make sure I understand. So when you make a .d file, you start with BEGIN ~uniquename~ and uniquename must be the same as the filename? Then there is a APPEND ~uniquename~...END block. In this block, several IF ~...~ THEN BEGIN ... END blocks are located. These play in "goto" order, following the player responses. Once the end of that APPENDed block is reached, i.e. gotos have been followed to the end, the script keeps reading the CHAINs, executing the IF ~~ BEGIN END blocks where the conditions are fulfilled. It does this to all CHAIN blocks in order they appear. CHAIN is used for other NPCs interjections. More APPEND blocks may be present below the first APPEND and the first CHAIN. This block is not triggered except if a "goto" in the first APPENDed/CHAINed blocks calls to them? Or perhaps they are executed sequentially after the first APPEND and CHAIN if EXIT has not been reached? Quote Link to comment
jastey Posted Thursday at 05:48 PM Share Posted Thursday at 05:48 PM 14 minutes ago, DalreiDal said: you start with BEGIN ~uniquename~ BEGIN dlgname is needed if you define a new dlg, for your own NPC / quest giver for example. The name of the d-file is of no importance. 16 minutes ago, DalreiDal said: Once the end of that APPENDed block is reached, i.e. gotos have been followed to the end, the script keeps reading the CHAINs Well.. you can also mix APPEND and CHAIN. I like to do that, because to me, being able to read the d-file is more important than some code order. The GOTO (or "+" in short syntax) always specifies the name of the following dialogue state (name/number it has inside the d file. Upon installing, all names are transferred into state numbers in the dlg that is created). 17 minutes ago, DalreiDal said: CHAIN is used for other NPCs interjections. CHAIn *can* be used for other NPC interjections. It can also be used to add an NPC line the PC only sees if certain conditions are met at the time the dialogue happens (e.g. in romance etc.). 19 minutes ago, DalreiDal said: More APPEND blocks may be present below the first APPEND and the first CHAIN. This block is not triggered except if a "goto" in the first APPENDed/CHAINed blocks calls to them? A dialogue is only started by a block that has a trigger variable. All others need a GOTO transition to happen inside a dialogue. it's of no importance whether this is above or below a CHAIN. I can only repeat: CHAIN is just a different way of coding the dialogue states. It has nothing to do with starting or ending a dialogue. To read a d-file, start with a state / CHAIN that has trigger variables in their head. These give a clue as to when this dialogue will happen. (For scripted dialogues, it's probably just one variable.) Then follow the dialogue from GOTO name to GOTO name until it ends with EXIT. Hope it helps. Quote Link to comment
DalreiDal Posted Thursday at 11:30 PM Author Share Posted Thursday at 11:30 PM I think we might be bamboozled by vocabulary. What is a "dialog state"? Is that IF ~...~ THEN BEGIN ... END block? That is one dialog state? But... if you just follow from GOTO to GOTO, why do you need CHAIN at all? What does CHAIN do? For example here, there is a line earlier that sends you to Laran1.17. What is the point of the CHAIN there, if you were going to get to Laran1.17 anyway? CHAIN IF ~~ THEN ~B!LARAN~ Laran1.17 What does an APPEND do? Why would you need/want to have several APPENDs in one .d file? Quote Link to comment
jastey Posted Friday at 07:01 AM Share Posted Friday at 07:01 AM 7 hours ago, DalreiDal said: What does an APPEND do? APPEND ~dlgname~ ... END tells the installer: the following content should go into the dlg "dlgname". 7 hours ago, DalreiDal said: Why would you need/want to have several APPENDs in one .d file? Various reasons: because you want to add dialogue to different dlgs. Bcause you had a CHAIN in between and need to tell the installer which dlg the following content should be put into again. 7 hours ago, DalreiDal said: What is a "dialog state"? Is that IF ~...~ THEN BEGIN ... END block? That is one dialog state? That is a dialogue state if it is coded not in CHAIN, yes. If the d-file uses CHAIN syntax, the installer will break it into such states inside the compiled DLG. You could compare a d-file content with a compiled dlg in the game to see the difference. CHAIN makes it easier to code, and easier to read, that's all. 7 hours ago, DalreiDal said: But... if you just follow from GOTO to GOTO, why do you need CHAIN at all? This is a misunderstanding. In your example, the Laran1.17 is the name of the CHAIN. In what you quoted, there is no GOTO, it's the definition header of the CHAIN. With "GOTO" I meant the transitions at the bottom of a CHAIN or state. Meaning, if you have somewhere else something like "GOTO Laran1.17" or, in short syntax: "+ Laran1.17", then you would continue reading the dialogue with this CHAIN. An - hopefully easy - example, with explanations. BEGIN dlgname1 //this defines our mod's new dlg for our quest giver IF ~NumTimesTalkedTo(0)~ THEN greeting //header: trigger variable (never talked to before) and name ("greeting") SAY ~You need to wait, I'm busy!~ IF ~~ THEN EXIT // dialogue ends if imoen is not in party IF ~IsValidForPartyDialogue("imoen")~ THEN + imoen_protest //dialogue continues below if Imoen is in party - this is executed first - bottom to top! END //this concludes the state "greeting" CHAIN //now we use CHAIN because two characters will talk IF ~~ THEN ~imoens_dlg~ imoen_protest //this is the header of the CHAIN. The next line is for Imoen, so the dlg needs to be specified. No trigger variable, because this is an ongoing dialogue from above. ~Ey, don't be so rude!~ // Imoen's line == dlgname1 //dialogue goes back to quest giver ~I had no intention to be rude! I'm just busy!~ END //this is for the installer. Now follow transitions or reply options: ++ ~It's alright, we will wait.~ + follow_up_1 //PC reply option. Continue reading with state "follow_up_1" below. ++ ~My friend is right, you know. We are busy, too!~ + follow_up_2 //PC reply option. Continue reading with state "follow_up_2" below. APPEND dlgname1 //the following content is for our quest giver again IF ~~ THEN follow_up_1 //state 1 SAY ~Thanks. It's crazy busy lately!~ IF ~~ THEN + follow_up_2 //dialogue continues below END IF ~~ THEN follow_up_2 // state 2 SAY ~I can't clone myself. Go and come back later then!~ IF ~~ THEN EXIT //dialogue ends END END //APPEND's end Quote Link to comment
jastey Posted Friday at 07:11 AM Share Posted Friday at 07:11 AM Maybe it gets clearer if I explain it differently. Let's focus on what is actually important for you who wants to read the dialogue. You do not necessarily understand the whole syntax, if you know what specifies what is going on. I'll break it down. the only things that are important for reading this I put in bold: Quote BEGIN dlgname1 // who is talking the following dialogue IF ~NumTimesTalkedTo(0)~ //when does this happen? THEN greeting //name of the state, in case it gets called somewhere else SAY ~You need to wait, I'm busy!~ //actual text line IF ~~ THEN EXIT // dialogue ends if imoen is not in party IF ~IsValidForPartyDialogue("imoen")~ THEN + imoen_protest //continue with "imoen_protest" if Imeon is in party CHAIN //now we use CHAIN because two characters will talk IF ~~ THEN ~imoens_dlg~ imoen_protest //here the dialogue continues ~Ey, don't be so rude!~ // Imoen's line == dlgname1 //dialogue goes back to quest giver ~I had no intention to be rude! I'm just busy!~ //quest giver's line END //this is for the installer. Now follow transitions or reply options: ++ ~It's alright, we will wait.~ + follow_up_1 //PC reply option. Continue reading with state "follow_up_1" below. ++ ~My friend is right, you know. We are busy, too!~ + follow_up_2 //PC reply option. Continue reading with state "follow_up_2" below. APPEND dlgname1 //the following content is for our quest giver again IF ~~ THEN follow_up_1 //state 1 SAY ~Thanks. It's crazy busy lately!~ IF ~~ THEN + follow_up_2 //dialogue continues below END IF ~~ THEN follow_up_2 // state 2 SAY ~I can't clone myself. Go and come back later then!~ IF ~~ THEN EXIT //dialogue ends END END //APPEND's end Ignore the rest, ENDs, etc. 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.