Reset Everything (Deletes Itself)

Expired

Resets float text, object rotate, texture animation, sit-target, & much more.

 

default
{
    state_entry()
    {
        llSetTextureAnim(FALSE,0,0,0,0.0,0.0,0.0);
        llSetText("",ZERO_VECTOR,0.0);
        llParticleSystem([]);
        llSetPayPrice(PAY_DEFAULT,[PAY_DEFAULT,PAY_DEFAULT,PAY_DEFAULT,PAY_DEFAULT]);
        llSitTarget(ZERO_VECTOR,ZERO_ROTATION);
        llTargetOmega(ZERO_VECTOR,0.0,0.0);
        llStopSound();
        llStopMoveToTarget();
        llStopLookAt();
        llVolumeDetect(FALSE);
        llCollisionFilter("", NULL_KEY, TRUE);
        llForceMouselook(FALSE);
        llPassCollisions(TRUE);
        llPassTouches(TRUE);
        llRemoveVehicleFlags(-1);
        llSetVehicleType(VEHICLE_TYPE_NONE);
        llSetRemoteScriptAccessPin(0);
        llSetSitText("");
        llSetTouchText("");
        llSetBuoyancy(0.0);
        llSetForceAndTorque(ZERO_VECTOR,ZERO_VECTOR,FALSE) ;
        llSetPrimitiveParams([PRIM_POINT_LIGHT,FALSE,<1.0,1.0,1.0 >,0.0,10.0,0.75]);
        llSay(0,"Object parameters have been reset. Deleting this script now.");
        llRemoveInventory(llGetScriptName());
    }
}

 

Channel Number Generator

Expired

Creates rancom channels

 

//
// generateChannel(): Given a text string, generate a (relatively) unique channel number.
// This conversion is repeatable, so you can use it to easily communicate with a script by
// remembering a text string instead of a channel number.
//
// You can copy or modify this script if you give me credit.
// Petre Lamar, 2006-07-31
//
integer generateChannel(string text)
{
    list hexDigits = ["dummy", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
    string md5 = llMD5String(text, 0);
    integer length = llStringLength(md5);
    integer channelNumber = 1; // zero makes a bad multiplier :-)
    integer hexValue;
    string character;
        
    for (length--; length >= 0; length--)
    {
        character = llGetSubString(md5, length, length);
        hexValue = llListFindList(hexDigits, [ character ]);
        channelNumber *= hexValue;
        if (channelNumber == 0)
        {
            // zero times anything remains zero, so force it to one
            channelNumber++;
        }
    }

    return channelNumber;
}

default
{
    state_entry()
    {
        llWhisper(0, "Type something and I'll convert that into a channel number!");
        llListen(0, "", llGetOwner(), "");
    }

    listen(integer channel, string name, key id, string message)
    {
        integer result = generateChannel(message);
        llWhisper(0, "'" + message + "' yields '" + (string)result + "'");
    }
}

 

Builders' Tabs

Expired

Abbreviation: BTs (eg. "This house uses BTs"), pronounced: b(ee) t(ee)s.

Builders' Tabs were invented and sold by me (TimelessPrototype). However, since they have proved to be the builder's right hand tool for precision building with ease - especially for unusually-shaped buildings - I thought I should share the script for all to enjoy. I DO NOT support this script so please don't ask me about it. Please use the http://lslwiki.net/lslwiki/css/outside.gif); padding-right: 9px; font-family: Verdana, sans-serif; font-size: 13px; line-height: 16px; background-position: 100% 50%; background-repeat: no-repeat no-repeat; ">SL forums and ask for help there. Thank you. However, the intellectual property is still mine. You may not sell Builders' Tabs unless they are part of your pre-fabricated product (eg. housing modules with touch assembly using Builders' Tabs). If you are making a raging profit, please show your financial appreciation by donating to TimelessPrototype in SL.

Please follow these instructions carefully to make the Builder's Tab.

1. Create two prims. One prim serves as a Tab, and the other serves as the root prim.
2. Link the two prims. You could have any number of prims in this link set with one or more Tab prims.
3. In the root prim, drop in the following script and rename the script to "mover".

 

 

// By Timeless Prototype
// 2005-01-17

vector   targetPos = ZERO_VECTOR;
rotation targetRot = ZERO_ROTATION;
integer  timeOut;
integer  pendingMove = 0;
integer  pendingLockDelete = 0;
integer  lockTimeOut;

init()
{
    if (! (llGetPermissions() & PERMISSION_CHANGE_LINKS))
    {
        llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
    }
}

default
{
    state_entry()
    {
        init();
    }

 

 

 


4. In the non-root prim (the Tab prim), drop in the following script and rename the script to "tab".

 

 

// Tip: zero rot the Tab prim then link to east side of root prim.
// You can link it anywhere to the root prim, but when you first use it,
// this is a good demonstrational position.

integer  lh;
vector   targetJointPos = <0,0,0>;
rotation targetJointRot = ZERO_ROTATION;
integer  nodeActive = 0;
integer  pendingTabDelete = 0;

init()
{
    if (llGetObjectName() != "Tab")
    {
        llSetObjectName("Tab");
    }
}

restoreColor()
{
    llSetColor(<0,0,1>, 0); // +ve Z axis (face)
    llSetColor(<0,1,0>, 1); // -ve Y axis (face)
    llSetColor(<1 ,0,0>, 2); // +ve X axis (face)
    llSetColor(<0,1,0>, 3); // +ve Y axis (face)
    llSetColor(<1 ,0,0>, 4); // -ve X axis (face)
    llSetColor(<0,0,1>, 5); // -ve Z axis (face)
    llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_WOOD ] );
}

show()
{
    string plus = "28aa0989-55ef-0abe-332d-5fb243bdc76c";
    string minus = "1f69b45a-6975-6353-87b8-d856f491430b";
    llSetTexture(plus, ALL_SIDES);
    llSetTexture(minus, 1);
    llSetTexture(minus, 4);
    llSetTexture(minus, 5);
}

hide()
{
    llSetTexture("f54a0c32-3cd1-d49a-5b4f-7b792bebc204", ALL_SIDES);
    llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_WOOD ] );
}

