Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

How does the example code for the llDetectedLinkNumber function work?

Rob Figtree
Registered User
Join date: 13 Jun 2006
Posts: 14
07-30-2008 21:56
This is the example code from the wiki for the llDetectedLinkNumber function:

default
{
touch_start(integer num_detected)
{
integer i = 0;
for(; i<num_detected; ++i)
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(i));
}
}

I understand the touch start line. I don't get the purpose of the next two lines. First integer i is set to zero and then incremented looped (I think) to what should be 1 since the num_detected variable is more than likely going to be 1 touch. The next line I mostly get in that the object will whisper in channel 0 (chat) Link number click: and then the string for the link number detected. What is the purpose of the variable (i) at the end? And if it serves a purpose, why go through the "for" logic, why not just use the num_detected variable which should be 1.

Many of the examples seem to have this same thing going on with the variable i.

Sorry, but newbies do confuse so easily.
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
07-30-2008 21:59
its easy

what if you have this in a "contest" and say "ok everyone hit the buzzer!!!"

so if 20 ppl hit the buzzer integer num_detected = 20

the rest is a standard for loop so each person that hit the buzzer gets included one at a time (0-19 = 20)

and your right it could be 1, for sake of sanity, thats the way i do it

x = 1

"when x == num_detected" blah blah blah both are valid using the 0-19 way you save a character and look more leet i guess (cause 19 IS < 20)


oh the i thing is just the way whoever wrote it, i would stand for an integer, i always use x, you might use zahhwhooohaaa it doesnt matter as long as you can make since out of it 5 years down the line
Rob Figtree
Registered User
Join date: 13 Jun 2006
Posts: 14
even more confusing???
07-30-2008 23:04
In a practice object I created, if I change the code to this:

default
{
touch_start(integer num_detected)
{
integer i = 0;
for(; i<num_detected; ++i)
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(i));
llWhisper(0, "integer i is: " + (string)i);
}
}

I get this result:
Practice Box whispers: Link number clicked: 3
Practice Box whispers: integer i is: 1

Which was the expected I result.

However, if I change the code to this:

default
{
touch_start(integer num_detected)
{
integer i = 1;
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(i));
llWhisper(0, "integer i is: " + (string)i);
}
}

which basically just sets the integer i to 1 and skips the logic, I get this result:
Practice Box whispers: Link number clicked: 0
Practice Box whispers: integer i is: 1

The code will not compile without some integer in the parens, either a directly entered integer or a variable integer. However, the only way it works is as written in the example.

Otherwise it always returns 0 (zero) as the clicked link.

It must make sense some way. I just don't get it.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
07-30-2008 23:49
From: Rob Figtree
which basically just sets the integer i to 1 and skips the logic
This will only work if at least 2 people are clicking the object at (almost) exactly the same time. 1 is the *second* entry in the array of "touchers." 0 is the first. It's likely you're exceeding the bounds of the touched array, and getting a default "error"-type result.

For the vast majority of applications for llDetected* functions inside touch* event handlers, you can just use index 0 and dispense with looping through the entire array, as it is unlikely more than one av will be touching the object at any given time (and impossible for HUD attachments, which only the owner can ever see, much less touch).
Rob Figtree
Registered User
Join date: 13 Jun 2006
Posts: 14
It makes sense now
07-31-2008 02:18
I see now how the lldetect function is working and my mistake was not realizing the count started at zero not one. In fact the following code worked:
default
{
touch_start(integer num_detected)
{
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(0));
}
}

Which, as a practical matter, probably works since the likelihood of 2 touches starting in the same instant are very slim. However, it then left me wondering why my little troubleshooting code gave me a wrong answer for i:

This code:
default
{
touch_start(integer num_detected)
{
integer i = 0;
for(; i<num_detected; ++i)
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(i));
llWhisper(0, "integer i is: " + (string)i);
}
}

I get this result:
Practice Box whispers: Link number clicked: 3
Practice Box whispers: integer i is: 1

Why in the heck did it tell me that i was 1. Did i get incremented again some way I don't understand?
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
07-31-2008 05:38
Since I'm not sure how your using the script .. I may be stating the obvious, but here goes anyway ...

If You are only putting the script in a single prim in the linkset and want to be able to determine the link numbers for each prim as you touch them .. then using llDetectedLinkNumber as you have is correct.

BUT .. if all you are doing is checking the link number of the prim the script is in .. and that you are touching .. then:

CODE

default
{
touch_start(integer num_detected)
{
llWhisper(0, "Link number clicked: " + (string)llGetLinkNumber());
}


Is all you need.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
07-31-2008 08:47
From: Rob Figtree
Why in the heck did it tell me that i was 1. Did i get incremented again some way I don't understand?
Yes. You didn't enclose both llWhisper lines in braces, hence only the first was actually part of the loop, the second executed after the loop. "i" was incremented to 1 after the first pass through the loop, causing the "i < num_detected" test to evaluate as false, terminating the loop and executing the next line of code, "llWhisper(0, "integer i is: " + (string)i);".
Rob Figtree
Registered User
Join date: 13 Jun 2006
Posts: 14
Thanks for the help all!
07-31-2008 10:10
Amazing what is packed into a few lines of code! So after some help here and playing in a sandbox I know that the index of the detected function starts at zero not one. I presume all indexes for detect functions start at zero. I also found out in the sandbox that if the code is in the root prim of the linked then all prims in the set will be detected. If it is in any other prim, then only that prim will detected. So good stuff.

I also found out with my little "test code line" that the for statement needs braces or it will loop after ever line of code after it. Thus I though the variable was 1 while it was 0 because of the extra iteration. Rewriting the code as follows fixed it:

default
{
touch_start(integer num_detected)
{
integer i = 0;
for(; i<num_detected; ++i)
{
llWhisper(0, "Link number clicked: " + (string)llDetectedLinkNumber(i));
llWhisper(0, "integer i is: " + (string)i);
}
}
}

Now, when placed in the root prim, this script will report the correct prim number of a touched prim and will correctly report that i is Zero for the first iteration.

Thanks again to all the Second Lifers who give of there time here.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
07-31-2008 10:59
From: Rob Figtree
I also found out in the sandbox that if the code is in the root prim of the linked then all prims in the set will be detected. If it is in any other prim, then only that prim will detected.
Specifically, touch* events on child prims are passed on to the root prim (thus allowing scripts in the root to determine which link was touched) unless the child prim touched contains a script with a touch* event handler of it own. If a child prim contains such a script, and you still want touches passed to the root, call llPassTouches(TRUE); at some point prior to the touch (i.e. in default state entry). This can be turned off, as might be obvious, by calling llPassTouches(FALSE);.