Jump to content

llMessageLinked with potentially dynamic link numbers.


JohnathanMacBride
 Share

You are about to reply to a thread that has been inactive for 3661 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I am working on a script set that will operate in a link set. Due to the fact that this will be required to operate with varying numbers of objects in the link set, and with multple instances of this script set in one linked object I am trying to overcome the issue of the llnk number identifications when the link number could potentially change. 

I am not the greatest at scripting so I have not yet found a way to do this. I have gotten things to work with three linked objects, the controller script sending the messages set as the root. if I link 6 together 3 and 3 then both sensors trigger all of the remaining prims rather than the 'Assigned' prims 

So to break it down link number 0 needs to affect 1 and 2 and link number 3 needs to affect 4 and 5 but 3 should not affect 1 and 2 and 0 should not affect 4 and 5.

Is there a way to do this?

I have tried the following:

 

PRIM 0 llMessageLinked:

llMessageLinked(linkNum + 1, 0, "close", NULL_KEY);
llMessageLinked(linkNum + 2, 0, "close", NULL_KEY);

second llMessageLinked does not go out. only prim 1 of the link set changes.

it only works if I put:

llMessageLinked(LINK_ALL_OTHERS, 0, "open", NULL_KEY);

LINK_ALL_OTHERS is too broad of a scope for what I am trying to do.

I need to target 'hopefully', if it's done right, The next two linked prims up from the controller only.

PRIM 1 & 2 link_message:

if (msg == "open")
{
    if (isOpen == FALSE)
    {
        ~code here~
    }
}

The child prims are set to respond conditionally to the controllers llMessageLinked() message. but only the next two up from the controller, if the builder has linked the objects together properly.

Any thoughts or ideas on how to work around this would be greatly appreciated.

Johnathan

 

Link to comment
Share on other sites

I managed ot make a little progress by moving the link number detection to the child objects while using LINK_ALL_OTHERS

link_message(integer sender_link_num, integer channel, string msg, key l_id )
{
integer linkNum = llGetLinkNumber();
vector posClose = llGetLocalPos() - offset * llGetLocalRot();
vector posOpen = llGetLocalPos() + offset * llGetLocalRot();
if(channel == sender_link_num)
{

Do Stuff

}

}

 

This essentially recieves two integers in the link message, the sender link number and a number assigned the variable name channel.

in the control prim which may or may not be root at the time it is triggered, it sends llMessageLinked() with the second integer parameter set like this

integer linkNum = llGetLinkNumber();

 

what this does is pass two variables that SHOULD be identical, the only caveat I have discovered is that the test registers true for both sets of scripted objects in the lnk set. so now I need to differentiate.

Link to comment
Share on other sites


JohnathanMacBride wrote:

...

So to break it down link number 0 needs to affect 1 and 2 and link number 3 needs to affect 4 and 5 but 3 should not affect 1 and 2 and 0 should not affect 4 and 5.

...

You first need to get a grasp on how link numbers work. Within an object composed of 2 or more prims, there is no link number 0. The Root Prim is 1 and then the numbers go up from there. The only time there is a link number 0 is in the case of a solo, unlinked prim. OK?

 

Link to comment
Share on other sites

There are only a few specialized reasons to have scripts in multiple prims of a linkset. You may have some academic interest in this inter-link messaging, or some other non-obvious practical use for it, but just looking at the sample scripts it appears you may be moving the links or maybe changing other properties of them. If that's the objective, you really, really do not want to be sending messages to scripts inside those prims, but rather you want to do it all from within the root prim, and probably all from a single script in that root prim, using llSetLinkPrimitiveParamsFast(). 

One of those very rare, specialized reasons to script multiple linked prims might be if there are distinct subassemblies that are linked together dynamically, perhaps temporarily, but must also operate separately in standalone mode. Or when the mousepointer must reflect that only some child prims are touchable. And a very few remaining prim parameters not link-controllable, such as sound.

Link to comment
Share on other sites

I am working on a door assembly. an automatic sliding door assembly for somthing I am building. I find that using any kind of rezzing system can be a pain when you have unlinked doors and thought it would be convenient if I could have these doors operate, linked to eachother or linked to the build as a whole.

I am still learning to script and so it does get confusing. I will explore the possibility of taking the child prim scripts and combining them into separate functions in the controller and see how that works out. 

Thank you both for your input and I am more than open to advice as it is offered.

Link to comment
Share on other sites

I don't think you need to use link messages for what you're trying to do -- now we have llSetLinkPrimitiveParamsFast, that's a much better option since it not only saves having multiple scripts but will also give a smoother visual effect if you're moving several prims at once.

That leaves you, though, with the problem of how to cope with potentialy dynamic link numbers, and the simple answer is that you don't use link numbers.   Use link names or descriptions instead.   So, something like

 

 
integer prim1;//placeholder for the link numbersinteger prim2;integer prim3;findPrims(){    integer max = llGetNumberOfPrims()+1;//because llGetNumberOfPrims starts counting at 1    integer counter = 1; //because link numbers in a linkset start at 1        do {        string str = llGetLinkName(counter); //get the name of the link                if ("Door 1" == str){ //and if it's the name of a prim we're interested in            prim1 = counter; //assign the link number to the appropriate variable        }        else if ("Door 2" ==str){            prim2 = counter;        }        else if ("Door 3"==str){            prim3 = counter;        }        //and so on    }    while (++counter <max); //loop through the list}default{    state_entry()    {       findPrims();    }    touch_start(integer total_number)    {            string s = (string)llGetLinkPrimitiveParams(llDetectedLinkNumber(0),[PRIM_NAME]);        if ("Button 1" == s){            //do stuff to Door 1        }                else if ("Button 2"==s){          //do stuff to Door 2        }    }}

 

