llMapDestination workaround?
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-11-2007 07:46
I'd like to be able to use llMapDestination with a rezzed object (not an attachment). The Wiki's and my experience say that it only works in the touch event or in an attachment. Unfortunately, in my script, the touch event brings up a dialog that presents locations to the user. Of course then the user response (location) is handled in the listen event. I can't think of a work around except to require a second touch to bring up the map. This could be confusing to the user and an extra step.
Can anyone think of a different work around. I don't think it's possible to simulate a touch via script. Is it?
|
|
Bobbyb30 Zohari
SL Mentor Coach
Join date: 11 Nov 2006
Posts: 466
|
11-11-2007 08:53
From: Monica Balut I'd like to be able to use llMapDestination with a rezzed object (not an attachment). The Wiki's and my experience say that it only works in the touch event or in an attachment. Unfortunately, in my script, the touch event brings up a dialog that presents locations to the user. Of course then the user response (location) is handled in the listen event. I can't think of a work around except to require a second touch to bring up the map. This could be confusing to the user and an extra step.
Can anyone think of a different work around. I don't think it's possible to simulate a touch via script. Is it? Unforunately, this isn't possible and LL will NEVER make it possible. Their main concern with regards to taking it out of the touch event is that people will use it to spam and grief.(Real shame, it would be very useful.)
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-11-2007 12:29
Too bad.
Well the only work around (accommodation) I can think of is to require a second touch, perhaps in a different state. Can anyone think of an alternate solution?
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-11-2007 15:09
you can use the system many multi-location teleporters use, in the listen event, rez a temp on rez object, which the user touches, to get the map destination...
for a demo of how this works do a search in world for "Cleary SGC"... they have a stargate network (a-la the tv series) that works exactly like this
_____________________
| | . "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... | - 
|
|
Johan Laurasia
Fully Rezzed
Join date: 31 Oct 2006
Posts: 1,394
|
11-12-2007 02:49
I ran into the same issue once... using the 2nd touch event was the only way I could figure out how to do it... unfortunately, spammers would abuse it if it was any other way
|
|
Salvador Nakamura
http://www.sl-index.com
Join date: 16 Jan 2007
Posts: 557
|
11-12-2007 04:00
Hello, due too the lack of a "favorite location list" in the SL-client, i've created a personal location teleporter (attachment) script aswell, indeed the best way would be to enter a new state after the 1st touch, and go back to "default" after the llMapdestination command. * i sell a L$1 (3 location limit) demo of my teleporter, if you wish to see it work, you can contact me or touch my profile in-game for the location or other info.
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-12-2007 04:44
or you can just go to the LSL_Portal of the secondlife wiki, and grab the example I wrote for llRequestInventoryData, and change it to use multiple landmarks... it really is a hideously simple script, I threw a hud version together in all of 5 minutes, most of which was making nice things like fwd/bck buttons and sizing it to fit on my screen nicely and look pretty
_____________________
| | . "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... | - 
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-12-2007 18:37
Thanks for the input guys. I don't much like the idea of temp rezzing a second object. I'd rather be able to control how long the second touch state is active. So, second touch in secondlife it is!
|
|
Teddy Qinan
Registered User
Join date: 10 Mar 2007
Posts: 34
|
11-12-2007 19:45
From: Monica Balut Thanks for the input guys. I don't much like the idea of temp rezzing a second object. I'd rather be able to control how long the second touch state is active. So, second touch in secondlife it is! What about a VolumeDetect prim that triggers the llDialog, so the user walks up to the object and when they get close enough the trigger the dialog by colliding with the VolumeDetect prim, then the object can be set with the text "Touch me to TP to: " + location;
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-13-2007 04:55
mmm Hadn't thought of that. Interesting concept tho. For my uses tho, the user will likely be at some distance from the object, so an initial touch to bring up the dialog is the only real convenient way to do it. May be useful for objects that are likely to be in closer proximity to the AV tho.
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-13-2007 06:27
dunno if this would work, but you could give it a try...
touch script in root object buried out of the way so avs don't touch it, contains your dialog...
child prim with touch llMapDestination and pass touches = true child prim script enters a sleep timed to your dialog timeout, then tries to read a description from it's prim, no descrip, return, else trigger map and clear descrip
when your dialog listen triggers a location, it passes a link message to a second script in the child prim, which sets the child prim descrip.
that should work with only one touch, as the first prim is still sleeping in the touch event and hasn't lost the av's key yet, the only caveat would be making the timeout for the sleep and the dialog in root to be short enough that the av isn't waiting forever for the map to open, but not so short it fires before they can make a choice
it may be possible to have the 1st child prim script to enter a polling loop, checking for descrip, and then not continue till it gets one, which you could key word if the dialog times out to just drop out
think I'll test that theory tomorrow
_____________________
| | . "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... | - 
|
|
nand Nerd
Flexi Fanatic
Join date: 4 Oct 2005
Posts: 427
|
11-13-2007 08:05
list = touched;
default { touch_start(integer num) { integer index; if (index = llListFindList(touched,(list)llDetectedName(0))) { touched = llListReplaceList(touched, [], index, index); // delete name from list. MapOpenFunction(llDetectedKey(0),llDetectedName(0),index); } else { touched += (list)llDetectedName(0); // alternatively, poplulate touched list when dialog gets returned with option selection. DialogFunction(llDetectedKey(0)); } }
}
_____________________
www.nandnerd.info http://ordinalmalaprop.com/forum - Ordinal Malaprop's Scripting Forum
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
damn I'm good...
11-14-2007 00:28
not only can I get it in one click, and 2 scripts, but it'll support reads from notes cards or landmarks... WARNING THIS IS A TEST CASE ! ! ! needs lots of work default{ state_entry(){ llListen( -42, "", "", "OK" ); } touch_start(integer total_number){ llDialog( llDetectedKey( 0 ), "blah, blah blah", ["OK"], -42 ); } listen( integer vIntNull, string vStrNull, key vKeyNull, string vStrOK ){ llRequestInventoryData( llGetInventoryName( INVENTORY_LANDMARK, 0 ) ); } dataserver( key vKeyNull, string vStrData ){ llSetObjectDesc( vStrData ); } }
default{ touch_start(integer total_number){ while (llGetObjectDesc() == ""){ } llSay( 0, llGetObjectDesc() ); llMapDestination( llGetRegionName(), (vector)llGetObjectDesc(), ZERO_VECTOR ); llSetObjectDesc( "" ); } }
::buffs nails on collar, walks off with a smug grin and promptly trips on shoelaces:: I meant to do that!
_____________________
| | . "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... | - 
|
|
nand Nerd
Flexi Fanatic
Join date: 4 Oct 2005
Posts: 427
|
11-14-2007 08:03
Nice work Void, though you'd need some sort of time-out in the event that someone hits ignore, logs out or simply ignores (doesn't click) the dialog. In which case the description is set to "none" and the second script tests for "none", if not (!) "none" then set the map destination. (for extra bonus points the listen in the first script could inform the user that they took too long to reply and they shall need to touch again and hurry up this time).
_____________________
www.nandnerd.info http://ordinalmalaprop.com/forum - Ordinal Malaprop's Scripting Forum
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
Nice job Void
11-14-2007 20:12
Here's my spruced up version. It gets rid of the llRequestInventoryData (which delays the script by 1 sec at every read) and assumes the region names and coordinates have been filled in by some other process. It also restores the contents of the description field to what it was originally. And, following nand's comments, it accounts for possible timing out (damn that ignore button!), and uses random listens. It also makes sure the second script is not left stranded in the while loop. So here are the two scripts //Script A - the main script
// These will likely be filled in by some other process list vListMenu = ["BearDrmLdg","Ross","Anzere","Warmouth"]; list vListRegions = ["Bear","Ross","Anzere","Warmouth"]; list vListCoordinates = [<31,131,111>,<34,220,57>,<70,53,125>,<31,136,94>];
//globals for the llListen integer vIntL1 = 0; integer vIntChannel1;
//global to store description field that may exist already string vStrOldDesc;
default { state_entry() { //set a random listen channel vIntChannel1 = (integer) llFrand(-2147483647.0) - 1; vIntL1 = llListen(vIntChannel1, "", NULL_KEY, ""); } touch_start(integer total_number) { //save current contents of description field to be able to restore it later vStrOldDesc = llGetObjectDesc(); //start listening llListenControl(vIntL1,TRUE); llDialog( llDetectedKey( 0 ), "Select an infohub to which to teleport.", ["Cancel"] + vListMenu, vIntChannel1 ); //Want to stop listening after 1 minute in case ignore was clicked, the user takes too long, etc. llSetTimerEvent(60.0); }
listen( integer channel, string vStrNull, key vKeyNull, string vStrDest ) { // is it coming in on the expected channel if (channel == vIntChannel1) { if (vStrDest != "Cancel") { // put the region name and coordinates into the description field of the object //preceed the string with "%#^*@" so script B can identify that it's coming from here //of course this presumes that the original description did not start with that string integer vIntIndex = llListFindList(vListMenu,[vStrDest]); string vStrTempDesc = "%#^*@" + llList2String(vListRegions,vIntIndex) + "^#*" + (string) llList2Vector(vListCoordinates,vIntIndex); llSetObjectDesc(vStrTempDesc); } else // if cancel was pressed stop the timer and reset the other script to get out of the while loop { llSetTimerEvent(0.0); llResetOtherScript("Script B"); } llListenControl(vIntL1,FALSE); } }
timer() { // reset the other script to get out of the while loop llResetOtherScript("Script B"); //stop listening llListenControl(vIntL1,FALSE); //restore the description field to its original contents llSetObjectDesc(vStrOldDesc); //Tell the user s/he took too long to respond llSay(0,"Menu timed out. Please try again."); //stop the timer llSetTimerEvent(0.0); } link_message(integer vIntSender, integer vIntNumb, string vStrStr, key vKeyId) { //message returned from the other script that it has completed successfully if (vIntNumb == 100) { //restore the description field to its original contents llSetObjectDesc(vStrOldDesc); //stop the timer llSetTimerEvent(0.0); } } }
// Script B - brings up the map
default { touch_start(integer total_number) { //This script will wait in the while loop until the description field changes to the expected string put there by script A // Script A will reset this script as needed if the expected string does not appear while (llGetSubString(llGetObjectDesc(),0,4) != "%#^*@") {} // get the string from the description field string vStrTempDesc = llDeleteSubString(llGetObjectDesc(),0,4); //parse it into the region name and vector coordinates list vListLocation = llParseString2List(vStrTempDesc,["^#*"],[]); string vStrRegion = llList2String(vListLocation,0); vector vVectorCoordinates = (vector) llList2String(vListLocation,1); //bring up the map llMapDestination( vStrRegion, vVectorCoordinates, ZERO_VECTOR ); //notify the main script that it is done so it can clean up llMessageLinked(LINK_THIS,100,"",NULL_KEY); } }
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-14-2007 23:10
I actually used RequestInventoryData because I habitually rewrite the names for landmarks, so they are descriptive of what they are for (and smaller), instead of region names... as a bonus using that system you could use the rewriten names to fill dialog buttons, and then snag the actual coordinates from the file... or even neater, use the name to fill variables for button name, region name, and region offset a small change, instead of resetting the other script, you could feed it a special value, like "oops" then if it detects a description, exit the loop, before it hits the mapDestionation call add if (description = "oops"  return;
_____________________
| | . "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... | - 
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-15-2007 11:37
We're getting a little off topic but... If you have 100 landmarks to read in the object's inventory RequestInventoryData could take close to 2 minutes to set up. If all the info for the dialog were included in the landmark name eg ([[groupName]]{{menuName}} region (x,y,z)) then I could use llGetInventoryName and parse that string into the relevant components. Doing this, I can set up 100 landmarks in about 10 seconds. The downside is the proneness to error in getting the syntax correct. The impatient types like me would probably vote for the first option. Good point about using if (description = "oops"  return; instead of resetting the script. It probably would use less resources. I'm thinking tho that there should be a brief llSleep after doing that to make sure the description field doesn't get overwritten by the old contents before the second script has a chance to read it. I'm thinking llSleep(0.01) should be enough.
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
Further considerations
11-15-2007 16:15
I've been thinking about this solution a little more. The "while loop" in the second script concerns me. It's probably ok if there are limited selections to the original menu since the user would likely get to a selection fairly quickly. In my situation, the initial menu may contain a setup option that brings the user off in a very different direction. The user could meddle around in the menu for quite a while setting various option before ever getting around to a TP selection. Also if the selections themselves are buried in a couple layers of groups, it could take a while before a final selection is made. During that time, the while loop in the second script it churning away eating up sim resources.
I've been thinking about how to control for this. One way would be to put a llSleep(0.5) in the while loop so it's just not continuously going around. But, I've read elsewhere that llSleep is a resource hog in itself. So I don't know if I would be gaining anything.
Alternately, I thought of using llSetScriptState to have the first script turn the second off when not ready to send anything and then back on when it is. I've never used it before and wonder if the second script would really turn itself off in the middle of a while loop and then resume where it left off.
I'd be interested in people's thoughts about this. In the meantime, I'm off to experiment.
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
11-15-2007 18:59
Just one script: // These will likely be filled in by some other process list vListMenu = ["BearDrmLdg","Ross","Anzere","Warmouth"]; list vListRegions = ["Bear","Ross","Anzere","Warmouth"]; list vListCoordinates = [<31,131,111>,<34,220,57>,<70,53,125>,<31,136,94>]; string Region; vector Coordinates;
//globals for the llListen integer vIntL1 = 0; integer vIntChannel1;
default { state_entry() { //set a random listen channel vIntChannel1 = (integer) llFrand(-2147483647.0) - 1; vIntL1 = llListen(vIntChannel1, "", NULL_KEY, ""); }
touch_start(integer total_number) { //start listening llListenControl(vIntL1,TRUE);
llDialog( llDetectedKey( 0 ), "Select an infohub to which to teleport.", ["Cancel"] + vListMenu, vIntChannel1 );
//Want to stop listening after 1 minute in case ignore was clicked, the user takes too long, etc. llSetTimerEvent(60.0); }
listen( integer channel, string vStrNull, key vKeyNull, string vStrDest ) { // is it coming in on the expected channel if (channel == vIntChannel1) { if (vStrDest != "Cancel") { integer vIntIndex = llListFindList(vListMenu,[vStrDest]); Region = llList2String(vListRegions,vIntIndex); Coordinates = llList2Vector(vListCoordinates,vIntIndex); state teleport; } else // if cancel was pressed stop the timer { llSetTimerEvent(0.0); } llListenControl(vIntL1,FALSE); } }
timer() { //stop listening llListenControl(vIntL1,FALSE); //Tell the user s/he took too long to respond llSay(0,"Menu timed out. Please try again."); //stop the timer llSetTimerEvent(0.0); } }
state teleport { state_entry() { llSay(0, "Touch me again to bring up map"); } touch_start(integer total_number) { llMapDestination( Region, Coordinates, ZERO_VECTOR ); state default; } }
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
More elegant yet!
11-15-2007 19:07
Ok. Stopping and starting the second script works just fine to prevent the while loop from churning away until a menu choice has been made. There needs to be a delay before implementing the llSetScriptState in Script A's touch event or the touch event may not get triggered appropriately in script B. I found that a delay of 0.2 seconds was just about right. Of course, just putting the llSetScriptState after the llDialog, which itself delays the script for 1.0 sec works just great too. That's what I ended up doing. I decided to stay with resetting the second script after a time out or cancel per my original posting rather that use Void's suggestion. I just think it's more reliable. Just a matter of preference. I also implemented a 10 minute time out to give the use plenty of time to muck around in the menu before it times out. The revised script A is as follows: //Script A - the main script
// These will likely be filled in by some other process list vListMenu = ["BearDrmLdg","Ross","Anzere","Warmouth"]; list vListRegions = ["Bear","Ross","Anzere","Warmouth"]; list vListCoordinates = [<31,131,111>,<34,220,57>,<70,53,125>,<31,136,94>];
//constants string cStrOtherScriptName = "Script B";
//globals for the llListen integer vIntL1 = 0; integer vIntChannel1;
//global to store description field that may exist already string vStrOldDesc;
default { state_entry() { //set a random listen channel vIntChannel1 = (integer) llFrand(-2147483647.0) - 1; vIntL1 = llListen(vIntChannel1, "", NULL_KEY, ""); } touch_start(integer total_number) { //save current contents of description field to be able to restore it later vStrOldDesc = llGetObjectDesc(); //start listening for the response from the dialog llListenControl(vIntL1,TRUE); llDialog( llDetectedKey( 0 ), "Select an infohub to which to teleport.", ["Cancel"] + vListMenu, vIntChannel1 );
// Stop the second script to keep it's while loop from churning unnecessarily llSetScriptState(cStrOtherScriptName,FALSE); //Want to stop listening after 10 minutes in case ignore was clicked, the user takes too long, etc. llSetTimerEvent(600.0); }
listen( integer channel, string vStrNull, key vKeyNull, string vStrDest ) { // is it coming in on the expected channel if (channel == vIntChannel1) { if (vStrDest != "Cancel") { // put the region name and coordinates into the description field of the object //preceed the string with "%#^*@" so script B can identify that it's coming from here //of course this presumes that the original description did not start with that string integer vIntIndex = llListFindList(vListMenu,[vStrDest]); string vStrTempDesc = "%#^*@" + llList2String(vListRegions,vIntIndex) + "^#*" + (string) llList2Vector(vListCoordinates,vIntIndex); llSetObjectDesc(vStrTempDesc); //now that a selection has been made, reactivate the second script to process it. llSetScriptState(cStrOtherScriptName,TRUE); } else // if cancel was pressed stop the timer and reset the other script to get out of the while loop { llSetTimerEvent(0.0); llSetScriptState(cStrOtherScriptName,TRUE); llResetOtherScript(cStrOtherScriptName); } llListenControl(vIntL1,FALSE); } }
timer() { // reset the other script to get out of the while loop llSetScriptState(cStrOtherScriptName,TRUE); llResetOtherScript(cStrOtherScriptName); //stop listening llListenControl(vIntL1,FALSE); //restore the description field to its original contents llSetObjectDesc(vStrOldDesc); //Tell the user s/he took too long to respond llSay(0,"Menu timed out. Please try again."); //stop the timer llSetTimerEvent(0.0); } link_message(integer vIntSender, integer vIntNumb, string vStrStr, key vKeyId) { //message returned from the other script that it has completed successfully if (vIntNumb == 100) { //restore the description field to its original contents llSetObjectDesc(vStrOldDesc); //stop the timer llSetTimerEvent(0.0); } } }
And for completeness Script B again (which wasn't changed) // Script B - brings up the map
default { touch_start(integer total_number) { //This script will wait in the while loop until the description field changes to the expected string put there by script A // Script A will reset this script as needed if the expected string does not appear while (llGetSubString(llGetObjectDesc(),0,4) != "%#^*@") {} // get the string from the description field string vStrTempDesc = llDeleteSubString(llGetObjectDesc(),0,4); //parse it into the region name and vector coordinates list vListLocation = llParseString2List(vStrTempDesc,["^#*"],[]); string vStrRegion = llList2String(vListLocation,0); vector vVectorCoordinates = (vector) llList2String(vListLocation,1); //bring up the map llMapDestination( vStrRegion, vVectorCoordinates, ZERO_VECTOR ); //notify the main script that it is done so it can clean up llMessageLinked(LINK_THIS,100,"",NULL_KEY); } }
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
Speed reading has been shown to decrease comprehension
11-15-2007 19:11
But Jesse, the whole point of this exercise was to avoid that second touch.
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
11-15-2007 19:14
From: Monica Balut But Jesse, the whole point of this exercise was to avoid that second touch. Changed my sig to cover instances like this
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-15-2007 20:46
From: Jesse Barnett Changed my sig to cover instances like this lol I love it, and wish I'd thought of it first =)
_____________________
| | . "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... | - 
|
|
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
|
11-15-2007 21:17
but you didi!
|