Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Builders' Buddy - Building Positioning/Rotation Tool

Ed Gobo
ed44's alt
Join date: 20 Jun 2006
Posts: 220
03-19-2007 18:49
From: Mason Kingsford
2. When rezzing a build, the objects in the inventory of the base prim get removed. However, if the build doesn't rez right, the objects are gone. Could the objects either stay in the contents or is it possible for them to return to the base prim on clean up? (or is this just pointless?)

I have clients who would rez twice if they could. You then have a building with double the prims! I put this in the basement, having modified the base script not to clean itself and I provide the basement with copy perms so rhey can re-rez after cleaning up. I still get the occasional client who rezzes two basements near each other and the first rezzed house "walks" across to occupy the second house - again doubling the prims.
Mason Kingsford
Registered User
Join date: 12 Nov 2006
Posts: 42
03-19-2007 21:47
From: Sterling Whitcroft
Mason,
Is this happening all the time, or just today?

I suspect from the time when you posted that you were caught in a general failure of inventory to REZ. An hour or so before you posted, problems all over the grid began occuring. As I reply, the problems continue.

Is this still happening?



Interesting. Thanks for this info. I haven't seen it happen this evening, so perhaps this was just a SL glitch.

Now I'm getting a script error when a user who isn't the creator rezzes a build - saying missing item "" - and it floods the error window with this. Not sure what this is from yet. Too tired tonight but I'll continue testing tomorrow...

Ed Gobo - I see your point. Rezzing twice from a single base does seem like it would be a problem.

UPDATE: Still getting the Missing Inventory Item '' Error. This is driving me mad - I can't explain this problem at all. It doesn't happen when I rez as the creator, only if I rez as an owner/end user. To make it even more confusing, it doesn't happen for every element. I've tried to narrow down the reason and at this point, I think it's in the script. The building rezzes fine, just pops up the error about the missing item. Frustrating!
Eazel Allen
EA-design™
Join date: 11 Feb 2007
Posts: 123
giant prims
04-13-2007 09:31
I recently built a log cabin using round logs instead of textured walls each log would have been 3 prims to achieve a 30m log so I tortured the giant long prim to make a single prim 30m log which has saved me well over 50 prims.Anyway I decided to put into a rez package so I could sell and buyers could easily rez and have been trying builders buddy but it wont record the position and rezz`s in the same place everytime .Does anyone know if this is because of the giant prims or just somthing else im doing wrong ?
ArchTx Edo
Mystic/Artist/Architect
Join date: 13 Feb 2005
Posts: 1,993
04-28-2007 12:41
From: Eazel Allen
I recently built a log cabin using round logs instead of textured walls each log would have been 3 prims to achieve a 30m log so I tortured the giant long prim to make a single prim 30m log which has saved me well over 50 prims.Anyway I decided to put into a rez package so I could sell and buyers could easily rez and have been trying builders buddy but it wont record the position and rezz`s in the same place everytime .Does anyone know if this is because of the giant prims or just somthing else im doing wrong ?


I used a giant prim in a build, using BB to install it and had no problems. I assume you missed a step in installing the scripts, recording positions then installing the objects into the base prim.
_____________________

VRchitecture Model Homes at http://slurl.com/secondlife/Shona/60/220/30
http://www.slexchange.com/modules.php?name=Marketplace&MerchantID=2240
http://shop.onrez.com/Archtx_Edo
ArchTx Edo
Mystic/Artist/Architect
Join date: 13 Feb 2005
Posts: 1,993
04-28-2007 12:43
Anyone else notice an increase in the frequency of prims sticking in place when rezzed since the last update?
_____________________

VRchitecture Model Homes at http://slurl.com/secondlife/Shona/60/220/30
http://www.slexchange.com/modules.php?name=Marketplace&MerchantID=2240
http://shop.onrez.com/Archtx_Edo
Mason Kingsford
Registered User
Join date: 12 Nov 2006
Posts: 42
04-29-2007 12:54
From: ArchTx Edo
Anyone else notice an increase in the frequency of prims sticking in place when rezzed since the last update?


