How to use: You must have Copy and Modify rights to any object you want to rez with these scripts. To use, edit the object to be rezzed and place the Rezzed Object Script in the Contents tab of that object and take it back into inventory. I recommend renaming it, so you can tell the version with the script from the original object. Create another 1-prim object ( a simple box works fine) and edit it. Add the object to be rezzed (which contains the first script), along with the remaining three Temp Rez scripts to the Contents tab of this object and close the edit window. Touch the object containing these scripts and the rezzable object. A dialog will appear. Turn on the rezzer, and the object will be rezzed and the 1-prim container object will be made invisible. Edit the rezzed object and move it and rotate it to the desired position. This must be within 10M of the object containing the scripts.
NOTE: Using a temp rezzer does not allow you to exceed the hard limit of 15,000 prims on a sim. That limit applies to both temp and permanent prims. What it does is allow you to "borrow" prim allocations from other parcels in the sim which may not be using their full allotment. Looking at "About Land" on a parcel that is using a temp rezzer will count only the single permanent prim of the rezzer, not the temporary prims of the rezzed object.
Dilbert Cleanslate
Revision history: All of these scripts were originally written by Eata Kitty, but had a severe drift problem. Her comments are: This is my version of those temporary rezzers that some jokers charge comedy prices for. I don't personally use one so I'm not sure if it's totally bug free and I didn't spend too long working on it so there's probably some improvements to be made. 1.2 - Tweaked around the main some mostly changing how we store rotation and pos. I think this totally removes the weird drift problem. Pos and Rez handling is smarter and it also has checking on the 10M rez range. 1.1 - Changed to use a timer as our main method for rerezzing, this makes rerezzes more smooth. The sensor provides a backup in case the object is deleted too early.
Known Issue: The Turn On/Turn Off dialog options can get out of synch with the main script and I couldn't be bothered to put in a link message to resynch them or redesign the menu, just ignore it! Three scripts in the main object, one script for all objects to be rezzed.
Thank you Eata Kitty! 1.3 - fix by Dilbert Cleanslate.
Changed the llRezObject commands to llRezAtRoot. This is the real fix to the drift problem. The previous scripts failed because sensor reports the position of the root prim only, and llRezObject uses the geometric center of the entire linked set. Each time the object was rezzed, it would drift by the distance from the root prim's geometric center to the entire linked object's geometric center.
Rezzed Object Script:
// Chat channel integer commChannel; default { state_entry() { // Makes the object temporary so the whole 0 prim part works llSetPrimitiveParams([PRIM_TEMP_ON_REZ, TRUE]); } on_rez(integer param) { if (!param) // If not rezzed by the rezzer this stops temporary so we can edit it llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE]); else { // Chat channel to use, passed to us as a rez parameter commChannel = param; llListen(commChannel, "", NULL_KEY, ""); } } listen(integer channel, string name, key id, string message) { // Security - check the object belongs to our owner if (llGetOwnerKey(id) != llGetOwner()) return; if (message == "derez") llDie(); } }
Temp Rez Dialog:
integer CHANNEL; // What we use here is a dynamic menu, this is a list that we define before // calling the dialog. It allows us to have changing buttons by using // global variables. list dynMenu = []; // Variables for dynamic menu buttons string power = "Turn On"; string avSensor = "Sensor On"; default { state_entry() { CHANNEL = (integer)llFrand(2000000000.0); llListen(CHANNEL, "", NULL_KEY, ""); } touch_start(integer total_number) { // Build the dynamic menu before we use it as a dialog list dynMenu = ["Reset", avSensor, power]; if (llDetectedKey(0) == llGetOwner()) llDialog(llDetectedKey(0), "What do you want to do?", dynMenu, CHANNEL); } listen(integer channel, string name, key id, string message) { llOwnerSay("You have selected: '" + message + "'."); if (message == "Reset") { // Reset llMessageLinked(LINK_THIS, 1000, "", NULL_KEY); llMessageLinked(LINK_THIS, 1500, "", NULL_KEY); power = "Turn On"; avSensor = "Sensor On"; } else if (message == "Turn On") { // Go online llMessageLinked(LINK_THIS, 1200, "", NULL_KEY); power = "Turn Off"; } else if (message == "Turn Off") { // Go offline llMessageLinked(LINK_THIS, 1300, "", NULL_KEY); power = "Turn On"; } else if (message == "Sensor On") { // Start the sensor mode llMessageLinked(LINK_THIS, 1400, "", NULL_KEY); avSensor = "Sensor Off"; } else if (message == "Sensor Off") { // Stop the sensor mode llMessageLinked(LINK_THIS, 1500, "", NULL_KEY); avSensor = "Sensor On"; } } on_rez(integer start_param) { llResetScript(); } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } }
Temp Rez Main Dialog:
// This is one of a set of four scripts written by Eata Kitty to allow a multi-prim // object to be rezzed as Temporary from a permanent single prim object. Temporary // objects are not counted against your prim total on land, so this allows you to // reduce your prim total without cutting into your lifestyle. You must have copy // and modify rights to any object you wish to use with these scripts. See the // included Notecard for more details. // // Version 1.3 - 12 February 2007 // Empty variables that will store set position/rotation // DON'T CHANGE THESE vector rezPosition = <0,0,0>; rotation rezRotation = <0,0,0,0>; // Inter-object commands string commandDerez = "derez"; // Chat channel integer commChannel; // Rezzed object key key childKey = NULL_KEY; // How often our sensor checks, smaller is more responsive but more demanding float sensorTime = 1; // Rerez time - Desired life time of our object integer lifeTime = 50; // Time this object was rezzed integer startTime = 0; // Tick to avoid getting pos too often integer tick; // avSensor is running integer avSensor = FALSE; // InventoryCheck // Checks the status of our inventory integer InventoryCheck() { // Check if we have too many objects if (llGetInventoryNumber(INVENTORY_OBJECT) > 1) { llOwnerSay("ERROR - Too many objects! This rezzer only takes a single object"); return 1; } // No objects else if (llGetInventoryNumber(INVENTORY_OBJECT) == 0) { llOwnerSay("ERROR - No objects in inventory!"); return 1; } // Inventory must be copy if (llGetInventoryPermMask(llGetInventoryName(INVENTORY_OBJECT, 0), MASK_OWNER) & PERM_COPY) return 0; else { llOwnerSay("ERROR - Object does not have copy permissions"); return 1; } } integer rez() { llSay(commChannel, commandDerez); llSetTimerEvent(0); childKey = NULL_KEY; // Check if we have a rez position set, don't want to rez at 0,0,0 if (rezPosition == <0,0,0>) { llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, 0), llGetPos(), ZERO_VECTOR, rezRotation, commChannel); return 0; } else { if (llVecDist(llGetPos(), rezPosition) > 10) { llOwnerSay("Rez position is over 10M away. Reset me or move me closer to: " + (string)rezPosition + "."); return 1; } llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, 0), rezPosition, ZERO_VECTOR, rezRotation, commChannel); return 0; } } default { state_entry() { llSetAlpha(1.0, ALL_SIDES); childKey = NULL_KEY; } changed(integer change) { if (change & CHANGED_INVENTORY) { if (!InventoryCheck()) llOwnerSay("Ready to run"); } if (change & CHANGED_OWNER) { llOwnerSay("New owner, resetting."); llOwnerSay("To use me put a 0 Prim Object script inside the object you want to be rezzed then put it in my inventory and turn me on. You can fine tune the rez position/rotation through the Set P/R button (10M max distance)."); llResetScript(); } } link_message(integer sender, integer num, string message, key id) { // Turn on message if (num == 1200) { if (!InventoryCheck()) state running; } // avSensor is running else if (num == 1400) { avSensor = TRUE; } // avSensor is disabled else if (num == 1500) { avSensor = FALSE; } else { llOwnerSay("Error - Rezzer not running"); } } } state running { state_entry() { llOwnerSay("Running."); childKey = NULL_KEY; llSetTimerEvent(0.0); // **** Comment out the following line if you don't want to make your container object invisible llSetAlpha(0.0, ALL_SIDES); // Random comm channel commChannel = (integer)llFrand(2000000000.0); // Create object if (!avSensor) // The rez() function returns a integer value depending on success // If we get a 1 we want to go back to the inactive state if (rez() == 1) state default; } object_rez(key child) { // Very important, we use this to sense our child childKey = child; startTime = llGetUnixTime(); llSetTimerEvent(sensorTime); } timer() { if (llGetUnixTime() >= (startTime + lifeTime)) { llSay(commChannel, commandDerez); rez(); } else llSensor("", childKey, SCRIPTED, 96, PI); } sensor(integer num_detected) { // Check every 5 runs of the sensor if (tick >= 5) { tick = 0; // Is our stored position the same as detected? if (rezPosition != llDetectedPos(0)) { if (llVecDist(llGetPos(), llDetectedPos(0)) > 10) { llOwnerSay("Deactivating: Object has moved out of 10M rez range. Move the sensor closer to the target rez position."); llSay(commChannel, commandDerez); state default; } llOwnerSay("Set pos"); rezPosition = llDetectedPos(0); } // Is our stored rotation the same as detected? if (rezRotation != llDetectedRot(0)) { llOwnerSay("Set rot"); rezRotation = llDetectedRot(0); } } else tick++; } no_sensor() { // Our child object is missing, rerez it rez(); } on_rez(integer param) { // Move back to default, keep object info state default; } changed(integer change) { // If out inventory changes if (change & CHANGED_INVENTORY) { // This calls our inventory check function, if there is an inventory // problem it returns a 1 which will causes us to return to default if (InventoryCheck()) state default; } } link_message(integer sender, integer num, string message, key id) { // Reset if (num == 1000) { llOwnerSay("Resetting - Object info cleared"); llSay(commChannel, commandDerez); llResetScript(); } // Turn on message else if (num == 1200) { llOwnerSay("Rezzer already running... resynching with dialog"); // Inform user, we don't really need to do anything as dialog will now be in synch } // Turn off message else if (num == 1300) { llOwnerSay("Rezzer turning off..."); llSay(commChannel, commandDerez); llMessageLinked(LINK_THIS, 1500, "", NULL_KEY); state default; } // avSensor is running else if (num == 1400) { avSensor = TRUE; } // avSensor is disabled else if (num == 1500) { avSensor = FALSE; } // avSensor detected an av else if (num == 2000) { if (childKey == NULL_KEY) rez(); } // avSensor detects no av else if (num == 2100) { llSetTimerEvent(0.0); llSay(commChannel, commandDerez); childKey = NULL_KEY; } } }
Temp Rez Sensor:
// Is the sensor enabled integer active = FALSE; // How often sensor checks, longer uses less resources but means slower reaction integer sensorPeriod = 10; // Distance in M the sensor will find avs integer sensorDist = 20; // Sensor detected an av on last run if true integer avDetected = FALSE; default { link_message(integer sender, integer num, string message, key id) { // Sensor on message if (num == 1400) { avDetected = FALSE; llSensorRepeat("", NULL_KEY, AGENT, sensorDist, PI, sensorPeriod); } // Sensor off message else if (num == 1500) { avDetected = FALSE; llSensorRemove(); } } sensor(integer total_number) { // Only do something if this is the first detection of an av if (!avDetected) { // We detected something, tell Main to rez llMessageLinked(LINK_THIS, 2000, "", NULL_KEY); avDetected = TRUE; } } no_sensor() { // Only do something if we had detected an av last sensor if (avDetected) { // No avs, disable rezzing llMessageLinked(LINK_THIS, 2100, "", NULL_KEY); avDetected = FALSE; } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } }