Jump to content

Home

Tokens and How to Use Them


Fair Strides 2

Recommended Posts

Intro:

This tutorial is to teach the community about Game and CustomTokens, an element of NSS Scripting from the NeverWinter Nights games. They're a little-known piece around here, but I'm hoping to change that.

 

In Darth333's Intro to Modding tutorial, she mentions using the NWN Lexicon as a reference for learning how to write scripts for the KotOR games. This was actually very good advice, as it allowed me to learn a lot about how the game handled things.

 

One of the things I learned about was the Custom Tokens: pieces of scriptable, dynamic info that I can set with a script and insert anywhere.

 

How To Use Tokens:

You can use a token in a conversation, a name for a character, door, placeable, item, or an item's description. To use either the Game's Tokens or a Custom Token, you merely have to surround it with <>.

 

For example, to refer to a player by "He" or "She" in a conversation, you'd need to use the Game Token <He/She> as-is in the sentence, and the game would insert the correct one based on the Player's gender.

 

The Game's Tokens:

To give you an idea of what the tokens can do or control, the game stores the Player's name in up to three tokens, the FullName, FirstName, and LastName tokens. The game seems to set the tokens based on splitting the Player's name at the first space into the FirstName and LastName tokens. Other helpful tokens are the <He/She>, <Alignment>(Upper-case version; lower-case is <alignment>), and <Class>(lower-case is <class>). More can be found in stringtokens.2da, though most seem to be NWN-Specific.

 

Custom Tokens:

The Custom Tokens are slightly different from the Game Tokens. For one thing, to use them them you have to use the format <CUSTOM#>, where "#" is a number between 0 to 2147483647.

 

In practice, however, the game uses 0-9 and the WhereAmI band mod uses 61 and 62, so I'd avoid those in TSL. Also, in K1, the K1R mod uses 1998-2030(or around there) for the Pazaak Tourney, so I'd really avoid those...:)

 

To set a Custom Token:

void main()
{
   // Syntax for the function: SetCustomToken(int iTokenToSet, string sMessage)
   SetCustomToken(2000, "Hi, I'm token 2000!");
}

 

Though there is no GetCustomToken function, you can still check the value in a script:

void main()
{
   string sToken = "<CUSTOM2000>";
   if(sToken == "Hi, I'm token 2000")
   {
       SendMessageToPC(GetFirstPC(), "Yep, this is it.");
   }
   else
   {
       SendMessageToPC(GetFirstPC(), "No, it's not it.");
   }
}

 

Something to remember about the Custom Tokens when working with them in scripting: they are a string, not a float or integer. To check them as a string:

As a Float:

void main()
{
   string sToken_pre = "<CUSTOM2000>";
   float fToken_real = StringToFloat(sToken_pre);

   if(fToken_real == 0.0)
   {
       SendMessageToPC(GetFirstPC(), "Yep, this is it.");
   }
   else
   {
       SendMessageToPC(GetFirstPC(), "No, it's not it.");
   }
}

 

As an Integer:

void main()
{
   string sToken_pre = "<CUSTOM2000>";
   int iToken_real = StringToInt(sToken_pre);

   if(iToken_real == 0)
   {
       SendMessageToPC(GetFirstPC(), "Yep, this is it.");
   }
   else
   {
       SendMessageToPC(GetFirstPC(), "No, it's not it.");
   }
}

 

Special Notes:

  • The Game Token <he/she> seems to not be set right, at least whenever I paired it with the <He/She> token; I had to set the "he" or "she" as a Custom Token, CUSTOM2009.
  • When used, the text stays as-is, even if the Custom Token itself changes. If it's a quest, you would have to take away and then re-give the quest entry to get the changes. Otherwise, you'd have to re-give the item. If it's a creature, you'd have to respawn them.
  • The same above applies to dialogues, which is why if you have to change a bit of info in a line, it's best to set a conditional statement in the first node that activates to set the value accordingly.
  • You can set an integer or float as a Custom Token, but it gets transformed into a string so the game can use it properly.*

 

*: For a float, it has a trailing character on it called a newline(basically akin to hitting the Enter key in a text document). To get a float->string conversion properly, it's best to take off that trailing character:

 

void main()
{
   float fTrial = 5.3;
   string sMessage = FloatToString(fTrial);
   sMessage = GetStringLeft(sMessage, GetStringLength(sMessage)-1);

   SetCustomToken(2000, "Float is: " + sMessage);
   SendMessageToPC(GetFirstPC(), "<CUSTOM2000>");
}

 

