Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Builders' Buddy - Building Positioning/Rotation Tool

Newfie Pendragon
Crusty and proud of it
Join date: 19 Dec 2003
Posts: 1,025
03-28-2006 19:11
****************************************
** The script in this post is *very* out of date. Please
** fetch the latest version at the SL Wiki:
** http://wiki.secondlife.com/wiki/Builders_Buddy
****************************************


On occasion I get requests to do some architectural builds. Unless they're built in-place, it can be a big pain to package it up, put it out, position/rotate such a large build. Throw on top of that the problem with pieces 'drifting' while being rotated, and it can be quite a hair-pulling experience.

So...I wrote the below scripts, which I'm calling the Builders' Buddy scripts. Drop the Base script into the packaging box, and the Component script into each piece of the building. Issue the /12345 record command, and the pieces remember their position/rotation in relationship to the Base. From then on, just move/rotate the Base, and /12345 move to have the building follow along.

First, the Base Script:
CODE

// Builders' Buddy 1.0 (Base Prim)
//
// 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?


//INSTRUCTIONS
//(These instructions use channel 1234 in the examples, but can be
// changed further down in the code to whatever channel you wish.)
//
// This is the *Base Prim* half of the Builders' Buddy system. Drop
// it into the prim that will be the container/box that will be used
// to store the building once completed. Drop the *Component* scripts
// into each 'piece' of the building.
//
// QUICK USE:
// - Drop this script in the Base.
// - Drop the "Component" Script in each building part.
// - Type: /12345 RECORD
// - Take all building parts into inventory
// - Drag building parts from inventory into Base Prim
// - Type /12345 BUILD
//
// OTHER COMMANDS
// - To reposition, move/rotate Base Prim Type: /12345 MOVE
// - To lock into position (removes scripts) Type: /12345 DONE
// - To delete building pieces: /12345 CLEAN


//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
integer CHAN = 12345; //Channel used to talk to Base Prim; change if you want
integer PRIMCHAN = 12346; //Channel used by Base Prim to talk to Component Prims;
// This must match in both scripts


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
default
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
llListen(CHAN, "", llGetOwner(), "");
}

//////////////////////////////////////////////////////////////////////////////////////////
listen(integer iChan, string sName, key kID, string sText)
{
//////////////////////////////////////////////////////////////////////////////////////////
sText = llToUpper(sText);
if( sText == "RECORD" )
{
llOwnerSay("Recording positions...");
llShout(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sText == "BUILD" )
{
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
integer i;
integer iCount = llGetInventoryNumber(INVENTORY_OBJECT);

//Loop through backwards (safety precaution in case of inventory change)
llOwnerSay("Rezzing build pieces...");
for( i = iCount - 1; i >= 0; i-- )
{
llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), vThisPos, ZERO_VECTOR, rThisRot, PRIMCHAN);
}

llOwnerSay("Positioning");
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sText == "MOVE" )
{
llOwnerSay("Positioning");
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sText == "CLEAN" )
{
llShout(PRIMCHAN, "CLEAN");
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sText == "DONE" )
{
llShout(PRIMCHAN, "DONE");
//llDie();
llOwnerSay("Removing mover scripts.");
return;
}
}
}


The Component Script:
CODE

// Builders' Buddy 1.0 (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?


//INSTRUCTIONS
//(These instructions use channel 1234 in the examples, but can be
// changed further down in the code to whatever channel you wish.)
//
// 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.
// - Type: /12345 RECORD
// - Take all building parts into inventory
// - Drag building parts from inventory into Base Prim
// - Type /12345 BUILD
//
// OTHER COMMANDS
// - To reposition, move/rotate Base Prim Type: /12345 MOVE
// - To lock into position (removes scripts) Type: /12345 DONE
// - To delete building pieces: /12345 CLEAN

//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
integer PRIMCHAN = 12346; //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;


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


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
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;
rRotation = llGetRot() / 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 * rBase) + vBase;
rotation rDestRot = rRotation * rBase;

llOwnerSay("Pos: " + (string)vDestPos + ", Rot: " + (string)rDestRot);
integer i = 0;
vector vLastPos = ZERO_VECTOR;
while( (i < 25) && (llGetPos() != vDestPos) )
{
//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)
llSetPos(llGetPos() + <0, 0, 10.0>);
} else {
//Record our spot for 'stuck' detection
vLastPos = llGetPos();
}
}
i++;

