NWNWiki
Advertisement
NWNWiki
3,718
pages

A local variable is a piece of data—integer, float, string, object, or location—that is stored on an object under a builder-specified name. If the object is lost, so is the data. The nomenclature is ironic in a way for, while the data is "local" to the object on which it is stored, local variables are often used in the same way "global variables" are used in other programming contexts (particularly when the data is stored on the module object). Local variables can be set via scripting or from within the Toolset (although only integers, floats, and strings can be set via the Toolset). They are retrieved via scripting by specifying the object on which the data is stored and the name under which it is stored.

Local variables are (for the most part) intrinsically module-specific. For data that must be transferred between modules, alternatives include campaign variables (storage in a database instead of on an object), possession of a certain item(s) by a player character, the (unidentified) description of an item known to be possessed by a player character, and (under certain circumstances) local variables on an item known to be possessed by a player character. The first two of these options were used in the official campaigns to track a player's choice of henchman. For more on the last of these options, see the player characters section below.

General uses[]

Local variables are the primary way to store data between invocations of a script, or to share data between scripts invoked at different times. (For example, the scripts used by the standard dialog x0_skill_ctrap make heavy use of this to track what is being crafted.) They can also be used as flags (especially if set through the Toolset), indicating whether or not certain behavior is supposed to occur for a given object. (For example, local variables are used to determine which creatures and which events invoke the OnUserDefined event at the end of their standard event handlers; these are typically set in the OnSpawn event.) Flags are simple on/off switches, though, and a single local variable can hold a much greater variety of values than that. A more advanced use has the variable holding a value that will be used within the script, such as the index of a skill that a script will make use of.

When local variables are set (in the Toolset) with values to be used by a script, generic scripts can be created. This sort of "variable-based scripting" takes advantage of the way local variables are retrieved—since both an object and a variable name are required to obtain a local variable's data, either can be changed to obtain different data. This sort of generic script uses the same variable name to retrieve data, but allows the object to change (typically using OBJECT_SELF). In this way, the script can have different results when executed by different objects. For example, suppose the index of a skill was stored in a local variable called "Skill", and a DC stored in a local variable called "DC", on a non-player character. Then a "text appears when" script in that character's dialog could perform a skill check using the values stored in those variables, instead of using a SKILL_* symbolic constant and a fixed DC. (That is, the script would use values returned by GetLocalInt as parameters to GetIsSkillSuccessful.) A different character could have a different skill index and DC stored in its "Skill" and "DC" local variables, then use the same script to perform a different skill check. In this way, a single script could replace the over 40 scripts provided by BioWare for performing skill checks in conversations. (However, this approach does introduce a limitation of only one skill check per conversation; multiple checks in a single conversation would require multiple scripts. In addition, this is not a particularly writer-friendly approach.)

Some care must be given to local variables stored on items, as there are some cases where the variables seem to disappear. More precisely, local variables are not copied when an item is, unless the script explicitly requests it. If the copy replaces the original item (as happens with dye kits or a crafting skill), the perception is of a modification rather than a copy-and-replace, hence the seeming disappearance of the variables. A similar situation arises with items in stores. Items in infinite supply are generated as needed, but lack any local variables that might have been on the item's blueprint. Furthermore, when such an item is sold to the store, the sold item is absorbed into the infinite supply, which means the item is actually destroyed along with any local variables it had.

Progress tracking[]

For many novice scripters, the first use of local variables that is encountered is tracking the progress of a conversation or quest. This includes having a different greeting the second time a non-player character is spoken to, as well as recognizing that a quest has already been given out.

For tracking if a particular conversation line has been spoken, a script like the following can be placed as the "Actions Taken" script for the line. (The variable name used here would be appropriate if the line was, for example, "Yes, I accept your quest".)

void main()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC, "Quest_Taken", 1);
}

The variable name ("Quest_Taken") can be changed as needed, as can the value 1. This allows the tracking of multiple quests (different variable names) and of multiple degrees of completion (different values).

Once the local variable is set, it needs to be checked to be effective. A script like the following could be placed as the "Text appears When" script for a line that should only appear after the above script has run (but not if the quest has been advanced to a new stage — meaning the local variable value has been increased above 1).

int StartingConditional()
{
    object oPC = GetPCSpeaker();
    return GetLocalInt(oPC, "Quest_Taken") == 1;
}

As with the "Actions Taken", the variable name and value can be changed as needed. Furthermore, to check for being at least at a stage (rather than exactly at a stage), the comparison "==" can be replaced by ">=".

Player characters[]

Player characters (PCs) introduce some intricacies with regard to local variables, arising from the fact that PCs are able to leave and rejoin a module.

Local variables can be used to store objects, and PCs are objects. Thus, a PC could be the data stored in a local variable. If a PC logs out, the data becomes an invalid object, even though it is not equal to OBJECT_INVALID. If a PC logs back in, the data is again valid and will refer to that same PC.

A PC might additionally be the object on which a local variable is stored. In this case, the local variables are stored within the game itself (so stored in saved games, but not stored in saved characters). If a players logs out then back in, the local variables are restored to the state they had just before the OnClientLeave event that fired when the player logged out. (That is, the local variables can be accessed during that event, but any changes to the locals during that event will be lost.)

The items possessed by a PC are another special case. If a PC is saved to a local vault (this includes PCs used in single-player games), then local variables are stripped from most of that PC's items. This is done to conserve space and reduce waste, justified by the low probability that existing local variables would be of any use in a new module that is unrelated to previously played modules. (The exception to this are items within container items, as local variables are not stripped from these before the character is saved. However, making use of this exception can be problematic, as players can move items into and out of bags at will. This bug was fixed in Enhanced Edition version 1.79.8188.) On the other hand, a PC that is saved to a server vault will have its items retain their local variables. (This might be considered support for persistent worlds, as it allows local variables to be retained over a server reset.)

Moving a PC between the modules of a campaign is follows the same rules as if the PC was saved between modules. That is, variables on the PC are lost and the persistence of variables on the PC's items depend on what kind of vault is being used (i.e. typically lost in single-player). Similarly, server resets count as starting a new module (unless the server loads a saved game instead of the original module).

See also[]

Advertisement