default
{
    state_entry()
    {
        init();
        lh = llListen(23, "", "", "");
        restoreColor();
        show();
    }
    
    on_rez(integer start_num)
    {
        llResetScript();
    }
    
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (pendingTabDelete == 1)
            {
                if (llGetLinkNumber() <2)
                {
                    llDie();
                }
                else
                {
                    llSetTimerEvent(0.0);
                    llSetTimerEvent(1.0);
                }
            }
        }
    }

    timer()
    {
        llSetTimerEvent(0.0);
        llMessageLinked(LINK_SET, llGetLinkNumber(), "final_lock_all", NULL_KEY);
    }
    
    touch_start(integer total_number)
    {
        if (targetJointPos == <0,0,0> && llDetectedKey(0) == llGetOwner())
        {
            if (nodeActive == 0)
            {
                // TESTED, LEAVE THIS ALONE!
                llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
                llShout(23, "joint|" + (string)(llGetRootPosition() + (llGetLocalPos() * llGetRootRotation())) + "|" + (string)(llGetLocalRot() * llGetRootRotation()));
                llSetColor(<1 ,0,1>, ALL_SIDES);
                llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_LIGHT ] );
                nodeActive = 1;
                // END OF TESTED
            }
            else 
            {
                llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
                llShout(23, "cancel_join");
                restoreColor();
                nodeActive = 0;
            }
        }
        else if (llDetectedKey(0) == llGetOwner())
        {
            llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
            llShout(23, "cancel_join");
            // Begin move to last known location
            
            rotation targetRootRot =  (ZERO_ROTATION / (<0.0, 0.0, 1.0, 0.0> * llGetLocalRot())) * targetJointRot;
            
            vector targetRootPos = targetJointPos - (llGetLocalPos() * targetRootRot);
            
            llMessageLinked(LINK_SET, 1, "move_to|" + (string)targetRootPos + "|" + (string)targetRootRot, NULL_KEY);
            restoreColor();
            nodeActive = 0;
            targetJointPos = <0,0,0>;
            targetJointRot = ZERO_ROTATION;
        }
    }
    
    listen(integer channel, string name, key id, string message)
    {
        if (llGetOwner() == llGetOwnerKey(id) || llGetOwner() == id)
        {
            list words   = llParseStringKeepNulls(llToLower(message), ["|"], []);
            string word0 = llList2String(words, 0);
            string word1 = llList2String(words, 1);
            string word2 = llList2String(words, 2);
            
            if (word0 == "joint")
            {
                targetJointPos = (vector)word1;
                targetJointRot = (rotation)word2;
                restoreColor();
                nodeActive = 0;
            }
            else if (word0 == "cancel_join")
            {
                targetJointPos = <0,0,0>;
                targetJointRot = ZERO_ROTATION;
                restoreColor();
                nodeActive = 0;
            }
            else if (word0 == "show")
            {
                show();
            }
            else if (word0 == "hide")
            {
                hide();
            }
            else if (word0 == "final_lock_all")
            {
                llSleep(llFrand(1.0));
                pendingTabDelete = 1;
                llSetTimerEvent(1.0);
            }
        }
    }
    
    moving_start()
    {
        if (nodeActive == 1)
        {
            llShout(23, "cancel_join");
            restoreColor();
            nodeActive = 0;
        }
    }
}

 

 

 