//Try to move to destination
llSetPos(vDestPos);
llSleep(0.1);
}

//Set rotation
llSetRot(rDestRot);
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sCmd == "DONE" )
{
//We are done, remove script
llRemoveInventory(llGetScriptName());
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( sCmd == "CLEAN" )
{
//Clean up
llDie();
return;
}
}
}

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


Finally, a little script that shapes your prim into an arrow (good for orienting front/back/etc) - not needed, but might be handy
CODE

default
{
state_entry()
{
llSetPrimitiveParams([
PRIM_TYPE, PRIM_TYPE_SPHERE, PRIM_HOLE_DEFAULT, <0.45, 0.55, 0.0>, 0.0, ZERO_VECTOR, <0.35, 0.65, 0.0> ]);
llSetRot(ZERO_ROTATION);
llRemoveInventory(llGetScriptName());
}
}


All feedback and suggestions will be greatly appreciated.

- Newfie Pendragon
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Original Thread
03-28-2006 20:03
/15/ff/96777/1.html
_____________________
i've got nothing. ;)
Kalidor Lazarno
Just here to have fun!!
Join date: 1 Feb 2006
Posts: 7
Dialog Menu System
03-31-2006 16:29
Threw this together it is a dialog menu for Builder's Buddy, thought this nice script could use a menu ...

CODE


//Based on Builder's Buddy by Newfie Pendragon, March 2006
//Dialog Menu added by Kalidor Lazarno, March 2006
//you must still use the component scripts from the original post.

// 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 MOVE
// - To lock into position (removes scripts) choose DONE
// - To delete building pieces: choose CLEAN

string name1 = "RECORD"; //Name each option-these names will be your button names.
string name2 = "BUILD";
string name3 = "MOVE";
string name4 = "CLEAN";
string name5 = "DONE";

integer CHAN = 12345; //Channel used to talk to Base Prim; change if you want
integer PRIMCHAN = 12346; //Channel used by Base Prim to talk to Component Prims;
// This must match in both scripts



integer group;

key id;

list optionlist = [];

default
{
state_entry()
{
llListen(12345, "", NULL_KEY, "");
optionlist = [name1, name2, name3,name4, name5];
}

touch_start(integer total_number)
{
group = llDetectedGroup(0);
if(group == TRUE)
{
id = llDetectedKey(0);
llDialog(id, "Pick your poision", optionlist, 12345);
}
}
listen(integer channel, string name, key id, string message)
{
if(message == name1)
{
llOwnerSay("Recording positions...");
llShout(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
return;
}
if(message == name2)
{
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
integer i;
integer iCount = llGetInventoryNumber(INVENTORY_OBJECT);

//Loop through backwards (safety precaution in case of inventory change)
llOwnerSay("Rezzing build pieces...");
for( i = iCount - 1; i >= 0; i-- )
{
llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), vThisPos, ZERO_VECTOR, rThisRot, PRIMCHAN);
}

llOwnerSay("Positioning");
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if(message == name3)
{
llOwnerSay("Positioning");
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if(message == name4)
{
llShout(PRIMCHAN, "CLEAN");
return;
}
if(message == name5)
{
llShout(PRIMCHAN, "DONE");
//llDie();
llOwnerSay("Removing mover scripts.");
return;
}

}
}
Maximilian Milosz
Registered User
Join date: 14 Oct 2005
Posts: 128
04-06-2006 09:53
Awesome work, thanks a bunch!!!
ArchTx Edo
Mystic/Artist/Architect
Join date: 13 Feb 2005
Posts: 1,993
05-18-2006 15:49
Builder's Buddy is a really cool tool!! Thanks Newfie!. Here are a couple of tips on using it (learned the hard way) and a question on how to improve it.

Tips:

1. The base installation box needs to have all rotations set at zero otherwise it the objects it rezzes come out funny.

2. If you use this to package a build for resell, the new owner will not be able to rezz the objects in the base prim unless they first reset the Builder's Buddy script inside. This is because of the <<llListen(CHAN, "", llGetOwner(), "";);>> Get Owner call I believe.

Question: Is there someway I can make this script reset itself when a new owner rezzes the Base installation box?
_____________________

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
Sator Canetti
Frustrated Catgirl
Join date: 20 Sep 2005
Posts: 130
05-18-2006 16:12
CODE
changed(integer change)
{
if (change & CHANGED_OWNER)
{
llResetScript();
}
}
_____________________
"Have gone to commit suicide. Intend to return from grave Friday. Feed cat." -- A memo by Spider Jerusalem in Transmetropolitan

"Some people are like Slinkies; not really good for anything, but they still bring a smile to your face when you push them down a flight of stairs."

If you're reading this signature, I've probably just disagreed with you. Welcome to the club :D
hurly Burleigh
Registered User
Join date: 19 Sep 2005
Posts: 167
Yay At Last
05-19-2006 04:04
Thanks from the bottom of my heart:))))

