Page 1 of 1

Builder's Buddy Update for Giant Varregions

Posted: Sat Feb 05, 2022 9:44 pm
by Brayla Sana
I made the changes to accommodate the new giant regions. You can find a copy of these at the Brayla Sana Gallery sim along with other useful free scripts.

Here is the main script:

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.10 (Base Script)
// by Newfie Pendragon, 2006-2008
//
// Updated by Brayla Sana 2020
//
///////////////////////////////////////////////////////////////////////////////
//
// Script Purpose & Use
// Functions are dependent on the "component script"
//
// QUICK USE:
// - Copy this entire notecard and place it in a script.  Name it "BB Base".
// - 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;
integer PRIMCHAN = -192567;             // OpenSim Modification - also comment out the previous line for OpenSim
                                        // ***THIS MUST MATCH IN BOTH SCRIPTS!***

///////////////////////////////////////////////////////////////////////////////
// Variables for Positioning limits within the sim
//
// Change these values if your using Megaregions or want to limit otherwise.
float vDestPosXMIN = 0.0;
float vDestPosXMAX = 2048.0;  //2048 for Varregions
float vDestPosYMIN = 0.0;
float vDestPosYMAX = 2048.0;  //2048 for Varregions
float vDestPosZMAX = 10000.0;



//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();
    llSleep(2);

    if(!bRezzing) {
        bRezzing = TRUE;
        //timer_on();
    }
    llSay(PRIMCHAN, "SET_LIMITS " + (string)vDestPosXMIN + " " + (string)vDestPosXMAX + " " + (string)vDestPosYMIN + " " + (string)vDestPosYMAX + " " + (string)vDestPosZMAX );
}

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;
    }
}

And Here is the Component:

Code: Select all



///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.10 (Component Script)
// by Newfie Pendragon, 2006-2008
//
// Updated by Brayla Sana 2020
//
///////////////////////////////////////////////////////////////////////////////
//
// 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
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Added a Memory datastorage for opensim using osMakeNotecard
///////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////
// 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;
integer PRIMCHAN = -192567;           // OpenSim Modification - also comment out the previous line for OpenSim
                                      // ***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;


list record_mem = []; // Memory to be stored
key g_quary_nc;  //for reading our memory notecard
integer nc_line;  //what line are we reading
integer iStartValue;

//////////////////////////////////////////////////////////////////////////////////////////
// Variables for Positioninglimits within the sim
float vDestPosXMIN = 0.0;
float vDestPosXMAX = 2048.0;
float vDestPosYMIN = 0.0;
float vDestPosYMAX = 2048.0;
float vDestPosZMAX = 10000.0;


////////////////////////////////////////////////////////////////////////////////
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 < iHops; x++ ) {
            lParams += [ PRIM_POSITION, vDestPos ];
        }
        llSetPrimitiveParams(lParams);
        //llSleep(0.1);
        i++;
    }

    //Set rotation
    llSetRot(rDestRot);
}

