Join us in Outworldz at www.outworldz.com:9000 or follow us:

Search dozens of selected web sites for OpenSim and LSL script

New! Script Meta-Search will search thousands of scripts here and at other sites for LSL or Opensim scripts.
Loading

Want to add a script or a project? Upload it and a half million people will see it and your name here this year.

Home   Show All
Category: Contributor: Creator
Building Builders Buddy  

Builders Buddy

This script goes in the each link set of parts. Those parts then go in the Builders Buddy Box

Category: Building
By : Newfie Pendragon
Created: 2014-10-21 Edited: 2014-10-20
Worlds: Second Life

the Zip file

Download all files for Builders Buddy
Contents are in zip format, with .LSL (text) source code and LSLEdit (text + Solution) formats.
Get file # 1. V10.0 Builders Buddy (Component Script).lsl
Get file # 2. V10.1 Builders' Buddy (Component Script).lsl
Get file # 3. Readme.txt
Get file # 4. V10.0 Builders' Buddy (Base Script).lsl
Get file # 5. V10.1 Builders' Buddy (Base Script).lsl
Get file # 6. BuilderBuddyComponent__by_Newfie_Pe_1.lsl
Get file # 7. Builders_Buddy_1_1.lsl
Get file # 8. Builders_Buddy_README_1.lsl
1
2 // Fri Dec 12, 2008 Mods by Michelle Argus to allow use on Var amd Mega regions in Opensim.
3
4
5 ///////////////////////////////////////////////////////////////////////////////
6 // Builders' Buddy 1.10 (Component Script)
7 // by Newfie Pendragon, 2006-2008
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 // Script Purpose & Use
11 // Functions are dependent on the "component script"
12 //
13 // QUICK USE:
14 // - Drop this script in the Base.
15 // - Drop the "Component" Script in each building part.
16 // - Touch your Base, and choose RECORD
17 // - Take all building parts into inventory
18 // - Drag building parts from inventory into Base Prim
19 // - Touch your base and choose BUILD
20 //
21 // OTHER COMMANDS from the Touch menu
22 // - To reposition, move/rotate Base Prim choose POSITION
23 // - To lock into position (removes scripts) choose DONE
24 // - To delete building pieces: choose CLEAN
25 ///////////////////////////////////////////////////////////////////////////////
26 // This script is copyrighted material, and has a few (minor) restrictions.
27 // For complete details, including a revision history, please see
28 // http://wiki.secondlife.com/wiki/Builders_Buddy
29 ///////////////////////////////////////////////////////////////////////////////
30
31 ///////////////////////////////////////////////////////////////////////////////
32 // Added a Memory datastorage for opensim using osMakeNotecard
33 ///////////////////////////////////////////////////////////////////////////////
34
35
36 //////////////////////////////////////////////////////////////////////////////////////////
37 // Configurable Settings
38 float fTimerInterval = 0.25; // Time in seconds between movement 'ticks'
39 integer DefaultChannel = -192567; // Andromeda Quonset's default channel
40 //integer PRIMCHAN = DefaultChannel; // Channel used by Base Prim to talk to Component Prims;
41 integer PRIMCHAN = -192567; // OpenSim Modification - also comment out the previous line for OpenSim
42 // ***THIS MUST MATCH IN BOTH SCRIPTS!***
43
44 //////////////////////////////////////////////////////////////////////////////////////////
45 // Runtime Variables (Dont need to change below here unless making a derivative)
46 vector vOffset;
47 rotation rRotation;
48 integer bNeedMove;
49 vector vDestPos;
50 rotation rDestRot;
51 integer bMovingSingle = FALSE;
52 integer bAbsolute = FALSE;
53 integer bRecorded = FALSE;
54
55
56 list record_mem = []; // Memory to be stored
57 key g_quary_nc; //for reading our memory notecard
58 integer nc_line; //what line are we reading
59 integer iStartValue;
60
61 //////////////////////////////////////////////////////////////////////////////////////////
62 // Variables for Positioninglimits within the sim of a 1024 X 1024 var or mega
63 float vDestPosXMIN = 0.0;
64 float vDestPosXMAX = 1024.0;
65 float vDestPosYMIN = 0.0;
66 float vDestPosYMAX = 1024.0;
67 float vDestPosZMAX = 10000.0;
68
69
70 ////////////////////////////////////////////////////////////////////////////////
71 string first_word(string In_String, string Token)
72 {
73 //This routine searches for the first word in a string,
74 // and returns it. If no word boundary found, returns
75 // the whole string.
76 if(Token == "") Token = " ";
77 integer pos = llSubStringIndex(In_String, Token);
78
79 //Found it?
80 if( pos >= 1 )
81 return llGetSubString(In_String, 0, pos - 1);
82 else
83 return In_String;
84 }
85
86 ////////////////////////////////////////////////////////////////////////////////
87 string other_words(string In_String, string Token)
88 {
89 //This routine searches for the other-than-first words in a string,
90 // and returns it. If no word boundary found, returns
91 // an empty string.
92 if( Token == "" ) Token = " ";
93
94 integer pos = llSubStringIndex(In_String, Token);
95
96 //Found it?
97 if( pos >= 1 )
98 return llGetSubString(In_String, pos + 1, llStringLength(In_String));
99 else
100 return "";
101 }
102
103 ////////////////////////////////////////////////////////////////////////////////
104 do_move()
105 {
106 integer i = 0;
107 vector vLastPos = ZERO_VECTOR;
108 while( (i < 5) && (llGetPos() != vDestPos) )
109 {
110 list lParams = [];
111
112 //If we're not there....
113 if( llGetPos() != vDestPos )
114 {
115 //We may be stuck on the ground...
116 //Did we move at all compared to last loop?
117 if( llGetPos() == vLastPos )
118 {
119 //Yep, stuck...move straight up 10m (attempt to dislodge)
120 lParams = [ PRIM_POSITION, llGetPos() + <0, 0, 10.0> ];
121 //llSetPos(llGetPos() + <0, 0, 10.0>);
122 } else {
123 //Record our spot for 'stuck' detection
124 vLastPos = llGetPos();
125 }
126 }
127
128 //Try to move to destination
129 //Upgraded to attempt to use the llSetPrimitiveParams fast-move hack
130 //(Newfie, June 2006)
131 integer iHops = llAbs(llCeil(llVecDist(llGetPos(), vDestPos) / 10.0));
132 integer x;
133 for( x = 0; x < iHops; x++ ) {
134 lParams += [ PRIM_POSITION, vDestPos ];
135 }
136 llSetPrimitiveParams(lParams);
137 //llSleep(0.1);
138 i++;
139 }
140
141 //Set rotation
142 llSetRot(rDestRot);
143 }
144
145 start_move(string sText, key kID)
146 {
147 //Don't move if we've not yet recorded a position
148 if( !bRecorded ) return;
149
150 //Also ignore commands from bases with a different owner than us
151 //(Anti-hacking measure)
152 if( llGetOwner() != llGetOwnerKey(kID) ) return;
153
154 //Calculate our destination position relative to base?
155 if(!bAbsolute) {
156 //Relative position
157 //Calculate our destination position
158 sText = other_words(sText, " ");
159 list lParams = llParseString2List(sText, [ "|" ], []);
160 vector vBase = (vector)llList2String(lParams, 0);
161 rotation rBase = (rotation)llList2String(lParams, 1);
162
163 vDestPos = (vOffset * rBase) + vBase;
164 rDestRot = rRotation * rBase;
165 } else {
166 //Sim position
167 vDestPos = vOffset;
168 rDestRot = rRotation;
169 }
170
171 //Make sure our calculated position is within the sim
172 if(vDestPos.x < vDestPosXMIN) vDestPos.x = vDestPosXMIN;
173 if(vDestPos.x > vDestPosXMAX) vDestPos.x = vDestPosXMAX;
174 if(vDestPos.y < vDestPosYMIN) vDestPos.y = vDestPosYMIN;
175 if(vDestPos.y > vDestPosYMAX) vDestPos.y = vDestPosYMAX;
176 if(vDestPos.z > vDestPosZMAX) vDestPos.z = vDestPosZMAX;
177
178
179 //Turn on our timer to perform the move?
180 if( !bNeedMove )
181 {
182 llSetTimerEvent(fTimerInterval);
183 bNeedMove = TRUE;
184 }
185 return;
186 }
187
188 //////////////////////////////////////////////////////////////////////////////////////////
189 //////////////////////////////////////////////////////////////////////////////////////////
190 //////////////////////////////////////////////////////////////////////////////////////////
191 default
192 {
193 //////////////////////////////////////////////////////////////////////////////////////////
195 {
196 //Open up the listener
197 llListen(PRIMCHAN, "", NULL_KEY, "");
198 llRegionSay(PRIMCHAN, "READYTOPOS");
199 }
200
201 //////////////////////////////////////////////////////////////////////////////////////////
202 on_rez(integer iStart)
203 {
204 iStartValue = iStart;
205 if(llGetInventoryType("Builders Buddy Memory") != -1)
206 {
207 nc_line = 0;
208 g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
209 }
210 else
211 {
212 //Set the channel to what's specified
213 if( iStart != 0 )
214 {
215 PRIMCHAN = iStart;
216 state reset_listeners;
217 }
218 }
219 }
220
221 //////////////////////////////////////////////////////////////////////////////////////////
222 listen(integer iChan, string sName, key kID, string sText)
223 {
224 string sCmd = llToUpper(first_word(sText, " "));
225
226 if( sCmd == "SET_LIMITS" )
227 {
228 list lParams = llParseString2List(sText, [ " " ], []);
229
230 vDestPosXMIN = llList2Float(lParams, 1);
231 vDestPosXMAX = llList2Float(lParams, 2);
232 vDestPosYMIN = llList2Float(lParams, 3);
233 vDestPosYMAX = llList2Float(lParams, 4);
234 vDestPosZMAX = llList2Float(lParams, 5);
235
236 }
237 else if( sCmd == "RECORD" )
238 {
239 record_mem = [];
240
241 //Record position relative to base prim
242 sText = other_words(sText, " ");
243 list lParams = llParseString2List(sText, [ "|" ], []);
244 vector vBase = (vector)llList2String(lParams, 0);
245 rotation rBase = (rotation)llList2String(lParams, 1);
246
247 vOffset = (llGetPos() - vBase) / rBase;
248 record_mem += "vOffset|" +(string)vOffset ;
249 rRotation = llGetRot() / rBase;
250 record_mem += "rRotation|" +(string)rRotation ;
251 bAbsolute = FALSE;
252 record_mem += "bAbsolute|" +(string)bAbsolute ;
253 bRecorded = TRUE;
254 record_mem += "bRecorded|" +(string)bRecorded ;
255
256 if(llGetInventoryType("Builders Buddy Memory") != -1)
257 {
258 llRemoveInventory("Builders Buddy Memory");
259 }
260 osMakeNotecard( "Builders Buddy Memory", record_mem );
261
262
263 llOwnerSay("Recorded position.");
264 return;
265 }
266
267 if( sCmd == "RECORDABS" )
268 {
269 record_mem = [];
270 //Record absolute position
271 rRotation = llGetRot();
272 record_mem += "rRotation|" +(string)rRotation ;
273 vOffset = llGetPos();
274 record_mem += "vOffset|" +(string)vOffset ;
275 bAbsolute = TRUE;
276 record_mem += "bAbsolute|" +(string)bAbsolute ;
277 bRecorded = TRUE;
278 record_mem += "bRecorded|" +(string)bRecorded ;
279
280 if(llGetInventoryType("Builders Buddy Memory") != -1)
281 {
282 llRemoveInventory("Builders Buddy Memory");
283 }
284 osMakeNotecard( "Builders Buddy Memory", record_mem );
285
286 llOwnerSay("Recorded sim position.");
287 return;
288 }
289
290 //////////////////////////////////////////////////////////////////////////////////////////
291 if( sCmd == "MOVE" )
292 {
293 start_move(sText, kID);
294 return;
295 }
296
297 if( sCmd == "MOVESINGLE" )
298 {
299 //If we haven't gotten this before, position ourselves
300 if(!bMovingSingle) {
301 //Record that we are a single-prim move
302 bMovingSingle = TRUE;
303
304 //Now move it
305 start_move(sText, kID);
306 return;
307 }
308 }
309
310 //////////////////////////////////////////////////////////////////////////////////////////
311 if( sCmd == "DONE" )
312 {
313 //We are done, remove script
314 if(llGetInventoryType("Builders Buddy Memory") != -1)
315 {
316 llRemoveInventory("Builders Buddy Memory");
317 }
319 return;
320 }
321
322 //////////////////////////////////////////////////////////////////////////////////////////
323 if( sCmd == "CLEAN" )
324 {
325 //Clean up
326 llDie();
327 return;
328 }
329
330 //////////////////////////////////////////////////////////////////////////////////////////
331 if( sCmd == "RESET" )
332 {
334 }
335 }
336
337 //////////////////////////////////////////////////////////////////////////////////////////
338 timer()
339 {
340 //Turn ourselves off
341 llSetTimerEvent(0.0);
342
343 //Do we need to move?
344 if( bNeedMove )
345 {
346 //Perform the move and clean up
347 do_move();
348
349 //If single-prim move, announce to base we're done
350 if(bMovingSingle) {
351 llRegionSay(PRIMCHAN, "ATDEST");
352 }
353
354 //Done moving
355 bNeedMove = FALSE;
356 }
357 return;
358 }
359 dataserver(key queryid, string data)
360 {
361 if( queryid == g_quary_nc)
362 {
363 if(data != EOF)
364 {
365 list n = llParseString2List(data, ["|"], []);
366
367 if(llList2String(n, 0) == "vOffset")
368 {
369 vOffset = llList2Vector(n, 1);
370 }
371 else if(llList2String(n, 0) == "rRotation")
372 {
373 rRotation = llList2Rot(n, 1);
374 }
375 else if(llList2String(n, 0) == "bAbsolute")
376 {
377 bAbsolute = (integer)llList2String(n, 1);
378 }
379 else if(llList2String(n, 0) == "bRecorded")
380 {
381 bRecorded = (integer)llList2String(n, 1);
382 }
383 nc_line++;
384 g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
385 }
386 else
387 {
388 //Set the channel to what's specified
389 if( iStartValue != 0 )
390 {
391 PRIMCHAN = iStartValue;
392 state reset_listeners;
393 }
394 }
395 }
396 }
397 }
398
399
400 //////////////////////////////////////////////////////////////////////////////////////////
401 //////////////////////////////////////////////////////////////////////////////////////////
402 //////////////////////////////////////////////////////////////////////////////////////////
403 state reset_listeners
404 {
405 //////////////////////////////////////////////////////////////////////////////////////////
407 {
408 state default;
409 }
410 }

