• Hello game master! Welcome to our growing community. Please take a moment to Register (top right button, see how: Slides).

    If you use Campaign Logger, you can use the same login details - we've linked the app to this forum for secure and easy single sign-on for you.

    And please drop by the Introductions thread and say hi.

Passing variables in generators

jrrnewton

Member
Adventure Builder
In looking for answers to this, I searched the site, and found the following post:
Helpful to have those links, but they were not really helpful in writing generators (many gaps, etc).

I'm trying to understand how to pass a variable back up to a calling generator. I've read through the documentation, and while it does show how to define variables, it does not cover how to reference variables or how to pass back variables. I've looked through the json files for NPC, and I believe I understand how things are moving, but I cannot replicate in my own generator, so I think I'm missing something.

In looking at NPC.json, we see the following bits:
"name": "NPC",
"resultPattern": "{init}{result}",
"globals": {
<snip>
"gender": "",
"ambiguity": "",
"orientation": "",
<snip>
"Subject": "",
"subject": "",
<snip>
"possessive": "",
"independentpossessive": "",
"reflexive": "",
And a little further down, we see code that inits some of these, and calls the gender library function, assigning gender, ambiguity, and orientation:
"name": "init",
"explanation": "Initializing the required global variables, if any.",
"export": {
<snip>
"gender": "{lib:gender#common}",
"ambiguity": "{lib:gender#ambiguity}",
"orientation": "{lib:gender#orientation}",
The global variables Subject, subject, possessive, independentpossessive, and reflexive do not appear to be assigned anywhere in NPC.json.

Looking at the gender library, we see that they get initialized at the start of the library, and then assigned by calling the "common" gender table, and picking a gender which assigns the values using export command:
"name": "gender",
"resultPattern": "{init}{result}",
"globals": {
"gender": "",
"ambiguity": "",
"orientation": "",
"Subject": "",
"subject": "",
"object": "",
"possessive": "",
"independentpossessive": "",
"reflexive": ""

<big snip>

{
"name": "female",
"explanation": "Female gender.",
"export": {
"gender": "female",
"a gender": "a female",
"Subject": "She",
"subject": "she",
"object": "her",
"possessive": "her",
"independentpossessive": "hers",
"reflexive": "herself"
}
Back in the NPC.json, I see these variables referenced using a format of {g:varname}, such as this:
"{g:Subject} is wearing {lib: outfit}"
note: I added a space after lib: so that this post won't turn it into a smily

I believe what needs to happen is you define a global variable in your "master" generator, then define it again in your sub-generator/library, and set it via "export" in the sub-generator/library, so you can reference it using {g:varname} in your master... but it doesn't seem to work for me on the Generator Service test page.

What am I missing? Please help! :)
 

ELF

Generator Sage
Staff member
Beta-Tester
Faster Combatant
Adventure Builder
Variables, especially globals, can admittedly be one of the trickiest features of Campaign Logger generators. And the NPC.json is one of the most complex generators to use them, so you have started on the hardest difficulty level. :)

But to summarize the functionality, these are the key requirements for using variables (most of this you already know):
  • There are two types of variables, locals and globals.
    • Local variables retain their values only within the generator where they were defined.
    • Global variables can be used also by other generators that your first generator calls.
  • The variables need to be introduced to use them. This means listing them with their default values in a specific text block in the generator.
    • Local variables are introduced in a variables block. This example introduces a local variable called footnote that is initially empty.
      Code:
      "variables": {
      "footnote": ""
      },
    • Similarly, global variables are introduced in a globals block. This example introduces a global variable imaginatively called variable, with the default value of value.
      Code:
      "globals": {
      "variable": "value"
      },
  • After a variable has been introduced, it can be defined to contain some other value than the default. Again, there is different syntax for defining local and global variables.
    • Local variables are defined with set.
    • Global variables are defined with export.
    • This example table picks a rural settlement type at random, and defines the value of a global variable called environment as rural, no matter which entry is picked at random:
      Code:
      { "name": "countryside settlement",
      "export": {
      "environment": "rural"
      },
      "entries": [
      "cottage",
      "farm",
      "manor",
      "thorp",
      "hamlet",
      "village"
      ]
      },
  • After a variable has been introduced and its value defined, its current value can be used in the generator as part of the normal generator output. Once again, the syntax for local and global variables are different.
    • Local variable values are referenced with the string {var:}. For example, to print out the current value of the footnote variable, you would use {var:footnote}.
    • Global variable values are referenced with the string {global:} which can be shortened as just {g:}. To use the example table above, you could say for example:
      Code:
      This is a {g:environment} [countryside settlement].
      This could output for example "This is a rural farm." or "This is a rural village."
But things can become more tricky, as the variables can be introduced and defined also in other generators than your first generator that calls the other generators. It's perfectly fine to introduce variables in a generator that is called by the first generator. The host generator that can use these variables just fine, even if they were introduced somewhere else. This is handy, as it allows to keep your generators modular: any generator can call any other generator without first introducing or defining the variables the other generator needs.

As you have seen, this is what happens with the npc.json and gender.json generators:

The global variables Subject, subject, possessive, independentpossessive, and reflexive do not appear to be assigned anywhere in NPC.json.

Looking at the gender library, we see that they get initialized at the start of the library, and then assigned by calling the "common" gender table, and picking a gender which assigns the values using export command:
So this all boils down to this:
I believe what needs to happen is you define a global variable in your "master" generator, then define it again in your sub-generator/library, and set it via "export" in the sub-generator/library, so you can reference it using {g:varname} in your master... but it doesn't seem to work for me on the Generator Service test page.

What am I missing? Please help! :)
Your assumptions are almost on the spot, except that it is not necessary to introduce (or define) the variables in the "master" generator. If the variable is introduced in a generator that the master generator calls, the master generator can reference that variable just fine.

What kind of results you are getting on the Generator Service test page?
 

jrrnewton

Member
Adventure Builder
I'm working on an NPC generator for a custom race & profession set for my CRMH campaign. In any case, I'm using a stripped down set of data while I troubleshoot this. Specifically I'm trying to generate a race, return a full race name, and set a variable for an abbreviation that will be used later to call an appropriate name generator table. Basically I'm not getting the global variable set for the master script. One difference I'm doing (compared to all the examples I've seen) is doing an export per table value, and not an export at the table level. I've tried having it interpolate that by setting a local variable and then using that to set the global variable... In any case, here is my test code:
Generator JSON:
{
"name": "export var FF RACE test",
"resultPattern": "Race: {var:full_race}, {var:gender}, short: {g:short_race}",
"globals": {
"short_race": ""
},
"variables": {
"full_race": "{gen:FFRace}",
"gender": "{gender}"
},
"tables": [
{
"name": "gender",
"entries": [
"male",
"female"
]
}
]
}
Private Generator Array:
[
{
"name": "FFRace",
"resultPattern": "{FFRace} ({g:short_race})",
"globals": {
"short_race": ""
},
"tables": [
{
"name": "FFRace",
"entries": [
{ "m": 3, "v": "Au Ra: Raen", "export": { "short_race": "AR" } },
{ "m": 6, "v": "Au Ra: Xaela", "export": { "short_race": "AX" } },
{ "m": 5, "v": "Dwur: Hill", "export": { "short_race": "DH" } },
{ "m": 6, "v": "Dwur: Mountain", "export": { "short_race": "DM" } },

{ "m": 5, "v": "Roegadyn: Seawolf", "export": { "short_race": "RS" } }
]
}
]

}
]
I know that the global "short_race" is being set, because (as part of the test), I'm sending it back with the main table results. I see output that includes the full race name, and the short, but in the master generator it doesn't seem to populate the short_race global variable.
Example output:
- Race: Roegadyn: Seawolf (RS), female, short:
- Race: Roegadyn: Seawolf (RS), male, short:
- Race: Au Ra: Raen (AR), female, short:
 

