Earlier I’d written a post on Mono and Bytecode Sharing. In that post, I mentioned that there were several ways that a script could be written to take configuration parameters. Being able to configure scripts for multiple purposes has at least two advantages.
- Scripts that don’t need to be compiled to make small parameter changes support bytecode sharing.
- Being able to configure a single script to serve multiple purposes potentially makes the script easier to maintain.
One way to make a script configurable is to put socks in your object. Yeah, yeah, I know that sounds weird. But it is really a pretty easy way to set simple configuration parameters. And if you don’t like socks you could use any clothing object. The LSL functions that deal with clothing can’t actually tell what type of clothing it is.
Basically, what you do is place a clothing item with a particular name in the object. Then have the script read the object inventory looking for clothing items. If it finds an item with a name of a keyword that you’ve chosen, then set a flag, flip a switch or whatever you need to do in your script to make it behave differently.
First you have to create a pair of socks. Don’t worry. This is easy. You don’t have to do anything to them other than name them as their name is all we’re interested in. Open your inventory, select the ‘Clothing’ folder and right click on it. On the menu that opens, select ‘New Clothing’, then ‘New Socks’. If you don’t rename them now, they’ll be called ‘New Socks’. Drag them to the inventory of your object and rename them to whatever you like.
The llGetInventoryName function is the key to socks approach. It will return the n’th item of the indicated type from the inventory. In this case I specified ‘0′ for the item number so we get the first item.
socks = llToLower(llGetInventoryName(INVENTORY_CLOTHING, 0));
In the example above, I’m saving the name of the first item of type INVENTORY_CLOTHING in the variable ’socks’. I also use the llToLower function to make it lower case so I don’t have to worry about what case things are. I’ll do all of my compares in lower case.
For this demonstration, the assumption is that there is only one clothing item in the inventory. If there are others, the one you want might not be the first one and the code would have to loop through and look at all clothing items.
In the sample script below, the code immediately after llGetInventory goes through a sequence of if statements to check for various names and sets a flag as appropriate. In this example, I was setting a debug flag. Of course you could just as easily set a ‘left’ or ‘right’ to tell a script to open a door to the left or right. Or a ‘blue’ or ‘red’ to make a particle script spew blue or red particles. You get the idea.
A few other comments about the sample code.
I use the on_rez event in most of my scripts to cause an automatic reset when the object is rezzed.
Also, in this sample, I used the changed event to detect when the object inventory changes. The result is that if you rename the socks inventory item, or change any inventory item, the script automatically resets.
Then lastly, the touch_start event is just included so you can touch the object and have it report the current setting of the flag.
And now for the sample code. It doesn’t do anything useful. Just demonstrates the approach. And, it works in both SL and OpenSim.
// Config Demo - Socks
//
// Script to demonstrate the use of socks to set config parameters.
//
// The clothing object name in inventory is checked to see if it is
// a particular keyword of 'debug on' or 'debug off'. Set the gDebug
// flag accordingly.
//
// Additional inventory objects could be used to set other flags.
//
// Micheil Merlin/SL - 12/1/2009
integer gDebug = 0; // Debug flag.
default
{
state_entry()
{
string socks; // Name of inventory clothing object.
// Get the name of the first inventory item of type clothing. Any
// clothing type will work. The llGetInventoryName function does
// not look for socks specfically. The llGetInventoryName function
// is called with a '0' to get the first item of type clothing. It
// could be called successively to obtain additional clothing
// items. If it returns an empty string, there is no more
// inventory of that type.
socks = llToLower(llGetInventoryName(INVENTORY_CLOTHING, 0));
// Look for clothing name of 'debug on' in lower case.
if (socks == "debug on")
{
gDebug = 1;
// Look for clothing name of 'debug off' in lower case.
} else if (socks == "debug off")
{
gDebug = 0;
// Check for the existence of the inventory item.
} else if (socks == "")
{
llSay(0, "No inventory of type clothing exists.");
// If the clothing name is neither, then just say it.
} else
{
llSay(0, "Clothing name of '" + socks +
"' found. We weren't expecting this.");
}
llSay(0, "Debug is set to " + (string)gDebug);
//
// The socks processing is complete. Other code could be inserted
// here.
//
}
// This event is triggered when the object is rezzed.
on_rez(integer num)
{
llResetScript(); // Reset script when object rezzed.
}
// This event is triggered when the object has changed.
changed(integer change)
{
// If inventory has changed, assume script reset is needed.
// Adding socks to the inventory or renaming them will cause this
// event to trigger.
if (change == CHANGED_INVENTORY)
{
llResetScript();
}
}
// This event is triggered when the object is touched.
touch_start(integer total_number)
{
llSay(0, "Debug is set to " + (string)gDebug);
}
}