5. Take a copy of this Builder's Tab into your inventory. This will become your Base Tab that gets used to make modules that can be touch assembled.

Test your new Builders' Tabs:

1. Rez two of these Builders' Tabs
2. Touch the Tab on each and watch them magically align the tabs on themselves.

The following is derived from the help notecard that came with the Builders' Tabs Kit:

BUILDER'S TAB KIT version 2.1
bringing 'Touch to Assemble' to your buildings


by Timeless Prototype


NOTE: ADVANCED BUILDING SKILLS REQUIRED FOR PRECISION PLACEMENT OF BUILDER TABS!!!


What is it?


Ever needed to join up building parts over and over again? Builder's Tabs introduce an easy way to Touch to Assemble your buildings.

The Builder's Tab is a prim that you link one or more of to your building modules. A building module is typically a component of a building, perhaps a wall, an entire room or a roof for example. You place the 'mover' script into the building module's root prim. When you touch the first Tab that is where the other module must move to. Touch the Tab on the other module to begin the movement.

The target module stays in place and the second module will move and rotate as necessary so that the touched prims (Tabs) overlap exactly.

You WILL REQUIRE precise building skills if you want the modules to join up precisely by correctly placing the Tabs.


What Commands Are There?


Say:
'/23 hide' - to hide the Tabs from view.
'/23 show' - to show the Tabs again.
'/23 final_lock_all' - de-links the tabs and deletes the tab prims and the mover scripts. Only the current Owner can issue this command.


How do I get started?


1. Rez the Builder's Tab.
2. De-link the Tab from the example root prim.
3. Position the tab on your building module.
4. Link the Tab (or more than one Tab if you like) to your building module. The building module should be Shift selected LAST so that the Tabs are NEVER the root prim.
5. Copy the 'mover' script from the example Builder's Tab's root prim's contents into your inventory.
6. Copy the 'mover' script from your inventory into the root prim of your building module.
7. Your building module is now ready for touch assembly. Take a copy of your work. You can add as many Tabs to a single module as you like.
8. Test it.

Tips:


The Tabs when touched will move to overlap eachother exactly. They will also rotate 180 degrees around the local Z axis. So with this in mind, always keep the RED face with the PLUS sign facing outwards.

 

 

 

Builders' Buddy

Expired

This pair of scripts makes it easy to package a large, complex linked set of objects into a single package, and then build the entire complex at once. Basically, it works by choosing one object to be the "base", and then putting a copy of all the other objects into base's inventory after recording their relative position and rotation. The instructions expect intermediate building skills, and are in the scripts themselves, so they won't be repeated here.

 

The first script is also a decent example of using a menu, and of parsing chat input.  

 

Primary Root Prim Script

 

