Temp Rezzer Scripts

Expired

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

 

Elevator Script

Expired

vector  alignment;
vector  targetVector;
integer travelDistance;
integer numListen;
integer targetFloor;
list    floorHeights = [26.1,36,46,56,66,76,86,96,106,116,126,136];
float   fixedFloorHeight = 10; //Set to floor heights, or set to -1 to use floorHeights list
float   speed = 0.25; //Valid values are 0.01 to 1.0, a Percentage of maxSpeed;
float   maxSpeed = 32;
float   precision = 0.5;
integer autoSpeed = TRUE;
integer initialDistance;

elevate (vector end)
{
    vector current = llGetPos();
    travelDistance = llRound(current.z-end.z);
    travelDistance = llAbs(travelDistance);
    
    if (autoSpeed)
    {
        if (travelDistance <(initialDistance / 2))
        {
            speed -= (precision / 50);
            if (speed < 0.25) 
              speed = 0.25;
        }
        else
        {
            speed += (precision / 25);
            if (speed > 1) 
              speed = 1;
        }
    }
    if (travelDistance > 30)
    {
        travelDistance = 30;
        if (end.z > current.z)
        {
            end.z = current.z + 30;
        }
        else
        {
            end.z = current.z - 30;
        }
    }
    float i = travelDistance/(maxSpeed*speed);
    llMoveToTarget(end,i);
}

GotoFloor (integer floor, key id)
{    
    llWhisper(0, "Moving to floor#" + (string)floor);
    llSetStatus(STATUS_PHYSICS, TRUE);
    llLoopSound("ElevatorNoises", 1);
    
    targetFloor = floor;

    if (fixedFloorHeight > 0)
    {
        targetVector = alignment;
        targetVector.z = alignment.z + (fixedFloorHeight * floor);
    }
    else
    {
        targetVector = alignment;
        targetVector.z = llList2Float(floorHeights, floor);
    }
    llWhisper(0, "At " + (string)targetVector.z + " meters...");
    
    vector current = llGetPos();
    initialDistance = llRound(current.z-targetVector.z);
    initialDistance = llAbs(initialDistance);
    
    if (autoSpeed)
    {
        speed = 0.01;
    }

    elevate(targetVector);
    llSetTimerEvent(precision);
}

reset()
{
    llSay(0, "Resetting Elevator...");
    llSetStatus(STATUS_ROTATE_X| STATUS_ROTATE_Y| STATUS_ROTATE_Z, FALSE);
    
    alignment = llGetPos();
    llSetStatus(STATUS_PHYSICS, FALSE);
    llStopSound();
    llListenRemove(numListen);
    numListen = llListen( 0, "", "", "" );
}
default 
{
    state_entry()
    {
        reset();
    }
    object_rez(key id)
    {
        llResetScript();
    }
    listen(integer a, string n, key id, string m) 
    { 
        vector pos;
        integer Floor;
        float tempFloat;
        
        if (llSubStringIndex(m, "goto floor") == 0)
        {
            Floor = (integer)llGetSubString(m, 10, llStringLength(m));
            GotoFloor(Floor, NULL_KEY);
        }
        if (llSubStringIndex(m, "speed") == 0)
        {
            tempFloat = (float)llGetSubString(m, 5, llStringLength(m));
            if ((tempFloat > 0.001) && (tempFloat <= 1.0))
            {
                speed = tempFloat;
            }
        }
        if ((m=="elevator reset") && (id==llGetOwner()))
        {
            reset();
        }        
    } 
    
    timer()
    {
        vector CurrentPos;
        float tempfloat;
        
        CurrentPos = llGetPos();
        tempfloat = (CurrentPos.z - targetVector.z);
        
        if (llFabs(tempfloat) < 2) 
        {
            if (llFabs(tempfloat) < 0.05) 
            {
                //Arrived at Floor
                llWhisper(0, "Arrived at floor #" + (string)targetFloor);
                llSetTimerEvent(0); 
                llSetStatus(STATUS_PHYSICS, FALSE);
                llStopSound();
            }
            else
            {
                llMoveToTarget(targetVector,1.0);
            }
        }
        else 
        {
            if (fixedFloorHeight > 0)
            {
                targetVector = alignment;
                targetVector.z = alignment.z + (fixedFloorHeight * targetFloor);
            }
            else
            {
                targetVector = alignment;
                targetVector.z = llList2Float(floorHeights, targetFloor);
            }
            elevate(targetVector);
        }
    }
}




 

Double Glass Sliding Door

Expired

//********************************************************
//This Script was pulled out for you by YadNi Monde from the SL FORUMS at http://forums.secondlife.com/forumdisplay.php?f=15, it is intended to stay FREE by it s author(s) and all the comments here in ORANGE must NOT be deleted. They include notes on how to use it and no help will be provided either by YadNi Monde or it s Author(s). IF YOU DO NOT AGREE WITH THIS JUST DONT USE!!!
//********************************************************








//1 prim double sliding glass door was made by Seagel Neville as public domain, Nov 2006
//
//Hello there,
//
//This is 1 prim double sliding glass door.
//Just put this script into a prim.
//You can open it by touching or bumping.
//For security, it is locked when you keep touching for a while. Just the owner can open it. It toggles.
//After being rezzed, you can modify scale, color, and alpha. I don't recommend you post a texture on it because it has complicated faces.


integer pitch = 5;
float TimeInterval = 3.0;
integer TouchFlag;
integer Holding;
integer SecureFlag;

