User:Tutti Anatine/scripts

From Second Life Wiki
Jump to navigation Jump to search

<< Return to Tutti Anatine

These are open source scripts I have written. You are free to alter and distribute these scripts, but not sell them for more than L$0. If you alter the script, make sure to add it to the comments on top of the script. Do not remove existing comments. There is no need to credit me when using these scripts, but do credit when you use part of my code in your own script.

Please make sure the scripts are distributed with full permissions.

Back-up Box

A script that turns a newly rezzed prim into a Back-up Box, with unpacker function. Box name and inventory count will be displayed as floating text above the box itself.

Inexperienced-user-friendly options include:

  • Custom preset box texture (applied when resetting the script)
  • Custom floating text color
  • Custom floating text transparency
  • Optional box name prefix
    • This option is added to make reusing of the script with the same settings from inventory possible.

<lsl>// [*TA*] Back-up Box script // By Tutti Anatine key CREATOR = "95eaa123-5b83-437e-9fe9-90def840da39";

// This scripts creates a quick Back-up Box, in which you can store items to back them up in your inventory. // This solution can help keeping your inventory small and clutter-free.

// How to use: // Rez a new box prim (or an other shape of your preference) from the build menu. // Drag this script into the box's contents, the script should set up the box for you. // After this, put items into the contents of this box. // You can unpack the box by touching the box and selecting "Unpack" from the menu.

// You can give the box any name you wish, this will be the name your box will have in your inventory. // The unpack function will give you a folder, which is named after the Back-up Box's description field. // Should your description field be empty, the box will be called "Anonymous Back-up Box". // If you wish, you can also add a prefix to the name of the folder by adding it in the settings below. // Using the settings, you can define some default values which every box has to use and take the script into your inventory for easy reusing.

// This script is open source. Therefore, you are free to use this script, modify it and spread (only) with full permissions. // You are not allowed to charge more than L$0 for this script. If you have paid for this script, ask for a refund! // Please do not remove comment lines and do update them where neccesary if you have modified the script.

// -------------------- // settings // --------------------

// constants key BOX_TEXTURE = "b65eadd8-904f-f304-6e14-31e4e74d180d"; // original texture key: b65eadd8-904f-f304-6e14-31e4e74d180d made by Vmanhalk Wylie (vmanhalk.wylie) vector TEXT_COLOR = <1.0,1.0,1.0>; // text color // order: Red, Green, Blue // <1.0,1.0,1.0> = white, <0.0,0.0,0.0> = black float TEXT_ALPHA = 1.0; // floating text transparancy // 1.0 = visible, 0.0 = invisible string BOX_NAME_PREFIX = ""; // optional folder name prefix

// -------------------- // do not enter below this line unless you know what you're doing! // --------------------

//constants integer DIALOG_CHANNEL = -46346436; // channel used for dialog communication float TIME_OUT = 30.0; // number of seconds before timer activates

// variables key owner; // owner of the containing object string boxDescription; // description of the containing object integer numberOfContents; // number of contents inside containing object (this script not included) list inventoryList; // list containing the names of containing object's contents (this script not included) integer dialogHandler; // the chat channel handler for the dialog, will be removed by timer

init() { llListenRemove(dialogHandler);

owner = llGetOwner(); update(); }

// update inventoryList and floating text above containing object update() { boxDescription = llGetObjectDesc(); numberOfContents = llGetInventoryNumber(INVENTORY_ALL) - 1;

if (boxDescription == "") { boxDescription = "Anonymous Back-up Box"; }

// fill inventoryList with names of containing object's contents inventoryList = []; integer i; for (i = 0; i <= numberOfContents; i++) { string name = llGetInventoryName(INVENTORY_ALL,i); if (name != llGetScriptName()) { inventoryList += [name]; } }

// update floating text above containing object string body = (string) llKey2Name(owner)+"'s Back-up Box\n\""+boxDescription+"\"\n "+(string) numberOfContents+" item(s) inside"; llSetText(body, TEXT_COLOR, TEXT_ALPHA); }

default {

   state_entry() {
   	llSetTexture(BOX_TEXTURE, ALL_SIDES);
   	
       init();
   }
   
   touch_start(integer num_detected) {
   	if (llDetectedKey(0) == owner) {
   		dialogHandler = llListen(DIALOG_CHANNEL, "", owner, "");
   		llDialog(owner, "Please choose an option.\n\nPage 1/1", ["Unpack","Reset","Close"], DIALOG_CHANNEL);
   		llSetTimerEvent(TIME_OUT);
   	}
   }
   
   listen(integer channel, string name, key id, string message) {
   	if (channel == DIALOG_CHANNEL) {
   		llSetTimerEvent(0.0);
   		
   		message = llToLower(message);
   		if (message == "unpack") {
   			if (numberOfContents > 0) {
   				string folderName;
   				if (BOX_NAME_PREFIX != "") {
   					folderName = BOX_NAME_PREFIX+" "+boxDescription;
   				} else {
   					folderName = boxDescription;
   				}
   				llGiveInventoryList(owner, folderName, inventoryList);
   			} else {
   				llInstantMessage(owner, "This Back-up Box has no contents beside this script. If you wish to remove the script from the box, please do so via 'Contents' in the Edit window.");
   			}
   		} else if (message == "reset") {
   			llInstantMessage(owner, "This Back-up Box will now reset, this should have no effect on items inside the box.");
   			llResetScript();
   		}
   	}
   }
   
   changed(integer change) {
   	if (change & CHANGED_INVENTORY || change & CHANGED_ALLOWED_DROP) {
   		update();
   	} else if (change & CHANGED_OWNER || change & CHANGED_REGION_START) {
   		init();
   	}
   }
   
   timer() {
   	llListenRemove(dialogHandler);
   	llInstantMessage(owner, "Dialog Handler was removed. This Back-up Box will no longer respond to dialogs (menus) opened before this message appeared. You can touch the box again to reactivate the menu.");
   }
   
   on_rez(integer start_param) {
   	init();
   }

}</lsl>

Known bugs

  • The unpacker script will not hand out no-copy items from inventory.

Floating text

Inexperienced-user-friendly options include:

  • Personalized floating text;
  • Custom text color (default is white);
  • Optional text transparency;
  • Optional text disappearance after given number of seconds.
    • Note: if this is set, text will reappear on touch of the containing object.

<lsl>/* [*TA*] Floating Text script By Tutti Anatine

Feel free to edit this code but do not sell it for more than L$0. Keep permissions copy/mod/transfer at all times. Make a copy of the original script before editing the code to prevent loss. If you have been charged money for this script, please contact the seller and ask for full compensation. Please do not remove this text and other comments within this script.

Last edit: 17 August 2011 */ key CREATOR = "95eaa123-5b83-437e-9fe9-90def840da39";

// -------------------- // settings - edit these to suit your taste // --------------------

// constants float TIMEOUT = 0.0; // this is 0.0 on default, put in a higher value to make the floating text disappear after given number of seconds string FLOATING_TEXT = ""; // this is the floating text that is displayed | start new lines using '\n', without the quotes, in your text vector TEXT_COLOR = <1.0,1.0,1.0>; // color value of the floating text | ranges between <1.0, 1.0, 1.0> (white) and <0.0, 0.0, 0.0> (black) | order: red, green, blue float TEXT_ALPHA = 1.0; // the transparency of the floating text | ranges between 0.0 (full transparency) and 1.0 (no transparency)

// -------------------- // do not edit below this line unless you know what you're doing! // --------------------

// basic setup of script, used instead of llResetScript(); init() {

   llSetText(FLOATING_TEXT,TEXT_COLOR,TEXT_ALPHA);
       
   if (TIMEOUT > 0) {
       llSetTimerEvent(TIMEOUT);
   }

}

default {

   state_entry() {
       init();
   }
   
   touch_start(integer num_detected) {
       init();
   }
   
   timer() {
       llSetText("",TEXT_COLOR,TEXT_ALPHA); // remove floating text
   }
   
   changed(integer change) {
       if (change & CHANGED_OWNER) {
           init();
       }
   }
   
   on_rez(integer start_param) {
       init();
   }

}</lsl>

Pose stand (with buttons)

A single-animation pose stand which can pose one avatar at a time. It is compatible with the optional button scripts provided here as well.

Base

The base of the pose stand, where a single avatar can sit on. Inexperienced-user-friendly options include:

  • Turn automatic deletion of the object on or off;
  • Set the timeout for automatic deletion in seconds;
  • Set the amount of meters an avatar will move up or down when the height offset buttons are used;
  • Set the number of degrees an avatar will turn clockwise or anti-clockwise when the rotation buttons are used.

More experienced users may want to change the init() function to make the script more suitable for their stand. Please read the comments in this function for instructions.

<lsl> /**

* [*TA*] Pose Stand script
* 
* This is the base for a pose stand with optional buttons.
* This stand is meant for fitting purposes only.
*
* Feel free to edit this code but do not sell it for more than L$0. Keep permissions copy/mod/transfer at all times.
* Make a copy of the original script before editing the code to prevent loss.
* If you have been charged money for this script, please contact the seller and ask for full compensation.
* Please do not remove this text and other comments within this script.
*
* @author Tutti Anatine
* @since 6 August 2011
* @version 3 June 2012
*/

key CREATOR = "95eaa123-5b83-437e-9fe9-90def840da39";

// -------------------- // settings - edit these to suit your taste // --------------------

// constants integer AUTO_DELETE = FALSE; // turns auto deletion of the object on or off | TRUE for on, FALSE is off integer TIMEOUT = 60; // the number of seconds that have to pass before the object deletes itself (when AUTO_DELETE = TRUE) float HEIGHT_OFFSET = 0.1; // the amount of meters the posing avatar moves up or down when touching the height buttons | has to be a positive number | default: 0.1 float ROTATION_OFFSET = 30.0; // the number of degrees the posing avatar turns around when touching the rotation buttons | has to be a positive number | default: 30.0

// -------------------- // do not edit below this line unless you know what you're doing! // --------------------

// variables string animation; string current_anim; vector current_offset; vector current_rot_in_degrees; rotation current_rot; integer being_sat_on;

/**

* Set up the script. This is used instead of llResetScript() for more granular control.
*/

init() {

 current_anim = "";
 current_offset = <0.0, 0.0, 0.01>;
 
 change_pose("T Pose");
 
 llSetSitText("Pose");
 llSetClickAction(CLICK_ACTION_SIT);

}

/**

* Changes the pose used to animate the avatar sitting on this object.
*
* @param string name The name of the pose used. This animation should be in the object's inventory. (Exception: SL's built-in pose "turn_180")
*/

change_pose(string name) {

   current_rot_in_degrees = <0.0, 0.0, 0.0>;
   if (name == "T Pose") {
     animation = "T Pose";
     current_rot_in_degrees = <0.0, 0.0, 180.0>;
   } else {
     animation = "turn_180";
   }
   
   current_rot = degrees_to_rotation(current_rot_in_degrees);
   update_sit_target(current_offset, current_rot);
   
   key avatar = llAvatarOnSitTarget();
   if (avatar != NULL_KEY) {
     llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION);
   }

}

/**

* Create a height offset value based on the avatar's length.
*
* @param key UUID The ID of the avatar.
*/

adjust_height_to_avatar(key UUID) {

 vector avatar_size = llGetAgentSize(UUID);
 vector object_size = llGetScale();
 
 float height_offset = avatar_size.z / 2 + object_size.z / 2;
 
 current_offset = <0.0, 0.0, height_offset>;
 update_sit_target(current_offset, current_rot);

}

/**

* Moves the avatar up and down.
*
* @param float correction
*/

update_height(float correction) {

 current_offset.z = current_offset.z + correction;
 update_sit_target(current_offset, current_rot);

}

/**

* Turns the avatar left and right.
*
* @param float correction
*/

update_rotation(float correction) {

 current_rot_in_degrees.z += correction;
 current_rot = degrees_to_rotation(current_rot_in_degrees);
 update_sit_target(current_offset, current_rot);

}

/**

* Converts a vector containing xyz-values to a rotation value.
*
* @param vector rot_in_degrees A vector containing xyz-rotation values in degrees.
* @return rotation The converted rotation value.
*/

rotation degrees_to_rotation(vector rot_in_degrees) {

 vector rot_in_radians = rot_in_degrees * DEG_TO_RAD;
 rotation rot = llEuler2Rot(rot_in_radians);
 return rot;

}

/**

* Sets / Updates the sit target moving the avatar on it if necessary.
*
* @param vector
* @param rotation
* @author Written by Strife Onizuka, size adjustment provided by Escort DeFarge
*/

update_sit_target(vector pos, rotation rot) { //Using this while the object is moving may give unpredictable results.

 llSitTarget(pos, rot); //Set the sit target
 key user = llAvatarOnSitTarget();
 if (user) // true if there is a user seated on the sittarget, if so update their position
 {
   vector size = llGetAgentSize(user);
   if (size) // This tests to make sure the user really exists.
   {
     // We need to make the position and rotation local to the current prim
     rotation localrot = ZERO_ROTATION;
     vector localpos = ZERO_VECTOR;
     if (llGetLinkNumber() > 1) // only need the local rot if it's not the root.
     {
       localrot = llGetLocalRot();
       localpos = llGetLocalPos();
     }
     pos.z += 0.4;
     integer linkNum = llGetNumberOfPrims();
     do {
       if (user == llGetLinkKey( linkNum )) // just checking to make sure the index is valid.
       {
         llSetLinkPrimitiveParams(linkNum, [PRIM_POSITION, ((pos - (llRot2Up(rot) * size.z * 0.02638)) * localrot) + localpos, PRIM_ROTATION, rot * localrot / llGetRootRotation()]);
         jump end; // cheaper but a tad slower then return
       }
     } while( --linkNum );
   }
   else
   { // It is rare that the sit target will bork but it does happen, this can help to fix it.
     llUnSit(user);
   }
 }
 @end;

}