Yes. I've noticed this. It's like the chat to tell the object where to move to fails, or the script times out before it receives the command. I've noticed my chats in general have been lagging quite a bit.

The other problem that I have now with BB is that when a client rezzes the base object, and then finally clicks it and chooses build, it does NOTHING. Then, if they click it again and choose build, it works. So, there is something wrong there. I guess it could be a time out issue, but I'm not sure.

Either way, it's frustrating to see a client have to deal with these issues when trying to rez something. But hey, this script is free, so I can't really complain. I guess I might have to lay down the cash for one of the commercial rezzers OR try to fix this script or write my own (heaven forbid).
Newfie Pendragon
Crusty and proud of it
Join date: 19 Dec 2003
Posts: 1,025
04-29-2007 15:41
In order to minimize the impact on the servers, the script was using a 10-second shutoff for the listener. It's looking though like the servers are lagged enough all on their own, and causing more problems for the script itself.

I've adjusted the listener timout to 30 seconds, which should stand up against most server lag. Just in case though, I've added a new variable in the script (named "fListenTime";) which can be tweaked if anyone wishes a longer listener time. Hopefully this will help with the deafness problems the script has been experiencing.

The updated scripts are pending release in the Scripting Library forum; once they're viewable I'll post the link here. In the meantime, just IM me if you'd like a copy of the updated scripts right away.


- Newfie
_____________________
Mason Kingsford
Registered User
Join date: 12 Nov 2006
Posts: 42
04-29-2007 17:38
I just want to thank Newfie here in the forum. He was cool enough to IM me in world to send me updated scripts. That's above and beyond cool. Thanks again Newfie, I look forward to playing with the updates!
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
05-11-2007 11:20
just used it to repack my first house, awsom script! :P
Newfie Pendragon
Crusty and proud of it
Join date: 19 Dec 2003
Posts: 1,025
06-30-2007 18:30
Hi all,

I've released another version of BB scripts. There's a whole bunch of little changes, too numerous to count (that, and I've forgotten some of them), but here's the core changes:

* Updated to use LLRegionSay(). YES, that means NO MORE 96m LIMIT!
* The way the script rezzed the pieces is changed, and added a timer to catch any lost due to lag/gray goo fence. My own testing seems to hint it's a touch faster too.
* The timer has been reworked to be always on, rather than switching on/off as needed. Was getting too complex, and wasn't always working as intended. Works fine now.
* Added a check to ensure component pieces always stay within sim edges.


Scripts will be on this board once they've passed moderation. In the meantime, if you'd like a copy, just IM me and I'll send them along!


- Newfie



PS: I've noticed the posts (and had at least one IM) about the buyers having a 'clean' option. Please let me know if you think this will be generally a good idea, in which case I'll add it to the next release - Newfie
_____________________
Justkickzazz Taurog
Registered User
Join date: 17 Jun 2007
Posts: 4
Deleting posts or editing them later on
07-06-2007 08:45
From: Jesse Barnett
Ah I am laughing pretty hard. Came in and deleted it all. Been awhile since I had posted this bit of code and looking back it is pretty nasty. Of course I can't imagine looking back 6 months from now and reading the scripts I am creating today also.

:-) But it is amusing!!!!!


I know how annoying looking at one's old posts sometimes is after having 'moved' to higher levels aka 'upgrading brain to V 2.0beta' but DELETING them is unfortunately the wrong approach imho.
The post that appear obsolete to the original poster are far from thus for others, especially beginners.
Very often the questions or erroneous paths one has or wanders on are similar or very closely related to problems other beginners may have and also are an ESSENTIAL part of the thread. Some answers become hard to understand or to follow if you do not know the question that triggered them. Leaving them intact in the thread allows me and other users to understand and learn the same way that you did Jesse.

So please, as embarrassing as it may appear to you (in this case you refers to all posters) when reading posts, DO NOT EDIT OR DELETE THEM (apart from typos :p). Instead get a chuckle out of them and be proud about your advances in coding.