Builders Buddy

Builder's Buddy lets ordinary SL users rez a set of unlinked items in their proper places in relation to each other, without needing any building skills.
The "Set" is usually a building, but there is no reason it can't also be a statue, a furniture set, etc.
You prepare the unlinked items according to the easy steps below, then for distribution put them in a Packing Box.
This script goes in the Builders Buddy box along with all parts

Category: Building
By : Newfie Pendragon
Created: 2014-10-21 Edited: 2014-10-20
Worlds: Second Life

1
2 ///////////////////////////////////////////////////////////////////////////////
3 // Builders' Buddy 1.10 (Base Script)
4 // by Newfie Pendragon, 2006-2008
5 ///////////////////////////////////////////////////////////////////////////////
6 //
7 // Script Purpose & Use
8 // Functions are dependent on the "component script"
9 //
10 // QUICK USE:
11 // - Drop this script in the Base.
12 // - Drop the "Component" Script in each building part.
13 // - Touch your Base, and choose RECORD
14 // - Take all building parts into inventory
15 // - Drag building parts from inventory into Base Prim
16 // - Touch your base and choose BUILD
17 //
18 // OTHER COMMANDS from the Touch menu
19 // - To reposition, move/rotate Base Prim choose POSITION
20 // - To lock into position (removes scripts) choose DONE
21 // - To delete building pieces: choose CLEAN
22 ///////////////////////////////////////////////////////////////////////////////
23 // This script is copyrighted material, and has a few (minor) restrictions.
24 // For complete details, including a revision history, please see
25 // http://wiki.secondlife.com/wiki/Builders_Buddy
26 ///////////////////////////////////////////////////////////////////////////////
27
28 // Channel used by Base Prim to talk to Component Prims
29 // This channel must be the same one in the component script
30 // A negative channel is used because it elimited accidental activations
31 // by an Avatar talking on obscure channels
32 integer DefaultPRIMCHAN = -192567; // Default channel to use
33 //integer PRIMCHAN = DefaultPRIMCHAN; // Channel used by Base Prim to talk to Component Prims;
34 integer PRIMCHAN = -192567; // OpenSim Modification - also comment out the previous line for OpenSim
35 // ***THIS MUST MATCH IN BOTH SCRIPTS!***
36
37 ///////////////////////////////////////////////////////////////////////////////
38 // Change these values if your using Megaregions or want to limit otherwise.
39 // Variables for Positioninglimits within the sim of a 1024 X 1024 var or mega
40 float vDestPosXMIN = 0.0;
41 float vDestPosXMAX = 1024.0;
42 float vDestPosYMIN = 0.0;
43 float vDestPosYMAX = 1024.0;
44 float vDestPosZMAX = 10000.0;
45
46
47
48 //The UUID of the creator of the object
49 //Leave this as "" unless SL displays wrong name in object properties
50 key creatorUUID = "";
51
52 // Set to TRUE to allow group members to use the dialog menu
53 // Set to FALSE to disallow group members from using the dialog menu
54 integer ingroup = TRUE;
55
56 // Set to TRUE to delete piece from inventory when rezzed
57 // (WARNING) If set to FALSE, user will be able to rez multiple copies
58 integer deleteOnRez = FALSE;
59
60 // Allow non-creator to use CLEAN command?
61 // (WARNING) If set to TRUE, it is recommended to set
62 // deleteOnRez to FALSE, or user could lose entire building
63 integer allowClean = TRUE;
64
65 //When user selects CLEAN, delete the base prim too?
66 integer dieOnClean = FALSE;
67
68 // Set to TRUE to record piece's location based on sim
69 // coordinates instead of relationship to base prim
70 integer recordSimLocation = FALSE;
71
72 // Set to TRUE to rez all building pieces before positioning,
73 // or FALSE to do (slower?) one at a time
74 integer bulkBuild = TRUE;
75
76 //Set to FALSE if you dont want the script to say anything while 'working'
77 integer chatty = TRUE;
78
79 //How long to listen for a menu response before shutting down the listener
80 float fListenTime = 30.0;
81
82 //How often (in seconds) to perform any timed checks
83 float fTimerRate = 0.25;
84
85 //How long to sit still before exiting active mode
86 float fStoppedTime = 30.0;
87
88 //SL sometimes blocks rezzing to prevent "gray goo" attacks
89 //How long we wait (seconds) before we assume SL blocked our rez attempt
90 integer iRezWait = 10;
91
92 //Specify which Menu Options will be displayed
93 //FALSE will restrict full options to creator
94 //TRUE will offer full options to anyone
95 integer fullOptions = FALSE;
96
97 //Set to TRUE if you want ShapeGen channel support
98 // (Last 4 digits of channel affected)
99 integer SGCompatible = FALSE;
100
101
102 ///////////////////////////////////////////////////////////////////////////////
103 //Part of KEYPAD CODE BY Andromeda Quonset....More added below in seevral places
104 list Menu2 = [ "-", "0","enter","7","8","9","4","5","6","1","2","3"];
105 string Input = "";
106 string Sign = "+";
107 string SignInput = " ";
108 string Caption = "Enter a number, include any leading 0's: ";
109
110 ///////////////////////////////////////////////////////////////////////////////
111 // DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
112 ///////////////////////////////////////////////////////////////////////////////
113
114 //Name each option-these names will be your button names.
115 string optRecord = "Record";
116 string optReset = "Reset";
117 string optBuild = "Build";
118 string optPos = "Position";
119 string optClean = "Clean";
120 string optDone = "Done";
121 string optChannel = "Channel";
122
123 //Menu option descriptions
124 string descRecord = ": Record the position of all parts\n";
125 string descReset = ": Forgets the position of all parts\n";
126 string descBuild = ": Rez inv. items and position them\n";
127 string descPos = ": Reposition the parts to a new location\n";
128 string descClean = ": De-Rez all pieces\n";
129 string descDone = ": Remove all BB scripts and freeze parts in place.\n";
130 string descChannel = ": Change Channel used on base and parts.\n";
131
132 integer MENU_CHANNEL;
133 integer MENU2_CHANNEL;
134 integer MENU_HANDLE;
135 integer MENU2_HANDLE;
136 key agent;
137 key objectowner;
138 integer group;
139 string title = "";
140 list optionlist = [];
141 integer bMoving;
142 vector vLastPos;
143 rotation rLastRot;
144 integer bRezzing;
145 integer iListenTimeout = 0;
146 integer iLastRez = 0;
147 integer iRezIndex;
148
149
150 InvertSign()
151 {
152 if(Sign == "+")
153 Sign = "-";
154 else
155 Sign = "+";
156 }
157
158 //To avoid flooding the sim with a high rate of movements
159 //(and the resulting mass updates it will bring), we used
160 // a short throttle to limit ourselves
161 announce_moved()
162 {
163 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
164 llResetTime(); //Reset our throttle
165 vLastPos = llGetPos();
166 rLastRot = llGetRot();
167 return;
168 }
169
170
171 rez_object()
172 {
173 //Rez the object indicated by iRezIndex
175 iLastRez = llGetUnixTime();
176 llSleep(2);
177
178 if(!bRezzing) {
179 bRezzing = TRUE;
180 //timer_on();
181 }
182 llSay(PRIMCHAN, "SET_LIMITS " + (string)vDestPosXMIN + " " + (string)vDestPosXMAX + " " + (string)vDestPosYMIN + " " + (string)vDestPosYMAX + " " + (string)vDestPosZMAX );
183 }
184
185 post_rez_object()
186 {
187 if( creatorUUID != llGetOwner() ) {
189 }
190 }
191
192 heard(integer channel, string name, key id, string message)
193 {
194 if( channel == PRIMCHAN ) {
195 if( message == "READYTOPOS" ) {
196 //New prim ready to be positioned
197 vector vThisPos = llGetPos();
198 rotation rThisRot = llGetRot();
199 llRegionSay(PRIMCHAN, "MOVESINGLE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
200
201 } else if( message == "ATDEST" ) {
202 //Rez the next in the sequence (if any)
203 iRezIndex--;
204 if(iRezIndex >= 0) {
205 //Attempt to rez it
206 rez_object();
207 } else {
208 //We are done building, reset our listeners
209 iLastRez = 0;
210 bRezzing = FALSE;
211 state reset_listeners;
212 }
213 }
214 return;
215
216 } else if( channel == MENU_CHANNEL ) { //Process input from original menu
217 if( message == optRecord ) {
218 PRIMCHAN = DefaultPRIMCHAN;
219 llOwnerSay("Recording positions...");
220 if(recordSimLocation) {
221 //Location in sim
222 llRegionSay(PRIMCHAN, "RECORDABS " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
223 } else {
224 //Location relative to base
225 llRegionSay(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
226 }
227 return;
228 }
229 if( message == optReset ) {
230 llOwnerSay("Forgetting positions...");
231 llShout(PRIMCHAN, "RESET");
232 return;
233 }
234 if( message == optBuild ) {
235 if(chatty) llOwnerSay("Rezzing build pieces...");
236
237 //If rezzing/positioning one at a time, we need
238 // to listen for when they've reached their dest
239 if(!bulkBuild) {
240 llListen(PRIMCHAN, "", NULL_KEY, "READYTOPOS");
241 llListen(PRIMCHAN, "", NULL_KEY, "ATDEST");
242 }
243
244 //Start rezzing, last piece first
246 rez_object();
247 return;
248 }
249 if( message == optPos ) {
250 if(chatty) llOwnerSay("Positioning");
251 vector vThisPos = llGetPos();
252 rotation rThisRot = llGetRot();
253 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
254 return;
255 }
256 if( message == optClean ) {
257 llRegionSay(PRIMCHAN, "CLEAN");
258 if(dieOnClean) llDie();
259 return;
260 }
261 if( message == optDone ) {
262 llRegionSay(PRIMCHAN, "DONE");
263 if(chatty) llOwnerSay("Removing Builder's Buddy scripts.");
264 return;
265 }
266 if( message == optChannel ) {
267 Sign = "+"; //default is a positive number
268 Input = "";
269 llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
270 }
271
272 } else if( channel == MENU2_CHANNEL ) { //process input from MENU2
273 // if a valid choice was made, implement that choice if possible.
274 // (llListFindList returns -1 if Choice is not in the menu list.)
275 if( llListFindList( Menu2, [ message ]) != -1 ) {
276 if( llListFindList(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], [message]) != -1) {
277 Input += message;
278 SignInput = Sign + Input;
279 llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
280
281 } else if( message == "-" ) {
282 InvertSign();
283 SignInput = Sign + Input;
284 llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
285
286 } else if( message == "enter" ) { //terminate input from menu2
287 string CalcChan = Input;
288
289 //Apply ShapeGen compatibility?
290 if(SGCompatible) {
291 //new assign channel number, forcing last 4 digits to 0000
292 integer ChanSize = llStringLength(Input); //determine number of digits (chars)
293 if(ChanSize > 5) {
294 CalcChan = llGetSubString(Input, 0, 4); //Shorten to 5 digits
295 }
296 CalcChan += "0000"; //append 0000
297 if(Sign == "-")
298 CalcChan = Sign + CalcChan;
299 }
300 PRIMCHAN = (integer)CalcChan; //assign channel number
301 llOwnerSay("Channel set to " + (string)PRIMCHAN + ".");
302 }
303
304 } else {
305 llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
306 }
307 }
308 }
309
310
311 ///////////////////////////////////////////////////////////////////////////////
312 ///////////////////////////////////////////////////////////////////////////////
313 ///////////////////////////////////////////////////////////////////////////////
314 default {
315 ///////////////////////////////////////////////////////////////////////////////
316 changed(integer change) {
317 if(change & CHANGED_OWNER)
319 }
320
321 ///////////////////////////////////////////////////////////////////////////////
322 state_entry () {
323 //Determine the creator UUID
324 if(creatorUUID == "") creatorUUID = llGetCreator();
325
326 //Use which menu?
327 if(creatorUUID == llGetOwner() || fullOptions) {
328 //Display all options
329 optionlist = [optPos, optClean, optDone, optRecord, optReset, optBuild, optChannel];
330 title = optRecord + descRecord;
331 title += optReset + descReset;
332 title += optBuild + descBuild;
333 title += optPos + descPos;
334 title += optClean + descClean;
335 title += optDone + descDone;
336 title += optChannel + descChannel;
337
338 } else {
339 //Display limited options
340 if(allowClean) {
341 optionlist = [optBuild, optPos, optClean, optDone];
342 title = optBuild + descBuild;
343 title += optPos + descPos;
344 title += optClean + descClean;
345 title += optDone + descDone;
346 } else {
347 optionlist = [optBuild, optPos, optDone];
348 title = optBuild + descBuild;
349 title += optPos + descPos;
350 title += optDone + descDone;
351 }
352 }
353
354 //Record our position
355 vLastPos = llGetPos();
356 rLastRot = llGetRot();
357
358 llSetTimerEvent(fTimerRate);
359 }
360
361 ///////////////////////////////////////////////////////////////////////////////
362 touch_start (integer total_number) {
363 group = llDetectedGroup(0); // Is the Agent in the objowners group?
364 agent = llDetectedKey(0); // Agent's key
365 objectowner = llGetOwner(); // objowners key
366 // is the Agent = the owner OR is the agent in the owners group
367 if( (objectowner == agent) || ( group && ingroup ) ) {
368 iListenTimeout = llGetUnixTime() + llFloor(fListenTime);
369 MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
370 MENU2_CHANNEL = MENU_CHANNEL + 1;
371 MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
372 MENU2_HANDLE = llListen(MENU2_CHANNEL,"","","");
373 if( creatorUUID == llGetOwner() || fullOptions) {
374 llDialog(agent,title + "Now on Channel " + (string)PRIMCHAN, optionlist, MENU_CHANNEL); //display channel number if authorized
375 } else {
376 llDialog(agent, title, optionlist, MENU_CHANNEL);
377 }
378 //timer_on();
379 }
380 }
381
382 ///////////////////////////////////////////////////////////////////////////////
383 listen(integer channel, string name, key id, string message) {
384 heard(channel, name, id, message);
385 return;
386 }
387
388 ///////////////////////////////////////////////////////////////////////////////
390 {
391 if( !bMoving )
392 {
393 bMoving = TRUE;
394 //timer_on();
395 announce_moved();
396 }
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////
400 object_rez(key id) {
401 //The object rezzed, perform any post-rez processing
402 post_rez_object();
403
404 //Rezzing it all before moving?
405 if(bulkBuild) {
406 //Move on to the next object
407 //Loop through backwards (safety precaution in case of inventory change)
408 iRezIndex--;
409 if(iRezIndex >= 0) {
410 //Attempt to rez it
411 rez_object();
412
413 } else {
414 //Rezzing complete, now positioning
415 iLastRez = 0;
416 bRezzing = FALSE;
417 if(chatty) llOwnerSay("Positioning");
418 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
419 }
420 }
421 }
422
423 ///////////////////////////////////////////////////////////////////////////////
424 timer() {
425 //Did we change position/rotation?
426 if( (llGetRot() != rLastRot) || (llGetPos() != vLastPos) )
427 {
428 if( llGetTime() > fTimerRate ) {
429 announce_moved();
430 }
431 }
432
433 //Are we rezzing?
434 if(bRezzing) {
435 //Did the last one take too long?
436 if((llGetUnixTime() - iLastRez) >= iRezWait) {
437 //Yes, retry it
438 if(chatty) llOwnerSay("Reattempting rez of most recent piece");
439 rez_object();
440 }
441 }
442
443 //Open listener?
444 if( iListenTimeout != 0 )
445 {
446 //Past our close timeout?
447 if( iListenTimeout <= llGetUnixTime() )
448 {
449 iListenTimeout = 0;
450 llListenRemove(MENU_HANDLE);
451 }
452 }
453 }
454
455 ///////////////////////////////////////////////////////////////////////////////
456 on_rez(integer iStart)
457 {
458 //Reset ourselves
460 }
461 }
462
463
464 //////////////////////////////////////////////////////////////////////////////////////////
465 //////////////////////////////////////////////////////////////////////////////////////////
466 //////////////////////////////////////////////////////////////////////////////////////////
467 state reset_listeners
468 {
469 //////////////////////////////////////////////////////////////////////////////////////////
471 {
472 state default;
473 }
474 }

Builders Buddy

Builders Buddy readme

Category: Building
By : Newfie Pendragon
Created: 2014-10-21 Edited: 2014-10-20
Worlds: Second Life

1
2
3 Revision History
4
5 Menu mod for BB by Kalidor Lazarno.
6 Help written by Chaz Longstaff April 2008
7 Help version 1.1.0 - 2
8
9
10 TABLE OF CONTENTS
11
12
13 01. PRODUCT SUMMARY
14 02. LICENCE AND COPYRIGHT
15 03. OFFICIAL RELEASES
16 04. ABOUT THE SCRIPTS
17 05. USAGE SUMMARY
18 06. DEFINITIONS
19 07. PREPARING A SET OF PRIMS TO WORK WITH BUILDER'S BUDDY
20 08. FINE-TUNING THE BEHAVIOUR
21 09. OTHER NOTES
22 10. FOOTNOTES
23 11. USING BUILDER'S BUDDY -- CUSTOMER HELP
24
25
26 01. PRODUCT SUMMARY
27
28 Builder's Buddy lets ordinary SL users rez a set of unlinked items in their proper places in relation to each other, without needing any building skills. The "Set" is usually a building, but there is no reason it can't also be a statue, a furniture set, etc.
29
30 You prepare the unlinked items according to the easy steps below, then for distribution put them in a Packing Box.
31
32 02. LICENCE AND COPYRIGHT
33
34 * Use the Builder's Buddy scripts as you wish, to modify, sell, etc.
35 * If you use this script in a for-sale product, please give credit to Newfie Pendragon as the creator of the script.
36 * If you wish to modify this script and release the changes for public use, please submit changes to Newfie Pendragon. This is to ensure a consistent version numbering on releases, and to ensure changes are not wiped out in future releases.
37
38 03. OFFICIAL RELEASES
39
40 Official Releases of Builder's Buddy are tracked here: http://wiki.secondlife.com/wiki/Builders_Buddy
41
42 The most current official release as of April 2008 is version 1.10. Any release numbers higher than this, as of April 2008, are not on the officially supported path for updates in the future.
43
44 Subsequent versions of help for Builder's Buddy v 1.10 will be named -2, -3, -4, etc. This indicates the version of Builder's Buddy it is for, and the version of the help document.
45
46 For instance, when Builder's Buddy v 1.20 comes out, then the help for it would be named v 1.20 -1, etc.
47
48 04. ABOUT THE SCRIPTS
49
50 There are two scripts, base and component.
51
52 Make sure the Builder's Buddy scripts have the right permissions on them. They need at least transfer permissions, and since they are open source, there's no reason not to make them modify and copy as well.
53
54 Both scripts must be set to running. Do NOT hold down the CTRL key -- or Apple key on a Mac -- while dragging and dropping any of the scripts into prims, or that will set them to not running.
55
56 05. USAGE SUMMARY
57
58 The base script you only use once in an item. It goes in a "base" prim, which is the piece that is moved/rotated/etc. The component script goes into each part or each linked part that makes up the rest of the large build. In short, only one base script, many component scripts. You do not put a component script in the same item where you put a base script.
59
60 1. Drop the base script in the Base.
61 2. Drop the "Component" Script in each building part.
62 3. Touch your Base, and choose RECORD
63 4. Take all building parts into inventory except for the base prim
64 5. Drag building parts from inventory into Base Prim
65 6. Touch your base and choose BUILD
66
67 OTHER COMMANDS from the Touch menu
68
69 * To reposition, move or rotate the Base Prim choose POSITION
70 * To adjust where the house has rezzed after choosing BUILD, you can just edit - arrow move the base prim around, and the Rest of the build will follow;
71 * To lock into position (removes all scripts, helping to reduce work on the sim server) choose DONE
72 * To delete building pieces: choose CLEAN
73
74 06. DEFINITIONS
75
76 For the sake of this help, we refer to the base unit as the "Packing Box", and the set of unlinked items as the "Set."
77
78 07. PREPARING A SET OF PRIMS TO WORK WITH BUILDER'S BUDDY
79
80 [Note: please ensure first that you are on land where you are allowed to run scripts, or this will not work.]
81
82 A) Make a prim. Any size, any shape, and you can decorate later how you wish.
83
84 This is now what we are going to refer to as the "Packing Box." Occasionally, elsewhere, you will see it referred to as the "base unit."
85
86 All rotations for "Packing Box" should be set to 0, or all bets are off for how the objects rezzed out of it later will come out :} [1]
87
88 Drop the base script into it.
89
90 B) Rez in-world the set of prims you wish to be working with, if they are not already. As we are preparing them for distribution, now is the time to check that all of the permissions on them are what you like.
91
92 [TIP! in the steps below, you are going to do something to these items, then take them back into inventory. Remember that items rezzed in-world in SL, once taken *back* into inventory, tend to want to go back into the folder you rezzed them from. See the potential problem? You could end up with identically named items in that folder, the unprepared objects and the prepared objects, with no way to tell the difference. Consequently, you may wish to make sure in advance that once you have rezzed the items in-world from a folder, that in your inventory you then drag the originals off to another folder, so the coast will be clear for the incoming prepared ones. This can be particularly important if like most builders you leave each piece with the remarkably unique name of "Object" :} ]
93
94 C) Place the Component script into the content folder [2] of each piece or set of linked pieces of your build or set. To clarify, if you have several prims linked together (a "linked" set), just one of those prims (the "root" prim, which is the one you see by default when you edit a linked set, anyway) needs a Component script in it. If a prim is a standalone prim, it needs its own Component script.
95
96 D) Check your work. Did every piece or set of linked pieces get a Component script? Okay, then proceed.
97
98 E) Unless you have logistical reasons not to, we recommend now moving the Packing Box into roughly the centre of the Set. See footnote [3] at the end.
99
100 F) Click on the Packing Box (the prim you dropped the base script into earlier.) A blue menu will appear on your screen.
101
102 For now, the only button we care about is the RECORD button, but here's an explanation of all of them:
103
104 [Note: the menu also very cleverly contains brief explanations right on it!]
105
106 CHANNEL: The Packing Box and the Set pieces need a "channel" that they use to talk to each other. If you have several Packing Boxes, or several Sets, rezzed out and on the go all at once, you'll definitely want to make sure that each Packing Box / Set combination has its own unique channel to talk on, or the wrong Set might end up listening to the wrong Packing Box, and disaster could result! You could end up, for instance, issuing a CLEAN (delete) command that the only copy you have on a build might here!
107
108 RECORD: This memorizes the locations of the linksets you have dropped Component scripts into;
109
110 RESET: This "un-memorizes" the locations of the linksets you have dropped Component scripts into -- that is to say, it undoes any recording;
111
112 BUILD: This will rez your set of prepared, unlinked items, putting them all in the right place in relation both to each other, and in relation to the Packing Box.
113
114 POSITION: There may be times when the Set of objects doesn't respond to being moved by simply moving the Packing Box with the arrows (covered further below in point 4 of 11. USING BUILDER'S BUDDY) -- owing to lag, or no-script zones, etc. The POSITION command can be used to force the Set to try again.
115
116 CLEAN: This will derez the items you just rezzed using BUILD. This is done using the llDie() command. This means these items are gone, bye-bye, gonzo -- you won't even see them in your Lost and Found, or Trash.
117
118 DONE: Removes the Component scripts from the linksets, leaving them where they are "permanently." (Removing all the scripts helps to reduce work on the sim server.)
119
120 MOVE: Moves and rotates your set of unlinked items in relation to the Packing Box's height and rotation (e.g. your Packing Box will stay where it is; the build pieces will move.)
121
122 G) Press the RECORD button; the base Packing Box then records the locations of the prims or primsets that have a component script in them.
123
124 [TIP! With many pieces in a build, it can be very easy to forget to add component scripts into a piece or two. To help check that you haven't, after you have recorded the positions, go into edit mode on the Packing Box and move it up a bit. If everything follows as expected, then you are set. If not, from the SL client menu overhead, go EDIT - UNDO to have the Packing Box go back to where it was a second ago. Add a component script to the bits that didn't move. Record the positions again, then proceed.]
125
126 H) Leave the base Packing Box out, but take back into inventory all of the pieces that have Component scripts in them. It doesn't matter whether you take them in one by one, or whether you grab them all at once using TAKE from the SL client overhead menu to take them as a compound object.
127
128 I) The items are now in your inventory, and if you noted the advice in Step 2 above, you know exactly where they are in your inventory. Now, edit the Packing Box, switch to its contents folder, and drag all these prepared items into it.
129
130 J) Rename the Packing Box prim to a more helpful name than Object, if you haven't already.
131
132 K) Try rezzing the set from the Packing Box, as described below in 11. USING BUILDER'S BUDDY. Editing the packing box, and using the position arrows in edit mode, will cause the entire Set to move around with the Packing Box. Occasionally, if you are in a very laggy sim, or SL is having some kind of problem, when rezzing a build out of the Packing Box you may have to click on the Packing Box to get the menu, and click the POSITION button to get everything to pop into place. If that still doesn't do the trick, click on the CLEAN button, and then the BUILD button to try again.
133
134 [TIP! Occasionally, you may put all the prepared component pieces into the Packing Box, and run a test rez only to find that you're missing a piece of a house or furniture set that you meant to include. Don't despair; after all, that's what test runs are for!
135
136 Do the following:
137
138 a) rez the set as it is out of the Packing Box;
139 b) position the missing piece into place, where it should have gone;
140 c) add a component script to that missing piece;
141 d) record;
142 e) take just that missing piece into your inventory (make sure perms are right!);
143 f) place just that missing piece into the Packing Box
144
145 Note: that's right, just the missing piece -- no need to replace everything else.
146
147 08. FINE-TUNING THE BEHAVIOUR
148
149 Inside the Base script, at the top of it, are some parameters that you can set.
150
151 Full help comments are provided in the script above each parameter.
152
153 Please see these if you wish to change various aspects of how Buddy's Builder operates for you.
154
155 Here, though, is expanded help on a few items:
156
157 (a) "dieOnClean"
158
159 If you choose to use a piece of your build as the base component (which is fine), you will want to ensure that the "dieOnClean" to parameter is set to FALSE, or you risk deleting the piece during when any CLEAN command is issued.
160
161 (b) "creatorUUID" variable
162
163 You only need to fill this in if you are not the creator of the main root prim of your object.
164
165 Builder's Buddy checks the creator of the main root prim of your object to ensure that it can correctly determine which menu to show to whom. The creator gets the expanded menu; end users get the simpler menu that they need.
166
167 Normally, the creator of the packaged object has also made its root prim.
168
169 Occasionally, though, you may use prims other than those made by your own hand -- for instance, if you use megaprims. In this case, you can make sure you still get the expanded menu by specifying your UUID.
170
171 (c) "chatty" variable
172
173 If you want the Builder's Buddy to be less "chatty" while working away, you can change this via this script variable.
174
175 By default, it is set to:
176
177 integer chatty = TRUE.
178
179 To make Builder's Buddy quieter, you would change this to:
180
181 integer chatty = FALSE;
182
183 Bear in mind, though, that only the owner of the Packing Box can hear the messages, because the LSL script uses "llOwnerSay" versus "Say".
184
185 So, even though group members by default can use the menu on the Packing Box (because by default integer ingroup = TRUE ), those group members won't hear any confirmation messages unless they are the owner.
186
187 [TIP! If you want do want your team members to hear these messages, do a Search and Replace in the base script - search of llOwnerSay and replace it with llSay.]
188
189
190 09. OTHER NOTES
191
192 A) Position of set from Packing Box
193
194 If you had the Packing Box 5 metres in the air when you hit the RECORD button, then all the pieces of your Set will remember their position in relation to the box. Bearing that in mind, it therefore would not be a good idea to place the Packing Box on the ground and hit the BUILD button, because some pieces -- say, a floor -- might then end up 5 metres *under* the ground and be a headache for all concerned. So, tell purchasers of your Packing Box how high up or how low to place the Packing Box before hitting the BUILD button.
195
196 If you have indeed placed the Packing Box in the centre of your build before hitting the RECORD button, then advise purchasers that the build will rez using the Packing Box as the approximate centre.
197
198 B) Not getting a Menu on the Packing Box
199
200 * Check that scripts are enabled for you where you are;
201 * Check that the default click behaviour on the Packing Box hasn't been changed to Pay, etc.
202 * Edit the Packing Box, go to the contents folder, open up the Base Script, and check that it is set to running.
203 * If you copied the scripts yourself directly from the wiki on the web, ensure that no funny spaces or bad breaks come in with the text, as it often does from web pages;
204
205 C) There is no issue per se using megaprims, though normal constraints re sim boundaries, unsocial neighbours who deny building rights, etc :} still apply. However, if a megaprim is used as your base object, you may need to set the "creatorUUID" variable (08. FINE-TUNING THE BEHAVIOUR above) to your creator's UUID.
206
207 D) There is no issue with Buddy's Builder rezzing part of a build -- e.g. a foundation, a basement, etc, below ground level, if that is what you want.
208
209 E) Underground
210
211 When the linksets are moved/positioned, SL uses the coordinates of the root prim to move everything else with it.
212
213 When you move a root prim by hand, you can to some extent ram it under the ground (as you no doubt remember from your early days in SL.)
214
215 However, when a root prim is moved by script, script cannot move that room underground. Attempts to do so will fail silently.
216
217 Child prims linked to it, though, *can* go underground, so long as the root prim's centrepoint remains aboveground.
218
219 Bear this in mind if, for instance, you are planning to rez a house with a foundation, or basement.
220
221 F) Two different Menus
222
223 There are two different menus: one full menu for the creator of the Packing Box, and one with fewer options for the customer.
224
225 G) What memorizes the positions of all the bits to be rezzed -- the Packing Box, or the bits themselves?
226
227 Each "bit" remembers its own position, independent of the Packing Box and independent of its fellow bits.
228
229 For instance, with pieces from an already recorded set, you can:
230
231 a) make a fresh, new Packing Box;
232 b) drop a fresh, new base script into it;
233 c) load the previously prepared component pieces into it....
234
235 and it will all still work!
236
237 H) Naming component pieces
238
239 Builder's Buddy does not require all the prims in a build to have unique names. That being said, many feel it is good practice to have some kind of a naming system for the objects in your build so that they are not all named "object" or "block" or whatever. Otherwise, when you add them to the Packing Box, the SL system will just arbitrarily name them all Object, Object 1, Object 2, etc, and they will then not have the same name as those pieces in your inventory.
240
241 Depending on what your build is, you may have more than one naming convention. At the very least, when you manually add the component script to the component objects, consider naming the objects numerically yourself such as Object 01, Object 02, etc. That way, you have some idea of how many objects are in the build, and by going 01, 02, you know the numbers weren't just system-assigned ones. You can also count them easier from inside your inventory. When a build command doesn't work right, you can look back at your history and see which object by number didn't respond to the base prim when you did the record command.
242
243 10. FOOTNOTES
244
245 [1] Rotation
246
247 It is only the rotation of the Packing Box that you have to be concerned with. The rotation of the prims, or linked sets of prims, that you will be rezzing *doesn't* matter. Their rotations are part of the data that Builder's Buddy records, and deals with.
248
249 [2] Finding the Content Folder of an Item
250
251 Right-click the item in question (it must be rezzed in-world.) From the round pie menu, choose edit. The modal properties window will appear. Look on the right hand side for a button that says either "More>>" or "Less>>". If the blue button says "More>>", please click it. It will now say "Less>>". If it already says less, you are already ready for the next step.
252
253 For the next step, look for the folder tab called "Content". Click on this tab, please. You are now in the Content area of the item. To put items in here, locate them in your inventory, and drag them from your inventory and *drop* then into the Content folder. In a second or two, they will appear there. If SL is not behaving at the time, it may take a few more seconds.
254
255 To leave edit mode, locate the x in the upper-right hand corner of this editing properties window. Click it.
256
257 [3] Distance of Set pieces from Packing Box
258
259 In one way, there is no distance limit, with the simple proviso that all the prims must be in the same sim as the base. The base uses "region say" to communicate with them, meaning that its directions will be heard any anything listening for them within that region (aka sim.)
260
261 However, the linden script command to rez something can only rez something at a maximum distance of 96 metres from the item doing the rezzing. Note, however, that this is "in all directions", so the rezzer can rez something a maximum distance of 96 metres to the left, and 96 metres to the right -- ergo, a total distance, if the rezzer is in the middle, of 192 metres, which is not bad going. If you also place the box, say, 96 metres in the air, then you can rez pieces 96 metres up, 96 metres down, and 96 metres to either side, right and left (bear in mind that you probably want to be higher than 96 metres in the air; ground level is rarely actually bang on "0" in most sims.)
262
263 Consequently, when first setting out the Packing Box, and before pressing the RECORD button, it's good practice to place the Packing Box in the *middle* of the build, unless there are other prevailing reasons to place it elsewhere.
264
265 11. USING BUILDER'S BUDDY -- CUSTOMER HELP
266
267 Note: the following directions for usage are written in such a way that you can supply them just as they are written below to users / purchasers of your products, or, of course, modify them to make them more relevant to your product.
268 - - - - - - - - - - - - - - - - - - -
269
270 Packing Box refers to the prim object you received for your purchase. "Set" refers to the items that will be rezzed out of it.
271
272 [Note: please ensure first that you are on land where you are allowed to run scripts, or this will not work.]
273
274 1. Rez the Packing Box. The creator may have supplied you with directions about how to place the Packing Box for optimal rezzing results. If the creator noted that the Set rezzes using the Packing Box as its centre, bear that in mind. The creator may have recommended placing the Packing Box at a certain height before using it. If so, this is most easily done by editing the Packing Box [1], going to the Object tab of its properties, and just typing the coordinates provided into the appropriate X, Y and / or Z fields. When you close the editing properties, the Packing Box may appear to vanish, but it hasn't -- it has just instantly moved to that new position! Fly there yourself to join it.
275
276 TIP! Before changing the position using the X-Y-Z fields, consider just plain sitting on the Packing Box. That way, when it whizzes off, you will too right along with it!
277
278 2. Click on the Packing Box. A blue menu will appear on your screen. The buttons are:
279
280 Build / Position / Clean / Done
281
282 3. Click the BUILD button. In a matter of microseconds, the Set rezzes into place.
283
284 4. To move the entire Set of objects all at once, just edit the Packing Box and move it -- the pieces magically move in relation to it!
285
286 5. There may be times when the Set of objects doesn't respond to being moved, as just described -- owing to lag, or no-script zones, etc. The POSITION command can be used to force the Set to try again.
287
288 6. If a real mess has somehow happened, or if you were just experimenting, click the CLEAN button. This will derez everything you just rezzed, except the Packing Box itself. Then, click the BUILD button again.
289
290 7. To fix the build in place, click the DONE button.
291
292 CUSTOMER HELP FOOTNOTES
293
294 [1] Editing the Packing Box
295
296 Right-click the item in question (it must be rezzed in-world.) From the round pie menu, choose Edit. The modal properties window will appear. Look on the right hand side of it for a button that says either "More>>" or "Less>>". If it already says less, you are already ready for the next step. If the blue button instead says "More>>", please click it. It will now say "Less>>". You are now ready to proceed.
297
298 To leave edit mode, locate the x in the upper-right hand corner of this editing properties window. Click it.