Good Example:

As an example of using Custom Tokens effectively, here's a script Darth Insidious had me help him on just the other day. What I ended up having him do was make a dialogue file with one entry, and that entry have the text "<CUSTOM50000>", minus the quotes. I had him save that as-is and then use the following script:

Show spoiler
(hidden content - requires Javascript to show)
void main()
{
   int r = Random(20) + 1;  // r equals anywhere from 1 to 20

   object oPC = GetFirstPC();
   location lPC = GetLocation(oPC);

   object oSS1 = GetItemInSlot( INVENTORY_SLOT_LEFTWEAPON, oPC);
   object oSS2 = GetItemInSlot( INVENTORY_SLOT_RIGHTWEAPON, oPC);

   // IF either item matches the tagm execute code based on random number r.
   if(GetTag(oSS1) == "di_ss_01" || GetTag(oSS2) == "di_ss_01")
   {
       if(r >= 15) // If r is greater than or equal to 15, the Sonic Screwdriver works.
       {
           object oDoor=GetFirstObjectInShape(SHAPE_SPHERE, 5.0, lPC, FALSE, OBJECT_TYPE_DOOR);
           // Now execute code IF the door was found.
           if(GetIsObjectValid(oDoor))
           {
               SetLocked(oDoor,FALSE);
               ActionOpenDoor(oDoor);
           }

           object oBox = GetFirstObjectInShape(SHAPE_SPHERE, 5.0, lPC, FALSE, OBJECT_TYPE_PLACEABLE);
           // Now execute code IF the placeable was found.
           if(GetIsObjectValid(oBox))
           {
               if(GetLocked(oBox) == TRUE)
               {
                   SetLocked(oBox, FALSE);
               }
           }
       }
       // If r is not greater than or equal to 15, the Sonic Screwdriver "fizzles".
       else
       {
           SetCustomToken(50000, "*Bzzt.*");
           ActionStartConversation(OBJECT_SELF, "di_ssd_01");
       }
   }
   // You don't have the Sonic Screwdriver equipped...
   else
   {
       SetCustomToken(50000, "The sonic screwdriver isn't very effective when left in your pocket.");
       ActionStartConversation(OBJECT_SELF, "di_ssd_01");
   }
}

 

In short, the script will check a random number and whether you have a certain item equipped.

 

If you do have it equipped, but fail the random number roll, the device "fizzles", and the Custom Token 50000 is set accordingly so that you get a one-liner "*bzzzt*" line in the upper-left corner.

 

However, if you don't have the item equipped, the Custom Token 50000 is set with that message, and you will get a different one-liner in the corner telling you so.

 

This eliminated the need for keeping track of Globals and reduced the number of scripts needed to one.

 

If you feel like this could help you, chances are it will. As an additional tool, you can use the TSL Script Parameters to take advantage of the Engine's features and pass arguments that could affect your Custom Tokens...:)

 

If you run into trouble or want advice on usage, feel free to send me a message.;)

Link to comment
Share on other sites

Well since no one said it, I guess I will. This is awesome! Tokens are one of the things that definitely haven't been utilized frequently enough in the modding community. Good that we finally have a solid tutorial and documentation on the subject. :)

 

I'd also like to point out that the tokens 31-34 and 41-45 are used by the game's default scripts to calculate the Computer Use/Repair modifier and reduce the number of spikes or repair parts the NPC needs to hack terminals or repair droids. These scripts are called at the beginning of computer dialog files, so I'd avoid those values if you don't want your stuff overwritten by the number of spikes you need to blow up a power conduit. :)

Link to comment
Share on other sites

Well since no one said it, I guess I will. This is awesome! Tokens are one of the things that definitely haven't been utilized frequently enough in the modding community. Good that we finally have a solid tutorial and documentation on the subject. :)

 

I'd also like to point out that the tokens 30-40 (or at least I think so, I'll verify when I get home) are used by the game's default scripts to calculate the Computer Use/Repair modifier and reduce the number of spikes or repair parts the NPC needs to hack terminals or repair droids. These scripts are called at the beginning of computer dialog files, so I'd avoid those values if you don't want your stuff overwritten by the number of spikes you need to blow up a power conduit. :)

 

Thanks for the info! I'd actually forgotten about those... Looks like I'll be going through KT sometime and compiling a list for both games...

 

As to the first paragraph:

 

Well, I've educated several people in the past six months(some of them highly-esteemed scripters) on Custom Tokens, so I came to the conclusion that they weren't as well-known as I had previously thought...:)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...