One thing I found problematic with BB in some circumstances is the quite large space it needs when positioning the objects. This becomes an issue when the plot you want to rez the building on is quite small and your 'dear neighbors' have set the permissions on their land to nil...meaning won't allow anything on it. In these cases rezzing the building fails completely.
Looking at some houses I acquired earlier in my SL life (what a waste of L$) that are using feux-rez showed me that it doesn't need as much space as BB.

Maybe someone can comment on that one :)
Best regards

J. T.
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
07-08-2007 17:24
The "rezzing in a restricted space" may be a problem that needs to be solved. One way would be to have a rezzing loop in which the rezzed object informs the rezzor that it has got to its final position. The rezzor's rezzing loop might wait until each object informs it that it has been positioned and then rez the next object, or it might time out and rez the same object at a different location, repeating this a couple of times if necessary. This would require the use of states (not necessarily lsl states) and a timer.

I will continue to use llShout only because I can then rez different houses at 400 M up without the houses standing at ground level starting their travel up (responding to the wrong rezzor)! Maybe this should be configurable.
Corwin Carillon
Registered User
Join date: 26 Jun 2006
Posts: 5
Builders Buddy - Absolute position on sim
07-31-2007 16:01
Has anyone added the option or amended builder's buddy to record the absolute position on the sim, rather than relative to the base? And if so, has or could it be shared? Thanks.
Destiny Niles
Registered User
Join date: 23 Aug 2006
Posts: 949
08-01-2007 08:33
From: Corwin Carillon
Has anyone added the option or amended builder's buddy to record the absolute position on the sim, rather than relative to the base? And if so, has or could it be shared? Thanks.


One way to do it is to change the component script to elimate the relational calulations (4 lines).
CODE

if( sCmd == "RECORD" )
{
sText = other_words(sText, " ");
list lParams = llParseString2List(sText, [ "|" ], []);
vector vBase = (vector)llList2String(lParams, 0);
rotation rBase = (rotation)llList2String(lParams, 1);

--> vOffset = llGetPos(); // remove - vBase;
--> rRotation = llGetRot(); // remove / rBase;
llOwnerSay("Recorded position.");
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sCmd == "MOVE" )
{
//Calculate our destination position
sText = other_words(sText, " ");
list lParams = llParseString2List(sText, [ "|" ], []);
vector vBase = (vector)llList2String(lParams, 0);
rotation rBase = (rotation)llList2String(lParams, 1);

//Calculate our destination position
--> vector vDestPos = vOffset; //remove * rBase) + vBase;
--> rotation rDestRot = rRotation; //remove * rBase;
Huney Jewell
Registered User
Join date: 11 Jul 2007
Posts: 7
Version 2.0 of scripts
08-28-2007 22:35
This is my humble contribution to the topic:
Version 2.0 of Base Script

Also published in LSL Wiki: (http://wiki.secondlife.com/wiki/Builders_Buddy

Read script history for explanation of changes


///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 2.0 (Base Script)
// by Newfie Pendragon, March 2006
//
// This script is distributed with permission that it may be used in
// any way, or may be further modified/included in resale items.
// HOWEVER, if this script is used as part of a for-sale product,
// it is required that appropriate credit be given to Newfie for
// the script (or portions used in derivatives). That's a fair price
// in exchange for unlimited use of this script, dontcha think?
//
// SL Forum thread and new versions found here:
// /54/2b/96792/1.html
///////////////////////////////////////////////////////////////////////////////
//
// 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
//
///////////////////////////////////////////////////////////////////////////////
//
// History
//
// v1.0 - 20060328 - Newfie Pendragon
// - Original Version
// v1.1 - 20060331 - Kalidor Lazarno
// - Added a Dialog Engine to the base script
// v1.5 - 20060612 - Androclese Antonelli
// - Added a random number generator to the dialog engine to elimintate
// problems with multiple BB boxes cross-talking
// - Added a timer to the listen command to put it asleep after 10sec.
// - Added a Menu Description
// - Added n "creator" flag so the owner could use the same object with full
// menu options and only a single flag change
// - Added an "ingroup" flag to enable/disable the same group use function
// - Non-Admin usage cleans the inventory items as they spawn
// v1.6 - 20060624 - Newfie Pendragon
// - Added active repositioning (building moves as the base piece moves)
// - Added "Reset" Option to unlink parts from base temporarily
// - Modified creator flag to automatically set based if owner is creator
// - Minor changes to improve code readability (for those learning LSL)
// v1.8 - 20070429 - Newfie Pendragon
// - Added a variable to allow a user to tweak how long a listener is open,
// and changed the default to 30 seconds.
// v1.9 - 20070630 - Newfie Pendragon
// - Changed to use llRegionSay - no more 96m max distance (same sim)
// - Changed rez sequence to be less affected by lag/gray goo fence
// - Timer always on, less code/more reliable
// v2.0 - 20070829 - Huney Jewell
// - Added configurable constant to determine, which Menu Options will be displayed
// - Menu Option 'Clean' now also deletes the prim which contains this script
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Configurable Settings


// 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 PRIMCHAN = -19730611; // Channel used by Base Prim to talk to Component Prims;
// ***THIS MUST MATCH IN BOTH SCRIPTS!***

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

//Specify which Menu Options will be displayed
//FALSE will restrict full options to creator
//TRUE will offer full options to anyone
integer fullOptions = FALSE;


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

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

integer MENU_CHANNEL;
integer MENU_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;
//integer bTimerOn = FALSE;

//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 ( llGetCreator() != llGetOwner() )
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, iRezIndex));
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
default {
///////////////////////////////////////////////////////////////////////////////
changed(integer change) {
if(change & CHANGED_OWNER)
llResetScript();
}

///////////////////////////////////////////////////////////////////////////////
state_entry () {
//Use which menu?
if ( llGetCreator() == llGetOwner() || fullOptions) {
//Display all options
optionlist = [optPos, optClean, optDone, optRecord, optReset, optBuild];
title = optRecord + descRecord;
title += optReset + descReset;
title += optBuild + descBuild;
title += optPos + descPos;
title += optClean + descClean;
title += optDone + descDone;

} else {
//Display limited options
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));
MENU_HANDLE = llListen(MENU_CHANNEL,"","","";);
llDialog(agent, title, optionlist, MENU_CHANNEL);
//timer_on();
}
}

