├── README.txt ├── experience_tools ├── [solo] Experience Teleporter 1.0.lsl └── [solo] Join The Experience 1.0.lsl ├── super_advanced ├── [solo] Dent On Collision 1.0.lsl ├── [solo] Give All Inventory 2.0.lsl ├── [solo] Primitive Params List Fixer 1.0.lsl ├── [solo] Random Color Changer 1.1.lsl ├── [solo] Simple Multi-Pay 1.0.lsl ├── [solo] SimplePilot 1.0.lsl └── [solo] Thrower 1.0.lsl └── very_basic ├── Cinco's Ultra-Simple Teleport Script 2.0.lsl ├── Proximity Alpha 0.2.lsl ├── [solo] Basic Wear:Animate script 1.0.lsl ├── [solo] Donation Box 1.3.lsl ├── [solo] Drink Your Tea 1.3.lsl ├── [solo] Give All Notecards 0.1.lsl ├── [solo] Give First Notecard 0.3.lsl ├── [solo] Object Die.lsl ├── [solo] Phantom Children.lsl ├── [solo] Physical On Delink 1.0.lsl ├── [solo] Play Sound On Sit.lsl ├── [solo] Preload Slideshow.lsl ├── [solo] Put Prim Name In Hover, Then Delete 1.0.lsl ├── [solo] Read A Notecard.lsl ├── [solo] Scrub All Particles 1.0.lsl ├── [solo] Vehicular Bobbing Floater.lsl ├── [solo] Walk-Thru Play Sound.lsl └── [solo] string tokens.lsl /README.txt: -------------------------------------------------------------------------------- 1 | The goal of this script repository is twofold: 2 | 3 | 1) Provide useful scripts to the Second Life/OpenSimulator communities, and 4 | 5 | 2) Provide USEFULLY COMMENTED scripts to those same communities. 6 | 7 | There are two main categories: super_advanced and very_basic. This is because there are only two types of LSL scripts: Super advance or very basic. That's the nature of LSL: The script will either be obvious or require a bunch of learning and reference. 8 | 9 | These two categories encourage anyone who contributes to comment their script. Either the script is so basic that newbies will be reading it, and therefore it should be commented so they can understand it, or the script is so advanced that advanced scripters will be scratching their heads and wishing you had commented more. 10 | -------------------------------------------------------------------------------- /experience_tools/[solo] Experience Teleporter 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Experience-based Teleporter 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2018, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script uses an existing Experience to request permissions to teleport 13 | // an avatar to a destination when they walk into the object containing it. 14 | 15 | // Learn about Experience tools here: 16 | // http://wiki.secondlife.com/wiki/Category:Experience_Tools 17 | 18 | // It's based on sample code from here: 19 | // http://wiki.secondlife.com/wiki/LlRequestExperiencePermissions 20 | 21 | // To use: 22 | // Set up your Experience. 23 | // Rez a prim. 24 | // Set the name of the prim to the hovertext you want. 25 | // Set the description of the prim to the coordinates and facing location you 26 | // want, as two vectors, like this: <128,128,30>&<0,0,0> 27 | // Add this script to the prim inventory. 28 | // Edit the script. 29 | // Check the 'Use Experience' checkbox and set the Experience you prefer. 30 | // Save the script, so that it compiles. 31 | // Walk into the prim. You are teleported! 32 | 33 | // Some users might not be familiar with the experience tools. In those cases 34 | // we can teleport them when they sit. 35 | 36 | default 37 | { 38 | state_entry() 39 | { 40 | // Put the object name in the hover text. 41 | llSetText(llGetObjectName(), <1.0,1.0,1.0>, 1.0); 42 | // Make the prim phantom so the avatar can walk through it. 43 | llVolumeDetect(TRUE); 44 | llSitTarget(<0.0,0.0,0.1>, ZERO_ROTATION); 45 | llSetSitText("Teleport"); 46 | llUnSit(llAvatarOnSitTarget()); 47 | } 48 | 49 | collision_start(integer number_of_collisions) 50 | { 51 | integer i; 52 | for(i=0; i < number_of_collisions; i++) 53 | { 54 | llRequestExperiencePermissions(llDetectedKey(i), ""); 55 | } 56 | } 57 | 58 | changed(integer change) 59 | { 60 | if (change & CHANGED_LINK) 61 | { // if a link change occurs (sit or unsit) 62 | key av = llAvatarOnSitTarget(); 63 | if(av != NULL_KEY) { 64 | llRequestExperiencePermissions(av, ""); 65 | } 66 | } 67 | } 68 | 69 | experience_permissions(key target_id) 70 | { 71 | string object_desc = llGetObjectDesc(); 72 | // Use & separator because you can't put | in an object description. 73 | list desc_list = llParseString2List(object_desc, ["&"], []); 74 | // (vector)llList2String(src, index); 75 | vector target_vector = (vector)llList2String(desc_list, 0); 76 | if (target_vector != ZERO_VECTOR) { 77 | vector target_facing = (vector)llList2String(desc_list, 1); 78 | llUnSit(llAvatarOnSitTarget()); 79 | llTeleportAgent(target_id, "", target_vector, target_facing); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /experience_tools/[solo] Join The Experience 1.0.lsl: -------------------------------------------------------------------------------- 1 | string gExperienceName; 2 | 3 | default 4 | { 5 | state_entry() 6 | { 7 | list experience = llGetExperienceDetails(NULL_KEY); 8 | gExperienceName = llList2String(experience, 0); 9 | llSetText("Touch to join the\n" + gExperienceName + "\nexperience.", <1,1,1>, 1.0); 10 | } 11 | 12 | touch_start(integer total_number) 13 | { 14 | while(total_number--) { 15 | key agent = llDetectedKey(total_number); 16 | if (llAgentInExperience(agent)) { 17 | llRegionSayTo(agent, 0, "You are already part of the " + gExperienceName + " experience."); 18 | } 19 | else { 20 | llRequestExperiencePermissions(agent, ""); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /super_advanced/[solo] Dent On Collision 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Dent On Collision 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script makes the linked prims 'dent' when something runs 13 | // into them. This is accompanied by a particle effect which is 14 | // scaled roughly to the size of the prim. 15 | // After a certain number of 'dents,' the prim unlinks. 16 | 17 | // It's assumed that this script is in the root prim of the object. 18 | // As a consequence, the root prim won't ever 'dent.' This makes it 19 | // a good idea to add this script to a very small and unobtrusive 20 | // prim, and then link this new prim to the object to be dented. 21 | 22 | 23 | vector gScale; // scale of this prim. we store it so we don't have to ask a lot. 24 | float gLargest; // largest dimension 25 | string gTexture; 26 | 27 | list gPrimCounts; // populated with vectors, one per non-root prim 28 | 29 | particleCloud(integer link, float mag) 30 | { 31 | // this function makes a cloud of 'dust' for the given linked prim. 32 | // mag is the amount of time the emitter should produce dust particles. 33 | float startScale = gLargest * 0.07; // arbitrary constant. adjust for aesthetics. 34 | llLinkParticleSystem( link, [ 35 | PSYS_SRC_TEXTURE, gTexture, 36 | PSYS_PART_START_SCALE, , 37 | PSYS_PART_END_SCALE, , 38 | PSYS_PART_START_COLOR, <.5,.5,.5>, 39 | PSYS_PART_END_COLOR, <.1,.1,.1>, 40 | PSYS_PART_START_ALPHA, .8, 41 | PSYS_PART_END_ALPHA, .0, 42 | PSYS_SRC_BURST_PART_COUNT, 1, 43 | PSYS_SRC_BURST_RATE, 0.2, 44 | PSYS_PART_MAX_AGE, 2.0, 45 | PSYS_SRC_MAX_AGE, mag, // <-- mag 46 | PSYS_SRC_PATTERN, 8, 47 | PSYS_SRC_ACCEL, <0.0,0.0,.2>, 48 | PSYS_SRC_BURST_SPEED_MIN, 0.01, PSYS_SRC_BURST_SPEED_MAX, 0.2, 49 | PSYS_SRC_ANGLE_BEGIN, 15*DEG_TO_RAD, 50 | PSYS_PART_FLAGS, ( 0 51 | | PSYS_PART_INTERP_COLOR_MASK 52 | | PSYS_PART_INTERP_SCALE_MASK 53 | | PSYS_PART_EMISSIVE_MASK 54 | | PSYS_PART_FOLLOW_VELOCITY_MASK 55 | | PSYS_PART_WIND_MASK 56 | | PSYS_PART_BOUNCE_MASK 57 | ) ] 58 | ); 59 | } 60 | 61 | list moveVel(integer link, vector vel) 62 | { 63 | // 'dent' the object based on collision velocity 64 | // move and rotate 65 | list params = llGetLinkPrimitiveParams(link, [PRIM_POSITION, PRIM_ROTATION]); 66 | // convert position to local position 67 | vector p = llList2Vector(params, 0); 68 | rotation r = llGetRootRotation(); 69 | vector localPos = ((p-llGetPos()) / r); 70 | // add in the collision velocity.. 71 | localPos += vel * 0.05; 72 | // work some random magic on the rotation... 73 | rotation primR = llList2Rot(params, 1) / r; // local rotation 74 | primR = primR * llAxisAngle2Rot(vel, (llFrand(0.5) - 0.25)); // put some english on it 75 | // return a list with our new position and rotation. 76 | return [PRIM_POSITION, localPos, PRIM_ROTATION, primR]; 77 | } 78 | 79 | initPrims() 80 | { 81 | // this function fills up gPrimCounts with some initial data 82 | // we're making a counter that tells how many 'hits' the 83 | // prim has left before it's delinked. 84 | // declare some function-scoped variables to save a bit of memory... 85 | list params; 86 | vector pos; 87 | gPrimCounts = []; // clear old data 88 | integer prims = llGetNumberOfPrims(); 89 | if (prims == 1) 90 | { 91 | // prims will == 1 if there are no child prims 92 | // so we can just set this and be on our way. 93 | gPrimCounts = [3]; 94 | } 95 | else 96 | { 97 | // but if there are more than one prims in link set 98 | // we loop through and make sure all the prims are really prims 99 | // (they could be seated avatars), and init them to the number 100 | // we like. 101 | integer i; 102 | for (i = 1; i <= prims; i++) 103 | { 104 | // avatars can't have ZERO_VECTOR size. 105 | if (llGetAgentSize(llGetLinkKey(i)) == ZERO_VECTOR) 106 | { 107 | gPrimCounts += [3]; 108 | } 109 | else i--; 110 | } 111 | } 112 | } 113 | 114 | unsitAllAvatars() 115 | { 116 | // this function lets us unsit any avatar who attempts to sit down 117 | // on the object. 118 | integer links = 0; 119 | while (llGetObjectPrimCount(llGetKey()) < (links = llGetNumberOfPrims())) llUnSit(llGetLinkKey(links)); 120 | } 121 | 122 | default 123 | { 124 | // default state is where we ask permission to be able to unlink 125 | // prims. 126 | state_entry() 127 | { 128 | llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS); 129 | } 130 | 131 | run_time_permissions(integer perms) 132 | { 133 | if (perms & PERMISSION_CHANGE_LINKS) 134 | // we got permission to change links, so go to the next step.. 135 | state waiting; 136 | } 137 | on_rez(integer foo) 138 | {llResetScript();} 139 | } 140 | 141 | state waiting 142 | { 143 | // this state is where we wait for the owner to tell us to start 144 | // denting. 145 | state_entry() 146 | { 147 | // this could be much more secure. 148 | llListen(23, "", NULL_KEY, "dent"); 149 | } 150 | 151 | listen(integer channel, string name, key id, string message) 152 | { 153 | // get the object details and discover if we have the same owner 154 | // this is so an object could start the denting process. 155 | list details = llGetObjectDetails(id, [OBJECT_OWNER]); 156 | if (llList2Key(details,0) == llGetOwner()) 157 | { 158 | if (llToLower(message) == "dent") 159 | { 160 | state denting; 161 | } 162 | } 163 | } 164 | 165 | on_rez(integer foo) 166 | {llResetScript();} 167 | } 168 | 169 | state denting 170 | { 171 | // ok, here we go. finally the big show. 172 | // start letting collisions dent the object. 173 | state_entry() 174 | { 175 | unsitAllAvatars(); 176 | llSitTarget(<0,0,0.1>, ZERO_ROTATION); 177 | initPrims(); 178 | gScale = llGetScale(); 179 | gLargest = llVecMag(gScale) * 5.0; 180 | } 181 | 182 | collision_start(integer collisions) 183 | { 184 | // something ran into the object. 185 | vector vel; 186 | float mag; 187 | integer link; 188 | integer i; 189 | // more than one thing can run into the object, 190 | // so we need to deal with them all. 191 | for (i=0; i < collisions; i++) 192 | { 193 | // which prim got hit? 194 | link = llDetectedLinkNumber(i); 195 | // root prim never dents. 196 | if (link > 1) 197 | { 198 | // We make a list of all the things to update 199 | // This is why moveVel returns a list rather than 200 | // setting the parameters itself. 201 | // Start with the glow params.... 202 | // (if we were really tricky, we'd get the glow params 203 | // and modify them, but we'll assume no glow on the object) 204 | list params = [PRIM_GLOW, ALL_SIDES, 0.1]; 205 | vel = llDetectedVel(i); 206 | mag = llVecMag(vel); 207 | particleCloud(link, mag * 0.7); // arbitrary constant. 208 | // add in the move... 209 | params += moveVel(link, vel); 210 | // send the glow and move 211 | // we use the non-fast version so the flash is visible. 212 | llSetLinkPrimitiveParams(link, params); 213 | //....and now that that's over, we undo the glow. 214 | llSetLinkPrimitiveParamsFast(link, [PRIM_GLOW, ALL_SIDES, 0.0]); 215 | // we precomp an index so we can manipulate our list... 216 | integer linkListIndex = link-1; 217 | // how many hits has this prim taken? 218 | integer hits = llList2Integer(gPrimCounts, linkListIndex); 219 | if (--hits < 0) 220 | { 221 | // if there aren't any more hits left, we delink. 222 | // it's on its own now.... :-) 223 | llBreakLink(link); 224 | // and delete the prim from our list. 225 | gPrimCounts = llDeleteSubList(gPrimCounts, linkListIndex, linkListIndex); 226 | } 227 | else 228 | { 229 | // still has some hits left, so we just rebuild the list 230 | // with the decremented hit count. 231 | gPrimCounts = llListReplaceList(gPrimCounts, [hits], linkListIndex, linkListIndex); 232 | } 233 | } 234 | } 235 | } 236 | 237 | changed(integer change) 238 | { 239 | if (change & CHANGED_LINK) 240 | { 241 | // unsit any av that makes themselves comfortable 242 | unsitAllAvatars(); 243 | // and if we're the last prim after denting and delinking 244 | // all the others, then die. 245 | if (llGetObjectPrimCount(llGetKey()) <= 1) llDie(); 246 | } 247 | } 248 | on_rez(integer foo) 249 | {llResetScript();} 250 | } 251 | -------------------------------------------------------------------------------- /super_advanced/[solo] Give All Inventory 2.0.lsl: -------------------------------------------------------------------------------- 1 | // Give All Inventory (Except This Script) 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script gives all the inventory contained in the object 13 | // to whoever touches it. The items will be in a folder with the same 14 | // name as the giver object. 15 | // It is the big brother to the Give First Notecard script in the 16 | // very_basic folder of this repository. 17 | 18 | // UPDATE: v.2.0 has some basic usability improvements. It imposes a few 19 | // rules for the benefit of anyone who has to maintain a giver kiosk: 20 | // * If you add a script to the object inventory, it will warn you 21 | // that this is a bad idea. 22 | // * All inventory items will be checked for copy/trans permissions. 23 | // 24 | // The giver script will still give objects even if these checks don't 25 | // pass. Changing the object inventory will cause the checks to be 26 | // performed again. 27 | 28 | 29 | // This string is the text of the hover text. 30 | string gHoverText = "Touch for some goodies!"; 31 | 32 | default 33 | { 34 | // 'default' is a vague name, so we just switch right over to 35 | // state errorCheck. 36 | state_entry() 37 | { 38 | state errorCheck; 39 | } 40 | } 41 | 42 | state errorCheck 43 | { 44 | // state errorCheck is where we make sure the object inventory 45 | // is reasonably error-free. 46 | // We don't want to distribute scripts, and we want kiosk 47 | // items to be copiable and transferrable. 48 | // This state is fairly linear, so it will all occur in 49 | // the state_entry event. 50 | state_entry() 51 | { 52 | // first check for scripts 53 | // we get a count of scrips in this object 54 | integer count = llGetInventoryNumber(INVENTORY_SCRIPT); 55 | // there should be one script (this one). any more than that 56 | // is a bad idea. 57 | if (count > 1) 58 | { 59 | llOwnerSay("*** It's a terrible idea to distribute scripts through a kiosk. Please remove scripts other than '" + llGetScriptName() + "' and try again. (Copying and pasting a script to a notecard is a reasonable way to work around this.)"); 60 | state vend; 61 | } 62 | // next we check for permissions on each item. 63 | // we're interested in copy and trans, so we'll set up a variable for that 64 | integer PERM_COPYTRANS = (PERM_COPY | PERM_TRANSFER); 65 | // some variables we'll need... 66 | integer ownerPerms; 67 | string itemName; 68 | list badPerms; 69 | integer i; 70 | // we want to get this script's name, so we can exclue it from 71 | // the permission check. 72 | string scriptName = llGetScriptName(); 73 | // how many items in inventory? 74 | count = llGetInventoryNumber(INVENTORY_ALL); 75 | // do we even need to do this check? 76 | // if count is < 2 (1 for this script, plus any one item) 77 | // then there are no freebies to vend. 78 | if (count < 2) 79 | { 80 | llOwnerSay("*** This vendor does not contain any items to give away."); 81 | state vend; 82 | } 83 | // we loop through all the items. 84 | for (i=0; i 0) 112 | { 113 | // more than none, so we have to tell the user. 114 | llOwnerSay("*** You do not have copy/trans permission for the following items:\n - " + llDumpList2String(badPerms, ",\n - ")); 115 | state vend; 116 | } 117 | // OK so if we made it this far, there's probably nothing wrong with 118 | // object inventory. 119 | llOwnerSay("*** Congratulations. Your vendor does not contain scripts, and all items are copyable and transferrable."); 120 | state vend; 121 | } 122 | } 123 | 124 | state vend 125 | { 126 | state_entry() 127 | { 128 | // Set up the hover text.... 129 | llSetText(gHoverText, <1,1,1>, 1.0); 130 | } 131 | 132 | touch_start(integer total_number) 133 | { 134 | // First we want to find out if there's anything to give... 135 | integer count = llGetInventoryNumber(INVENTORY_ALL); 136 | // count will be at least 1, because of this script. 137 | if (count > 1) 138 | { 139 | // this is the list of stuff we want to hand over 140 | list itemsToGive; 141 | // and this is the name of this script 142 | string thisScript = llGetScriptName(); 143 | 144 | // we start getting all the inventory items... 145 | // this is a fairly standard pattern. Loop through the 146 | // items, neglect to add the one we don't want. :-) 147 | string thisItem; 148 | integer i; 149 | for (i=0; i 84 | 85 | // Since we know the size and types of data structures 86 | // related to the various PRIM_TYPEs, we can use that 87 | // knowledge to make a rule set. 88 | 89 | // Then we send params and the rule set off to the castList 90 | // function, in order to cast the list to the proper types. 91 | 92 | // This, of course, consumes a great deal of memory that would 93 | // probably be better spent some other way. 94 | 95 | list rules; 96 | integer i; 97 | integer constant; 98 | integer length = llGetListLength(params); 99 | while (i; 32 | } 33 | 34 | setRandomColors() 35 | { 36 | // gPrimCount is the global that tells us how many prims there are 37 | if (gPrimCount == 1) 38 | { 39 | // only one prim to deal with. If there were an 40 | // llSetPrimitiveParamsFast function, we'd use it here. 41 | // But since there isn't, we trick llSetLinkPrimitiveParamsFast 42 | // into doing our work for us. Specifying LINK_SET means all 43 | // prims get changed. 44 | llSetLinkPrimitiveParamsFast(LINK_SET, 45 | [PRIM_COLOR, ALL_SIDES, randomPrimarySecondaryColor(), 1.0]); 46 | } 47 | else 48 | { 49 | // more than one prim, so we loop through all the prims and set 50 | // their color. 51 | integer i; 52 | for (i=1; i<= gPrimCount; ++i) 53 | { 54 | // set the color for the prim 55 | llSetLinkPrimitiveParamsFast(i, 56 | [PRIM_COLOR, ALL_SIDES, randomPrimarySecondaryColor(), 1.0]); 57 | } 58 | } 59 | } 60 | 61 | 62 | default 63 | { 64 | state_entry() 65 | { 66 | // load up the prim count global... 67 | gPrimCount = llGetObjectPrimCount(llGetKey()); 68 | // set up the timer.... 69 | llSetTimerEvent(0.2); 70 | } 71 | 72 | timer() 73 | { 74 | // set the random color. 75 | setRandomColors(); 76 | } 77 | 78 | changed(integer what) 79 | { 80 | // whatever changes, we just update gPrimCount 81 | // this takes care of relinked objects and when 82 | // an av sits down or gets up. 83 | // we do this here so we're not doing it every 0.2 second 84 | // through the timer event. 85 | gPrimCount = llGetObjectPrimCount(llGetKey()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /super_advanced/[solo] Simple Multi-Pay 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Solo's Simple Multi-Pay Script 1.0. 2 | 3 | // THIS NOTICE MUST REMAIN INTACT: 4 | // Copyright 2010, Solo Mornington 5 | // License: Use freely in any way you want. Modified versions 6 | // may be used in any way. No credit or acknowledgement required. 7 | // Definitive source and updates available here: 8 | // http://github.com/SoloMornington/Solos-Script-Repository 9 | // ** end notice 10 | 11 | // A super-simple multi-pay script. 12 | 13 | // This script assumes all payees get an equal amount. 14 | // The object owner wins the spoils of division remainers. 15 | 16 | // Configuration details follow license... 17 | 18 | // ----------------------------------------------------- 19 | 20 | // source for this license: 21 | // http://poidmahovlich.blogspot.com/2008/05/betlog-hax-licence-20080504a.html 22 | 23 | //---------------------------------- 24 | // ---LICENCE START--- 25 | // This script may only be distributed/used under these conditions: 26 | // 27 | // - The original SecondLife permissions must be retained. 28 | // [Generally this will mean Modify/Copy/Transfer .. full perms.] 29 | // 30 | // - It is NOT *SOLD* BY ITSELF, UNMODIFIED. 31 | // [Modifying the 'CONFIGURATION' sections alone does NOT constitute 32 | // signficant odification.] 33 | // 34 | // 1] If you do NOT significantly modify the script's 'CORE CODE': 35 | // - This licence information must not be removed or altered. 36 | // - The original script is used so as to: 37 | // a] Retain the original creator name in its properties. 38 | // a] Retain the original script name. 39 | // [Do not just copy and paste it into a new script that shows you as the creator.] 40 | // 41 | // 2] If you DO significantly modify the script's 'CORE CODE': 42 | // - It must be clear in the notecard/script/description (a prominent place) 43 | // of any item using it that: 44 | // a) This script was used. 45 | // b) The original author's name. 46 | // c) Any credits from the original script are passed through. 47 | // e.g. 'CREDIT: script name by BETLOG Hax, with credits to: '. 48 | // 49 | // This is essentially a Lesser GPL licence: 50 | // http://creativecommons.org/licenses/LGPL/2.1/ 51 | // With some specific additions to reflect it's SecondLife/LSL origins. 52 | // ---LICENCE END--- 53 | //---------------------------------- 54 | 55 | // CONFIGURATION..... 56 | 57 | // Modify the following values to configure the script. 58 | 59 | // First, the price of the item: 60 | 61 | integer gItemPrice = 23; 62 | 63 | // Second, the list of payees, as UUID keys. 64 | 65 | list gPayeeKeys = [ 66 | // your keys here, separated with commas... 67 | "6d286553-59ae-409a-887d-ee75df67b834" // c'mon.. give a cut to poor Solo. :-) 68 | ]; 69 | 70 | // Don't know how to get a UUID for an avatar? 71 | // Here's how. 72 | // Create a cube. 73 | // Edit it, look in the Contents tab. 74 | // Create a new script. 75 | // Replace the text of the new script with the following line of code: 76 | 77 | // default{touch_start(integer i){llSay(0, (string)llDetectedKey(0));}} 78 | 79 | // Be sure the code is not commented (remove the // at the beginning) 80 | // Click save. Now the cube will say the UUID of anyone who touches it. 81 | 82 | // .....END CONFIGURATION 83 | 84 | default 85 | { 86 | state_entry() 87 | { 88 | state debitPermission; 89 | } 90 | } 91 | 92 | state debitPermission 93 | { 94 | state_entry() 95 | { 96 | llInstantMessage(llGetOwner(), "This script requires that you give it permission to take your money. This is for refunds in case the purchaser pays the wrong amount. You have 30 seconds to give this permission."); 97 | // start the countdown timer.... 98 | llSetTimerEvent(30.0); 99 | llRequestPermissions(llGetOwner(), PERMISSION_DEBIT); 100 | } 101 | 102 | state_exit() 103 | { 104 | // stop the timer 105 | llSetTimerEvent(0.0); 106 | } 107 | 108 | run_time_permissions(integer perms) 109 | { 110 | if (perms & PERMISSION_DEBIT) 111 | { 112 | // yay we can debit! 113 | state acceptPayment; 114 | } 115 | else 116 | { 117 | // oops... no debit. 118 | state deadMachine; 119 | } 120 | } 121 | 122 | timer() 123 | { 124 | // oops... no debit. 125 | state deadMachine; 126 | } 127 | on_rez(integer f){llResetScript();} 128 | } 129 | 130 | state acceptPayment 131 | { 132 | state_entry() 133 | { 134 | // we want one quick pay button with the item price: 135 | llSetPayPrice(PAY_HIDE, [gItemPrice, PAY_HIDE, PAY_HIDE, PAY_HIDE]); 136 | } 137 | 138 | money(key id, integer amount) 139 | { 140 | // first things first: compare the amount to the price 141 | // if they're different do a refund. this could be mondified to 142 | // give change, but something would be really wrong for this 143 | // error to occur, so we'll just do a straight-up refund. 144 | if (amount != gItemPrice) 145 | { 146 | llInstantMessage(id, "The amount you paid was incorrect. It will be refunded. Please try again."); 147 | llGiveMoney(id, amount); 148 | // since this should never happen, we IM the owner. 149 | llInstantMessage(llGetOwner(), "Refunded money to " + llKey2Name(id) + " due to incorrect payment amount."); 150 | } 151 | else 152 | { 153 | // ok, amount is good. Now we divide the amount between payees. 154 | integer i; 155 | integer payeeCount = llGetListLength(gPayeeKeys); 156 | integer amountEach = gItemPrice / (payeeCount + 1); // add one for the object owner 157 | for (i=0; i < payeeCount; i++) 158 | { 159 | llGiveMoney(llList2Key(gPayeeKeys,i), amountEach); 160 | } 161 | } 162 | } 163 | on_rez(integer f){llResetScript();} 164 | } 165 | 166 | 167 | state deadMachine 168 | { 169 | state_entry() 170 | { 171 | llInstantMessage(llGetOwner(), "You have not given the Multi-Payout script permission to take your money. In order to try again, you must reset this script. Edit the object containing it, and select Tools -> Reset Scripts In Selection."); 172 | } 173 | on_rez(integer f){llResetScript();} 174 | } 175 | -------------------------------------------------------------------------------- /super_advanced/[solo] SimplePilot 1.0.lsl: -------------------------------------------------------------------------------- 1 | // SoloFlight 2 | // by Solo Mornington 3 | 4 | // This script is based on the HC-1 flight script by illume Skallagrimson 5 | // but VERY HEAVILY MODIFIED. :-) 6 | 7 | // we only have a position for the sit target, no rotation. it is assumed that 8 | // this script is in the root prim of a zero-rotation object. 9 | vector gSitTarget = <0,0,0.65>; 10 | string gSitText = "Board"; // Text to show in the pie menu for sitting 11 | 12 | string gAnimationName; // this will be the first animation in inventory 13 | string gLoopSound = "mechanical flap"; // the sound to loop during flying. 14 | key gPilot = NULL_KEY; // who's flying? (distinct from passengers) 15 | 16 | // these are values for the vehicle motors 17 | // they'd more properly be state-scope variable for state flying. 18 | // https://jira.secondlife.com/browse/SVC-3297 19 | vector linear; 20 | vector angular; 21 | float water_offset = 0.6; 22 | 23 | // Defining the Parameters of the normal driving camera. 24 | // This will let us follow behind with a loose camera. 25 | list gDriveCam =[ 26 | CAMERA_ACTIVE, TRUE, 27 | CAMERA_BEHINDNESS_ANGLE, 0.0, 28 | CAMERA_BEHINDNESS_LAG, 0.5, 29 | CAMERA_DISTANCE, 6.0, 30 | CAMERA_PITCH, 10.0, 31 | CAMERA_FOCUS_LAG, 0.05, 32 | CAMERA_FOCUS_LOCKED, FALSE, 33 | CAMERA_FOCUS_THRESHOLD, 0.0, 34 | CAMERA_POSITION_LAG, 0.5, 35 | CAMERA_POSITION_LOCKED, FALSE, 36 | CAMERA_POSITION_THRESHOLD, 0.0, 37 | CAMERA_FOCUS_OFFSET, <0,0,0>]; 38 | 39 | // lists of which prims are legs and wings, so we can do special effects 40 | list gWingPrims; 41 | list gLegPrims; 42 | 43 | setVehicle() 44 | { 45 | llCollisionSound("", 0.0); 46 | llSetVehicleType(VEHICLE_TYPE_AIRPLANE); 47 | // linear friction 48 | llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <100.0, 100.0, 100.0>); 49 | // uniform angular friction 50 | llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1.0); 51 | // linear motor 52 | llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0.0, 0.0, 0.0>); 53 | llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, .5); 54 | llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 1.0); 55 | // angular motor 56 | llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0.0, 0.0, 0.0>); 57 | llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, .2); 58 | llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 2.0); 59 | // hover 60 | llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 0.0); 61 | llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.0); 62 | llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 350.0); 63 | llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.981); 64 | // linear deflection 65 | llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.5); 66 | llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 1.0); 67 | // angular deflection 68 | llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.25); 69 | llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 100.0); 70 | // vertical attractor 71 | llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.75); 72 | llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1.0); 73 | // banking 74 | llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.0); 75 | llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 1.0); 76 | llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 360.0); 77 | // default rotation of local frame 78 | llSetVehicleRotationParam(VEHICLE_REFERENCE_FRAME, <0.0, 0.0, 0.0, 1.0>); 79 | // removed vehicle flags 80 | llRemoveVehicleFlags(VEHICLE_FLAG_NO_DEFLECTION_UP 81 | | VEHICLE_FLAG_HOVER_WATER_ONLY 82 | | VEHICLE_FLAG_HOVER_TERRAIN_ONLY 83 | | VEHICLE_FLAG_HOVER_UP_ONLY 84 | | VEHICLE_FLAG_LIMIT_MOTOR_UP 85 | | VEHICLE_FLAG_LIMIT_ROLL_ONLY); 86 | // set vehicle flags 87 | llSetVehicleFlags(VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT); 88 | } 89 | 90 | loadLegAndWingPrims() 91 | { 92 | gWingPrims = []; 93 | gLegPrims = []; 94 | integer i; 95 | list params; 96 | // use llGetObjectPrimCount() so we don't include seated avatars. 97 | integer count = llGetObjectPrimCount(llGetKey()); 98 | for (i=1; i<=count; ++i) 99 | { 100 | params = llGetLinkPrimitiveParams(i, [PRIM_DESC]); 101 | string desc = llList2String(params, 0); 102 | if (desc == "leg") gLegPrims += [i]; 103 | if (desc == "wing") gWingPrims += [i]; 104 | } 105 | } 106 | 107 | newAnimationCheck() 108 | { 109 | // we might have a new animation in inventory 110 | // and if we do, stop the old one and play the new one. 111 | if (gPilot != NULL_KEY) 112 | { 113 | llStopAnimation(gAnimationName); 114 | gAnimationName = llGetInventoryName(INVENTORY_ANIMATION, 0); 115 | llStartAnimation(gAnimationName); 116 | return; 117 | } 118 | gAnimationName = llGetInventoryName(INVENTORY_ANIMATION, 0); 119 | } 120 | 121 | primAlpha(list prims, float alpha) 122 | { 123 | // primAlpha function sets the prims in the list to alpha alpha. 124 | integer i; 125 | integer count = llGetListLength(prims); 126 | for (i=0; i 0.5) 139 | llSetLinkAlpha(llList2Integer(gWingPrims, i), 0.7, ALL_SIDES); 140 | else 141 | llSetLinkAlpha(llList2Integer(gWingPrims, i), 0.3, ALL_SIDES); 142 | } 143 | } 144 | 145 | default 146 | { 147 | // 'default' is not a very descriptive state name, is it? 148 | // So we'll do some init and go to a state with a nice name, like 149 | // 'atRest'. 150 | state_entry() 151 | { 152 | // load up the exception prims 153 | loadLegAndWingPrims(); 154 | // some basic initializations 155 | gPilot = NULL_KEY; 156 | newAnimationCheck(); 157 | llSitTarget(gSitTarget, ZERO_ROTATION); 158 | llSetSitText(gSitText); 159 | state atRest; 160 | } 161 | } 162 | 163 | state atRest 164 | { 165 | // state atRest is the state we should be in when the vehicle is at rest 166 | // just sitting there, as in we just rezzed it, or the avatar stood up from it. 167 | // mainly this state is responsible for going to the flying state when 168 | // the owner sits on the vehicle and we get all our necessary permissions. 169 | state_entry() 170 | { 171 | gPilot = NULL_KEY; 172 | // hide the wings and show the legs 173 | primAlpha(gWingPrims, 0.0); 174 | primAlpha(gLegPrims, 1.0); 175 | // turn off vehicle stuff. 176 | llSetStatus(STATUS_PHYSICS, FALSE); 177 | // TODO: make the vehicle right itself. 178 | // let the whole object know we're at rest. 179 | llMessageLinked(LINK_SET, 0, "flying", NULL_KEY); 180 | } 181 | 182 | changed(integer what) 183 | { 184 | // Whenever an av sits on or stands up from an object, it is treated as if it 185 | // were being linked or unlinked. 186 | // Unfortunately, there are a whole bunch of other things that cause CHANGED_LINK 187 | // as well, so we have to allow for them. 188 | // Things that can cause CHANGED_LINK: 1) linking in new prims, 2) unlinking prims 189 | // 3) avatars sitting, 4) avatars unsitting 190 | if (what & CHANGED_LINK) 191 | { 192 | // are there *any* seated avatars? 193 | if (llGetNumberOfPrims() != llGetObjectPrimCount(llGetKey())) 194 | { 195 | // we have seated avs, so let's find the sit target one 196 | key agent = llAvatarOnSitTarget(); 197 | // same as the owner? 198 | if (agent == llGetOwner()) 199 | { 200 | // store pilot key... 201 | gPilot = agent; 202 | // ask politely for permission do to stuff. 203 | // These will be automatically granted. 204 | llRequestPermissions(agent, 205 | PERMISSION_TRIGGER_ANIMATION | 206 | PERMISSION_TAKE_CONTROLS | 207 | PERMISSION_CONTROL_CAMERA); 208 | } 209 | else 210 | // sit target agent is not the owner 211 | { 212 | llUnSit(agent); 213 | llWhisper(0,"Only the owner can drive this vehicle."); 214 | } 215 | } 216 | else 217 | // there are no seated avatars... 218 | { 219 | if (gPilot != NULL_KEY) 220 | { 221 | // since there are no seated avs, but we still know about 222 | // the pilot, they must have just stood up. 223 | // we need to release controls and do other cleanup 224 | llReleaseControls(); 225 | llClearCameraParams(); 226 | llStopAnimation(gAnimationName); 227 | gPilot = NULL_KEY; 228 | } 229 | } 230 | } 231 | if (what & CHANGED_INVENTORY) 232 | { 233 | // someone might have dropped in a new animation 234 | newAnimationCheck(); 235 | } 236 | } 237 | 238 | run_time_permissions(integer perm) 239 | { 240 | // to be correct, we really should check the perms and make sure we 241 | // got the ones we need. but this will usually work: 242 | if (perm) state flying; 243 | } 244 | 245 | on_rez(integer foo) { state default; } 246 | } 247 | 248 | state flying 249 | { 250 | // state flying assumes we have permission to take controls, run animations, 251 | // and control the camera. 252 | state_entry() 253 | { 254 | // hide the legs, show the wings... 255 | primAlpha(gLegPrims, 0.0); 256 | wingFlapAlpha(); 257 | // play the flying sound 258 | llLoopSound(gLoopSound, 1.0); 259 | llSetTimerEvent(0.05); 260 | llTakeControls( CONTROL_FWD | 261 | CONTROL_BACK | 262 | CONTROL_LEFT | 263 | CONTROL_RIGHT | 264 | CONTROL_ROT_LEFT | 265 | CONTROL_ROT_RIGHT | 266 | CONTROL_UP | 267 | CONTROL_DOWN | 268 | CONTROL_LBUTTON, 269 | TRUE, FALSE); 270 | setVehicle(); 271 | llSetCameraParams(gDriveCam); 272 | llStartAnimation(gAnimationName); 273 | vector current_pos = llGetPos(); 274 | llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, current_pos.z); 275 | llSetStatus(STATUS_PHYSICS, TRUE); 276 | // let the rest of the object know we're flying 277 | llMessageLinked(LINK_SET, 0, "flying", NULL_KEY); 278 | } 279 | 280 | changed(integer what) 281 | { 282 | // Whenever an av sits on or stands up from an object, it is treated as if it 283 | // were being linked or unlinked. 284 | // Unfortunately, there are a whole bunch of other things that cause CHANGED_LINK 285 | // as well, so we have to allow for them. 286 | // Things that can cause CHANGED_LINK: 1) linking in new prims, 2) unlinking prims 287 | // 3) avatars sitting, 4) avatars unsitting 288 | if (what & CHANGED_LINK) 289 | { 290 | // are there *any* seated avatars? 291 | if (llGetNumberOfPrims() == llGetObjectPrimCount(llGetKey())) 292 | { 293 | // there are no seated avatars... 294 | if (gPilot != NULL_KEY) 295 | { 296 | // since there are no seated avs, but we still know about 297 | // the pilot, they must have just stood up, so let's rest. 298 | state atRest; 299 | } 300 | } 301 | } 302 | if (what & CHANGED_INVENTORY) 303 | { 304 | newAnimationCheck(); 305 | } 306 | } 307 | 308 | // The control event is what we get when the user mashed down the keys 309 | // we asked about in llTakeControls(). 310 | control(key id, integer levels, integer edges) 311 | { 312 | if(llGetStatus(STATUS_PHYSICS)!=TRUE) 313 | llSetStatus(STATUS_PHYSICS, TRUE); 314 | 315 | if ((edges & levels & CONTROL_UP)) { 316 | linear.z += 12.0; 317 | } else if ((edges & ~levels & CONTROL_UP)) { 318 | linear.z -= 12.0;} 319 | if ((edges & levels & CONTROL_DOWN)) { 320 | linear.z -= 12.0; 321 | } else if ((edges & ~levels & CONTROL_DOWN)) { 322 | linear.z += 12.0;} 323 | if ((edges & levels & CONTROL_FWD)) { 324 | linear.x += 14.0; 325 | } else if ((edges & ~levels & CONTROL_FWD)) { 326 | linear.x -= 14.0;} 327 | if ((edges & levels & CONTROL_BACK)) { 328 | linear.x -= 14.0; 329 | } else if ((edges & ~levels & CONTROL_BACK)) { 330 | linear.x += 14.0;} 331 | if ((edges & levels & CONTROL_LEFT)) { 332 | linear.y += 8.0; 333 | } else if ((edges & ~levels & CONTROL_LEFT)) { 334 | linear.y -= 8.0;} 335 | if ((edges & levels & CONTROL_RIGHT)) { 336 | linear.y -= 8.0; 337 | } else if ((edges & ~levels & CONTROL_RIGHT)) { 338 | linear.y += 8.0;} 339 | if ((edges & levels & CONTROL_ROT_LEFT)) { 340 | angular.z += (PI / 180) * 55.0; 341 | angular.x -= PI * 4; 342 | } else if ((edges & ~levels & CONTROL_ROT_LEFT)) { 343 | angular.z -= (PI / 180) * 55.0; 344 | angular.x += PI * 4;} 345 | if ((edges & levels & CONTROL_ROT_RIGHT)) { 346 | angular.z -= (PI / 180) * 55.0; 347 | angular.x += PI * 4; 348 | } else if ((edges & ~levels & CONTROL_ROT_RIGHT)) { 349 | angular.z += (PI / 180) * 55.0; 350 | angular.x -= PI * 4; 351 | } 352 | } 353 | 354 | timer() 355 | { 356 | wingFlapAlpha(); 357 | vector vel = llGetVel(); 358 | float water = llWater(vel * 0.05); 359 | float ground = llGround(vel * 0.05); 360 | if (water > ground) { // above water 361 | vector MahPos = llGetPos(); 362 | if (MahPos.z < water+water_offset){ 363 | llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.5); 364 | llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 0.1); 365 | llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, water + water_offset); 366 | } 367 | else { 368 | llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.0); 369 | llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 350.0); 370 | } 371 | } 372 | else { // above ground 373 | llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.0); 374 | llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 350.0); 375 | } 376 | 377 | llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, linear); 378 | llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular); 379 | } 380 | 381 | state_exit() 382 | { 383 | // we need to release controls and do other cleanup 384 | llStopSound(); 385 | llReleaseControls(); 386 | llClearCameraParams(); 387 | llStopAnimation(gAnimationName); 388 | } 389 | 390 | on_rez(integer foo) { state default; } 391 | } 392 | -------------------------------------------------------------------------------- /super_advanced/[solo] Thrower 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Thrower 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script is in memory of the late lamented Brooklyn is Watching project. 13 | 14 | // This script allows the user to throw items. The items are in the object 15 | // inventory. The script cycles through all items. The items will have to 16 | // be physical, and should be temp, so they won't make the whole place 17 | // terrible and cluttered with physical junk that no one really wants. :-) 18 | 19 | // After throwing, the thrower object disappears and the 'holding' animation 20 | // stops. After a few seconds, it reappears. This gives the impression of 21 | // having actually thrown the object. 22 | 23 | // The script needs two animations, named here: 24 | 25 | string gHoldingAnimation = "bombhold"; 26 | string gThrowingAnimation = "bombthrow"; 27 | 28 | integer gCurrentObject = -1; 29 | 30 | do_throw() 31 | { 32 | // This function does the actual rezzing of the projectile. 33 | // The math here is taken out of Ben Linden's Popgun object from 34 | // the Library. 35 | rotation rot = llGetRot(); 36 | vector fwd = llRot2Fwd(rot); 37 | vector pos = llGetPos(); 38 | pos = pos + fwd; 39 | pos.z += 0.75; // Correct to eye point 40 | fwd = fwd * 15.0; 41 | 42 | ++gCurrentObject; 43 | if (gCurrentObject >= llGetInventoryNumber(INVENTORY_OBJECT)) 44 | gCurrentObject = 0; 45 | string projectile = llGetInventoryName(INVENTORY_OBJECT, gCurrentObject); 46 | llRezObject(projectile, pos, fwd, rot, 2); 47 | } 48 | 49 | default 50 | { 51 | // get started with the permissions. 52 | state_entry() 53 | { 54 | llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION | 55 | PERMISSION_TAKE_CONTROLS | PERMISSION_ATTACH); 56 | } 57 | 58 | run_time_permissions(integer permissions) 59 | { 60 | if (permissions > 0) 61 | { 62 | // OK, we have permission, so take over the mouselook button click 63 | llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); 64 | if (!llGetAttached()) 65 | { 66 | // ...and if we're not attached, try to attach to the avatar's 67 | // right hand. 68 | llAttachToAvatar(ATTACH_RHAND); 69 | } 70 | else 71 | { 72 | // all is well so go to 'holding.' 73 | state holding; 74 | } 75 | } 76 | } 77 | 78 | attach(key attachedAgent) 79 | { 80 | if (attachedAgent != NULL_KEY) 81 | { 82 | // if we were able to attach to the avatar, go to 'holding.' 83 | state holding; 84 | } 85 | } 86 | 87 | on_rez(integer foo) 88 | { llResetScript(); } 89 | } 90 | 91 | state holding 92 | { 93 | // standing around ready to throw 94 | 95 | state_entry() 96 | { 97 | // if we're in this state we have permissions 98 | // we've taken controls 99 | // and the object is attached 100 | // so show the 'holding' animation. 101 | llStartAnimation(gHoldingAnimation); 102 | } 103 | 104 | control(key name, integer levels, integer edges) 105 | { 106 | // this inelegant code tells us whether the user pressed 107 | // the mouselook button. 108 | if ( ((edges & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) 109 | &&((levels & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) ) 110 | { 111 | { 112 | // and they did press the mouselook button, so it's 113 | // time for 'throwing.' 114 | state throwing; 115 | } 116 | } 117 | } 118 | 119 | state_exit() 120 | { 121 | // any time we leave this state we should stop the holding anim. 122 | llStopAnimation(gHoldingAnimation); 123 | } 124 | 125 | on_rez(integer foo) 126 | { state default; } 127 | } 128 | 129 | state throwing 130 | { 131 | // doing the actual throw 132 | 133 | state_entry() 134 | { 135 | // show the 'throwing' animation 136 | llStartAnimation(gThrowingAnimation); 137 | // let the arm do the throw before rezzing. adjust as needed. 138 | llSetTimerEvent(0.25); 139 | // you can preload a sound here, so it's ready when the 140 | // projectile needs it 141 | //llPreloadSound("2e3fa950-4e09-1741-a826-54366c9b65a1"); 142 | } 143 | 144 | timer() 145 | { 146 | // rez projectile... 147 | do_throw(); 148 | // hide the object in hand 149 | llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES); 150 | // stop for a while. 151 | state snooze; 152 | } 153 | 154 | on_rez(integer foo) 155 | { state default; } 156 | } 157 | 158 | state snooze 159 | { 160 | // the time between the end of the throw and 161 | // when the next ornament appears in av's hand 162 | state_entry() 163 | { 164 | // stop the throwing animation 165 | llStopAnimation(gThrowingAnimation); 166 | llSetTimerEvent(2.0); 167 | } 168 | timer() 169 | { 170 | // ok, reload.... 171 | llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); 172 | // and go back to 'holding.' 173 | state holding; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /very_basic/Cinco's Ultra-Simple Teleport Script 2.0.lsl: -------------------------------------------------------------------------------- 1 | // Cinco's Teleporter 2.0 2 | 3 | // THIS NOTICE MUST REMAIN INTACT: 4 | // Copyright 2010, Cinco Pizzicato 5 | // License: Use freely in any way you want. Modified versions 6 | // may be used in any way. No credit or acknowledgement required. 7 | // Definitive source and updates available here: 8 | // http://github.com/SoloMornington/Solos-Script-Repository 9 | // ** end notice 10 | 11 | // a very basic teleporter script by Cinco Pizzicato, totally ripped and mangled from 12 | // Teleporter Script v 3.0 by Asira Sakai 13 | // 14 | // no notecards, no hard-coding. HOW TO: 15 | 16 | // 1) The name of the prim will be it's hover text. 17 | 18 | // 2) The description of the prim will be the destination vector. 19 | // you can find the text to put in the description by rezzing a cube 20 | // where you want to end up. Put this script into it: 21 | // 22 | // default{state_entry(){llOwnerSay((string)llGetPos());}} 23 | // 24 | // then copy the chat text you see into the teleport prim's description. 25 | 26 | // 3) You'll probably need to make another prim for the return voyage. 27 | 28 | // updates for v.2.0: Now using the new llSetRegionPos() function. 29 | // http://wiki.secondlife.com/wiki/LlSetRegionPos 30 | 31 | vector gHomeVector; // where I should go back; updated every teleport 32 | 33 | default 34 | { 35 | state_entry() 36 | { 37 | // basic init stuff 38 | // put the object name in the hover text 39 | llSetText(llGetObjectName(), <1.0,1.0,1.0>, 1.0); 40 | // set a sit target... we have to do this to trigger 41 | // a changed event 42 | llSitTarget(<0.0,0.0,0.1>, ZERO_ROTATION); 43 | // and a nice sit text, which is completely ignored by viewer 2. 44 | llSetSitText("Teleport"); 45 | // make sure no one's sitting..... 46 | llUnSit(llAvatarOnSitTarget()); 47 | } 48 | 49 | changed(integer change) 50 | { 51 | if (change & CHANGED_LINK) 52 | { // if a link change occurs (sit or unsit) 53 | if(llAvatarOnSitTarget() != NULL_KEY) 54 | { 55 | vector targetVector = (vector)llGetObjectDesc(); // where are we headed? 56 | if (targetVector != ZERO_VECTOR) 57 | { 58 | llSetStatus(STATUS_PHANTOM,TRUE); 59 | gHomeVector = llGetPos(); // record current position for return 60 | if (llSetRegionPos(targetVector)) 61 | { 62 | // the teleporter moved to the target 63 | llUnSit(llAvatarOnSitTarget()); // unsit him 64 | llSetRegionPos(gHomeVector); // teleport back to old position 65 | } 66 | else 67 | { 68 | // teleporter didn't go where it should have. 69 | llUnSit(llAvatarOnSitTarget()); // unsit him 70 | llOwnerSay("This teleporter was unable to move to the destination."); 71 | } 72 | llSetStatus(STATUS_PHANTOM,FALSE); 73 | } 74 | else llOwnerSay("This teleporter has a bad destination in its description."); 75 | } 76 | // if someone links the object, we reset the script. 77 | else llResetScript(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /very_basic/Proximity Alpha 0.2.lsl: -------------------------------------------------------------------------------- 1 | // Proximity Alpha 2 | // by Cinco Pizzicato 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Cinco Pizzicato 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // A sensor that changes the alpha transparency of an object. 13 | 14 | // Change this number to a new distance to tweak the behavior: 15 | float gSensorDistance = 5.0; 16 | 17 | // don't change anything below here, unless you know what you're doing, 18 | // and if yo do, and it works better, please let me know. :-) --Cinco Pizzicato 19 | 20 | float gAlpha = 0.0; 21 | 22 | default 23 | { 24 | state_entry() 25 | { 26 | // First, set up the sensor repeat 27 | llSensorRepeat("",NULL_KEY,AGENT,gSensorDistance,PI, 1.0); 28 | // ...and set the alpha 29 | llSetLinkAlpha(LINK_SET, gAlpha, ALL_SIDES); 30 | } 31 | 32 | sensor(integer num_detected) 33 | { 34 | // Start by getting my position 35 | vector myPos = llGetPos(); 36 | // and the position of the nearest avatar 37 | vector targetPos = llDetectedPos(0); 38 | // how far to the avatar? 39 | float targetDistance = llVecDist(myPos, targetPos); 40 | // Use this to calculate the alpha 41 | gAlpha = 1.0 - (targetDistance / gSensorDistance); 42 | // ...and set it. 43 | llSetLinkAlpha(LINK_SET, gAlpha, ALL_SIDES); 44 | } 45 | 46 | no_sensor() 47 | { 48 | // there's no av nerarby, so... 49 | // ... if the alpha isn't already 0... 50 | if (gAlpha != 0.0) 51 | { 52 | // ... set it to 0. 53 | gAlpha = 0.0; 54 | llSetLinkAlpha(LINK_SET, gAlpha, ALL_SIDES); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /very_basic/[solo] Basic Wear:Animate script 1.0.lsl: -------------------------------------------------------------------------------- 1 | // BASIC WEAR/ANIMATE SCRIPT 1.0 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // A very basic framework script for others to modify 13 | // hopefully illustrating some best-practices 14 | // 15 | // inspired by Catherine Omega's basic animation script on lslwiki.net 16 | 17 | // WHAT THIS SCRIPT DOES: 18 | // it plays an animation when the avatar wears the prim containing the script. 19 | // it illustrates how to use the permissions system 20 | 21 | // HOW TO USE IT: 22 | // put this script in an object. this script should be in the root prim of the object 23 | // change the next line to reflect the name of the animation you want to play 24 | 25 | list gAnimations = [ 26 | "[solo] karakasa spine lock", 27 | "[solo] shoulders up" 28 | ]; // what animation to play? 29 | 30 | // NOTE: I use a naming convention of putting g at the start of any 31 | // global variable. This makes it easier to see which variables have 32 | // which scope. 33 | 34 | default 35 | { 36 | state_entry() 37 | { 38 | // when we come to state_entry, it can be from a number of different circumstances: 39 | // 1) the script has been reset 40 | // 2) the script has been edited 41 | // 3) the prim has been shift-drag copied 42 | // note that none of these have anything to do with being worn or removed. 43 | // but because we're probably going to be editing this script, and since the 44 | // user might reset it while wearing it, let's figure out if we're attached.... 45 | if (llGetAttached()) 46 | { 47 | // yes, we're attached, so we ask for permission to play animations. 48 | // which starts the whole cascade of permissions being given and 49 | // animation-playing. we also request the ability to take over the 50 | // controls, so that this script will stand a better chance of running 51 | // in no-script areas. 52 | llRequestPermissions(llGetOwner(), 53 | PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); 54 | } 55 | } 56 | 57 | run_time_permissions(integer perm) 58 | { 59 | // handle the permissions change, in case the user resets the script 60 | // or the scripter is changing the script and doesn't want to detach/reattach 61 | // as part of the development cycle 62 | // or the object goes across a sim border 63 | // or the avatar teleports 64 | // 65 | // all other code leads here. 66 | // when the user does anything with this scripted object, it will 67 | // ask for permission to trigger animations. 68 | // this event will always fire when we ask permissions, even if 69 | // we already have those permissions. 70 | // therefore we only ever start animations here. 71 | if (perm & PERMISSION_TRIGGER_ANIMATION) 72 | { 73 | // yay we got permission, so let's start animating: 74 | integer i; 75 | integer count = llGetListLength(gAnimations); 76 | for(i=0; i, 1.0); 33 | } 34 | 35 | default 36 | { 37 | state_entry() 38 | { 39 | // when we start up, we want to see the hover text. 40 | setText(gTotalDonations); 41 | } 42 | 43 | money(key giver, integer amount) 44 | { 45 | // the money event happens whenever anyone pays the object. 46 | // it tells us who gave the money, and how much. 47 | // we can thank them by speaking out loud into chat. 48 | // (an obvious modification would be to IM them with thanks, instead of 49 | // announcing in public chat.) 50 | // if you don't want the donation box to talk, comment out 51 | // the following line: 52 | llSay(0, "Thank you, " + llKey2Name(giver) + " for your donation!"); 53 | // add the amount to the total 54 | gTotalDonations += amount; 55 | // show the donation in the hovertext 56 | setText(amount); 57 | // when we add the amount to the total, up there, the total 58 | // could go above the maximum. However, if we cap the total back to 0, 59 | // or limit the total shown, then the donor might be a bit disappointed 60 | // that their donation didn't count to the total. 61 | // thus, we cap the maximum after the display. The next donors' 62 | // donation will show a less shocking reduction in total. 63 | if (gTotalDonations >= gMaxDonations) gTotalDonations = 0; 64 | } 65 | 66 | on_rez(integer foo) 67 | { 68 | // on_rez happens when a scripted object is rezzed from inventory 69 | // and in our case, this means we should reset the totals 70 | // and display this new information. 71 | gTotalDonations = 21; 72 | setText(gTotalDonations); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /very_basic/[solo] Drink Your Tea 1.3.lsl: -------------------------------------------------------------------------------- 1 | // Drink Your Tea 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // Based on a script called Drink by Francis Chung 13 | // Gutted and gussied-up by Solo Mornington in June, 2008 14 | // If you improve this, please let me know how. :-) 15 | 16 | // This is basically a tiny, limited animation overrider. 17 | 18 | // IMPROVEMENTS: Will not sip while doing things you wouldn't sip during, such as 19 | // moving around (either flying or walking), typing, etc. 20 | 21 | // I use gVariableName as a coding convention for global variables. 22 | // It makes them instantly recognizeable. 23 | 24 | // Here's a global list of animation states we are concerned with: 25 | 26 | list gReplaceTheseAnimations = ["Sitting", "Sitting on Ground", "Standing", "Hovering"]; 27 | 28 | default 29 | { 30 | state_entry() 31 | { 32 | // first things first: we ask for permission to trigger animations 33 | // and also permission to take controls. 34 | // we ask for controls because if we don't register a control, 35 | // this script will stop working in no-script areas. 36 | llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); 37 | } 38 | 39 | run_time_permissions(integer parm) 40 | { 41 | // it's pretty much a given than we'll get the permissions that we want, 42 | // but this code makes it clear what we're doing: 43 | if(parm & PERMISSION_TRIGGER_ANIMATION) 44 | { 45 | // we got permission to trigger animations, so we start the 'drinking' animation 46 | // and set the timer event which will play the 'sipping' animation. 47 | llSetTimerEvent(23.0); 48 | llStartAnimation("drink"); 49 | } 50 | if (parm & PERMISSION_TAKE_CONTROLS) 51 | { 52 | // we only want to take control so the script keeps working in no-script areas. 53 | // so we don't accept anything and pass on everything 54 | llTakeControls(CONTROL_ML_LBUTTON, FALSE, TRUE); 55 | } 56 | } 57 | 58 | on_rez(integer st) 59 | { 60 | // when the object is rezzed, we want to be sure to reset our permissions 61 | // and ask for them again, so the proper animations will be playing. 62 | llResetScript(); 63 | } 64 | 65 | changed(integer c) 66 | { 67 | // changed is fired for a lot of different reasons, all of them 68 | // good reasons to reset this script. If we were filtering any out 69 | // we'd be sure and include CHANGED_TELEPORT, because the sim we'd TPd 70 | // to wouldn't know what animations to be playing. 71 | llResetScript(); 72 | } 73 | 74 | attach(key id) 75 | { 76 | // when the object is detached, this is our last chance to stop 77 | // the holding-a-cup animation. 78 | llStopAnimation("drink"); 79 | } 80 | 81 | timer() 82 | { 83 | // The timer event is where we play the 'sipping' animation. 84 | // But we don't always want to play it, because sometimes 85 | // the av might be in situations where no one would take a 86 | // sip of anything, like falling or typing. 87 | // We want to rule out all the possibilities that we can 88 | // using llGetAgentInfo(), because bitwise math is very quick. 89 | integer agentInfo = llGetAgentInfo(llGetPermissionsKey()); 90 | 91 | // check for walking, typing, crouching and (away)... 92 | if (agentInfo & (AGENT_WALKING | 93 | AGENT_TYPING | 94 | AGENT_CROUCHING | 95 | AGENT_AWAY )) return; 96 | // check for falling, jumping, or being launched through the air 97 | if ((agentInfo & AGENT_IN_AIR) && !(agentInfo & AGENT_FLYING)) return; 98 | 99 | // get the current animation state 100 | // we cast this as a list so it's easier to compare 101 | list animationState = [llGetAnimation(llGetPermissionsKey())]; 102 | 103 | // If the current animation state is in our list, then we're good. 104 | // This type of list manipulation is a very common LSL coding pattern. 105 | if (llListFindList(gReplaceTheseAnimations, animationState) != -1) 106 | { 107 | llStartAnimation("sipping sl"); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /very_basic/[solo] Give All Notecards 0.1.lsl: -------------------------------------------------------------------------------- 1 | // [solo] Give All Notecards 0.1 2 | 3 | // THIS NOTICE MUST REMAIN INTACT: 4 | // Copyright 2010, Solo Mornington 5 | // License: Use freely in any way you want. Modified versions 6 | // may be used in any way. No credit or acknowledgement required. 7 | // Definitive source and updates available here: 8 | // http://github.com/SoloMornington/Solos-Script-Repository 9 | // ** end notice 10 | 11 | // The most complete and correct notecard giver script ever. :-) 12 | // Now there's no excuse for script errors when someone clicks 13 | // for a notecard. 14 | 15 | // TO USE: Place this script in an object. Place a notecard in the object. 16 | // When a resident clicks on ('touches') the object, they will be given 17 | // the notecard. 18 | 19 | // Change the following line to alter the hovertext displayed. 20 | 21 | string gHoverText = "Touch for informative notecard."; 22 | 23 | giveAllNotecards(key avatar) 24 | { 25 | // hand out all the notecards..... 26 | integer count = llGetInventoryNumber(INVENTORY_NOTECARD); 27 | integer i; 28 | for(i=0; i, 1.0); 40 | } 41 | 42 | touch_start(integer total_number) 43 | { 44 | // If the name isn't empty.... 45 | if (llGetInventoryName(INVENTORY_NOTECARD, 0) != "") 46 | { 47 | // loop through all the touch_starts. 48 | // usually this is extraneous work, but it does matter. 49 | integer i; 50 | for (i=0; i < total_number; ++i) 51 | { 52 | giveAllNotecards(llDetectedKey(i)); 53 | } 54 | } 55 | else 56 | // There was no notecard, so tell the user. 57 | llSay(0, "There is no notecard to give. Please contact the owner of this object."); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /very_basic/[solo] Give First Notecard 0.3.lsl: -------------------------------------------------------------------------------- 1 | // [solo] Give First Notecard 0.3 2 | 3 | // THIS NOTICE MUST REMAIN INTACT: 4 | // Copyright 2010, Solo Mornington 5 | // License: Use freely in any way you want. Modified versions 6 | // may be used in any way. No credit or acknowledgement required. 7 | // Definitive source and updates available here: 8 | // http://github.com/SoloMornington/Solos-Script-Repository 9 | // ** end notice 10 | 11 | // The most complete and correct notecard giver script ever. :-) 12 | // Now there's no excuse for script errors when someone clicks 13 | // for a notecard. 14 | 15 | // TO USE: Place this script in an object. Place a notecard in the object. 16 | // When a resident clicks on ('touches') the object, they will be given 17 | // the notecard. 18 | 19 | // Please uncheck 'Mono' when you compile. Be nice to everyone on the sim. 20 | 21 | // Change the following line to alter the hovertext displayed. 22 | 23 | string gHoverText = "Touch for informative notecard."; 24 | 25 | default 26 | { 27 | state_entry() 28 | { 29 | // Set up the hover text.... 30 | //llSetText(gHoverText, <1,1,1>, 1.0); 31 | } 32 | 33 | touch_start(integer total_number) 34 | { 35 | // Get the name of the first notecard 36 | string notecard = llGetInventoryName(INVENTORY_LANDMARK, 0); 37 | // If the name isn't empty.... 38 | if (notecard != "") 39 | { 40 | // loop through all the touch_starts. 41 | // usually this is extraneous work, but it does matter. 42 | integer i; 43 | for (i=0; i < total_number; ++i) 44 | { 45 | llGiveInventory(llDetectedKey(i), notecard); 46 | } 47 | } 48 | else 49 | // There was no notecard, so tell the user. 50 | llSay(0, "There is no landmark to give. Please contact the owner of this object."); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /very_basic/[solo] Object Die.lsl: -------------------------------------------------------------------------------- 1 | // Object Die 2 | // by Solo Mornington 3 | 4 | // This is the simplest script in the universe. 5 | // However, it requires careful use. 6 | // It will destroy any object that contains it. 7 | // That is to say, if you put this script in an object, 8 | // that object will be destroyed. 9 | // It won't be in Trash or Lost and Found, it will be well and truly 10 | // GONE. 11 | 12 | // Uses for this script: 13 | // Destroying a megaprim you can't seem to edit through the viewer. 14 | // Destroying any object over which you have mod rights. 15 | // Being evil. 16 | // Being good. 17 | 18 | default 19 | { 20 | state_entry() 21 | { 22 | llDie(); 23 | } 24 | } 25 | 26 | // THIS NOTICE MUST REMAIN INTACT: 27 | // Copyright 2010, Solo Mornington 28 | // License: Use freely in any way you want. Modified versions 29 | // may be used in any way. No credit or acknowledgement required. 30 | // Definitive source and updates available here: 31 | // http://github.com/SoloMornington/Solos-Script-Repository 32 | // ** end notice 33 | -------------------------------------------------------------------------------- /very_basic/[solo] Phantom Children.lsl: -------------------------------------------------------------------------------- 1 | // Phantom Children 2 | // by Solo Mornington 3 | // 4 | // Based on the hard work of these people: 5 | // http://wiki.secondlife.com/wiki/Phantom_Child 6 | // Particularly ninjafoo Ng. 7 | // 8 | // This script is a generalized phantom-child-prim-setter. 9 | // Currently, it sets all prims with 'phantom' in their 10 | // description as phantom. All other prims are non-phantom. 11 | // 12 | // It can be easily modified by changing the shouldSetThisPhantom() 13 | // function to reflect whatever logic you want. For instance 14 | // if you wanted it to change only scultpy prims to phantom, 15 | // then your function might look like this: 16 | // 17 | // integer shouldSetThisPhantom(integer linknumber) 18 | // { 19 | // list params = llGetLinkPrimitiveParams(linknumber, [PRIM_TYPE]); 20 | // return PRIM_TYPE_SCULPT == llList2Integer(params, 0); 21 | // } 22 | // 23 | 24 | list PRIM_PHANTOM_HACK = [ 25 | PRIM_FLEXIBLE, 1, 0, 0.0, 0.0, 0.0, 0.0, <0,0,0>, 26 | PRIM_FLEXIBLE, 0, 0, 0.0, 0.0, 0.0, 0.0, <0,0,0> 27 | ]; 28 | 29 | integer shouldSetThisPhantom(integer linknumber) 30 | { 31 | // This is a callback function to setAllPhantom(). 32 | // Return TRUE to have linknumber set phantom, FALSE otherwise. 33 | // This function is factored out so that you can put your own 34 | // logic into it. Re-use the rest of the script and just change 35 | // this part for different phantom-prim scenarios. 36 | list params = llGetLinkPrimitiveParams(linknumber, [PRIM_DESC]); 37 | return llStringTrim(llList2String(params, 0), STRING_TRIM) == "phantom"; 38 | } 39 | 40 | setAllPhantom() 41 | { 42 | // We have to use llSetStatus to set all of the prims non-phantom 43 | // and then only set the phantom ones on the loop. 44 | // This could potentially be mean to anyone who's using 45 | // the object at the time. 46 | llSetStatus(STATUS_PHANTOM, FALSE); 47 | // Get the total prim count. 48 | // llGetObjectPrimCount() avoids seated avatars 49 | integer prims = llGetObjectPrimCount(llGetKey()); 50 | // We don't want to change the root prim, and if 51 | // there are no child prims then there's nothing else to do. 52 | if (prims < 2) return; 53 | integer i; 54 | list params; 55 | // LSL has a stupid way of referring to root and child prims. 56 | // If there's only one prim, then the lowest link number is 57 | // 0, but if there are more, it's 1. 58 | for (i=1; i<=prims; ++i) 59 | { 60 | if (shouldSetThisPhantom(i)) 61 | { 62 | params = llGetLinkPrimitiveParams(i,[PRIM_TYPE]); 63 | llSetLinkPrimitiveParamsFast(i, 64 | [PRIM_TYPE, PRIM_TYPE_BOX, PRIM_HOLE_DEFAULT, <0,1,0>, 0, <0,0,0>, <1,1,0>, <0,0,0>] 65 | + PRIM_PHANTOM_HACK 66 | + [PRIM_TYPE] + params 67 | ); 68 | } 69 | } 70 | } 71 | 72 | default 73 | { 74 | // Just a few events where we want to do this process. 75 | // state_entry, when the sim restarts, and when the 76 | // user links in a new prim. Ideally, we'd have an 77 | // event for when the user changes the descriptions, 78 | // but that's not available to us. 79 | state_entry() 80 | { 81 | setAllPhantom(); 82 | } 83 | 84 | changed (integer what){ 85 | if ((CHANGED_REGION_START & what) || 86 | (CHANGED_LINK & what)) 87 | { 88 | setAllPhantom(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /very_basic/[solo] Physical On Delink 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Physical On Delink 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // this script has minimal responsibilities. 13 | // when the prim containing it is unlinked, and is the only prim in 14 | // the link set, it will wait for some time and then become physical 15 | // and start a process of dying. 16 | // we wait in order to prevent editing from destroying the object. 17 | 18 | // the delay on the physics part exists because I wanted to keep prims 19 | // around in my project, so they'd pile up as debris. Modifications could 20 | // include setting the prim to be temp and physical at the same time, and 21 | // thus getting rid of state die. 22 | 23 | 24 | float gWaitTime = 5.0; // How long after we're delinked? 25 | float gPhysicsTime = 60.0; // How long after we're physical but before llDie? 26 | 27 | default 28 | { 29 | changed(integer change) 30 | { 31 | if (change & CHANGED_LINK) 32 | { 33 | // we know we were linked or delinked. 34 | if (llGetObjectPrimCount(llGetKey()) <= 1) 35 | { 36 | // we're the only prim in the linkset 37 | llSetTimerEvent(gWaitTime); 38 | } 39 | else 40 | { 41 | // we were just linked back in to an object 42 | // so turn off the timer 43 | llSetTimerEvent(0.0); 44 | } 45 | } 46 | } 47 | 48 | timer() 49 | { 50 | // gWaitTime is over... so do the deed. 51 | state physics; 52 | } 53 | } 54 | 55 | state physics 56 | { 57 | state_entry() 58 | { 59 | // OK, we're delinked and it's time to turn physical. 60 | // We set a timer... 61 | llSetTimerEvent(gPhysicsTime); 62 | // and turn on the gravity. 63 | llSetStatus(STATUS_PHYSICS, TRUE); 64 | } 65 | 66 | timer() 67 | { 68 | state die; 69 | } 70 | } 71 | 72 | state die 73 | { 74 | state_entry() 75 | { 76 | // In this script, we just call llDie, to delete the prim. 77 | // This could be modified to turn the prim temp, for instance. 78 | llDie(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /very_basic/[solo] Play Sound On Sit.lsl: -------------------------------------------------------------------------------- 1 | // Play Sound On Sit 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script will play a sound whenever anyone sits on the object. 13 | // It can be easily modified to do something else whenever anyone sits. 14 | 15 | integer gAvCount = 0; 16 | 17 | avSat() 18 | { 19 | // this function is the callback function that gets called 20 | // whenever a new av sits on the object. 21 | // You can change this. For now, however, it's a fart sound: 22 | llLoopSound("900bdb8a-a208-1c9b-c08e-c67016bf3069", 1.0); 23 | } 24 | 25 | avUnsat() 26 | { 27 | // this function is the callback that gets called 28 | // whenever an av gets up off the object. 29 | llStopSound(); 30 | } 31 | 32 | default 33 | { 34 | state_entry() 35 | { 36 | // store the current number of avs sitting on the object. 37 | // llGetNumberOfPrims() returns the number of linked items, including 38 | // seated avatars. llGetObjectPrimCount() includes only prims. Thus 39 | // the difference between them is the number of seated avatars. 40 | gAvCount = llGetNumberOfPrims() - llGetObjectPrimCount(llGetKey()); 41 | } 42 | 43 | changed(integer what) 44 | { 45 | if (what & CHANGED_LINK) 46 | { 47 | // either the owner edited the object, or an av got up or sat down 48 | // figure out the av count... see state_entry for explanation. 49 | integer currentAvCount = llGetNumberOfPrims() - llGetObjectPrimCount(llGetKey()); 50 | if (currentAvCount > gAvCount) 51 | { 52 | // the number of seated avatars has increased, so 53 | // we want to do something. we'll use this callback function 54 | // for modularity. 55 | avSat(); 56 | } 57 | else if (currentAvCount < gAvCount) 58 | { 59 | // the number of seated avatars has decreased 60 | // so we want to do something. we'll use the callback for 61 | // unseated avatars.... 62 | avUnsat(); 63 | } 64 | // regardless of whether we did the callback function, 65 | // we can update the global av count. this is easier 66 | // and probably quicker than figuring out if the new number is 67 | // different from the global one. 68 | gAvCount = currentAvCount; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /very_basic/[solo] Preload Slideshow.lsl: -------------------------------------------------------------------------------- 1 | // Preload Slideshow 2 | // by 3 | // Solo Mornington 4 | 5 | // v.1.0 6 | 7 | // What this does is cover all sides of a prim with all the textures 8 | // in inventory and rotates through them. This means you can set all 9 | // the sides to black except one for a slideshow, and all the textures 10 | // will be preloaded. Alternately, you could use it to preload textures 11 | // in an environment of some sort. 12 | 13 | float gInterval = 23.0; // How long before we switch to the next texture? 14 | 15 | list gTextures; // list of texures in prim inventory 16 | integer gTexturePointer = 0; // which of gTextures is the texture for the 0th face? 17 | 18 | load_gTextures() 19 | { 20 | // load all the textures into gTextures 21 | gTextures = []; 22 | integer i; 23 | integer count = llGetInventoryNumber(INVENTORY_TEXTURE); 24 | for (i=0; i, ZERO_VECTOR, 0.0]; 48 | if (currentTexture >= textureCount) currentTexture = 0; 49 | } 50 | llSetLinkPrimitiveParamsFast(LINK_THIS, params); 51 | if (++gTexturePointer >= textureCount) gTexturePointer = 0; 52 | } 53 | 54 | default 55 | { 56 | state_entry() 57 | { 58 | // first initialize the texture list 59 | load_gTextures(); 60 | // next paint the textures on all the sides 61 | applyFaceTextures(); 62 | // finally set up the timer interval. 63 | llSetTimerEvent(gInterval); 64 | } 65 | 66 | changed(integer what) 67 | { 68 | // in the changed event, the user could have edited the object 69 | // which would change the number of sides, or added items to 70 | // inventory, which might change the number of textures. 71 | // so we just deal with all those concerns this way: 72 | // reload the textures 73 | load_gTextures(); 74 | // figure out if gTexturePointer is too big, and points to 75 | // a non-existent item in the gTextures list 76 | integer textureCount = llGetListLength(gTextures); 77 | if (gTexturePointer >= textureCount) gTexturePointer = textureCount - 1; 78 | // apply the new textures. 79 | applyFaceTextures(); 80 | } 81 | 82 | timer() 83 | { 84 | // paint the sides with the textures. 85 | applyFaceTextures(); 86 | } 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /very_basic/[solo] Put Prim Name In Hover, Then Delete 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Put Prim Name In Hovertext Then Delete 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This script puts the name of the object into the object's hovertext 13 | // and then deletes itself. 14 | 15 | // This is primarily so you can drag the script out of inventory 16 | // and drop it into a prim, in order to set the hovertext to the 17 | // prim name. 18 | 19 | // This follows a common LSL coding pattern: doing something and then 20 | // deleting the script. 21 | 22 | // This technique can be very useful for a number of different applications. 23 | // For instance, see the related Die Prim script. Or if you want an object 24 | // to chat its rotation, so you can copy/paste it somewhere. 25 | 26 | default 27 | { 28 | state_entry() 29 | { 30 | llSetText(llGetObjectName(), <1,1,1>, 1.0); 31 | llRemoveInventory(llGetScriptName()); // delete this script 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /very_basic/[solo] Read A Notecard.lsl: -------------------------------------------------------------------------------- 1 | // Read A Notecard 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2012, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This is a script that demonstrates how to read a notecard. 13 | 14 | // All it does is read the notecard and say each line aloud. 15 | 16 | // There are a few things to keep in mind when trying to read a notecard in LSL: 17 | 18 | // 1) The Empty Notecard Bug: There is a bug/feature of SL that says 19 | // that you can make a new notecard in your avatar's inventory, save 20 | // it without any text, and then drag it into the inventory of an object. 21 | // LSL inventory functions can learn the name of this notecard, so you 22 | // would think that it exists. But it doesn't, really. When you try 23 | // to read it, LSL will throw an error. Here is a JIRA about it: 24 | // https://jira.secondlife.com/browse/SVC-5293 25 | 26 | // 2) Design Patterns: There are many contexts in which you'd want to 27 | // read a notecard. In some circumstances you'd need to read the 28 | // notecard while something else is happening. In other circumstances 29 | // you'd want to read a notecard *before* something else happens, as 30 | // with a configuration notecard. These are design decisions that 31 | // need to be made. This script demonstrates how to read a notecard 32 | // as its own state in the script, as you might for a configuration script, 33 | // because this will give a simpler illustration that can be adapted 34 | // for other contexts. 35 | 36 | // GLOBAL VARIABLES: (I mark them with g at the start) 37 | // Since notecards are read line-by-line in an event, we have to 38 | // keep track of which line we're reading, and which notecard we want 39 | // to read. 40 | string gNotecardName; 41 | integer gNotecardLine; 42 | 43 | // Because the process of reading a notecard is asynchronous, 44 | // you have to keep a 'key' of your request. This gives you 45 | // something to check to see which request you're getting 46 | // an answer for. 47 | key gNotecardQuery; 48 | 49 | // This will store the contents of the notecard. 50 | // We could make this a big string, but it's 51 | // easier for some purposes to store it 52 | // as a list. 53 | list gNotecardContents; 54 | 55 | 56 | // Since we're just demonstrating how to read a notecard, we'll have a 57 | // vestitial default state. It won't do much of anything other than 58 | // start the process. 59 | 60 | default 61 | { 62 | state_entry() 63 | { 64 | state readNotecard; 65 | } 66 | } 67 | 68 | state readNotecard 69 | { 70 | state_entry() 71 | { 72 | // To start, we'll get the name of the first notecard 73 | // and determine that it's not empty. 74 | // We'll make an error condition so we know if we've succeeded. 75 | integer goodNotecard = FALSE; 76 | // Zero out some variables... 77 | gNotecardLine = 0; 78 | gNotecardContents = []; 79 | gNotecardName = llGetInventoryName(INVENTORY_NOTECARD, 0); 80 | if (gNotecardName != "") 81 | { 82 | // There is a named notecard, but does it have a UUID? 83 | // See http://wiki.secondlife.com/wiki/LlGetNotecardLine#Caveats 84 | if (llGetInventoryKey(gNotecardName) != NULL_KEY) 85 | { 86 | goodNotecard = TRUE; 87 | } 88 | } 89 | // If it's a bad notecard, then die. 90 | if (!goodNotecard) state die; 91 | // OK, so we have a good notecard and we can start reading it. 92 | // llGetNotecardLine() asks SL to get the line of text from 93 | // the notecard, but it doesn't return it. Instead, since it 94 | // might take some time (relatively speaking), the text will 95 | // be returned in the dataserver event. 96 | // The ++ operator uses the current value of the variable, and 97 | // then increments it. This lets us use one line of code to read 98 | // one line of text. Isn't that nice? :-) 99 | gNotecardQuery = llGetNotecardLine(gNotecardName, gNotecardLine++); 100 | } 101 | 102 | dataserver(key query, string data) 103 | { 104 | // Here's where our query variable comes back into play. 105 | // We check to see if it's the notecard query that the system 106 | // is telling us about. For this simple script it doesn't matter 107 | // too much, but in a more complex script there might be other 108 | // queries happening, other than our single one. So it's 109 | // good practice to check. 110 | if (query == gNotecardQuery) 111 | { 112 | // When there aren't any more lines to read from the notecard, 113 | // LSL will send back an EOF (end-of-file). 114 | if (data != EOF) 115 | { 116 | // Data isn't an EOF, so we have something to add to the 117 | // results list. 118 | gNotecardContents += [data]; 119 | // And now we can fetch the next line of text. 120 | gNotecardQuery = llGetNotecardLine(gNotecardName, gNotecardLine++); 121 | } 122 | else // data is EOF 123 | { 124 | // All done. 125 | state success; 126 | } 127 | 128 | } 129 | } 130 | } 131 | 132 | state success 133 | { 134 | state_entry() 135 | { 136 | // The idea is that we only get to this state when we've read the notecard. 137 | // So now we tell the user what we got. 138 | llSay(0, "I read the notecard: " + gNotecardName + ". It is " + 139 | (string)gNotecardLine + " lines long."); 140 | llSay(0, "Here's what the notecard said:\n" + 141 | llDumpList2String(gNotecardContents, "\n")); 142 | llSay(0, "Touch this object to read the notecard again."); 143 | } 144 | 145 | touch_start(integer foo) 146 | { 147 | state default; 148 | } 149 | 150 | changed(integer what) 151 | { 152 | // If the inventory changes, go back to state default 153 | // and try again. 154 | if (what & CHANGED_INVENTORY) state default; 155 | } 156 | } 157 | 158 | state die 159 | { 160 | // We get to state die if there's no notecard, or if there's some other 161 | // problem we can't otherwise solve. 162 | state_entry() 163 | { 164 | llOwnerSay("This script has died. Try putting a notecard in the object's inventory to make it live again."); 165 | } 166 | 167 | changed(integer what) 168 | { 169 | // If the inventory changes, go back to state default 170 | // and try again. 171 | if (what & CHANGED_INVENTORY) state default; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /very_basic/[solo] Scrub All Particles 1.0.lsl: -------------------------------------------------------------------------------- 1 | // Scrub All Bling 2 | // by Solo Mornington 3 | 4 | // This script will remove particle systems from all linked prims. 5 | 6 | // THIS NOTICE MUST REMAIN INTACT: 7 | // Copyright 2011, Solo Mornington 8 | // License: Use freely in any way you want. Modified versions 9 | // may be used in any way. No credit or acknowledgement required. 10 | // Definitive source and updates available here: 11 | // http://github.com/SoloMornington/Solos-Script-Repository 12 | // ** end notice 13 | 14 | // HOW TO: 15 | 16 | // Put this script into an object, and it will cause all particle systems 17 | // in all linked prims to stop. 18 | 19 | // First we make a function that will reset the particle systems 20 | // of all prims. 21 | killAllParticles() 22 | { 23 | // primCount tells us how many prims there are 24 | integer primCount = llGetObjectPrimCount(llGetKey()); 25 | if (primCount == 1) 26 | { 27 | // Only one prim to deal with, and that prim is the one we're in. 28 | // So therefore we can just call llParticleSystem(). 29 | llParticleSystem([]); 30 | } 31 | else 32 | { 33 | // more than one prim, so we loop through all the prims and 34 | // scrub the particles. 35 | integer i; 36 | for (i=1; i<= primCount; ++i) 37 | { 38 | // scrub the particles... 39 | llLinkParticleSystem(i, []); 40 | } 41 | } 42 | } 43 | 44 | // Now we address when to scrub the particles. 45 | default 46 | { 47 | state_entry() 48 | { 49 | // Clearly we want to scrub the particles on state_entry... 50 | killAllParticles(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /very_basic/[solo] Vehicular Bobbing Floater.lsl: -------------------------------------------------------------------------------- 1 | // Vehicular Bobbing Floater 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // Put this script in an object, and it will bob around 13 | // and be pushed by the wind, like a rubber ducky might. 14 | 15 | float gTimerBaseValue = 2.0; 16 | float gTimerMargin = 0.5; 17 | 18 | float newTimerValue() 19 | { 20 | float margin = llFrand(gTimerMargin * 2) - gTimerMargin; 21 | return gTimerBaseValue + margin; 22 | //return 2.0; 23 | } 24 | 25 | setupVehicle() 26 | { 27 | // this function re-initializes the phyysics and vehicle parameters 28 | // make it a physical object.... 29 | llSetStatus(STATUS_PHYSICS, TRUE); 30 | // make it a vehicle.... 31 | llSetVehicleType(VEHICLE_TYPE_BOAT); 32 | llSetVehicleFlags(VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT); 33 | llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.5); 34 | llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.7); 35 | llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 1.0); 36 | // we want hover height to be determined by the object bounding box 37 | // this assumes this script is in the root prim, which is probably a safe 38 | // assumption. but it's still an assumption. 39 | // the bounding box is a very imprecise way to get the outside dimensions 40 | // of an object. But we'll use this because it's easy, not because it's 41 | // right. 42 | list bbox = llGetBoundingBox(llGetKey()); 43 | vector bboxVector = llList2Vector(bbox, 1) - llList2Vector(bbox,0); 44 | float bboxOffset = bboxVector.z * 0.3; 45 | llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, llWater(llGetPos()) + bboxOffset); 46 | llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1.3); 47 | llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.0); 48 | // the bounding box also helps us 49 | llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <5.0,5.0,1.2>); 50 | llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.5); 51 | llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.3); 52 | } 53 | 54 | default 55 | { 56 | state_entry() 57 | { 58 | // start the vehicle stuff... 59 | setupVehicle(); 60 | // set a timer for the wind-based impulses 61 | llSetTimerEvent(newTimerValue()); 62 | } 63 | 64 | timer() 65 | { 66 | vector windy = llWind(llGetPos()); 67 | windy.y = windy.y * 0.3; 68 | windy.x = windy.x * 0.3; 69 | windy.z = windy.z * 0.7; 70 | llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, windy); 71 | llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0.5,0.01,1.0>); 72 | //llMessageLinked(LINK_SET, 999, (string)llWind(llGetPos()), NULL_KEY); 73 | llSetTimerEvent(newTimerValue()); 74 | } 75 | 76 | changed(integer what) 77 | { 78 | setupVehicle(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /very_basic/[solo] Walk-Thru Play Sound.lsl: -------------------------------------------------------------------------------- 1 | // Walk-Thru Play Sound 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // This is a dead-simple script. :-) 13 | // It will turn the object phantom and play a sound when an avatar travels through 14 | // the object. This demonstrates the way llVolumeDetect works. 15 | 16 | // llVolumeDetect turns the object phantom, and changes the way the collision 17 | // events work. Normally they respond to objects or avatars colliding with the 18 | // sides of an object. With llVolumeDetect set to be true, the events fire 19 | // when an object or avatar is detected within the volume of the scripted object. 20 | 21 | // this is a constant to hold the name or UUID of the sound to play 22 | // if you leave it as "", the first sound in inventory 23 | // will be used. Or change it to whichever sound you prefer. 24 | string gSound = ""; 25 | 26 | default 27 | { 28 | state_entry() 29 | { 30 | if (gSound == "") 31 | { 32 | gSound = llGetInventoryName(INVENTORY_SOUND, 0); 33 | } 34 | // if there is no sound to play, even after looking in inventory, 35 | // then we don't want to set up volume detect. 36 | if (gSound != "") 37 | llVolumeDetect(TRUE); // Starts llVolumeDetect, sets object to be phantom 38 | } 39 | 40 | collision_start(integer total_number) 41 | { 42 | 43 | // first things first... we have to set up a loop for all the 44 | // collisions that could have fired this event. 45 | integer i; 46 | for (i=0; i < total_number; ++i) 47 | { 48 | // we only want to play the sound for avatars 49 | if (llDetectedType(i) == AGENT) 50 | { 51 | llPlaySound(gSound, 1.0); 52 | // but we also only want to play it once per event. 53 | return; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /very_basic/[solo] string tokens.lsl: -------------------------------------------------------------------------------- 1 | // String Tokens 2 | // by Solo Mornington 3 | 4 | // THIS NOTICE MUST REMAIN INTACT: 5 | // Copyright 2010, Solo Mornington 6 | // License: Use freely in any way you want. Modified versions 7 | // may be used in any way. No credit or acknowledgement required. 8 | // Definitive source and updates available here: 9 | // http://github.com/SoloMornington/Solos-Script-Repository 10 | // ** end notice 11 | 12 | // Find a 'token' in a string and replace it with a value. 13 | 14 | // Easy improvements: Let the user set the token. 15 | // Hard improvements: Case and plural tokens. 16 | 17 | string replaceToken(string tokenized, string value) 18 | { 19 | // see if there's a token to replace 20 | if ( llSubStringIndex(tokenized, "%") >= 0) 21 | { 22 | // split up the tokenized line into pieces. 23 | list tokenChunks = llParseStringKeepNulls(tokenized, ["%"], [""]); 24 | // reassemble the pieces using the new value as 'delimiter.' 25 | return llDumpList2String(tokenChunks, value); 26 | } 27 | // there weren't any tokens, so return the original string. 28 | return tokenized; 29 | } 30 | 31 | default 32 | { 33 | state_entry() 34 | { 35 | llOwnerSay(replaceToken("%, will you be my bestest friend?", llGetOwner())); 36 | } 37 | } --------------------------------------------------------------------------------