Change font size
It is currently Thu Nov 22, 2018 5:48 am

Forum rules


{L_IMAGE}



Post a new topicPost a reply Page 1 of 3   [ 22 posts ]
Go to page 1, 2, 3  Next
Author Message
 Post subject: Builders' Buddy 1.10 for OpenSim
PostPosted: Wed Jun 10, 2009 10:50 pm 

Joined: Sun Mar 01, 2009 10:07 pm
Posts: 4
Instructions are in the code. I had to add one line where it initializes PRIMCHAN and haven't seen any real problems. One time I had to position a build twice before all parts were correct.

Builders' Buddy 1.10 (Base Script) for OpenSim

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


Builders' Buddy 1.10 (Component Script) for OpenSim

{L_CODE}:
///////////////////////////////////////////////////////////////////////////////
// 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;
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;


////////////////////////////////////////////////////////////////////////////////
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 < 0.0) vDestPos.x = 0.0;
    if(vDestPos.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.x > 768.0) vDestPos.x = 768.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;
    }
}


According to justincc's opensim blog, credit for getting Builders' Buddy working on OpenSim should go to:
{L_QUOTE}:
Alan Webb contributed a patch that enables script state persistence when taking objects into inventory, when saving OpenSim Archives (OARs) and when using attachments (r9265).


Last edited by Joe Radik on Thu Jun 11, 2009 12:42 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Wed Jun 10, 2009 11:35 pm 
Furious Typer
User avatar

Joined: Sat Dec 27, 2008 7:57 am
Posts: 71
Joe, I apologize for sounding like a Moron, but what does "Builders Buddy" do?

_________________
OSG Home User Group: http://groups.google.com/group/OSGHUG


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Thu Jun 11, 2009 12:05 am 

Joined: Sun Mar 01, 2009 10:07 pm
Posts: 4
RetroDan {L_WROTE}:
Joe, I apologize for sounding like a Moron, but what does "Builders Buddy" do?


No problem. It's used a lot in Second Life to package, distribute and erect builds, especially larger ones where the link limits on prims is more restrictive in Second Life than OpenSim. It's similar to a commercial product available in Second Life called Rez Faux.

This is from the documentation on the Second Life Wiki.

{L_QUOTE}:
01. PRODUCT SUMMARY

Builder's Buddy lets ordinary SL users rez a set of unlinked items in their proper places in relation to each other, without needing any building skills. The "Set" is usually a building, but there is no reason it can't also be a statue, a furniture set, etc.

You prepare the unlinked items according to the easy steps below, then for distribution put them in a Packing Box.

05. USAGE SUMMARY

The base script you only use once in an item. It goes in a "base" prim, which is the piece that is moved/rotated/etc. The component script goes into each part or each linked part that makes up the rest of the large build. In short, only one base script, many component scripts. You do not put a component script in the same item where you put a base script.

1. Drop the base script in the Base.
2. Drop the "Component" Script in each building part.
3. Touch your Base, and choose RECORD
4. Take all building parts into inventory except for the base prim
5. Drag building parts from inventory into Base Prim
6. Touch your base and choose BUILD

OTHER COMMANDS from the Touch menu

* To reposition, move or rotate the Base Prim choose POSITION
* To adjust where the house has rezzed after choosing BUILD, you can just edit - arrow move the base prim around, and the Rest of the build will follow;
* To lock into position (removes all scripts, helping to reduce work on the sim server) choose DONE
* To delete building pieces: choose CLEAN


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Thu Jul 09, 2009 3:45 pm 
User avatar

Joined: Thu Jul 09, 2009 3:25 pm
Posts: 3
Location: france
Hello,

I have try to use this, but i never get it work. it rez the object, but it dont move and rotate the objects, like if nothing was recorded.
Somebody use this and its working?

thank you

oligia


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Wed Jul 29, 2009 10:41 am 

Joined: Wed Jul 29, 2009 7:21 am
Posts: 1
oligia imako {L_WROTE}:
Hello,

I have try to use this, but i never get it work. it rez the object, but it dont move and rotate the objects, like if nothing was recorded.
Somebody use this and its working?

thank you

oligia


Olgia I was confused by this at first but here is the solution.

1) Click on the base prim and it brings up the menu.

2) The objects you have built and scripted previously are rezzed on top of the base prim.

3) Click on the base prim again and choose "position" from the menu.

4) Click on the base prim again and "clean" to take all the code from your prims.

I have two videos of the process in Reaction Grid on Open Sim here:

http://blip.tv/file/2414631

and here

http://blip.tv/file/2414863

Hope that helps.


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Thu Jul 30, 2009 4:06 am 
User avatar

Joined: Thu Jul 09, 2009 3:25 pm
Posts: 3
Location: france
Thanks for your help. But i still get some problems :

i do all the recording part, then after i take the object containing all and go to an other region. I rezz the object, go in the menu, do build, parts of my house rezz on top of the prim.