///////////////////////////////////////////////////////////////////////////////
listen(integer channel, string name, key id, string message) {
if ( message == optRecord ) {
llOwnerSay("Recording positions...";);
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...";);
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";);
llDie();
return;
}
if ( message == optDone ) {
llRegionSay(PRIMCHAN, "DONE";);
if(chatty) llOwnerSay("Removing Builder's Buddy scripts.";);
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();

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



Version 1.9 of Component Pieces


///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.9 (Component Pieces)
// by Newfie Pendragon, March 2006
//
// This script is distributed with permission that it may be used in
// any way, or may be further modified/included in resale items.
// HOWEVER, if this script is used as part of a for-sale product,
// it is required that appropriate credit be given to Newfie for
// the script (or portions used in derivatives). That's a fair price
// in exchange for unlimited use of this script, dontcha think?
//
// SL Forum thread and new versions found here:
// /54/2b/96792/1.html
///////////////////////////////////////////////////////////////////////////////
// INSTRUCTIONS
// This is the *Component Piece* half of the Builders' Buddy system.
// Drop it into each 'piece' of the building. Drop the Base Prim Script
// into the prim that will be the container/box that will be used to
// store the building once completed. It can be in each individual
// prim, but if you link as much as possible (and put the script in the link
// set), it'll be much more neighbourly and less strain on the sim.
//
// 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
//
///////////////////////////////////////////////////////////////////////////////
// History
//
// v1.0 - 20060328 - Newfie Pendragon - Original Version
// v1.5 - 20060612 - Androclese Antonelli
// - (See base script for details)
// v1.6 - 20060624 - Newfie Pendragon
// - Added active repositioning (pieces move as the base piece moves)
// - Pieces use WarpPos technique to instantanetly move large distances
// - Pieces no longer move until the the "Record" option has been used
// at least once
// - Pieces will not move if base is not same owner as the pieces
// - Pieces no longer 'bounce' when hitting the ground
// v1.7 - 20060821 - Correction for non-zero rotation (thanks Ed44 Gupta!)
// v1.9 - 20070630 - Added check to keep within sim edges
///////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
float fTimerInterval = 0.25; // Time in seconds between movement 'ticks'
integer PRIMCHAN = -19730611; // 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 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
// the 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);
}


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
default
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
//Open up the listener
llListen(PRIMCHAN, "", NULL_KEY, "";);
}