Open()
{
    TouchFlag = TRUE;
    llTriggerSound("de7ac1a3-f31b-e1a4-5a21-5b9907921bf1", 1.0);
    integer i;
    for(i = 0; i ,
        0.949000, <0.000000, 0.000000, 0.000000>, <(float)i/pitch, 1.000000, 0.000000>,
        <0.000000, 0.000000, 0.000000>]);   
    }
    llSetTimerEvent(TimeInterval);
}

Close()
{
    llSetTimerEvent(0);
    TouchFlag = FALSE;
    llTriggerSound("44f32d82-8604-1f29-37c9-a35baec646ee", 1.0);
    integer i;
    for(i = pitch - 1; i >= 0 ; i--)
    {
        llSetPrimitiveParams([PRIM_TYPE, 0, 0, <0.000000, 1.000000, 0.000000>,
        0.949000, <0.000000, 0.000000, 0.000000>, <(float)i/pitch, 1.000000, 0.000000>,
        <0.000000, 0.000000, 0.000000>]);
    }
}

TouchOpen()
{
    if(TouchFlag == FALSE)
    {
        Open();
    }
    else
    {
        Close();
    }
}

CollideOpen()
{
    if(TouchFlag == FALSE)
    {
        Open();
    }
    else
    {
        llSetTimerEvent(TimeInterval);
    }
}

Init()
{
    llSetPrimitiveParams([PRIM_MATERIAL, PRIM_MATERIAL_GLASS, PRIM_SIZE, <2 .0, 2.7, 0.01>,
    PRIM_TYPE, 0, 0, <0.0, 1.0, 0.0>, 0.949, <0.0, 0.0, 0.0>, <0.0, 1.0, 0.0>, <0.0, 0.0, 0.0>,
    PRIM_FULLBRIGHT, ALL_SIDES, TRUE, PRIM_ROTATION, <0.7, 0, 0, 0.7>,
    PRIM_COLOR, ALL_SIDES, <0.0, 0.0, 0.5>, 0.5, PRIM_POSITION, llGetPos() + (<0, 0, 1.1> * llGetRot()),
    PRIM_TEXTURE, ALL_SIDES, "5748decc-f629-461c-9a36-a35a221fe21f",
    <1 .0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
}

default
{
    state_entry()
    {
        Init();
    }
    changed(integer change)
    {
        if(change & CHANGED_OWNER)
        {
            llResetScript();
        }
    }
    touch(integer total_number)
    {
        if(llDetectedKey(0) == llGetOwner())
        {
            Holding++;
            if(Holding == 50)
            {
                if(SecureFlag == FALSE)
                {
                    llOwnerSay("Secured mode has been ON");
                    SecureFlag = TRUE;
                }
                else
                {
                    llOwnerSay("Secured mode has been OFF");
                    SecureFlag = FALSE;
                }
            }
        }
    }
    touch_end(integer total_number)
    {
        Holding = 0;
        if(SecureFlag == FALSE)
        {
            TouchOpen();
        }
        else
        {
            if(llDetectedKey(0) == llGetOwner())
            {
                TouchOpen();
            }
            else
            {
                llWhisper(0, "Sorry, this door is beeing locked.");
            }
        }
    }
    collision_start(integer num_detected)
    {
        if(SecureFlag == FALSE)
        {
            CollideOpen();
        }
        else
        {
            if(llDetectedKey(0) == llGetOwner())
            {
                CollideOpen();
            }
            else
            {
                llWhisper(0, "Sorry, this door is beeing locked.");
                llSleep(5.0);
            }
        }
    }
    timer()
    {
        Close();
    }
} 

 

Sliding Door

Expired

integer PFuncCallArgs = 56;


integer isOpen = FALSE;
string open_sound = "sliding door";
string close_sound = "sliding door";

integer autoCloseTime = 30; // seconds (-1 for no auto-close)

float steps = 4; // no. of steps for open movement (1 for smoothest/fastest)

vector scale;
vector position;
float y;


open()
{
    if (isOpen) return;

    if (autoCloseTime > 0)
        llSetTimerEvent(autoCloseTime);
    
    if (open_sound != "")
        llPlaySound(open_sound,0.5);

    position=position+<0,y,0>;
    llSetPos(position);    
    isOpen = TRUE;
}


close()
{
    llSetTimerEvent(0);
    
    if (!isOpen) return;

    position=position-<0,y,0>;
    llSetPos(position);

    if (close_sound != "")
        llPlaySound(close_sound,0.5);
        
    isOpen = FALSE;
}



callRemoteFuncP(string funcName, list args)
{
    list extArgs = [funcName] + args;
    string extArgStr = llDumpList2String(extArgs, "-=-");
    llMessageLinked( LINK_THIS, PFuncCallArgs, extArgStr, "" );
}



handleFuncCall(string funcName, list args)
{
    if (funcName=="open" || (funcName=="opendoor"))
        open();
    else if (funcName=="close" || (funcName=="closedoor"))
        close();
}






default
{
    state_entry()
    {
        scale=llGetScale();
        position=llGetPos();
        y=scale.y;        
    }

    timer()
    {
        close();
    }

    link_message(integer sender_num, integer num, string str, key id)
    {
        if ((num == PFuncCallArgs)) {
            
            list fullArgs = llParseStringKeepNulls( str, ["-=-"], [] );
            str="";
            string funcName = llList2String(fullArgs,0);
            
            list args = llList2List(fullArgs, 1, -1);
            fullArgs = [];

            handleFuncCall(funcName, args);
        }
    }
    

    touch_start(integer total_number)
    {
        key agentKey = llDetectedKey(0);
        string agentName = llDetectedName(0);
        
        if (!isOpen)
            callRemoteFuncP("checkauth",[agentKey,agentName,"open"]);
        else
            callRemoteFuncP("checkauth",[agentKey,agentName,"close"]);
    }
}