What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
My game has a concept of days represented in a variable called Day. I'd like to make a conditional that says, "if this other node was displayed yesterday or before." How would I do that? I know I could make a variable and record the day the other node was recorded, but is there a worthwhile way of making this work automatically?
It would be convenient if I could have a field on every dialogue entry called, "lastDayDisplayed". If that existed, I could just check if "otherNode.lastDayDisplayed < Day". I think the way I would set this field is by implementing a OnConversationLine that assigns it? Then in my condition, I think I could do something similar to a simstatus like this: "Dialog[42].lastDayDisplayed", but I'm not sure if you can do that on fields.
Should I avoid doing this because it will use up a lot of disk space, or is that not worth thinking about?
It would be convenient if I could have a field on every dialogue entry called, "lastDayDisplayed". If that existed, I could just check if "otherNode.lastDayDisplayed < Day". I think the way I would set this field is by implementing a OnConversationLine that assigns it? Then in my condition, I think I could do something similar to a simstatus like this: "Dialog[42].lastDayDisplayed", but I'm not sure if you can do that on fields.
Should I avoid doing this because it will use up a lot of disk space, or is that not worth thinking about?
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
(Edit: I didn't like using entry IDs for this. I rewrote it to use the entry's Title.)
The save system doesn't normally save dialogue entry fields. I'd add them as variables instead so the info will be included in saved games. And perhaps only for dialogue entries that are specially marked to keep track of the day. For example:
1. Define a custom dialogue entry field named "rememberDay" (Boolean). Set it true for any dialogue entry that should remember the last day it was visited.
2. Add an OnConversationLine method like this:
3. Register a Lua function DayHasPassed(#):
In your conditions, check DayHasPassed("Some Title") where "Some Title" is the Title of the entry that you want to check. You could use entry IDs, but I think Titles are more readable.
The save system doesn't normally save dialogue entry fields. I'd add them as variables instead so the info will be included in saved games. And perhaps only for dialogue entries that are specially marked to keep track of the day. For example:
1. Define a custom dialogue entry field named "rememberDay" (Boolean). Set it true for any dialogue entry that should remember the last day it was visited.
2. Add an OnConversationLine method like this:
Code: Select all
void OnConversationLine(Subtitle subtitle)
{
var entry = subtitle.dialogueEntry;
if (Field.LookupBool(entry.fields, "rememberDay"))
{ // Record that this entry was visited today:
var today = DialogueLua.GetVariable("Day").asInt;
DialogueLua.SetVariable("day" + entry.Title, today);
}
}
Code: Select all
Lua.RegisterFunction("DayHasPassed", this, SymbolExtensions.GetMethodInfo(() => DayHasPassed(string.Empty)));
...
bool DayHasPassed(string title)
{
var entry = FindEntryByTitle(title);
if (entry == null) return false;
var today = DialogueLua.GetVariable("Day").asInt;
var entryDay = DialogueLua.GetVariable("day" + entry.Title).asInt;
return entryDay < today;
}
DialogueEntry FindEntryByTitle(string title)
{
foreach (var conversation in DialogueManager.masterDatabase.conversations)
{
foreach (var entry in conversation.dialogueEntries)
{
if (entry.Title == title) return entry;
}
}
return null;
}
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
Hi Tony,
speaking of best practices, would you say a variant of this approach would also be the best choice for the following:
1) Characters dropping into the conversation if they're nearby.
Similarly to how Infinity Engine games did it – during a dialogue, if a character was standing close to the conversants, they'd comment. Currently, I check the presence of all possible participants when the conversation starts and use variables like Alice.present and Bob.present.
I just wondered if there's a better/simpler/more unified way and making a function like IfPresent(character, distance=7m) would seem to do the trick.
2) Exhausting all (some) dialogue options before the final one.
Currently, I think I'm creating too many one-time boolean variables and it's hard to stay organised as the global variable table keeps expanding fast. I'm essentially manually entering and setting option1Exhausted, option2Exhausted etc. and check option1Exhausted && option2Exhausted && … on the final one.
I know this has most likely been asked a million times already, but since there are many ways to do it, I'm curious what would you consider the most scalable approach, because mine currently feels a bit overcomplicated.
speaking of best practices, would you say a variant of this approach would also be the best choice for the following:
1) Characters dropping into the conversation if they're nearby.
Similarly to how Infinity Engine games did it – during a dialogue, if a character was standing close to the conversants, they'd comment. Currently, I check the presence of all possible participants when the conversation starts and use variables like Alice.present and Bob.present.
I just wondered if there's a better/simpler/more unified way and making a function like IfPresent(character, distance=7m) would seem to do the trick.
2) Exhausting all (some) dialogue options before the final one.
Currently, I think I'm creating too many one-time boolean variables and it's hard to stay organised as the global variable table keeps expanding fast. I'm essentially manually entering and setting option1Exhausted, option2Exhausted etc. and check option1Exhausted && option2Exhausted && … on the final one.
I know this has most likely been asked a million times already, but since there are many ways to do it, I'm curious what would you consider the most scalable approach, because mine currently feels a bit overcomplicated.

Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
Hi,
Also, for managing global variables, many devs will add grouping names to the beginning of their variable names, such as:
Adding an IsPresent() custom Lua function is a good way to go. Then you can set up side-comment nodes like this:Rallix wrote: ↑Mon Jul 08, 2019 1:49 pm1) Characters dropping into the conversation if they're nearby.
Similarly to how Infinity Engine games did it – during a dialogue, if a character was standing close to the conversants, they'd comment. Currently, I check the presence of all possible participants when the conversation starts and use variables like Alice.present and Bob.present.
I just wondered if there's a better/simpler/more unified way and making a function like IfPresent(character, distance=7m) would seem to do the trick.
- Link Priority: AboveNormal
- Conditions: IsPresent("Alistair", 7)
- Dialogue Text: "I'm saying some quippy side comment."
I'm not sure exactly what you're using it for, but what about using SimStatus?Rallix wrote: ↑Mon Jul 08, 2019 1:49 pm2) Exhausting all (some) dialogue options before the final one.
Currently, I think I'm creating too many one-time boolean variables and it's hard to stay organised as the global variable table keeps expanding fast. I'm essentially manually entering and setting option1Exhausted, option2Exhausted etc. and check option1Exhausted && option2Exhausted && … on the final one.
Also, for managing global variables, many devs will add grouping names to the beginning of their variable names, such as:
- Battle.FirstBlood
- Battle.NumTrollsKilled
- Wardens.Joined
- Wardens.Offended
- Wardens.MetFounder
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
Thank you very much! 
I'm using it for something like here; i.e. "ask three background questions before the final, most important question appears". Just to make sure the player character has all information before moving on. Or to block something with a sequence I would not like to trigger again.
I'm using articy:draft to write the dialogue, so I'll probably add essentially the same thing as SimStatus as a property to certain important dialogue nodes and use getProp / setProp, seeing that it's supported by the Dialogue System.
Default to Untouched, WasOffered when passing through an "important Hub" and WasDisplayed as soon as an option is picked.
Again, thank you for the advice!

Thanks for this tip.
That's exactly what I need.
I'm using it for something like here; i.e. "ask three background questions before the final, most important question appears". Just to make sure the player character has all information before moving on. Or to block something with a sequence I would not like to trigger again.
I'm using articy:draft to write the dialogue, so I'll probably add essentially the same thing as SimStatus as a property to certain important dialogue nodes and use getProp / setProp, seeing that it's supported by the Dialogue System.
Default to Untouched, WasOffered when passing through an "important Hub" and WasDisplayed as soon as an option is picked.
Yup, I'm doing this ("CharacterLocation.DialogueXXX"), although Articy only supports one level of grouping, so I'm relying on alphabetical sorting for the rest; although that's not related to the Dialogue System.Tony Li wrote: ↑Mon Jul 08, 2019 2:22 pmAlso, for managing global variables, many devs will add grouping names to the beginning of their variable names, such as:
It makes it easier to sort and filter for a specific category of variables such as "Wardens".
- Battle.FirstBlood
- Battle.NumTrollsKilled
- Wardens.Joined
- Wardens.Offended
- Wardens.MetFounder
Again, thank you for the advice!
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
Normally, I don't care about performance (unless I know that a human can notice it), but I'm wondering if I should be worried about this code. It's looking at every single conversation then every single node. Is this probably fine, even in large databases?Tony Li wrote: ↑Mon Jul 08, 2019 12:39 amCode: Select all
DialogueEntry FindEntryByTitle(string title) { foreach (var conversation in DialogueManager.masterDatabase.conversations) { foreach (var entry in conversation.dialogueEntries) { if (entry.Title == title) return entry; } } return null; }
Since I don't think these things change at runtime, I could easily run it once, cache a Dictionary<string, DialogueEntry> (where the key is the entry title), and get O(1) lookups. I just don't know if it's worth optimizing. I also don't know if naively caching like that will work correctly.
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
I tried out this code, and the problem is that when you haven't visited the node, its day value defaults to 0. Is there a way to make it default to a really big number? In this case, this happens to be a response choice that hasn't been picked yet. I'm not sure if that's relevant.
Re: What's the best way to make a conditional that says, "if a day has passed since you visited this other node"?
Try this:
Code: Select all
var entryDay = DialogueLua.GetVariable("day" + entry.Title).asInt;
if (entryDay == 0) entryDay = System.Int32.MaxValue; //<--ADD THIS.