This script is just what i needed. I have used it several times and it works great. I have discovered the problem with the root prim not being set to 0,0,0 but did not know how to cure it until reading this thread. Now i can box all my buildings.

One tip though, If you have several building with the scripts in make sure to change the listyening channel to something very different in each build or it will cause conflicts.

You are a GOD!!!
Darkhorse Golem
Registered User
Join date: 25 Oct 2005
Posts: 23
Reset script and rotate to zero
05-19-2006 06:27
Thanks for the tip. i had huge trouble until i found the set rotate to zero.

anyway, being new to scripting, where do i put the new owner code please?

DH.
ArchTx Edo
Mystic/Artist/Architect
Join date: 13 Feb 2005
Posts: 1,993
06-03-2006 10:18
From: Sator Canetti
CODE
changed(integer change)
{
if (change & CHANGED_OWNER)
{
llResetScript();
}
}


I am not sure how that is supposed to be incorporated into the script either, but this script to Reset a Script on Rez lookes useful.

/54/45/109801/1.html
_____________________

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
Azreal Rubio
PrimHead
Join date: 29 Jan 2004
Posts: 194
06-03-2006 10:29
From: ArchTx Edo
Question: Is there someway I can make this script reset itself when a new owner rezzes the Base installation box?


To reset the base script why not add this...

CODE

on_rez(integer rez_num)
{
llResetScript();
}



I add it basically to any script I knock out which needs a known start state. to use just stick it at the top level under the default state.
Androclese Antonelli
Org. B-Day: 05/11/04
Join date: 25 Apr 2006
Posts: 96
06-12-2006 14:35
I have gotten a lot of use out of the original script and along the way, I have made a number of changes to it.

I figure it is only fair thing to do is to publish those changes here.

The changes:
  1. I added two menu systems, one for the creator, one for the reseller. The flag is set inside the script, so make sure set it correctly when using this script in a saleable item. Turning creator flag off makes the Build button a one-time rez by removing the inventory items
  2. I added a flag to enable/disable the group use flag. This is only really usefull if you are using this to asselble items you have sold.
  3. Added a Random number generator to the menu system to keep multiple versions of the scripted items from talking to eachother
  4. Added a timer to the dialog menu to close the menu handler after 10 seconds.
  5. As requested, when the spawing object is sold/transfered to a new owner, the base prim script will reset and recognized that new owner.
I found that the best way to make these scripts work is to spawn a single prim and put all the inventory items and the base script in there. As stated above, is the rotation is set to <0, 0, 0> You'll be better off.

I hope you find these changes useful.



CODE

///////////////////////////////////////////////////////////////////////////////
//
// Builder Buddy - Root Prim Script
//
// Coded by: Newfie Pendragon
// Written On: 20060328
//
// This code is open source
//
// SL Forum thread and new versions found here:
// http://forums.secondlife.com/showthread.php?t=96792
//
///////////////////////////////////////////////////////////////////////////////
//
// 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
///////////////////////////////////////////////////////////////////////////////
// User Variables
///////////////////////////////////////////////////////////////////////////////
// Set to TRUE for unlimited inventory spawns and all menu options
// Set to FALSE to a one-time inventory spawn and limited menu options
integer creator = TRUE;

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

//Name each option-these names will be your button names.
string name1 = "Record";
string name2 = "Build";
string name3 = "Position";
string name4 = "Clean";
string name5 = "Done";

//Menu option descriptions
string desc1 = " : Record the position of all parts\n";
string desc2 = " : Spawn inv. items and position them\n";
string desc3 = " : Reposition the parts to a new location\n";
string desc4 = " : De-Rez all pieces\n";
string desc5 = " : Remove all BB scripts and make the parts permanent.\n";

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

///////////////////////////////////////////////////////////////////////////////
// DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
///////////////////////////////////////////////////////////////////////////////
integer MENU_CHANNEL;
integer MENU_HANDLE;
key agent;
key objectowner;
integer group;
string title = "";
list optionlist = [];

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

