Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

touch_start question

Dylan Rickenbacker
Animator
Join date: 11 Oct 2006
Posts: 365
02-01-2008 07:53
Hi, I want a script to display one dialog when an agent touches it and another one if subsequent agents touch it (basically to avoid repeated triggers). I tried it this way, but this doesn't seem to work:

touch_start(integer num_detected)
{
if(num_detected == 1)
{
llDialog(llDetectedKey(0),"Enjoy your ride!",boatmenu,237);
}
else
{
llDialog(llDetectedKey(0),"The menu is already in use.",["OK"],237);
}

Is there only a small error in this or is my idea totally wrong? Any other ones?

Thanks :-)
Very Keynes
LSL is a Virus
Join date: 6 May 2006
Posts: 484
02-01-2008 09:58
It counts from zero not one, so try replacing == 1 with <1
I have not tested that it's just a thought.
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
02-01-2008 11:44
It's my understanding that touch_start gets triggered by a user left clicking on the object, perhaps even several times if the user holds down the button. The numb_detected parameter, I believe returns the number of clicks perceived at the same time. It's not keeping a running count and would only be > 1 if it so happened that two users clicked at the same time.

I think you would have to keep track of who may have clicked recently and compare that list to who is clicking now. I can think of a complicated way of doing it. Save who clicked in a strided list along with the time of the click. Set a timer and clear out old entries every so often. When someone else clicks see it they are in the list.

Perhaps some of the scripting gurus know how to do this in a more elegant way.
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
02-01-2008 12:03
The touch_start event will really only ever have 1 person in its data. If you want to deal with multiple people touching simultaneously, you could use plain old touch, but its applications are limited. Instead, just realize that a single touch_start event happens for each time anyone touches the object. That means if the same person clicks 5 times, 5 events will trigger.

If you want to make sure no one else can use the menu at the same time, then you'll need to do a couple of things. You could switch to a different state, one that has no touch event, and process the dialog response from there. Alternatively, you could just set an integer touched = 1 when they touch it, and check to see if (touched) whenever anyone touches. The latter avoids multiple states.

Either way you do it, you'll have to clean up things so other people can use the menu. When they press a button and they're done, and probably also after a set time-out, the menu should expire and anyone else should have access.
_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-01-2008 14:19
the standard way:
ignore all but the first person to touch if there are simultaneaous touches
CODE

touch_start( integer vIntTouches ){
//-- all llDetected* functions use 0
}


the safe way
loop through the number of touches to process all simultaneous touches
CODE

touch_start( integer vIntTouches ){
while (~(--vIntTouches)){ //-- loops through backwards less code
//-- llDetected* Functions use vIntTouches
}
}


other loops will work, just remember that detect* uses the index, not the count, so the indexes will be from 0 to (count-1)

IMPORTANT NOTE ABOUT "SIMULTANEITY":
touch events have a trigger time of 0.1sec when the script is NOT processing anything. so simultaneous means within .1sec of the first touch.

IF however, the script is processing code, the touch event gets added to the queue, and further touches after that are added to it's event slot, until the touch event executes... this can mean several touches can stack up (but only one per avatar). in the below example, any touch within 30 seconds is simultaneous for this purpose

as an example, have several people touch a prim with the following script immediately after it starts.
CODE

default{
state_entry(){
llSay( 0, "collecting touches for the next 30 seconds" );
llSleep( 30.0 );
}

touch_start( integer vIntTouches ){
llSay( 0, "I detected " + (string)vIntTouches + " different touches"
while (~(--vIntTouches)){
llSay( 0, llDetectedName( vIntTouches ) );
}
}
}


what this means:
you should ALWAYS loop through your touch event properly, but especially if you have code that takes a long time to process, or have many high traffic users.

even if it's only set to respond to the owner (so not expected that others would be touching it constantly), someone else could lock the owner out of their own script by rapidly clicking on the 'standard' example

just for fun
a super fast loop:
CODE

@loop
if (~(--vIntTouches)){
//-- use llDetected* with (vIntTouches);
jump loop;
}


is logically the same as, but faster than:
CODE

integer index;
for( index = vIntTouches - 1; index != -1; index = index - 1 )
//-- llDetected*( index );
}
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Dylan Rickenbacker
Animator
Join date: 11 Oct 2006
Posts: 365
02-05-2008 04:31
Thanks for all replies! Got it sorted now.
Boreal Latte
Registered User
Join date: 15 Nov 2007
Posts: 104
02-06-2008 23:55
How about this solution?:
default
{
state_entry()
{
llSay(0, "Touch me :-)";);
}

touch(integer total_number)
{
llSay(0, "Touched.";);
state touched;
}
}

state touched
{
touch(integer x)
{
llSay(0,"busy";);
llSleep(15);
state default;
}
}