David Gaider - Setting Variables

From NWN Lexicon
Jump to: navigation, search

One of the most common things you will do is set variables and retrieve them... this is the only way of determining whether most events have taken place or of changing/keeping track of different story states.

The most common command you will use when setting variables is this:

// void SetLocalInt(object oObject, string sVarName, int nValue)
SetLocalInt(OBJECT_SELF, "VARIABLE1", 1);

This command sets a 'local integer'. What does it mean by local? It means that the integer is referenced to, or 'stored on', the oObject you specify (it isn't really stored there physically, but it's easier to think of it that way).

There are three things that are important to remember, here:

  1. The 'oObject' has to be a valid object. You will see many commands that return object at the beginning of their structure (like it says 'void' at the beginning of SetLocalInt). This means that those commands return data of the type object.
    Whatever object you specify is where the integer is referenced to. If you're in dialogue, using GetPCSpeaker() will return the PC who's talking to the NPC as the object. You can use GetModule() to store the integer on the module itself... you could use OBJECT_SELF to reference whatever object is running the current script, etc.
    This is important because the variable you choose becomes unique to that object. If you store a variable by the name of "VARIABLE1" with the value of 1 on the module, that's the only variable by that name that can be stored there. You could have a "VARIABLE1" stored on a different object, like a PC, and it could have a completely different value.
  2. The 'string sVarName' is the name you give to your variable. Make sure it is unique. Like all strings, it must be enclosed in quotes (like "VARIABLE1" above). Variable names are not case-sensitive.
  3. The 'int nValue' is the information you're storing in the variable. Since it is an integer we're setting with this command, it must be a number (with no decimal places)... such as 1, 15 or 320. If you wanted to store different information here, you need a different command:
// stores a float number (a number with a decimal place)
// void SetLocalFloat(object oObject, string sVarName, float fValue);
SetLocalFloat(OBJECT_SELF, "nw_some_key", 12.0f);
// stores a string (such as a sentence or word or an object's name
// it must have quotes around it, just like the variable name
// void SetLocalString(object oObject, string sVarName, string sValue);
SetLocalString(OBJECT_SELF, "nw_some_key", "some string");
// void SetLocalLocation(object oObject, string sVarName, location lValue);
// stores a location
SetLocalLocation(OBJECT_SELF, "nw_some_key", GetLocation(OBJECT_SELF));
// void SetLocalObject(object oObject, string sVarName, object oValue);
// stores object data (such as placeable object, an inventory item, or a creature)
SetLocalObject(OBJECT_SELF, "nw_some_key", OBJECT_SELF);

How do I use variables?

Well, once you've set a variable on something, it stays there until replaced or destroyed. At any other time in another script (or the same script) you can call on that variable again and recall the information stored in it.

If I wanted to recall that integer data I just set in a variable, I would use this:

// int GetLocalInt(object oObject, string sVarName);

This is exactly the same command as what you just used to set the variable... minus the actual value of the data (as that's what you're looking for).

Note that this isn't a void command... it returns an integer, actual information. This means you don't just use this command on its own. You use it to define either needed 'int' data in another command or a variable you are setting... like so:

int nValue = GetLocalInt(OBJECT_SELF, "VARIABLE1");

The above means you have just specified a new variable called 'nValue' which is now equal to the integer that was stored in the OBJECT_SELF under the name of "VARIABLE1".

Confused yet? Examples...

One great example of how a variable might be used is to track the progression of plots. Let's say I want to have a variable called "STORY"... when the player accepts the plot, I set it to 1. When the player finishes the plot, I set it to 2.

The player accepted the plot...

At the point in dialogue where the player accepts, I go to 'Actions Taken' and make a script that sets the "STORY" variable to 1 on the PC.

void main()
{
    SetLocalInt(GetPCSpeaker(), "STORY", 1);
}

The player finishes the plot...

Let's say the player has returned, having done what the NPC wanted. The NPC congratulates him and the "STORY" variable is set to 2 on the PC.

void main()
{
    SetLocalInt(GetPCSpeaker(), "STORY", 2);
}

How do I know if the player has accepted or finished the plot or not?

When it comes to dialogue, you just need to make a new starting node for each condition. The computer will start from the top and check any scripts in the 'Text Appears When' section and see if it is TRUE (or if there is no script there, which makes it automatically TRUE). If so, it starts that node. If not, it continues to the next.

So, with this plot, you'd list the nodes from last to first...

  1. (plot done) "Thank you for doing that plot."
  2. (plot accepted) "Have you finished that plot?"
  3. (not accepted, not done) "Hello there!"

So you need a script which returns TRUE for #1 if the PC has the "STORY" variable on him set to 2, right? And for #2, the script must return TRUE if the variable is set to 1. No script is needed for 3, because if both #1 and #2 were FALSE, then the plot has neither been accepted nor done.

Is the plot done?

int StartingConditional()
{
    int nDone = GetLocalInt(GetPCSpeaker(), "STORY") == 2;
    return nDone;
}

Is the plot accepted?

int StartingConditional()
{
    int nAccept = GetLocalInt(GetPCSpeaker(), "STORY") == 1;
    return nAccept;
}

So you'd end up with this:

  1. (1st script in "Text Appears When") "Thank you for doing that plot."
  2. (2nd script in "Text Appears When") "Have you finished that plot?"
  3. (no script) "Hello there!"

In the above script, I only want the NPC to give the plot to 1 person.

At the point when he sets the "STORY" variable on the PC to 1, why not have him set a variable called "PLOT_GIVEN" to 1 on OBJECT_SELF (the NPC)?

Then when the dialogue branches from the default #3 dialogue (because another PC with no "STORY" variable on him wanders along and speaks to the NPC), you could have the dialogue split into two:

--> (script in "Text Appears When" that returns true if "PLOT_GIVEN" on OBJECT_SELF returns a 1) "Sorry, no work for you today."
|
|
--> (no script) "How would you like to do a plot for me?"

A Really Simple Example Quest Dialogue

The thing to remember is that when you line up your 'starting nodes' underneath the Root, they should be in reverse order of completion.

The following is a rundown of what scripts would be at each node:

#1 script in 'Text Appears When' set to return TRUE if "Job" variable on PC set to 4 like so:

int StartingConditional()
{
    int nJob = GetLocalInt(GetPCSpeaker(), "Job") == 4;
    return nJob;
}

#2 script in 'Text Appears When' set to return TRUE if "Job" variable on PC set to 3 (set below). If the PC has finished the job, have NPC give reward and set "Job" variable to 4 (no more jobs) in 'Actions Taken' like so:

void main()
{
    SetLocalInt(GetPCSpeaker(), "Job", 4);
}

#3 script in 'Text Appears When' set to return TRUE if "Job" variable on PC set to 2 (set below). If the PC has finished the job, have NPC give reward and job #3... set "Job" variable to 3 in 'Actions Taken'.

#4 script in 'Text Appears When' set to return TRUE if "Job" variable on PC set to 1 (set below). If the PC has finished the job, have NPC give reward and job #2... set "Job" variable to 2 in 'Actions Taken'.

#5 Script in 'Text Appears When' returns TRUE if "TalkedToJoe" variable on the PC set to 1 (set below). In the dialogue, if the PC accepts job#1, set the "Job" variable on the PC to 1 in 'Actions Taken'.

#6 no script in 'Text Appears When' (if all other scripts above are FALSE, this is the first time the PC has spoken to this NPC). On the first line, put a script in 'Actions Taken' that sets a "TalkedToJoe" variable on the PC to 1.

So this is the basic setting and getting of variables. Storing and using string and object data and other sorts is a little more complicated... but something that is easily caught onto once you get used to manipulating integers. Hopefully this will get you started.


 author: David Gaider, editor: Charles Feduke