state_entry () {

if ( creator ) {
optionlist = [name1, name2, name3, name4, name5, " "];
title = name1 + desc1;
title += name2 + desc2;
title += name3 + desc3;
title += name4 + desc4;
title += name5 + desc5;

} else {
optionlist = [name2, name3, name5];
title = name2 + desc2;
title += name3 + desc3;
title += name5 + desc5;
}
}

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 ) ) {
MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
llDialog(agent, title, optionlist, MENU_CHANNEL);
llSetTimerEvent(10.0);
}
}
listen(integer channel, string name, key id, string message) {
if ( message == name1 ) {
llOwnerSay("Recording positions...");
llShout(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
return;
}
if ( message == name2 ) {
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
integer i;
integer iCount = llGetInventoryNumber(INVENTORY_OBJECT);

//Loop through backwards (safety precaution in case of inventory change)
llOwnerSay("Rezzing build pieces...");
for( i = iCount - 1; i >= 0; i-- )
{
llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), vThisPos, ZERO_VECTOR, rThisRot, PRIMCHAN);
if ( creator == FALSE ) {
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, i));
}
}

llOwnerSay("Positioning");
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == name3 ) {
llOwnerSay("Positioning");
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == name4 ) {
llShout(PRIMCHAN, "CLEAN");
return;
}
if ( message == name5 ) {
llShout(PRIMCHAN, "DONE");
//llDie();
llOwnerSay("Removing mover scripts.");
return;
}
}

timer() {
//so the menu timeout and close its listener
llSetTimerEvent(0.0);
llListenRemove(MENU_HANDLE);
}
}
_____________________
The Sculpted Garden

Originally Born 5/11/2004 - New AV, Old Player.

If you leave the game, don't delete your account, just make it 'free'. You'll lose your inventory like I did. *sniff*
Ron Overdrive
Registered User
Join date: 10 Jul 2005
Posts: 1,002
06-19-2006 21:49
great! now all this needs is active repositioning instead of the current passive repositioning.
Androclese Torgeson
I've got nothin'
Join date: 11 May 2004
Posts: 144
06-20-2006 07:11
What do you mean by "active repositioning"?
_____________________
Androclese Torgeson

Real Life, also known as "that big room with the ceiling that is sometimes blue and sometimes black with little lights"

dana Archer
Registered User
Join date: 10 May 2005
Posts: 8
Re Rotation Tool: Syntax error
06-20-2006 09:43
Hi

and a big thankyou to Newfie, Kalidor and Androclese for this wonderful script.

My first and only problem at the moment is i cut n pasted the script from Androclese's post
and pasted it into a new script in SL. I went to save and i got a (144, 71) : ERROR : Syntax error

llRemoveInventory(llGetInventoryName(INVENTORY_OBJ ECT, i));
}


i dont know how to script, so what did i do wrong in the cut/paste and what do i do to fix it...help please


dana
Androclese Torgeson
I've got nothin'
Join date: 11 May 2004
Posts: 144
06-20-2006 10:10
=C

I'll take a look at it when I get to a SL playable computer.
_____________________
Androclese Torgeson

Real Life, also known as "that big room with the ceiling that is sometimes blue and sometimes black with little lights"

Androclese Torgeson
I've got nothin'
Join date: 11 May 2004
Posts: 144
06-20-2006 13:30
From: dana Archer
Hi

and a big thankyou to Newfie, Kalidor and Androclese for this wonderful script.

My first and only problem at the moment is i cut n pasted the script from Androclese's post
and pasted it into a new script in SL. I went to save and i got a (144, 71) : ERROR : Syntax error

llRemoveInventory(llGetInventoryName(INVENTORY_OBJ ECT, i));
}


i dont know how to script, so what did i do wrong in the cut/paste and what do i do to fix it...help please


dana


It's a quirk of the way it was pasted into the editor. I've tried to fix it, but it's not cooperating with me.

Remove the spaces between the "J" and the "E" in "INVENTORY_OBJ ECT" and it will work just fine.
_____________________
Androclese Torgeson

Real Life, also known as "that big room with the ceiling that is sometimes blue and sometimes black with little lights"

Ron Overdrive
Registered User
Join date: 10 Jul 2005
Posts: 1,002
06-20-2006 21:11
From: Androclese Torgeson
What do you mean by "active repositioning"?


