Jump to content

Lymirah Gardner

Resident
  • Posts

    10
  • Joined

  • Last visited

Everything posted by Lymirah Gardner

  1. Hello again! Apologies for the delay. I wanted to let you know that I haven't forgotten about the script. I just spent the last 4 hours learning how to offset textures. Such fun. I *think* I understand how to code it correctly now, though I have absolutely no idea why it's set up the way it is. Boggles the mind. And the wiki documentation on [PRIM_TEXTURE] was incredibly unhelpful - ended up puzzling it out by trial & error. Which was reeeeeeally annoying. I'll get back to you when I've got a working prototype. While I've sort of puzzled out how the repeat works, it's going to be extremely annoying to extend it to a random subset. I don't have the equation yet and I don't see it, though I see the pattern. Maybe. I hope. Ugh.
  2. Thanks, Rolig! I keep forgetting about non-chat controls. I wrote the listing one first, but then realized that I wanted the face number, too. I'll edit the main post to indicate yours.
  3. This was probably the first moderately complicated script I wrote. It stems from my burlesque performances and my desire to demystify some of the scripting abilities for other performers. In other words, I wanted to give them a powerful, somewhat easy-to-use script that might enable them to achieve effects they could not otherwise realize without a deeper (or any) knowledge of LSL. I have no idea if it was successful with this goal, but I do want to share it with others. The script toggles appearance (hide/show) of object1 with a command on a so-called "common" channel. Enables control of multiple such objects on a single channel. Commands are not case-sensitive. Initial state of object1 (hidden/shown) set by global variable. Enables fading in/out of object1. Assumes even change of alpha setting over the duration. Can have different fade in/fade out speeds. Chat commands entered during (in the middle of) a fade in or fade out will not be acted on. Can use a single command to toggle multiple objects/linksets (each having their own version of the script), such as fading out object1 while fading in object2. Everything is controlled/set via global variables. The script is purposefully written to be a bit bloated (bound checking, redundancy on achieving the desired alpha, etc.). Remember - it was written for the non-scripter and for use in a temporary setting (a burlesque performance. If using this as a scripter, I encourage you to modify it and remove some of the bloat - it should be recognizable (the user function "checkgvar()" is pure bound-checking; the user-function "setcvar()" can be reduced to eliminate the bound-checking; better yet the entire script can be tailored to the specific use, removing unused parts). The biggest extensible point for this script is to enable per-link number control so that it can operate within a linkset by fading in/out only parts of the linkset. While I've put together such a version for my personal use, I decided only to release the simple-user version below. A scripter should be able to tailor this to per-link number control. If you want any assistance with this, hit me up in SL (notecard if offline, IM if online) or send me a private message (and hope I remember to sign in soon and see it). I've tested the script for the identified functionality and it appears to work correctly. (Believe me, I tried to troubleshoot this sucker as best I could.) If anyone has any recommendations, either for the existing code or additional features, please let me know! ///////////////////////////////////////////////////////////////////////////////////////////////////// // // Object Appearance Script by Lymirah Gardner, Version 1.2b, 12 March 2012 // Channel Commands for Having an Object/Linkset Appear and/or Disappear // //<----------------------- STRETCH YOUR WINDOW THIS WIDE FOR EASY READING ------------------------>// // // Script for object1/linkset1 (referred to herein as "object1"). // Works for a single object or an entire linkset. // // Toggles appearance (hide/show) of object1 with a command on a so-called "common" channel. // Enables control of multiple such objects on a single channel. Commands are not case-sensitive. // Initial state of object1 (hidden/shown) set by global variable. // Enables fading in/out of object1. Assumes even change of alpha setting over the duration. // Can have different fade in/fade out speeds. // Chat commands entered during (in the middle of) a fade in or fade out will not be acted on. // // Currently set up only for owner control. // Extensible to per-link item (e.g., per-prim) control. // // OPERATION: // // Type this in local: To do this: Example: // --------------------------------------------------------------------------------------- // /CHANNEL commhide Hide object 1 while it is shown. /42 object2 // /CHANNEL commshow Show object 1 while it is hidden. /42 object1 // /CHANNEL commreset Reset script while object1 is hidden or shown. /42 reset // // FIRST EXAMPLE WITH TWO OBJECTS: // // Set object1 to show at the start, hide with command "object2" and show with command "object1". // Set object2 to hide at the start, show with command "object2" and hide with command "object1". // At start, object1 is shown and object2 is hidden. // When you type "/42 object2" in local chat, object1 will hide and object2 will show. // When you type "/42 object1" in local chat, object1 will show and object2 will hide. // When you type "/42 reset" in local chat, both will revert to their initial states. // // SECOND EXAMPLE WITH TWO OBJECTS: // // Assume you changed the first example above such that object2 does not hide again. // This is accomplished by changing a variable (HIDEOBJ_ON = 0) in the script for object2. // The script for object1 remains the same since its operation is the exact same. // When you type "/42 object2" in local chat, object1 will hide and object2 will show. // When you type "/42 object1" in local chat, object1 will show. Object2 will remain showing. // (This command now has no effect on the state of object2 – whether it is shown or hidden.) // When you type "/42 reset" in local chat, both will revert to their initial states. // // Note that in all of the above examples, the commands will only have an effect if the respective // object is in the opposite state. That is, the command to hide object1 will have no effect on // object1 if object1 is already hidden when the command is given. // ///////////////////////////////////////////////////////////////////////////////////////////////////// // // Please feel free to share this script. It's meant for anyone and everyone! All I ask is that // you don't sell the script on its own or as part of any package, objects or products. It's // provided for free - please keep it that way! Please also keep this title box. // ///////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES ///////////////////////////////////////////////////////////////////////////////////////////////////// //***Main Controls*** integer CHANNEL = 42; //set listen channel number: CHANNEL > 0 integer HIDE_START = 0; //toggles whether object1 is shown or hidden at start: //0 = shown, 1 = hidden string commreset = "reset"; //chat command to reset script //***Show Object Attributes*** integer SHOWOBJ_ON = 1; //toggles whether object is shown on command: 0 = off, 1 = on string commshow = "object2"; //chat command to show object1 integer FADEIN_ON = 0; //toggles fading of object on show: 0 = off, 1 = on integer FADEIN_SPD = 1; //speed of fade in: 0 = custom, 1 = slow, 2 = medium, 3 = fast //slow: 10 steps over 5 seconds //medium: 6 steps over 3 seconds //fast: 5 steps over 1 second //***Hide Object Attributes*** integer HIDEOBJ_ON = 1; //toggles whether object is hidden on command: 0 = off, 1 = on string commhide = "object1"; //chat command to hide object1 integer FADEOUT_ON = 0; //toggles fading of object on hide: 0 = off, 1 = on integer FADEOUT_SPD = 1; //speed of fade out: 0 = custom, 1 = slow, 2 = medium, 3 = fast //slow: 10 steps over 5 seconds //medium: 6 steps over 3 seconds //fast: 5 steps over 1 second ///////////////////////////////////////////////////////////////////////////////////////////////////// // CUSTOM FADING ///////////////////////////////////////////////////////////////////////////////////////////////////// //***Change these variables if custom fade in is used.*** float SHOW_CALPHA = 1.0; //alpha of object when shown: 1.0 = normal/fully shown //0.0 < SHOW_CALPHA <= 1.0 and HIDE_CALPHA < SHOW_CALPHA integer FADEIN_CSTEPS = 20; //custom fade in: number of steps/increments //FADEIN_CTEPS >= 1 float FADEIN_CTIME = 10.0; //custom fade in: time for fade (in seconds) //FADEIN_CTIME >= 1.0 //***Change these variables if custom fade out is used.*** float HIDE_CALPHA = 0.0; //alpha of object when hidden: 0.0 = normal/fully hidden //0.0 <= HIDE_CALPHA < 1.0 and HIDE_CALPHA < SHOW_CALPHA integer FADEOUT_CSTEPS = 20; //custom fade out: number of steps/increments //FADEOUT_CTEPS >= 1 float FADEOUT_CTIME = 10.0; //custom fade out: time for fade (in seconds) //FADEOUT_CTIME >= 1.0 //For custom alpha settings, set both custom alphas (SHOW_CALPHA and HIDE_CALPHA) //even if only using one of custom fade in or custom fade out. //Even if only using one of custom fade in or custom fade out, alpha settings are pulled //from both custom alpha settings (SHOW_CALPHA and HIDE_CALPHA). ///////////////////////////////////////////////////////////////////////////////////////////////////// // DON'T CHANGE ANYTHING BELOW THIS UNLESS YOU KNOW WHAT YOU'RE DOING! ///////////////////////////////////////////////////////////////////////////////////////////////////// //***Other Variables*** key owner; //tracks current owner integer LISTEN_ID; //enables release of listens integer INIT_RUN = 0; //tracks how many times init() has run integer MAX_INIT = 2; //sets max number of times init() can run (default 2) integer bug = 0; //triggers bugged state from a user-defined function integer OBJSHOW; //tracks if object is shown (1) or hidden (0) //only used for default state, remains for debugging if needed float SHOW_ALPHA = 1.0; //default show alpha setting (1.0) float HIDE_ALPHA = 0.0; //default hide alpha setting (0.0) integer FADEIN_STEPS; //number of fade in increments float FADEIN_TIME; //fade in time increment, NOT overall time float FADEIN_ALPHA; //fade in alpha increment, NOT overall alpha integer FADEOUT_STEPS; //number of fade out increments float FADEOUT_TIME; //fade out time increment, NOT overall time float FADEOUT_ALPHA; //fade out alpha increment, NOT overall alpha // LEARNING LESSON NOTE: I had to redo the trigger (event) in the default state to accommodate // ownership change. This entailed redoing the architecture of the whole state-based system. // Initially I had the default state just proceeding to the correct state, with chat commands in // each state triggering object alpha change directly. Instead, now object alpha change occurs at // state entry and chat commands subsequently trigger state change. This enables a listen event in // default state to trigger initial state change after ownership update. // SECOND NOTE: This kind of architecture is probably due to the nature of the script. Most // public scripts (e.g., chairs) respond to the user, not the owner per se. In addition, I'm using // chat commands as triggers instead of something firmer like a touch event. //***USER-DEFINED FUNCTIONS*** checkgvar() { //checks global variables for compliance with bounds if(CHANNEL<=0) { llOwnerSay("***Bad value! CHANNEL <= 0 (Error UD-CV01)***"); bug=1; } integer CHECK = 0; if(HIDE_START == 0) CHECK = 1; else if(HIDE_START == 1) CHECK = 1; if(CHECK == 0) { llOwnerSay("***Bad value! HIDE_START != 0 or 1 (Error UD-CV02)***"); bug=1; } CHECK = 0; if(SHOWOBJ_ON == 0) CHECK = 1; else if(SHOWOBJ_ON == 1) CHECK = 1; if(CHECK == 0) { llOwnerSay("***Bad value! SHOWOBJ_ON != 0 or 1 (Error UD-CV03)***"); bug=1; } CHECK = 0; if(FADEIN_ON == 0) CHECK = 1; else if(FADEIN_ON == 1) CHECK = 1; if(CHECK == 0) { llOwnerSay("***Bad value! FADEIN_ON != 0 or 1 (Error UD-CV04)***"); bug=1; } CHECK = 0; if(HIDEOBJ_ON == 0) CHECK = 1; else if(HIDEOBJ_ON == 1) CHECK = 1; if(CHECK == 0) { llOwnerSay("***Bad value! HIDEOBJ_ON != 0 or 1 (Error UD-CV05)***"); bug=1; } CHECK = 0; if(FADEOUT_ON == 0) CHECK = 1; else if(FADEOUT_ON == 1) CHECK = 1; if(CHECK == 0) { llOwnerSay("***Bad value! FADEOUT_ON != 0 or 1 (Error UD-CV06)***"); bug=1; } } setcvar() { //checks & sets custom variables if either custom is in use if(SHOW_CALPHA>1.0) { llOwnerSay("***Bad value! SHOW_CALPHA > 1.0 (Error UD-SV01)***"); bug=1; } else if(SHOW_CALPHA<=0.0) { llOwnerSay("***Bad value! SHOW_CALPHA <= 0.0 (Error UD-SV02)***"); bug=1; } else if(HIDE_CALPHA<0.0) { llOwnerSay("***Bad value! HIDE_CALPHA < 0.0 (Error UD-SV03)***"); bug=1; } else if(HIDE_CALPHA>=1.0) { llOwnerSay("***Bad value! HIDE_CALPHA >= 1.0 (Error UD-SV04)***"); bug=1; } else if(SHOW_CALPHA<=HIDE_CALPHA) { llOwnerSay("***Bad value! SHOW_CALPHA <= HIDE_CALPHA (Error UD-SV05)***"); bug=1; } if(FADEIN_ON == 1 && bug == 0) { if(FADEIN_SPD == 0) { if(FADEIN_CSTEPS<1) { llOwnerSay("***Bad value! FADEIN_CSTEPS < 1 (Error UD-SV06)***"); bug=1; } else if(FADEIN_CTIME<1.0) { llOwnerSay("***Bad value! FADEIN_CTIME < 1.0 (Error UD-SV07)***"); bug=1; } if(bug == 0) { SHOW_ALPHA = SHOW_CALPHA; HIDE_ALPHA = HIDE_CALPHA; FADEIN_STEPS = FADEIN_CSTEPS; FADEIN_ALPHA = (SHOW_CALPHA-HIDE_CALPHA) / (float)FADEIN_CSTEPS; FADEIN_TIME = FADEIN_CTIME / (float)FADEIN_CSTEPS; } } else if(FADEIN_SPD == 1) { //10 steps over 5 seconds, assumes normal alphas for show/hide FADEIN_STEPS = 10; // = given FADEIN_ALPHA = 0.1; // = delta-alpha / steps = 1.0 / steps FADEIN_TIME = 0.5; // = total-time / steps } else if(FADEIN_SPD == 2) { //6 steps over 3 seconds, assumes normal alphas for show/hide FADEIN_STEPS = 6; FADEIN_ALPHA = 0.2; FADEIN_TIME = 0.5; } else if(FADEIN_SPD == 3) { //5 steps over 1 second, assumes normal alphas for show/hide FADEIN_STEPS = 5; FADEIN_ALPHA = 0.2; FADEIN_TIME = 0.2; } else { llOwnerSay("***Bad value! FADEIN_SPD != 0,1,2,3 (Error UD-SV08)***"); bug=1; } } if(FADEOUT_ON == 1 && bug == 0) { if(FADEOUT_SPD == 0) { if(FADEOUT_CSTEPS<1) { llOwnerSay("***Bad value! FADEOUT_CSTEPS < 1 (Error UD-SV9)***"); bug=1; } else if(FADEOUT_CTIME<1.0) { llOwnerSay("***Bad value! FADEOUT_CTIME < 1.0 (Error UD-SV10)***"); bug=1; } if(bug == 0) { SHOW_ALPHA = SHOW_CALPHA; HIDE_ALPHA = HIDE_CALPHA; FADEOUT_STEPS = FADEOUT_CSTEPS; FADEOUT_ALPHA = (SHOW_CALPHA-HIDE_CALPHA) / (float)FADEOUT_CSTEPS; FADEOUT_TIME = FADEOUT_CTIME / (float)FADEOUT_CSTEPS; } } else if(FADEOUT_SPD == 1) { //10 steps over 5 seconds, assumes normal alphas for show/hide FADEOUT_STEPS = 10; FADEOUT_ALPHA = 0.1; FADEOUT_TIME = 0.5; } else if(FADEOUT_SPD == 2) { //6 steps over 3 seconds, assumes normal alphas for show/hide FADEOUT_STEPS = 6; FADEOUT_ALPHA = 0.2; FADEOUT_TIME = 0.5; } else if(FADEOUT_SPD == 3) { //5 steps over 1 second, assumes normal alphas for show/hide FADEOUT_STEPS = 5; FADEOUT_ALPHA = 0.2; FADEOUT_TIME = 0.2; } else { llOwnerSay("***Bad value! FADEOUT_SPD != 0,1,2,3 (Error UD-SV11)***"); bug=1; } } } init() { //ensures proper ownership update on change if(INIT_RUN < MAX_INIT) { //prevents this from running more than MAX_INIT times owner = llGetOwner(); llListenRemove(LISTEN_ID); LISTEN_ID = llListen(CHANNEL,"",owner,""); ++INIT_RUN; } } //***START HERE: DEFAULT STATE RUNS ONCE ON OBJECT REZ OR SCRIPT RESET*** default { state_entry() { string temp = llStringTrim(commshow,STRING_TRIM); commshow = llToUpper(temp); //trim and capitalize commshow temp = llStringTrim(commhide,STRING_TRIM); commhide = llToUpper(temp); //trim and capitalize commhide temp = llStringTrim(commreset,STRING_TRIM); commreset = llToUpper(temp); //trim and capitalize commreset checkgvar(); //check g variables for compliance if(bug == 1) { //trigger bug if checkgvar() fails llListenRemove(LISTEN_ID); state bugged; } if(FADEIN_ON == 1 || FADEOUT_ON == 1) setcvar(); //check & set c variables if any fading if(bug == 1) { //trigger bug if check in setcvar() fails llListenRemove(LISTEN_ID); state bugged; } if(HIDE_START == 1) { //set correct start based on HIDE_START llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); OBJSHOW = 0; } else { llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); OBJSHOW = 1; } init(); } on_rez(integer start_param) { init(); } changed(integer change) { if(change & CHANGED_OWNER) { init(); } } listen (integer channel, string name, key id, string command) { string temp = llStringTrim(command,STRING_TRIM); command = llToUpper(temp); if(command == commshow && OBJSHOW == 0) { llListenRemove(LISTEN_ID); state showme; } else if(command == commhide && OBJSHOW == 1) { llListenRemove(LISTEN_ID); state hideme; } else if(command == commreset) { llListenRemove(LISTEN_ID); llResetScript(); } } } //***WHEN OBJECT IS TO BE SHOWN*** state showme { state_entry() { if(FADEIN_ON == 0) { llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); OBJSHOW = 1; } else { integer i; float ALPHA_TEMP; integer ONCERUN = 0; for(i=1;i<=FADEIN_STEPS;++i) { ALPHA_TEMP = (float)i * FADEIN_ALPHA; if(ALPHA_TEMP<=1.0 && ALPHA_TEMP>0.0) { if(i==1) ONCERUN = 1; llSetLinkAlpha(LINK_SET, ALPHA_TEMP, ALL_SIDES); llSleep(FADEIN_TIME); } } if(ALPHA_TEMP <= 0.0) llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); else if(ALPHA_TEMP > 1.0) llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); if(ALPHA_TEMP != SHOW_ALPHA) llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); if(ONCERUN == 0) llSetLinkAlpha(LINK_SET, SHOW_ALPHA, ALL_SIDES); OBJSHOW = 1; } LISTEN_ID = llListen(CHANNEL, "", owner, ""); } listen (integer channel, string name, key id, string command) { string temp = llStringTrim(command,STRING_TRIM); command = llToUpper(temp); if(command == commhide && HIDEOBJ_ON == 1) { llListenRemove(LISTEN_ID); state hideme; } else if(command == commreset) { llListenRemove(LISTEN_ID); llResetScript(); } } } //***WHEN OBJECT IS TO BE HIDDEN*** state hideme { state_entry() { if(FADEOUT_ON == 0) { llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); OBJSHOW = 0; } else { integer i; float ALPHA_TEMP; integer ONCERUN = 0; for(i=FADEOUT_STEPS;i>0;--i) { ALPHA_TEMP = ((float)i - 1.0) * FADEOUT_ALPHA; if(ALPHA_TEMP>=0.0 && ALPHA_TEMP<1.0) { if(i==FADEOUT_STEPS) ONCERUN = 1; llSetLinkAlpha(LINK_SET, ALPHA_TEMP, ALL_SIDES); llSleep(FADEOUT_TIME); } } if(ALPHA_TEMP < 0.0) llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); else if(ALPHA_TEMP >= 1.0) llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); if(ALPHA_TEMP != HIDE_ALPHA) llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); if(ONCERUN == 0) llSetLinkAlpha(LINK_SET, HIDE_ALPHA, ALL_SIDES); OBJSHOW = 0; } LISTEN_ID = llListen(CHANNEL, "", owner, ""); } listen (integer channel, string name, key id, string command) { string temp = llStringTrim(command,STRING_TRIM); command = llToUpper(temp); if(command == commshow && SHOWOBJ_ON == 1) { llListenRemove(LISTEN_ID); state showme; } else if(command == commreset) { llListenRemove(LISTEN_ID); llResetScript(); } } } //***BAD VARIABLE VALUE SOMEWHERE*** state bugged { state_entry() { llOwnerSay("***Script operation terminated!***"); } }
  4. This one's a two-fer -- two scripts for the price of none! Since both scripts relate to getting link numbers of prims in a build, I'm including them in a single post. The genesis for these was my frustration upon learning that the displayed "link number" in the edit window has no connection to the actual link number of the prim. *sigh* Makes you wonder, eh? Obviously these are meant for builders. They're of limited (no?) use for non-builders. This is why both scripts include a scrub command to delete the script. While anyone can trigger the chat commands, only the owner can delete the script. I suppose one point of extensibility could be to make the chat commands only respond to the owner. Unless it becomes a problem, I'd go with fewer checks for now. (Building is laggy enough as it is.) I've tested both scripts for the identified functionality and they appear to work correctly. If anyone has any recommendations, either for the existing code or additional features, please let me know! EDIT: Check out Rolig Loon's script in her reply below. Renders my first one obsolete in a very elegant way. (1) GET NUMBER ON TOUCH In response to a touch (by anyone), this script whispers the owner with the link number and/or face number of the touched prim/face. Script includes reset and scrub commands on channel 314 (e.g., "/314 reset" or "/314 scrub"). Scrub is only after confirmation via a dialogue window. Everything is controlled by global variables. //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Get (Face or Link) Number on Touch Script by Lymirah Gardner, Version 1.0, 01 May 2012 // (First Written 01 May 2012) // // Touch a face on the prim to get the face number. // Touch a prim to get the link number. Both reported only to the owner. // Listens for a scrub command to delete script from prim. // Also responds to a reset command. // //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Please feel free to share this script. It's meant for anyone and everyone! All I ask is that you // don't sell the script on its own or as part of any package, objects or products. It's provided // for free - please keep it that way! Please also keep this title box. // //////////////////////////////////////////////////////////////////////////////////////////////////////// //GNT314 v1.0 /314 reset-scrub //GLOBAL CONTROL VARIABLES integer CHANNEL = 314; string comm_del = "SCRUB"; string comm_reset = "RESET"; //FACE AND/OR LINK NUMBER ON TOUCH? 1 = ON, 0 = OFF integer FACE = 1; integer LINK = 1; //OTHER GLOBAL VARIABLES key owner = NULL_KEY; integer LISTEN_ID; integer DCHANNEL; string temp = ""; integer i; float DTIME = 15.0; //START HERE default { state_entry() { llListenRemove(LISTEN_ID); DCHANNEL = ((integer)("0x"+llGetSubString((string)llGetKey(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; owner = llGetOwner(); LISTEN_ID = llListen(CHANNEL,"",owner,""); } on_rez(integer param) { llResetScript(); } touch_end(integer num_det) { for(i=0;i<num_det;++i) if(FACE == 1) llOwnerSay("Face touched is number "+(string)llDetectedTouchFace(i)); if(LINK == 1) llOwnerSay("Link touched is number "+(string)llDetectedLinkNumber(i)); } listen (integer channel, string name, key id, string command) { temp = llStringTrim(command,STRING_TRIM); command = llToUpper(temp); if(command == comm_reset) { llListenRemove(LISTEN_ID); llOwnerSay("Resetting script."); llResetScript(); } else if(command == comm_del) { llListenRemove(LISTEN_ID); state delete_script; } } } state delete_script { state_entry() { LISTEN_ID = llListen(DCHANNEL, "", owner, ""); llDialog(owner, "Delete this script?", ["Yes","No"], DCHANNEL); llSetTimerEvent(DTIME); } listen(integer channel, string name, key id, string msg) { if(msg == "Yes") { llListenRemove(LISTEN_ID); llOwnerSay("Goodbye!"); llSetTimerEvent(0.0); llRemoveInventory(llGetScriptName()); } else if(msg == "No") { llListenRemove(LISTEN_ID); llSetTimerEvent(0.0); state default; } else { llListenRemove(LISTEN_ID); llOwnerSay("***Something went horribly wrong!***"); llSetTimerEvent(0.0); state bugged; } } timer() { llListenRemove(LISTEN_ID); llOwnerSay("Dialogue time expired."); llSetTimerEvent(0.0); state default; } } state bugged { state_entry() { llOwnerSay("***Script operation terminated!***"); } } (2) GET LINK NUMBERS This one responds to a chat command and whispers the owner with the requested information. Default is channel 313. "this" gives the prim name and link number of the prim the script is in. "all" lists the names of the prims for all link numbers in ascending numerical order (link 1 to link n) and reports the total number of prims in the linkset (at the end of the report). "reset" resets the script. "help" or "?" lists the commands. "scrub" removes the script (after confirmation via a dialogue window). Everything is controlled by global variables. //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Get Link Numbers Script by Lymirah Gardner, Version 1.0, 05 April 2012 // (First Written 05 April 2012) // // Obtains and reports link numbers (to owner) for individual prim or all prims in link set. // Can delete scrip on command and dialogue confirmation. // //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Please feel free to share this script. It's meant for anyone and everyone! All I ask is that you // don't sell the script on its own or as part of any package, objects or products. It's provided // for free - please keep it that way! Please also keep this title box. // //////////////////////////////////////////////////////////////////////////////////////////////////////// //GLN313 v1.0 /313 all-this-reset-scrub-help-? //GLOBAL VARIABLES integer CCHANNEL = 313; //chat channel string comm_all = "ALL"; //command to indicate report for all prims in linkset string comm_this = "THIS"; //command to indicate report for only this prim string comm_reset = "RESET"; //command to reset script string comm_del = "SCRUB"; //command to delete script string comm_help1 = "HELP"; //command to get help/commands string comm_help2 = "?"; //command to get help/commands float SLEEP = 0.2; //time pause when reporting for a linkset (comm_all) key owner = NULL_KEY; integer LISTEN_ID; integer NUM_PRIMS; string temp = ""; integer i; //These are only used to confirm script removal integer DCHANNEL; float DTIME = 15.0; //START HERE default { state_entry() { llListenRemove(LISTEN_ID); NUM_PRIMS = llGetNumberOfPrims(); if(NUM_PRIMS < 2) { //also could have used: if(llGetLinkNumber() == 0) llOwnerSay("***This is not a linkset.***"); state bugged; } DCHANNEL = ((integer)("0x"+llGetSubString((string)llGetKey(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; owner = llGetOwner(); LISTEN_ID = llListen(CCHANNEL,"",owner,""); } on_rez(integer param) { llResetScript(); } listen (integer channel, string name, key id, string command) { temp = llStringTrim(command,STRING_TRIM); command = llToUpper(temp); if(command == comm_this) { i = llGetLinkNumber(); temp = llGetLinkName(i); llOwnerSay("Name of This Prim: "+temp); llOwnerSay("Link Number of This Prim: "+(string)i); } else if(command == comm_all) { for(i=1;i<=NUM_PRIMS;++i) { temp = llGetLinkName(i); if(i<10) llOwnerSay("Link No. "+(string)i+": "+temp); if(i>9 && i<100) llOwnerSay("Link No. "+(string)i+": "+temp); if(i>99) llOwnerSay("Link No. "+(string)i+": "+temp); llSleep(SLEEP); } llOwnerSay("Total Number of Prims: "+(string)NUM_PRIMS); } else if(command == comm_reset) { llListenRemove(LISTEN_ID); llOwnerSay("Resetting script."); llResetScript(); } else if(command == comm_help1 || command == comm_help2) { llOwnerSay("/313 all – get link numbers for all prims in the linkset\n/313 this – get link number for this prim only (the one the script is in)\n/313 reset – reset script\n/313 scrub – delete this script\n/313 help or /313 ? – display this help text"); } else if(command == comm_del) { llListenRemove(LISTEN_ID); state delete_script; } } } state delete_script { state_entry() { LISTEN_ID = llListen(DCHANNEL, "", owner, ""); llDialog(owner, "Delete this script?", ["Yes","No"], DCHANNEL); llSetTimerEvent(DTIME); } listen(integer channel, string name, key id, string msg) { if(msg == "Yes") { llListenRemove(LISTEN_ID); llOwnerSay("Goodbye!"); llSetTimerEvent(0.0); llRemoveInventory(llGetScriptName()); } else if(msg == "No") { llListenRemove(LISTEN_ID); llSetTimerEvent(0.0); state default; } else { llListenRemove(LISTEN_ID); llOwnerSay("***Something went horribly wrong!***"); llSetTimerEvent(0.0); state bugged; } } timer() { llListenRemove(LISTEN_ID); llOwnerSay("Dialogue time expired."); llSetTimerEvent(0.0); state default; } } state bugged { state_entry() { llOwnerSay("***Script operation terminated!***"); } }
  5. Apologies for not getting back to you. With the rez issues and one of my burlesque troupes taking what looks to be a 2-month holiday, not to mention the release of Diablo 3, I haven't been in SL very much to troubleshoot the script. I did quickly load it up and note that my test wasn't working correctly. But that just means I have to troubleshoot the individual functions to start with and be sure I fully understand how they work. I'll try to get some work in on it by the end of June. Diablo 3 has lost some of its lustre (*cough*at least until the next patch*cough*), so I'll try to give SL a little time.
  6. I'll test it tonight and see what I can figure out. (I'm usually not around on Thursday nights.)
  7. This script began when I wanted to write my own poseball script and learn more LSL in the process. It evolved as I added features to move it beyond a simple, one-prim poseball script. Since I perform SL burlesque, this has led to further development and the script has turned out to be very useful. The script now works for a linked prim (e.g., a poseball linked to a burlesque set, v1.5) and for multiple such poseballs linked together (e.g., poseballs for a group burlesque act, all linked to the set, v1.6 and 1.7). All options are controlled by global variables (located immediately below the title box). They're labeled for easy use. You can enable/disable and modify hover text that automatically hides when you click/sit on the object (very useful for assigning people to specific poseballs in a group act). Use "\n" for multiple lines of hover text (if needed). You can enable/disable hiding of the object on click/sit (normal poseball operation). You can also modify the position of your avatar while performing the animation (via sittarget offset and sittarget rotation - useful for different animations). I've tested the script for the identified functionality and it appears to work correctly. If anyone has any recommendations, either for the existing code or additional features, please let me know! (And fwiw, the forum posting totally destroyed my title box formatting. Ugh.) EDIT: Btw, the reason I have the normal poseball function (object hiding) available as a toggle is for flexibility. For example, I used a version of this script for an object in a burlesque set of mine to trigger a snow angel animation. In that case, I didn't want the object/prim to hide - I just wanted click-sitting on it to trigger the animation (with me in the proper orientation). //////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Object Click-Sit-Animation Script by Lymirah Gardner, Version 1.7, 08 May 2012 // // (First Written 06 March 2012) // // // // Clicking will sit on object & animate avatar. // // Hover text and object hide controlled from global variables. // // v1.5: Now works for a linked prim. Normal functionality retained for separate, unlinked objects. // // v1.6: Now works correctly (individually) for multiple poseballs linked together. // // v1.7: Bug fix for v1.6. // // // //////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Please feel free to share this script. It's meant for anyone and everyone! All I ask is that you // // don't sell the script on its own or as part of any package, objects or products. It's provided // // for free - please keep it that way! Please also keep this title box. // // // //////////////////////////////////////////////////////////////////////////////////////////////////////// //GLOBAL VARIABLES string animation = "ANIMATIONNAME"; //change to animation name vector sittarget = < 0.0, 0.0, 0.1>; //adjust sittarget offset vector sitangle = < 0.0, -90.0, -90.0>; //adjust sittarget rotation in degrees //WHO CAN USE THIS? ONLY OWNER? integer only_owner = 0; //toggle access: 1 = only owner, 0 = anyone //TOGGLE HOVER TEXT AND/OR OBJECT HIDE (SEPARATELY) integer HOV_ON = 1; //toggle hover text: 1 = on, 0 = off integer OBJHIDE_ON = 1; //toggle object hide (poseball action): 1 = on, 0 = off //MODIFY HOVER TEXT & COLOR string HOVERTEXT = "Sit here or else!"; //hover text vector COLOR = < 0.0, 0.0, 0.0>; //color of hover text //black: < 0.0, 0.0, 0.0> //gray: < 0.5, 0.5, 0.5> //white: < 1.0, 1.0, 1.0> //pink: < 1.0, 0.0, 0.5> //red: < 1.0, 0.0, 0.0> //orange: < 1.0, 0.5, 0.0> //yellow: < 1.0, 1.0, 0.0> //light green: < 0.5, 1.0, 0.0> //green: < 0.0, 1.0, 0.0> //blue-green: < 0.0, 1.0, 0.5> //cyan: < 0.0, 1.0, 1.0> //med-blue: < 0.0, 0.5, 1.0> //blue: < 0.0, 0.0, 1.0> //purple: < 0.5, 0.0, 1.0> //magenta: < 1.0, 0.0, 1.0> //SIT MENU TEXT integer SITTXT_ON = 1; //toggle sit menu text override: 1 = on, 0 = off string SITTEXT = "Sit here!"; //sit menu text //OTHER GLOBAL VARIABLE DECLARATIONS rotation sitrotation; key owner; key sitter = NULL_KEY; integer SITTING; integer LN; integer LS; //USER-DEFINED FUNCTION integer test_sit() { if(LS == 1) { if(llAvatarOnLinkSitTarget(LN) != NULL_KEY) return 1; else return 0; } else if(LS == 0) { if(llAvatarOnSitTarget() != NULL_KEY) return 1; else return 0; } else return 0; } //START HERE default { state_entry() { SITTING = 0; if(only_owner == 1) owner = llGetOwner(); if(llGetNumberOfPrims() > 1) { LN = llGetLinkNumber(); LS = 1; } else { LN = LINK_SET; LS = 0; } sitrotation = llEuler2Rot(sitangle * DEG_TO_RAD); //deg to rad & --> rot llSitTarget(sittarget,sitrotation); //set sittarget llSetClickAction(CLICK_ACTION_SIT); //click action to sit if(SITTXT_ON) llSetSitText(SITTEXT); //set sit menu text if(HOV_ON) llSetText(HOVERTEXT,COLOR,1.0); //show hover text else llSetText("",<0.0,0.0,0.0>,1.0); //or make it null if(OBJHIDE_ON) llSetLinkAlpha(LN,1.0,ALL_SIDES); //show object } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_LINK) { //links changed! if(SITTING == 0 && LS == 1) sitter = llAvatarOnLinkSitTarget(LN); if(SITTING == 0 && LS == 0) sitter = llAvatarOnSitTarget(); if(only_owner == 1 && sitter != owner && sitter != NULL_KEY) { llUnSit(sitter); llInstantMessage(sitter,"You are not permitted to sit here."); sitter = NULL_KEY; } else if(SITTING == 0 && sitter != NULL_KEY) { //someone sitting? SITTING = 1; llRequestPermissions(sitter,PERMISSION_TRIGGER_ANIMATION); } else if(SITTING == 1 && test_sit() == 0) { //I think someone stood up! if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStopAnimation(animation); if(HOV_ON) llSetText(HOVERTEXT,COLOR,1.0); //show hover text if(OBJHIDE_ON) llSetLinkAlpha(LN,1.0,ALL_SIDES); //show object SITTING = 0; sitter = NULL_KEY; } } } run_time_permissions(integer perm) { if(perm & PERMISSION_TRIGGER_ANIMATION) { if(HOV_ON) llSetText("",COLOR,1.0); //hide hover text if(OBJHIDE_ON) llSetLinkAlpha(LN,0.0,ALL_SIDES); //hide object llStopAnimation("sit"); //stop normal sit llStartAnimation(animation); //and use this animation } } }
  8. If I recall correctly, it's that a non-linkset (i.e., an unlinked single object/prim) has a link number of 0. Link numbers in a linkset begin from 1 (root prim) and are determined by the order in which the prims are selected for the linkset. You shouldn't ever find a link number of 0 in a linkset. (See http://wiki.secondlife.com/wiki/LlGetLinkNumber ) Since with LSL we're forced to store information in (multiple) lists, I believe llListFindList is the index location mechanism we're afforded. I'm currently unaware of another LSL search tool. I'm sure you can do fun stuff with exporting the information (e.g., to a server, to be operated on in a real coding language) and importing the results, but that's well beyond my abilities. Top left is 1,1. Got it. As for the additional "global" display scale (g_scale_x and g_scale_y) and "global" display offset (g_offset_x and g_offset_y), those are pretty easy since they're really just some extra "offset" values. Not a problem. I think this is what the code would look like: float g_scale_x = 1.0;float g_scale_y = 1.0;float g_offset_x = 0.0;float g_offset_y = 0.0;//set g_scale_x and g_scale_y, ranging from 0.1 to 100.0; none/default = 1.0 (see above)//set g_offset_x and g_offset_y, ranging from -1.0 to 1.0; none/default = 0.0 (see above)//make sure all of those values are floatsfloat rot = 0.0;integer size_x = end_x – start_x +1;integer size_y = end_y – start_y +1;float repeat_x = (1.0/(float)size_x)*g_scale_x;float repeat_y = (1.0/(float)size_y)*g_scale_y;for(j = start_y; j <= end_y; ++j) { for(i = start_x; i <= end_x; ++i) { integer k = llListFindList(cache_coordinates, [<i,j,0>]); //change to <j,i,0> if y,x in object description integer linknum = llList2Integer(cache_linknum, k); float offset_x = (((float)i – (float)start_x)/(float)size_x) + g_offset_x; float offset_y = (((float)j – (float)start_y)/(float)size_y) + g_offset_y; llSetLinkPrimitiveParamsFast(linknum,[PRIM_TEXTURE,CHUNK_FACE,inventory,<repeat_x,repeat_y,0.0>,<offset_x,offset_y,0.0>,rot]); }} I purposefully just added the global scale and global offset bits to the code I wrote earlier today. That way someone could remove them if they didn't want that feature (slightly more modular approach - don't think it costs much if anything). You can add in the other bits - if the texture is blank, debugging text, etc. As an fyi, once the 192 chunk version is working, in theory you can extend the functionality to additional linksets by having the linksets communicate with one another. That would be one way to reach your 512 prim version. I don't know too much about such communication (haven't done it yet myself), but I remember looking at it and jotting down some notes somewhere. If you do want to pursue something crazy like that (hehe), I'll gladly help you work on it.
  9. Thanks for the further information! That certainly helps with some of the specific implementation aspects. As an initial thought, given that the link numbers will range from 1 to llGetNumberOfPrims(), is there a need to index from 0 in cache_chunks? Seems to me like use of the index 0 just causes some unnecessary evaluations for a prim that doesn't exist. Another thought, you use a for loop in linknum_to_coordinates_vec to search through cache_linknum for the corresponding entry. llListFindList might be a better option. That way, a single function call returns the index and avoids unnecessary evaluations as otherwise are performed with the for loop. Turning to the problem at hand: (1) I assume your "chunks" are the prims/pixels of the display. (2) I assume the position information in the description field is just the x, y coordinates of that chunk within the display. Given that you appear to be working with a large number of chunks (192?!?? Wow!), you may want to avoid iterating over the entire chunk set with the for loop in texture_set. This would also avoid the inrange function entirely (thus reducing evaluations, speeding things up, etc.). Such functionality would not entail a serious modification of your existing script since if x and y are integers for the coordinates of the chunk within the display, you can preselect specific chunks by using llListFindList(cache_coordinates,[<x,y,0>] to find the index and then look up the corresponding link number from cache_linknum. For example, let's use j as the y index and i as the x index: for(j = start_y; j <= end_y; ++j) { for(i = start_x; i <= end_x; ++i) { integer k = llListFindList(cache_coordinates, [<i,j,0>]); integer linknum = llList2Integer(cache_linknum, k); (do other stuff); }} I started writing out another block of code for your specific implementation when I realized that I need more information. It's not super critical since it really only affects offsets and signs and such, but it would annoy me immensely to provide code that doesn't work as desired without further modifications. It sounds like the matrix indices for a given chunk are stored in the description field of that chunk (for example: "2,5" or "24,93"). Do these indices start at 0 or 1? Also, which corner of the display is 0,0 or 1,1? (Top left corner? Bottom left corner?) If you give me answers to those two questions, along with any comments or revisions for the other bits, I can give you a specific example of offset & repeat code for your script. It'll pretty much be what I put in my previous post but with some tweaks for your variable names and specific setup.
  10. I saw this thread earlier (I lurk from time to time) and was thinking about it. I do love a good, solid scripting "problem." Since you're working with a preexisting linkset as opposed to providing the script blindly (e.g., for someone else to use and/or apply to their own linkset), it seems to me like you can dispense with some of the awkwardness. You should know upfront the total size of your grid. And if we assume you're working from a known product, then you can also hardcode the link numbers (which makes everything easier - no discovery needed). Since lists index from 0 to LIST_SIZE - 1, I redid my notes below to consider indices from 0 to SIZE - 1. Turns out it made the math easier to parse, too. I came up with 3 steps, though the first two are more setup than anything: associate link number (integer LN) with prim identity in matrix; receive desired image size & rotation; and show desired image. For (1), just use a hardcoded list of link numbers per row or column. By row made sense to me, so I went with: list x0 = [LN00,LN10,LN20,LN30,...,LN(x_TotalLength - 1)0];list x1 = [LN10,LN11,LN21,LN31,...,LN(x_TotalLength - 1)1]; ... list xy = [etc.]; Note that this is with indexing from 0 to LENGTH - 1. For ease, assume that 0,0 is the upper left corner. For (2), that's just a matter of input and can be handled however you like - chat commands, dialogue, notecard reading, HUD, hardcoded, whatever. For now, let x_Length and y_Length each correspond to the target size of the displayed image. For example, consider a grid of 3x3. If you wanted to show the image on the first 2 pixels (prims) of the top row, you have x_Length = 2 and y_Length = 1. For (3), the fun begins! integer face = 1; //face number for all prims/pixelsstring texture = "TEXTURE NAME";integer x_Length;integer y_Length;integer x;integer y; integer LN; //link number of corresponding primfloat ur; //x value for repeatfloat vr; //y value for repeatfloat uo; //x value for offsetfloat vo; //y value for offsetfloat rot = 0.0; //rotation in radians list x0 = [see above]; list x1 = [see above]; ... //insert code re selecting x_Length & y_Length ur = 1.0/(float)x_Length; //repeat is the % of image to showvr = 1.0/(float)y_Length; //static for all x and yfor(y = 0;y <= y_Length - 1; ++y) { for(x = 0,x <= x_Length - 1; ++x) { LN = llList2Integer("x"+(string)y,x); uo = (float)x/(float)x_Length; //offset is incremental vo = (float)y/(float)y_Length; //clearly not static for all x and y llSetLinkPrimitiveParamsFast(LN,[PRIM_TEXTURE,face,texture,<ur,vr,0.0>,<uo,vo,0.0>,rot]); }} I haven't tested this out, but it makes sense to me. I could easily be wrong - admittedly, I'm learning more and more LSL as I go. As for rotation, I'd have to test it out to be sure but I'd start with the above and then try hardcoding examples with rot = PI/2 and things like that. You can find examples of how to go from degrees to radians (I have code for it somewhere if need be). Obviously, the above is more just some dirty figuring to get you moving. Please let me know if/how it works out! (Edited because I'm learning how to post.)
×
×
  • Create New...