///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.10 (Base Script)
// by Newfie Pendragon, 2006-2008
///////////////////////////////////////////////////////////////////////////////
//
// Script Purpose & Use
// Functions are dependent on the "component script"
//
// QUICK USE:
// - Drop this script in the Base.
// - Drop the "Component" Script in each building part.
// - Touch your Base, and choose RECORD
// - Take all building parts into inventory
// - Drag building parts from inventory into Base Prim
// - Touch your base and choose BUILD
//
// OTHER COMMANDS from the Touch menu
// - To reposition, move/rotate Base Prim choose POSITION
// - To lock into position (removes scripts) choose DONE
// - To delete building pieces: choose CLEAN
///////////////////////////////////////////////////////////////////////////////
// This script is copyrighted material, and has a few (minor) restrictions.
// For complete details, including a revision history, please see
//  http://wiki.secondlife.com/wiki/Builders_Buddy
///////////////////////////////////////////////////////////////////////////////
 
// Channel used by Base Prim to talk to Component Prims
// This channel must be the same one in the component script
// A negative channel is used because it elimited accidental activations
// by an Avatar talking on obscure channels
integer DefaultPRIMCHAN = -192567;     // Default channel to use
integer PRIMCHAN = DefaultPRIMCHAN;    // Channel used by Base Prim to talk to Component Prims;
                                       // ***THIS MUST MATCH IN BOTH SCRIPTS!***
 
//The UUID of the creator of the object
//Leave this as "" unless SL displays wrong name in object properties
key creatorUUID = "";
 
// Set to TRUE to allow group members to use the dialog menu
// Set to FALSE to disallow group members from using the dialog menu
integer ingroup = TRUE;
 
// Set to TRUE to delete piece from inventory when rezzed
// (WARNING) If set to FALSE, user will be able to rez multiple copies
integer deleteOnRez = FALSE;
 
// Allow non-creator to use CLEAN command?
// (WARNING) If set to TRUE, it is recommended to set
// deleteOnRez to FALSE, or user could lose entire building
integer allowClean = TRUE;
 
//When user selects CLEAN, delete the base prim too?
integer dieOnClean = FALSE;
 
// Set to TRUE to record piece's location based on sim
// coordinates instead of relationship to base prim
integer recordSimLocation = FALSE;
 
// Set to TRUE to rez all building pieces before positioning,
// or FALSE to do (slower?) one at a time
integer bulkBuild = TRUE;
 
//Set to FALSE if you dont want the script to say anything while 'working'
integer chatty = TRUE;
 
//How long to listen for a menu response before shutting down the listener
float fListenTime = 30.0;
 
//How often (in seconds) to perform any timed checks
float fTimerRate = 0.25;
 
//How long to sit still before exiting active mode
float fStoppedTime = 30.0;
 
//SL sometimes blocks rezzing to prevent "gray goo" attacks
//How long we wait (seconds) before we assume SL blocked our rez attempt
integer iRezWait = 10;
 
//Specify which Menu Options will be displayed
//FALSE will restrict full options to creator
//TRUE will offer full options to anyone
integer fullOptions = FALSE;
 
//Set to TRUE if you want ShapeGen channel support
// (Last 4 digits of channel affected)
integer SGCompatible = FALSE;
 
 
///////////////////////////////////////////////////////////////////////////////
//Part of KEYPAD CODE BY Andromeda Quonset....More added below in seevral places
list Menu2 = [ "-", "0","enter","7","8","9","4","5","6","1","2","3"];
string Input = "";
string Sign = "+";
string SignInput = " ";
string Caption = "Enter a number, include any leading 0's: ";
 
///////////////////////////////////////////////////////////////////////////////
// DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
///////////////////////////////////////////////////////////////////////////////
 
//Name each option-these names will be your button names.
string optRecord = "Record";
string optReset = "Reset";
string optBuild = "Build";
string optPos = "Position";
string optClean = "Clean";
string optDone = "Done";
string optChannel = "Channel";
 
//Menu option descriptions
string descRecord = ": Record the position of all parts\n";
string descReset = ": Forgets the position of all parts\n";
string descBuild = ": Rez inv. items and position them\n";
string descPos = ": Reposition the parts to a new location\n";
string descClean = ": De-Rez all pieces\n";
string descDone = ": Remove all BB scripts and freeze parts in place.\n";
string descChannel = ": Change Channel used on base and parts.\n";
 
