Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save TimelessP/c0cbb8921c836b74cded41f694f06e4c to your computer and use it in GitHub Desktop.
Save TimelessP/c0cbb8921c836b74cded41f694f06e4c to your computer and use it in GitHub Desktop.
LSL scripts
// myGetRoll(), myGetPitch(), myGetBearing(), mySetHorizonTexture()
// by Timeless Prototype
// Helps with attitude indicator (artificial horizon) display on a prim, plus a few other functions you will probably want for any flying vehicle instruments.
// Created 2009-12-01
// Please give credit to Timeless Prototype in documentation when using anything from this script.
key craftKey = NULL_KEY;
// Returns the roll relative to the horizon (0.0), ranging from 90.0 (right wing down) to -90.0 (left wing down). Assumes frame of reference is East-facing at zero rotation.
float myGetRoll(rotation rot)
{
vector vOffset = <0,1,0> * rot;
vector noX = <0.0, llVecMag(<0.0, vOffset.x, vOffset.y>), vOffset.z>;
float roll = llAtan2(noX.z, noX.y) * RAD_TO_DEG;
// However, this is the only indicator we're using to check if we're upside down.
// Therefore the only indicator we want to exceed the -90.0 and 90.0 thresholds.
vector upsideDownCheck = <0,0,1> * rot;
if (upsideDownCheck.z < 0.0)
{
if (roll < 0.0)
{
roll = -180.0 - roll;
}
else
{
roll = 180.0 - roll;
}
}
return roll * DEG_TO_RAD;
}
// Returns the pitch relative to the horizon (0.0), ranging from 90.0 (up) to -90.0 (down). Assumes frame of reference is East-facing at zero rotation.
float myGetPitch(rotation rot)
{
vector vOffset = <1,0,0> * rot;
vector noY = <llVecMag(<vOffset.x, vOffset.y, 0.0>), 0.0, vOffset.z>;
return llAtan2(noY.z, noY.x);
}
// Returns a compass bearing. Assumes frame of reference is East-facing at zero rotation.
float myGetBearing(rotation rot)
{
vector vOffset = <1,0,0> * rot;
float bearing = llAtan2(vOffset.x, vOffset.y) * RAD_TO_DEG;
if (bearing < 0.0)
{
bearing += 360.0;
}
return bearing * DEG_TO_RAD;
}
mySetHorizonTexture(rotation vehicleRotation, integer primFace) {
llSetPrimitiveParams([PRIM_TEXTURE, primFace, "973bb206-0812-89e6-21d3-a268f47dfa65", <0.3, 0.3, primFace>, <0.0, (myGetPitch(vehicleRotation)/6.39)-0.25, primFace>, myGetRoll(vehicleRotation)]);
}
default
{
state_entry()
{
llSetTimerEvent(0.0);
llListen(55, "", NULL_KEY, "");
}
attach(key id)
{
llSetTimerEvent(0.0);
}
listen(integer channel, string name, key id, string message)
{
if (llSubStringIndex(message, "cmd|hud|connect|") == 0)
{
key pilotId = (key)llGetSubString(message, 16, -1);
if (pilotId == llGetOwner())
{
craftKey = id;
llSetTimerEvent(0.5);
}
}
}
timer()
{
list details = llGetObjectDetails(craftKey, [OBJECT_NAME, OBJECT_POS, OBJECT_ROT, OBJECT_VELOCITY]);
if (llList2String(details, 2) == "")
{
llSetTimerEvent(0.0);
llOwnerSay("Vehicle has left the region. Please use autopilot features to control the vehicle.");
}
mySetHorizonTexture((rotation)llList2String(details, 2), 4);
}
}
// Timeless Linked Turret
// --------------------------
// Description: LSL script to rotate a linked child prim locally
// around local z and y axes only to point at a position in
// the sim. Perfect for creating gun turrets that are linked
// to a vehicle.
// Version 1.0.13 27th September 2009
// Concept by Timeless Prototype, 6th June 2008
// Scripted by: Timeless Prototype
// With ideas and optimizations from: Jiminy Roo, Prime Oxide
//
// If you need help, please *only* get community support in forums, etc.
// Please do not contact the names above.
//
// This script is a gift to the scripters of Second Life from Timeless Prototype,
// and hopefully to be enjoyed by the community as widely as is the
// Timeless Linked Door script. <3
//
// Usage:
// --------
// This script belongs in the gun turret prim that is a child prim in a link set.
//
// 1. Set localJointPos variable to the relative offset within the linkset
// where the rotation point of the gun barrel prim will be.
// 2. Set the offsetFromJoint variable to how much the prim will need to
// be offset along its final rotation. For example: if the
// turret gun barrel is 5m long, setting offsetFromJoint to
// <2.5, 0.0, 0.0> will slide the barrel forwards by 2.5m,
// such that the back end of the barrel will touch the
// rotation point.
// 3. Set the frameOfref to the intended frame of reference.
// Example 1: barrel prim at zero rotation aims East; set
// frameOfRef to ZERO_ROTATION.
// Example 2: barrel prim at zero rotation aims up and
// under-side is facing East; set frameOfRef to
// llEuler2Rot(<0.0, PI_BY_TWO, 0.0>);
// Example 3: barrel prim at zero rotation aims down and
// under-side is facing West; set frameOfRef to
// llEuler2Rot(<0.0, -PI_BY_TWO, 0.0>);
//
// Your own tasks: Modify the script accordingly to make use of camera
// position and angle if you want to do mouselook aiming. This is merely
// the implementation of the function that rotates the child prim to point
// at the position in the sim. How you determine that position is up to the
// scripter (you). Have fun! :)
vector localJointPos = <0.79629, -0.65721, 0.30054>;
vector offsetFromJoint = <2.5, 0.0, 0.0>;
rotation frameOfRef = ZERO_ROTATION;
myPrimRotAt(vector target, vector rotPoint, vector offsetFromPoint, rotation frameOfReference)
{
rotation rootRot = llGetRootRotation();
vector direction = (target - (llGetRootPosition() + (rotPoint * rootRot))) / rootRot;
rotation rot = llEuler2Rot(<0.0, llAtan2(llVecMag(<direction.x, direction.y, 0.0>), direction.z) - PI_BY_TWO, 0.0>) * llEuler2Rot(<0.0, 0.0, llAtan2(direction.y, direction.x)>);
llSetPrimitiveParams([PRIM_ROTATION, frameOfReference * (rot / rootRot), PRIM_POSITION, rotPoint + (offsetFromPoint * rot)]);
}
default
{
state_entry()
{
frameOfRef = llEuler2Rot(<0,PI_BY_TWO,0>);
llSensorRepeat("", llGetOwner(), AGENT, 25.0, TWO_PI, 0.5);
}
sensor(integer num_detected)
{
myPrimRotAt(llDetectedPos(0), localJointPos, offsetFromJoint, frameOfRef);
}
}
//------------------------------------------------------
// Timeless Linked Door Script by Timeless Prototype
//------------------------------------------------------
//======================================================
// Modified by Yabu Kurosawa (feb 2008)
// As of server version 1.19.0, the length of the object
// name is always truncated to 63 characters, the length of the
// description to 127 characters. See also:
// http://blog.secondlife.com/2008/02/01/scripters-object-name-and-description-changes/
// The original script exceeds the maximum name length.
// This problem is solved by compressing the 20 float
// values into 5-character strings and storing them all
// in the description field. Total string length is 105.
//======================================================
// The original version of this script can always be found
// in the Library section of the wiki:
// http://www.secondlife.com/badgeo/
// This script is free to use, but whereever it is used
// the SCRIPT's permissions MUST be set to:
// [x] Next owner can modify
// [x] Next owner can copy
// [x] Next owner can transfer
// [x] Allow anyone to copy
// [x] Share with group
//------------------------------------------------------
// USAGE INSTRUCTIONS FOR EVERYDAY USE:
//------------------------------------------------------
// Say the following commands on channel 0:
// 'unlock' - Unlocks all doors in range.
// 'lock' - Locks all doors in range and allows
// only the permitted users to open it.
// To open the door, either Touch it, Walk into it or
// say 'open' or say 'close'.
//------------------------------------------------------
// USAGE INSTRUCTIONS FOR BUILDERS:
//------------------------------------------------------
// 1. Copy and paste this script into the door prim and
// change the settings (see further down).
// 2. The door prim must be linked to at least one other
// prim (could be linked to the house for example).
// 3. The door prim MUST NOT be the root prim.
// 4. Use Edit Linked Parts to move, rotate and size the
// door prim for the closed state.
// 5. When ready, stand close to the door and say
// '/door closed' (this records the closed door
// position, rotation and size to the object's
// name and description).
// 6. Use the Edit Linked parts to move, rotate and size
// the door prim for the opened state.
// 7. When ready, stand close to the door and say
// '/door opened' (this records the opened door
// position, rotation and size).
// 8. Once recorded it will not accept these commands
// again. If you do need to redo the settings then
// delete the Description of the door prim
// (these are where the position information is
// stored), and then follow the steps above again.
//------------------------------------------------------
// Change these settings to suit your needs.
//------------------------------------------------------
// To mute any/all of the sounds set the sound string(s)
// to "" (empty string).
// To get the UUID of a sound, right click on the sound
// in your inventory and choose "Copy Asset UUID", then
// paste the UUID in here.
string doorOpenSound = "cb340647-9680-dd5e-49c0-86edfa01b3ac";
string doorCloseSound = "e7ff1054-003d-d134-66be-207573f2b535";
string confirmedSound = "69743cb2-e509-ed4d-4e52-e697dc13d7ac";
string accessDeniedSound = "58da0f9f-42e5-8a8f-ee51-4fac6c247c98";
string doorBellSound = "";//"ee871042-e272-d8ec-3d40-0b0cb3371346"; // Setting to empty stops door announcements too.
float autoCloseTime = 0.0; // 0 seconds to disable auto close.
integer allowGroupToo = TRUE; // Set to FALSE to disallow same group access to door.
list allowedAgentUUIDs = ["8efecbac-35de-4f40-89c1-2c772b83cafa"]; // Comma-separated, quoted list of avatar UUIDs who are allowed access to this door.
integer listenChannel = 0;
//------------------------------------------------------
// Leave the rest of the settings alone, these are
// handled by the script itself.
//------------------------------------------------------
integer isLocked = FALSE; // Only when the door is locked do the permissions apply.
integer isOpen = TRUE;
vector openPos = ZERO_VECTOR;
rotation openRot = ZERO_ROTATION;
vector openScale = ZERO_VECTOR;
vector closedPos = ZERO_VECTOR;
rotation closedRot = ZERO_ROTATION;
vector closedScale = ZERO_VECTOR;
key openerKey = NULL_KEY;
key closerKey = NULL_KEY;
integer isSetup = FALSE;
integer listenHandle = 0;
string avatarName = "";
// code string used for the parameter encoding/decoding
string code68 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@$#&!?";
mySayName(integer channel, string objectName, string message)
{
string name = llGetObjectName();
llSetObjectName(objectName);
llSay(0, "/me " + message);
llSetObjectName(name);
}
mySay(integer channel, string message)
{
string name = llGetObjectName();
llSetObjectName("Door");
llSay(0, message);
llSetObjectName(name);
}
myOwnerSay(string message)
{
string name = llGetObjectName();
llSetObjectName("Door");
llOwnerSay(message);
llSetObjectName(name);
}
mySoundConfirmed()
{
if (confirmedSound != "")
{
llTriggerSound(confirmedSound, 1.0);
}
}
mySoundAccessDenied()
{
if (accessDeniedSound != "")
{
llTriggerSound(accessDeniedSound, 1.0);
}
}
myGetDoorParams()
{
isSetup = FALSE;
if (llSubStringIndex(llGetObjectDesc(), "door:") == 0)
{
string s = llGetObjectDesc();
integer k = 5;
openPos.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openPos.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openPos.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.s = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openScale.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openScale.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openScale.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedPos.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedPos.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedPos.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.s = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedScale.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedScale.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedScale.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
isSetup = TRUE;
}
else
{
myOwnerSay("The door prim's description is empty of has invalid syntax. Delete the door prim's description and setup the door prim again.");
}
}
mySetDoorParams(vector openPos, rotation openRot, vector openScale, vector closedPos, rotation closedRot, vector closedScale)
{
string s = "door:";
s += encode_float(openPos.x);
s += encode_float(openPos.y);
s += encode_float(openPos.z);
s += encode_float(openRot.x);
s += encode_float(openRot.y);
s += encode_float(openRot.z);
s += encode_float(openRot.s);
s += encode_float(openScale.x);
s += encode_float(openScale.y);
s += encode_float(openScale.z);
s += encode_float(closedPos.x);
s += encode_float(closedPos.y);
s += encode_float(closedPos.z);
s += encode_float(closedRot.x);
s += encode_float(closedRot.y);
s += encode_float(closedRot.z);
s += encode_float(closedRot.s);
s += encode_float(closedScale.x);
s += encode_float(closedScale.y);
s += encode_float(closedScale.z);
llSetObjectDesc(s);
isSetup = TRUE;
mySay(0,"Parameters are stored");
}
integer myPermissionCheck(key id)
{
integer hasPermission = FALSE;
if (isLocked == FALSE)
{
hasPermission = TRUE;
}
else if (llGetOwnerKey(id) == llGetOwner())
{
hasPermission = TRUE;
}
else if (allowGroupToo == TRUE && llSameGroup(id))
{
hasPermission = TRUE;
}
else if (llListFindList(allowedAgentUUIDs, [(string)id]) != -1)
{
hasPermission = TRUE;
}
return hasPermission;
}
myOpenDoor()
{
isOpen = FALSE;
myToggleDoor();
}
myCloseDoor()
{
isOpen = TRUE;
myToggleDoor();
}
myToggleDoor()
{
if (isSetup == FALSE)
{
myOwnerSay("The door prim has not been configured yet. Please read the usage instructions in the door script.");
}
else if (llGetLinkNumber() == 0 || llGetLinkNumber() == 1)
{
myOwnerSay("The door prim must be linked to at least one other prim and the door prim must not be the root prim");
}
else
{
isOpen = !isOpen;
if (isOpen)
{
if (doorBellSound != "")
{
llTriggerSound(doorBellSound, 1.0);
if (avatarName != "")
{
mySayName(0, avatarName, "is at the door.");
avatarName = "";
}
}
if (doorOpenSound != "")
{
llTriggerSound(doorOpenSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, openPos, PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation(), PRIM_SIZE, openScale ]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|opened", NULL_KEY);
}
else
{
if (doorCloseSound != "")
{
llTriggerSound(doorCloseSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, closedPos, PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation(), PRIM_SIZE, closedScale ]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|closed", NULL_KEY);
}
llSetTimerEvent(0.0);
if (isOpen == TRUE && autoCloseTime != 0.0)
{
llSetTimerEvent(autoCloseTime);
}
}
}
//==========================================================================
// encode a float with 7 digits precision into a 5-character string
// minimum=1e-31, maximum=1e+31
// example: 1.234567 --> "hAM70"
//==========================================================================
string encode_float(float value)
{
integer neg = 0;
integer exp = 0;
integer k = 0;
integer i;
integer n;
string s;
// get sign, make value positive
if( value < 0 )
{
neg = 1;
value = -value;
}
// scale value to 7 digits before decimal dot
if( value > 0 )
{
if( value > 1e31 ) value = 1e31;
if( value < 1e-31) value = 1e-31;
while( value >= 10000000 )
{
exp += 1;
value = value / 10;
}
while( value < 1000000 )
{
exp -= 1;
value = value * 10;
}
}
// round to integer, discard decimals
k = (integer)(value+0.5);
// encode exponent and sign into integer (should fit into 32 bit)
k = k*64 + (exp+38);
k = k*2 + neg;
// encode integer into string
s = "";
for( i=0; i<5; i++ )
{
n = k % 68;
k = k / 68;
s = llGetSubString(code68,n,n) + s;
}
return s;
}
//==========================================================================
// decode a 5-character string into a float with 7 digits precision
// example: "hAM70" --> 1.234567
//==========================================================================
float decode_float(string s)
{
integer k = 0;
integer i;
integer neg;
float value;
integer exp;
// decode string into integer
for( i=0; i<5; i++ )
{
k = k*68 + llSubStringIndex(code68,llGetSubString(s,i,i));
}
// extract sign and exponent
neg = k % 2;
k = k/2;
exp = k % 64 - 38;
k = k/64;
// convert into float
value = (float)k;
// scale according to exponent
while( exp > 0 )
{
value = value * 10;
exp -= 1;
}
while( exp < 0 )
{
value = value / 10;
exp += 1;
}
// insert sign
if( neg ) value = -value;
return value;
}
default
{
state_entry()
{
listenHandle = llListen(listenChannel, "", NULL_KEY, "");
myGetDoorParams();
}
touch_start(integer total_number)
{
if (myPermissionCheck(llDetectedKey(0)) == TRUE)
{
avatarName = llDetectedName(0);
myToggleDoor();
}
else
{
mySoundAccessDenied();
}
}
timer()
{
myCloseDoor();
}
link_message(integer sender_num, integer num, string str, key id)
{
// Door API. The API is here in case you want to create PIN entry keypads or whatever.
if (num == llGetLinkNumber())
{
if (str == "cmd|door|doOpen")
{
myOpenDoor();
}
else if (str == "cmd|door|doClose")
{
myCloseDoor();
}
}
if (str == "cmd|door|discover")
{
llMessageLinked(LINK_SET, 255, "cmd|door|discovered|" + (string)llGetKey(), id);
}
}
listen(integer channel, string name, key id, string message)
{
// Performance note: it's quicker to compare the strings than to compare
// permissions each time anyone says anything on this channel.
if (message == "open")
{
if (myPermissionCheck(id) == TRUE)
{
// Only open the door if the person is quite close to this door.
openerKey = id;
closerKey = NULL_KEY;
avatarName = name;
llSensor(name, id, AGENT, 5.0, TWO_PI);
}
else
{
mySoundAccessDenied();
}
}
else if (message == "close")
{
if (myPermissionCheck(id) == TRUE)
{
openerKey = NULL_KEY;
closerKey = id;
avatarName = name;
// Only close the door if the person is quite close to this door.
llSensor(name, id, AGENT, 5.0, TWO_PI);
}
else
{
mySoundAccessDenied();
}
}
else if (message == "lock")
{
if (myPermissionCheck(id) == TRUE)
{
isLocked = TRUE;
mySoundConfirmed();
}
else
{
mySoundAccessDenied();
}
}
else if (message == "unlock")
{
if (myPermissionCheck(id) == TRUE)
{
isLocked = FALSE;
mySoundConfirmed();
}
else
{
mySoundAccessDenied();
}
}
else if (message == "/door opened" && llSubStringIndex(llGetObjectDesc(), "door:") == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
openPos = llGetLocalPos();
openRot = llGetLocalRot();
openScale = llGetScale();
isOpen = TRUE;
if (! (closedPos == ZERO_VECTOR && closedRot == ZERO_ROTATION && closedScale == ZERO_VECTOR))
{
mySetDoorParams(openPos, openRot, openScale, closedPos, closedRot, closedScale);
}
}
else
{
mySoundAccessDenied();
}
}
else if (message == "/door closed" && llSubStringIndex(llGetObjectDesc(), "door:") == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
closedPos = llGetLocalPos();
closedRot = llGetLocalRot();
closedScale = llGetScale();
isOpen = FALSE;
if (! (openPos == ZERO_VECTOR && openRot == ZERO_ROTATION && openScale == ZERO_VECTOR))
{
mySetDoorParams(openPos, openRot, openScale, closedPos, closedRot, closedScale);
}
}
else
{
mySoundAccessDenied();
}
}
}
sensor(integer num_detected)
{
if (openerKey != NULL_KEY)
{
integer i;
for (i = 0; i < num_detected; i++)
{
if (llDetectedKey(i) == openerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
{
myOpenDoor();
}
}
openerKey = NULL_KEY;
}
else
{
integer i;
for (i = 0; i < num_detected; i++)
{
if (llDetectedKey(i) == closerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
{
myCloseDoor();
}
}
closerKey = NULL_KEY;
}
}
collision_start(integer num_detected)
{
integer i;
for (i = 0; i < num_detected; i++)
{
if (myPermissionCheck(llDetectedKey(i)) == TRUE)
{
avatarName = llDetectedName(i);
myOpenDoor();
}
else if (llDetectedType(i) & AGENT)
{
mySoundAccessDenied();
}
}
}
} // End of default state and end of script.
// Timeless Storage Crate - Mover
// by Timeless Prototype
// 2007-11-04
// 1. Place this script in the objects that will be rezzed.
// 2. Place copies of the objects in the storage prim.
// 3. Ensure the Storage script is in the storage prim.
// 4. Touch the storage prim and Save locations.
integer isAboutToMove = FALSE;
integer rezzerId = 0;
integer lh = 0;
default
{
state_entry()
{
if (llGetObjectName() == "Object")
{
state awaitNameChange;
}
lh = llListen(23, "", NULL_KEY, "");
}
state_exit()
{
llListenRemove(lh);
}
on_rez(integer start_param)
{
isAboutToMove = TRUE;
rezzerId = start_param;
}
listen(integer channel, string name, key id, string message)
{
if (llGetOwnerKey(id) == llGetOwner())
{
if ((llSubStringIndex(message, "cmd|crate|store|") == 0 && (rezzerId == 0 || (integer)llGetSubString(message, 16, -1) == rezzerId)) || (message == "cmd|crate|append" && rezzerId == 0))
{
llRegionSay(23, "cmd|crate|add|" + (string)llGetPos() + "|" + (string)llGetRootRotation());
}
else if (llSubStringIndex(message, "cmd|crate|derez|") == 0)
{
// check the id matches
integer theId = (integer)llGetSubString(message, 16, -1);
if (theId == rezzerId)
{
llDie();
}
}
else if (llSubStringIndex(message, "cmd|crate|moverelative|") == 0 && isAboutToMove == TRUE)
{
isAboutToMove = FALSE;
list tokens = llParseStringKeepNulls(message, ["|"], []);
vector pos = llGetPos() + (vector)llList2String(tokens, 3);
rotation rot = (rotation)llList2String(tokens, 4);
llSetRot(rot);
integer timeout = 1000;
while (llVecDist(llGetPos(), pos) > 0.01)
{
llSetPos(pos);
}
}
else if (llSubStringIndex(message, "cmd|crate|setid|") == 0)
{
list tokens = llParseStringKeepNulls(message, ["|"], []);
key theKey = (key)llList2String(tokens, 3);
integer theId = (integer)llList2String(tokens, 4);
if (llGetKey() == theKey)
{
rezzerId = theId;
}
}
}
}
}
state awaitNameChange
{
state_entry()
{
llOwnerSay("This object needs to be given a unique name to activate this script");
llSetTimerEvent(1.0);
}
state_exit()
{
llSetTimerEvent(0.0);
}
timer()
{
if (llGetObjectName() != "Object")
{
llOwnerSay("This object can now be stored");
state default;
}
}
}
// Timeless Storage Crate - Storage
// by Timeless Prototype
// 2007-11-04
// 1. Place this script in the storage prim.
// 2. Follow instructions in the Mover script.
float storageTimeout = 15.0; // seconds
list objects = [];
integer index = 0;
integer lh = 0;
integer uniqueId = 0;
integer wasTouched = FALSE;
integer append = FALSE;
chooseAnotherId()
{
uniqueId = 0;
while (uniqueId == 0)
{
uniqueId = (integer)llFrand(30000.0);
}
llRegionSay(23, "cmd|crate|doesanyonehaveid|" + (string)uniqueId);
}
rezObject(integer index)
{
llSetTimerEvent(0.0);
string object = llList2String(objects, index);
list tokens = llParseStringKeepNulls(object, ["|"], []);
string name = llList2String(tokens, 0);
vector pos = (vector)llList2String(tokens, 1);
rotation rot = (rotation)llList2String(tokens, 2) * llGetRot();
llRezAtRoot(name, llGetPos(), ZERO_VECTOR, rot, uniqueId);
llSetTimerEvent(5.0);
}
default
{
state_entry()
{
if (uniqueId == 0)
{
state findUniqueId;
}
lh = llListen(23, "", NULL_KEY, "");
llSetText("Touch for menu\n" + (string)llGetListLength(objects) + " positions stored\n" + (string)llGetFreeMemory() + " bytes free", <1,1,1>, 1.0);
}
state_exit()
{
llListenRemove(lh);
}
touch_start(integer total_number)
{
if (llGetOwnerKey(llDetectedKey(0)) == llGetOwner())
{
wasTouched = TRUE;
llDialog(llDetectedKey(0), "Select an operation:", ["Store", "Append", "Derez", "Rez"], 23);
}
}
on_rez(integer start_param)
{
state findUniqueId;
}
listen(integer channel, string name, key id, string message)
{
if (llGetOwnerKey(id) == llGetOwner())
{
if (message == "Store" && wasTouched == TRUE)
{
wasTouched = FALSE;
append = FALSE;
state store;
}
else if (message == "Append" && wasTouched == TRUE)
{
wasTouched = FALSE;
append = TRUE;
state store;
}
else if (message == "Derez" && wasTouched == TRUE)
{
wasTouched = FALSE;
llRegionSay(23, "cmd|crate|derez|" + (string)uniqueId);
}
else if (message == "Rez" && wasTouched == TRUE)
{
wasTouched = FALSE;
if (objects == [])
{
llOwnerSay("Nothing was stored yet");
}
else
{
state rez;
}
}
if (llSubStringIndex(message, "cmd|crate|doesanyonehaveid|") == 0)
{
integer theId = (integer)llGetSubString(message, 27, -1);
if (theId == uniqueId)
{
llRegionSay(23, "cmd|crate|ihaveid|" + (string)uniqueId);
}
}
}
}
}
state store
{
state_entry()
{
llOwnerSay("Storing...");
lh = llListen(23, "", NULL_KEY, "");
if (append == FALSE)
{
objects = [];
llRegionSay(23, "cmd|crate|store|" + (string)uniqueId);
}
else
{
llRegionSay(23, "cmd|crate|append");
}
llSetTimerEvent(storageTimeout);
}
state_exit()
{
llSetTimerEvent(0.0);
llOwnerSay("Storage completed, " + (string)llGetListLength(objects) + " positions stored");
llListenRemove(lh);
}
timer()
{
state default;
}
listen(integer channel, string name, key id, string message)
{
if (llGetOwnerKey(id) == llGetOwner())
{
if (llSubStringIndex(message, "cmd|crate|add|") == 0)
{
llSetTimerEvent(0.0);
if (llGetInventoryType(name) == INVENTORY_OBJECT)
{
list tokens = llParseStringKeepNulls(message, ["|"], []);
vector pos = ((vector)llList2String(tokens, 3) - llGetPos()) / llGetRot();
rotation rot = (rotation)llList2String(tokens, 4) / llGetRot();
objects += [name + "|" + (string)pos + "|" + (string)rot];
llSetText("Positions stored: " + (string)llGetListLength(objects), <1,1,1>, 1.0);
// set the id in the object
llRegionSay(23, "cmd|crate|setid|" + (string)id + "|" + (string)uniqueId);
}
llSetTimerEvent(storageTimeout);
}
}
}
}
state rez
{
state_entry()
{
index = 0;
llOwnerSay("Rezzing...");
rezObject(index);
}
state_exit()
{
llSetTimerEvent(0.0);
llOwnerSay("Rezzing complete");
}
timer()
{
string name = llList2String(llParseStringKeepNulls(llList2String(objects, index), ["|"], []), 0);
llOwnerSay("Rez operation for '" + name + "' timed out, parcel full, object removed from contents or insufficient parcel permissions?");
state default;
}
object_rez(key id)
{
llSetTimerEvent(0.0);
// tell it where to go and how to rotate relative to our rotation and position
string object = llList2String(objects, index);
list tokens = llParseStringKeepNulls(object, ["|"], []);
string name = llList2String(tokens, 0);
vector pos = (vector)llList2String(tokens, 1) * llGetRot();
rotation rot = (rotation)llList2String(tokens, 2) * llGetRot();
llWhisper(23, "cmd|crate|moverelative|" + (string)pos + "|" + (string)rot);
if (index + 1 == llGetListLength(objects))
{
state default;
}
else
{
index++;
rezObject(index);
}
}
}
state findUniqueId
{
state_entry()
{
lh = llListen(23, "", NULL_KEY, "");
llSetText("Assigning unique identifier to this crate...", <1,1,1>, 1.0);
chooseAnotherId();
llSetTimerEvent(5.0);
}
state_exit()
{
llSetTimerEvent(0.0);
llListenRemove(lh);
}
listen(integer channel, string name, key id, string message)
{
if (llGetOwnerKey(id) == llGetOwner())
{
if (llSubStringIndex(message, "cmd|crate|ihaveid|") == 0)
{
integer theId = (integer)llGetSubString(message, 17, -1);
if (theId == uniqueId)
{
llSetTimerEvent(0.0);
chooseAnotherId();
llSetTimerEvent(5.0);
}
}
}
}
timer()
{
state default;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment