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

[Table of Contents]

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 BuildersBuddy-Opensim  

BuildersBuddy-Opensim

Builders Buddy for Opensim Base Script

Category: Building
By : Newfie Pendragon
Created: 2019-03-18 Edited: 2019-03-17
Worlds: OpenSim

the Zip file

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

BuildersBuddy-Opensim

Builders Buddy for Opensim readme

Category: Building
By : Newfie Pendragon
Created: 2019-03-18 Edited: 2019-03-17
Worlds: OpenSim

1
2
3 Revision History
4
5 TABLE OF CONTENTS
6
7
8 01. PRODUCT SUMMARY
9 02. LICENCE AND COPYRIGHT
10 03. OFFICIAL RELEASES
11 04. ABOUT THE SCRIPTS
12 05. USAGE SUMMARY
13 06. DEFINITIONS
14 07. PREPARING A SET OF PRIMS TO WORK WITH BUILDER'S BUDDY
15 08. FINE-TUNING THE BEHAVIOUR
16 09. OTHER NOTES
17 10. FOOTNOTES
18 11. USING BUILDER'S BUDDY -- CUSTOMER HELP
19
20
21 01. PRODUCT SUMMARY
22
23 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.
24
25 You prepare the unlinked items according to the easy steps below, then for distribution put them in a Packing Box.
26
27 02. LICENCE AND COPYRIGHT
28
29 * Use the Builder's Buddy scripts as you wish, to modify, sell, etc.
30 * If you use this script in a for-sale product, please give credit to Newfie Pendragon as the creator of the script.
31 * 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.
32
33 03. OFFICIAL RELEASES
34
35 Official Releases of Builder's Buddy are tracked here: http://wiki.secondlife.com/wiki/Builders_Buddy
36
37 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.
38
39 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.
40
41 For instance, when Builder's Buddy v 1.20 comes out, then the help for it would be named v 1.20 -1, etc.
42
43 04. ABOUT THE SCRIPTS
44
45 There are two scripts, base and component.
46
47 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.
48
49 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.
50
51 05. USAGE SUMMARY
52
53 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.
54
55 1. Drop the base script in the Base.
56 2. Drop the "Component" Script in each building part.
57 3. Touch your Base, and choose RECORD
58 4. Take all building parts into inventory except for the base prim
59 5. Drag building parts from inventory into Base Prim
60 6. Touch your base and choose BUILD
61
62 OTHER COMMANDS from the Touch menu
63
64 * To reposition, move or rotate the Base Prim choose POSITION
65 * 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;
66 * To lock into position (removes all scripts, helping to reduce work on the sim server) choose DONE
67 * To delete building pieces: choose CLEAN
68
69 06. DEFINITIONS
70
71 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."
72
73 07. PREPARING A SET OF PRIMS TO WORK WITH BUILDER'S BUDDY
74
75 [Note: please ensure first that you are on land where you are allowed to run scripts, or this will not work.]
76
77 A) Make a prim. Any size, any shape, and you can decorate later how you wish.
78
79 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."
80
81 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]
82
83 Drop the base script into it.
84
85 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.
86
87 [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" :} ]
88
89 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.
90
91 D) Check your work. Did every piece or set of linked pieces get a Component script? Okay, then proceed.
92
93 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.
94
95 F) Click on the Packing Box (the prim you dropped the base script into earlier.) A blue menu will appear on your screen.
96
97 For now, the only button we care about is the RECORD button, but here's an explanation of all of them:
98
99 [Note: the menu also very cleverly contains brief explanations right on it!]
100
101 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!
102
103 RECORD: This memorizes the locations of the linksets you have dropped Component scripts into;
104
105 RESET: This "un-memorizes" the locations of the linksets you have dropped Component scripts into -- that is to say, it undoes any recording;
106
107 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.
108
109 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.
110
111 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.
112
113 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.)
114
115 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.)
116
117 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.
118
119 [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.]
120
121 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.
122
123 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.
124
125 J) Rename the Packing Box prim to a more helpful name than Object, if you haven't already.
126
127 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.
128
129 [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!
130
131 Do the following:
132
133 a) rez the set as it is out of the Packing Box;
134 b) position the missing piece into place, where it should have gone;
135 c) add a component script to that missing piece;
136 d) record;
137 e) take just that missing piece into your inventory (make sure perms are right!);
138 f) place just that missing piece into the Packing Box
139
140 Note: that's right, just the missing piece -- no need to replace everything else.
141
142 08. FINE-TUNING THE BEHAVIOUR
143
144 Inside the Base script, at the top of it, are some parameters that you can set.
145
146 Full help comments are provided in the script above each parameter.
147
148 Please see these if you wish to change various aspects of how Buddy's Builder operates for you.
149
150 Here, though, is expanded help on a few items:
151
152 (a) "dieOnClean"
153
154 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.
155
156 (b) "creatorUUID" variable
157
158 You only need to fill this in if you are not the creator of the main root prim of your object.
159
160 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.
161
162 Normally, the creator of the packaged object has also made its root prim.
163
164 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.
165
166 (c) "chatty" variable
167
168 If you want the Builder's Buddy to be less "chatty" while working away, you can change this via this script variable.
169
170 By default, it is set to:
171
172 integer chatty = TRUE.
173
174 To make Builder's Buddy quieter, you would change this to:
175
176 integer chatty = FALSE;
177
178 Bear in mind, though, that only the owner of the Packing Box can hear the messages, because the LSL script uses "llOwnerSay" versus "Say".
179
180 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.
181
182 [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.]
183
184
185 09. OTHER NOTES
186
187 A) Position of set from Packing Box
188
189 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.
190
191 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.
192
193 B) Not getting a Menu on the Packing Box
194
195 * Check that scripts are enabled for you where you are;
196 * Check that the default click behaviour on the Packing Box hasn't been changed to Pay, etc.
197 * Edit the Packing Box, go to the contents folder, open up the Base Script, and check that it is set to running.
198 * 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;
199
200 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.
201
202 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.
203
204 E) Underground
205
206 When the linksets are moved/positioned, SL uses the coordinates of the root prim to move everything else with it.
207
208 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.)
209
210 However, when a root prim is moved by script, script cannot move that room underground. Attempts to do so will fail silently.
211
212 Child prims linked to it, though, *can* go underground, so long as the root prim's centrepoint remains aboveground.
213
214 Bear this in mind if, for instance, you are planning to rez a house with a foundation, or basement.
215
216 F) Two different Menus
217
218 There are two different menus: one full menu for the creator of the Packing Box, and one with fewer options for the customer.
219
220 G) What memorizes the positions of all the bits to be rezzed -- the Packing Box, or the bits themselves?
221
222 Each "bit" remembers its own position, independent of the Packing Box and independent of its fellow bits.
223
224 For instance, with pieces from an already recorded set, you can:
225
226 a) make a fresh, new Packing Box;
227 b) drop a fresh, new base script into it;
228 c) load the previously prepared component pieces into it....
229
230 and it will all still work!
231
232 H) Naming component pieces
233
234 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.
235
236 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.
237
238 10. FOOTNOTES
239
240 [1] Rotation
241
242 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.
243
244 [2] Finding the Content Folder of an Item
245
246 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.
247
248 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.
249
250 To leave edit mode, locate the x in the upper-right hand corner of this editing properties window. Click it.
251
252 [3] Distance of Set pieces from Packing Box
253
254 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.)
255
256 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.)
257
258 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.
259
260 11. USING BUILDER'S BUDDY -- CUSTOMER HELP
261
262 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.
263 - - - - - - - - - - - - - - - - - - -
264
265 Packing Box refers to the prim object you received for your purchase. "Set" refers to the items that will be rezzed out of it.
266
267 [Note: please ensure first that you are on land where you are allowed to run scripts, or this will not work.]
268
269 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.
270
271 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!
272
273 2. Click on the Packing Box. A blue menu will appear on your screen. The buttons are:
274
275 Build / Position / Clean / Done
276
277 3. Click the BUILD button. In a matter of microseconds, the Set rezzes into place.
278
279 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!
280
281 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.
282
283 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.
284
285 7. To fix the build in place, click the DONE button.
286
287 CUSTOMER HELP FOOTNOTES
288
289 [1] Editing the Packing Box
290
291 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.
292
293 To leave edit mode, locate the x in the upper-right hand corner of this editing properties window. Click it.

