[TOOL] BP function to choose random dialog/descriptions/etc

This is a function that easily allows you to create randomized dialog, descriptions, etc. by using this function as a string filter.

For example, you might have an NPC say:

Hello.

But saying the same thing every time is dull. So you can use this string and run it through RandomPhrase():

[Hello.|Hi.]

This will sometimes output “Hello.” and sometimes output “Hi.”

If you really want to save space, this works identically to the previous string:

H[ello|i].

You can have any number of phrases separated by “|” and any number of “…]” pairs, which can be nested:

[Hello.|Hi.|Greetings[!|.]|How are you?]

This will output either “Hello.” (25% chance) or “Hi.” (25% chance) or “Greetings!” (12.5% chance) or “Greetings.” (12.5% chance) or “How are you?” (25% chance)

If you want “Hi.” to be the most frequent and “Greetings” and “How are you?” to be rare, you could do:

[Hello.|Hello.|Hello.|Hello.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Hi.|Greetings[!|!|.]|How are you?]

But it’s much easier to add a weight to segments so they are favored (default weight is 1):

[4Hello.|11Hi.|Greetings[2!|.]|How are you?]

The weight number stops as soon as a non-digit, non-plus, non-minus character is hit, but you can always add a space which is clipped off:

[4 Hello.|11 Hi.|1 Greetings[2 !|1 .]|1 How are you?]

If you want a segment to start with a number or “+” or “-”, you must put a weight number with a space first:

[Go!|1 3 2 1 go!]

The above will output “Go!” or “3 2 1 go!”

If there is only one choice, that works too:

This [text ]has only one choice

This will output “This text has only one choice”

If ALL of the segments of a particular “…]” have a weight of 0, no segments are used:

This [0text |0sentence ]part ]goes|] away

This will output “This part goes away”

Null segments are fine:

This sentence |||usually ||||]has five words.

This will usually output “This sentence has five words.” but sometimes “This sentence usually has five words.”

Finally, you can also pass an OptionalFlags argument string and use “+” and “-” to test for the presence of any flags you want to create. After each “” and the optional weight number, a “+” or “-” will scan the next few characters until a space (" ") is encountered. This will be the Flag to check.

A “+” will succeed if the Flag is a case-sensitive substring of OptionalFlags; a “-” will succeed if the Flag is NOT a case-sensitive substring of OptionalFlags.

If a flag does NOT succeed, the weight of that segment is 0. This allows you to easily change the output text depending on what OptionalFlags are passed.

Here’s a simple example; suppose you have various objects in a game, and each object has an OptionalFlags string unique to that object. Also suppose that you have a Lamp object, and the OptionalFlags is set to either “on” if the lamp is on or “” (a null string) if the lamp is off.

This string will output different text depending on whether OptionalFlags is “on” or “”:

The lamp is +on on|-on off]

If OptionalFlags is “on”, the above evaluates to:
The lamp is [1on|0off]
and will output “The lamp is on”
If OptionalFlags is “”, the above evaluates to:
The lamp is [0on|1off]
and will output “The lamp is off”

Now suppose you have a brief description for picking up and dropping objects, but you also have a way to examine objects. If you append “E” to OptionalFlags when examining an object like this lamp, you could use this:

-E A [lamp|lantern]][1+E A[ rusty |n old | ][kerosene |3][lamp|lantern]+on , burning brightly.|-on . It’s off.]]

If OptionalFlags does NOT have “E” in it anywhere, the above will only output “A lamp” or “A lantern”.
Otherwise, it will output the longer description, such as “An old lantern, burning brightly.” (assuming OptionalFlags is something like “on E”), or “A kerosene lamp. It’s off.” if OptionalFlags is “E” or “FREE” or anything with “E” and no “on”.

OptionalFlags does NOT assume any sort of delimiters, so beware of unintentionally matching strings. Also, don’t use any of the first four delimiters in flags (default delimiters are “|]”)

For example, let’s say NPCs have an OptionalFlags string that indicates how your character addresses them:
“?” means you don’t know their name
“mr” means you call them “Mr.” or “Mister”
“mrs” means you call them “Mrs.”
Also assuming you’re using FText for localization, and plug in the NPC’s last name as “{0}” with a Format call.

Your English-language FText could start out like this:
Hello+? .]-? +mr [Mr.|Mister] {0}]+mrs Mrs. {0}], how are you?]

After going through the Format call, it’s now this:

Hello+? .]-? +mr [Mr.|Mister] Jones]+mrs Mrs. Jones], how are you?]

And if you use the above OptionalFlags, the output will be e.g.
“Hello.” if OptionalFlags is “?”
“Hello Mr. Jones, how are you?” if OptionalFlags is “mr”
“Hello Mr. JonesMrs. Jones, how are you?” if OptionalFlags is “mrs” – whoops!
Since “mrs” contains both “mr” and “mrs”, both Mr. and Mrs. Jones matched.

This particular bug can be fixed by changing the flags to these:
“?” means you don’t know their name
“Mr.” means you call them “Mr.” or “Mister”
“Mrs.” means you call them “Mrs.”

Finally, a null flag is handled differently and simply tests whether the whole OptionalFlags string is null or not – “+ OptionalFlags is not null]- OptionalFlags is null]” will output “OptionalFlags is not null” if OptionalFlags is not null, and “OptionalFlags is null” if it’s null.

The default delimiters are “|]” with “” as the escape character and “.” is used internally. You can replace them with any set you like, and even use different sets when the function is called. You must pass either 3 characters, or 5 or more characters, and the first five characters must all be different. If you only pass 3 characters, no character escaping is done. If you pass 0, 1, 2, or 4 characters the input will simply be copied to the output.

The characters “|]” need to be escaped if you want them to be ignored instead of being used as special delimiters. “” will output as “”, “|” as “|”, “]” as “]”, and “\” as “”. The internal “.” is NOT escaped. For example, the string “This is [a\]] test” will output “This is [a] test”. No other character escaping is done, and non-syntactic arrangements are generally left alone. The string “This ] is \a bad|ly [made string.” will output as “This ] is \a bad|ly [made string.”.

If you want to use a specific random stream, you can pass it as an argument (and pass True for “Use Random Stream” since there seems to be no way to detect if an actual random stream was passed or not). One random number will be used for every “[…]” pair, even if it only has one argument or becomes null because all weights are zero, or if it’s nested within a segment that ends up not being used. This means it will use up the same amount of random numbers each time.

The attachment has a readme.txt which is just the above text, and RandomPhraseFn.uasset, which you can just drop somewhere into your Content folder. Its the child of a GameInstance BP (so it’s easy to call from other BPs). Made under 4.17.0

Here’s my free BP function for realistic drinking from glasses
Here’s my free BP function for animation shading
And here’s a little BP clip so your pawn hears sounds instead of the follow camera