/////START SCRIPT //// COMPONET
// 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;
}
}
///////END SCRIPT COMPONET>