ELF

Generator Sage
Staff member
Beta-Tester
Faster Combatant
Adventure Builder
How about if you remove the short_race variable introduction from the main generator, and introduce the variable only in the called generator?
Code:
"globals": {
   "short_race": ""
},
 

jrrnewton

Member
Adventure Builder
How about if you remove the short_race variable introduction from the main generator, and introduce the variable only in the called generator?
That completely worked... YaY! Thank you!
Question is: why?
Was it re-initializing it in the main generator and clearing the value created by the called generator?
This seems to contradict what is going on in NPC.json...

Results:
Race: Dwur: Hill (DH), female, short: DH
Race: Roegadyn: Seawolf (RS), male, short: RS
Race: Dwur: Hill (DH), male, short: DH

Oh, btw, I just realized the CODE keyword exists... that will help with future things too, so thank you again for that! :)
 
  • Like
Reactions: ELF

ELF

Generator Sage
Staff member
Beta-Tester
Faster Combatant
Adventure Builder
That completely worked... YaY! Thank you!
Question is: why?
Was it re-initializing it in the main generator and clearing the value created by the called generator?
It's simply a bug. I thought it had been fixed already, but apparently not.

In some cases it's possible to work around this, but it can severely limit what you will be able to do with the generators, as you have to plan in advance how the generators will use the variables. If you later use your generators in some other way, they may not work. These mystery errors can also be hard to debug, as you unfortunately have found out. :(

My hypothesis is the same as yours: in the current implementation the variable value seems to reset every time the variable is introduced. (The desired behavior would be that if the variable already has a value, the system would simply ignore any re-introductions.)

I'm not sure how hard squishing this bug will be, but I think @JochenL can give an educated guess.
 
Top