{L_IMAGE}

then i do position. And as i can see, it do the rotation, but it send parts of the house to the limit of the region.

{L_IMAGE}

{L_IMAGE}

thanks for your help


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Mon Aug 03, 2009 11:03 pm 
Furious Typer

Joined: Tue Oct 28, 2008 4:53 pm
Posts: 166
I had the same problem, but the simple solution is not to use it, the reason is, scripts that record information (unless recorded on a notecard) do not save their previous state if the object containing such a script is taken, then rezzed, mainly because when the object is rezzed, the script is re-compiled, thus re initializing the variables and losing the data they contain.

Sorry for the disappointment, but the only way Builders Buddy is going to work, is if the recorded information is stored on a notecard in the objects inventory, be it a linkset or a single prim.

UPDATE........
Tested on windows, the builders buddy script works so, so, but on Linux, it uses the llGetUnixTime() code, which for some reason does not work, and the base script keeps rezzing the previous object, because the llGetUnixTime() comparison to the 'Are we taking to long?' condition, is always more than the 'RezWait' time and therefore will continuiously rezz the last object regardless.

What needs be changed (which I can't at my current knowledge level of LSL), is to replace the 'are we taking too long' condition, and use a sleep time instead, then rez the next in line, sleep a while, then the next, and so on, until all objects have been rezzed, then continue to the move function, this is for 'bulkrez = true', but for 'bulkrez = false', rez, move, sleep, rez, move sleep, and so on, again until all objects have been rezzed, then, it'll work in both windows and Linux.


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Wed May 11, 2011 12:02 pm 
Furious Typer

Joined: Fri Dec 12, 2008 9:47 am
Posts: 258
Ok, i added a Notecard memory to the component script, the base script is unchanged. With this modification the components do not loose their data.

This modification requires the OSSL function osMakeNotecard to be allowed on your region only when storing the position, not needed for rezzing. It will automaticaly write a notecard with the needed data saved in it. I used osMakeNotecard because it would be a nightmare if your would need to do the work manualy if your planing on saving the data for many objects.


{L_CODE}:
///////////////////////////////////////////////////////////////////////////////
// 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
///////////////////////////////////////////////////////////////////////////////

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


////////////////////////////////////////////////////////////////////////////////
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 < 0.0) vDestPos.x = 0.0;
    if(vDestPos.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.x > 768.0) vDestPos.x = 768.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)
    {
        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 == "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;
    }
}

_________________
{L_IMAGE}{L_IMAGE}{L_IMAGE}


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Thu May 12, 2011 1:08 am 
Site Admin

Joined: Sun Nov 28, 2010 5:09 pm
Posts: 408
Thanks Michelle that is a great additiion to a very useful utility. I was not aware that they had converted the Builder Buddy 1.10, and had recently been working on it myself. But this is a great leap forward in making it more stable on Opensim.


Top
 Profile  
 
 Post subject: Re: Builders' Buddy 1.10 for OpenSim
PostPosted: Sat May 14, 2011 5:17 pm 
Site Admin

Joined: Sun Nov 28, 2010 5:09 pm
Posts: 408
Michelle I discovered a bug in the component script and in fact one in the orginal Builder Buddy Component which also was probably causing the problems people were seeing. In this section from the original script on Second Life you will notice the bottom line:
{L_CODE}:
//Make sure our calculated position is within the sim
    if(vDestPos.x < 0.0) vDestPos.x = 0.0;
    if(vDestPos.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;


Basically this is trying to set the limits for where the rezzed object can be placed. The final line is correct for z coordinate, but what follows is a typo the line should read z and not x!

{L_CODE}:
if(vDestPos.z > 4096.0) vDestPos.z = 4096.0;


That is basically saying that you have to rezz or build under 4096 which it true on Second Life.

Now the converted script that was posted here back in 2009 says something different:

{L_CODE}:
//Make sure our calculated position is within the sim
    if(vDestPos.x < 0.0) vDestPos.x = 0.0;
    if(vDestPos.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.x > 768.0) vDestPos.x = 768.0;


It is a redundant declaration. The above sets the limits for the x coordinate at 255.0 then says on the bottom line the limit is 768.0. Not sure where that value came from however. But there is no mention of the z coordiante, and for rezzing skyboxes which is one of the often uses for Builder Buddy, this is necessary. So I have change the bottom line too:

{L_CODE}:
//Make sure our calculated position is within the sim
        if(vDestPos.z > 10000.0) vDestPos.z = 10000.0;


Now the reason I have done this, is opensim will support rezzing up to 10000 meters, and there is no reason I can see for avoiding this. The space is there and with these changes it works just fine. I just would not go above 10000 meters. Imprudence, Hippo and Meerkat all support rezzing to this height.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post a new topicPost a reply Page 1 of 3   [ 22 posts ]
Go to page 1, 2, 3  Next


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
610nm Style by Daniel St. Jules of Gamexe.net