start_move(string sText, key kID)
{
    //Don't move if we've not yet recorded a position
    if( !bRecorded ) return;

    //Also ignore commands from bases with a different owner than us
    //(Anti-hacking measure)
    if( llGetOwner() != llGetOwnerKey(kID) ) return;

    //Calculate our destination position relative to base?
    if(!bAbsolute) {
        //Relative position
        //Calculate our destination position
        sText = other_words(sText, " ");
        list lParams = llParseString2List(sText, [ "|" ], []);
        vector vBase = (vector)llList2String(lParams, 0);
        rotation rBase = (rotation)llList2String(lParams, 1);

        vDestPos = (vOffset * rBase) + vBase;
        rDestRot = rRotation * rBase;
    } else {
        //Sim position
        vDestPos = vOffset;
        rDestRot = rRotation;
    }

    //Make sure our calculated position is within the sim
    if(vDestPos.x < vDestPosXMIN) vDestPos.x = vDestPosXMIN;
    if(vDestPos.x > vDestPosXMAX) vDestPos.x = vDestPosXMAX;
    if(vDestPos.y < vDestPosYMIN) vDestPos.y = vDestPosYMIN;
    if(vDestPos.y > vDestPosYMAX) vDestPos.y = vDestPosYMAX;
    if(vDestPos.z > vDestPosZMAX) vDestPos.z = vDestPosZMAX;


    //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)
    {
        iStartValue = iStart;
        if(llGetInventoryType("Builders Buddy Memory") != -1)
        {
            nc_line = 0;
            g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
        }
        else
        {
            //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 == "SET_LIMITS" )
        {
            list lParams = llParseString2List(sText, [ " " ], []);
            
            vDestPosXMIN = llList2Float(lParams, 1);
            vDestPosXMAX = llList2Float(lParams, 2);
            vDestPosYMIN = llList2Float(lParams, 3);
            vDestPosYMAX = llList2Float(lParams, 4);
            vDestPosZMAX = llList2Float(lParams, 5);        
        
        }   
        else if( sCmd == "RECORD" )
        {
            record_mem = [];
            
            //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;
                record_mem += "vOffset|" +(string)vOffset ;
            rRotation = llGetRot() / rBase;
                record_mem += "rRotation|" +(string)rRotation ;
            bAbsolute = FALSE;
                record_mem += "bAbsolute|" +(string)bAbsolute ;
            bRecorded = TRUE;
                record_mem += "bRecorded|" +(string)bRecorded ;
            
            if(llGetInventoryType("Builders Buddy Memory") != -1)
            {
                llRemoveInventory("Builders Buddy Memory");
            }
            osMakeNotecard( "Builders Buddy Memory", record_mem );
            
            
            llOwnerSay("Recorded position.");
            return;
        }

        if( sCmd == "RECORDABS" )
        {
            record_mem = [];
            //Record absolute position
            rRotation = llGetRot();
                record_mem += "rRotation|" +(string)rRotation ;
            vOffset = llGetPos();
                record_mem += "vOffset|" +(string)vOffset ;
            bAbsolute = TRUE;
                record_mem += "bAbsolute|" +(string)bAbsolute ;
            bRecorded = TRUE;
                record_mem += "bRecorded|" +(string)bRecorded ;
                
            if(llGetInventoryType("Builders Buddy Memory") != -1)
            {
                llRemoveInventory("Builders Buddy Memory");
            }
            osMakeNotecard( "Builders Buddy Memory", record_mem );                
            
            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
            if(llGetInventoryType("Builders Buddy Memory") != -1)
            {
                llRemoveInventory("Builders Buddy Memory");
            }
            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;
    }
    dataserver(key queryid, string data)
    {
        if ( queryid == g_quary_nc)
        {
            if (data != EOF)
            {
                list n = llParseString2List(data, ["|"], []);
                
                if(llList2String(n, 0) == "vOffset")
                {
                    vOffset = llList2Vector(n, 1);
                }
                else if(llList2String(n, 0) == "rRotation")
                {
                    rRotation = llList2Rot(n, 1);
                }
                else if(llList2String(n, 0) == "bAbsolute")
                {
                    bAbsolute = (integer)llList2String(n, 1);
                }
                else if(llList2String(n, 0) == "bRecorded")
                {
                    bRecorded = (integer)llList2String(n, 1);
                }
                nc_line++;
                g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
            }
            else
            {
                //Set the channel to what's specified
                if( iStartValue != 0 )
                {
                    PRIMCHAN = iStartValue;
                    state reset_listeners;
                }
            }
        }
    }
}


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
state reset_listeners
{
    //////////////////////////////////////////////////////////////////////////////////////////
    state_entry()
    {
        state default;
    }
}


Re: Builder's Buddy Update for Giant Varregions

Posted: Sun Feb 06, 2022 3:19 pm
by Chris Namaste
hi brayla,
can u please,add the url of your gallery?
i've looked via your profile (did not find url),
i could tp via the kitely map,
landed where beautiful houses are,
i'm sorry i can't find your gallery,
thankyou :)

Re: Builder's Buddy Update for Giant Varregions

Posted: Sun Feb 06, 2022 3:19 pm
by Chris Namaste
Chris Namaste wrote: Sun Feb 06, 2022 3:19 pm hi brayla,
can u please,add the url of your gallery?
i've looked via your profile (did not find url),
i could tp via the kitely map,
landed where beautiful houses are,
i'm sorry i can't find your gallery,
thankyou :)

Re: Builder's Buddy Update for Giant Varregions

Posted: Sun Feb 06, 2022 5:34 pm
by Brayla Sana
hop://grid.kitely.com:8002/Brayla%20Sana%20Gallery/347/316/30 is the slurl to the free scripts area of my sim.

Re: Builder's Buddy Update for Giant Varregions

Posted: Mon Feb 07, 2022 8:28 am
by Filipa Thespian
you my lady are the bestest :)