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,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,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;
}
}
}
0>
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();
}
}
}