BuildersBuddy-Opensim

Builders Buddy for Opensim Component

Category: Building
By : Newfie Pendragon
Created: 2019-03-18 Edited: 2019-03-17
Worlds: OpenSim

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 // - First change the numbers on lines 35 and 37 to any negative number, then save this script, it is important that to avoid multiple calls using more than one rez box to change these numbers everytime a new build is packed away.
11 // - Change the same numbers in the Component script to,,,,,to match the numbers changed in this script.
12 // - Drop this script in each building part, if using a linset, then drop this script into the root prim.
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 ///////////////////////////////////////////////////////////////////////////////
29 // Added a Memory datastorage for opensim using osMakeNotecard
30 ///////////////////////////////////////////////////////////////////////////////
31
32
33 //////////////////////////////////////////////////////////////////////////////////////////
34 // Configurable Settings
35 float fTimerInterval = 0.25; // Time in seconds between movement 'ticks'
36 integer DefaultChannel = -120003; // Andromeda Quonset's default channel
37 //integer PRIMCHAN = DefaultChannel; // Channel used by Base Prim to talk to Component Prims;
38 integer PRIMCHAN = -120003; // OpenSim Modification - also comment out the previous line for OpenSim
39 // ***THIS MUST MATCH IN BOTH SCRIPTS!***
40
41 //////////////////////////////////////////////////////////////////////////////////////////
42 // Runtime Variables (Dont need to change below here unless making a derivative)
43 vector vOffset;
44 rotation rRotation;
45 integer bNeedMove;
46 vector vDestPos;
47 rotation rDestRot;
48 integer bMovingSingle = FALSE;
49 integer bAbsolute = FALSE;
50 integer bRecorded = FALSE;
51 vector Region_Size;
52 vector vLimit;
53
54
55 list record_mem = []; // Memory to be stored
56 key g_quary_nc; //for reading our memory notecard
57 integer nc_line; //what line are we reading
58 integer iStartValue;
59
60
61 ////////////////////////////////////////////////////////////////////////////////
62 string first_word(string In_String, string Token)
63 {
64 //This routine searches for the first word in a string,
65 // and returns it. If no word boundary found, returns
66 // the whole string.
67 if(Token == "") Token = " ";
68 integer pos = llSubStringIndex(In_String, Token);
69
70 //Found it?
71 if( pos >= 1 )
72 return llGetSubString(In_String, 0, pos - 1);
73 else
74 return In_String;
75 }
76
77 ////////////////////////////////////////////////////////////////////////////////
78 string other_words(string In_String, string Token)
79 {
80 //This routine searches for the other-than-first words in a string,
81 // and returns it. If no word boundary found, returns
82 // an empty string.
83 if( Token == "" ) Token = " ";
84
85 integer pos = llSubStringIndex(In_String, Token);
86
87 //Found it?
88 if( pos >= 1 )
89 return llGetSubString(In_String, pos + 1, llStringLength(In_String));
90 else
91 return "";
92 }
93
94 ////////////////////////////////////////////////////////////////////////////////
95 do_move()
96 {
97 integer i = 0;
98 vector vLastPos = ZERO_VECTOR;
99 while( (i < 5) && (llGetPos() != vDestPos) )
100 {
101 list lParams = [];
102
103 //If we're not there....
104 if( llGetPos() != vDestPos )
105 {
106 //We may be stuck on the ground...
107 //Did we move at all compared to last loop?
108 if( llGetPos() == vLastPos )
109 {
110 //Yep, stuck...move straight up 10m (attempt to dislodge)
111 lParams = [ PRIM_POSITION, llGetPos() + <0, 0, 10.0> ];
112 //llSetPos(llGetPos() + <0, 0, 10.0>);
113 } else {
114 //Record our spot for 'stuck' detection
115 vLastPos = llGetPos();
116 }
117 }
118
119 //Try to move to destination
120 //Upgraded to attempt to use the llSetPrimitiveParams fast-move hack
121 //(Newfie, June 2006)
122 integer iHops = llAbs(llCeil(llVecDist(llGetPos(), vDestPos) / 10.0));
123 integer x;
124 for( x = 0; x < iHops; x++ ) {
125 lParams += [ PRIM_POSITION, vDestPos ];
126 }
127 llSetPrimitiveParams(lParams);
128 //llSleep(0.1);
129 i++;
130 }
131
132 //Set rotation
133 llSetRot(rDestRot);
134 }
135
136 start_move(string sText, key kID)
137 {
138 //Don't move if we've not yet recorded a position
139 if( !bRecorded ) return;
140
141 //Also ignore commands from bases with a different owner than us
142 //(Anti-hacking measure)
143 if( llGetOwner() != llGetOwnerKey(kID) ) return;
144
145 //Calculate our destination position relative to base?
146 if(!bAbsolute) {
147 //Relative position
148 //Calculate our destination position
149 sText = other_words(sText, " ");
150 list lParams = llParseString2List(sText, [ "|" ], []);
151 vector vBase = (vector)llList2String(lParams, 0);
152 rotation rBase = (rotation)llList2String(lParams, 1);
153
154 vDestPos = (vOffset * rBase) + vBase;
155 rDestRot = rRotation * rBase;
156 } else {
157 //Sim position
158 vDestPos = vOffset;
159 rDestRot = rRotation;
160 }
161
162 Region_Size = osGetRegionSize();
163 vLimit.x = (Region_Size.x - 15);
164 vLimit.y = (Region_Size.y - 15);
165
166
167 //Make sure our calculated position is within the sim
168 if(vDestPos.x < 0.0) vDestPos.x = 0.0;
169 if(vDestPos.x > vLimit.x) vDestPos.x = vLimit.x;
170 if(vDestPos.y < 0.0) vDestPos.y = 0.0;
171 if(vDestPos.y > vLimit.y) vDestPos.y = vLimit.y;
172 if(vDestPos.z > 4096.0) vDestPos.z = 4096.0;
173
174 //Turn on our timer to perform the move?
175 if( !bNeedMove )
176 {
177 llSetTimerEvent(fTimerInterval);
178 bNeedMove = TRUE;
179 }
180 return;
181 }
182
183 //////////////////////////////////////////////////////////////////////////////////////////
184 //////////////////////////////////////////////////////////////////////////////////////////
185 //////////////////////////////////////////////////////////////////////////////////////////
186 default
187 {
188 //////////////////////////////////////////////////////////////////////////////////////////
190 {
191 //Open up the listener
192 llListen(PRIMCHAN, "", NULL_KEY, "");
193 llRegionSay(PRIMCHAN, "READYTOPOS");
194 }
195
196 //////////////////////////////////////////////////////////////////////////////////////////
197 on_rez(integer iStart)
198 {
199 iStartValue = iStart;
200 if(llGetInventoryType("Builders Buddy Memory") != -1)
201 {
202 nc_line = 0;
203 g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
204 }
205 else
206 {
207 //Set the channel to what's specified
208 if( iStart != 0 )
209 {
210 PRIMCHAN = iStart;
211 state reset_listeners;
212 }
213 }
214 }
215
216 //////////////////////////////////////////////////////////////////////////////////////////
217 listen(integer iChan, string sName, key kID, string sText)
218 {
219 string sCmd = llToUpper(first_word(sText, " "));
220
221 if( sCmd == "RECORD" )
222 {
223 record_mem = [];
224
225 //Record position relative to base prim
226 sText = other_words(sText, " ");
227 list lParams = llParseString2List(sText, [ "|" ], []);
228 vector vBase = (vector)llList2String(lParams, 0);
229 rotation rBase = (rotation)llList2String(lParams, 1);
230
231 vOffset = (llGetPos() - vBase) / rBase;
232 record_mem += "vOffset|" +(string)vOffset ;
233 rRotation = llGetRot() / rBase;
234 record_mem += "rRotation|" +(string)rRotation ;
235 bAbsolute = FALSE;
236 record_mem += "bAbsolute|" +(string)bAbsolute ;
237 bRecorded = TRUE;
238 record_mem += "bRecorded|" +(string)bRecorded ;
239
240 if(llGetInventoryType("Builders Buddy Memory") != -1)
241 {
242 llRemoveInventory("Builders Buddy Memory");
243 }
244 osMakeNotecard( "Builders Buddy Memory", record_mem );
245
246
247 llOwnerSay("Recorded position.");
248 return;
249 }
250
251 if( sCmd == "RECORDABS" )
252 {
253 record_mem = [];
254 //Record absolute position
255 rRotation = llGetRot();
256 record_mem += "rRotation|" +(string)rRotation ;
257 vOffset = llGetPos();
258 record_mem += "vOffset|" +(string)vOffset ;
259 bAbsolute = TRUE;
260 record_mem += "bAbsolute|" +(string)bAbsolute ;
261 bRecorded = TRUE;
262 record_mem += "bRecorded|" +(string)bRecorded ;
263
264 if(llGetInventoryType("Builders Buddy Memory") != -1)
265 {
266 llRemoveInventory("Builders Buddy Memory");
267 }
268 osMakeNotecard( "Builders Buddy Memory", record_mem );
269
270 llOwnerSay("Recorded sim position.");
271 return;
272 }
273
274 //////////////////////////////////////////////////////////////////////////////////////////
275 if( sCmd == "MOVE" )
276 {
277 start_move(sText, kID);
278 return;
279 }
280
281 if( sCmd == "MOVESINGLE" )
282 {
283 //If we haven't gotten this before, position ourselves
284 if(!bMovingSingle) {
285 //Record that we are a single-prim move
286 bMovingSingle = TRUE;
287
288 //Now move it
289 start_move(sText, kID);
290 return;
291 }
292 }
293
294 //////////////////////////////////////////////////////////////////////////////////////////
295 if( sCmd == "DONE" )
296 {
297 //We are done, remove script
298 if(llGetInventoryType("Builders Buddy Memory") != -1)
299 {
300 llRemoveInventory("Builders Buddy Memory");
301 }
303 return;
304 }
305
306 //////////////////////////////////////////////////////////////////////////////////////////
307 if( sCmd == "CLEAN" )
308 {
309 //Clean up
310 llDie();
311 return;
312 }
313
314 //////////////////////////////////////////////////////////////////////////////////////////
315 if( sCmd == "RESET" )
316 {
318 }
319 }
320
321 //////////////////////////////////////////////////////////////////////////////////////////
322 timer()
323 {
324 //Turn ourselves off
325 llSetTimerEvent(0.0);
326
327 //Do we need to move?
328 if( bNeedMove )
329 {
330 //Perform the move and clean up
331 do_move();
332
333 //If single-prim move, announce to base we're done
334 if(bMovingSingle) {
335 llRegionSay(PRIMCHAN, "ATDEST");
336 }
337
338 //Done moving
339 bNeedMove = FALSE;
340 }
341 return;
342 }
343 dataserver(key queryid, string data)
344 {
345 if( queryid == g_quary_nc)
346 {
347 if(data != EOF)
348 {
349 list n = llParseString2List(data, ["|"], []);
350
351 if(llList2String(n, 0) == "vOffset")
352 {
353 vOffset = llList2Vector(n, 1);
354 }
355 else if(llList2String(n, 0) == "rRotation")
356 {
357 rRotation = llList2Rot(n, 1);
358 }
359 else if(llList2String(n, 0) == "bAbsolute")
360 {
361 bAbsolute = (integer)llList2String(n, 1);
362 }
363 else if(llList2String(n, 0) == "bRecorded")
364 {
365 bRecorded = (integer)llList2String(n, 1);
366 }
367 nc_line++;
368 g_quary_nc = llGetNotecardLine("Builders Buddy Memory", nc_line);
369 }
370 else
371 {
372 //Set the channel to what's specified
373 if( iStartValue != 0 )
374 {
375 PRIMCHAN = iStartValue;
376 state reset_listeners;
377 }
378 }
379 }
380 }
381 }
382
383
384 //////////////////////////////////////////////////////////////////////////////////////////
385 //////////////////////////////////////////////////////////////////////////////////////////
386 //////////////////////////////////////////////////////////////////////////////////////////
387 state reset_listeners
388 {
389 //////////////////////////////////////////////////////////////////////////////////////////
391 {
392 state default;
393 }
394 }

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