Builders Buddy

Builder's Buddy lets ordinary SL users rez a set of unlinked items in their proper places in relation to each other, without needing any building skills.
The "Set" is usually a building, but there is no reason it can't also be a statue, a furniture set, etc.
You prepare the unlinked items according to the easy steps below, then for distribution put them in a Packing Box.
This script goes in the Builders Buddy box along with all parts

Category: Building
By : Newfie Pendragon
Created: 2014-10-21 Edited: 2014-10-20
Worlds: Second Life

1 ///////////////////////////////////////////////////////////////////////////////
2 // Builders' Buddy 1.10 (Base Script)
3 // by Newfie Pendragon, 2006-2008
4 ///////////////////////////////////////////////////////////////////////////////
5 //
6 // Script Purpose & Use
7 // Functions are dependent on the "component script"
8 //
9 // QUICK USE:
10 // - Drop this script in the Base.
11 // - Drop the "Component" Script in each building part.
12 // - Touch your Base, and choose RECORD
13 // - Take all building parts into inventory
14 // - Drag building parts from inventory into Base Prim
15 // - Touch your base and choose BUILD
16 //
17 // OTHER COMMANDS from the Touch menu
18 // - To reposition, move/rotate Base Prim choose POSITION
19 // - To lock into position (removes scripts) choose DONE
20 // - To delete building pieces: choose CLEAN
21 ///////////////////////////////////////////////////////////////////////////////
22 // This script is copyrighted material, and has a few (minor) restrictions.
23 // For complete details, including a revision history, please see
24 // http://wiki.secondlife.com/wiki/Builders_Buddy
25 ///////////////////////////////////////////////////////////////////////////////
26
27 // Channel used by Base Prim to talk to Component Prims
28 // This channel must be the same one in the component script
29 // A negative channel is used because it elimited accidental activations
30 // by an Avatar talking on obscure channels
31 integer DefaultPRIMCHAN = -192567; // Default channel to use
32 //integer PRIMCHAN = DefaultPRIMCHAN; // Channel used by Base Prim to talk to Component Prims;
33 integer PRIMCHAN = -192567; // OpenSim Modification - also comment out the previous line for OpenSim
34 // ***THIS MUST MATCH IN BOTH SCRIPTS!***
35
36 //The UUID of the creator of the object
37 //Leave this as "" unless SL displays wrong name in object properties
38 key creatorUUID = "";
39
40 // Set to TRUE to allow group members to use the dialog menu
41 // Set to FALSE to disallow group members from using the dialog menu
42 integer ingroup = TRUE;
43
44 // Set to TRUE to delete piece from inventory when rezzed
45 // (WARNING) If set to FALSE, user will be able to rez multiple copies
46 integer deleteOnRez = FALSE;
47
48 // Allow non-creator to use CLEAN command?
49 // (WARNING) If set to TRUE, it is recommended to set
50 // deleteOnRez to FALSE, or user could lose entire building
51 integer allowClean = TRUE;
52
53 //When user selects CLEAN, delete the base prim too?
54 integer dieOnClean = FALSE;
55
56 // Set to TRUE to record piece's location based on sim
57 // coordinates instead of relationship to base prim
58 integer recordSimLocation = FALSE;
59
60 // Set to TRUE to rez all building pieces before positioning,
61 // or FALSE to do (slower?) one at a time
62 integer bulkBuild = TRUE;
63
64 //Set to FALSE if you dont want the script to say anything while 'working'
65 integer chatty = TRUE;
66
67 //How long to listen for a menu response before shutting down the listener
68 float fListenTime = 30.0;
69
70 //How often (in seconds) to perform any timed checks
71 float fTimerRate = 0.25;
72
73 //How long to sit still before exiting active mode
74 float fStoppedTime = 30.0;
75
76 //SL sometimes blocks rezzing to prevent "gray goo" attacks
77 //How long we wait (seconds) before we assume SL blocked our rez attempt
78 integer iRezWait = 10;
79
80 //Specify which Menu Options will be displayed
81 //FALSE will restrict full options to creator
82 //TRUE will offer full options to anyone
83 integer fullOptions = FALSE;
84
85 //Set to TRUE if you want ShapeGen channel support
86 // (Last 4 digits of channel affected)
87 integer SGCompatible = FALSE;
88
89
90 ///////////////////////////////////////////////////////////////////////////////
91 //Part of KEYPAD CODE BY Andromeda Quonset....More added below in seevral places
92 list Menu2 = [ "-", "0","enter","7","8","9","4","5","6","1","2","3"];
93 string Input = "";
94 string Sign = "+";
95 string SignInput = " ";
96 string Caption = "Enter a number, include any leading 0's: ";
97
98 ///////////////////////////////////////////////////////////////////////////////
99 // DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
100 ///////////////////////////////////////////////////////////////////////////////
101
102 //Name each option-these names will be your button names.
103 string optRecord = "Record";
104 string optReset = "Reset";
105 string optBuild = "Build";
106 string optPos = "Position";
107 string optClean = "Clean";
108 string optDone = "Done";
109 string optChannel = "Channel";
110
111 //Menu option descriptions
112 string descRecord = ": Record the position of all parts\n";
113 string descReset = ": Forgets the position of all parts\n";
114 string descBuild = ": Rez inv. items and position them\n";
115 string descPos = ": Reposition the parts to a new location\n";
116 string descClean = ": De-Rez all pieces\n";
117 string descDone = ": Remove all BB scripts and freeze parts in place.\n";
118 string descChannel = ": Change Channel used on base and parts.\n";
119
120 integer MENU_CHANNEL;
121 integer MENU2_CHANNEL;
122 integer MENU_HANDLE;
123 integer MENU2_HANDLE;
124 key agent;
125 key objectowner;
126 integer group;
127 string title = "";
128 list optionlist = [];
129 integer bMoving;
130 vector vLastPos;
131 rotation rLastRot;
132 integer bRezzing;
133 integer iListenTimeout = 0;
134 integer iLastRez = 0;
135 integer iRezIndex;
136
137
138 InvertSign()
139 {
140 if(Sign == "+")
141 Sign = "-";
142 else
143 Sign = "+";
144 }
145
146 //To avoid flooding the sim with a high rate of movements
147 //(and the resulting mass updates it will bring), we used
148 // a short throttle to limit ourselves
149 announce_moved()
150 {
151 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
152 llResetTime(); //Reset our throttle
153 vLastPos = llGetPos();
154 rLastRot = llGetRot();
155 return;
156 }
157
158
159 rez_object()
160 {
161 //Rez the object indicated by iRezIndex
163 iLastRez = llGetUnixTime();
164
165 if(!bRezzing) {
166 bRezzing = TRUE;
167 //timer_on();
168 }
169 }
170
171 post_rez_object()
172 {
173 if( creatorUUID != llGetOwner() ) {
175 }
176 }
177
178 heard(integer channel, string name, key id, string message)
179 {
180 if( channel == PRIMCHAN ) {
181 if( message == "READYTOPOS" ) {
182 //New prim ready to be positioned
183 vector vThisPos = llGetPos();
184 rotation rThisRot = llGetRot();
185 llRegionSay(PRIMCHAN, "MOVESINGLE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
186
187 } else if( message == "ATDEST" ) {
188 //Rez the next in the sequence (if any)
189 iRezIndex--;
190 if(iRezIndex >= 0) {
191 //Attempt to rez it
192 rez_object();
193 } else {
194 //We are done building, reset our listeners
195 iLastRez = 0;
196 bRezzing = FALSE;
197 state reset_listeners;
198 }
199 }
200 return;
201
202 } else if( channel == MENU_CHANNEL ) { //Process input from original menu
203 if( message == optRecord ) {
204 PRIMCHAN = DefaultPRIMCHAN;
205 llOwnerSay("Recording positions...");
206 if(recordSimLocation) {
207 //Location in sim
208 llRegionSay(PRIMCHAN, "RECORDABS " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
209 } else {
210 //Location relative to base
211 llRegionSay(PRIMCHAN, "RECORD " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
212 }
213 return;
214 }
215 if( message == optReset ) {
216 llOwnerSay("Forgetting positions...");
217 llShout(PRIMCHAN, "RESET");
218 return;
219 }
220 if( message == optBuild ) {
221 if(chatty) llOwnerSay("Rezzing build pieces...");
222
223 //If rezzing/positioning one at a time, we need
224 // to listen for when they've reached their dest
225 if(!bulkBuild) {
226 llListen(PRIMCHAN, "", NULL_KEY, "READYTOPOS");
227 llListen(PRIMCHAN, "", NULL_KEY, "ATDEST");
228 }
229
230 //Start rezzing, last piece first
232 rez_object();
233 return;
234 }
235 if( message == optPos ) {
236 if(chatty) llOwnerSay("Positioning");
237 vector vThisPos = llGetPos();
238 rotation rThisRot = llGetRot();
239 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
240 return;
241 }
242 if( message == optClean ) {
243 llRegionSay(PRIMCHAN, "CLEAN");
244 if(dieOnClean) llDie();
245 return;
246 }
247 if( message == optDone ) {
248 llRegionSay(PRIMCHAN, "DONE");
249 if(chatty) llOwnerSay("Removing Builder's Buddy scripts.");
250 return;
251 }
252 if( message == optChannel ) {
253 Sign = "+"; //default is a positive number
254 Input = "";
255 llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
256 }
257
258 } else if( channel == MENU2_CHANNEL ) { //process input from MENU2
259 // if a valid choice was made, implement that choice if possible.
260 // (llListFindList returns -1 if Choice is not in the menu list.)
261 if( llListFindList( Menu2, [ message ]) != -1 ) {
262 if( llListFindList(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], [message]) != -1) {
263 Input += message;
264 SignInput = Sign + Input;
265 llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
266
267 } else if( message == "-" ) {
268 InvertSign();
269 SignInput = Sign + Input;
270 llDialog( agent, Caption + SignInput, Menu2, MENU2_CHANNEL );
271
272 } else if( message == "enter" ) { //terminate input from menu2
273 string CalcChan = Input;
274
275 //Apply ShapeGen compatibility?
276 if(SGCompatible) {
277 //new assign channel number, forcing last 4 digits to 0000
278 integer ChanSize = llStringLength(Input); //determine number of digits (chars)
279 if(ChanSize > 5) {
280 CalcChan = llGetSubString(Input, 0, 4); //Shorten to 5 digits
281 }
282 CalcChan += "0000"; //append 0000
283 if(Sign == "-")
284 CalcChan = Sign + CalcChan;
285 }
286 PRIMCHAN = (integer)CalcChan; //assign channel number
287 llOwnerSay("Channel set to " + (string)PRIMCHAN + ".");
288 }
289
290 } else {
291 llDialog( agent, Caption, Menu2, MENU2_CHANNEL );
292 }
293 }
294 }
295
296
297 ///////////////////////////////////////////////////////////////////////////////
298 ///////////////////////////////////////////////////////////////////////////////
299 ///////////////////////////////////////////////////////////////////////////////
300 default {
301 ///////////////////////////////////////////////////////////////////////////////
302 changed(integer change) {
303 if(change & CHANGED_OWNER)
305 }
306
307 ///////////////////////////////////////////////////////////////////////////////
308 state_entry () {
309 //Determine the creator UUID
310 if(creatorUUID == "") creatorUUID = llGetCreator();
311
312 //Use which menu?
313 if(creatorUUID == llGetOwner() || fullOptions) {
314 //Display all options
315 optionlist = [optPos, optClean, optDone, optRecord, optReset, optBuild, optChannel];
316 title = optRecord + descRecord;
317 title += optReset + descReset;
318 title += optBuild + descBuild;
319 title += optPos + descPos;
320 title += optClean + descClean;
321 title += optDone + descDone;
322 title += optChannel + descChannel;
323
324 } else {
325 //Display limited options
326 if(allowClean) {
327 optionlist = [optBuild, optPos, optClean, optDone];
328 title = optBuild + descBuild;
329 title += optPos + descPos;
330 title += optClean + descClean;
331 title += optDone + descDone;
332 } else {
333 optionlist = [optBuild, optPos, optDone];
334 title = optBuild + descBuild;
335 title += optPos + descPos;
336 title += optDone + descDone;
337 }
338 }
339
340 //Record our position
341 vLastPos = llGetPos();
342 rLastRot = llGetRot();
343
344 llSetTimerEvent(fTimerRate);
345 }
346
347 ///////////////////////////////////////////////////////////////////////////////
348 touch_start (integer total_number) {
349 group = llDetectedGroup(0); // Is the Agent in the objowners group?
350 agent = llDetectedKey(0); // Agent's key
351 objectowner = llGetOwner(); // objowners key
352 // is the Agent = the owner OR is the agent in the owners group
353 if( (objectowner == agent) || ( group && ingroup ) ) {
354 iListenTimeout = llGetUnixTime() + llFloor(fListenTime);
355 MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
356 MENU2_CHANNEL = MENU_CHANNEL + 1;
357 MENU_HANDLE = llListen(MENU_CHANNEL,"","","");
358 MENU2_HANDLE = llListen(MENU2_CHANNEL,"","","");
359 if( creatorUUID == llGetOwner() || fullOptions) {
360 llDialog(agent,title + "Now on Channel " + (string)PRIMCHAN, optionlist, MENU_CHANNEL); //display channel number if authorized
361 } else {
362 llDialog(agent, title, optionlist, MENU_CHANNEL);
363 }
364 //timer_on();
365 }
366 }
367
368 ///////////////////////////////////////////////////////////////////////////////
369 listen(integer channel, string name, key id, string message) {
370 heard(channel, name, id, message);
371 return;
372 }
373
374 ///////////////////////////////////////////////////////////////////////////////
376 {
377 if( !bMoving )
378 {
379 bMoving = TRUE;
380 //timer_on();
381 announce_moved();
382 }
383 }
384
385 ///////////////////////////////////////////////////////////////////////////////
386 object_rez(key id) {
387 //The object rezzed, perform any post-rez processing
388 post_rez_object();
389
390 //Rezzing it all before moving?
391 if(bulkBuild) {
392 //Move on to the next object
393 //Loop through backwards (safety precaution in case of inventory change)
394 iRezIndex--;
395 if(iRezIndex >= 0) {
396 //Attempt to rez it
397 rez_object();
398
399 } else {
400 //Rezzing complete, now positioning
401 iLastRez = 0;
402 bRezzing = FALSE;
403 if(chatty) llOwnerSay("Positioning");
404 llRegionSay(PRIMCHAN, "MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
405 }
406 }
407 }
408
409 ///////////////////////////////////////////////////////////////////////////////
410 timer() {
411 //Did we change position/rotation?
412 if( (llGetRot() != rLastRot) || (llGetPos() != vLastPos) )
413 {
414 if( llGetTime() > fTimerRate ) {
415 announce_moved();
416 }
417 }
418
419 //Are we rezzing?
420 if(bRezzing) {
421 //Did the last one take too long?
422 if((llGetUnixTime() - iLastRez) >= iRezWait) {
423 //Yes, retry it
424 if(chatty) llOwnerSay("Reattempting rez of most recent piece");
425 rez_object();
426 }
427 }
428
429 //Open listener?
430 if( iListenTimeout != 0 )
431 {
432 //Past our close timeout?
433 if( iListenTimeout <= llGetUnixTime() )
434 {
435 iListenTimeout = 0;
436 llListenRemove(MENU_HANDLE);
437 }
438 }
439 }
440
441 ///////////////////////////////////////////////////////////////////////////////
442 on_rez(integer iStart)
443 {
444 //Reset ourselves
446 }
447 }
448
449
450 //////////////////////////////////////////////////////////////////////////////////////////
451 //////////////////////////////////////////////////////////////////////////////////////////
452 //////////////////////////////////////////////////////////////////////////////////////////
453 state reset_listeners
454 {
455 //////////////////////////////////////////////////////////////////////////////////////////
457 {
458 state default;
459 }
460 }

Builders Buddy

This script goes in the each link set of parts. Those parts then go in the Builders Buddy Box

Category: Building
By : Newfie Pendragon
Created: 2014-10-21 Edited: 2014-10-20
Worlds: Second Life

1 ///////////////////////////////////////////////////////////////////////////////
2 // Builders' Buddy 1.10 (Component Script)
3 // by Newfie Pendragon, 2006-2008
4 ///////////////////////////////////////////////////////////////////////////////
5 //
6 // Script Purpose & Use
7 // Functions are dependent on the "component script"
8 //
9 // QUICK USE:
10 // - Drop this script in the Base.
11 // - Drop the "Component" Script in each building part.
12 // - Touch your Base, and choose RECORD
13 // - Take all building parts into inventory
14 // - Drag building parts from inventory into Base Prim
15 // - Touch your base and choose BUILD
16 //
17 // OTHER COMMANDS from the Touch menu
18 // - To reposition, move/rotate Base Prim choose POSITION
19 // - To lock into position (removes scripts) choose DONE
20 // - To delete building pieces: choose CLEAN
21 ///////////////////////////////////////////////////////////////////////////////
22 // This script is copyrighted material, and has a few (minor) restrictions.
23 // For complete details, including a revision history, please see
24 // http://wiki.secondlife.com/wiki/Builders_Buddy
25 ///////////////////////////////////////////////////////////////////////////////
26
27
28 //////////////////////////////////////////////////////////////////////////////////////////
29 // Configurable Settings
30 float fTimerInterval = 0.25; // Time in seconds between movement 'ticks'
31 integer DefaultChannel = -192567; // Andromeda Quonset's default channel
32 //integer PRIMCHAN = DefaultChannel; // Channel used by Base Prim to talk to Component Prims;
33 integer PRIMCHAN = -192567; // OpenSim Modification - also comment out the previous line for OpenSim
34 // ***THIS MUST MATCH IN BOTH SCRIPTS!***
35
36 //////////////////////////////////////////////////////////////////////////////////////////
37 // Runtime Variables (Dont need to change below here unless making a derivative)
38 vector vOffset;
39 rotation rRotation;
40 integer bNeedMove;
41 vector vDestPos;
42 rotation rDestRot;
43 integer bMovingSingle = FALSE;
44 integer bAbsolute = FALSE;
45 integer bRecorded = FALSE;
46
47
48 ////////////////////////////////////////////////////////////////////////////////
49 string first_word(string In_String, string Token)
50 {
51 //This routine searches for the first word in a string,
52 // and returns it. If no word boundary found, returns
53 // the whole string.
54 if(Token == "") Token = " ";
55 integer pos = llSubStringIndex(In_String, Token);
56
57 //Found it?
58 if( pos >= 1 )
59 return llGetSubString(In_String, 0, pos - 1);
60 else
61 return In_String;
62 }
63
64 ////////////////////////////////////////////////////////////////////////////////
65 string other_words(string In_String, string Token)
66 {
67 //This routine searches for the other-than-first words in a string,
68 // and returns it. If no word boundary found, returns
69 // an empty string.
70 if( Token == "" ) Token = " ";
71
72 integer pos = llSubStringIndex(In_String, Token);
73
74 //Found it?
75 if( pos >= 1 )
76 return llGetSubString(In_String, pos + 1, llStringLength(In_String));
77 else
78 return "";
79 }
80
81 ////////////////////////////////////////////////////////////////////////////////
82 do_move()
83 {
84 integer i = 0;
85 vector vLastPos = ZERO_VECTOR;
86 while( (i < 5) && (llGetPos() != vDestPos) )
87 {
88 list lParams = [];
89
90 //If we're not there....
91 if( llGetPos() != vDestPos )
92 {
93 //We may be stuck on the ground...
94 //Did we move at all compared to last loop?
95 if( llGetPos() == vLastPos )
96 {
97 //Yep, stuck...move straight up 10m (attempt to dislodge)
98 lParams = [ PRIM_POSITION, llGetPos() + <0, 0, 10.0> ];
99 //llSetPos(llGetPos() + <0, 0, 10.0>);
100 } else {
101 //Record our spot for 'stuck' detection
102 vLastPos = llGetPos();
103 }
104 }
105
106 //Try to move to destination
107 //Upgraded to attempt to use the llSetPrimitiveParams fast-move hack
108 //(Newfie, June 2006)
109 integer iHops = llAbs(llCeil(llVecDist(llGetPos(), vDestPos) / 10.0));
110 integer x;
111 for( x = 0; x < iHops; x++ ) {
112 lParams += [ PRIM_POSITION, vDestPos ];
113 }
114 llSetPrimitiveParams(lParams);
115 //llSleep(0.1);
116 i++;
117 }
118
119 //Set rotation
120 llSetRot(rDestRot);
121 }
122
123 start_move(string sText, key kID)
124 {
125 //Don't move if we've not yet recorded a position
126 if( !bRecorded ) return;
127
128 //Also ignore commands from bases with a different owner than us
129 //(Anti-hacking measure)
130 if( llGetOwner() != llGetOwnerKey(kID) ) return;
131
132
133 //Calculate our destination position relative to base?
134 if(!bAbsolute) {
135 //Relative position
136 //Calculate our destination position
137 sText = other_words(sText, " ");
138 list lParams = llParseString2List(sText, [ "|" ], []);
139 vector vBase = (vector)llList2String(lParams, 0);
140 rotation rBase = (rotation)llList2String(lParams, 1);
141
142 vDestPos = (vOffset * rBase) + vBase;
143 rDestRot = rRotation * rBase;
144 } else {
145 //Sim position
146 vDestPos = vOffset;
147 rDestRot = rRotation;
148 }
149
150 //Make sure our calculated position is within the sim
151 if(vDestPos.x < 0.0) vDestPos.x = 0.0;
152 if(vDestPos.x > 255.0) vDestPos.x = 255.0;
153 if(vDestPos.y < 0.0) vDestPos.y = 0.0;
154 if(vDestPos.y > 255.0) vDestPos.y = 255.0;
155 if(vDestPos.x > 768.0) vDestPos.x = 768.0;
156
157 //Turn on our timer to perform the move?
158 if( !bNeedMove )
159 {
160 llSetTimerEvent(fTimerInterval);
161 bNeedMove = TRUE;
162 }
163 return;
164 }
165
166 //////////////////////////////////////////////////////////////////////////////////////////
167 //////////////////////////////////////////////////////////////////////////////////////////
168 //////////////////////////////////////////////////////////////////////////////////////////
169 default
170 {
171 //////////////////////////////////////////////////////////////////////////////////////////
173 {
174 //Open up the listener
175 llListen(PRIMCHAN, "", NULL_KEY, "");
176 llRegionSay(PRIMCHAN, "READYTOPOS");
177 }
178
179 //////////////////////////////////////////////////////////////////////////////////////////
180 on_rez(integer iStart)
181 {
182 //Set the channel to what's specified
183 if( iStart != 0 )
184 {
185 PRIMCHAN = iStart;
186 state reset_listeners;
187 }
188 }
189
190 //////////////////////////////////////////////////////////////////////////////////////////
191 listen(integer iChan, string sName, key kID, string sText)
192 {
193 string sCmd = llToUpper(first_word(sText, " "));
194
195 if( sCmd == "RECORD" )
196 {
197 //Record position relative to base prim
198 sText = other_words(sText, " ");
199 list lParams = llParseString2List(sText, [ "|" ], []);
200 vector vBase = (vector)llList2String(lParams, 0);
201 rotation rBase = (rotation)llList2String(lParams, 1);
202
203 vOffset = (llGetPos() - vBase) / rBase;
204 rRotation = llGetRot() / rBase;
205 bAbsolute = FALSE;
206 bRecorded = TRUE;
207 llOwnerSay("Recorded position.");
208 return;
209 }
210
211 if( sCmd == "RECORDABS" )
212 {
213 //Record absolute position
214 rRotation = llGetRot();
215 vOffset = llGetPos();
216 bAbsolute = TRUE;
217 bRecorded = TRUE;
218 llOwnerSay("Recorded sim position.");
219 return;
220 }
221
222 //////////////////////////////////////////////////////////////////////////////////////////
223 if( sCmd == "MOVE" )
224 {
225 start_move(sText, kID);
226 return;
227 }
228
229 if( sCmd == "MOVESINGLE" )
230 {
231 //If we haven't gotten this before, position ourselves
232 if(!bMovingSingle) {
233 //Record that we are a single-prim move
234 bMovingSingle = TRUE;
235
236 //Now move it
237 start_move(sText, kID);
238 return;
239 }
240 }
241
242 //////////////////////////////////////////////////////////////////////////////////////////
243 if( sCmd == "DONE" )
244 {
245 //We are done, remove script
247 return;
248 }
249
250 //////////////////////////////////////////////////////////////////////////////////////////
251 if( sCmd == "CLEAN" )
252 {
253 //Clean up
254 llDie();
255 return;
256 }
257
258 //////////////////////////////////////////////////////////////////////////////////////////
259 if( sCmd == "RESET" )
260 {
262 }
263 }
264
265 //////////////////////////////////////////////////////////////////////////////////////////
266 timer()
267 {
268 //Turn ourselves off
269 llSetTimerEvent(0.0);
270
271 //Do we need to move?
272 if( bNeedMove )
273 {
274 //Perform the move and clean up
275 do_move();
276
277 //If single-prim move, announce to base we're done
278 if(bMovingSingle) {
279 llRegionSay(PRIMCHAN, "ATDEST");
280 }
281
282 //Done moving
283 bNeedMove = FALSE;
284 }
285 return;
286 }
287 }
288
289
290 //////////////////////////////////////////////////////////////////////////////////////////
291 //////////////////////////////////////////////////////////////////////////////////////////
292 //////////////////////////////////////////////////////////////////////////////////////////
293 state reset_listeners
294 {
295 //////////////////////////////////////////////////////////////////////////////////////////
297 {
298 state default;
299 }
300 }

Back to the Best Free Tools in Second Life and OpenSim.