Active Repositioning = on the fly position/rotation updates as the package is moved around/rotated instead of having to move, rotate, manually tell it to update position/rotation, and repeat until its in a desired location. Both Rez-Foo & Rez-Faux do active repositioning wich besides the pricetag is what seperates builder-buddy from them.
Androclese Torgeson
I've got nothin'
Join date: 11 May 2004
Posts: 144
06-21-2006 07:14
From: Ron Overdrive
Active Repositioning = on the fly position/rotation updates as the package is moved around/rotated instead of having to move, rotate, manually tell it to update position/rotation, and repeat until its in a desired location. Both Rez-Foo & Rez-Faux do active repositioning wich besides the pricetag is what seperates builder-buddy from them.


My initial thoughts are to set a state through the dialog menu where, while active, it passes through a timed state, constantly updating the coordinates, and then that state can be disabled through the dialog menu if requested.

OK... it should be easy enough to code. I'll start working on it when the servers come back up.
_____________________
Androclese Torgeson

Real Life, also known as "that big room with the ceiling that is sometimes blue and sometimes black with little lights"

Newfie Pendragon
Crusty and proud of it
Join date: 19 Dec 2003
Posts: 1,025
06-21-2006 11:59
Just a quick reply to let everyone know:

I am working on an update to the scripts (using the enhanced versions included in this post, great job folks!), which I am intending on adding the active repositioning and a feature I am still testing out. I hope to be releasing that update here in the next few days.


- Newfie
_____________________
Androclese Torgeson
I've got nothin'
Join date: 11 May 2004
Posts: 144
06-22-2006 06:21
Well in that case, I'll just let Newfie crank out his version. (and then hack it later :D)

BTW Androclese Antonelli == Androclese Torgeson
_____________________
Androclese Torgeson

Real Life, also known as "that big room with the ceiling that is sometimes blue and sometimes black with little lights"

Cid Vilas
Registered User
Join date: 16 May 2006
Posts: 4
07-01-2006 00:39
From: dana Archer

My first and only problem at the moment is i cut n pasted the script from Androclese's post
and pasted it into a new script in SL. I went to save and i got a (144, 71) : ERROR : Syntax error

llRemoveInventory(llGetInventoryName(INVENTORY_OBJ ECT, i));
}
dana


Ok....this is one of my first posts...YAY...anyway. You need to delete the space between OBJ and ECT. The line should look as follows afterwards.


llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, i));

For some reason...it still has the space there....just erase it inside SL
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
Fixed base rotation problem?
07-01-2006 23:29
I had problems with the base rotation not being zero.

I changed this line:
CODE

vOffset = llGetPos() - vBase;


to:

CODE

vOffset = (llGetPos() - vBase) / rBase;


Works for my simples cases.


Now using this so rezzing my house just lays down the basement. After the basement is positioned the operator clicks on the basement to run the base prim which rezzed the house above it. Works well.

Ed
Leon Drinkwater
Registered User
Join date: 29 Jun 2006
Posts: 4
Cut & paste error
07-19-2006 19:03
I cut and pasted this sctipt from the wiki and got the same syntax error. it turned out that a a extra carage return got added to the middle of a varible I deleted it and the code compiled. I still diden't get it to work the first time. I think that was because i was woorking with a very tall treehouse and may have ben out of range near the bottom.
ArchTx Edo
Mystic/Artist/Architect
Join date: 13 Feb 2005
Posts: 1,993
Bouncing, Incorrect Position and Menu with stuck objects
07-26-2006 08:22
I have used Builder's Buddy with great success, its a wonderful tool, but have noticed a few problems I would like to share. I am more a builder then a scripter so my comments may be naive froma scripting standpoint. But I am enjoying learning this stuff and I learn something new each day.

BOUNCING: I have noticed some objects tend to bounce up and down alot during the installation. I realize the bouncing is part of the scripts effort to correctly position the object. Is there anything we can do to decrese the likelyhood that the objects will be difficult to position correctly? Such as making sure the base rotation of the parent prim are zero? I noticed on a recent build that 3 objects on the East side always bounce, while same 3 identical objects on the West side do not bounce. The only differences between these ojbects is those on the East side are rotated 180 from the West side.

INCORRECT POSITION: I have used this in one build where a 2 prim foundation object refused to set to the correct location. it settles into a position a .3 m or so above the rest of the floor. "Move" or repositioning the build slightly does not fix this.

