Sooner or later, if you are creating gadgets that do useful things, you will find the need to have some communication between scripts in different prims.

There are two basic methods of doing this. One is to use the llMessageLinked() function, the other is to use a chat channel. In this article I am going to look at using llMessageLinked, but it is important to understand when to use which option.

Let me start, then, by briefly looking at the chat channel option.

The main advantage of this option is that the prims which contain the communicating scripts do not have to be linked. This allows prims to communicate across an entire sim (note that there is no easy way to communicate across different sims short of using an external web-service of some kind).

The main disadvantage, and this is a biggie, is that using a chat channel normally requires the scripts to set up Listeners which are constantly active. This adds to simulator lag, and is something that therefore should be minimised.

If your scripts absolutely need to be run in unlinked prims, or in prims which are in separate objects, however, the chat channel option is probably the only way to go.

However, if your scripts are part of a set of linked prims, the llMessageLinked function is a better option, and it is this option that I am going to cover.

llMessageLinked takes a number of parameters, although you rarely need to make use of all of them. The first parameter is crucial, though, as it is the number of the prim that you are sending the message to. It can also be one of a set of special values, the most useful of which are probably the following:

LINK_ALL_OTHERS – this sends the message to all other prims except the current one.

LINK_ALL_CHILDREN – this sends the message to all prims which are children of the root prim.

LINK_ALL – this sends the message to all the prims in set, including the one that the message is sent from.

The second parameter is an integer. This can be used as an identifier of the type of message. For example, you could set up the following constants in each script:

integer CMD_INIT = 1;
integer CMD_MOVE = 2;	// I'll use this in my examples below

You would then pass the appropriate value to llMessageLinked.

The third parameter is a string. This can be used to pass parameters to the receiving scripts. If you only need one parameter, this is simple. Remember that you can use LSL’s type-casting to let you put (for example) numbers into this parameter. I’ll show an example of this later.

The final parameter is a key.

At the receiving end, the message() function will be called when a message is received from an llMessageLinked() call. It is passed five values, the first of which is the number of the sending prim, and the other four are the four parameters from llMessageLinked().

As an example, lets create a system whereby touching the root prim will move the linked prim. In itself, this isn’t exactly useful, but it could be used as the basis of (for example) some kind of ‘sliding door’ system.

Create two prims, and link them together.

Create a new script in the root prim (note that if you create a script while a link set is selected, the script will automatically be created in the root prim).

In our script, we will have a setting which tells us if the other prim is in its original position. If it is, when the owner touches the root prim, we move the other prim a short distance away. If it is not, we will move it back.

Here is the basic script:

integer hasMoved = FALSE;
float moveBy = 1.25;
// Commands
integer CMD_MOVE = 1;
integer CMD_RESTORE = 2;
default
{
    touch_start(integer count)
    {
        // Only respond to our owner.
        if (llDetectedKey(0) == llGetOwner())
        {
            if (hasMoved)
            {
                // Tell the other prim to restore its original position.
                llMessageLinked(2, CMD_RESTORE, "", NULL_KEY);
                hasMoved = FALSE;
            }
            else
            {
                // Tell the other prim to move by a specified distance. Note
                // that we are type-casting the distance to a string.
                llMessageLinked(2, CMD_MOVE, (string)moveBy, NULL_KEY);
                hasMoved = TRUE;
            }
        }
    }
}

Save the script.

Now, tick the ‘Edit individual prims’ checkbox, and select the other prim. Create a script in this prim. In this script, we will detect the message from the root prim, and respond accordingly:

vector originalPos;
// Commands
integer CMD_MOVE = 1;
integer CMD_RESTORE = 2;
default
{
    state_entry()
    {
        originalPos = llGetLocalPos();
    }
    on_rez(integer param)
    {
        originalPos = llGetLocalPos();
    }
    link_message(integer sender, integer num, string params, key id)
    {
        // Check that this came from the main script.
        if (sender == 1)
        {
            // Find out which command was received
            if (num == CMD_MOVE)
            {
                // Read our local position (i.e. relative
                // to the link-set object)
                vector pos = llGetLocalPos();
                // Adjust it -- note that we can typecast
                // the string parameter to a float.
                pos.x += (float)params;
                // Set the new position
                llSetPos(pos);
            }
            else if (num == CMD_RESTORE)
            {
                // Restore our original position
                llSetPos(originalPos);
            }
        }
    }
}

Save the script, close the Build dialog, and test the object.

You should find that this works, and touching the object will move the second prim. Touching it again will move it back to its original position.

However, there are some problems with this system. For example, we need to know the link number of the prim that we want to send a message to. When there are only two prims (as in our example) this is simple, but if there are a number of prims, it can get difficult to keep track of this (especially if you
unlink and relink the prims while you are building your object, as is quite likely).

Also, the string that we are using to pass a parameter to the linked prim seems a little restrictive.

In the next article I’ll look at both of these issues, and some possible solutions (though as a hint for the parameters, remember that you can typecast a list).