You are currently browsing the tag archive for the ‘llGetLinkName’ tag.

In my previous article, I showed how to set up communication between different scripts in a set of linked prims. In this article I will explore this a little further, and show how to make it more flexible and easier to use.

First, we need a way of finding the link numbers of the prims in a set. Although it is possible to work this out manually, it is tedious and error-prone, and the more prims that are linked, the worse this becomes.

Let’s try an alternative. Give each of the prims a unique name (or at least unique within the link-set). This is probably a useful thing to do anyway.

Once this is done, you can set up variables for the prims that a script is interested in, and then locate the linked prims by name, using llGetLinkName function. Call this when the script is reset or the prim is rezzed.

Here’s a small example:

// This will hold the link number for the prim we
// want to send messages before.
integer LINK_TARGET = -1;
// A function to read the link numbers.
getLinks()
{
    integer i;
    // How many prims are linked?
    integer linkcount = llGetNumberOfPrims();
    // Reset our link target number, just to be
    // safe.
    LINK_TARGET = -1;
    // Work through the prims, looking for our
    // target.
    for (i = 1; i <= linkcount; ++i)
    {
        string str = llGetLinkName(i);
        if (str == "LINK_TARGET_NAME")
        {
            // Found it. Store the link number.
            LINK_TARGET = i;
        }
        // We can obviously extend this to
        // look for and record the link
        // numbers of other prims.
    }
    // If we didn't find our target, report this
    // to the owner.
    if (LINK_TARGET == -1)
    {
        llOwnerSay("Could not find LINK_TARGET_NAME");
    }
}
default
{
    state_entry()
    {
        getLinks();
    }
    on_rez(integer param)
    {
        getLinks();
    }
    touch_start(integer count)
    {
        // Make sure we actually found our target
        // prim.
        if (LINK_TARGET != -1)
        {
            // Send the message to it.
            llMessageLinked(LINK_TARGET, 0, "MESSAGE", NULL_KEY);
        }
    }
}

The only thing to be careful about here is that if you change the link order (by unlinking and re-linking your prims in a different order), you have to make sure that all the scripts are reset.

One convenient way of doing this is to include a RESET command which is sent from the root prim to all the other prims. When they receive this command, they should call llResetScript() to reset themselves:

link_message(integer sender, integer cmd, string param, string id)
{
    // Assume we have defined CMD_RESET somewhere.
    if (cmd == CMD_RESET)
    {
        llResetScript();
    }
}

Now, how about passing different types of parameters, other than simple strings? If you only want to pass a single value, a straight-forward typecast is all that is required. For example, suppose we want to have a message that tells another prim to move to a specific position. To do this, we want to send a vector. We can do this like this:

llMessageLinked(TARGET, CMD_MOVE, (string)<128.0,128.0,128.0>, NULL_KEY);

The receiving prim can convert this back into a vector in a similar way:

link_message(integer sender, integer cmd, string param, string id)
{
    if (cmd == CMD_MOVE)
    {
        vector pos = (vector)param;
        llSetPos(pos);
    }
}

(Of course, I am assuming you have set up a CMD_MOVE variable in both scripts, with the same value in each. It would also be sensible to provide some kind of error-trapping, in case the parameter string does not actually hold a vector. If it doesn’t, you will end up with a vector of .)

What about passing more than one parameter between the scripts? The main trick here is for the sending script to pack the parameters into a string, and then the receiving script uses llParseString2List() to extract the result.

In this example, I am separating the parameters with a semi-colon. Here is the sender’s code:

llMessageLinked(TARGET, CMD_MOVE, "<1.0,1.0,1.0>;Move!", NULL_KEY);

The receiver needs to unpack this, like so:

link_message(integer sender, integer cmd, string params, key id)
{
    if (cmd == CMD_MOVE)
    {
        list parameters = llParseString2List(params, [";"], [""]);
        vector moveBy = (vector)llList2String(parameters, 0);
        string command = llList2String(parameters, 1);
        // Do something with the results
        // ...
    }
}

Note that when extracting the vector, I am extracting the parameter from the list as a string, and then typecasting it to a vector, because the parameter is stored as a string in the list (llParseString2List will extract the contents as string), and llList2Vector will not perform a typecast itself.

By combining the getLinks() function and the ability to pass multiple parameters, you can construct a flexible and fairly robust system for passing information between linked prims.

A final caveat: don’t overdo this. Every script takes up resources. If you have an object with a large number of scripts all communicating with one another you can seriously contribute to lag. If you find yourself doing this, it is worth rethinking how your object is working, and whether there is a simpler way of doing things.