It appears this is because the center of the foundation piece would be below ground, while the top remains above it. When I raise the entire build higher, and give the "MOVE" or resposition command, the foundation pieces all realign correctly. I assume there is something about the vDestPos that does not like putting the object below ground.

MENU: I have begun using the MENU script in the base prim and have found one problem with using it. Regardless of whether I am using the MENU or original base prim script, it is not uncommon for some objects to sick at the base prim location upon the first attempt to rez. "CLEAN" and repeating the "BUILD" command, or using the "MOVE" command usually fixes this. However this can be difficult to do it you are using the MENU in the base prim, because the MENU closes after one use. If the stuck object is larger then the base prim it completely hides the base prim, so you cannot touch it to reactivate the MENU. It would be nice if the MENU would stay open until you close it manually.
_____________________

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
Ron Overdrive
Registered User
Join date: 10 Jul 2005
Posts: 1,002
07-26-2006 18:53
seems like the new script wasn't posted up yet so I'll repost it here.

BuildersBuddy 1.6 - Base
CODE

////////////
// User Variables
///////////////////////////////////////////////////////////////////////////////

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

//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 = " : Spawn 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 make the parts permanent.\n";

//How often (in seconds) to check for change in position when moving
float fMovingRate = 0.25;

//How long to sit still before exiting active mode
float fStoppedTime = 30.0;

//Minimum amount of time (in seconds) between movement updates
float fShoutRate = 0.25;

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

///////////////////////////////////////////////////////////////////////////////
// DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
///////////////////////////////////////////////////////////////////////////////
integer MENU_CHANNEL;
integer MENU_HANDLE;
key agent;
key objectowner;
integer group;
string title = "";
list optionlist = [];
integer bMoving;
vector vLastPos;
rotation rLastRot;
integer iListenTimeout = 0;

//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()
{
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
llResetTime(); //Reset our throttle
vLastPos = llGetPos();
rLastRot = llGetRot();
return;
}


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

///////////////////////////////////////////////////////////////////////////////
state_entry () {
//Use which menu?
if ( llGetCreator() == llGetOwner() ) {
//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();

}

///////////////////////////////////////////////////////////////////////////////
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() + 10;
MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
llDialog(agent, title, optionlist, MENU_CHANNEL);
llSetTimerEvent(fShoutRate);
}
}

///////////////////////////////////////////////////////////////////////////////
listen(integer channel, string name, key id, string message) {
if ( message == optRecord ) {
llOwnerSay("Recording positions...");
llShout(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
return;
}
if( message == optReset ) {
llOwnerSay("Forgetting positions...");
llShout(PRIMCHAN, "RESET");
return;
}
if ( message == optBuild ) {
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
integer i;
integer iCount = llGetInventoryNumber(INVENTORY_OBJECT);

//Loop through backwards (safety precaution in case of inventory change)
llOwnerSay("Rezzing build pieces...");
for( i = iCount - 1; i >= 0; i-- )
{
llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), vThisPos, ZERO_VECTOR, rThisRot, PRIMCHAN);
if ( llGetCreator() != llGetOwner() )
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, i));
}

llOwnerSay("Positioning");
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == optPos ) {
llOwnerSay("Positioning");
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == optClean ) {
llShout(PRIMCHAN, "CLEAN");
return;
}
if ( message == optDone ) {
llShout(PRIMCHAN, "DONE");
//llDie();
llOwnerSay("Removing mover scripts.");
return;
}
}

///////////////////////////////////////////////////////////////////////////////
moving_start()
{
if( !bMoving )
{
bMoving = TRUE;
llSetTimerEvent(0.0); //Resets the timer if already running
llSetTimerEvent(fMovingRate);
announce_moved();
}
}

///////////////////////////////////////////////////////////////////////////////
timer() {
//Were we moving?
if( bMoving )
{
//Did we change position/rotation?
if( (llGetRot() != rLastRot) || (llGetPos() != vLastPos) )
{
if( llGetTime() > fShoutRate ) {
announce_moved();
}
}
} else {
//Have we been sitting long enough to consider ourselves stopped?
if( llGetTime() > fStoppedTime )
bMoving = FALSE;
}

//Open listener?
if( iListenTimeout != 0 )
{
//Past our close timeout?
if( iListenTimeout <= llGetUnixTime() )
{
iListenTimeout = 0;
llListenRemove(MENU_HANDLE);
}
}

//Stop the timer?
if( (iListenTimeout == 0) && ( !bMoving ) )
{
llOwnerSay("Stopping Timer");
llSetTimerEvent(0.0);
}
}