//////////////////////////////////////////////////////////////////////////////////////////
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" )
{
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;
bRecorded = TRUE;
llOwnerSay("Recorded position.";);
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sCmd == "MOVE" )
{
//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
sText = other_words(sText, " ";);
list lParams = llParseString2List(sText, [ "|" ], []);
vector vBase = (vector)llList2String(lParams, 0);
rotation rBase = (rotation)llList2String(lParams, 1);

//Calculate our destination position
vDestPos = (vOffset * rBase) + vBase;
rDestRot = rRotation * rBase;

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

//////////////////////////////////////////////////////////////////////////////////////////
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();
bNeedMove = FALSE;
}
return;
}
}

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

Have fun,

greetz Huney
Min Fairweather
Registered User
Join date: 21 Feb 2007
Posts: 202
Shortcut ;)
09-14-2007 03:21
Thanks to everyone who's contributed to these brilliant scripts!

I've created a folder in-world containing the latest versions of these scripts (Base 2.0 and Component 1.91) and it's taken me a little while to read all the posts and put this thing together. Therefore, if you're looking for SL versions of these scripts in a handy folder please send me an IM and I'll send you a copy.
Chance Unknown
Registered User
Join date: 17 Feb 2006
Posts: 18
llDie() in the cleanup routine is very inconvenient
09-26-2007 23:42
When packaging a large build (a complete sim for instance), it is typical to use the following process to get each prim into the package.

1. insert component script to a few objects
2. record positions
3. take the objects into inventory
4. transfer the objects from inventory into the base object
5. rez from base object all contents
6. verify contents are in correct places
7. clean the rez prims (this is where clean up of the base is very inconvenient)
8. repeat the process again until the complete build is packaged

I recommend removing the llDie() from the following code fragment within the base script.. this occurrance is around line 248...

if ( message == optClean ) {
llRegionSay(PRIMCHAN, "CLEAN";);
// llDie();
return;
}
Andromeda Quonset
Registered User
Join date: 20 May 2006
Posts: 46
My builder's buddy contribution, version 2.1 base, 2.0 component
10-14-2007 03:00
I've been wanting 2 different options in Builder's Buddy for a long time.

1. An ability to change channels.

2. A way to integrate with Cadroe Murphy's ShapeGen product.

For instance, someone wants 4 copies of a building in 1 sim. I can now rez the base prim with the correct build, build the structure, change the channel on the base prim, and rez another without interference.

For ShapeGen, it can create a lot of prims I want to save, using Builder's Buddy, later as part of a huge build. I have In the very least, it is helpful to have Shapegen include the Component script in every prim.

I ran into some difficulties in combining these functions, but I finally have a working unit. The difficulty is in using the on_rez integer for 2 functions. I am using the 6 most-significant digits for a channnel number, and the 4 least-significant to auto-name all the prims created by ShapeGen.

The Builder's Buddy base prim has a new button called "channel". it appears only in the full dialog menu. The full dialog menu also tells you what channel it is currently set for. pressing the channel button brings up a nested dialog menu which you use to key-in the desired channel number. Leading zero-s are required. The final channnel will have the least-significant 4 digits hard-coded to 0000. The default channel is -0019730000. There is no checking for out-of-valid-integer-range, or number of digits keyed-in. I am assuming (dangerous) that it is operated by someone who understands :) Pressing the enter-button on the dialog menu will finish input.