/**

* Poses the avatar.
*/

pose() {

 being_sat_on = TRUE;
 llStopAnimation(current_anim);
 llStartAnimation(animation);
 current_anim = animation;

}

/**

* Sets the timer for automatic deletion. This will only be activated when AUTO_DELETE is TRUE.
*/

setTimer() {

 llWhisper(0, "I will delete myself in " + (string) TIMEOUT + " seconds unless someone sits on me before then.");
 llSetTimerEvent(TIMEOUT);

}

default {

 state_entry() {
   init();
 }
 
 touch_start(integer num_detected) {
   // get the name of the (child) prim that passed the touch event
   integer detected_link = llDetectedLinkNumber(0);
   string name = llToLower(llGetLinkName(detected_link));
   
   // bind an action to the name of each button, this way you can easily create buttons that perform any action you want
   if (name == "up") {
     update_height(HEIGHT_OFFSET);
   } else if (name == "down") {
     update_height(-HEIGHT_OFFSET);
   } else if (name == "clockwise") {
     update_rotation(-ROTATION_OFFSET);
   } else if (name == "anticlockwise") {
     update_rotation(ROTATION_OFFSET);
   } else if (name == "turn_180") {
     change_pose("turn_180");;
   } else if (name == "T Pose") {
     change_pose("T Pose");
   }
 }
   
 changed(integer change) {
   // this occurs when an avatars sits on the object, or stands up from it
   if (change & CHANGED_LINK) {
     key avatar = llAvatarOnSitTarget();
     
     if (avatar != NULL_KEY) {
       if (being_sat_on != TRUE) {
         llSetTimerEvent(0.0);
         current_anim = "sit";
         adjust_height_to_avatar(avatar);
         llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION);
       }
     } else {
       being_sat_on = FALSE;
       current_anim = "";
       if (AUTO_DELETE == TRUE) {
         setTimer();
       }
     }
   } else if (change & (CHANGED_SCALE | CHANGED_LINK | CHANGED_OWNER)) {
     init();
   }
 }
   
 run_time_permissions(integer perm) {
   // check if the avatar has given permission for animation
   if (perm & PERMISSION_TRIGGER_ANIMATION){
     pose();
   }
 }
   
 on_rez(integer start_param) {
   init();
 }
   
 timer() {
   llDie(); // delete the entire object
 }

} </lsl>

Buttons

Any prim you link to the pose stand is handled like a button. The script will respond to the name of a prim when that prim is touched, this happens in the touch_start event. On default, six button names are supported:

  • up | this moves the avatar up
  • down | this moves the avatar down
  • clockwise | this rotates the avatar clockwise
  • anticlockwise | this rotates the avatar anti-clockwise
  • turn_180 | this switches to animation "turn_180"
  • T Pose | this switches to animation "T Pose"

You can also create new buttons. In this case you will have to find a unique name for your new button and then write a handler in the ' if-else if' code inside touch_start. You may have to rewrite other parts of the script as well, so much sure you know have made a back-up of previously changes.

Notes

  • The function UpdateSitTarget() is written by Strife Onizuka and Escort DeFarge and was taken from LlSitTarget.
  • The in-world original uses a pose called 'T Pose' by Adenoraque Qin. It's also possible to change the script to use Linden Labs' default animation, turn_180. Just change change_pose("T Pose"); into change_pose("turn_180"); in the function init() close to the top of the script.

Known bugs

  • Sometimes, the animation will get bugged when changing clothes or attachements while standing on the pose stand. I'm still investigating what this is caused by.

Tip jar

A simple tip jar script, all donations go to the owner. Inexperienced-user-friendly options include:

  • Change quick pay button values;
  • Set the color of the floating text;
  • Personalized thank you message.

<lsl>/* [*TA*] Tip Jar script By Tutti Anatine

Feel free to edit this code but do not sell it for more than L$0. Keep permissions copy/mod/transfer at all times. Make a copy of the original script before editing the code to prevent loss. If you have been charged money for this script, please contact the seller and ask for full compensation. Please do not remove this text and other comments within this script.

Last edit: 31 July 2011 */ key CREATOR = "95eaa123-5b83-437e-9fe9-90def840da39";