;

NB -- you need to call the findPrims function on_rez and in the changed event if (change & CHANGED_LINK) to re-read the link numbers, and if you need to change the link names for any reason (or if you put the script in before you name the prims), then reset the script to make it re-read everything.

I wouldn't do it exactly this way in a script I was writing, but I wanted to give a simple demonstration of a couple of things you might find useful.

  • Like 1
Link to comment
Share on other sites

Yes, like that. The only reason I have not purchased any scripts is because I am trying to become more skilled in scripting and felt it would make a good challenge. I have moved all my functions for the doors to my single controller script. I have not yet gotten it to work but with a few debug messages in place I should be able to locate what is going wrong.

Link to comment
Share on other sites

I currently have the following function implemented

 

doorOpen1()
{

    vector posClose = llGetLocalPos() - offset1 * llGetLocalRot();
    vector posOpen = llGetLocalPos() + offset1 * llGetLocalRot();
    linkNum = llGetLinkNumber() + 1;
    if(!isOpen)
    {
        llSetLinkPrimitiveParamsFast(linkNum, [PRIM_POS_LOCAL, posOpen]);
    } else if(isOpen)
    {
         llSetLinkPrimitiveParamsFast(linkNum, [PRIM_POS_LOCAL, posClose]);
    }
}

 that handles door state and the open/close function via llSetLinkPrimitiveParamsfast().


There is one function for each door as the open offset is different for the two doors.

I don't intend on making this universal for one to N  doors. it is simply for a set of two doors that slide open.

A side question, is anyone familiar with non blocking functions in single threaded applications? similar to pipelining?

I am trying to figure that out as well.

Link to comment
Share on other sites

A couple of suggestions:

1. It often makes more sense to refer to individual prims in a linkset but their name rather than by link numbers, especially if you are likely to keep linking and unlnking things. so, generically...

integer i;while (i <=  llGetNumberOfPrims()){    ++i;    if (llGetLinkName(i) == "Front Door")    {        //Do front door stuff    }    else if (llGetLinkName(i) == "Side Door")    {        // Do side door stuff    }}

 2.  If you are using a "standard" cut prim door -- that is, one that you have cut so that its hinge edge is what used to be the middle of the door --- then the easy way to deal with your offset is to use llGetScale (or its llGetLinkPrimitiveParams equivalent).  So ask ...

vector DoorSize = llGetScale();

float Offset = DoorSize.y * 0.5;

llSetLinkPrimitiveParamsFast(link_number_here,[PRIM_POS_LOCAL, Local_pos + <0.0,Offset,0.0>]);

where you have already captured Local_pos as another part of the exercise.  That way, you can use a little bit of code to figure the offset for each different door in your linkset instead of having to feed a bunch of numerical values in each time you redimension a doorway.

 

 

Link to comment
Share on other sites


JohnathanMacBride wrote:

 

A side question, is anyone familiar with non blocking functions in single threaded applications? similar to pipelining?

I am trying to figure that out as well.

i am (:

but would be helpful if you could be a little bit more specific about your use case

Link to comment
Share on other sites


JohnathanMacBride wrote:

I currently have the following function implemented

 

doorOpen1()

{

    vector posClose = llGetLocalPos() - offset1 * llGetLocalRot();

    vector posOpen = llGetLocalPos() + offset1 * llGetLocalRot();

    linkNum = llGetLinkNumber() + 1;

    if(!isOpen)

    {

        llSetLinkPrimitiveParamsFast(linkNum, [PRIM_POS_LOCAL, posOpen]);

    } else if(isOpen)

    {

         llSetLinkPrimitiveParamsFast(linkNum, [PRIM_POS_LOCAL, posClose]);

    }

}

 that handles door state and the open/close function via 
llSetLinkPrimitiveParamsfast().

There is one function for each door as the open offset is different for the two doors.

I don't intend on making this universal for one to 
N
 
doors. it is simply for a set of two doors that slide open.

 

I'm not quite sure if that's intended as a question, but I don't think it will work, at least not if called from the root prim, since llGetLocalRot returns the rotation of the prim containing the script.

Try something based on this: 

integer toggle;default{    state_entry()    {        //llSay(0, "Hello, Avatar!");    }    touch_start(integer total_number)    {        toggle = !toggle;        list l = llGetLinkPrimitiveParams(2,[PRIM_SIZE,PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);        vector size = llList2Vector(l,0);        vector v = <0.0,size.y,0.0>;        if(toggle){            v *=-1.0;        }        vector p = llList2Vector(l,1);        rotation r = llList2Rot(l,2);        llSetLinkPrimitiveParamsFast(2,[PRIM_POS_LOCAL,p+v*r]);    }}

 

I think, if I were trying to open sets of double doors, I'd put together a user function to open two doors at a time, in the same call of llSetLinkedPrimitiveParamsFast, by using PRIM_LINK_TARGET. I think I'd also experiment with identifying pairs of doors, perhaps by using both the name and description fields. That is, I would have two doors called "Door 1" and their descriptions would read "left" or "right" so I knew how to move them.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3661 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...