I also commented-out the llDie() that is a part of the optClean function.
Andromeda Quonset
Registered User
Join date: 20 May 2006
Posts: 46
Code as described in previous message....
10-14-2007 03:02
CODE

///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 2.1 (Base Script)
// revisions to 2.0 by Andromeda Quonset, October 2007
///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 2.0 (Base Script)
// by Newfie Pendragon, March 2006
//
// This script is distributed with permission that it may be used in
// any way, or may be further modified/included in resale items.
// HOWEVER, if this script is used as part of a for-sale product,
// it is required that appropriate credit be given to Newfie for
// the script (or portions used in derivatives). That's a fair price
// in exchange for unlimited use of this script, dontcha think?
//
// SL Forum thread and new versions found here:
// /54/2b/96792/1.html
///////////////////////////////////////////////////////////////////////////////
//
// 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
//
///////////////////////////////////////////////////////////////////////////////
//
// History
//
// v1.0 - 20060328 - Newfie Pendragon
// - Original Version
// v1.1 - 20060331 - Kalidor Lazarno
// - Added a Dialog Engine to the base script
// v1.5 - 20060612 - Androclese Antonelli
// - Added a random number generator to the dialog engine to elimintate
// problems with multiple BB boxes cross-talking
// - Added a timer to the listen command to put it asleep after 10sec.
// - Added a Menu Description
// - Added n "creator" flag so the owner could use the same object with full
// menu options and only a single flag change
// - Added an "ingroup" flag to enable/disable the same group use function
// - Non-Admin usage cleans the inventory items as they spawn
// v1.6 - 20060624 - Newfie Pendragon
// - Added active repositioning (building moves as the base piece moves)
// - Added "Reset" Option to unlink parts from base temporarily
// - Modified creator flag to automatically set based if owner is creator
// - Minor changes to improve code readability (for those learning LSL)
// v1.8 - 20070429 - Newfie Pendragon
// - Added a variable to allow a user to tweak how long a listener is open,
// and changed the default to 30 seconds.
// v1.9 - 20070630 - Newfie Pendragon
// - Changed to use llRegionSay - no more 96m max distance (same sim)
// - Changed rez sequence to be less affected by lag/gray goo fence
// - Timer always on, less code/more reliable
// v2.0 - 20070829 - Huney Jewell
// - Added configurable constant to determine, which Menu Options will be displayed
// - Menu Option 'Clean' now also deletes the prim which contains this script
// v2.1 - 20071006 - Andromeda Quonset
// - Added Channel command to dialog box
// - Added second dialog box for inputting channel
// - Added changing to default channel when invoking RECORD function
// - disabled: Menu Option 'Clean' now also deletes the prim which contains this script
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Configurable Settings


// 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 = -0019730000; //original channel used was -0019730611
integer PRIMCHAN = DefaultPRIMCHAN; // Channel used by Base Prim to talk to Component Prims;
// ***THIS MUST MATCH IN BOTH SCRIPTS!***

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

//Specify which Menu Options will be displayed
//FALSE will restrict full options to creator
//TRUE will offer full options to anyone
integer fullOptions = 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: ";