integer MENU_CHANNEL;
integer MENU2_CHANNEL;
integer MENU_HANDLE;
integer MENU2_HANDLE;
key agent;
key objectowner;
integer group;
string title = "";
list optionlist = [];
integer bMoving;
vector vLastPos;
rotation rLastRot;
integer bRezzing;
integer iListenTimeout = 0;
integer iLastRez = 0;
integer iRezIndex;
 
 
InvertSign()
{
    if(Sign == "+")
        Sign = "-";
    else
        Sign = "+";
}
 
//To avoid flooding the sim with a high rate of movements
//(and the resulting mass updates it will bring), we used
// a short throttle to limit ourselves
announce_moved()
{
    llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
    llResetTime();        //Reset our throttle
    vLastPos = llGetPos();
    rLastRot = llGetRot();
    return;
}
 
 
rez_object()
{
    //Rez the object indicated by iRezIndex
    llRezObject(llGetInventoryName(INVENTORY_OBJECT, iRezIndex), llGetPos(), ZERO_VECTOR, llGetRot(), PRIMCHAN);
    iLastRez = llGetUnixTime();
 
    if(!bRezzing) {
        bRezzing = TRUE;
        //timer_on();
    }
}
 
post_rez_object()
{
    if ( creatorUUID != llGetOwner() ) {
        if(deleteOnRez) llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, iRezIndex));
    }
}
 
