Jump to content

Quistess Alpha

Resident
  • Posts

    3,801
  • Joined

  • Last visited

Everything posted by Quistess Alpha

  1. If I had to guess, perhaps there's some sort of naive show/hide system in the collar that (on some condition) turns everything in the linkset visible. The solution in that case would be to set the texture of the ball to the 100% transparent texture.
  2. FWIW, In some cases, an inconspicuous face that's color is set to black, or just a prim that's small and inside something else non-transparent, can serve the same role as a face that's completely transparent.
  3. If you could make it physical, you could use llPushObject() on it on land that doesn't have push disabled (I do not recommend doing so, but AFAIK it's the only method of affecting an object via script without the script being in that object) . I don't think you can make non-physical no-mod objects physical, but it's not impossible that llRezObjectWithParams allows setting that flag on no-mod objects (if it does, I'd consider that a bug to be honest.)
  4. my assumption would be dragging from inventory onto a face to change the texture (which is very error-prone, I highly recommend doing it via the build window instead). And in that case, the problem is that changed(integer c){ if(c&CHANGED_TEXTURE){ /*...*/} } provides no information to the script about ~how the textures have changed. AFAIK, the only solution would have to be a rather involved script-copy of the information about all texture-parameters of the object in global variables or (much more conveniently) Linkset Data.
  5. What's your organization's name, and what are some notable previous projects?
  6. This (the script in the OP, which as love suggests, is the same script twice, once unformatted and again with formatting) is verbatim a script I wrote near the end of 2020. It was meant as an example of how to utilize another script which presents a menu to the user to select a target from a list. The (following) script heavily utilizes code originally written by void singer. I don't recall if I fixed all the bugs, as doing this in a way that doesn't overflow llDialog's 512 byte limit for the message is somewhat non-trivial, but here is the matching script along with 2 other minor variations that were part of a set at the time: (FWIW, Qss stands for 'Q Sub Script') Qss2 Set Target (Agent) list gAgentList; list gLstMnu; // global list for the menu. integer gChannel; integer gListenHandle; // TODO: make this a strided handler,user list for multiple users. list uDlgBtnLst( integer vIdxPag ){ list vLstRtn; if ((gLstMnu != []) > 12){ //-- we have more than one possible page integer vIntTtl = -~((~([] != gLstMnu)) / 10); //-- Total possible pages integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10; //-- first menu index string vStrPag = llGetSubString( " ", 21 - vIdxPag, 21 ); //-- encode page number as spaces //-- get ten (or less for the last page) entries from the list and insert back/fwd buttons vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) + (list)(" »" + vStrPag); }else{ //-- we only have 1 page vLstRtn = gLstMnu; //-- just use the list as is } return //-- fix the order for [L2R,T2B] and send it out llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) + llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 ); }/*// Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/ string uList2nString(list l,integer offset) { integer index = llGetListLength(l); string sReturn; while(index>0) { index--; //string item = "secondlife:///app/agent/" + llList2String(l,index) + "/inspect"; string item = llGetDisplayName(llList2String(l,index)); sReturn = (string)(index+offset) + ") " + item + "\n" + sReturn; } return sReturn; } default { link_message(integer sender,integer n,string str,key who) { if(n==2) { gAgentList=llGetAgentList(AGENT_LIST_PARCEL,[]); /*fill gLstMnu with numbers from 0 to llGetListLength(AgentList)*/ integer index=0; integer max = llGetListLength(gAgentList); gLstMnu=[]; while(index<max) { gLstMnu+=(string)(index++); } gChannel = (integer)(llFrand(-1000000000.0) - 1000000000.0); gListenHandle = llListen(gChannel,"",who,""); list agents=gAgentList; if(llGetListLength(agents)>10) agents=llDeleteSubList(gAgentList,11,-1); llDialog( who, uList2nString(agents,0), uDlgBtnLst( 0 ), gChannel ); llSetTimerEvent(60); // 60 second timeout } } listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){ if (!llSubStringIndex( vStrMsg, " " )) { //-- detects (hidden) leading non-breaking space of page change buttons integer vIdxPage = ( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ); integer vIdxBgn = 0; if(vIdxPage !=0) { /* calculate the index of the first item in list for this page*/ integer vIntTtl = -~((~([] != gLstMnu)) / 10); vIdxBgn = (vIdxPage = (vIntTtl + vIdxPage) % vIntTtl) * 10; //-- first menu index } llDialog( vKeySpk, uList2nString( llList2List(gAgentList,vIdxBgn, vIdxBgn+9),vIdxBgn ), uDlgBtnLst(vIdxPage), vIntChn ); }else { //-- button was not a page button, your code goes here, //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present //integer vIdxPage=(llListFindList( gLstMnu, (list)vStrMsg ) / 10); llListenRemove(gListenHandle); ///*DEBUG*/llSay(0,"Test! "+(string)llList2Key(gAgentList,(integer)vStrMsg)); llMessageLinked(LINK_THIS,-2,"",llList2Key(gAgentList,(integer)vStrMsg)); } } timer() { llListenRemove(gListenHandle); llSetTimerEvent(0); } } Qss01 Set Target (sensor) list gAgentList; list gLstMnu; // global list for the menu. key gWho; //who is using menu. integer gChannel; integer gListenHandle; // TODO: make this a strided handler,user list for multiple users. list uDlgBtnLst( integer vIdxPag ){ list vLstRtn; if ((gLstMnu != []) > 12){ //-- we have more than one possible page integer vIntTtl = -~((~([] != gLstMnu)) / 10); //-- Total possible pages integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10; //-- first menu index string vStrPag = llGetSubString( " ", 21 - vIdxPag, 21 ); //-- encode page number as spaces //-- get ten (or less for the last page) entries from the list and insert back/fwd buttons vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) + (list)(" »" + vStrPag); }else{ //-- we only have 1 page vLstRtn = gLstMnu; //-- just use the list as is } return //-- fix the order for [L2R,T2B] and send it out llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) + llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 ); }/*// Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/ string uList2nString(list l,integer offset) { integer index = llGetListLength(l); string sReturn; while(index>0) { index--; //string item = "secondlife:///app/agent/" + llList2String(l,index) + "/inspect"; string item = llKey2Name(llList2String(l,index)); sReturn = (string)(index+offset) + ") " + item + "\n" + sReturn; } return sReturn; } default { link_message(integer sender,integer n,string str,key who) { if(n==1) { gWho=who; llSensor("",NULL_KEY,(AGENT|PASSIVE|ACTIVE),32.0,PI); } } sensor(integer detectedN) { llSay(0,"DEBUG!"); gAgentList=[]; while(detectedN-- >0) gAgentList+=llDetectedKey(detectedN); /*fill gLstMnu with numbers from 0 to llGetListLength(AgentList)*/ integer index=0; integer max = llGetListLength(gAgentList); gLstMnu=[]; while(index<max) { gLstMnu+=(string)(index++); } gChannel = (integer)(llFrand(-1000000000.0) - 1000000000.0); gListenHandle = llListen(gChannel,"",gWho,""); list agents=gAgentList; if(llGetListLength(agents)>10) agents=llDeleteSubList(gAgentList,11,-1); llDialog( gWho, uList2nString(agents,0), uDlgBtnLst( 0 ), gChannel ); llSetTimerEvent(60); // 60 second timeout } listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){ if (!llSubStringIndex( vStrMsg, " " )) { //-- detects (hidden) leading non-breaking space of page change buttons integer vIdxPage = ( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ); llDialog( vKeySpk, uList2nString( llDeleteSubList(gAgentList,(10*vIdxPage) + 11, (10*vIdxPage) -1),10*vIdxPage ), uDlgBtnLst(vIdxPage), vIntChn ); }else { //-- button was not a page button, your code goes here, //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present //integer vIdxPage=(llListFindList( gLstMnu, (list)vStrMsg ) / 10); llListenRemove(gListenHandle); ///*DEBUG*/llSay(0,"Test! "+(string)llList2Key(gAgentList,(integer)vStrMsg)); llMessageLinked(LINK_THIS,-1,"",llList2Key(gAgentList,(integer)vStrMsg)); } } timer() { llListenRemove(gListenHandle); llSetTimerEvent(0); } } Qss3 Select From List list gItemList; list gLstMnu; // global list for the menu. integer gChannel; integer gListenHandle; // TODO: make this a strided handler,user list for multiple users. list uDlgBtnLst( integer vIdxPag ){ list vLstRtn; if ((gLstMnu != []) > 12){ //-- we have more than one possible page integer vIntTtl = -~((~([] != gLstMnu)) / 10); //-- Total possible pages integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10; //-- first menu index string vStrPag = llGetSubString( " ", 21 - vIdxPag, 21 ); //-- encode page number as spaces //-- get ten (or less for the last page) entries from the list and insert back/fwd buttons vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) + (list)(" »" + vStrPag); }else{ //-- we only have 1 page vLstRtn = gLstMnu; //-- just use the list as is } return //-- fix the order for [L2R,T2B] and send it out llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) + llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 ); }/*// Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/ string uList2nString(list l,integer offset) { integer index = llGetListLength(l); string sReturn; while(index>0) { index--; //string item = "secondlife:///app/agent/" + llList2String(l,index) + "/inspect"; string item = llList2String(l,index); sReturn = (string)(index+offset) + ") " + item + "\n" + sReturn; } return sReturn; } default { link_message(integer sender,integer n,string str,key who) { if(n==3) { gItemList=llParseString2List(str,[";"],[]); /*fill gLstMnu with numbers from 0 to llGetListLength(AgentList)*/ integer index=0; integer max = llGetListLength(gItemList); gLstMnu=[]; while(index<max) { gLstMnu+=(string)(index++); } gChannel = (integer)(llFrand(-1000000000.0) - 1000000000.0); gListenHandle = llListen(gChannel,"",who,""); list items=gItemList; if(llGetListLength(items)>10) items=llList2List(gItemList,0,10); llDialog( who, uList2nString(items,0), uDlgBtnLst( 0 ), gChannel ); llSetTimerEvent(60); // 60 second timeout } } listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){ if (!llSubStringIndex( vStrMsg, " " )) { //-- detects (hidden) leading non-breaking space of page change buttons integer vIdxPage = ( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ); integer vIdxBgn = 0; if(vIdxPage !=0) { /* calculate the index of the first item in list for this page*/ integer vIntTtl = -~((~([] != gLstMnu)) / 10); vIdxBgn = (vIdxPage = (vIntTtl + vIdxPage) % vIntTtl) * 10; //-- first menu index } llDialog( vKeySpk, uList2nString( llList2List(gItemList,vIdxBgn, vIdxBgn+9),vIdxBgn ), uDlgBtnLst(vIdxPage), vIntChn ); }else { //-- button was not a page button, your code goes here, //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present //integer vIdxPage=(llListFindList( gLstMnu, (list)vStrMsg ) / 10); llListenRemove(gListenHandle); ///*DEBUG*/llSay(0,"Test! "+(string)llList2Key(gAgentList,(integer)vStrMsg)); llMessageLinked(LINK_THIS,-3,llList2String(gItemList,(integer)vStrMsg),""); } } timer() { llListenRemove(gListenHandle); llSetTimerEvent(0); } } If I were to re-do this in 2024, I would use linksetData to pass the request and result to/from the 'sub-script' synchronously, and also leverage linkset data for string bytelength checking (why we can't easily get a string's bytelengh directly is beyond me).
  7. https://www.lovense.com/game/lovense-viewer/?_utm_pro=2401081632& seems this is just the standard LL viewer with a fancy lovense button. Is it possible other viewers might incorporate whatever functionality it adds?
  8. I'm too lazy to test, but Cool VL Viewer sometimes handles this kind of thing differently. Last time I checked, with that viewer it's possible to directly edit scripts in objects owned by other people (assuming you have permission to do so) whereas other viewers I tested at the time, you have to drag the script to your inventory and then back into the object after editing.
  9. AFAIK you need to drag the object from the object's inventory into your own inventory, then from your inventory into the world; you can't 'manually' rez from object inventory.
  10. For ease of use, I generally prefer llListenControl with a static listener. There are pros and cons to this approach though. integer gHandleListen; integer gChannelListen = -17; key gToucher; default { state_entry() { gHandleListen = llListen(gChannelListen,"","",""); llListenControl(gHandleListen,FALSE); } touch_end(integer n) { if(gToucher) { llRegionSayTo(llDetectedKey(0),0,"Menu is in-use."); }else { llListenControl(gHandleListen,TRUE); llSetTimerEvent(30.0); llTextBox(gToucher=llDetectedKey(0),"Please type new description:",gChannelListen); } } timer() { llSetTimerEvent(0); gToucher=NULL_KEY; llListenControl(gHandleListen,FALSE); } listen(integer chan, string name, key ID, string text) { llRegionSayTo(gToucher,0,"Setting description to '"+text+"'."); llSetObjectDesc(text); llSetTimerEvent(0); // alternatively, set to 0.02 to execute listen close procedure. gToucher = NULL_KEY; llListenControl(gHandleListen,FALSE); } }
  11. A subtle point, but after making the changes suggested by Love and Elleevelyn, you should also call llListenRemove(dialogHandle); at the beginning of your open_menu() function. Otherwise, if the prim is touched 64 times while menu is open (perhaps split across multiple times the menu is opened), the script will accumulate an unclosed listener for each one and crash. unclear why this is in the script. channel 624 is never listened to, and this listener is never closed, which again, will crash the script eventually.
  12. a year or two ago, I played with the idea of making a system where you could move/rotate prims and eventually it would spit out an animation you could upload to apply to your avatar, but that's still at least 65 Land impact, and would be expensive to use on the main grid rather than the beta grid for getting things just so.
  13. when you're scripting in a somewhat cluttered space, it's easy to accidentally move a script into something you don't intend to have a script in it (ex. the wall of your house) Sure would be nice if SL had a function to list all scripts in an area/parcel, but I digress. . .
  14. As far as I can tell the script is working exactly as designed. I would have implemented this with llListenControl, rather than re-declaring the listener for every transaction, but the script as written avoids most of the easy pitfalls of the method. (one nitpick: you may want to move the llSetTimerEvent from line 28 to outside the if condition.) What steps do you do, and what happens? How is what happens different from what you expect to happen? (my interaction tests:) Timeout: /12 Test <no response> (correct behavior) <touch the prim> (I removed the UV coordinate check from the script) Object: Please type in chat /12 YourNewNickname. Or type /12 Reset to reset your name. <wait 30 seconds> Object: : I am not listening anymore. /12 Test <no response> (correct behavior) take one input: <touch the prim> (I removed the UV coordinate check from the script) Object: Please type in chat /12 YourNewNickname. Or type /12 Reset to reset your name. /12 test Object: : Nickname set. No longer listening. /12 test <no response> (correct behavior)
  15. you only need one sensor for the whole system of tiles, and you can turn the sensor off when it detects nothing, only turn it on after the collision_start event detects an avatar. That's actually a good idea, using texture animation to do the fade in/out. It might be a bit of a pain to control though.
  16. my mistake in not correcting all instances of the mistake. In the above line, 'menu_handler' should be 'menu_channel'.
  17. Use Avastar, Qavimator (doesn't do bento bones), the black dragon viewer's poser, or the other alternative I'm specifically not mentioning. Anything you commission someone to build for you will be of lower quality (initially, quality could be improved with continued time and investment), take at least a year of development, and cost you (at least) thousands of dollars.
  18. The script is confusing the channel and the listen handle. One way of fixing that might be: string animation = "MOAN_STOP-EYES"; // Nom de l'animation à jouer integer menu_channel = -17; integer menu_handler; default { state_entry() { llSetTouchText("Cliquez ici pour ouvrir le menu"); // Texte lorsqu'on touche le prim // Création du menu menu_handler = llListen(menu_channel, "", llGetOwner(), ""); llListenControl(menu_handler,FALSE); } touch_start(integer total_number) { llOwnerSay("Ouverture du menu..."); // Message dans le chat du propriétaire // Création du menu llListenControl(menu_handler,TRUE); llSetTimerEvent(60.0); llDialog(llDetectedKey(0), "Choisissez une option :", ["Jouer Animation", "Arrêter Animation"], menu_handler); } listen(integer channel, string name, key id, string message) { //if (channel == menu_handler) // not needed, but was wrong, should be //if(channel == menu_channel) // instead. //{ if (message == "Jouer Animation") { llStartAnimation(animation); } else if (message == "Arrêter Animation") { llStopAnimation(animation); } llListenControl(menu_handler,FALSE); //} } timer() { llListenControl(menu_handler,FALSE); llSetTimerEvent(0); } }
  19. Weird. updating a listing for an item shown in the viewer but not on the website does nothing. ETA: links for items not accessible via search are still valid. Ex. you cannot find https://marketplace.secondlife.com/p/Shoulder-deformer/23762200 via search.
  20. Given occam's razor, I'd have to assume they'd just place a link to their online website storefront in SL, perhaps on an easily clickable prim. Without a 'to-complicated to be worth it' setup to infer some association, they wouldn't know if you came from SL, or just found the site through some other method. If you have your conspiracy hat on, you (the hypothetical potential buyer) could even just find the link in SL, wait 5~10 minutes then copy-paste it into your external web-browser of choice.
  21. Yes and the solution is the same, you use colision_start to increment the count, colision_end to decrement it, but also use a sensor or llGetAgentList() to 'sanity check' whether the avatars you think are colliding with the prim, are actually still doing so. Some impromptu testing is showing a collision_end event when the avatar stops moving, even if they are still on the 'floor'. if that weren't the case, this would work: // N.B. Sensor can only keep track of 16 (or is it 32?) avatars max. float gSensorRange = 10.0; list gColliders; //integer count; // use llGetListLength(gColliders); instead default { collision_start(integer n) { llSay(0,"Collision."); while(~--n) { key collider = llDetectedKey(n); if(llGetAgentSize(collider)) // is an avatar { if(-1==llListFindList(gColliders,[collider])) // prevent a (improbable) double-entry. { gColliders+=collider; } } } llOwnerSay((string)llGetListLength(gColliders)); //count = llGetListLength(gColliders); llSensorRepeat("","",AGENT,gSensorRange,PI,0.5); } collision_end(integer n) { while(~--n) { key collider = llDetectedKey(n); integer index= llListFindList(gColliders,[collider]); if(-1!=index) { gColliders = llDeleteSubList(gColliders,index,index); } } llOwnerSay("End collision: "+(string)llGetListLength(gColliders)); //count = llGetListLength(gColliders); } sensor(integer n) { integer found; while(~--n) { integer index = llListFindList(gColliders,[llDetectedKey(n)]); if(-1!=index) { found = found|(1<<index); } } integer indexCollider = llGetListLength(gColliders); if(found!= (1<<indexCollider)-1 ) { llInstantMessage(llGetOwner(),"Lost an avatar to logout or teleport."); // debug. while(~--indexCollider) { key collider = llList2Key(gColliders,indexCollider); if((~found)&(1<<indexCollider)) { gColliders = llDeleteSubList(gColliders,indexCollider,indexCollider); } } } //count = llGetListLength(gColliders); } no_sensor() { gColliders = []; llSensorRemove(); // count = 0; } touch_start(integer total_number) { llSay(0, "There are "+(string)llGetListLength(gColliders)+" avatar(s) colliding with me." ); } }
  22. AFAIK it's allowed if you do it on your own land. Wikipedia even has a list of RL business that were in SL (picking through at random, all of them seem defunct.) https://en.wikipedia.org/wiki/Businesses_and_organizations_in_Second_Life#cite_note-40
  23. Indeed, doesn't seem to be released yet, on Dec. 11, they had planned to release it Dec. 13, *shrugs*
  24. An alternate way of approaching this is to llSensorRepeat() for avatars in-range, and then set the glow for the panel under their feet. If you turn off the sensor when nobody's in range, and only turn it on when an avatar collides with the system, it's reasonably efficient. . . . funnily enough it seems the last time I touched the version I made was a year and a day ago. I'd post the script, but it's specific to custom mesh and (retrospect being 20/20) the style is a bit cryptic.
×
×
  • Create New...