InvertSign()
{
if(Sign == "+")
Sign = "-";
else
Sign = "+";
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////////
// 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;
//integer bTimerOn = FALSE;

//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 ( llGetCreator() != llGetOwner() )
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, iRezIndex));
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
default
{
///////////////////////////////////////////////////////////////////////////////
changed(integer change)
{
if(change & CHANGED_OWNER)
llResetScript();
}

///////////////////////////////////////////////////////////////////////////////
state_entry ()
{
//Use which menu?
if ( llGetCreator() == 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
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 ( llGetCreator() == 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)
{
if( channel == MENU_CHANNEL ) //Process input from original menu
{
if ( message == optRecord )
{
PRIMCHAN = DefaultPRIMCHAN;
llOwnerSay("Recording positions...");
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...");
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");
//llDie(); //this removes the base prim.
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( message == "0" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "1" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "2" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "3" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "4" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "5" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "6" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "7" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "8" )
{
Input += message;
SignInput = Sign + Input;
llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
}
else if( message == "9" )
{
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
{
//note channel range is +-aaaaaabbbb where b is always 0
Input += "000000"; //ensures minimum string length of 6 digits
Input = llGetSubString(Input,0,5); //get just first 6 digits
Input += "0000"; //force last 4 digits to 0
if(Sign == "-")
{
SignInput = Sign + Input;
}
else
{
SignInput = Input;
}
PRIMCHAN = (integer)SignInput;
}
}
else
{
llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
}

}
}


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

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


///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 2.0 (Component Pieces)
// by Andromeda Quonset, October 2007
///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.9 (Component Pieces)
// by Newfie Pendragon, March 2006
//
// This script is distributed with permission that it may be used in
// any way, or may be further modified/included in resale items.
// HOWEVER, if this script is used as part of a for-sale product,
// it is required that appropriate credit be given to Newfie for
// the script (or portions used in derivatives). That's a fair price
// in exchange for unlimited use of this script, dontcha think?
//
// SL Forum thread and new versions found here:
// /54/2b/96792/1.html
///////////////////////////////////////////////////////////////////////////////
// INSTRUCTIONS
// This is the *Component Piece* half of the Builders' Buddy system.
// Drop it into each 'piece' of the building. Drop the Base Prim Script
// into the prim that will be the container/box that will be used to
// store the building once completed. It can be in each individual
// prim, but if you link as much as possible (and put the script in the link
// set), it'll be much more neighbourly and less strain on the sim.
//
// 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
//
///////////////////////////////////////////////////////////////////////////////
// History
//
// v1.0 - 20060328 - Newfie Pendragon - Original Version
// v1.5 - 20060612 - Androclese Antonelli
// - (See base script for details)
// v1.6 - 20060624 - Newfie Pendragon
// - Added active repositioning (pieces move as the base piece moves)
// - Pieces use WarpPos technique to instantanetly move large distances
// - Pieces no longer move until the the "Record" option has been used
// at least once
// - Pieces will not move if base is not same owner as the pieces
// - Pieces no longer 'bounce' when hitting the ground
// v1.7 - 20060821 - Correction for non-zero rotation (thanks Ed44 Gupta!)
// v1.9 - 20070630 - Added check to keep within sim edges
// v2.0 - 20071006 - Andromeda Quonset - Changed channel assignment on-rez, defualt channel, so ends with 0000
///////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
float fTimerInterval = 0.25; // Time in seconds between movement 'ticks'
integer DefaultChannel = -19730000; //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 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
// the 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);
}


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
default
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
//Open up the listener
llListen(PRIMCHAN, "", NULL_KEY, "");
}

//////////////////////////////////////////////////////////////////////////////////////////
on_rez(integer iStart)
{
//Set the channel to what's specified
if( iStart != 0 )
{ //new assign channel number, forcing last 4 digits to 0000
string Chan = (string)iStart; //cast to string
integer ChanSize = llStringLength(Chan); //determine number of digits (chars)
string CalcChan = llGetSubString(Chan,0,ChanSize-5); //remove last 4 digits
CalcChan += "0000"; //append 0000
PRIMCHAN = (integer)CalcChan; //assign channel number

//PRIMCHAN = iStart; //old assign channel number
state reset_listeners;
}
}

//////////////////////////////////////////////////////////////////////////////////////////
listen(integer iChan, string sName, key kID, string sText)
{
string sCmd = llToUpper(first_word(sText, " "));

if( sCmd == "RECORD" )
{
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;
bRecorded = TRUE;
llOwnerSay("Recorded position.");
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sCmd == "MOVE" )
{
//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
sText = other_words(sText, " ");
list lParams = llParseString2List(sText, [ "|" ], []);
vector vBase = (vector)llList2String(lParams, 0);
rotation rBase = (rotation)llList2String(lParams, 1);

//Calculate our destination position
vDestPos = (vOffset * rBase) + vBase;
rDestRot = rRotation * rBase;

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

//////////////////////////////////////////////////////////////////////////////////////////
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();
bNeedMove = FALSE;
}
return;
}
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
state reset_listeners
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
state default;
}
}
Newfie Pendragon
Crusty and proud of it
Join date: 19 Dec 2003
Posts: 1,025
11-05-2007 18:02
Hi all,