///////////////////////////////////////////////////////////////////////////////
on_rez(integer iStart)
{
//Reset ourselves
llResetScript();
}
}


BuildersBuddy 1.6 - Component
CODE

///////////////////////////////////////////////////////////////////////////////
// Builders' Buddy 1.6 (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:
// http://forums.secondlife.com/showthread.php?t=96792
///////////////////////////////////////////////////////////////////////////////
//
// 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)

///////////////////////////////////////////////////////////////////////////////
// User Variables
///////////////////////////////////////////////////////////////////////////////

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

//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 = " : Spawn 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 make the parts permanent.\n";

//How often (in seconds) to check for change in position when moving
float fMovingRate = 0.25;

//How long to sit still before exiting active mode
float fStoppedTime = 30.0;

//Minimum amount of time (in seconds) between movement updates
float fShoutRate = 0.25;

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

///////////////////////////////////////////////////////////////////////////////
// DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
///////////////////////////////////////////////////////////////////////////////
integer MENU_CHANNEL;
integer MENU_HANDLE;
key agent;
key objectowner;
integer group;
string title = "";
list optionlist = [];
integer bMoving;
vector vLastPos;
rotation rLastRot;
integer iListenTimeout = 0;

//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()
{
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
llResetTime(); //Reset our throttle
vLastPos = llGetPos();
rLastRot = llGetRot();
return;
}


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

///////////////////////////////////////////////////////////////////////////////
state_entry () {
//Use which menu?
if ( llGetCreator() == llGetOwner() ) {
//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();

}

///////////////////////////////////////////////////////////////////////////////
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() + 10;
MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
llDialog(agent, title, optionlist, MENU_CHANNEL);
llSetTimerEvent(fShoutRate);
}
}

///////////////////////////////////////////////////////////////////////////////
listen(integer channel, string name, key id, string message) {
if ( message == optRecord ) {
llOwnerSay("Recording positions...");
llShout(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
return;
}
if( message == optReset ) {
llOwnerSay("Forgetting positions...");
llShout(PRIMCHAN, "RESET");
return;
}
if ( message == optBuild ) {
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
integer i;
integer iCount = llGetInventoryNumber(INVENTORY_OBJECT);

//Loop through backwards (safety precaution in case of inventory change)
llOwnerSay("Rezzing build pieces...");
for( i = iCount - 1; i >= 0; i-- )
{
llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), vThisPos, ZERO_VECTOR, rThisRot, PRIMCHAN);
if ( llGetCreator() != llGetOwner() )
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT, i));
}

llOwnerSay("Positioning");
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == optPos ) {
llOwnerSay("Positioning");
vector vThisPos = llGetPos();
rotation rThisRot = llGetRot();
llShout(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
return;
}
if ( message == optClean ) {
llShout(PRIMCHAN, "CLEAN");
return;
}
if ( message == optDone ) {
llShout(PRIMCHAN, "DONE");
//llDie();
llOwnerSay("Removing mover scripts.");
return;
}
}

///////////////////////////////////////////////////////////////////////////////
moving_start()
{
if( !bMoving )
{
bMoving = TRUE;
llSetTimerEvent(0.0); //Resets the timer if already running
llSetTimerEvent(fMovingRate);
announce_moved();
}
}

///////////////////////////////////////////////////////////////////////////////
timer() {
//Were we moving?
if( bMoving )
{
//Did we change position/rotation?
if( (llGetRot() != rLastRot) || (llGetPos() != vLastPos) )
{
if( llGetTime() > fShoutRate ) {
announce_moved();
}
}
} else {
//Have we been sitting long enough to consider ourselves stopped?
if( llGetTime() > fStoppedTime )
bMoving = FALSE;
}

//Open listener?
if( iListenTimeout != 0 )
{
//Past our close timeout?
if( iListenTimeout <= llGetUnixTime() )
{
iListenTimeout = 0;
llListenRemove(MENU_HANDLE);
}
}

//Stop the timer?
if( (iListenTimeout == 0) && ( !bMoving ) )
{
llOwnerSay("Stopping Timer");
llSetTimerEvent(0.0);
}
}

///////////////////////////////////////////////////////////////////////////////
on_rez(integer iStart)
{
//Reset ourselves
llResetScript();
}
}
1 2 3 4 5 6 7