// -------------------- // settings - edit these to suit your taste // --------------------

// constants list QUICK_PAY_BUTTONS = [5,10,20,40]; // the values of the quick page buttons, set value to PAY_HIDE to hide a button | order: top left, top right, bottom left, bottom right vector FLOATING_TEXT_COLOR = <1.0 , 1.0, 1.0>; // color value of floating text | ranges between <1.0 , 1.0, 1.0> (white) and <0.0 , 0.0, 0.0> (black) | order: red, green, blue string THANK_MESSAGE = "Thank you for your donation, I really appreciate it!"; // the private message sent to a donator after donation

// -------------------- // do not edit below this line unless you know what you're doing! // --------------------

// variables key owner; integer donatedThisSession; integer lastDonation; string lastDonator;

// basic setup of script, used instead of llResetScript(); init() {

   owner = llGetOwner();
   donatedThisSession = 0;
   llSetPayPrice(0, QUICK_PAY_BUTTONS);
   updateFloatingText();
   llSetClickAction(CLICK_ACTION_PAY);

}

updateFloatingText() {

   if (donatedThisSession > 0) {
       llSetText(llKey2Name(owner)+"'s Tip Jar\nClick me to donate\nL$"+(string)donatedThisSession+" donated this session\nLast donation: L$"+(string)lastDonation+" by "+lastDonator, FLOATING_TEXT_COLOR, 1.0);
   } else {
       llSetText(llKey2Name(owner)+"'s Tip Jar\nClick me to donate", FLOATING_TEXT_COLOR, 1.0);
   }

}

default {

   state_entry() {
       init();
   }
   
   money(key id, integer amount) {
       donatedThisSession += amount;
       lastDonation = amount;
       lastDonator = llKey2Name(id);
       updateFloatingText();
       llInstantMessage(id, THANK_MESSAGE);
       llInstantMessage(owner,lastDonator+" just donated L$"+(string)lastDonation);
   }
   
   changed(integer change) {
       if (change & CHANGED_OWNER) {
           init();
       }
   }
   
   on_rez(integer start_param) {
       init();
   }

}</lsl>

Unpacker

Unpacker for owner of containing object. Users can change the color of the floating text.

<lsl>/* [*TA*] Unpacker script By Tutti Anatine

Feel free to edit this code but do not sell it for more than L$0. Keep permissions copy/mod/transfer at all times. Make a copy of the original script before editing the code to prevent loss. If you have been charged money for this script, please contact the seller and ask for full compensation. Please do not remove this text and other comments within this script.

Last edit: 17 August 2011 */ key CREATOR = "95eaa123-5b83-437e-9fe9-90def840da39";

// -------------------- // settings - edit these to suit your taste // --------------------

// constants vector FLOATING_TEXT_COLOR = <1.0 , 1.0, 1.0>; // color value of floating text | ranges between <1.0 , 1.0, 1.0> (white) and <0.0 , 0.0, 0.0> (black) | order: red, green, blue

// -------------------- // do not edit below this line unless you know what you're doing! // --------------------

// variables key owner; list inventoryList;

// basic setup of script, used instead of llResetScript(); init() { owner = llGetOwner(); updateInventoryList();

if (llGetListLength(inventoryList) == 0) { llSetText("This package is empty.",FLOATING_TEXT_COLOR,1.0); } else { llSetText("Please touch to unpack me.",FLOATING_TEXT_COLOR,1.0); } }

updateInventoryList() { llSetText("Reloading inventory, please be patient while waiting.",FLOATING_TEXT_COLOR,1.0);

   integer count = llGetInventoryNumber(INVENTORY_ALL);
   inventoryList = [];

integer i; for (i = 0; i < count; i++) { string name = llGetInventoryName(INVENTORY_ALL,i); if (name != llGetScriptName()) { inventoryList += [name]; } } }

default {

   state_entry() {
   	init();
   }
   touch_start(integer num_detected) {
   	if (!llGetListLength(inventoryList) == 0) {

key avatar = llDetectedKey(0); if (avatar == owner) { llGiveInventoryList(owner,llGetObjectName(),inventoryList); llSetText("This package is now unpacked and can be safely deleted.",FLOATING_TEXT_COLOR,1.0); } else { llInstantMessage(avatar,"I can not give you the contents of this package, because you are not the owner."); }

   	}
   }
   changed(integer change) {
   	if (change & CHANGED_INVENTORY) {
   		init();
       } else if (change & CHANGED_OWNER) {
           init();
       }
   }
   
   on_rez(integer start_param) {
       init();
   }

}</lsl>