heard(integer channel, string name, key id, string message)
{
    if( channel == PRIMCHAN ) {
        if( message == "READYTOPOS" ) {
            //New prim ready to be positioned
            vector vThisPos = llGetPos();
            rotation rThisRot = llGetRot();
            llRegionSay(PRIMCHAN, "MOVESINGLE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
 
        } else if( message == "ATDEST" ) {
            //Rez the next in the sequence (if any)
            iRezIndex--;
            if(iRezIndex >= 0) {
                //Attempt to rez it
                rez_object();
            } else {
                //We are done building, reset our listeners
                iLastRez = 0;
                bRezzing = FALSE;
                state reset_listeners;
            }
        }
        return;
 
    } else if( channel == MENU_CHANNEL ) {   //Process input from original menu
        if ( message == optRecord ) {
            PRIMCHAN = DefaultPRIMCHAN;
            llOwnerSay("Recording positions...");
            if(recordSimLocation) {
                //Location in sim
                llRegionSay(PRIMCHAN, "RECORDABS " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
            } else {
                //Location relative to base
                llRegionSay(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
            }
            return;
        }
        if( message == optReset ) {
            llOwnerSay("Forgetting positions...");
            llShout(PRIMCHAN, "RESET");
            return;
        }
        if ( message == optBuild ) {
            if(chatty) llOwnerSay("Rezzing build pieces...");
 
            //If rezzing/positioning one at a time, we need
            // to listen for when they've reached their dest
            if(!bulkBuild) {
                llListen(PRIMCHAN, "", NULL_KEY, "READYTOPOS");
                llListen(PRIMCHAN, "", NULL_KEY, "ATDEST");
            }
 
            //Start rezzing, last piece first
            iRezIndex = llGetInventoryNumber(INVENTORY_OBJECT) - 1;
            rez_object();
            return;
        }
        if ( message == optPos ) {
            if(chatty) llOwnerSay("Positioning");
            vector vThisPos = llGetPos();
            rotation rThisRot = llGetRot();
            llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
            return;
        }
        if ( message == optClean ) {
            llRegionSay(PRIMCHAN, "CLEAN");
            if(dieOnClean) llDie();
            return;
        }
        if ( message == optDone ) {
            llRegionSay(PRIMCHAN, "DONE");
            if(chatty) llOwnerSay("Removing Builder's Buddy scripts.");
            return;
        }
        if ( message == optChannel ) {
            Sign = "+"; //default is a positive number
            Input = "";
            llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
        }
 
    } else if ( channel == MENU2_CHANNEL ) {    //process input from MENU2
        // if a valid choice was made, implement that choice if possible.
        // (llListFindList returns -1 if Choice is not in the menu list.)
        if ( llListFindList( Menu2, [ message ]) != -1 ) {
            if( llListFindList(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], [message]) != -1) {
                Input += message;
                SignInput = Sign + Input;
                llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
 
            } else if( message == "-" ) {
                InvertSign();
                SignInput = Sign + Input;
                llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
 
            } else if( message == "enter" ) {     //terminate input from menu2
                string CalcChan = Input;
 
                //Apply ShapeGen compatibility?
                if(SGCompatible) {
                    //new assign channel number, forcing last 4 digits to 0000
                    integer ChanSize = llStringLength(Input); //determine number of digits (chars)
                    if(ChanSize > 5) {
                        CalcChan = llGetSubString(Input, 0, 4);    //Shorten to 5 digits
                    }
                    CalcChan += "0000"; //append 0000
                    if(Sign == "-")
                        CalcChan = Sign + CalcChan;
                }
                PRIMCHAN = (integer)CalcChan; //assign channel number
                llOwnerSay("Channel set to " + (string)PRIMCHAN + ".");
            }
 
        } else {
            llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
        }
    }
}
 
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
default {
    ///////////////////////////////////////////////////////////////////////////////
    changed(integer change) {
        if(change & CHANGED_OWNER)
        llResetScript();
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    state_entry () {
        //Determine the creator UUID
        if(creatorUUID == "") creatorUUID = llGetCreator();
 
        //Use which menu?
        if (creatorUUID == llGetOwner() || fullOptions) {
            //Display all options
            optionlist = [optPos, optClean, optDone, optRecord, optReset, optBuild, optChannel];
            title = optRecord + descRecord;
            title += optReset + descReset;
            title += optBuild + descBuild;
            title += optPos + descPos;
            title += optClean + descClean;
            title += optDone + descDone;
            title += optChannel + descChannel;
 
        } else {
            //Display limited options
            if(allowClean) {
                optionlist = [optBuild, optPos, optClean, optDone];
                title = optBuild + descBuild;
                title += optPos + descPos;
                title += optClean + descClean;
                title += optDone + descDone;
            } else {
                optionlist = [optBuild, optPos, optDone];
                title = optBuild + descBuild;
                title += optPos + descPos;
                title += optDone + descDone;
            }
        }
 
        //Record our position
        vLastPos = llGetPos();
        rLastRot = llGetRot();
 
        llSetTimerEvent(fTimerRate);
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    touch_start (integer total_number) {
        group = llDetectedGroup(0); // Is the Agent in the objowners group?
        agent = llDetectedKey(0); // Agent's key
        objectowner = llGetOwner(); // objowners key
        // is the Agent = the owner OR is the agent in the owners group
        if ( (objectowner == agent) || ( group && ingroup )  )  {
            iListenTimeout = llGetUnixTime() + llFloor(fListenTime);
            MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
            MENU2_CHANNEL = MENU_CHANNEL + 1;
            MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
            MENU2_HANDLE = llListen(MENU2_CHANNEL,"","","");
            if ( creatorUUID == llGetOwner() || fullOptions) {
                llDialog(agent,title + "Now on Channel " + (string)PRIMCHAN, optionlist, MENU_CHANNEL); //display channel number if authorized
            } else {
                llDialog(agent, title, optionlist, MENU_CHANNEL);
            }
            //timer_on();
        }
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    listen(integer channel, string name, key id, string message) {
        heard(channel, name, id, message);
        return;
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    moving_start()
    {
        if( !bMoving )
        {
            bMoving = TRUE;
            //timer_on();
            announce_moved();
        }
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    object_rez(key id) {
        //The object rezzed, perform any post-rez processing
        post_rez_object();
 
        //Rezzing it all before moving?
        if(bulkBuild) {
            //Move on to the next object
            //Loop through backwards (safety precaution in case of inventory change)
            iRezIndex--;
            if(iRezIndex >= 0) {
                //Attempt to rez it
                rez_object();
 
            } else {
                //Rezzing complete, now positioning
                iLastRez = 0;
                bRezzing = FALSE;
                if(chatty) llOwnerSay("Positioning");
                llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
            }
        }
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    timer() {
        //Did we change position/rotation?
        if( (llGetRot() != rLastRot) || (llGetPos() != vLastPos) )
        {
            if( llGetTime() > fTimerRate ) {
                announce_moved();
            }
        }
 
        //Are we rezzing?
        if(bRezzing) {
            //Did the last one take too long?
            if((llGetUnixTime() - iLastRez) >= iRezWait) {
                //Yes, retry it
                if(chatty) llOwnerSay("Reattempting rez of most recent piece");
                rez_object();
            }
        }
 
        //Open listener?
        if( iListenTimeout != 0 )
        {
            //Past our close timeout?
            if( iListenTimeout <= llGetUnixTime() )
            {
                iListenTimeout = 0;
                llListenRemove(MENU_HANDLE);
            }
        }
    }
 
    ///////////////////////////////////////////////////////////////////////////////
    on_rez(integer iStart)
    {
        //Reset ourselves
        llResetScript();
    }
}
 
 
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
state reset_listeners
{
    //////////////////////////////////////////////////////////////////////////////////////////
    state_entry()
    {
        state default;
    }
}

 

 

----------------

 

Component Pieces Script

 

///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.10 (Component Script)
// by Newfie Pendragon, 2006-2008
///////////////////////////////////////////////////////////////////////////////
//
// Script Purpose & Use
// Functions are dependent on the "component script"
//
// QUICK USE:
// - Drop this script in the Base.
// - Drop the "Component" Script in each building part.
// - Touch your Base, and choose RECORD
// - Take all building parts into inventory
// - Drag building parts from inventory into Base Prim
// - Touch your base and choose BUILD
//
// OTHER COMMANDS from the Touch menu
// - To reposition, move/rotate Base Prim choose POSITION
// - To lock into position (removes scripts) choose DONE
// - To delete building pieces: choose CLEAN
///////////////////////////////////////////////////////////////////////////////
// This script is copyrighted material, and has a few (minor) restrictions.
// For complete details, including a revision history, please see
//  http://wiki.secondlife.com/wiki/Builders_Buddy
///////////////////////////////////////////////////////////////////////////////
 
 
//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
float fTimerInterval = 0.25;        // Time in seconds between movement 'ticks'
integer DefaultChannel = -192567; // Andromeda Quonset's default channel
integer PRIMCHAN = DefaultChannel;  // Channel used by Base Prim to talk to Component Prims;
                                    // ***THIS MUST MATCH IN BOTH SCRIPTS!***
 
//////////////////////////////////////////////////////////////////////////////////////////
// Runtime Variables (Dont need to change below here unless making a derivative)
vector vOffset;
rotation rRotation;
integer bNeedMove;
vector vDestPos;
rotation rDestRot;
integer bMovingSingle = FALSE;
integer bAbsolute = FALSE;
integer bRecorded = FALSE;
 
 
////////////////////////////////////////////////////////////////////////////////
string first_word(string In_String, string Token)
{
    //This routine searches for the first word in a string,
    // and returns it.  If no word boundary found, returns
    // the whole string.
    if(Token == "") Token = " ";
    integer pos = llSubStringIndex(In_String, Token);
 
    //Found it?
    if( pos >= 1 )
        return llGetSubString(In_String, 0, pos - 1);
    else
        return In_String;
}
 
////////////////////////////////////////////////////////////////////////////////
string other_words(string In_String, string Token)
{
    //This routine searches for the other-than-first words in a string,
    // and returns it. If no word boundary found, returns
    // an empty string.
    if( Token == "" ) Token = " ";
 
    integer pos = llSubStringIndex(In_String, Token);
 
    //Found it?
    if( pos >= 1 )
        return llGetSubString(In_String, pos + 1, llStringLength(In_String));
    else
        return "";
}
 
////////////////////////////////////////////////////////////////////////////////
do_move()
{
    integer i = 0;
    vector vLastPos = ZERO_VECTOR;
    while( (i <5) && (llGetPos() != vDestPos) )
    {
        list lParams = [];
 
        //If we're not there....
        if( llGetPos() != vDestPos )
        {
            //We may be stuck on the ground...
            //Did we move at all compared to last loop?
            if( llGetPos() == vLastPos )
            {
                //Yep, stuck...move straight up 10m (attempt to dislodge)
                lParams = [ PRIM_POSITION, llGetPos() + <0, 0, 10.0> ];
                //llSetPos(llGetPos() + <0, 0, 10.0>);
            } else {
                //Record our spot for 'stuck' detection
                vLastPos = llGetPos();
            }
        }
 
        //Try to move to destination
        //Upgraded to attempt to use the llSetPrimitiveParams fast-move hack
        //(Newfie, June 2006)
        integer iHops = llAbs(llCeil(llVecDist(llGetPos(), vDestPos) / 10.0));
        integer x;
        for( x = 0; x  255.0) vDestPos.x = 255.0;
    if(vDestPos.y <0.0) vDestPos.y = 0.0;
    if(vDestPos.y > 255.0) vDestPos.y = 255.0;
    if(vDestPos.z > 4096.0) vDestPos.x = 4096.0;
 
    //Turn on our timer to perform the move?
    if( !bNeedMove )
    {
        llSetTimerEvent(fTimerInterval);
        bNeedMove = TRUE;
    }
    return;
}
 
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
default
{
    //////////////////////////////////////////////////////////////////////////////////////////
    state_entry()
    {
        //Open up the listener
        llListen(PRIMCHAN, "", NULL_KEY, "");
        llRegionSay(PRIMCHAN, "READYTOPOS");
    }
 
    //////////////////////////////////////////////////////////////////////////////////////////
    on_rez(integer iStart)
    {
        //Set the channel to what's specified
        if( iStart != 0 )
        {
            PRIMCHAN = iStart;
            state reset_listeners;
        }
    }
 
    //////////////////////////////////////////////////////////////////////////////////////////
    listen(integer iChan, string sName, key kID, string sText)
    {
        string sCmd = llToUpper(first_word(sText, " "));
 
        if( sCmd == "RECORD" )
        {
            //Record position relative to base prim
            sText = other_words(sText, " ");
            list lParams = llParseString2List(sText, [ "|" ], []);
            vector vBase = (vector)llList2String(lParams, 0);
            rotation rBase = (rotation)llList2String(lParams, 1);
 
            vOffset = (llGetPos() - vBase) / rBase;
            rRotation = llGetRot() / rBase;
            bAbsolute = FALSE;
            bRecorded = TRUE;
            llOwnerSay("Recorded position.");
            return;
        }
 
        if( sCmd == "RECORDABS" )
        {
            //Record absolute position
            rRotation = llGetRot();
            vOffset = llGetPos();
            bAbsolute = TRUE;
            bRecorded = TRUE;
            llOwnerSay("Recorded sim position.");
            return;
        }
 
        //////////////////////////////////////////////////////////////////////////////////////////
        if( sCmd == "MOVE" )
        {
            start_move(sText, kID);
            return;
        }
 
        if( sCmd == "MOVESINGLE" )
        {
            //If we haven't gotten this before, position ourselves
            if(!bMovingSingle) {
                //Record that we are a single-prim move
                bMovingSingle = TRUE;
 
                //Now move it
                start_move(sText, kID);
                return;
            }
        }
 
        //////////////////////////////////////////////////////////////////////////////////////////
        if( sCmd == "DONE" )
        {
            //We are done, remove script
            llRemoveInventory(llGetScriptName());
            return;
        }
 
        //////////////////////////////////////////////////////////////////////////////////////////
        if( sCmd == "CLEAN" )
        {
            //Clean up
            llDie();
            return;
        }
 
        //////////////////////////////////////////////////////////////////////////////////////////
        if( sCmd == "RESET" )
        {
            llResetScript();
        }
    }
 
    //////////////////////////////////////////////////////////////////////////////////////////
    timer()
    {
        //Turn ourselves off
        llSetTimerEvent(0.0);
 
        //Do we need to move?
        if( bNeedMove )
        {
            //Perform the move and clean up
            do_move();
 
            //If single-prim move, announce to base we're done
            if(bMovingSingle) {
                llRegionSay(PRIMCHAN, "ATDEST");
            }
 
            //Done moving
            bNeedMove = FALSE;
        }
        return;
    }
}
 
 
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
state reset_listeners
{
    //////////////////////////////////////////////////////////////////////////////////////////
    state_entry()
    {
        state default;
    }
}