I want to thank an unnamed someone for letting me know that there is apparently some confusion among people as to which versions of the BB scripts are available, and what features are involved.

First of all, the official (from me) word:

THE CURRENT VERSION OF THE BB SCRIPTS ARE
- BASE: *****1.9*****
- COMPONENT: *****1.9*****



Now that that's out of the way, I'll elaborate. I'm more than happy to accept changes to the BB scripts; if anything, I encourage it. HOWEVER - if you have changes to make to my scripts, please submit them directly to me so that I can merge them with other changes in works. The version that is on these forums (or the dozen other places in teh intarwebs) is NOT the official version; that version is sitting in my inventory. If you post the changes here, your version will run the very real and likely risk of being outright replaced by an 'official' upgrade.

I, as much as anyone, knows the amount of time and effort required in providing ongoing support for a popular script, especially one that is open-source and not making me a penny. To that end, if you want to help, then great, send me your proposed additions and I'll be glad to give them consideration.

In the meantime, please note that the most current version is 1.9. All higher-numbered revisions I will take a look at over the next few days and see what can be done with them.


- Newfie Pendragon


PS: Next release will be 1.10 - following the SL versioning style. There will not be a version 2.0 if/until BB is rewritten from scratch - and that's not anytime soon! :)
Soen Eber
Registered User
Join date: 3 Aug 2006
Posts: 428
11-05-2007 19:04
I have a mod version of Adromida's source I can kick your way, allowing the use of megaprims in the base (replaces llCreatorKey check [which fails] with a check for a creator key defined variable). I did it so my base prim could be the actual foundation with a texture overlay showing the top view of the house. I thought it'd be easier than having someone fiddle with a box and the entire house.

Also, I have a "set height" script like you see in some houses that I was going to eventually work into the script ... perhaps I should just send the script to you and have you work it in, instead?

Q: your script uses llRegionSay for inter-object communication, right? If its llShout then the "set height" script won't work....
Aaron23 DeCuir
Registered User
Join date: 21 Sep 2007
Posts: 12
touch is grey'd out
12-06-2007 10:42
Sorry to pollute the forum with newbie bb questions... Hopefully my learning curve will be fairly quick.

I have version 1.9 of base and client. And find these instructions...
// 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

I create a base object (a box), drop the base script in as advised.
I create a component object nearby (a sphere), drop the component script in as advised
drop out of edit mode
touch the base object, expecting a menu of some sort - and get nothing
looking more closely, the 'touch' option is greyed in the rt-click menu.

I'm missing something basic, I know. Could someone enlighten me?

aaron
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-06-2007 12:37
From: Aaron23 DeCuir
Sorry to pollute the forum with newbie bb questions... Hopefully my learning curve will be fairly quick.

I have version 1.9 of base and client. And find these instructions...
// 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

I create a base object (a box), drop the base script in as advised.
I create a component object nearby (a sphere), drop the component script in as advised
drop out of edit mode
touch the base object, expecting a menu of some sort - and get nothing
looking more closely, the 'touch' option is greyed in the rt-click menu.

I'm missing something basic, I know. Could someone enlighten me?

aaron

are you on land that restricts scripts? are the items you are using to test with ones you created yourself?

you should have recieved a menu assuming both those are true
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Vent Sinatra
Registered User
Join date: 4 Jan 2007
Posts: 71
12-06-2007 16:19
Argh, I just notice this thread now. I have build something similar to move linked prim structures. It is similar but uses llLinkedMessages instead of chat communication. Another useful addition is the use of multiple bases.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
12-06-2007 16:49
From: Vent Sinatra
Argh, I just notice this thread now. I have build something similar to move linked prim structures. It is similar but uses llLinkedMessages instead of chat communication. Another useful addition is the use of multiple bases.

Well hopefully you were aware of MultiMove also?:

/54/5c/219078/1.html
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
1 2 3 4 5 6 7